X11 - XCB: информация об окне не актуальна?

Я использую XCB для создания своего окна x11 и где-то в коде хочу его переместить.

Я делаю небольшой тест, чтобы распечатать позицию окна (0, 0), затем переместить его и снова распечатать позицию (200, 100).

К сожалению, у меня всегда x:10 и y:10.

Вот код:

// g++ -o test test_xcb.cpp -lX11 -lxcb
#include <xcb/xcb.h>
#include <iostream>
using namespace std;

void print_window_xywh(xcb_connection_t *conn, xcb_drawable_t win)
{
    auto geo = xcb_get_geometry_reply(
       conn, xcb_get_geometry(conn, win), nullptr);

    cout << "Window( " << win << ") - x: " << geo->x 
         << " - y: " << geo->y 
         << " - w: " << geo->width
         << " - h: " << geo->height << endl;
}

int main(void) {
   xcb_connection_t *c;
   xcb_screen_t     *screen;
   xcb_window_t      win;

   /* Open the connection to the X server */
   c = xcb_connect (NULL, NULL);

   /* Get the first screen */
   screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;

   /* Ask for our window's Id */
   win = xcb_generate_id(c);

   /* Create the window */
   xcb_create_window (c,                             /* Connection          */
                     XCB_COPY_FROM_PARENT,          /* depth (same as root)*/
                     win,                           /* window Id           */
                     screen->root,                  /* parent window       */
                     10, 10,                          /* x, y                */
                     150, 150,                      /* width, height       */
                     10,                            /* border_width        */
                     XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
                     screen->root_visual,           /* visual              */
                     0, NULL);                      /* masks, not used yet */

   /* Map the window on the screen */
   xcb_map_window (c, win);

   /* Make sure commands are sent, so window is shown */
   xcb_flush (c);

   // Print the position and size of the window
   print_window_xywh(c, win);

   // Move the window
   const static uint32_t values[] = { 200, 100 };
   xcb_configure_window(c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
   
   // Print again, should be 200 for x and 100 for y
   print_window_xywh(c, win);

   return 0;
}

Я что-то пропустил? Спасибо.


person Le-Dragon-Dev    schedule 12.10.2020    source источник


Ответы (1)


Краткая версия: вы игнорируете взаимодействие с оконным менеджером.

Длинная версия:

Во-первых, позиция, которую дает вам GetGeometry, относится к родительскому окну. С помощью оконного менеджера с переподчинением WM добавит окно рамки вокруг вашего окна, чтобы нарисовать украшения окна (заголовок, кнопка закрытия, ...). Если вам нужна позиция вашего окна на экране, вы должны использовать use xcb_translate_coordinates(c, win, screen->root, 0, 0). Ответ на этот запрос даст вам позицию 0,0 вашего окна, переведенную в корневое окно.

Однако в вашем примере это все равно не сработает. Это из-за того, как работает оконный менеджер. Это в основном запрещает вашей программе перемещать свое окно (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT). Из-за этого, когда вы пытаетесь переместить свое окно, сервер X11 отправляет этот запрос только как событие диспетчеру окон. Затем оконному менеджеру требуется некоторое время, чтобы обработать этот запрос. Поскольку вы немедленно снова проверяете положение окна, запрос еще не будет обработан.

person Uli Schlachter    schedule 13.10.2020
comment
Большое спасибо за объяснение! Действительно полезно!! - person Le-Dragon-Dev; 14.10.2020