How do I get the dimensions of the inner and outer window using Xlib / XCB?

Is there a reliable way to get the inner and outer rectangle of a top-level window with XCB / Xlib? (IOW frame and client rectangle).

Here's what I've tried:

  • xcb_get_geometry always returns the initial dimensions even after the window is resized (what gives?)

  • I figured I would call xcb_query_tree several times until I find the window frame window - is this a way to do this? I believe ICCCM / EWMH should provide this, but couldn't find anything. Is there any other standard / non-standard for this? It won't work with compiz / ubuntu10 anyway, because xcb_query_tree reports the client window as with root = parent (with normal ubuntu wm the window gets the parent correctly).

  • xcb_translate_coordinates () seemed to be the only reliable way to get root-based coords [1] in 2007 - is that still the case? That is, is XCB_CONFIGURE_NOTIFY non-standard with WM?

[1] http://fixunix.com/xwindows/91652-finding-position-top-level-windows.html

+3


source to share


1 answer


This is a partial answer as it only explains how to find the internal dimensions of a window. Also I'm not sure if this is the canonical path, but it works for me.

You can subscribe to the event XCB_EVENT_MASK_RESIZE_REDIRECT

when the window is created:

xcb_window_t           window    = xcb_generate_id          (connection);
const xcb_setup_t     *setup     = xcb_get_setup            (connection);
xcb_screen_t          *screen    = xcb_setup_roots_iterator (setup).data;
uint32_t               mask      = XCB_CW_EVENT_MASK;
uint32_t               valwin[1] = { XCB_EVENT_MASK_EXPOSURE
                                   | XCB_EVENT_MASK_RESIZE_REDIRECT };

xcb_create_window(
    connection,
    XCB_COPY_FROM_PARENT,
    window,
    screen->root,
    0, 0,
    800, 600,
    0,
    XCB_WINDOW_CLASS_INPUT_OUTPUT,
    screen->root_visual,
    mask, valwin);
xcb_map_window(connection, window);
xcb_flush(connection);

      



In the event loop, you can track size changes:

xcb_generic_event_t *event;
uint16_t width = 0, height = 0;
while ((event = xcb_wait_for_event(connection)) != NULL) {
    switch (event->response_type & ~0x80) {
    case XCB_EXPOSE: {
        /* ... */
        break;
    }
    case XCB_RESIZE_REQUEST: {
        auto resize = (xcb_resize_request_event_t*) event;
        if (resize->width > 0) width = resize->width;
        if (resize->height > 0) height = resize->height;
        break;
    }
    default:
        break;
    }
    free(event);
    xcb_flush(connection);
}

      

Note that I am not sure if this event is emitted when you trigger an app code resize with xcb_configure_window

eg. I've never tested it and just updated width

and height

in the wrapper functions for xcb_configure_window

.

+2


source







All Articles