简体   繁体   English

X11 FocusIn无法正常工作

[英]X11 FocusIn is not working

As long as I understand it, the X11 FocusIn event is triggered whenever the window comes into focused. 据我了解,只要窗口聚焦,就会触发X11 FocusIn事件。 It the the window that the keyboard input is sent to. 它是键盘输入发送到的窗口。 I am having trouble triggering this event. 我在触发此事件时遇到了麻烦。 I have made sure to give it the FocusChangeMask when creating the window. 创建窗口时,请确保为它提供FocusChangeMask。 I have created a breakpoint inside my event handler where the FocusIn event is supposed to happen and it is not stopping. 我在事件处理程序中创建了一个断点,应该在该断点处发生FocusIn事件,并且该断点不会停止。

I have 2 separate window, a transparent one and one non-transparent. 我有2个单独的窗口,一个透明窗口,一个不透明窗口。 Currently I have it so the transparent window is always on top of the non transparent window. 目前我有它,因此透明窗口始终位于非透明窗口之上。 Whenever I switch focus and then switch back to the transparent window, the non-transparent window is directly underneath. 每当我切换焦点然后再切换回透明窗口时,非透明窗口都位于其正下方。 This causes other windows to be stuck in 'between' the transparent and non-transparent window. 这导致其他窗口被卡在透明和非透明窗口之间。

I have noticed that whenever I focus on the non-transparent window that is underneath that triggers the FocusIn event. 我注意到,每当我将焦点放在下面的非透明窗口上时,就会触发FocusIn事件。 I can not get the transparent window to trigger the event. 我无法获得透明窗口来触发事件。 Does this have something to do with the window being in 32-bit color? 这与32位颜色的窗口有关吗?

What am I missing? 我想念什么?

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;
        }
    }

Here is how I created the window. 这是我创建窗口的方式。

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 );

It appears as though I set the FocusChangeMask at the wrong place. 好像我将FocusChangeMask设置在错误的位置。 By adding the line XSelectInput(x_display, opengl_window, FocusChangeMask) , it now triggers the FocusIn event. 现在,通过添加XSelectInput(x_display, opengl_window, FocusChangeMask) ,它会触发FocusIn事件。 It was triggering the other display because it had the mask but this one didn't. 它触发了另一台显示器,因为它有面具,但是没有。

It's not clear from your question whether the windows referenced in your question are top level application windows, or secondary, ancillary windows that are child windows of your top level application windows. 从您的问题中还不清楚,问题中引用的窗口是顶级应用程序窗口,还是辅助,辅助窗口(它们是顶级应用程序窗口的子窗口)。

But in all cases, proper input focus handling requires you to inform the window manager exactly how your application expects to handle input focus. 但是在所有情况下,正确的输入焦点处理都要求您准确告知窗口管理器您的应用程序期望如何处理输入焦点。

See section 4.1.7 of the ICCCM specification for more information. 有关更多信息,请参见ICCCM规范的4.1.7节 Unfortunately, it's not enough just to code an event loop that handles FocusIn messages, and expect them to fall out of the sky. 不幸的是,仅仅编写一个处理FocusIn消息的事件循环并期望它们掉到空中是不够的。 First, you need to tell your window manager how exactly you are going to handle input focus switching, then respond to the window manager's messages, as explained in the ICCCM specification; 首先,您需要告诉窗口管理器您将如何精确地处理输入焦点切换,然后按照ICCCM规范中的说明响应窗口管理器的消息; perhaps by explicitly sending the SetInputFocus requests for your own application windows. 也许通过为您自己的应用程序窗口显式发送SetInputFocus请求。

See my post under OP's self accepted answer for background 请参阅OP自我接受的答案下的背景信息

I had the same problem and it seems if you use XSelectInput it overrides the event mask for a window, instead of adding to it. 我有同样的问题,似乎如果您使用XSelectInput它将覆盖窗口的事件掩码,而不是添加到窗口。 You need to either: 您需要:

  • skip adding XSelectInput and set the event masks on the window when created 创建时跳过添加XSelectInput并在窗口上设置事件掩码

  • or add all of the masks for the window to the XSelectInput command 或将窗口的所有遮罩添加到XSelectInput命令

Here's my similar setup which worked before I added the XSelectInput line: 这是我添加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);

When I added this for capturing key input: 当我添加此内容以捕获按键输入时:

XSelectInput(disp, wnd, KeyPressMask | KeyReleaseMask);

everything else stopped working, which I didn't realize for a while, until now, because I was just testing keys. 其他所有东西都停止了工作,直到现在我还没有意识到,因为我只是在测试密钥。

I have a single window application with no controls in the client area, so I don't know what else XSelectInput does for a window that already has the masks, but I do get key up and down messages without it. 我有一个单一的窗口应用程序,在工作区中没有控件,所以我不知道XSelectInput对已经有遮罩的窗口还有什么XSelectInput ,但是我确实在没有它的情况下得到了上下按键消息。 In the OP's self accepted answer he just goes the other way and adds 'FocusChangeMask' to XSelectInput instead. 在OP自己接受的答案中,他只是走了另一条路,而是在XSelectInput添加了“ FocusChangeMask”。

The documentation for a lot of X11 is, in my opinion, a lot like the standard Apple documentation where it has the affliction of never saying what the function really actually does or affects, but tells you all about everything else. 在我看来,许多X11的文档与标准的Apple文档很像,在该文档中,它的痛苦之处在于从不说出功能的真正作用或影响,却将所有其他内容告诉您。 (See bottom snippet here) To be fair a good portion of the Cocoa docs are pretty decent, but maybe half are not. (请参见下面的代码段)公平地说,可可文档中相当一部分相当不错,但也许有一半不是。 That goes for many or most of the parameters as well. 这也适用于许多或大多数参数。

From Linux man page which I think is the maybe verbatim the same as the Xlib manual here https://tronche.com/gui/x/xlib/ 在Linux手册页中,我认为这可能与Xlib手册完全相同, 网址为https://tronche.com/gui/x/xlib/

The XSelectInput function requests that the X server report the events associated with the specified event mask. XSelectInput函数请求X服务器报告与指定事件掩码关联的事件。

Setting the event-mask attribute of a window overrides any previous call for the same window but not for other clients. 设置窗口的事件掩码属性会覆盖同一窗口的所有先前调用,但不会覆盖其他客户端。


(Below is my own perhaps incorrect rewording of the XInputSelect docs) (以下是我自己对XInputSelect文档的可能不正确的改写)

This can be interpreted as perhaps: 这可以解释为:

XSelectInput sets the event-mask on a window for a display for events reported to the client. XSelectInput在窗口上设置事件掩码,以显示报告给客户端的事件。 Each client can set its own independent mask for events it wants to receive with the following exceptions (skipping the exceptions). 每个客户端都可以为希望接收的事件设置自己的独立掩码,并具有以下异常(跳过异常)。

Now the critical part: 现在关键的部分是:

XInputSelect will override and replace for a client any previous event-mask settings for a window on a display, including any event-mask set when creating the window. XInputSelect将为客户端覆盖并替换显示器上窗口的任何以前的事件掩码设置,包括在创建窗口时设置的任何事件掩码。

And what I wish it was written as to make sure its understood, if true, that the XInputSelect does nothing else like enable key to character interpretation and what not, because I believe the core confusion is that people from all the various examples out there get the impression that there is some other magic besides setting mask. 我希望编写它的目的是确保它理解(如果为真)XInputSelect不执行其他任何操作,例如启用字符解释键,而不能执行其他操作,因为我相信核心困惑在于,来自所有各种示例的人们给人的印象是除了设置面具外还有其他魔术。 I'm assuming there's not, and the docs speak of no other magic besides the mask. 我以为没有,除了面具,文档中没有其他魔术。

XInputSelect sets the event-mask for a window and allows for setting an event mask after a window is created. XInputSelect设置窗口的事件掩码,并允许在创建窗口后设置事件掩码。

And my opinion is that that line should have been first. 我认为那条线应该是第一位的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM