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 位置,因此请求尚未得到处理。
我正在使用 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 位置,因此请求尚未得到处理。