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

时间:2016-09-13 00:43:24

标签: linux gtk x11 cairo

我想在所有其他窗口之上绘制某种窗口。例如,显示一些调试信息(如conky)或类似计时器的事情。

主要的是我希望能够在使用时继续使用其他窗口(事件透明地进行)。

我已尝试使用pygtkpyqt和其他人进行此操作,但无法找到一种方法使其成为真正的叠加层而不会捕获事件。

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

3 个答案:

答案 0 :(得分:2)

我认为复合扩展方法在合成管理器运行时不起作用(因此已经使用了Composite的叠加窗口)。

由于您明确提及"没有事件捕获":

SHAPE extension允许为窗口设置一些不同的形状。此扩展的1.1版添加了"输入"形状。只需将其设置为空白区域,就可以完全按照自己的意愿进行操作。

我认为你要求的一些具体例子可以在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

答案 1 :(得分:1)

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

  

协议版本0.3添加了复合叠加窗口,其中   为合成管理者提供一个无需绘制的表面   干扰。此窗口始终高于正常窗口   屏幕保护程序窗口下方。它是一个InputOutput窗口,其宽度   和高度是屏幕尺寸。它的视觉是根视觉   它的边界宽度为零。试图使用。重定向它   复合扩展被忽略。此窗口不会出现在   QueryTree请求的回复。它也是一个覆盖重定向   窗口。最后两个功能使窗口管理器不可见   和其他X11客户端。访问此窗口的XID的唯一方法   是通过CompositeGetOverlayWindow请求。最初,复合材料   覆盖窗口未映射。

     

CompositeGetOverlayWindow返回Composite Overlay的XID   窗口。如果窗口尚未映射,则由此映射   请求。调用此请求的所有客户端都已终止   他们的X11连接窗口未映射。

     

复合管理器可以直接渲染到复合叠加层   窗户,或者他们可能重新将其他窗户重新成为这个孩子   窗口并渲染到这些。多个客户端可能会呈现给   复合叠加窗口,创建它的子窗口,重塑它,和   重新定义其输入区域,但遵循特定的仲裁规则   本规范未定义这些客户端;这些政策   应该由客户自己定义。

C api:XCompositeGetOverlayWindow

答案 2 :(得分:1)

PyGTK解决方案:

我认为Composite和shape 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,从事件传播的角度来看,整个窗口my_window除了像素(0,0)之外,不应被视为其一部分。按照我目前的理解,这反过来意味着,当指针移动并单击时,事件将进入指针位置下方的基础窗口,就像my_window不在那里一样。

注意事项:

这确实使您的叠加窗口成为焦点窗口(由于用户请求的窗口切换,或者仅因为它在应用程序启动时弹出并获得焦点)。这意味着,例如,键盘事件仍然会不合要求地进行下去,直到用户单击它以使其失去焦点而转向光标下方的任何窗口为止。我可能会使用here中描述的方法来解决此问题。

如果有一种使屏幕的一部分“显示内容但不接收事件”的正确方法,却又没有在上方构建奇异球窗口的话,我很乐意学习。

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