2013-05-23 1 views
1

Я получаю сообщение об ошибке при закрытии дисплея (или его синхронизации) после переключения фокуса ввода в каждое окно с идентификатором соответствующего процесса. Ниже приведена ошибка, которую я получаю, и исходный код, который ее производит.Многие XSetInputFocus и XSync вызывают ошибку

код Источник:

#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 

Он производит ошибку, когда он достигает XSync или XCloseDisplay. Когда я удалил эти два вызова, он не производит эти ошибки. Я не уверен, что я делаю неправильно здесь, что вызывает как XSync, так и XCloseDisplay, чтобы жаловаться.

ответ

1

Из документации, говорится следующее:

The specified focus window must be viewable at the time XSetInputFocus is called, or a BadMatch error results. If the focus window later becomes not viewable, the X server evaluates the revert_to argument to determine the new focus window as follows:

  • If revert_to is RevertToParent, the focus reverts to the parent (or the closest viewable ancestor), and the new revert_to value is taken to be RevertToNone.

  • If revert_to is RevertToPointerRoot or RevertToNone, the focus reverts to PointerRoot or None, respectively. When the focus reverts, the X server generates FocusIn and FocusOut events, but the last-focus-change time is not affected.

XSetInputFocus can generate BadMatch, BadValue, and BadWindow errors.

Итак, я пропускал проверку, чтобы определить, является ли окно видимым или нет. Следующие изменения исправят проблему:

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