6
votes

I'm currently trying to enable alt-tabbing out of my fullscreen Xlib OpenGL window, but am having some difficulties. I've tried XUnmapWindow(..), which kindof works, but the resolution does not reset (unless I should be doing that manually?) and my Xlib window does not appear as a minimized window (i.e. I can't alt-tab back into the window, even though the app still seems to be running in the background).

The next thing I tried was changing my window from fullscreen to windowed mode (i.e. re-creating the window over again in windowed mode), but obviously, I'd rather not have to do that.

I'm listening to FocusOut and FocusIn events, and the FocusOut seems to be called when I alt-tab, but I'm just not sure how to get my app to minimize properly. If I don't do anything in my code when a FocusOut event is called, my app doesn't do anything (i.e. I can't minimize the window).

Any help would be appreciated!

Edit: Unfortunately, I've been unable to get X Windows to properly minimize a fullscreen window. So, to work around this problem I've decided to destroy() the fullscreen window and then create() a new window in windowed mode. Seems to work well.

2
This information is a bit old, but it seems as though XIconifyWindow doesn't work when the X Window is in fullscreen mode. Here's the link: rdesktop.org/archive/2001/msg00981.html. It mentions some work-arounds, which I will probably try out at some point.Jarrett
Thanks to @VJo and @datenwolf for your help!Jarrett
what are you using? gnome or kde?BЈовић
one machine is using Ubuntu 10.04 with Gnome, the other is using Linux Mint 10 LXDEJarrett
Alright, I appreciate all the help fella's, but I think I'm going to just destroy() the window and then create(..) it again in windowed mode - I don't seem to be able to coax X Windows into minimizing a fullscreen window. Thanks for the help! CheersJarrett

2 Answers

6
votes

XUnmapWindow() completely removes the window from the display. Minimizing a Window happens through EMWH ICCCM state, so that the window manager knows, that the window is still there in some form. And like you already assumed you're responsible for resetting the screen resolution. This is BTW the very same in Windows.

EDIT:

Minimizing a Window in Xlib is done with XIconifyWindow, which will take care to set the right ICCCM properties, and unmaps the window. Both must be done to interact properly with the WM. However X11 only defines the methods, not the policy, so when unmapping a fullscreen window you're also responsible to reset the screen resolution, like I already wrote above.

On a side note: I suggest you don't change the resolution at all, but instead, if such is available, render to a Framebuffer Object of the target size, and map the final result to the full, native screen size. If you combine this with native resolution text/HUD overlays (I assume this is for a game or similar), you get much higher percieved quality and save the resolution switching. You may even combine this with taking a screenshot of the desktop and gradually fading to your content.

EDIT 2 for reference : XIconifyWindow is just a helper/convenience function, it's source code is

/*
 * This function instructs the window manager to change this window from
 * NormalState to IconicState.
 */
Status XIconifyWindow(Display *dpy, Window w, int screen)
{
    XClientMessageEvent ev;
    Atom prop;

    prop = XInternAtom(dpy, "WM_CHANGE_STATE", False);
    if(prop == None)
    return False;

    ev.type = ClientMessage;
    ev.window = w;
    ev.message_type = prop;
    ev.format = 32;
    ev.data.l[0] = IconicState;
    return XSendEvent(dpy, RootWindow(dpy, screen), False,
            SubstructureRedirectMask|SubstructureNotifyMask,
            (XEvent *)&ev);
}
1
votes

You can try to do it like this :

XEvent xev;
Atom wm_state     =  XInternAtom(dpy, "_NET_WM_STATE", False);
Atom wm_hide_win  =  XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", False);

memset(&xev, 0, sizeof(xev));
xev.type = ClientMessage;
xev.xclient.window = win;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
xev.xclient.data.l[1] = wm_hide_win;

XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureNotifyMask, &xev);

EDIT

If you have access to gnome API, you can use wnck_window_minimize(), or take a look into the source for that function.