From e56f05bac15cbab5198a0921f084460aa21b5bae Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
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 14c29f308e398..4b6fb98f20f57 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 01c2eff203169..065d11b8ea6f3 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 4d05869bfbfab..69d4bffd97469 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 ee20396f75d25..b2dd17b187498 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;