Получить WID активного окна с XCB

Каков был бы правильный способ получить активное окно (с фокусом ввода) с 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.

1

Решение

Насколько я знаю, EWMH-совместимые оконные менеджеры должны установить _NET_ACTIVE_WINDOW атрибут корневого окна к идентификатору окна текущего активного окна.

Чтобы получить это,

  1. использование xcb_intern_atom чтобы получить значение атома для _NET_ACTIVE_WINDOW
  2. Получить идентификатор корневого окна, например, с помощью xcb_setup_roots_iterator(xcb_get_setup(connection)).data->root
  3. использование xcb_get_property, xcb_get_property_reply, а также xcb_get_property_value получить значение атрибута корневого окна.

_NET_ACTIVE_WINDOW имеет тип CARDINAL, который для целей XCB имеет размер 32 бита.

Или вы могли бы использовать libxcb-EWMH который оборачивает эту задачу в xcb_ewmh_get_active_window функция.

2

Другие решения

Это решение работает для меня, это более или менее переход от некоторого кода 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;
}
2

По вопросам рекламы [email protected]