We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2409

Summary: Window steals focus when switching to a different desktop
Product: SDL Reporter: Katie Stafford <katie>
Component: videoAssignee: Sam Lantinga <slouken>
Status: ASSIGNED --- QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 CC: blacktav, katie
Version: 2.0.1   
Hardware: x86_64   
OS: Linux   
Attachments: Quick patch

Description Katie Stafford 2014-02-21 07:16:35 UTC
When I run an SDL2 application in a window, if I switch to another desktop, the SDL application will request focus immediately, cause the window manager to switch back to the desktop containing the SDL application and bring it to the front.

The only way that I can actually switch to a different desktop is if: 1. The SDL application is currently the foreground window, 2: I use keyboard shortcuts (clicking on the pager does not work), and 3: there is no full-screen window on the desktop I switch to (e.g. Firefox in full-screen mode).

Here is a video which demonstrates this behavior, and also shows which events the application receives when the bug happens: https://www.youtube.com/watch?v=BfxtD-PCNz4

I am using XFCE as a window manager.
Comment 1 Sam Lantinga 2014-02-23 01:22:34 UTC
I've never seen this behavior or heard of it before. Can you track down the sequence of X11 events and calls that are causing this?

Thanks!
Comment 2 Katie Stafford 2014-02-23 06:39:32 UTC
Created attachment 1575 [details]
Quick patch

I've traced the problem to SDL_x11events.c:768, in the handling for PropertyNotify:

            if (xevent.xproperty.atom == data->videodata->_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.
                 */
                Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
                if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN) {
                    if (flags & SDL_WINDOW_HIDDEN) {
                        X11_DispatchUnmapNotify(data);
                    } else {
                        X11_DispatchMapNotify(data);
                    }
                }
            }

The problem is that XFCE only sets _NET_WM_STATE_HIDDEN on windows that are minimized, not on windows that are not visible due to being on another desktop.

The comment above indicates that this code works around other window managers not sending unmap events, so it shouldn't be run if an unmap event has been received, i.e. SDL_WINDOW_HIDDEN should be the logical OR of <unmapped> or <_NET_WM_STATE_HIDDEN>.

I have attached a quick-and-dirty patch which fixes the problem for me, but I haven't tested with any other window managers.
Comment 3 Katie Stafford 2014-02-23 06:51:06 UTC
There is another related issue that happens now that I have applied the patch: SDL_OnWindowRestored calls SDL_RaiseWindow, so any time the window is unhidden, it steals focus. If I have an SDL application in the background, and I switch to another desktop, then switch back, the SDL application will now be in the foreground.

Is there a reason SDL_RaiseWindow needs to be called from SDL_OnWindowRestored? It seems that the intention was that OnWindowRestored means that the window was minimized, and the user has just switched to it, in which case it should already be in the foreground and focused.
Comment 4 Katie Stafford 2014-03-08 16:50:01 UTC
Forgot to mark as responded
Comment 5 Drew Ferguson 2014-06-14 12:21:42 UTC
Should this issue be closed now?

I seem to be experiencing similar behaviour with SDL 2.0.3