我为compiz窗口管理器开发了一个插件。我想绘制一个转换后的窗口纹理并向该窗口发送一个事件。当转换的窗口是渲染器时,我抓取指针以控制所有 xevents,抓取指针的 compiz 函数的主要部分如下所示:
status = XGrabPointer (privateScreen.dpy, privateScreen.eventManager.getGrabWindow(), true,
POINTER_GRAB_MASK,
GrabModeAsync, GrabModeAsync,
privateScreen.rootWindow(), cursor,
CurrentTime);
当一个指针被抓住时,我重新计算按钮按下坐标,并使用XSendEvent将事件发送到目标窗口。它适用于 google chrome 窗口或像这样的简单 xwindow 应用程序:link不幸的是,对于执行 OpenGL 渲染的窗口,它不能正常工作——我已经测试了 SDL 和 GLFW。这样的窗口接收点击事件,但参数(xbutton.x_root、xbutton.y_root、xbutton.x、xbutton.y)与我在 XSendEvent 中指定的不同。每次我发送事件时,这些参数都包含相同的值,这些值似乎是调用 xgrabpointer 之前的鼠标位置。当指针未被抓取时,事件(来自 XSendEvent)被正确接收。xsendevent、xgrabpointer 和执行 OpenGL 渲染的窗口之间必须存在某种特定关系。此外,客户端(Windows)实现可能会有所不同,因为我的代码仅适用于该特定窗口,或者我做错了什么?
编辑1
让我们考虑下面的例子:我有一个全屏窗口,然后我可以使用一个插件来绘制变换的窗口纹理(例如缩放变换 (0.5, 0.5, 1.0)),但是 X11 仍然看到一个全屏窗口,所以当我点击转换纹理事件之外的区域转到窗口。当我在插件中抓取指针时,我是所有事件的唯一接收者,然后我可以根据我的窗口变换重新计算坐标并将它们发送到窗口。
Edit2 当我使用 Freeglut 时,所有事件都会在指针被抓取时正确发送到目标窗口。库实现之间必须存在一些差异。