Как определить окна верхнего уровня X11 с помощью xlib?
Я пытаюсь получить список всех окон рабочего стола верхнего уровня в сеансе X11. В принципе, я хочу получить список всех окон, которые отображаются в приложении window Manager-switching 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, была ужасно сухой и трудной для понимания. Возможно, кому-то может быть лучше ресурс?
3 ответов
у меня есть решение!
Ну, вроде.
Если ваш оконный менеджер использует расширенные подсказки оконного менеджера( EWMH), вы можете запросить корневое окно с помощью "_NET_CLIENT_LIST
" атома. Это возвращаемый список клиентских окон, которыми управляет диспетчер окон. Дополнительные сведения см. В разделе здесь.
тем не менее, есть некоторые проблемы с этим. Для начала используемый оконный менеджер должен поддерживать EWMH. KDE и GNOME, и я уверен, что некоторые другие делают то же самое. Однако я уверен, что многие этого не делают. Кроме того, я заметил несколько проблем с KDE. В принципе, некоторые приложения, отличные от KDE, не включаются в список. Например, если вы запустите xcalc под KDE, он не будет отображаться в этом списке.
Если кто-нибудь может предоставить какие-либо улучшения в этом методе, я был бы рад их услышать. Для справки, код, который я использую ниже:
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);
}
чтобы развернуть предыдущее решение, если вы хотите получить имена окон:
// get window Id:
Window w = (Window) array[k];
char* name = '';
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);
Если вам не нужно использовать Xlib, используя GDK gdk_screen_get_window_stack()
и gdk_window_get_window_type()
может помочь вам для ваших нужд.