16

我正在尝试创建一个 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 编译,使用相同的文件!)

4

6 回答 6

13

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

XSetWindowAttributes wa;                                                     
wa.override_redirect = True;                                           
XCreateWindow( ..., &wa );
于 2012-01-30T14:51:28.597 回答
4

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

因此,对于编写屏幕保护程序,您是清楚的。如果您要编写全屏游戏,则必须设置 Override Redirect 属性以防止窗口被 WM 管理并使其覆盖整个屏幕。

于 2012-01-30T17:58:10.727 回答
2

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

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()在需要的地方使用功能即可。

于 2015-02-08T17:06:59.150 回答
1

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

#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 */
于 2012-01-30T15:01:32.197 回答
1

这绝对不难。您只需按照此处所述将正确的原子添加到正确的列表中。

于 2012-01-30T15:50:15.263 回答
1

试试看这个例子:

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

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

于 2012-01-30T15:13:11.767 回答