Как получить внутренние и внешние размеры окна с помощью Xlib / XCB?

Есть ли надежный способ получить внутренний и внешний прямоугольник окна верхнего уровня с помощью XCB / Xlib? (Рамка IOW и клиентский прямоугольник).

Вот что я пробовал:

  • xcb_get_geometry всегда возвращает исходные размеры даже после изменения размера окна (что дает?)

  • Я подумал, что буду вызывать xcb_query_tree несколько раз, пока не найду окно фрейма окна - это способ сделать это? Я полагаю, что ICCCM / EWMH должен предоставить это, но ничего не нашел. Есть ли другие стандартные / нестандартные для этого? В любом случае это не работает с compiz / ubuntu10, потому что xcb_query_tree сообщает, что клиентское окно имеет root = parent (в обычном ubuntu wm окно правильно переопределяется).

  • xcb_translate_coordinates () казался единственным надежным способом получить корневые координаты [1] в 2007 году - так ли это до сих пор? Т.е. XCB_CONFIGURE_NOTIFY нестандартен для WM?

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


person Community    schedule 03.07.2015    source источник


Ответы (1)


Это частичный ответ, поскольку он только объясняет, как найти внутренние размеры окна. Также я не уверен, что это канонический путь, но он работает для меня.

Вы можете подписаться на событие XCB_EVENT_MASK_RESIZE_REDIRECT при создании окна:

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

Затем в цикле событий вы можете отслеживать изменения размеров:

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

Обратите внимание, что я не уверен, генерируется ли это событие, когда вы инициируете изменение размера из кода вашего приложения, например, с помощью xcb_configure_window. Я никогда не тестировал его, а просто обновил width и height в функции-оболочке для xcb_configure_window.

person Richard    schedule 05.03.2016