1

在将输入焦点切换到具有匹配进程 ID 的每个窗口后,关闭显示(或同步显示)时出现错误。下面是我得到的错误和产生它的源代码。

源代码:

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <iostream>
#include <list>

using namespace std;

class WindowsMatchingPid{
public:
    WindowsMatchingPid(Display *display, Window wRoot, unsigned long pid)
        : _display(display)
        , _pid(pid)
    {
    // Get the PID property atom.
        _atomPID = XInternAtom(display, "_NET_WM_PID", True);
        if(_atomPID == None)
        {
            cout << "No such atom" << endl;
            return;
        }

        search(wRoot);
    }

    const list<Window> &result() const { return _result; }

private:
    unsigned long  _pid;
    Atom           _atomPID;
    Display       *_display;
    list<Window>   _result;

    void search(Window w)
    {
    // Get the PID for the current Window.
        Atom           type;
        int            format;
        unsigned long  nItems;
        unsigned long  bytesAfter;
        unsigned char *propPID = 0;
        if(Success == XGetWindowProperty(_display, w, _atomPID, 0, 1, False, XA_CARDINAL,
                                         &type, &format, &nItems, &bytesAfter, &propPID))
        {
            if(propPID != 0)
            {
            // If the PID matches, add this window to the result set.
                if(_pid == *((unsigned long *)propPID))
                    _result.push_back(w);

                XFree(propPID);
            }
        }

    // Recurse into child windows.
        Window    wRoot;
        Window    wParent;
        Window   *wChild;
        unsigned  nChildren;
        if(0 != XQueryTree(_display, w, &wRoot, &wParent, &wChild, &nChildren))
        {
            for(unsigned i = 0; i < nChildren; i++)
                search(wChild[i]);
        }
    }
};

main()
{
 // Obtain the X11 display.
    Display *display = XOpenDisplay(0);
    if(display == NULL)
        return -1;

 // Get the root window for the current display.
    Window winRoot = XDefaultRootWindow(display);

    WindowsMatchingPid wmp(display,winRoot,4344);
    list<Window> lw = wmp.result();

    for(list<Window>::iterator it=lw.begin(); it != lw.end(); it++ ){
        XSetInputFocus(display,*it,RevertToParent,CurrentTime);
    }
    //XSync(display,false);
    XCloseDisplay(display);
    return 0;
}

错误:

X Error of failed request:  BadMatch (invalid parameter attributes)
  Major opcode of failed request:  42 (X_SetInputFocus)
  Serial number of failed request:  495
  Current serial number in output stream:  506

当它到达XSyncor时会产生错误XCloseDisplay。当我删除这两个调用时,它不会产生这些错误。我不确定我在这里做错了什么,这会导致两者都XSync抱怨XCloseDisplay

4

1 回答 1

1

从文档中,它说明了以下内容:

指定的焦点窗口必须在调用 XSetInputFocus 时可见,否则会导致 BadMatch 错误。如果焦点窗口稍后变得不可见,X 服务器评估 revert_to 参数以确定新的焦点窗口,如下所示:

  • 如果 revert_to 是 RevertToParent,则焦点将返回到父级(或最近的可视祖先),并且新的 revert_to 值被视为 RevertToNone。

  • 如果 revert_to 为 RevertToPointerRoot 或 RevertToNone,则焦点将分别恢复为 PointerRoot 或 None。当焦点恢复时,X server 会产生 FocusIn 和 FocusOut 事件,但 last-focus-change 时间不受影响。

XSetInputFocus 可以生成 BadMatch、BadValue 和 BadWindow 错误。

所以,我错过了一项检查以确定窗口是否可见。以下更改将解决此问题:

main()
{
 // Obtain the X11 display.
    Display *display = XOpenDisplay(0);
    if(display == NULL)
        return -1;

 // Get the root window for the current display.
    Window winRoot = XDefaultRootWindow(display);

    WindowsMatchingPid wmp(display,winRoot,4344);
    list<Window> lw = wmp.result();

    for(list<Window>::iterator it=lw.begin(); it != lw.end(); it++ ){
        XWindowAttributes attribute; // <-- Added
        XGetWindowAttributes(display,*it,&attribute); // <-- Added
        if(attribute.map_state == IsViewable ){ // <-- Added
            XSetInputFocus(display,*it,RevertToParent,CurrentTime);
        } // <-- Added
    }
    XCloseDisplay(display);
    return 0;
}
于 2013-05-23T19:27:24.137 回答