【问题标题】:X11 - XCB: Window information not up-to-date?X11 - XCB:窗口信息不是最新的?
【发布时间】:2021-01-26 21:08:31
【问题描述】:

我正在使用 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;
}

我错过了什么吗?谢谢。

【问题讨论】:

    标签: c++ linux window x11 xcb


    【解决方案1】:

    简短版:您忽略了与窗口管理器的交互。

    长版:

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

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

    【讨论】:

    • 非常感谢您的解释!真的很有帮助!
    猜你喜欢
    • 2021-04-08
    • 2019-03-29
    • 2020-11-10
    • 2018-11-30
    • 2019-04-01
    • 1970-01-01
    • 2019-06-06
    • 2011-10-20
    • 1970-01-01
    相关资源
    最近更新 更多