I am trying to create a Linux application - a screensaver, in this case - and it is proving remarkably difficult to find information on the simple task of making a wind
Best and easier way to achieve it is to use the ICCCM Specification atom
which will work for most recent Window Managers. Just use the following code:
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);
Your window might be transparent, if so, just use XSetBackground()
function where you need it and it's done.
The piece of information you lack is, that the screensavers are not responsible for going fullscreen. The screensaver daemon will manage the screensaver window, put it into the dedicated screensaver window layer and make it full screen.
So for writing a screensaver you're in the clear. If you were about writing a fullscreen game, you's have to set the Override Redirect attribute to prevent the window from getting managed by the WM and make it cover the whole screen.
Try looking at this for an example:
Really Slick Screensavers Port to GLX http://rss-glx.sourceforge.net/
Look at the createWindow() function in driver.c.
I found freeglut fullscreen works well, even when hosting shader based opengl application inside. Here the internal code that get called (X11 branch...). 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 */
It's absolutely not difficult. You just have to add the right atom to the right list as described here.
One way is to bypass the window manager:
XSetWindowAttributes wa;
wa.override_redirect = True;
XCreateWindow( ..., &wa );