2012-01-30 68 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()功能,你需要它,它的完成。