如何制作不捕获任何事件的叠加层

How to make an overlay which capture no events

我想在所有其他 windows 之上绘制某种 window。例如,显示一些调试信息(如 conky)或诸如计时器之类的东西。

主要是我希望能够在使用它的同时继续使用另一个 windows(事件透明地进行)。

我已经尝试使用 pygtkpyqt 和其他方法来实现它,但无法找到一种方法使其成为没有事件捕获的真实叠加层。

是否有一些低级 x11 解决方案?

您可能需要 Composite extension + GetOverlayWindow 请求:

Version 0.3 of the protocol adds the Composite Overlay Window, which provides compositing managers with a surface on which to draw without interference. This window is always above normal windows and is always below the screen saver window. It is an InputOutput window whose width and height are the screen dimensions. Its visual is the root visual and its border width is zero. Attempts to redirect it using the composite extension are ignored. This window does not appear in the reply of the QueryTree request. It is also an override redirect window. These last two features make it invisible to window managers and other X11 clients. The only way to access the XID of this window is via the CompositeGetOverlayWindow request. Initially, the Composite Overlay Window is unmapped.

CompositeGetOverlayWindow returns the XID of the Composite Overlay Window. If the window has not yet been mapped, it is mapped by this request. When all clients who have called this request have terminated their X11 connections the window is unmapped.

Composite managers may render directly to the Composite Overlay Window, or they may reparent other windows to be children of this window and render to these. Multiple clients may render to the Composite Overlay Window, create child windows of it, reshape it, and redefine its input region, but the specific arbitration rules followed by these clients is not defined by this specification; these policies should be defined by the clients themselves.

C api : XCompositeGetOverlayWindow

我认为 Composite-extension-approach 在合成管理器为 运行 时不起作用(因此 Composite 的覆盖层 window 已被使用)。

既然你明确提到了"no event capture":

SHAPE extension 允许为 window 设置一些不同的形状。此扩展的 1.1 版添加了 "input" 形状。只需将其设置为空白区域就可以满足您的需求。

可以在 Conky 的源代码中找到我认为您所要求的一些具体示例:http://sources.debian.net/src/conky/1.10.3-1/src/x11.cc/?hl=769#L764-L781

编辑:既然你说你没有在 Gtk 中找到任何东西(好吧,PyGtk),这里是你在 Gtk 中需要的函数:https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-window-input-shape-combine-region

PyGTK 解决方案:

我认为复合和形状 X 扩展非常普遍,这里假设它们在您的系统上处于活动状态。这是 PyGtk 代码:

# avoid title bar and standard window minimize, maximize, close buttons
win.set_decorated(False)

# make the window stick above all others (super button will still override it in the z-order, which is fine)
win.set_keep_above(True)

# make events pass through
region = cairo.Region(cairo.RectangleInt(0, 0, 0, 0))
my_window.input_shape_combine_region(region)

win.show_all()

# set the entire window to be semi-transparent, if we like
win.set_opacity(0.2)

基本上这是告诉 Gtk 除了像素 (0,0) 之外,整个 window my_window 在事件传播方面不应被视为其自身的一部分。那反过来,按照我目前的理解意思就是当指针移动和点击时,事件转到指针位置下面的底层window,就好像my_window不存在一样。

警告:

这确实允许您的叠加层 window 成为焦点 window(由于用户请求 window 切换或仅仅因为它在您的应用程序启动时弹出并获得焦点) .这意味着,例如,键盘事件仍然会不受欢迎地发生,直到用户单击它以使其失去焦点以支持光标下的任何 window 。我可能会使用描述的方法 来解决这个问题。

如果有一个不同的和适当的方法来制作屏幕的一部分 "display stuff but not receive events",而不是像上面那样在上面构建一个奇怪的 window,我很高兴了解它。

我假设一个人的特定桌面环境(linux 上的 gnome、unity 等)在某些情况下可能会干扰此解决方案,具体取决于版本和配置。