【问题标题】:Sending an event using XSendEvent when a pointer is grabbed抓取指针时使用 XSendEvent 发送事件
【发布时间】:2014-12-19 08:17:59
【问题描述】:

我为 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 仍然看到一个全屏窗口,所以当我单击转换纹理事件之外的区域转到窗口。当我在插件中抓取指针时,我是所有事件的唯一接收者,然后我可以根据我的窗口变换重新计算坐标并将它们发送到窗口。

编辑2 当我使用 Freeglut 时,所有事件都会在抓取指针时正确发送到目标窗口。库实现之间必须存在一些差异。

【问题讨论】:

    标签: opengl x11 xlib compiz


    【解决方案1】:

    OpenGL 不关心输入事件,它只是绘制东西,甚至不知道 X11 或指针事件是什么。

    这必须是 SDL 和 GLFW 在其窗口设置中所做的事情。

    但是我想知道你为什么要抓住指针? X Composite 扩展是构建 Compiz 和其他合成 WM 的基础,它已经具有用于指针输入转换的专用 API,请参阅 http://www.x.org/archive/X11R7.5/doc/compositeproto/compositeproto.txt RedirectCoordinateTransformCoordinate。您应该使用这些功能,而不是乱抓指针。抓住指针是一个非常非常糟糕的主意。

    好的,我链接的 X 复合扩展的副本(我的计算机上有)似乎是早期的草稿,其中仍然包含 RedirectCoordinate。有一个更新的版本(不幸的是,它的头部带有相同的日期 - WTF?)其中坐标重定向已被删除。

    【讨论】:

    • 请参阅Edit1(回答我为什么要抓住指针)。我对X11不熟悉。也许您的解决方案正是我正在寻找的,但我不确定如何使用它。 Compiz 包含在复合插件 中,但我在 /usr/include 或 /usr/local/include 中找不到任何包含 RedirectCoordinate 或 TransformCoordinate 的标头。您能否描述一下我如何实现 Xcomposite 功能。
    【解决方案2】:

    SDL 在处理 MouseMotion 事件时更新鼠标位置。它不使用存储在 ButtonPress 事件中的坐标。当窗口管理器获取指针并将 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-22
      • 1970-01-01
      • 1970-01-01
      • 2011-05-06
      • 1970-01-01
      相关资源
      最近更新 更多