mirror of
https://github.com/Relintai/sdl2_frt.git
synced 2024-12-25 09:17:12 +01:00
video: Refresh Windows display list on WM_DISPLAYCHANGE
- Displays may have been added, removed or changed and all cached monitor handles are invalidated as a result. - Display events are handled in three steps: 1. Mark all currently know displays as invalid 2. Enumerate all displays, adding new ones and marking known displays as valid 3. Remove all displays still invalid after enumeration - Display connect/disconnect events are sent when displays are added or removed after initial setup
This commit is contained in:
parent
a558409b2e
commit
b9cbea354f
@ -1057,6 +1057,13 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WM_DISPLAYCHANGE:
|
||||||
|
{
|
||||||
|
// Reacquire displays if any were added or removed
|
||||||
|
WIN_RefreshDisplays(SDL_GetVideoDevice());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case WM_NCCALCSIZE:
|
case WM_NCCALCSIZE:
|
||||||
{
|
{
|
||||||
Uint32 window_flags = SDL_GetWindowFlags(data->window);
|
Uint32 window_flags = SDL_GetWindowFlags(data->window);
|
||||||
|
@ -140,8 +140,9 @@ WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mod
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool
|
static SDL_bool
|
||||||
WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEX *info)
|
WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEXW *info, SDL_bool send_event)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
SDL_VideoDisplay display;
|
SDL_VideoDisplay display;
|
||||||
SDL_DisplayData *displaydata;
|
SDL_DisplayData *displaydata;
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
@ -155,6 +156,18 @@ WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEX *info)
|
|||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent adding duplicate displays. Do this after we know the display is
|
||||||
|
// ready to be added to allow any displays that we can't fully query to be
|
||||||
|
// removed
|
||||||
|
for(i = 0; i < _this->num_displays; ++i) {
|
||||||
|
SDL_DisplayData *driverdata = (SDL_DisplayData *)_this->displays[i].driverdata;
|
||||||
|
if (SDL_wcscmp(driverdata->DeviceName, info->szDevice) == 0) {
|
||||||
|
driverdata->MonitorHandle = hMonitor;
|
||||||
|
driverdata->IsValid = SDL_TRUE;
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
|
displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
|
||||||
if (!displaydata) {
|
if (!displaydata) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
@ -162,6 +175,7 @@ WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEX *info)
|
|||||||
SDL_memcpy(displaydata->DeviceName, info->szDevice,
|
SDL_memcpy(displaydata->DeviceName, info->szDevice,
|
||||||
sizeof(displaydata->DeviceName));
|
sizeof(displaydata->DeviceName));
|
||||||
displaydata->MonitorHandle = hMonitor;
|
displaydata->MonitorHandle = hMonitor;
|
||||||
|
displaydata->IsValid = SDL_TRUE;
|
||||||
|
|
||||||
SDL_zero(display);
|
SDL_zero(display);
|
||||||
device.cb = sizeof(device);
|
device.cb = sizeof(device);
|
||||||
@ -171,13 +185,14 @@ WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEX *info)
|
|||||||
display.desktop_mode = mode;
|
display.desktop_mode = mode;
|
||||||
display.current_mode = mode;
|
display.current_mode = mode;
|
||||||
display.driverdata = displaydata;
|
display.driverdata = displaydata;
|
||||||
SDL_AddVideoDisplay(&display, SDL_FALSE);
|
SDL_AddVideoDisplay(&display, send_event);
|
||||||
SDL_free(display.name);
|
SDL_free(display.name);
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _WIN_AddDisplaysData {
|
typedef struct _WIN_AddDisplaysData {
|
||||||
SDL_VideoDevice *video_device;
|
SDL_VideoDevice *video_device;
|
||||||
|
SDL_bool send_event;
|
||||||
SDL_bool want_primary;
|
SDL_bool want_primary;
|
||||||
} WIN_AddDisplaysData;
|
} WIN_AddDisplaysData;
|
||||||
|
|
||||||
@ -188,16 +203,16 @@ WIN_AddDisplaysCallback(HMONITOR hMonitor,
|
|||||||
LPARAM dwData)
|
LPARAM dwData)
|
||||||
{
|
{
|
||||||
WIN_AddDisplaysData *data = (WIN_AddDisplaysData*)dwData;
|
WIN_AddDisplaysData *data = (WIN_AddDisplaysData*)dwData;
|
||||||
MONITORINFOEX info;
|
MONITORINFOEXW info;
|
||||||
|
|
||||||
SDL_zero(info);
|
SDL_zero(info);
|
||||||
info.cbSize = sizeof(info);
|
info.cbSize = sizeof(info);
|
||||||
|
|
||||||
if (GetMonitorInfo(hMonitor, (LPMONITORINFO)&info) != 0) {
|
if (GetMonitorInfoW(hMonitor, (LPMONITORINFO)&info) != 0) {
|
||||||
const SDL_bool is_primary = ((info.dwFlags & MONITORINFOF_PRIMARY) == MONITORINFOF_PRIMARY);
|
const SDL_bool is_primary = ((info.dwFlags & MONITORINFOF_PRIMARY) == MONITORINFOF_PRIMARY);
|
||||||
|
|
||||||
if (is_primary == data->want_primary) {
|
if (is_primary == data->want_primary) {
|
||||||
WIN_AddDisplay(data->video_device, hMonitor, &info);
|
WIN_AddDisplay(data->video_device, hMonitor, &info, data->send_event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,10 +221,11 @@ WIN_AddDisplaysCallback(HMONITOR hMonitor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
WIN_AddDisplays(_THIS)
|
WIN_AddDisplays(_THIS, SDL_bool send_event)
|
||||||
{
|
{
|
||||||
WIN_AddDisplaysData callback_data;
|
WIN_AddDisplaysData callback_data;
|
||||||
callback_data.video_device = _this;
|
callback_data.video_device = _this;
|
||||||
|
callback_data.send_event = send_event;
|
||||||
|
|
||||||
callback_data.want_primary = SDL_TRUE;
|
callback_data.want_primary = SDL_TRUE;
|
||||||
EnumDisplayMonitors(NULL, NULL, WIN_AddDisplaysCallback, (LPARAM)&callback_data);
|
EnumDisplayMonitors(NULL, NULL, WIN_AddDisplaysCallback, (LPARAM)&callback_data);
|
||||||
@ -221,7 +237,7 @@ WIN_AddDisplays(_THIS)
|
|||||||
int
|
int
|
||||||
WIN_InitModes(_THIS)
|
WIN_InitModes(_THIS)
|
||||||
{
|
{
|
||||||
WIN_AddDisplays(_this);
|
WIN_AddDisplays(_this, SDL_FALSE);
|
||||||
|
|
||||||
if (_this->num_displays == 0) {
|
if (_this->num_displays == 0) {
|
||||||
return SDL_SetError("No displays available");
|
return SDL_SetError("No displays available");
|
||||||
@ -395,6 +411,32 @@ WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WIN_RefreshDisplays(_THIS)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Mark all displays as potentially invalid to detect
|
||||||
|
// entries that have actually been removed
|
||||||
|
for (i = 0; i < _this->num_displays; ++i) {
|
||||||
|
SDL_DisplayData *driverdata = (SDL_DisplayData *)_this->displays[i].driverdata;
|
||||||
|
driverdata->IsValid = SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enumerate displays to add any new ones and mark still
|
||||||
|
// connected entries as valid
|
||||||
|
WIN_AddDisplays(_this, SDL_TRUE);
|
||||||
|
|
||||||
|
// 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_DisplayData *driverdata = (SDL_DisplayData *)_this->displays[i].driverdata;
|
||||||
|
if (driverdata->IsValid == SDL_FALSE) {
|
||||||
|
SDL_DelVideoDisplay(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WIN_QuitModes(_THIS)
|
WIN_QuitModes(_THIS)
|
||||||
{
|
{
|
||||||
|
@ -25,8 +25,9 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
TCHAR DeviceName[32];
|
WCHAR DeviceName[32];
|
||||||
HMONITOR MonitorHandle;
|
HMONITOR MonitorHandle;
|
||||||
|
SDL_bool IsValid;
|
||||||
} SDL_DisplayData;
|
} SDL_DisplayData;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -40,6 +41,7 @@ extern int WIN_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rec
|
|||||||
extern int WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi);
|
extern int WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi);
|
||||||
extern void WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
|
extern void WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
|
||||||
extern int WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
|
extern int WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
|
||||||
|
extern void WIN_RefreshDisplays(_THIS);
|
||||||
extern void WIN_QuitModes(_THIS);
|
extern void WIN_QuitModes(_THIS);
|
||||||
|
|
||||||
#endif /* SDL_windowsmodes_h_ */
|
#endif /* SDL_windowsmodes_h_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user