From 667b706a933d79ca02008f1cb57578c9215bf603 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 2 Apr 2025 20:20:19 -0400 Subject: [PATCH] x11: Don't set the hidden flag when minimizing windows On non-compositing window managers, XIconifyWindow can trigger map/unmap events, which would toggle the window hidden/shown state. This should not be done, as a hidden window in SDL is equivalent to a withdrawn window in X, and SDL will try to set/reset state when it is shown again. Unless the window is explicitly being withdrawn via X11_HideWindow(), set unmapped windows to the minimized/occluded state, and send a restored event when mapped again. --- src/video/x11/SDL_x11events.c | 36 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index e674b9abcf..2c5fb0dd0e 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -506,17 +506,29 @@ static void X11_DispatchFocusOut(SDL_VideoDevice *_this, SDL_WindowData *data) static void X11_DispatchMapNotify(SDL_WindowData *data) { SDL_Window *window = data->window; - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0); - if (!(window->flags & SDL_WINDOW_HIDDEN) && (window->flags & SDL_WINDOW_INPUT_FOCUS)) { + + // This may be sent when restoring a minimized window. + if (window->flags & SDL_WINDOW_MINIMIZED) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_EXPOSED, 0, 0); + } + + if (window->flags & SDL_WINDOW_INPUT_FOCUS) { SDL_UpdateWindowGrab(window); } } static void X11_DispatchUnmapNotify(SDL_WindowData *data) { - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIDDEN, 0, 0); - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); + SDL_Window *window = data->window; + + // This may be sent when minimizing a window. + if (!window->is_hiding) { + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); + SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_OCCLUDED, 0, 0); + } } static void DispatchWindowMove(SDL_VideoDevice *_this, const SDL_WindowData *data, const SDL_Point *point) @@ -1320,7 +1332,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) xevent->xcrossing.detail != NotifyInferior) { /* In order for interaction with the window decorations and menu to work properly - on Mutter, we need to ungrab the keyboard when the the mouse leaves. */ + on Mutter, we need to ungrab the keyboard when the mouse leaves. */ if (!(data->window->flags & SDL_WINDOW_FULLSCREEN)) { X11_SetWindowKeyboardGrab(_this, data->window, false); } @@ -1782,19 +1794,15 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) if (xevent->xproperty.atom == data->videodata->atoms._NET_WM_STATE) { /* Get the new state from the window manager. - Compositing window managers can alter visibility of windows - without ever mapping / unmapping them, so we handle that here, - because they use the NETWM protocol to notify us of changes. + * Compositing window managers can alter visibility of windows + * without ever mapping / unmapping them, so we handle that here, + * because they use the NETWM protocol to notify us of changes. */ const SDL_WindowFlags flags = X11_GetNetWMState(_this, data->window, xevent->xproperty.window); const SDL_WindowFlags changed = flags ^ data->window->flags; - if ((changed & (SDL_WINDOW_HIDDEN | SDL_WINDOW_FULLSCREEN)) != 0) { - if (flags & SDL_WINDOW_HIDDEN) { - X11_DispatchUnmapNotify(data); - } else { - X11_DispatchMapNotify(data); - } + if ((changed & SDL_WINDOW_HIDDEN) && !(flags & SDL_WINDOW_HIDDEN)) { + X11_DispatchMapNotify(data); } if (!SDL_WINDOW_IS_POPUP(data->window)) {