Я хочу контролировать все открытые окна под X11. В настоящее время я делаю это следующим образом:Как получить и синхронизировать полный список всех окон X11?
- Изначально шел все дерево рекурсивно вызывая XQueryTree из корневого окна
- Прослушивание изменений субструктуры на весь рабочий стол:
XSelectInput(display, root_window, SubstructureNotifyMask | PropertyChangeMask)
- Handling все MapNotify, UnmapNotify и DestroyNotify, обновляя мой собственный список окон в процессе.
Я в основном обеспокоен точкой 1. Во время рекурсии XQueryTree будет вызываться несколько раз. Есть ли способ гарантировать, что дерево не изменится тем временем? Другими словами, чтобы получить «снимок» всего дерева в один момент времени?
Кроме того, я заметил, что при некоторых системах X11 не все события поступают правильно. Например, при открытии нового окна на рабочем столе MapNotify для этого окна может никогда не появиться в моем приложении мониторинга. Как это может быть? Возможно ли, что он выброшен до прибытия?
Update:
Я написал небольшую программу, которая будет отслеживать X события на корневом окне (см. Ниже) Теперь, когда я запускаю эту программу и запускаю и завершаю xcalc, я получаю следующий вывод:
Reparented: 0x4a0005b to 0x1001e40
Mapped : 0x1001e40
Destroyed : 0x1001e40
Вот и все. Я никогда не уведомляюсь о том, что реальное окно (0x4a0005b) уничтожено. Даже при этом не отображается! Может ли кто-нибудь сказать мне, почему нет? Подструктура SubStructureNotifyMask вызывает только события . Прямые субкоды будут отправляться вместо всего поддерева?
Кстати, этого, похоже, не происходит, когда работает Compiz. Тогда нет reparenting не делается:
Mapped : 0x4a0005b
Mapped : 0x4e00233
Destroyed : 0x4a0005b
Destroyed : 0x4e00233
Мониторинг исходный код программы:
#include <X11/Xlib.h>
#include <cstdio>
int main()
{
Display *display;
Window rootwin;
display = XOpenDisplay(NULL);
rootwin = DefaultRootWindow(display);
XSelectInput(display, rootwin, SubstructureNotifyMask);
XEvent event;
while (1) {
XNextEvent(display, &event);
if (event.type == MapNotify) {
XMapEvent *mapevent = (XMapEvent *)&event;
printf("Mapped : 0x%x\n", (unsigned int)(mapevent->window));
}
if (event.type == DestroyNotify) {
XDestroyWindowEvent *destroywindowevent = (XDestroyWindowEvent *)&event;
printf("Destroyed : 0x%x\n", (unsigned int)(destroywindowevent->window));
}
if (event.type == ReparentNotify) {
XReparentEvent *reparentevent = (XReparentEvent *)&event;
printf("Reparented: 0x%x to 0x%x\n", (unsigned int)(reparentevent->window), (unsigned int)(reparentevent->parent));
}
}
return 0;
}
Спасибо! Я взглянул на исходный код для xwininfo и, похоже, делает обход дерева так же, как и я: без защиты конструкций вокруг него. Поэтому, если есть вероятность изменения дерева между вызовами XQueryTree, xwininfo также будет затронута и не даст правильных результатов, я думаю ... – Marten
@Marten, да. xwininfo - это моментальный снимок, но он даст вам иерархию. Затем вы можете открыть несколько окон и использовать их для запуска xprop -spy для проверки обновлений. Есть немало таких инструментов. Взгляните на список справочных страниц по адресу http://www.x.org/archive/X11R6.9.0/doc/html/manindex1.html –