Skip to content

Commit 6677fad

Browse files
committed
Added SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED
Fixes #12785
1 parent bfc96c9 commit 6677fad

File tree

10 files changed

+75
-38
lines changed

10 files changed

+75
-38
lines changed

include/SDL3/SDL_events.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,9 @@ typedef enum SDL_EventType
127127
SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED, /**< Display has changed desktop mode */
128128
SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, /**< Display has changed current mode */
129129
SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed content scale */
130+
SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED, /**< Display has changed usable bounds */
130131
SDL_EVENT_DISPLAY_FIRST = SDL_EVENT_DISPLAY_ORIENTATION,
131-
SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED,
132+
SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED,
132133

133134
/* Window events */
134135
/* 0x200 was SDL_WINDOWEVENT, reserve the number for sdl2-compat */

src/events/SDL_events.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ int SDL_GetEventDescription(const SDL_Event *event, char *buf, int buflen)
525525
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED);
526526
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED);
527527
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED);
528+
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED);
528529
#undef SDL_DISPLAYEVENT_CASE
529530

530531
#define SDL_WINDOWEVENT_CASE(x) \

src/test/SDL_test_common.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,14 @@ void SDLTest_PrintEvent(const SDL_Event *event)
16261626
event->display.displayID, (int)(scale * 100.0f));
16271627
}
16281628
break;
1629+
case SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED:
1630+
{
1631+
SDL_Rect bounds;
1632+
SDL_GetDisplayUsableBounds(event->display.displayID, &bounds);
1633+
SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " changed usable bounds to %dx%d at %d,%d",
1634+
event->display.displayID, bounds.w, bounds.h, bounds.x, bounds.y);
1635+
}
1636+
break;
16291637
case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED:
16301638
SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " desktop mode changed to %" SDL_PRIs32 "x%" SDL_PRIs32,
16311639
event->display.displayID, event->display.data1, event->display.data2);

src/video/SDL_video.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,7 @@ bool SDL_GetDisplayBounds(SDL_DisplayID displayID, SDL_Rect *rect)
10641064
}
10651065

10661066
if (_this->GetDisplayBounds) {
1067+
SDL_zerop(rect);
10671068
if (_this->GetDisplayBounds(_this, display, rect)) {
10681069
return true;
10691070
}
@@ -1103,6 +1104,7 @@ bool SDL_GetDisplayUsableBounds(SDL_DisplayID displayID, SDL_Rect *rect)
11031104
}
11041105

11051106
if (_this->GetDisplayUsableBounds) {
1107+
SDL_zerop(rect);
11061108
if (_this->GetDisplayUsableBounds(_this, display, rect)) {
11071109
return true;
11081110
}

src/video/cocoa/SDL_cocoamodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
struct SDL_DisplayData
2727
{
2828
CGDirectDisplayID display;
29+
SDL_Rect usable_bounds;
2930
};
3031

3132
struct SDL_DisplayModeData

src/video/cocoa/SDL_cocoamodes.m

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,21 @@ static void Cocoa_GetHDRProperties(CGDirectDisplayID displayID, SDL_HDROutputPro
323323
}
324324
}
325325

326+
static bool Cocoa_GetUsableBounds(CGDirectDisplayID displayID, SDL_Rect *rect)
327+
{
328+
NSScreen *screen = GetNSScreenForDisplayID(displayID);
329+
330+
if (screen == nil) {
331+
return false;
332+
}
333+
334+
const NSRect frame = [screen visibleFrame];
335+
rect->x = (int)frame.origin.x;
336+
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
337+
rect->w = (int)frame.size.width;
338+
rect->h = (int)frame.size.height;
339+
return true;
340+
}
326341

327342
bool Cocoa_AddDisplay(CGDirectDisplayID display, bool send_event)
328343
{
@@ -331,7 +346,7 @@ bool Cocoa_AddDisplay(CGDirectDisplayID display, bool send_event)
331346
return false;
332347
}
333348

334-
SDL_DisplayData *displaydata = (SDL_DisplayData *)SDL_malloc(sizeof(*displaydata));
349+
SDL_DisplayData *displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata));
335350
if (!displaydata) {
336351
CGDisplayModeRelease(moderef);
337352
return false;
@@ -359,6 +374,8 @@ bool Cocoa_AddDisplay(CGDirectDisplayID display, bool send_event)
359374

360375
Cocoa_GetHDRProperties(displaydata->display, &viddisplay.HDR);
361376

377+
Cocoa_GetUsableBounds(displaydata->display, &displaydata->usable_bounds);
378+
362379
viddisplay.desktop_mode = mode;
363380
viddisplay.internal = displaydata;
364381
const bool retval = SDL_AddVideoDisplay(&viddisplay, send_event);
@@ -538,6 +555,13 @@ void Cocoa_UpdateDisplays(SDL_VideoDevice *_this)
538555

539556
Cocoa_GetHDRProperties(displaydata->display, &HDR);
540557
SDL_SetDisplayHDRProperties(display, &HDR);
558+
559+
SDL_Rect rect;
560+
if (Cocoa_GetUsableBounds(displaydata->display, &rect) &&
561+
SDL_memcmp(&displaydata->usable_bounds, &rect, sizeof(rect)) != 0) {
562+
SDL_memcpy(&displaydata->usable_bounds, &rect, sizeof(rect));
563+
SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED, 0, 0);
564+
}
541565
}
542566
}
543567

@@ -556,24 +580,10 @@ bool Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, S
556580

557581
bool Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
558582
{
559-
@autoreleasepool {
560-
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->internal;
561-
NSScreen *screen = GetNSScreenForDisplayID(displaydata->display);
562-
563-
if (screen == nil) {
564-
return SDL_SetError("Couldn't get NSScreen for display");
565-
}
566-
567-
{
568-
const NSRect frame = [screen visibleFrame];
569-
rect->x = (int)frame.origin.x;
570-
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
571-
rect->w = (int)frame.size.width;
572-
rect->h = (int)frame.size.height;
573-
}
583+
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->internal;
574584

575-
return true;
576-
}
585+
SDL_memcpy(rect, &displaydata->usable_bounds, sizeof(*rect));
586+
return true;
577587
}
578588

579589
bool Cocoa_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)

src/video/windows/SDL_windowsevents.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,6 +2422,9 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
24222422
if (wParam == SPI_SETMOUSE || wParam == SPI_SETMOUSESPEED) {
24232423
WIN_UpdateMouseSystemScale();
24242424
}
2425+
if (wParam == SPI_SETWORKAREA) {
2426+
WIN_UpdateDisplayUsableBounds(SDL_GetVideoDevice());
2427+
}
24252428
break;
24262429

24272430
#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)

src/video/windows/SDL_windowsmodes.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,14 @@ void WIN_RefreshDisplays(SDL_VideoDevice *_this)
933933
}
934934
}
935935

936+
void WIN_UpdateDisplayUsableBounds(SDL_VideoDevice *_this)
937+
{
938+
// This almost never happens, so just go ahead and send update events for all displays
939+
for (int i = 0; i < _this->num_displays; ++i) {
940+
SDL_SendDisplayEvent(_this->displays[i], SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED, 0, 0);
941+
}
942+
}
943+
936944
void WIN_QuitModes(SDL_VideoDevice *_this)
937945
{
938946
// All fullscreen windows should have restored modes by now

src/video/windows/SDL_windowsmodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern bool WIN_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay
5050
extern bool WIN_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display);
5151
extern bool WIN_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
5252
extern void WIN_RefreshDisplays(SDL_VideoDevice *_this);
53+
extern void WIN_UpdateDisplayUsableBounds(SDL_VideoDevice *_this);
5354
extern void WIN_QuitModes(SDL_VideoDevice *_this);
5455

5556
#endif // SDL_windowsmodes_h_

src/video/x11/SDL_x11events.c

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,31 +1418,33 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
14181418

14191419
X11_UpdateKeymap(_this, true);
14201420
}
1421-
} else if (xevent->type == PropertyNotify && videodata && videodata->windowlist) {
1421+
} else if (xevent->type == PropertyNotify && videodata) {
14221422
char *name_of_atom = X11_XGetAtomName(display, xevent->xproperty.atom);
1423-
1424-
if (SDL_strncmp(name_of_atom, "_ICC_PROFILE", sizeof("_ICC_PROFILE") - 1) == 0) {
1425-
XWindowAttributes attrib;
1426-
int screennum;
1427-
for (i = 0; i < videodata->numwindows; ++i) {
1428-
if (videodata->windowlist[i] != NULL) {
1429-
data = videodata->windowlist[i];
1430-
X11_XGetWindowAttributes(display, data->xwindow, &attrib);
1431-
screennum = X11_XScreenNumberOfScreen(attrib.screen);
1432-
if (screennum == 0 && SDL_strcmp(name_of_atom, "_ICC_PROFILE") == 0) {
1433-
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ICCPROF_CHANGED, 0, 0);
1434-
} else if (SDL_strncmp(name_of_atom, "_ICC_PROFILE_", sizeof("_ICC_PROFILE_") - 1) == 0 && SDL_strlen(name_of_atom) > sizeof("_ICC_PROFILE_") - 1) {
1435-
int iccscreennum = SDL_atoi(&name_of_atom[sizeof("_ICC_PROFILE_") - 1]);
1436-
1437-
if (screennum == iccscreennum) {
1423+
if (name_of_atom) {
1424+
if (SDL_startswith(name_of_atom, "_ICC_PROFILE")) {
1425+
XWindowAttributes attrib;
1426+
int screennum;
1427+
for (i = 0; i < videodata->numwindows; ++i) {
1428+
if (videodata->windowlist[i] != NULL) {
1429+
data = videodata->windowlist[i];
1430+
X11_XGetWindowAttributes(display, data->xwindow, &attrib);
1431+
screennum = X11_XScreenNumberOfScreen(attrib.screen);
1432+
if (screennum == 0 && SDL_strcmp(name_of_atom, "_ICC_PROFILE") == 0) {
14381433
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ICCPROF_CHANGED, 0, 0);
1434+
} else if (SDL_strncmp(name_of_atom, "_ICC_PROFILE_", sizeof("_ICC_PROFILE_") - 1) == 0 && SDL_strlen(name_of_atom) > sizeof("_ICC_PROFILE_") - 1) {
1435+
int iccscreennum = SDL_atoi(&name_of_atom[sizeof("_ICC_PROFILE_") - 1]);
1436+
1437+
if (screennum == iccscreennum) {
1438+
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ICCPROF_CHANGED, 0, 0);
1439+
}
14391440
}
14401441
}
14411442
}
1443+
} else if (SDL_strcmp(name_of_atom, "_NET_WORKAREA") == 0) {
1444+
for (i = 0; i < _this->num_displays; ++i) {
1445+
SDL_SendDisplayEvent(_this->displays[i], SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED, 0, 0);
1446+
}
14421447
}
1443-
}
1444-
1445-
if (name_of_atom) {
14461448
X11_XFree(name_of_atom);
14471449
}
14481450
}

0 commit comments

Comments
 (0)