c++xcbewmh

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.


Solution

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