通過Xlib枚舉指定進程下所有窗體


在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關閉連接,否則連接泄露會導致程序異常退出。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM