X11 / GLX - полноэкранный режим? - PullRequest
14 голосов
/ 30 января 2012

Я пытаюсь создать приложение для 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 ]

13 голосов
/ 30 января 2012

Один из способов - обойти оконный менеджер:

XSetWindowAttributes wa;                                                     
wa.override_redirect = True;                                           
XCreateWindow( ..., &wa );
4 голосов
/ 30 января 2012

Часть информации, которой вам не хватает, заключается в том, что заставки не несут ответственности за переход в полноэкранный режим. Демон заставки управляет окном заставки, помещает его в выделенный слой окна заставки и делает его полноэкранным.

Так что для написания скринсейвера вы в чистоте. Если вы собирались написать полноэкранную игру, вам нужно установить атрибут Override Redirect, чтобы предотвратить управление окном с помощью WM и сделать так, чтобы оно охватывало весь экран.

2 голосов
/ 08 февраля 2015

Лучший и более простой способ добиться этого - использовать спецификацию 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() там, где вам это нужно, и все готово.

1 голос
/ 30 января 2012

Это абсолютно не сложно. Вам просто нужно добавить правильный атом в правильный список, как описано здесь .

1 голос
/ 30 января 2012

Попробуйте взглянуть на это в качестве примера:

Действительно Slick Screensavers Port для GLX http://rss -glx.sourceforge.net /

Посмотрите на createWindow () функция в driver.c.

1 голос
/ 30 января 2012

Я обнаружил, что полноэкранный режим 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 */
...