From e56f05bac15cbab5198a0921f084460aa21b5bae Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 24 Apr 2024 12:03:50 -0700 Subject: [PATCH] Fixed unclipping the mouse when a monitor is placed left of the primary one on Windows. There is now a desktop bounds variable that could potentially be exposed in the API if we wanted. --- src/events/SDL_displayevents.c | 3 +++ src/video/SDL_sysvideo.h | 2 ++ src/video/SDL_video.c | 31 +++++++++++++++++++++++++++ src/video/windows/SDL_windowswindow.c | 5 ++++- 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/events/SDL_displayevents.c b/src/events/SDL_displayevents.c index 14c29f308e..4b6fb98f20 100644 --- a/src/events/SDL_displayevents.c +++ b/src/events/SDL_displayevents.c @@ -57,6 +57,9 @@ int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, case SDL_EVENT_DISPLAY_ADDED: SDL_OnDisplayAdded(display); break; + case SDL_EVENT_DISPLAY_MOVED: + SDL_OnDisplayMoved(display); + break; default: break; } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 01c2eff203..065d11b8ea 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -352,6 +352,7 @@ struct SDL_VideoDevice SDL_Mutex *wakeup_lock; /* Initialized only if WaitEventTimeout/SendWakeupEvent are supported */ int num_displays; SDL_VideoDisplay **displays; + SDL_Rect desktop_bounds; SDL_Window *windows; SDL_Window *grabbed_window; Uint8 window_magic; @@ -515,6 +516,7 @@ extern void SDL_RelativeToGlobalForWindow(SDL_Window *window, int rel_x, int rel extern void SDL_GlobalToRelativeForWindow(SDL_Window *window, int abs_x, int abs_y, int *rel_x, int *rel_y); extern void SDL_OnDisplayAdded(SDL_VideoDisplay *display); +extern void SDL_OnDisplayMoved(SDL_VideoDisplay *display); extern void SDL_OnWindowShown(SDL_Window *window); extern void SDL_OnWindowHidden(SDL_Window *window); extern void SDL_OnWindowMoved(SDL_Window *window); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 4d05869bfb..69d4bffd97 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -624,6 +624,28 @@ SDL_SystemTheme SDL_GetSystemTheme(void) } } +static void SDL_UpdateDesktopBounds() +{ + SDL_Rect rect; + SDL_zero(rect); + + SDL_DisplayID *displays = SDL_GetDisplays(NULL); + if (displays) { + for (int i = 0; displays[i]; ++i) { + SDL_Rect bounds; + if (SDL_GetDisplayBounds(displays[i], &bounds) == 0) { + if (i == 0) { + SDL_copyp(&rect, &bounds); + } else { + SDL_GetRectUnion(&rect, &bounds, &rect); + } + } + } + SDL_free(displays); + } + SDL_copyp(&_this->desktop_bounds, &rect); +} + static void SDL_FinalizeDisplayMode(SDL_DisplayMode *mode) { /* Make sure all the fields are set up correctly */ @@ -705,6 +727,8 @@ SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, display->HDR.HDR_headroom); } + SDL_UpdateDesktopBounds(); + return id; } @@ -718,6 +742,11 @@ void SDL_OnDisplayAdded(SDL_VideoDisplay *display) } } +void SDL_OnDisplayMoved(SDL_VideoDisplay *display) +{ + SDL_UpdateDesktopBounds(); +} + void SDL_DelVideoDisplay(SDL_DisplayID displayID, SDL_bool send_event) { SDL_VideoDisplay *display; @@ -745,6 +774,8 @@ void SDL_DelVideoDisplay(SDL_DisplayID displayID, SDL_bool send_event) SDL_memmove(&_this->displays[display_index], &_this->displays[display_index + 1], (_this->num_displays - display_index - 1) * sizeof(_this->displays[display_index])); } --_this->num_displays; + + SDL_UpdateDesktopBounds(); } SDL_DisplayID *SDL_GetDisplays(int *count) diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index ee20396f75..b2dd17b187 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -1492,6 +1492,7 @@ static BOOL GetClientScreenRect(HWND hwnd, RECT *rect) void WIN_UpdateClipCursor(SDL_Window *window) { + SDL_VideoDevice *videodevice = SDL_GetVideoDevice(); SDL_WindowData *data = window->driverdata; SDL_Mouse *mouse = SDL_GetMouse(); RECT rect, clipped_rect; @@ -1568,7 +1569,9 @@ void WIN_UpdateClipCursor(SDL_Window *window) SDL_bool unclip_cursor = SDL_FALSE; /* If the cursor is clipped to the screen, clear the clip state */ - if (clipped_rect.left == 0 && clipped_rect.top == 0) { + if (!videodevice || + (clipped_rect.left == videodevice->desktop_bounds.x && + clipped_rect.top == videodevice->desktop_bounds.y)) { unclip_cursor = SDL_TRUE; } else { POINT first, second;