Каков был бы правильный способ получить активное окно (с фокусом ввода) с XCB?
reply = xcb_get_input_focus_reply(connection, xcb_get_input_focus(connection), nullptr);
std::cout << "WId: " << reply->focus;
Кажется, иногда это работает, а иногда нет.
Я также видел, как кто-то упоминал, что он запрашивает свойство корневого окна _NET_ACTIVE_WINDOW, но я не могу понять, как это делается, и всегда ли это поддерживается XCB?
Редактировать: Описанный выше подход с xcb_get_input_focus — это только одна часть, после получения ответа -> фокус, вам нужно следить за родительскими окнами через xcb_query_tree.
Насколько я знаю, EWMH-совместимые оконные менеджеры должны установить _NET_ACTIVE_WINDOW
атрибут корневого окна к идентификатору окна текущего активного окна.
Чтобы получить это,
xcb_intern_atom
чтобы получить значение атома для _NET_ACTIVE_WINDOW
xcb_setup_roots_iterator(xcb_get_setup(connection)).data->root
xcb_get_property
, xcb_get_property_reply
, а также xcb_get_property_value
получить значение атрибута корневого окна._NET_ACTIVE_WINDOW
имеет тип CARDINAL
, который для целей XCB имеет размер 32 бита.
Или вы могли бы использовать libxcb-EWMH который оборачивает эту задачу в xcb_ewmh_get_active_window
функция.
Это решение работает для меня, это более или менее переход от некоторого кода X11 к XCB. В основном получите окно фокуса и следуйте по пути родительского окна, пока идентификатор окна не станет равным родительскому или корневому идентификатору, тогда это окно верхнего уровня.
WId ImageGrabber::getActiveWindow()
{
xcb_connection_t* connection = QX11Info::connection();
xcb_get_input_focus_reply_t* focusReply;
xcb_query_tree_cookie_t treeCookie;
xcb_query_tree_reply_t* treeReply;
focusReply = xcb_get_input_focus_reply(connection, xcb_get_input_focus(connection), nullptr);
xcb_window_t window = focusReply->focus;
while (1) {
treeCookie = xcb_query_tree(connection, window);
treeReply = xcb_query_tree_reply(connection, treeCookie, nullptr);
if (!treeReply) {
window = 0;
break;
}
if (window == treeReply->root || treeReply->parent == treeReply->root) {
break;
} else {
window = treeReply->parent;
}
free(treeReply);
}
free(treeReply);
return window;
}