X11:从叠加层绘制叠加/删除图形

Nid*_*ger 5 x11 gtk xlib cairo

我需要在X11中直接在屏幕上绘制一个形状(一个小箭头),它用作叠加层.我正在寻找大约一个小时没有没有好结果.任何人都可以为我提供一个很好的切入点吗?我可以使用的技术是cairo,gtk或XLib.

到目前为止我发现的所有东西都取决于构图,它并不总是可用,或者会在我的箭头(矩形,窗口)后面创建一个白色的形状.

编辑:我现在能够使用Composite和Cairo绘制X11叠加层.我是这样做的(注意:这是一个最小的例子.几乎没有错误检查!!!).从终端开始可以退出它!

// COMPILE WITH: g++ -o overlay overlay.cc -lXfixes -lXcomposite -lX11 `pkg-config --cflags --libs cairo`
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>

#include <stdio.h>
#include <unistd.h>

Display *display_;
int old_x_, old_y_;
cairo_surface_t *surf_;
Window overlay_;
int screen_;
int height_;
int width_;
cairo_t *cr_;


void paint_cursor(int new_x, int new_y, bool first = false)
{

    if (!first)
    {
        cairo_set_operator(cr_, CAIRO_OPERATOR_CLEAR);
        cairo_rectangle(cr_, old_x_, old_y_, 20, 20);
        cairo_fill(cr_);
    }
    old_x_ = new_x;
    old_y_ = new_y;

    cairo_set_operator(cr_, CAIRO_OPERATOR_SOURCE);
    cairo_move_to(cr_, new_x, new_y);
    cairo_line_to(cr_, new_x + 0, new_y + 16);
    cairo_line_to(cr_, new_x + 4, new_y + 13);
    cairo_line_to(cr_, new_x + 7, new_y + 18);
    cairo_line_to(cr_, new_x + 9, new_y + 17);
    cairo_line_to(cr_, new_x + 6, new_y + 12);
    cairo_line_to(cr_, new_x + 11, new_y + 12);
    cairo_line_to(cr_, new_x + 0, new_y + 0);

    cairo_set_source_rgba(cr_, 0.0, 0.0, 0.0, 0.5);
    cairo_stroke_preserve(cr_);
    cairo_set_source_rgba(cr_, 0.0, 1.0, 0.0, 0.5);
    cairo_fill(cr_);
}

int main()
{

    display_ = ::XOpenDisplay(0);
    if (!display_)
    {
        return -1;
    }

    screen_ = ::XDefaultScreen(display_);
    Window root = RootWindow(display_, screen_);

    ::XCompositeRedirectSubwindows(display_, root, CompositeRedirectAutomatic);
    ::XSelectInput(display_, root, SubstructureNotifyMask);

    overlay_ = ::XCompositeGetOverlayWindow(display_, root);

    XserverRegion region = ::XFixesCreateRegion(display_, 0, 0);
    ::XFixesSetWindowShapeRegion(display_, overlay_, ShapeBounding, 0, 0, 0);
    ::XFixesSetWindowShapeRegion(display_, overlay_, ShapeInput, 0, 0, region);
    ::XFixesDestroyRegion(display_, region);

    width_ = DisplayWidth(display_, screen_);
    height_ = DisplayHeight(display_, screen_);

    surf_ = ::cairo_xlib_surface_create(display_, overlay_, DefaultVisual(display_, screen_), width_, height_);

    cr_ = ::cairo_create(surf_);
    ::XSelectInput(display_, overlay_, ExposureMask);

    old_x_ = 0;
    old_y_ = 0;
    paint_cursor(0, 0, true);

    XEvent ev;

    Window root_return, child_return;
    int root_x_return, root_y_return;
    int win_x_return, win_y_return;
    unsigned int mask;


    for (;;)
    {
        XQueryPointer(display_, root, &root_return, &child_return, &root_x_return, &root_y_return, &win_x_return, &win_y_return, &mask);
        paint_cursor(root_x_return, root_y_return);
        printf("Paint\n");
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

剩下的问题:如何删除绘制的旧光标?我尝试了XClearArea,我试图用开罗重复绘图,我尝试了Cairo Clear操作符等.没有任何效果.有人能指出我在正确的方向吗?

Nid*_*ger -2

我现在已经使用 X11 的 Shape 扩展和线程中的单独消息循环自己解决了这个问题。它并不理想,但它有效。一旦我再次访问代码,我就会发布代码(生病的自动取款机)。