Keyboard XSetInputFocus失败

Keyboard XSetInputFocus失败,keyboard,focus,xlib,Keyboard,Focus,Xlib,在我的Xlib应用程序中,我需要将键盘设置为专注于某个特定的组件,我想用XSetInputFocus来实现这一点。由于某种原因,即使我的窗口是可见的(手册页上说导致此错误的原因是一个不可见/映射的窗口),我也总是会收到一个BadMatch错误。当我说它是可见的,我的意思是我可以在屏幕上看到它,我知道请求列表已经刷新了 因此,我没有分享我庞大的代码,而是在互联网上找到了一个较小的演示,并试图修改它。我使用Xlib中的事件处理代码,如我找到的一个示例中所示。我尝试添加以下行: XSetInputFo

在我的Xlib应用程序中,我需要将键盘设置为专注于某个特定的组件,我想用
XSetInputFocus
来实现这一点。由于某种原因,即使我的窗口是可见的(手册页上说导致此错误的原因是一个不可见/映射的窗口),我也总是会收到一个
BadMatch
错误。当我说它是可见的,我的意思是我可以在屏幕上看到它,我知道请求列表已经刷新了

因此,我没有分享我庞大的代码,而是在互联网上找到了一个较小的演示,并试图修改它。我使用Xlib中的事件处理代码,如我找到的一个示例中所示。我尝试添加以下行:

XSetInputFocus (display, win, RevertToNone, CurrentTime);
就在排队前

/* perform an events loop */
我得到的错误是:

X Error of failed request:  BadMatch (invalid parameter attributes)
  Major opcode of failed request:  42 (X_SetInputFocus)
  Serial number of failed request:  12
  Current serial number in output stream:  12
这与我在自己的应用程序中遇到的错误完全相同,事件顺序也完全相同:

  • 使用
    XCreateSimpleWindow
    创建一个窗口(该窗口应该是
    InputOutput
    窗口)
  • 使用
    XSelectInput
    并在掩码中选择,也可以获得
    KeyPressMask
  • 映射窗口(
    XMapWindow
  • 使用
    XSetInputFocus
    请求焦点,使用
    RevertToNone
    RevertToParent
    (均失败)
  • 我怀疑这与我需要使用
    XNextEvent
    处理窗口创建事件有关,直到我完成窗口的重新分配,但在这种情况下,我不知道我应该等到什么时候(在尝试之前应该接收哪些事件?)。在程序中第一次调用
    XNextEvent
    之前,我正在执行此操作


    任何帮助都将受到高度赞赏。提前谢谢

    就在昨天,我也遇到了类似的问题。。。这是因为X服务器异步处理事件;因此,在尝试使用XSetInputFocus()之前,需要等待窗口被映射

    您应该调用XIfEvent()来确定这一点

    示例(用freepascal编写):


    希望这有帮助

    对我来说,简化的解决方案也很有效:
    在调用
    XMapWindow()
    之后,在执行
    XSetInputFocus()
    之前,我只调用了
    XSync()

    在这里找到的代码彻底解决了这个问题:

    从那以后就再也没有问题了。这有点吓人,但由于应用程序 在窗口映射/取消映射的任何时候都可以完全控制(我想也是希望如此)


    XInputSetFocus是我遇到的唯一一个使用这种“rest-of-API-is-asynchronous-but-I-want-what-I-want-right-now”设计的命令。

    正如我在问题中所说的“我的窗口可见”,所以我认为这表明映射事件已被处理。然而,我确实听从了你的建议,尝试了XIfEvent。恐怕这对我的完整代码没有帮助,但这也可能是其中的一个bug。当我能做到的时候,我会用我给出的例子来试一下。谢谢你的提示,我试试看!虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,则仅链接的答案可能无效。
    // The filter-function, here you should return true if
    //  the event parameter matches the one you want
    //  in this case, I match the type to be MapNotify and the window to be the correct one
    Function WaitForNotify(aDPY: PDisplay; anEvent: PXEvent; arg: TXPointer): LongBool; cdecl;
    Begin
        Result:= (anEvent^._type = MapNotify) and (anEvent^.xmap.window = TWindow(arg));
    End;
    
    // XIfEvent cycles through the event cue, and evaluates each event through
    //  the function you provide it
    XIfEvent(dpy, @event, @WaitForNotify, TXPointer(xWindow));
    
    // Then, once this call returns, you're shure you've got focus and you can safely call
    //  XSetInpuFocus()
    XSetInputFocus(dpy, XWindow, RevertToNone, CurrentTime);