2012-01-30 52 views
13

我想创建一个Linux应用程序 - 屏幕保护程序,在这种情况下 - 这被证明是显着很难找到制作窗口全屏简单的任务信息。即使现有屏保的代码也没有提及他们如何管理它,我还没有看到任何明显的功能,如XRemoveDecoration()X11/GLX - 全屏模式?

多摸索周围后,我还是设法创建一个窗口,这就是大小为桌面一样,用这样的:

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,使用相同的文件!)

+2

+1显然做了一些研究。 – Flexo 2012-01-30 14:48:51

回答

10

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

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

你可能想要GrabKeyboard来获取关键事件。 – eile 2012-01-30 14:52:01

+3

那......实际上有效。试图追踪你的步骤,我仍然发现实际上没有任何与使用该切换有关的资源,并且X屏幕保护程序似乎没有任何资源......但通过jove,它实际上起作用了! – DigitalMan 2012-01-30 15:14:24

1

我发现托管时freeglut全屏效果很好,甚至基于shader的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 */ 
1

尝试寻找这一个例子:

真的油滑屏保港在给createWindow()在driver.c功能GLX http://rss-glx.sourceforge.net/

看。

+0

不幸的是,这与我尝试过的并没有太大差别(并且缺少结束工作的override_redirect),并且在某种程度上似乎对通常情况的评论甚少。 – DigitalMan 2012-01-30 16:14:27

+0

@DigitalMan阅读INSTALL.xscreensaver。另外结帐这个常见问题http://www.jwz.org/xscreensaver/faq.html#popup-windows。像datenwolf发布,它听起来像你正在创建自己的全屏应用程序,而不是插入屏幕保护程序deamon。 – Fred 2012-01-30 21:12:46

1

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

2

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

因此,编写一个屏幕保护程序,你很清楚。如果你想写一个全屏游戏,你必须设置覆盖重定向属性来防止窗口被WM管理并覆盖整个屏幕。

+0

这似乎是在默认的xscreensaver模块的情况下,是的,但OpenGL插件似乎普遍创建自己的Windows。 – DigitalMan 2012-01-31 04:01:46

+0

@DigitalMan:窗口创建!=窗口管理。实际上,xscreensaver守护进程就像一个窗口管理器,但仅用于屏幕保护程序窗口。 X-Screensaver扩展声明了一个额外的根窗口,该窗口始终位于所有其他窗口的顶部,并且屏幕保护程序守护程序负责将效果程序的窗口移到那里。 – datenwolf 2012-01-31 11:18:11

1

最好和更简单的方法来实现它是使用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()功能,你需要它,它的完成。