我为compiz窗口管理器开发了一个插件。我想绘制转换后的窗口纹理并将事件发送到该窗口。当转换后的窗口是渲染器时,我抓取指针来控制所有 xevents,抓取指针的 compiz 函数的主要部分如下所示:
status = XGrabPointer (privateScreen.dpy, privateScreen.eventManager.getGrabWindow(), true,
POINTER_GRAB_MASK,
GrabModeAsync, GrabModeAsync,
privateScreen.rootWindow(), cursor,
CurrentTime);
当指针被抓取时,我重新计算按钮按下坐标,并使用XSendEvent将事件发送到目标窗口。它适用于谷歌浏览器窗口或像这样的简单 xwindow 应用程序:链接 不幸的是,对于执行 OpenGL 渲染的窗口,它无法正常工作 - 我已经测试了 SDL 和 GLFW。这样的窗口接收点击事件,但参数(xbutton.x_root,xbutton.y_root,xbutton.x,xbutton.y(与我在XSendEvent中指定的参数不同。每次当我发送事件时,这些参数都包含相同的值,这些值似乎是调用 xgrabpointer 之前的鼠标位置。当指针未被抓取时,将正确接收事件(来自 XSendEvent(。xsendevent、xgrabpointer 和执行 OpenGL 渲染的窗口之间必须存在某种特定的关系。此外,客户端(窗口(实现可能会有所不同,因为我的代码不仅适用于该特定窗口,或者我做错了什么?
编辑1
让我们考虑以下示例:我有一个全屏窗口,然后我可以使用插件绘制转换后的窗口纹理(例如缩放转换(0.5、0.5、1.0((,但 X11 仍然看到一个全屏窗口,所以当我单击转换后的纹理事件之外的区域时,转到窗口。当我在插件中抓取指针时,我是所有事件的唯一接收者,然后我可以根据我的窗口转染重新计算坐标并将它们发送到窗口。
编辑2当我使用 Freeglut 时,当指针被抓取时,所有事件都会正确发送到目标窗口。库实现之间必须有一些差异。
OpenGL不关心输入事件,它只是绘制东西,甚至不知道X11或指针事件是什么。
这必须是 SDL 和 GLFW 在其窗口设置中执行的操作。
但是我想知道你为什么要抓住指针?X Composite 扩展是构建 Compiz 和其他合成 WM 的基础,它已经有一个用于指针输入转换的专用 API,请参阅 http://www.x.org/archive/X11R7.5/doc/compositeproto/compositeproto.txt
RedirectCoordinate
和 TransformCoordinate
。您应该使用这些函数,而不是弄乱抓取指针。抓住指针是一个非常非常糟糕的主意。
好的,似乎我链接的 X 复合扩展的副本(以及我的计算机上(是早期的草稿,其中仍然包含 RedirectCoordinate 。有一个较新的版本(不幸的是,它的脑海中带有相同的日期 - WTF?(,其中坐标重定向已被删除。
SDL 在处理 MouseMotion 事件时更新鼠标位置。它不使用存储在按钮按下事件中的坐标。当窗口管理器抓取指针并将 ButtonPress 事件发送到 SDL 窗口时,接收器内的鼠标位置不会更新。下面是示例解决方案(以下代码应添加到 SDL_x11events.c 中 ButtonPress 标签之后的部分:
if(xevent.xany.send_event)
{
SDL_Mouse *mouse = SDL_GetMouse();
mouse->x = xevent.xbutton.x;
mouse->y = xevent.xbutton.y;
}