下面的代码用来查找与特定进程的PID对应的X Window窗口。关键部分是递归查找窗口的_NET_WM_PID
属性。
一个进程PID可能会对应多个窗口,即使你在屏幕上只看到了一个窗口。
除了程序主窗口外,还可能有程序的“关于”等窗口。这类窗口虽然逻辑上(比如在Qt库中)应该从属于主窗口,但作为一个X Window来说,却有可能并不从属于主窗口。
#include <X11/X.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xproto.h> #include <X11/Xatom.h> #include <iostream> #include <list> /* Find X Window From PID * * Reference: * http://stackoverflow.com/questions/151407/how-to-get-an-x11-window-from-a-process-id */ class XWindowFinder { public: XWindowFinder(unsigned long pid, Display *display=NULL): _display(display), _pid(pid) { if(_display==NULL) _display = XOpenDisplay(NULL); _atomPID = XInternAtom(_display, "_NET_WM_PID", True); if(_atomPID == None) { std::cout << "No such atom" << std::endl; return; } Window wRoot = XDefaultRootWindow(_display); this->search(wRoot); } const std::vector<Window> &result() const { return _result; } void print(){ for(std::vector<Window>::const_iterator it=_result.begin(); it !=_result.end(); it++) std::cout << "Window #" << (unsigned long)(*it) << std::endl; } private: unsigned long _pid; Atom _atomPID; Display *_display; std::vector<Window> _result; unsigned long getPid(Window w){ 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) { unsigned long pid = *((unsigned long *)propPID); XFree(propPID); return pid; } } return 0; } bool search(Window w) { bool found = false; unsigned long propPID = this->getPid(w); if(_pid == propPID){ _result.push_back(w); return true; } // 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++){ found = search(wChild[i]) || found; // found = found || search(wChild[i]); //if(found) break; } } return found; } }; int main(int argc, char **argv){ if(argc>=3 && strcmp(argv[1],"pid")==0){ int pid = atoi(argv[2]); XWindowFinder finder(pid); finder.print(); return 0; } return 0; }