X11 - XCB: Window information not up-to-date?

454 Views Asked by At

I'm using XCB to create my x11 window and, somewhere in the code, I want to move it.

I make a little test to print the window position (0, 0), then move it, and print the position again (200, 100).

Saddly, I have always x:10 and y:10.

Here the code:

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

Did I miss something? Thank you.

1

There are 1 best solutions below

1
On BEST ANSWER

The short version: You are ignoring the interaction with the window manager.

The long version:

First, the position that GetGeometry gives you is relative to the parent window. With a reparenting window manager, the WM will add a frame window around your window to draw window decorations to (titlebar, close button, ...). If you want the position of your window on screen, you should use use xcb_translate_coordinates(c, win, screen->root, 0, 0). The reply to this request will give you the position of 0,0 of your window translated to the root window.

However, in your example that will still not work. This is because of how the window manager works. It basically forbids your program from moving its window (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT). Due to this, when you try to move your window, the X11 server only sends this request as an event to the window manager. The window manager then needs some time to handle this request. Since you are immediately checking the window position again, the request will not yet have been handled.