diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 678ce88d19cb15..bd7cea779b0468 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -115,6 +115,8 @@ typedef enum SDL_EventType SDL_EVENT_DISPLAY_ADDED, /**< Display has been added to the system */ SDL_EVENT_DISPLAY_REMOVED, /**< Display has been removed from the system */ SDL_EVENT_DISPLAY_MOVED, /**< Display has changed position */ + SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED, /**< Display has changed desktop mode */ + SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, /**< Display has changed current mode */ SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed content scale */ SDL_EVENT_DISPLAY_FIRST = SDL_EVENT_DISPLAY_ORIENTATION, SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, @@ -281,6 +283,7 @@ typedef struct SDL_DisplayEvent Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_DisplayID displayID;/**< The associated display */ Sint32 data1; /**< event dependent data */ + Sint32 data2; /**< event dependent data */ } SDL_DisplayEvent; /** diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index a426506010612b..2d9587a7373028 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -991,7 +991,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeRotationChanged)( if (Android_Window) { SDL_VideoDisplay *display = SDL_GetVideoDisplay(SDL_GetPrimaryDisplay()); - SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, displayCurrentOrientation); + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, displayCurrentOrientation, 0); } SDL_UnlockMutex(Android_ActivityMutex); diff --git a/src/events/SDL_displayevents.c b/src/events/SDL_displayevents.c index 4b6fb98f20f573..3740ef11481be4 100644 --- a/src/events/SDL_displayevents.c +++ b/src/events/SDL_displayevents.c @@ -24,7 +24,7 @@ #include "SDL_events_c.h" -int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1) +int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1, int data2) { int posted; @@ -50,6 +50,7 @@ int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, event.common.timestamp = 0; event.display.displayID = display->id; event.display.data1 = data1; + event.display.data2 = data2; posted = (SDL_PushEvent(&event) > 0); } diff --git a/src/events/SDL_displayevents_c.h b/src/events/SDL_displayevents_c.h index c93d9ffa15e1e4..6ccba10eae7f06 100644 --- a/src/events/SDL_displayevents_c.h +++ b/src/events/SDL_displayevents_c.h @@ -23,6 +23,6 @@ #ifndef SDL_displayevents_c_h_ #define SDL_displayevents_c_h_ -extern int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1); +extern int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1, int data2); #endif /* SDL_displayevents_c_h_ */ diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 069c8248e2c209..6e617ed8eae04e 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -285,13 +285,15 @@ static void SDL_LogEvent(const SDL_Event *event) #define SDL_DISPLAYEVENT_CASE(x) \ case x: \ SDL_strlcpy(name, #x, sizeof(name)); \ - (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u display=%u event=%s data1=%d)", \ - (uint)event->display.timestamp, (uint)event->display.displayID, name, (int)event->display.data1); \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u display=%u event=%s data1=%d, data2=%d)", \ + (uint)event->display.timestamp, (uint)event->display.displayID, name, (int)event->display.data1, (int)event->display.data2); \ break SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ORIENTATION); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ADDED); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_REMOVED); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_MOVED); + SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED); + SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED); #undef SDL_DISPLAYEVENT_CASE diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 159cb49a031c3e..6159e91e15d2b7 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1563,7 +1563,7 @@ static void SDLTest_PrintEvent(const SDL_Event *event) { switch (event->type) { case SDL_EVENT_SYSTEM_THEME_CHANGED: - SDL_Log("SDL EVENT: System theme changed to %s\n", SystemThemeName()); + SDL_Log("SDL EVENT: System theme changed to %s", SystemThemeName()); break; case SDL_EVENT_DISPLAY_ADDED: SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " attached", @@ -1576,6 +1576,14 @@ static void SDLTest_PrintEvent(const SDL_Event *event) event->display.displayID, (int)(scale * 100.0f)); } break; + case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED: + SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " desktop mode changed to %" SDL_PRIs32 "x%" SDL_PRIs32, + event->display.displayID, (int)event->display.data1, event->display.data2); + break; + case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED: + SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " current mode changed to %" SDL_PRIs32 "x%" SDL_PRIs32, + event->display.displayID, event->display.data1, event->display.data2); + break; case SDL_EVENT_DISPLAY_MOVED: SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " changed position", event->display.displayID); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 6618020a3b86f6..e3c1dc56b02cd8 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -791,7 +791,7 @@ SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send SDL_UpdateDesktopBounds(); if (send_event) { - SDL_SendDisplayEvent(new_display, SDL_EVENT_DISPLAY_ADDED, 0); + SDL_SendDisplayEvent(new_display, SDL_EVENT_DISPLAY_ADDED, 0, 0); } return id; @@ -823,7 +823,7 @@ void SDL_DelVideoDisplay(SDL_DisplayID displayID, SDL_bool send_event) display = _this->displays[display_index]; if (send_event) { - SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_REMOVED, 0); + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_REMOVED, 0, 0); } SDL_DestroyProperties(display->props); @@ -1044,7 +1044,7 @@ void SDL_SetDisplayContentScale(SDL_VideoDisplay *display, float scale) SDL_Window *window; display->content_scale = scale; - SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, 0); + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, 0, 0); /* Check the windows on this display */ for (window = _this->windows; window; window = window->next) { @@ -1310,14 +1310,34 @@ const SDL_DisplayMode *SDL_GetClosestFullscreenDisplayMode(SDL_DisplayID display return closest; } +static SDL_bool DisplayModeChanged(const SDL_DisplayMode *old, const SDL_DisplayMode *new) +{ + return ((old->displayID && old->displayID != new->displayID) || + (old->format && old->format != new->format) || + (old->w && old->h && (old->w != new->w ||old->h != new->h)) || + (old->pixel_density && old->pixel_density != new->pixel_density) || + (old->refresh_rate && old->refresh_rate != new->refresh_rate)); +} + void SDL_SetDesktopDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode) { + SDL_DisplayMode last_mode; + + SDL_copyp(&last_mode, &display->desktop_mode); + if (display->desktop_mode.driverdata) { SDL_free(display->desktop_mode.driverdata); } - SDL_memcpy(&display->desktop_mode, mode, sizeof(*mode)); + SDL_copyp(&display->desktop_mode, mode); display->desktop_mode.displayID = display->id; SDL_FinalizeDisplayMode(&display->desktop_mode); + + if (DisplayModeChanged(&last_mode, &display->desktop_mode)) { + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED, mode->w, mode->h); + if (display->current_mode == &display->desktop_mode) { + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, mode->w, mode->h); + } + } } const SDL_DisplayMode *SDL_GetDesktopDisplayMode(SDL_DisplayID displayID) @@ -1331,7 +1351,19 @@ const SDL_DisplayMode *SDL_GetDesktopDisplayMode(SDL_DisplayID displayID) void SDL_SetCurrentDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode) { + SDL_DisplayMode last_mode; + + if (display->current_mode) { + SDL_copyp(&last_mode, display->current_mode); + } else { + SDL_zero(last_mode); + } + display->current_mode = mode; + + if (DisplayModeChanged(&last_mode, mode)) { + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, mode->w, mode->h); + } } const SDL_DisplayMode *SDL_GetCurrentDisplayMode(SDL_DisplayID displayID) diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m index 98b84ae96619e6..70e99a3590fb10 100644 --- a/src/video/uikit/SDL_uikitmodes.m +++ b/src/video/uikit/SDL_uikitmodes.m @@ -534,7 +534,7 @@ void SDL_OnApplicationDidChangeStatusBarOrientation(void) default: break; } - SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, orientation); + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, orientation, 0); } } #endif /* !SDL_PLATFORM_TVOS */ diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 0745c09161dc9e..e7515880c602d0 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -905,7 +905,7 @@ static void display_handle_done(void *data, SDL_zero(driverdata->placeholder); } } else { - SDL_SendDisplayEvent(dpy, SDL_EVENT_DISPLAY_ORIENTATION, driverdata->orientation); + SDL_SendDisplayEvent(dpy, SDL_EVENT_DISPLAY_ORIENTATION, driverdata->orientation, 0); } } diff --git a/src/video/windows/SDL_windowsmodes.c b/src/video/windows/SDL_windowsmodes.c index adc8ed860e1e80..19bea73f6f54c7 100644 --- a/src/video/windows/SDL_windowsmodes.c +++ b/src/video/windows/SDL_windowsmodes.c @@ -538,9 +538,9 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI SDL_copyp(&driverdata->bounds, &bounds); } if (moved || changed_bounds) { - SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_MOVED, 0); + SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_MOVED, 0, 0); } - SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_ORIENTATION, current_orientation); + SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_ORIENTATION, current_orientation, 0); SDL_SetDisplayContentScale(existing_display, content_scale); #ifdef HAVE_DXGI1_6_H SDL_HDROutputProperties HDR; @@ -832,7 +832,7 @@ void WIN_RefreshDisplays(SDL_VideoDevice *_this) SDL_VideoDisplay *display = _this->displays[i]; SDL_DisplayData *driverdata = display->driverdata; if (driverdata->state == DisplayAdded) { - SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ADDED, 0); + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ADDED, 0, 0); } } }