我正在尝试获取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, 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()
。
这是有效的,因为它打印出有关数百个窗口的信息 - 我需要的是找出我可以询问哪个属性来确定给定Window
是否是顶级桌面应用程序窗口(不确定官方术语是什么)或不是。
有人可以对此有所了解吗?我发现的X11编程的所有参考文档非常干燥且难以理解。也许有人可以指出更好的资源?
答案 0 :(得分:11)
我有一个解决方案!
嗯,好吧。
如果您的窗口管理器使用扩展窗口管理器提示(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,
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);
}
答案 1 :(得分:6)
要扩展上一个解决方案,如果您想获取窗口名称:
// get window Id:
Window w = (Window) array[k];
char* name = '\0';
status = XFetchName(display, w, &name);
if (status >= Success)
{
if (name == NULL)
printf("Found: %ul NULL\n", w);
else
printf("Found: %ul %s\n", w, name);
}
XFree(name);
答案 2 :(得分:1)
如果您不必使用Xlib,则使用GDK的gdk_screen_get_window_stack()
和gdk_window_get_window_type()
可以帮助您满足您的需求。