如何从进程ID中获取X11窗口?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (271)

在Linux下,我的C++应用程序使用叉()和execv()启动多个OpenOffice实例,以便查看一些PowerPoint幻灯片。这部分起作用了。

接下来,我希望能够将OpenOffice窗口移动到显示器上的特定位置。我可以使用XMoveResize Window()函数来实现这一点,但是我需要为每个实例找到窗口。

我有每个实例的进程ID,如何从其中找到X11窗口?

OpenOffice似乎没有设置_net_Wm_PID属性,所以这最终不能解决我的问题,但它确实回答了这个问题。

// Attempt to identify a window by name or attribute.
// by Adam Pierce <adam@doctort.org>

#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]);
        }
    }
};

int main(int argc, char **argv)
{
    if(argc < 2)
        return 1;

    int pid = atoi(argv[1]);
    cout << "Searching for windows associated with PID " << pid << endl;

// Start with the root window.
    Display *display = XOpenDisplay(0);

    WindowsMatchingPid match(display, XDefaultRootWindow(display), pid);

// Print the result.
    const list<Window> &result = match.result();
    for(list<Window>::const_iterator it = result.begin(); it != result.end(); it++)
        cout << "Window #" << (unsigned long)(*it) << endl;

    return 0;
}
提问于
用户回答回答于

我知道的唯一方法就是遍历窗口树,直到找到你想要的东西。遍历并不难(只要看看xwininfo-root-tree,如果你需要一个例子的话,看看xwininfo-根树能做什么)。

但是你如何识别你要找的窗口呢?一些应用程序设置一个名为_net_Wm_PID

我相信OpenOffice设置该属性的应用程序之一(和大多数Gnome应用程序一样)。

用户回答回答于

检查是否/proc/pid/environ包含一个名为WINDOWID的变量

扫码关注云+社区

领取腾讯云代金券