X11 - XCB:Window 信息不是最新的?

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

我正在使用 XCB 创建我的 x11 window,并且在代码中的某处,我想移动它。

我做了一个小测试打印window位置(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;
}

我错过了什么吗?谢谢。

简短版本:您忽略了与 window 经理的互动。

长版:

首先,GetGeometry给你的位置是相对于parent window的。使用 reparenting window 管理器,WM 将在您的 window 周围添加框架 window 以绘制 window 装饰到(标题栏、关闭按钮、. ..).如果你想要 window 在屏幕上的位置,你应该使用 xcb_translate_coordinates(c, win, screen->root, 0, 0)。对该请求的回复将为您提供 window 的 0,0 位置翻译为根 window.

但是,在您的示例中,这仍然行不通。这是因为 window 管理器的工作方式。它基本上禁止您的程序移动其 window (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT)。因此,当您尝试移动 window 时,X11 服务器仅将此请求作为事件发送给 window 管理器。 window 经理需要一些时间来处理这个请求。由于您立即再次检查 window 位置,因此请求尚未得到处理。