Fixed bug 2260 - SDL_SetCursorGrab() is buggy on Windows BurnSpamAddress Steps to reproduce: 1. Grab the cursor with SDL_SetCursorGrab() 2. Alt-tab away from the window 3. Click on the titlebar of the window This will cause the window to disappear underneath the taskbar! This appears to be a general issue with ClipCursor() on windows, i.e. I am getting the same behavior if I call ClipCursor() directly. It is caused by a feedback loop between the ClipCursor function and the modal resize/move event loop that handles mouse-based sizing on Windows.
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
diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index eeb26c0..bbab2da 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -286,6 +286,45 @@ WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
return SDL_TRUE;
}
+static void
+WIN_UpdateClipCursor(SDL_Window *window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ /* Don't clip the cursor while we're in the modal resize or move loop */
+ if (data->in_modal_loop) {
+ ClipCursor(NULL);
+ return;
+ }
+
+ if (SDL_GetMouse()->relative_mode) {
+ LONG cx, cy;
+ RECT rect;
+ GetWindowRect(data->hwnd, &rect);
+
+ cx = (rect.left + rect.right) / 2;
+ cy = (rect.top + rect.bottom) / 2;
+
+ /* Make an absurdly small clip rect */
+ rect.left = cx-1;
+ rect.right = cx+1;
+ rect.top = cy-1;
+ rect.bottom = cy+1;
+
+ ClipCursor(&rect);
+ } else if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
+ (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
+ RECT rect;
+ if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
+ ClientToScreen(data->hwnd, (LPPOINT) & rect);
+ ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
+ ClipCursor(&rect);
+ }
+ } else {
+ ClipCursor(NULL);
+ }
+}
+
LRESULT CALLBACK
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
@@ -369,22 +408,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
data->mouse_button_flags = 0;
- if(SDL_GetMouse()->relative_mode) {
- LONG cx, cy;
- RECT rect;
- GetWindowRect(hwnd, &rect);
-
- cx = (rect.left + rect.right) / 2;
- cy = (rect.top + rect.bottom) / 2;
-
- /* Make an absurdly small clip rect */
- rect.left = cx-1;
- rect.right = cx+1;
- rect.top = cy-1;
- rect.bottom = cy+1;
-
- ClipCursor(&rect);
- }
+ WIN_UpdateClipCursor(data->window);
/*
* FIXME: Update keyboard state
@@ -585,6 +609,22 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
break;
#endif /* WM_INPUTLANGCHANGE */
+ case WM_ENTERSIZEMOVE:
+ case WM_ENTERMENULOOP:
+ {
+ data->in_modal_loop = SDL_TRUE;
+ WIN_UpdateClipCursor(data->window);
+ }
+ break;
+
+ case WM_EXITSIZEMOVE:
+ case WM_EXITMENULOOP:
+ {
+ data->in_modal_loop = SDL_FALSE;
+ WIN_UpdateClipCursor(data->window);
+ }
+ break;
+
#ifdef WM_GETMINMAXINFO
case WM_GETMINMAXINFO:
{
@@ -673,20 +713,14 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
RECT rect;
int x, y;
int w, h;
- Uint32 window_flags;
- if (!GetClientRect(hwnd, &rect) ||
- (rect.right == rect.left && rect.bottom == rect.top)) {
+ if (!GetClientRect(hwnd, &rect) || IsRectEmpty(&rect)) {
break;
}
ClientToScreen(hwnd, (LPPOINT) & rect);
ClientToScreen(hwnd, (LPPOINT) & rect + 1);
- window_flags = SDL_GetWindowFlags(data->window);
- if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
- (window_flags & SDL_WINDOW_INPUT_FOCUS)) {
- ClipCursor(&rect);
- }
+ WIN_UpdateClipCursor(data->window);
x = rect.left;
y = rect.top;
diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c
index f50a872..f75b8da 100644
--- a/src/video/windows/SDL_windowsmouse.c
+++ b/src/video/windows/SDL_windowsmouse.c
@@ -207,7 +207,7 @@ WIN_SetRelativeMouseMode(SDL_bool enabled)
/* (Un)register raw input for mice */
- if(RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
+ if (RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
/* Only return an error when registering. If we unregister and fail, then
it's probably that we unregistered twice. That's OK. */
@@ -216,7 +216,7 @@ WIN_SetRelativeMouseMode(SDL_bool enabled)
}
}
- if(enabled) {
+ if (enabled) {
LONG cx, cy;
RECT rect;
GetWindowRect(hWnd, &rect);
@@ -231,10 +231,9 @@ WIN_SetRelativeMouseMode(SDL_bool enabled)
rect.bottom = cy+1;
ClipCursor(&rect);
- }
- else
+ } else {
ClipCursor(NULL);
-
+ }
return 0;
}