From dd625a6763b8f33ce8049d2bc874eccad60a4798 Mon Sep 17 00:00:00 2001 From: expikr <77922942+expikr@users.noreply.github.com> Date: Wed, 16 Apr 2025 02:50:00 +0800 Subject: [PATCH] defer clipcursor refresh unto pump finish --- src/video/windows/SDL_windowsevents.c | 35 ++++++++++++++++++--------- src/video/windows/SDL_windowswindow.c | 2 +- src/video/windows/SDL_windowswindow.h | 3 ++- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index c49bf33420..e3159ea580 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1240,11 +1240,8 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara case WM_NCACTIVATE: { // Don't immediately clip the cursor in case we're clicking minimize/maximize buttons - // This is the only place that this flag is set. This causes all subsequent calls to - // WIN_UpdateClipCursor for this window to be no-ops in this frame's message-pumping. - // This flag is unset at the end of message pumping each frame for every window, and - // should never be carried over between frames. - data->skip_update_clipcursor = true; + data->postpone_clipcursor = true; + data->clipcursor_queued = true; /* Update the focus here, since it's possible to get WM_ACTIVATE and WM_SETFOCUS without actually being the foreground window, but this appears to get called in all cases where @@ -1413,9 +1410,8 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara window->flags & (SDL_WINDOW_MOUSE_RELATIVE_MODE | SDL_WINDOW_MOUSE_GRABBED) || (window->mouse_rect.w > 0 && window->mouse_rect.h > 0) ); - if (wish_clip_cursor) { - data->skip_update_clipcursor = false; - WIN_UpdateClipCursor(window); + if (wish_clip_cursor) { // queue clipcursor refresh on pump finish + data->clipcursor_queued = true; } } @@ -1440,6 +1436,9 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara SDL_SendMouseMotion(WIN_GetEventTimestamp(), window, SDL_GLOBAL_MOUSE_ID, false, (float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam)); } } + + return 0; + } break; case WM_LBUTTONUP: @@ -2602,13 +2601,27 @@ void WIN_PumpEvents(SDL_VideoDevice *_this) } } - // Update the clipping rect in case someone else has stolen it + // fire queued clipcursor refreshes if (_this) { SDL_Window *window = _this->windows; while (window) { + bool refresh_clipcursor = false; SDL_WindowData *data = window->internal; - if (data && data->skip_update_clipcursor) { - data->skip_update_clipcursor = false; + if (data) { + refresh_clipcursor = data->clipcursor_queued; + data->clipcursor_queued = false; // Must be cleared unconditionally. + data->postpone_clipcursor = false; // Must be cleared unconditionally. + // Must happen before UpdateClipCursor. + // Although its occurrence currently + // always coincides with the queuing of + // clipcursor, it is logically distinct + // and this coincidence might no longer + // be true in the future. + // Ergo this placement concordantly + // conveys its unconditionality + // vis-a-vis the queuing of clipcursor. + } + if (refresh_clipcursor) { WIN_UpdateClipCursor(window); } window = window->next; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index a11d74be8b..173af204d1 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -1627,7 +1627,7 @@ void WIN_UnclipCursorForWindow(SDL_Window *window) { void WIN_UpdateClipCursor(SDL_Window *window) { SDL_WindowData *data = window->internal; - if (data->in_title_click || data->focus_click_pending || data->skip_update_clipcursor) { + if (data->in_title_click || data->focus_click_pending || data->postpone_clipcursor) { return; } diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index d23d83c04e..e15e5780f7 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -78,7 +78,8 @@ struct SDL_WindowData bool in_border_change; bool in_title_click; Uint8 focus_click_pending; - bool skip_update_clipcursor; + bool postpone_clipcursor; + bool clipcursor_queued; bool windowed_mode_was_maximized; bool in_window_deactivation; bool force_ws_maximizebox;