简体   繁体   中英

Get WId of active window with XCB

What would be the proper way to get the active window (the one with input focus) with XCB?

reply = xcb_get_input_focus_reply(connection, xcb_get_input_focus(connection), nullptr);
std::cout << "WId: " << reply->focus;

This seems to be work sometimes and sometimes not.

I also saw someone mentioned querying _NET_ACTIVE_WINDOW root window property but I can't figure out how that is done and is it always supported with XCB?

Edit: The approach above with xcb_get_input_focus is only one part, after getting the reply->focus, you need to follow up the parent windows via xcb_query_tree.

As far as I know, EWMH-compliant window managers are expected to set _NET_ACTIVE_WINDOW attribute of root window to the window ID of the currently active window.

In order to get it,

  1. Use xcb_intern_atom to get the atom value for _NET_ACTIVE_WINDOW
  2. Get the root window ID, eg using xcb_setup_roots_iterator(xcb_get_setup(connection)).data->root
  3. Use xcb_get_property , xcb_get_property_reply , and xcb_get_property_value to get the value of the attribute of the root window.

_NET_ACTIVE_WINDOW has type of CARDINAL , which, for XCB purposes, has size of 32 bits.

Or you could use libxcb-ewmh which wraps this task into xcb_ewmh_get_active_window function.

This solution works for me, it's more or less migration from some X11 code to XCB. Basically get the focus window and follow up the the path of the parent window until the window id is equal to parent or root id, this is then the top level window.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM