如何使用xlib识别顶级X11窗口? [英] How to identify top-level X11 windows using xlib?

查看:1001
本文介绍了如何使用xlib识别顶级X11窗口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在X11会话中获得所有顶级桌面窗口的列表。基本上,我想获得窗口管理器应用程序切换UI中显示的所有窗口的列表(通常在用户按ALT + TAB时打开)。

I'm trying to get a list of all top level desktop windows in an X11 session. Basically, I want to get a list of all windows that are shown in the window managers application-switching UI (commonly opened when the user presses ALT+TAB).

从来没有做过任何X11编程之前,但到目前为止我已经设法枚举通过整个窗口列表,代码看起来像这样:

I've never done any X11 programming before, but so far I've managed to enumerate through the entire window list, with code that looks something like this:

void CSoftwareInfoLinux::enumerateWindows(Display *display, Window rootWindow)
{
    Window parent;
    Window *children;
    Window *child;
    quint32 nNumChildren;

    XTextProperty wmName;
    XTextProperty wmCommand;

    int status = XGetWMName(display, rootWindow, &wmName);
    if (status && wmName.value && wmName.nitems)
    {
        int i;
        char **list;
        status = XmbTextPropertyToTextList(display, &wmName, &list, &i);
        if (status >= Success && i && *list)
        {
            qDebug() << "Found window with name:" << (char*) *list;
        }

        status = XGetCommand(display, rootWindow, &list, &i);
        if (status >= Success && i && *list)
        {
            qDebug() << "... and Command:" << i << (char*) *list;
        }

        Window tf;
        status = XGetTransientForHint(display, rootWindow, &tf);
        if (status >= Success && tf)
        {
            qDebug() << "TF set!";
        }

        XWMHints *pHints = XGetWMHints(display, rootWindow);
        if (pHints)
        {
            qDebug() << "Flags:" << pHints->flags
                    << "Window group:" << pHints->window_group;
        }
    }

    status = XQueryTree(display, rootWindow, &rootWindow, &parent, &children, &nNumChildren);
    if (status == 0)
    {
        // Could not query window tree further, aborting
        return;
    }

    if (nNumChildren == 0)
    {
        // No more children found. Aborting
        return;
    }

    for (int i = 0; i < nNumChildren; i++)
    {
        enumerateWindows(display, children[i]);
    }

    XFree((char*) children);
}

enumerateWindows

enumerateWindows() is called initially with the root window.

这是可行的,因为它打印出关于数百个窗口的信息 - 我需要的是找出哪个属性可以询问以确定给定的 Window 是否是顶级桌面应用程序窗口(不知道官方术语是什么)。

This works, in so far as it prints out information about hundreds of windows - what I need, is to work out which property I can interrogate to determine if a given Window is a top-level Desktop application window (not sure what the official terminology is), or not.

任何人都可以了解这一点吗?所有的参考文档我发现X11编程已经非常干燥,很难理解。也许有人可能指向更好的资源?

Can anyone shed some light on this? All the reference documentation I've found for X11 programming has been terribly dry and hard to understand. Perhaps someone could point be to a better resource?

推荐答案

我有一个解决方案!

好吧,排序。

如果你的窗口管理器使用扩展窗口管理器提示(EWMH),你可以使用 _NET_CLIENT_LIST atom。窗口管理器正在管理的客户端窗口的返回列表。有关详细信息,请参阅此处

If your window manager uses the extended window manager hints (EWMH), you can query the root window using the "_NET_CLIENT_LIST" atom. This returna list of client windows the window manager is managing. For more information, see here.

但是,这有一些问题。一开始,正在使用的窗口管理器必须支持EWMH。 KDE和GNOME做,我相信一些其他人也一样。但是,我敢肯定有很多不。此外,我注意到KDE的几个问题。基本上,一些非KDE应用程序不包括在列表中。例如,如果在KDE下运行xcalc,它不会显示在此列表中。

However, there are some issues with this. For a start, the window manager in use must support the EWMH. KDE and GNOME do, and I'm sure some others do as well. However, I'm sure there are many that don't. Also, I've noticed a few issues with KDE. Basically, some non-KDE applications don't get included in the list. For example, if you run xcalc under KDE it won't show up in this list.

如果任何人都可以对此方法提供任何改进,我将很高兴听到他们。作为参考,我使用的代码如下所示:

If anyone can provide any improvements on this method, I'd be glad to hear them. For reference, the code I'm using is listed below:

	Atom a = XInternAtom(m_pDisplay, "_NET_CLIENT_LIST" , true);
	Atom actualType;
	int format;
	unsigned long numItems, bytesAfter;
	unsigned char *data =0;
	int status = XGetWindowProperty(m_pDisplay,
								rootWindow,
								a,
								0L,
								(~0L),
								false,
								AnyPropertyType,
								&actualType,
								&format,
								&numItems,
								&bytesAfter,
								&data);

	if (status >= Success && numItems)
	{
		// success - we have data: Format should always be 32:
		Q_ASSERT(format == 32);
		// cast to proper format, and iterate through values:
		quint32 *array = (quint32*) data;
		for (quint32 k = 0; k < numItems; k++)
		{
			// get window Id:
			Window w = (Window) array[k];

			qDebug() << "Scanned client window:" << w;
		}
		XFree(data);
	}

这篇关于如何使用xlib识别顶级X11窗口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆