Ответ 1
Один из способов - обойти диспетчера окон:
XSetWindowAttributes wa;
wa.override_redirect = True;
XCreateWindow( ..., &wa );
Я пытаюсь создать приложение 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 с тем же файлом!)
Один из способов - обойти диспетчера окон:
XSetWindowAttributes wa;
wa.override_redirect = True;
XCreateWindow( ..., &wa );
У вас нет информации о том, что заставки не отвечают за полноэкранный режим. Демон скринсейвера управляет окном заставки, помещает его в выделенный слой окна заставки и делает его полноэкранным.
Итак, для написания заставки вы поняли. Если бы вы писали полноэкранную игру, вам нужно установить атрибут Override Redirect, чтобы предотвратить управление окном WM и сделать его закрытым для всего экрана.
Я обнаружил, что полноэкранный режим freeglut работает хорошо, даже когда вы используете приложение forend, основанное на шейдере. Здесь внутренний код, который вызывается (ветвь 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 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 */
Попробуйте посмотреть на пример:
На самом деле Slick Screensavers Port to GLX http://rss-glx.sourceforge.net/
Посмотрите на функцию createWindow() в файле driver.c.
Это абсолютно не сложно. Вам просто нужно добавить правый атом в правый список, как описано здесь.
Лучший и простой способ добиться этого - использовать спецификацию 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()
, где вам это нужно, и это было сделано.