在windows系統下如果想要枚舉指定進程的窗體,我們可以通過EnumWindows加上自己實現的回調函數進行實現,那么在linux下該如何做呢?
其實也很簡單,在linux下,我們可以通過xlib中提供的API進行實現,關於xlib后面會專門寫一篇文章講解。
一、實現思路
從root窗體開始逐層遍歷每一個窗體,將這些窗體所屬進程與給定進程比較從而進行篩選。
二、實現代碼
#include <X11/Xlib.h> #include <X11/Xatom.h> #include <QList> class WindowsMatchingPid { public: WindowsMatchingPid(Display *display, Window wRoot, unsigned long pid) : _display(display) , _pid(pid) { _atomPID = XInternAtom(display, "_NET_WM_PID", True); if(_atomPID == None) { return; } search(wRoot); } const QList<Window> result() const { return _result; } private: unsigned long _pid; Atom _atomPID; Display *_display; QList<Window> _result; void search(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) { if(_pid == *((unsigned long *)propPID)) _result.append(w); XFree(propPID); } } 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]); } } };
這里主要使用XGetWindowProperty和XQueryTree進行窗體樹遍歷以及窗體屬性獲取。
XGetWindowProperty:獲取目標窗體屬性信息
XQueryTree:獲取目標窗體的窗體樹結構
接着就利用這個類去獲取進程窗體
int pid = getpid(); Display *display = XOpenDisplay(0); WindowsMatchingPid match(display, XDefaultRootWindow(display), pid); const QList<Window> result = match.result(); for(int i=0; i<result.count();i++) { unsigned long winId = (unsigned long)(result.at(i)); QWidget* win = QWidget::find(winId); if(win!=NULL&&win->isWindow()&&win->isVisible()){ m_pformList->append((QObject*)win); } } XCloseDisplay(display);
PS:每次調用XOpenDisplay獲取x-server連接之后要記得調用XCloseDisplay關閉連接,否則連接泄露會導致程序異常退出。