我有一个透明的、类似水印的应用程序,它是用 C 语言用 XLib 编写的。目前,如果您单击应用程序上的任何位置,则不会发生任何事情,但我希望它将鼠标输入传递给它下面的任何内容。例如,如果您单击 X 关闭应用程序下方的窗口,它应该关闭应用程序,而不是什么都不做。
5 回答
嗯,这就是我发现的。
请注意,此功能是在过去十年中添加的,因此如果您有旧版本的 X11,这可能会或可能不会起作用。
首先将它们包含在您的项目中,因为它们是需要的:
#include <X11/extensions/shape.h>
#include <X11/extensions/Xfixes.h>
并且要更改输入几何图形(即您可以与窗口交互的地方),在这种情况下,我们将其设置为 0 x 0 像素,这意味着没有。这是一个例子:
XRectangle rect;
XserverRegion region = XFixesCreateRegion(display, &rect, 1);
XFixesSetWindowShapeRegion(display, window, ShapeInput, 0, 0, region);
XFixesDestroyRegion(display, region);
并将其添加到项目链接器-lXfixes
如果您不希望您的“水印”窗口接收任何输入,而是让输入转到其下方的窗口,那么我将研究gtk_widget_input_shape_combine_region
. 我以前使用它的前身gtk_widget_input_shape_combine_mask
来导致弹出窗口的所有部分不接收任何事件。
我在这里超出了我的舒适区,但看起来XShapeCombineRectangles是相关的调用(在这种情况下调用了链接do_shape_combine_region
)shape = ShapeInput
。
我认为XQueryTree
可能会有所帮助。在根窗口上执行它并获取子窗口列表,找到它们的位置并将鼠标/键盘传递XEvent
给适当的窗口。
注意:您必须注意活动/非活动窗口、窗口的活动/非活动区域、另一个窗口的子窗口、其他窗口的大小和 x/y 位置。为此,代码将变得混乱。
您需要实现小窗口管理器,它将使用 XSelectInput 监听默认根窗口上的所有事件。
然后对 fd = connectionNember(display) 进行轮询。
每当您收到事件。检查这是否是鼠标事件,它会给你 x,y。您可以通过遍历窗口堆栈找到正确的窗口。
然后使用 XGrabPinter 向底层窗口报告事件。
一些附加说明:
- 如果您想在 xcb 中执行此操作,请确保首先查询 xfixes 版本 5.0,否则您将收到一个模糊的
BadRequest
错误 - 这是另一种方法(从picom 源窃取,而后者又从 compiz 源窃取它☺)
xcb_shape_mask(conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, window, 0, 0, 0);
xcb_shape_rectangles(conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, window, 0, 0, 0, NULL);
至于它是如何工作的,我不知道。XShape 是出了名的无证。然而结果似乎是一样的。