Added the hint SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, controlling whether the mouse should be constrained to the center of the window or the whole window in relative mode. For further info about the pros and cons, check out the discussion in https://github.com/libsdl-org/SDL/issues/5271
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 25383b1..140d37d 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -934,6 +934,22 @@ extern "C" {
#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE"
/**
+ * \brief A variable controlling whether relative mouse mode constrains the mouse to the center of the window
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative mouse mode constrains the mouse to the window
+ * "1" - Relative mouse mode constrains the mouse to the center of the window
+ *
+ * Constraining to the center of the window works better for FPS games and when the
+ * application is running over RDP. Constraining to the whole window works better
+ * for 2D games and increases the chance that the mouse will be in the correct
+ * position when using high DPI mice.
+ *
+ * By default SDL will constrain the mouse to the center of the window
+ */
+#define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER"
+
+/**
* \brief A variable controlling whether relative mouse mode is implemented using mouse warping
*
* This variable can be set to the following values:
diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index ccf4920..890d790 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -28,6 +28,7 @@
#include "../SDL_pixels_c.h"
#include "../../events/SDL_keyboard_c.h"
#include "../../events/SDL_mouse_c.h"
+#include "../../SDL_hints_c.h"
#include "SDL_windowsvideo.h"
#include "SDL_windowswindow.h"
@@ -170,6 +171,13 @@ WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
data->expected_resize = SDL_FALSE;
}
+static void SDLCALL
+WIN_MouseRelativeModeCenterChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+ SDL_WindowData *data = (SDL_WindowData *)userdata;
+ data->mouse_relative_mode_center = SDL_GetStringBoolean(hint, SDL_TRUE);
+}
+
static int
SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool created)
{
@@ -193,6 +201,8 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool cre
data->videodata = videodata;
data->initializing = SDL_TRUE;
+ SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, WIN_MouseRelativeModeCenterChanged, data);
+
window->driverdata = data;
/* Associate the data with the window */
@@ -297,7 +307,39 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool cre
return 0;
}
+static void CleanupWindowData(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if (data) {
+ SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, WIN_MouseRelativeModeCenterChanged, data);
+ if (data->keyboard_hook) {
+ UnhookWindowsHookEx(data->keyboard_hook);
+ }
+ ReleaseDC(data->hwnd, data->hdc);
+ RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
+ if (data->created) {
+ DestroyWindow(data->hwnd);
+ if (data->parent) {
+ DestroyWindow(data->parent);
+ }
+ } else {
+ /* Restore any original event handler... */
+ if (data->wndproc != NULL) {
+#ifdef GWLP_WNDPROC
+ SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
+ (LONG_PTR) data->wndproc);
+#else
+ SetWindowLong(data->hwnd, GWL_WNDPROC,
+ (LONG_PTR) data->wndproc);
+#endif
+ }
+ }
+ SDL_free(data);
+ }
+ window->driverdata = NULL;
+}
int
WIN_CreateWindow(_THIS, SDL_Window * window)
@@ -873,34 +915,7 @@ WIN_SetWindowKeyboardGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
void
WIN_DestroyWindow(_THIS, SDL_Window * window)
{
- SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
-
- if (data) {
- if (data->keyboard_hook) {
- UnhookWindowsHookEx(data->keyboard_hook);
- }
- ReleaseDC(data->hwnd, data->hdc);
- RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
- if (data->created) {
- DestroyWindow(data->hwnd);
- if (data->parent) {
- DestroyWindow(data->parent);
- }
- } else {
- /* Restore any original event handler... */
- if (data->wndproc != NULL) {
-#ifdef GWLP_WNDPROC
- SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
- (LONG_PTR) data->wndproc);
-#else
- SetWindowLong(data->hwnd, GWL_WNDPROC,
- (LONG_PTR) data->wndproc);
-#endif
- }
- }
- SDL_free(data);
- }
- window->driverdata = NULL;
+ CleanupWindowData(_this, window);
}
SDL_bool
@@ -1032,7 +1047,7 @@ WIN_UpdateClipCursor(SDL_Window *window)
if ((mouse->relative_mode || (window->flags & SDL_WINDOW_MOUSE_GRABBED) ||
(window->mouse_rect.w > 0 && window->mouse_rect.h > 0)) &&
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
- if (mouse->relative_mode && !mouse->relative_mode_warp) {
+ if (mouse->relative_mode && !mouse->relative_mode_warp && data->mouse_relative_mode_center) {
if (GetWindowRect(data->hwnd, &rect)) {
LONG cx, cy;
diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h
index d1570fd..659366a 100644
--- a/src/video/windows/SDL_windowswindow.h
+++ b/src/video/windows/SDL_windowswindow.h
@@ -49,6 +49,7 @@ typedef struct
Uint8 focus_click_pending;
SDL_bool skip_update_clipcursor;
Uint32 last_updated_clipcursor;
+ SDL_bool mouse_relative_mode_center;
SDL_bool windowed_mode_was_maximized;
SDL_bool in_window_deactivation;
RECT cursor_clipped_rect;