Получить 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.

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;
}

Насколько я знаю, 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 функция.

Другие вопросы по тегам