我试图在X11会话中获取所有顶级桌面窗口的列表.基本上,我想获取窗口管理器应用程序切换UI中显示的所有窗口的列表(通常在用户按ALT TAB时打开).
我从来没有做过任何X11编程,但到目前为止,我已经设法通过整个窗口列表枚举,代码如下所示:
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,&i); if (status >= Success && i && *list) { qDebug() << "... and Command:" << i << (char*) *list; } Window tf; status = XGetTransientForHint(display,&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,&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()最初使用根窗口调用.
这是有用的,只要打印出关于数百个窗口的信息 – 我需要什么,就是找出可以询问哪个属性来确定给定的窗口是否是顶级的桌面应用程序窗口(不知道什么是官方术语是),还是不.
任何人都可以看出这一点吗?我发现X11编程的所有参考文档都非常干燥,难以理解.有人可能会指出一个更好的资源?
解决方法
我有一个解决方案
好吧,
如果您的窗口管理器使用扩展窗口管理器提示(EWMH),则可以使用“_NET_CLIENT_LIST”原子来查询根窗口.这个窗口管理器正在管理的客户端窗口的返回列表.有关更多信息,请参阅here.
但是,有一些问题.一开始,正在使用的窗口管理器必须支持EWMH. KDE和GNOME,我确定其他人也做.但是,我确信有很多没有.另外,我注意到KDE有几个问题.基本上,一些非KDE应用程序不包括在列表中.例如,如果您在KDE下运行xcalc,则不会在此列表中显示.
如果任何人可以对这种方法提供任何改进,我很乐意听到他们的意见.作为参考,我使用的代码如下:
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,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); }