如何直接在桌面上绘制?

9

我想知道如何在X11环境下使用Cairo(用C语言)直接在根窗口上绘制,以便创建小部件。我复制了tint2的一些代码,但是它非常庞大,而且我得到的唯一结果并不令人满意。 我希望能够获得完整的工作示例代码,或者至少一些提示或小程序来学习。 谢谢!


1
我不确定直接在桌面上绘图是否是最好的方法。你知道在X11中可以有没有边框/标题栏的窗口,并将它们设置为永不最小化...并且位于堆栈底部。我认为这就是大多数小部件所做的。 - Thomas Dignan
这里有一个类似的帖子,附带一个链接可能会有所帮助:https://dev59.com/tErSa4cB1Zd3GeqPaOrd - CommonSense
但如果那是你想要的,可以看看xosd和xsnow。尽管它们不使用cairo,而是使用xlib。 - Thomas Dignan
我真的很想使用Cairo :/ 有没有使用cairo绘制根窗口的程序? - Dylar
这是我通过复制tint2的部分代码编写的一小段代码:链接。我不确定是否完全理解了整个代码,但我认为我明白了大致意思。然而,它并没有很好地工作。当你将一个窗口移动到小部件的顶部时,它会闪烁。 也许你们能够纠正它,或者给我一些提示。 - Dylar
你的示例会打印“真实透明关闭”吗?如果是的,或者深度不是32,使用这种方法将会产生闪烁。如果是这种情况,请尝试启用合成(也称为桌面效果)。没有好的方法可以在没有工作的合成管理器的情况下获得你想要的效果(如抗锯齿字体等,而且没有闪烁)。 - n. m.
1个回答

8
“底部”窗口是根窗口。问题在于,在某些桌面环境中,我们有窗口位于根窗口之上,因此如果更改根窗口,您将看不到更改:您需要更改位于顶部的窗口。
这个程序可以实现你的要求:在“根窗口”上画图。为了测试它,我建议你:
- 按ctrl+alt+f1 - 以root身份登录 - 停止你的桌面环境("/etc/init.d/gdm stop"、"/etc/init.d/kdm stop"或者在你的发行版中需要的任何命令) - X -noreset -retro & - DISPLAY=:0.0 xterm & - DISPLAY=:0.0 metacity &
然后,回到X(按ctrl+alt+f7或可能是f8)并运行程序。
如果你想在Nautilus的顶部窗口上绘制,请找出它的窗口ID,然后将其用作“w”变量。 "xwininfo" 命令可能会帮助你测试...
#include <assert.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <cairo.h>
#include <cairo-xlib.h>

int width, height;

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() {
    Display *d = XOpenDisplay(NULL);
    assert(d);

    int s = DefaultScreen(d);
    Window w = RootWindow(d, s);
    width = DisplayWidth(d, s);
    height = DisplayHeight(d, s);

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

    XSelectInput(d, w, ExposureMask);

    draw(cr);

    XEvent ev;
    while (1) {
    XNextEvent(d, &ev);
        printf("Event!\n");
        if (ev.type == Expose) {
            draw(cr);
        }
    }

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

这对我有用。我能够在另一个窗口(Sublime Text)上绘制,通过使用xwininfo获取窗口ID,然后将RootWindow()行更改为:Window w = (Window) 0x2400041;,当然要使用您自己的ID值。我注意到的一件事是它并不适用于每个窗口。使用桌面和Chrome的ID都不起作用。你有什么想法为什么吗? - gsgx
有趣的是,当我切换标签时,在Chrome上我看到了红色的正方形,但一瞬间它就消失了... - gsgx
我的猜测是该应用程序只是在你的矩形上方绘制。你不能真正开始在另一个应用程序的窗口上绘制,因为你不知道他们何时会再次在你所做的事情上面绘制。如果你想在桌面背景上做花哨的事情,那么我建议你查看负责在那里绘制的任何应用程序的源代码,然后进行更改。或者干脆杀掉它 :) - pzanoni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接