defer clipcursor refresh unto pump finish

This commit is contained in:
expikr
2025-04-16 02:50:00 +08:00
committed by Sam Lantinga
parent c84c2aa2c4
commit dd625a6763
3 changed files with 27 additions and 13 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;