2014-02-14 36 views
5

畫我想在屏幕上(類似於此question)對特定的像素畫簡單的原語。爲了做到這一點,我使用窗口管理器的覆蓋窗口繪製所有窗口的頂部。我可以看到我繪製的圖形和鼠標事件通過,但我沒有看到例如覆蓋窗口下面的窗口移動(除非我殺了我的應用程序)。我是Xlib編程的新手,可能會問一個簡單的問題。X11 - 上重疊視窗

#include <assert.h> 
#include <stdio.h> 
#include <X11/Xlib.h> 

#include <X11/extensions/Xcomposite.h> 
#include <X11/extensions/Xfixes.h> 
#include <X11/extensions/shape.h> 

#include <cairo.h> 
#include <cairo-xlib.h> 

Display *d; 
Window overlay; 
Window root; 
int width, height; 

void 
allow_input_passthrough (Window w) 
{ 
    XserverRegion region = XFixesCreateRegion (d, NULL, 0); 

    XFixesSetWindowShapeRegion (d, w, ShapeBounding, 0, 0, 0); 
    XFixesSetWindowShapeRegion (d, w, ShapeInput, 0, 0, region); 

    XFixesDestroyRegion (d, region); 
} 

void 
prep_overlay (void) 
{ 
    overlay = XCompositeGetOverlayWindow (d, root); 
    allow_input_passthrough (overlay); 
} 

void draw(cairo_t *cr) { 
    int quarter_w = width/4; 
    int quarter_h = height/4; 
    cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); 
    cairo_rectangle(cr, quarter_w, quarter_h, quarter_w * 2, quarter_h * 2); 
    cairo_fill(cr); 
} 

int main() { 
    d = XOpenDisplay(NULL); 

    int s = DefaultScreen(d); 
    root = RootWindow(d, s); 

    XCompositeRedirectSubwindows (d, root, CompositeRedirectAutomatic); 
    XSelectInput (d, root, SubstructureNotifyMask); 

    width = DisplayWidth(d, s); 
    height = DisplayHeight(d, s); 

    prep_overlay(); 

    cairo_surface_t *surf = cairo_xlib_surface_create(d, overlay, 
            DefaultVisual(d, s), 
            width, height); 
    cairo_t *cr = cairo_create(surf); 

    XSelectInput(d, overlay, ExposureMask); 

    draw(cr); 

    XEvent ev; 
    while (1) { 
    XNextEvent(d, &ev); 
     if (ev.type == Expose) { 
      draw(cr); 
     } 
    } 

    cairo_destroy(cr); 
    cairo_surface_destroy(surf); 
    XCloseDisplay(d); 
    return 0; 
} 

如何在疊加窗口上繪製像素並仍然可以看到下面的窗口?

+0

考慮增加對你的編程語言的標籤。許多C/C++程序員可能會幫助你,但如果他們按照他們的「主題」進行過濾,他們就不會看到你的問題。祝你好運。 – shellter

+0

你可以發佈整個程序嗎? –

+0

我編輯了原文,幷包含一個完整的程序。與編譯:'GCC x11drawoverlay.c -o x11drawoverlay -lX11 -lXfixes -lXcomposite -lcairo -I/usr/include目錄/ cairo' – user1325516

回答

3

sleep(50)!這太多了,這是50秒。我用了5ms的延遲,效果很好。

您的問題似乎與運行時環境。你應該有一個複合顯示管理器已經運行。 (並非所有的顯示管理器按預期工作,更好地嘗試不同的)

我確認下方更新的屏幕沒有任何問題,我可以與它進行交互。

這是上運行:

Ubuntu 15.10 
Kernel 4.2.0-18-generic 
X.Org X Server 1.17.2 
Compiz 0.9.12.2 

這裏的全部代碼,只需拖延修改:

#include <assert.h> 
#include <stdio.h> 
#include <time.h> 
#include <X11/Xlib.h> 

#include <X11/extensions/Xcomposite.h> 
#include <X11/extensions/Xfixes.h> 
#include <X11/extensions/shape.h> 

#include <cairo.h> 
#include <cairo-xlib.h> 

Display *d; 
Window overlay; 
Window root; 
int width, height; 

void 
allow_input_passthrough (Window w) 
{ 
    XserverRegion region = XFixesCreateRegion (d, NULL, 0); 

    XFixesSetWindowShapeRegion (d, w, ShapeBounding, 0, 0, 0); 
    XFixesSetWindowShapeRegion (d, w, ShapeInput, 0, 0, region); 

    XFixesDestroyRegion (d, region); 
} 

void 
prep_overlay (void) 
{ 
    overlay = XCompositeGetOverlayWindow (d, root); 
    allow_input_passthrough (overlay); 
} 

void draw(cairo_t *cr) { 
    int quarter_w = width/4; 
    int quarter_h = height/4; 
    cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); 
    cairo_rectangle(cr, quarter_w, quarter_h, quarter_w * 2, quarter_h * 2); 
    cairo_fill(cr); 
} 

int main() { 
    struct timespec ts = {0, 5000000}; 

    d = XOpenDisplay(NULL); 

    int s = DefaultScreen(d); 
    root = RootWindow(d, s); 

    XCompositeRedirectSubwindows (d, root, CompositeRedirectAutomatic); 
    XSelectInput (d, root, SubstructureNotifyMask); 

    width = DisplayWidth(d, s); 
    height = DisplayHeight(d, s); 

    prep_overlay(); 

    cairo_surface_t *surf = cairo_xlib_surface_create(d, overlay, 
            DefaultVisual(d, s), 
            width, height); 
    cairo_t *cr = cairo_create(surf); 

    XSelectInput(d, overlay, ExposureMask); 

    draw(cr); 

    XEvent ev; 
    while(1) { 
     overlay = XCompositeGetOverlayWindow (d, root); 
     draw(cr); 
     XCompositeReleaseOverlayWindow (d, root); 
     nanosleep(&ts, NULL); 
    } 

    cairo_destroy(cr); 
    cairo_surface_destroy(surf); 
    XCloseDisplay(d); 
    return 0; 
} 

X11 overlay on Ubuntu 15.10

X11 overlay on Ubuntu 15.10, desktop overview

+0

這在某種程度上取決於桌面環境,它在Ubuntu(Unity)中工作,但在肉桂中不起作用。我有一個問題:你知道是否可以繪製沒有閃爍?如果按照您在答案中描述的方式實施它,它肯定會奏效,但用戶將能夠看到圖像閃爍。 – ScienceSE