From 2e27812d39d17831da0a0d8afa1add6c8795af5a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 2 Jun 2023 08:51:47 -0700 Subject: [PATCH] Fixed event sequence when Remote Desktop connects and disconnects 1. Send display disconnected events for all displays no longer connected 2. Send display connected events for all displays that have been connected 3. Send window display events for any windows that have changed displays --- src/events/SDL_displayevents.c | 8 +++++++ src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 11 ++++++++++ src/video/windows/SDL_windowsmodes.c | 32 +++++++++++++++++----------- src/video/windows/SDL_windowsmodes.h | 10 ++++++++- 5 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/events/SDL_displayevents.c b/src/events/SDL_displayevents.c index cf3694466..803d24d43 100644 --- a/src/events/SDL_displayevents.c +++ b/src/events/SDL_displayevents.c @@ -53,5 +53,13 @@ int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, posted = (SDL_PushEvent(&event) > 0); } + switch (displayevent) { + case SDL_EVENT_DISPLAY_CONNECTED: + SDL_OnDisplayConnected(display); + break; + default: + break; + } + return posted; } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 5590e941c..9da28a1c3 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -517,6 +517,7 @@ extern SDL_bool SDL_HasWindows(void); extern void SDL_RelativeToGlobalForWindow(SDL_Window *window, int rel_x, int rel_y, int *abs_x, int *abs_y); extern void SDL_GlobalToRelativeForWindow(SDL_Window *window, int abs_x, int abs_y, int *rel_x, int *rel_y); +extern void SDL_OnDisplayConnected(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 af6c9194e..83936dda9 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -160,6 +160,7 @@ extern SDL_bool Cocoa_IsWindowInFullscreenSpace(SDL_Window *window); extern SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, SDL_bool state); #endif +static void SDL_CheckWindowDisplayChanged(SDL_Window *window); static void SDL_CheckWindowDisplayScaleChanged(SDL_Window *window); /* Convenience functions for reading driver flags */ @@ -694,6 +695,16 @@ SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send return id; } +void SDL_OnDisplayConnected(SDL_VideoDisplay *display) +{ + SDL_Window *window; + + /* See if any windows have changed to the new display */ + for (window = _this->windows; window; window = window->next) { + SDL_CheckWindowDisplayChanged(window); + } +} + void SDL_DelVideoDisplay(SDL_DisplayID displayID, SDL_bool send_event) { SDL_VideoDisplay *display; diff --git a/src/video/windows/SDL_windowsmodes.c b/src/video/windows/SDL_windowsmodes.c index 79a72daa1..50fa93e0b 100644 --- a/src/video/windows/SDL_windowsmodes.c +++ b/src/video/windows/SDL_windowsmodes.c @@ -318,7 +318,7 @@ WIN_GetDisplayNameVista_failed: return NULL; } -static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONITORINFOEXW *info, int *display_index, SDL_bool send_event) +static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONITORINFOEXW *info, int *display_index) { int i, index = *display_index; SDL_DisplayID displayID; @@ -356,7 +356,7 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI } driverdata->MonitorHandle = hMonitor; - driverdata->IsValid = SDL_TRUE; + driverdata->state = DisplayUnchanged; if (!_this->setting_display_mode) { SDL_VideoDisplay *existing_display = &_this->displays[i]; @@ -385,7 +385,7 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI } SDL_memcpy(displaydata->DeviceName, info->szDevice, sizeof(displaydata->DeviceName)); displaydata->MonitorHandle = hMonitor; - displaydata->IsValid = SDL_TRUE; + displaydata->state = DisplayAdded; SDL_zero(display); display.name = WIN_GetDisplayNameVista(info->szDevice); @@ -404,8 +404,7 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI display.device = _this; display.driverdata = displaydata; WIN_GetDisplayBounds(_this, &display, &displaydata->bounds); - displayID = SDL_AddVideoDisplay(&display, send_event); - SDL_assert(SDL_GetDisplayIndex(displayID) == *display_index); + displayID = SDL_AddVideoDisplay(&display, SDL_FALSE); SDL_free(display.name); done: @@ -416,7 +415,6 @@ typedef struct _WIN_AddDisplaysData { SDL_VideoDevice *video_device; int display_index; - SDL_bool send_event; SDL_bool want_primary; } WIN_AddDisplaysData; @@ -435,7 +433,7 @@ static BOOL CALLBACK WIN_AddDisplaysCallback(HMONITOR hMonitor, const SDL_bool is_primary = ((info.dwFlags & MONITORINFOF_PRIMARY) == MONITORINFOF_PRIMARY); if (is_primary == data->want_primary) { - WIN_AddDisplay(data->video_device, hMonitor, &info, &data->display_index, data->send_event); + WIN_AddDisplay(data->video_device, hMonitor, &info, &data->display_index); } } @@ -443,12 +441,11 @@ static BOOL CALLBACK WIN_AddDisplaysCallback(HMONITOR hMonitor, return TRUE; } -static void WIN_AddDisplays(SDL_VideoDevice *_this, SDL_bool send_event) +static void WIN_AddDisplays(SDL_VideoDevice *_this) { WIN_AddDisplaysData callback_data; callback_data.video_device = _this; callback_data.display_index = 0; - callback_data.send_event = send_event; callback_data.want_primary = SDL_TRUE; EnumDisplayMonitors(NULL, NULL, WIN_AddDisplaysCallback, (LPARAM)&callback_data); @@ -459,7 +456,7 @@ static void WIN_AddDisplays(SDL_VideoDevice *_this, SDL_bool send_event) int WIN_InitModes(SDL_VideoDevice *_this) { - WIN_AddDisplays(_this, SDL_FALSE); + WIN_AddDisplays(_this); if (_this->num_displays == 0) { return SDL_SetError("No displays available"); @@ -636,22 +633,31 @@ void WIN_RefreshDisplays(SDL_VideoDevice *_this) // entries that have actually been removed for (i = 0; i < _this->num_displays; ++i) { SDL_DisplayData *driverdata = _this->displays[i].driverdata; - driverdata->IsValid = SDL_FALSE; + driverdata->state = DisplayRemoved; } // Enumerate displays to add any new ones and mark still // connected entries as valid - WIN_AddDisplays(_this, SDL_TRUE); + WIN_AddDisplays(_this); // Delete any entries still marked as invalid, iterate // in reverse as each delete takes effect immediately for (i = _this->num_displays - 1; i >= 0; --i) { SDL_VideoDisplay *display = &_this->displays[i]; SDL_DisplayData *driverdata = display->driverdata; - if (driverdata->IsValid == SDL_FALSE) { + if (driverdata->state == DisplayRemoved) { SDL_DelVideoDisplay(display->id, SDL_TRUE); } } + + // Send events for any newly added displays + for (i = 0; i < _this->num_displays; ++i) { + SDL_VideoDisplay *display = &_this->displays[i]; + SDL_DisplayData *driverdata = display->driverdata; + if (driverdata->state == DisplayAdded) { + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_CONNECTED, 0); + } + } } void WIN_QuitModes(SDL_VideoDevice *_this) diff --git a/src/video/windows/SDL_windowsmodes.h b/src/video/windows/SDL_windowsmodes.h index 37ea30426..31a76026c 100644 --- a/src/video/windows/SDL_windowsmodes.h +++ b/src/video/windows/SDL_windowsmodes.h @@ -23,11 +23,19 @@ #ifndef SDL_windowsmodes_h_ #define SDL_windowsmodes_h_ +typedef enum +{ + DisplayUnchanged, + DisplayAdded, + DisplayRemoved, + +} WIN_DisplayState; + struct SDL_DisplayData { WCHAR DeviceName[32]; HMONITOR MonitorHandle; - SDL_bool IsValid; + WIN_DisplayState state; SDL_Rect bounds; };