From 50203d58b3a87defd5cfebc26232a3da50e1a32a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 8 Dec 2020 22:00:06 -0800 Subject: [PATCH] Fixed bug 5329 - SDL_SetWindowGrab(SDL_FALSE) fails to unlock cursor if window is partially offscreen Ivan Mogilko With SDL 2.0.12 under MS Windows, if the window is partially offscreen calling SDL_SetWindowGrab(w, SDL_TRUE) works, but subsequent call to SDL_SetWindowGrab(w, SDL_FALSE) does not work. I tested this in both real program, and a small test app, where unlocking cursor worked perfectly while window is fully in desktop bounds, but did not work if it was at least few pixels outside. For the reference, following code is enough to reproduce the issue: #include #include int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { SDL_Init(SDL_INIT_VIDEO); SDL_Window* w = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 400, 0); bool grabbed = false; bool want_quit = false; while (!want_quit) { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: want_quit = true; break; case SDL_KEYDOWN: if (event.key.keysym.scancode == SDL_SCANCODE_SPACE) { SDL_SetWindowGrab(w, static_cast(!grabbed)); grabbed = !grabbed; } } } } SDL_DestroyWindow(w); SDL_Quit(); return 0; } --- src/video/windows/SDL_windowswindow.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index ae3a9f60c..dd21315a8 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -954,9 +954,18 @@ WIN_UpdateClipCursor(SDL_Window *window) } } } - } else if (SDL_memcmp(&clipped_rect, &data->cursor_clipped_rect, sizeof(clipped_rect)) == 0) { - ClipCursor(NULL); - SDL_zero(data->cursor_clipped_rect); + } else { + POINT first, second; + + first.x = clipped_rect.left; + first.y = clipped_rect.top; + second.x = clipped_rect.right - 1; + second.y = clipped_rect.bottom - 1; + if (PtInRect(&data->cursor_clipped_rect, first) && + PtInRect(&data->cursor_clipped_rect, second)) { + ClipCursor(NULL); + SDL_zero(data->cursor_clipped_rect); + } } data->last_updated_clipcursor = SDL_GetTicks(); }