From dd625a6763b8f33ce8049d2bc874eccad60a4798 Mon Sep 17 00:00:00 2001
From: expikr <[EMAIL REDACTED]>
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 c49bf334206d6..e3159ea580188 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 a11d74be8b966..173af204d1170 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 d23d83c04e46b..e15e5780f722a 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;