6

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.

Jarrett
  • 1,767
  • 25
  • 47
  • 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: http://www.rdesktop.org/archive/2001/msg00981.html. It mentions some work-arounds, which I will probably try out at some point. – Jarrett Jun 17 '11 at 22:35
  • Thanks to @VJo and @datenwolf for your help! – Jarrett Jun 17 '11 at 22:37
  • what are you using? gnome or kde? – BЈовић Jun 18 '11 at 07:42
  • one machine is using Ubuntu 10.04 with Gnome, the other is using Linux Mint 10 LXDE – Jarrett Jun 18 '11 at 15:21
  • 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! Cheers – Jarrett Jun 19 '11 at 03:25
  • @Jarrett, how did you manage to get a fullscreen X OpenGL window? I have been trying to do this for a while now, and failing miserably. Could you possibly provide a code snipped through GitHub's Gist or something? – fouric Dec 25 '13 at 05:24
  • @InkBlend, sorry, I actually don't have that code kicking around anymore. I actually switched to just using SFML - you might try looking at how they do it. Good luck. – Jarrett Dec 25 '13 at 16:47

2 Answers2

6

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);
}
datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Hey @datenwolf, thanks for the info. Do you know how to code this? :) I'm having a great deal of trouble trying to get this to work. @VJo's solution below, unfortunately, doesn't work, and I'm having great difficulty finding examples on the net. I'd appreciate any help you can provide. – Jarrett Jun 17 '11 at 18:55
  • hey @datenwolf, I was afraid you were going to say `XIconifyWindow`, as I've tried that without success. I call `XIconifyWindow(display_, window_, screen_);` where I handle the `FocusOut` event (which I have confirmed IS being called when I alt-tab in fullscreen). I've tried this on two computers (one running Ubuntu 10.04 and one running Linux Mint 10) to no avail.. – Jarrett Jun 17 '11 at 20:24
  • On my mint LXDE machine it's OpenBox, and on my Ubuntu 10.04 machine it's the default (Metacity I believe) (I've tested the code on both of them) – Jarrett Jun 18 '11 at 15:20
1

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.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • Hey @VJo, thanks for the reply. I entered your code where I handle the `FocusOut` event, but unfortunately, nothing happens. I also tried the variant where you use `xev.xclient.data.l[0] = _NET_WM_STATE_ADD; xev.xclient.data.l[1] = WM_STATE_MAXIMIZED_VERT; xev.xclient.data.l[2] = WM_STATE_MAXIMIZED_HORZ;` to no effect. Is there something I need to do to enable these events to be processed? – Jarrett Jun 17 '11 at 18:59
  • Window iconification is done a little bit different, look at the source code fragment I extracted http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/Iconify.c – datenwolf Jun 18 '11 at 10:46