X11 FocusIn无效

时间:2015-08-31 20:14:55

标签: linux x11

只要我理解,只要窗口聚焦,就会触发X11 FocusIn事件。它是键盘输入发送到的窗口。我无法触发此事件。我确保在创建窗口时给它FocusChangeMask。我在我的事件处理程序中创建了一个断点,其中应该发生FocusIn事件并且它没有停止。

我有2个单独的窗口,一个透明的窗口和一个不透明的窗口。目前我有它所以透明窗口总是在非透明窗口的顶部。每当我切换焦点然后切换回透明窗口时,非透明窗口就在下面。这会导致其他窗口卡在'之间。透明和不透明的窗口。

我注意到每当我专注于下面的非透明窗口时,就会触发FocusIn事件。我无法获得透明窗口来触发事件。这是否与32位颜色的窗口有关?

我错过了什么?

while(!renderer->stop)
    {
        XNextEvent(renderer->x_display, &event);
        switch(event.type)
        {
            case Expose:
            if (event.xexpose.window == gstreamer_window)
            {
                XRaiseWindow(renderer->x_display, renderer->opengl_window);
            }
            break;

            case FocusIn:
            if (event.xfocus.window == renderer->opengl_window)
            {
                XRaiseWindow(renderer->x_display, gstreamer_window);
            }
            break;

            case ConfigureNotify:
            if (event.xconfigure.window == renderer->opengl_window)
            {
                XMoveWindow(renderer->x_display, gstreamer_window,
                            event.xconfigure.x, event.xconfigure.y - top_border_offset);
            }
            break;
        }
    }

以下是我创建窗口的方法。

XSetWindowAttributes  swa;
    swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | FocusChangeMask;
    swa.colormap = XCreateColormap(x_display, XDefaultRootWindow(x_display), visual, AllocNone);
    swa.background_pixel = 0;
    swa.border_pixel = 0;

    /* Create a window */
    opengl_window = XCreateWindow (
              x_display, parent,
              0, 0, m_plane_width, m_plane_height, 0,
              depth, InputOutput,
              visual, CWEventMask | CWBackPixel | CWColormap | CWBorderPixel,
              &swa );

3 个答案:

答案 0 :(得分:1)

好像我将FocusChangeMask设置在错误的位置。添加第XSelectInput(x_display, opengl_window, FocusChangeMask)行 ,它现在触发FocusIn事件。它触发了另一个显示器,因为它有掩码,但这个没有。

答案 1 :(得分:0)

从您的问题中不清楚您的问题中引用的窗口是顶级应用程序窗口,还是作为顶级应用程序窗口的子窗口的辅助辅助窗口。

但是在所有情况下,正确的输入焦点处理要求您准确地通知窗口管理器应用程序期望处理输入焦点的方式。

有关详细信息,请参阅section 4.1.7 of the ICCCM specification。不幸的是,仅仅编写处理FocusIn消息的事件循环并且期望它们脱离天空是不够的。首先,您需要告诉窗口管理器您将如何处理输入焦点切换,然后响应窗口管理器的消息,如ICCCM规范中所述;也许通过为您自己的应用程序窗口显式发送SetInputFocus请求。

答案 2 :(得分:0)

在OP自己接受的背景解答中查看我的帖子

我遇到了同样的问题,如果您使用XSelectInput,它似乎会覆盖窗口的事件掩码,而不是添加到窗口中。您需要:

  • 跳过添加XSelectInput并在创建时在窗口上设置事件掩码

  • 或将窗口的掩码的所有添加到XSelectInput命令

在添加XSelectInput行之前,这是与我相似的设置:

swa.event_mask = StructureNotifyMask | SubstructureNotifyMask | FocusChangeMask | ExposureMask | KeyPressMask;
wnd = XCreateWindow(disp, wndRoot, left, top, width, height, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
XMapWindow(disp, wnd);

当我添加它以捕获按键输入时:

XSelectInput(disp, wnd, KeyPressMask | KeyReleaseMask);

所有其他一切都停止了工作,直到现在我还没有意识到,因为我只是在测试密钥。

我在工作区中没有控件的单个窗口应用程序,因此我不知道XSelectInput对已经有遮罩的窗口还有什么作用,但是我确实得到了上下键消息,而没有它。在OP的自我接受答案中,他只是采用另一种方法,而是在XSelectInput上添加了“ FocusChangeMask”。

在我看来,许多X11的文档与标准的Apple文档非常相似,在该文档中,它从来不说该功能实际上是做什么或会影响什么,而是告诉您其他所有信息。 (请参见下面的代码段)公平地说,可可文档中相当一部分相当不错,但也许有一半不是。这也适用于许多或大多数参数。

在Linux手册页中,我认为它可能与Xlib手册在https://tronche.com/gui/x/xlib/上完全相同

  

XSelectInput函数请求X服务器报告与指定事件掩码关联的事件。

     

设置窗口的事件掩码属性会覆盖先前对同一窗口的调用,但不会覆盖其他客户端。


(下面是我自己对XInputSelect文档的错误改写)

这可以解释为:

  

XSelectInput在窗口上设置事件掩码,以显示报告给客户端的事件。每个客户端都可以为要接收的事件设置自己的独立掩码,并具有以下异常(跳过异常)。

现在关键部分:

  

XInputSelect将为客户端覆盖并替换显示器上窗口的任何以前的事件掩码设置,包括创建窗口时设置的任何事件掩码。

我希望编写它的目的是确保它理解(如果为真)XInputSelect不执行其他任何操作,例如启用字符解释键,什么也不做,因为我相信核心的困惑是来自各个示例的人员那里给人的印象是,除了设置面具外,还有其他魔术。我假设没有了,文档中除了面具以外,没有其他魔术。

  

XInputSelect设置窗口的事件掩码,并允许在创建窗口后设置事件掩码。

我认为那条线应该是第一行。