X11 / GLX - 全屏模式?

时间:2012-01-30 14:46:30

标签: c++ linux opengl x11 glx

我正在尝试创建一个Linux应用程序 - 在这种情况下是一个屏幕保护程序 - 它证明非常很难找到关于使窗口全屏的简单任务的信息。即使现有屏保的代码也没有提到他们如何管理它,我还没有看到任何明显的功能,如XRemoveDecoration()

经过多次摸索后,我确实设法创建了一个与桌面大小相同的窗口,其中包含:

Window win = DefaultRootWindow(disp);
XWindowAttributes getWinAttr;
XGetWindowAttributes(disp, win, &getWinAttr);
win = XCreateWindow(disp, win, 0, 0, getWinAttr.width, getWinAttr.height, 0, vInfo->depth, InputOutput, vInfo->visual, CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect, &winAttr );

但这并没有做任何事情来摆脱标题栏和边框。我知道有一种方法,显然 - 但是我还没有找到任何指向那个方向的东西,它不依赖于其他一些大型库被抛到顶层(现有的屏保不会使用)。

编辑:请不要删除帖子中的信息。有一个很好的理由我明确指出现有的屏保没有使用可选库,这是因为我在过去的大部分时间里一直在分析源代码。

我选择了最直接回答问题的答案,并且适用于一般的应用程序。

如果您发现此问题正在研究xscreensavers ......同样仍然适用。是的,xscreensaver有自己的API - 这很复杂,实际上涉及编写更多行代码(是的,认真的)。如果您想在屏幕保护程序中使用OpenGL,则需要通过另一个 API(xlockmore,一个竞争系统)和一个将其转换为xscreensaver的兼容层。

但是,xscreensaver能够运行任何程序,该程序可以使用虚拟根窗口(查看vroot.h)作为屏幕保护程序。所以我的建议就是这样做 - 你将拥有更多控制权,没有限制性API,以及更高的可移植性。 (我看过的一个例子甚至可以编译为Linux或Windows,使用相同的文件!)

6 个答案:

答案 0 :(得分:13)

一种方法是绕过窗口管理器:

XSetWindowAttributes wa;                                                     
wa.override_redirect = True;                                           
XCreateWindow( ..., &wa );

答案 1 :(得分:4)

您缺少的信息是,屏幕保护程序不负责全屏显示。屏幕保护程序守护程序将管理屏幕保护程序窗口,将其放入专用的屏幕保护程序窗口层并使其全屏显示。

因此,对于编写屏幕保护程序,您可以清楚地看到它。如果您要编写全屏游戏,则必须设置“覆盖重定向”属性以防止窗口被WM管理并使其覆盖整个屏幕。

答案 2 :(得分:2)

实现它的最佳和最简单的方法是使用适用于最新窗口管理器的ICCCM规范atom。只需使用以下代码:

Atom wm_state   = XInternAtom (display, "_NET_WM_STATE", true );
Atom wm_fullscreen = XInternAtom (display, "_NET_WM_STATE_FULLSCREEN", true );

XChangeProperty(display, window, wm_state, XA_ATOM, 32,
                PropModeReplace, (unsigned char *)&wm_fullscreen, 1);

您的窗口可能是透明的,如果是这样,只需在您需要的地方使用XSetBackground()功能即可。

答案 3 :(得分:1)

我发现freeglut全屏效果很好,即使在内部托管基于着色器的opengl应用程序时也是如此。这里是被调用的内部代码(X11分支......)。 HTH

#define _NET_WM_STATE_TOGGLE    2
static int fghResizeFullscrToggle(void)
{
    XWindowAttributes attributes;

    if(glutGet(GLUT_FULL_SCREEN)) {
        /* restore original window size */
        SFG_Window *win = fgStructure.CurrentWindow;
        fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
        fgStructure.CurrentWindow->State.Width  = win->State.OldWidth;
        fgStructure.CurrentWindow->State.Height = win->State.OldHeight;

    } else {
        /* resize the window to cover the entire screen */
        XGetWindowAttributes(fgDisplay.Display,
                fgStructure.CurrentWindow->Window.Handle,
                &attributes);

        /*
         * The "x" and "y" members of "attributes" are the window's coordinates
         * relative to its parent, i.e. to the decoration window.
         */
        XMoveResizeWindow(fgDisplay.Display,
                fgStructure.CurrentWindow->Window.Handle,
                -attributes.x,
                -attributes.y,
                fgDisplay.ScreenWidth,
                fgDisplay.ScreenHeight);
    }
    return 0;
}

static int fghEwmhFullscrToggle(void)
{
    XEvent xev;
    long evmask = SubstructureRedirectMask | SubstructureNotifyMask;

    if(!fgDisplay.State || !fgDisplay.StateFullScreen) {
        return -1;
    }

    xev.type = ClientMessage;
    xev.xclient.window = fgStructure.CurrentWindow->Window.Handle;
    xev.xclient.message_type = fgDisplay.State;
    xev.xclient.format = 32;
    xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE;
    xev.xclient.data.l[1] = fgDisplay.StateFullScreen;
    xev.xclient.data.l[2] = 0;  /* no second property to toggle */
    xev.xclient.data.l[3] = 1;  /* source indication: application */
    xev.xclient.data.l[4] = 0;  /* unused */

    if(!XSendEvent(fgDisplay.Display, fgDisplay.RootWindow, 0, evmask, &xev)) {
        return -1;
    }
    return 0;
}

static int fghToggleFullscreen(void)
{
    /* first try the EWMH (_NET_WM_STATE) method ... */
    if(fghEwmhFullscrToggle() != -1) {
        return 0;
    }

    /* fall back to resizing the window */
    if(fghResizeFullscrToggle() != -1) {
        return 0;
    }
    return -1;
}


#endif  /* TARGET_HOST_POSIX_X11 */

答案 4 :(得分:1)

试着看一下这个例子:

真正光滑的屏幕保护程序移植到GLX http://rss-glx.sourceforge.net/

查看driver.c中的createWindow()函数。

答案 5 :(得分:1)

绝对不难。您只需将正确的原子添加到右侧列表中,如here所述。