From 4b1378fe8e3f72b67e98510db20b8057baf2d2b9 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Sat, 18 Mar 2023 16:07:11 +0100 Subject: [PATCH] X11: fix size/position (test video_setWindowCenteredOnDisplay) this fix x11 backend to correctly pass video_setWindowCenteredOnDisplay() - get border values early (eg status bar) - wait for size/position change to get valid values Fix set topleft is client rendering area --- src/video/x11/SDL_x11events.c | 42 +++++++++++++++++++++-------------- src/video/x11/SDL_x11events.h | 1 + src/video/x11/SDL_x11window.c | 35 ++++++++++++++++++++++++----- 3 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index b373be12f3..fa5a34cd97 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -754,6 +754,30 @@ static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int return result; } +void X11_GetBorderValues(SDL_WindowData *data) +{ + SDL_VideoData *videodata = data->videodata; + Display *display = videodata->display; + + Atom type; + int format; + unsigned long nitems, bytes_after; + unsigned char *property; + if (X11_XGetWindowProperty(display, data->xwindow, videodata->_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &property) == Success) { + if (type != None && nitems == 4) { + data->border_left = (int)((long *)property)[0]; + data->border_right = (int)((long *)property)[1]; + data->border_top = (int)((long *)property)[2]; + data->border_bottom = (int)((long *)property)[3]; + } + X11_XFree(property); + +#ifdef DEBUG_XEVENTS + printf("New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d\n", data->border_left, data->border_right, data->border_top, data->border_bottom); +#endif + } +} + static void X11_DispatchEvent(_THIS, XEvent *xevent) { SDL_VideoData *videodata = _this->driverdata; @@ -1513,23 +1537,7 @@ static void X11_DispatchEvent(_THIS, XEvent *xevent) right approach, but it seems to work. */ X11_UpdateKeymap(_this, SDL_TRUE); } else if (xevent->xproperty.atom == videodata->_NET_FRAME_EXTENTS) { - Atom type; - int format; - unsigned long nitems, bytes_after; - unsigned char *property; - if (X11_XGetWindowProperty(display, data->xwindow, videodata->_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &property) == Success) { - if (type != None && nitems == 4) { - data->border_left = (int)((long *)property)[0]; - data->border_right = (int)((long *)property)[1]; - data->border_top = (int)((long *)property)[2]; - data->border_bottom = (int)((long *)property)[3]; - } - X11_XFree(property); - -#ifdef DEBUG_XEVENTS - printf("New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d\n", data->border_left, data->border_right, data->border_top, data->border_bottom); -#endif - } + X11_GetBorderValues(data); } } break; diff --git a/src/video/x11/SDL_x11events.h b/src/video/x11/SDL_x11events.h index a95b58454d..55b204b32c 100644 --- a/src/video/x11/SDL_x11events.h +++ b/src/video/x11/SDL_x11events.h @@ -28,5 +28,6 @@ extern int X11_WaitEventTimeout(_THIS, Sint64 timeoutNS); extern void X11_SendWakeupEvent(_THIS, SDL_Window *window); extern int X11_SuspendScreenSaver(_THIS); extern void X11_ReconcileKeyboardState(_THIS); +extern void X11_GetBorderValues(SDL_WindowData *data); #endif /* SDL_x11events_h_ */ diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 99f84e5a49..3fb5ca1b6f 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -905,8 +905,8 @@ void X11_UpdateWindowPosition(SDL_Window *window) attrs.x, attrs.y, &orig_x, &orig_y, &childReturn); SDL_RelativeToGlobalForWindow(window, - window->x - data->border_left, window->y - data->border_top, - &dest_x, &dest_y); + window->x - data->border_left, window->y - data->border_top, + &dest_x, &dest_y); /* Attempt to move the window */ X11_XMoveWindow(display, data->xwindow, dest_x, dest_y); @@ -1292,6 +1292,12 @@ void X11_ShowWindow(_THIS, SDL_Window *window) X11_SetKeyboardFocus(window); } } + + /* Get some valid border values, if we haven't them yet */ + if (data->border_left == 0 && data->border_right == 0 && data->border_top == 0 && data->border_bottom == 0) { + X11_GetBorderValues(data); + } + } void X11_HideWindow(_THIS, SDL_Window *window) @@ -1438,6 +1444,8 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis Display *display = data->videodata->display; Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE; Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN; + SDL_bool window_size_changed = SDL_FALSE; + int window_position_changed = 0; if (X11_IsWindowMapped(_this, window)) { XEvent e; @@ -1516,6 +1524,17 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis SubstructureNotifyMask | SubstructureRedirectMask, &e); } + if (!fullscreen) { + int dest_x = 0, dest_y = 0; + SDL_RelativeToGlobalForWindow(window, + window->windowed.x - data->border_left, window->windowed.y - data->border_top, + &dest_x, &dest_y); + + /* Attempt to move the window */ + X11_XMoveWindow(display, data->xwindow, dest_x, dest_y); + } + + /* Wait a brief time to see if the window manager decided to let this happen. If the window changes at all, even to an unexpected value, we break out. */ X11_XSync(display, False); @@ -1532,18 +1551,22 @@ static void X11_SetWindowFullscreenViaWM(_THIS, SDL_Window *window, SDL_VideoDis attrs.x, attrs.y, &x, &y, &childReturn); if (!caught_x11_error) { - SDL_bool window_changed = SDL_FALSE; if ((x != orig_x) || (y != orig_y)) { + orig_x = x; + orig_y = y; SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); - window_changed = SDL_TRUE; + window_position_changed += 1; } if ((attrs.width != orig_w) || (attrs.height != orig_h)) { + orig_w = attrs.width; + orig_h = attrs.height; SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, attrs.width, attrs.height); - window_changed = SDL_TRUE; + window_size_changed = SDL_TRUE; } - if (window_changed) { + /* Wait for at least 2 moves + 1 size changed to have valid values */ + if (window_position_changed >= 2 && window_size_changed) { break; /* window changed, time to go. */ } }