在屏幕顶部使用xlib绘制

9

我希望能在屏幕上所有窗口的顶部绘制一些基本图形。我找到了一些用C语言编写的代码,并尝试将其移植为使用Python的Xlib:

from Xlib.display import Display
from Xlib import X
from Xlib import protocol

display = Display(':0')
root = display.screen().root
gc = root.create_gc()
root.fill_rectangle(gc, 100, 100, 500, 500)

但是屏幕上没有任何显示(但是根窗口已经被分配:在它工作后抓取键盘)。如何正确地做到这一点?


除非你正在编写窗口管理器,否则编写X根是一个非常糟糕的想法。从其他所有东西中窃取输入焦点就是这样一种应用程序“粗鲁”的例子。我会在你使用的任何GUI工具包中寻找“模态对话框”。 - msw
1
@msw:我正在编写的不是窗口管理器,而是另一个低级应用程序,因此有必要在所有窗口的顶部绘制。 - aplavin
1个回答

6
你可以在根窗口上绘制 - 你的代码可能有效,但根窗口可能会被某些桌面窗口(如nautilus、kde桌面等)遮挡。尝试在没有任何程序运行的情况下启动X会话,你将看到更新(你可以使用Xephyr或Xnest进行此操作)
另一种方法是创建透明窗口,使其置顶并在其表面上绘制。你需要手动传播鼠标事件到底层窗口。
要实际在所有窗口的顶部绘制,您需要创建简单的合成管理器,或者如果已经有CM运行,请使用它的覆盖窗口。
来自合成协议规范
协议的0.3版本增加了Composite Overlay Window,它为合成管理器提供了一个表面,在此表面上绘制而不受干扰。该窗口始终在普通窗口之上,并始终位于屏幕保护程序窗口下方。它是一个InputOutput窗口,其宽度和高度为屏幕尺寸。其可视化是根可视化,边框宽度为零。使用复合扩展尝试重定向它会被忽略。此窗口不会出现在QueryTree请求的回复中。它还是一个覆盖重定向窗口。这两个功能使其对窗口管理器和其他X11客户端不可见。访问此窗口的XID的唯一方法是通过CompositeGetOverlayWindow请求。最初,Composite Overlay Window未映射。 CompositeGetOverlayWindow返回Composite Overlay Window的XID。如果该窗口尚未映射,则此请求将映射该窗口。当所有调用此请求的客户端终止其X11连接时,该窗口将取消映射。 合成管理器可以直接渲染到Composite Overlay Window,也可以将其他窗口重新父级为该窗口的子级并对其进行渲染。多个客户端可以渲染到Composite Overlay Window、创建其子窗口、改变其形状并重新定义其输入区域,但这些客户端遵循的具体仲裁规则未由本规范定义;这些策略应由客户端自己定义。

3
很遗憾,xlib的文档写得很糟糕,虽然它似乎已经实现了复合扩展,但没有指南可以告诉我们如何使用它。 - Benubird
1
在覆盖窗口上绘制(即使用cairo)需要每次我们想要绘制东西时请求和释放覆盖。但是,在覆盖层顶部绘制图像后,它将在几毫秒内消失。看来我们需要某种通知(“暴露”事件?)以了解何时可以在复合覆盖窗口上绘制。 - Daniel

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