最小化全屏Xlib OpenGL窗口

6

我目前正在尝试使我的全屏Xlib OpenGL窗口支持alt-tab切换,但是遇到了一些困难。我尝试了XUnmapWindow(..),它有点起作用,但分辨率不会重置(除非我应该手动重置?)而我的Xlib窗口没有出现为最小化的窗口(即使应用程序似乎仍在后台运行,我也无法通过alt-tab返回窗口)。

接下来我尝试将窗口从全屏模式更改为窗口模式(即在窗口模式下重新创建窗口),但显然,我不想这样做。

我正在侦听FocusOutFocusIn事件,当我使用alt-tab时,FocusOut似乎被调用了,但我不确定如何使我的应用程序正确地最小化。如果在调用FocusOut事件时不在我的代码中执行任何操作,则我的应用程序不会执行任何操作(即我无法最小化窗口)。

任何帮助都将不胜感激!

编辑: 不幸的是,我无法让X Windows正确地最小化全屏窗口。因此,为了解决这个问题,我决定destroy()全屏窗口,然后在窗口模式下create()一个新窗口。看起来效果不错。


这些信息有点过时,但似乎当X窗口处于全屏模式时,XIconifyWindow无法正常工作。这是链接:http://www.rdesktop.org/archive/2001/msg00981.html。它提到了一些解决方法,我可能会在某个时候尝试一下。 - Jarrett
感谢 @VJo 和 @datenwolf 的帮助! - Jarrett
一台机器正在使用Ubuntu 10.04和Gnome,另一台正在使用Linux Mint 10 LXDE。 - Jarrett
@Jarrett,你是如何实现全屏X OpenGL窗口的?我已经尝试了一段时间,但一直失败。你能否通过GitHub的Gist或其他方式提供一些代码片段? - fouric
@InkBlend,抱歉,我实际上不再拥有那段代码了。我实际上转而只使用SFML - 你可以尝试看看他们是如何做的。祝你好运。 - Jarrett
显示剩余2条评论
2个回答

6
XUnmapWindow()完全从显示器中移除窗口。最小化窗口是通过EMWH ICCCM状态完成的,以便窗口管理器知道窗口仍以某种形式存在。正如您已经猜到的那样,您需要负责重置屏幕分辨率。顺便说一句,在Windows中也是这样做的。
编辑:
在Xlib中,通过XIconifyWindow来最小化一个窗口,它将负责设置正确的ICCCM属性并取消映射窗口。两者都必须完成才能与WM进行正确交互。然而,X11只定义了方法,而没有策略,因此当取消映射全屏窗口时,您还需要负责重置屏幕分辨率,就像我上面写的那样。
顺便说一下:我建议您根本不要改变分辨率,而是如果可用的话,渲染到目标大小的FrameBuffer对象,并将最终结果映射到完整的本机屏幕大小。如果您将此与本机分辨率文本/ HUD叠加使用(我假设这是游戏或类似物),则可以获得更高的感知质量并节省分辨率切换。您甚至可以将此与捕获桌面截图并逐渐淡入到您的内容相结合。
编辑2供参考: XIconifyWindow只是一个辅助/便利函数,它的源代码是
/*
 * 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,感谢你提供的信息。你知道如何编写这个代码吗? :) 我在尝试让它工作时遇到了很大的麻烦。 @VJo下面的解决方案很不幸并不起作用,而我在网上找到示例也非常困难。如果你能提供任何帮助,我将不胜感激。 - Jarrett
嘿@datenwolf,我担心你会说“XIconifyWindow”,因为我尝试过但没有成功。我在处理“FocusOut”事件时调用XIconifyWindow(display_,window_,screen_);(我已确认在全屏模式下按alt-tab时确实被调用)。我已在两台计算机上尝试过(一台运行Ubuntu 10.04,另一台运行Linux Mint 10),但都无济于事。 - Jarrett
在我的 Mint LXDE 机器上,它是 OpenBox,在我的 Ubuntu 10.04 机器上,它是默认的(我相信是 Metacity)(我已在两台机器上测试了代码)。 - Jarrett

1
你可以尝试像这样做:
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);

编辑

如果您可以访问gnome API,您可以使用 wnck_window_minimize(),或查看该函数的源代码。


嘿@VJo,谢谢回复。我把你的代码输入到处理“FocusOut”事件的地方,但不幸的是,什么也没有发生。我还尝试了使用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;,但也没有效果。是否需要做些什么来启用这些事件的处理? - Jarrett
窗口最小化的实现方式略有不同,请查看我提取的源代码片段:http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/Iconify.c - datenwolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接