c #x11 #xcb
#c #x11 #xcb
Вопрос:
В настоящее время я работаю над написанием диспетчера окон для восстановления с использованием C и библиотеки XCB. Я отключаю управление окнами, когда получаю событие UnmapNotify; в этом случае код очень прост:
if (unmap_ignore > 0) {
unmap_ignore--;
return;
}
client *cl = nullptr;
size_t idx = 0;
for (client amp;c : clients) {
if (c.window == ev->window) {
cl = amp;c;
break;
}
idx ;
}
if (!cl)
return;
xcb_unmap_window(conn, cl->frame);
clients.erase(clients.begin() idx);
Однако это не работает для некоторых клиентов, которые не беспокоятся о том, чтобы отменить отображение окна (обычно это происходит, когда вы принудительно завершаете процесс). Затем вместо этого отправляется DestroyNotify. Однако ev->window
поле там (typeof ev = xcb_destroy_notify_event_t) представляет собой некоторое значение, которое мне не нужно… вот несколько примеров журналов (также обратите внимание, что каждая строка представляет собой новое событие DestroyNotify, по какой-то причине я получаю его дважды, и каждый раз поле #window отличается, но неверно):
Found a client window: 4194307 but this was destroyed: 4194305
Found a client window: 4194307 but this was destroyed: 4194313
Я помню, прежде чем я попытался написать оконный менеджер в Xlib, и у меня была точно такая же проблема. Должно быть, я упускаю что-то очевидное, но если я посмотрю на код других перепрофилирующих оконных менеджеров, таких как Awesome или Herbsluftwm, они просто используют поле window и не имеют проблем. Что я делаю не так?
(мой полный код здесь: http://ix.io/3yDj )
Я подозреваю, что это просто дает мне два дочерних окна уничтоженного родителя вместо отправки фактического родителя. понятия не имею, почему, но это самая логичная вещь, которую я могу придумать. Я просто хочу иметь возможность справиться с этим, чтобы я мог отменить привязку фрейма к вещам, которые не отправляют события UnmapNotify.
Я также сначала подумал, что он может сообщать о DestroyNotify в родительском окне вместо перепрофилированного клиентом, поэтому я попытался проверить фрейм, но безрезультатно:
Found a client window: 2097152 but this was destroyed: 4194305
Found a client window: 2097152 but this was destroyed: 4194313
Я действительно был в тупике, поэтому любая помощь приветствуется, спасибо!
Например, Awesome делает то же самое, что я пробовал с ev-> window:
static void
event_handle_destroynotify(xcb_destroy_notify_event_t *ev)
{
client_t *c;
if((c = client_getbywin(ev->window)))
client_unmanage(c, CLIENT_UNMANAGE_DESTROYED);
else
for(int i = 0; i < globalconf.embedded.len; i )
if(globalconf.embedded.tab[i].win == ev->window)
{
xembed_window_array_take(amp;globalconf.embedded, i);
luaA_systray_invalidate();
}
}
Комментарии:
1. Устанавливаете ли вы StructureNotifyMask или SubstructureNotifyMask или оба, и в каком окне?
2. Я установил SubstructureNotifyMask и SubstructureRedirect mask (
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
) в корневом окне.3. SubstructureNotifyMask должен заставить корневое окно получать события DestroyNotify для своих дочерних элементов. Какова ваша структура восстановления? У вас каждое окно перенаправлено на своего собственного родителя или на корень?
4. Я получаю события destroynotify; просто поле window из них не является фактическим уничтоженным окном. У меня каждое окно повторно отображается в созданном мной фреймовом окне, вы можете увидеть это
window_manager::handle_map_request
в моем коде.5. Возможно, обходным путем может быть попытка получить родительское окно из тех, для которых сообщается о DestroyNotify, если они на самом деле являются дочерними окнами. Но я не уверен, что это возможно даже с уже уничтоженным окном…