X11/Xlib/xcb:如果指定颜色图,创建 window 需要边框像素。为什么?
X11/Xlib/xcb: Creating a window requires border pixel if specifying colormap. Why?
在使用 Xlib 或 xcb 创建 X window 时,我发现如果我想提供颜色图,我必须提供边框像素属性。这个要求对我来说似乎很奇怪,因为我注意到这两个属性是如何相关的,我想知道是否有人可以分享一些关于为什么会这样的见解。
下面的两个示例创建了一个深度为 32 的 X window 和一个真彩色视觉对象 class。在这两个示例中,如果颜色贴图的遮罩连同相应的值一起被删除,我会在程序中出现意外行为。
在 xcb 中,检查 cookie 时出现 BadMatch
错误,而在 Xlib 示例中,window 创建成功但未映射。
有人可以解释为什么 Xlib 或 xcb 都不能在不指定边框像素属性的情况下工作,以及为什么每个库以不同的方式显示错误吗?
Xlib.c:
int main()
{
Display *display = XOpenDisplay(NULL);
if (!display) {
/* TODO(djr): Logging */
fputs("X11: Unable to create connection to display server", stderr);
return -1;
}
int screen = DefaultScreen(display);
Window root = RootWindow(display, screen);
XVisualInfo vinfo = {0};
if (!XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo)) {
/* TODO(djr): Logging */
fputs("X11: Unable to find supported visual info", stderr);
return -1;
}
Colormap colormap = XCreateColormap(
display, root, vinfo.visual, AllocNone);
const unsigned long wamask = CWColormap | CWBorderPixel;
XSetWindowAttributes wa;
wa.colormap = colormap;
wa.border_pixel = WhitePixel(display, screen);
Window window = XCreateWindow(
display,
root,
0, 0,
1600, 900,
1, /* border width */
vinfo.depth,
InputOutput,
vinfo.visual,
wamask,
&wa);
if (!window) {
/* TODO(djr): Logging */
fputs("X11: Unable to create window", stderr);
return -1;
}
XMapWindow(display, window);
XFlush(display);
pause();
XCloseDisplay(display);
return 0;
}
xcb.c:
int main()
{
xcb_connection_t *connection = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(connection)) {
fprintf(stderr, "ERROR: failed to connection to X server\n");
return -1;
}
const xcb_setup_t *setup = xcb_get_setup(connection);
xcb_screen_t *screen = xcb_setup_roots_iterator(setup).data;
xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(screen);
xcb_depth_t *depth = NULL;
while (depth_iter.rem) {
if (depth_iter.data->depth == 32 && depth_iter.data->visuals_len) {
depth = depth_iter.data;
break;
}
xcb_depth_next(&depth_iter);
}
if (!depth) {
fprintf(stderr, "ERROR: screen does not support 32 bit color depth\n");
xcb_disconnect(connection);
return -1;
}
xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth);
xcb_visualtype_t *visual = NULL;
while (visual_iter.rem) {
if (visual_iter.data->_class == XCB_VISUAL_CLASS_TRUE_COLOR) {
visual = visual_iter.data;
break;
}
xcb_visualtype_next(&visual_iter);
}
if (!visual) {
fprintf(stderr, "ERROR: screen does not support True Color\n");
xcb_disconnect(connection);
return -1;
}
xcb_colormap_t colormap = xcb_generate_id(connection);
xcb_void_cookie_t cookie = xcb_create_colormap_checked(
connection,
XCB_COLORMAP_ALLOC_NONE,
colormap,
screen->root,
visual->visual_id);
xcb_generic_error_t *error = xcb_request_check(connection, cookie);
if (error) {
fprintf(stderr, "ERROR: failed to create colormap: %s\n", xcb_errors[error->error_code]);
xcb_disconnect(connection);
return -1;
}
unsigned int cw_mask = XCB_CW_COLORMAP | XCB_CW_BORDER_PIXEL;
unsigned int cw_values[] = { screen->white_pixel, colormap };
xcb_window_t window = xcb_generate_id(connection);
cookie = xcb_create_window_checked(
connection,
depth->depth,
window,
screen->root,
0, 0,
1600, 900,
1,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
visual->visual_id,
cw_mask,
cw_values);
error = xcb_request_check(connection, cookie);
if (error) {
fprintf(stderr, "ERROR: failed to create window: %s\n", xcb_errors[error->error_code]);
xcb_disconnect(connection);
return -1;
}
xcb_map_window(connection, window);
xcb_flush(connection);
pause();
xcb_disconnect(connection);
return 0;
}
我刚试过你的程序,即使我没有指定颜色图,它也会失败,所以我认为颜色图与你的问题无关。
我不太确定,但我的猜测是默认边框像素图是 XCB_COPY_FROM_PARENT
,并且必须与 window 视觉和深度相匹配。但是您正在设置视觉和深度(与父级不同)。现在,边框视觉效果或深度与 window 的不同,因此您会得到一个 BadMatch。
通过指定边框像素颜色,X 创建了一个具有适当属性的像素图并将其设置为边框像素图,然后一切又恢复正常了。
在使用 Xlib 或 xcb 创建 X window 时,我发现如果我想提供颜色图,我必须提供边框像素属性。这个要求对我来说似乎很奇怪,因为我注意到这两个属性是如何相关的,我想知道是否有人可以分享一些关于为什么会这样的见解。
下面的两个示例创建了一个深度为 32 的 X window 和一个真彩色视觉对象 class。在这两个示例中,如果颜色贴图的遮罩连同相应的值一起被删除,我会在程序中出现意外行为。
在 xcb 中,检查 cookie 时出现 BadMatch
错误,而在 Xlib 示例中,window 创建成功但未映射。
有人可以解释为什么 Xlib 或 xcb 都不能在不指定边框像素属性的情况下工作,以及为什么每个库以不同的方式显示错误吗?
Xlib.c:
int main()
{
Display *display = XOpenDisplay(NULL);
if (!display) {
/* TODO(djr): Logging */
fputs("X11: Unable to create connection to display server", stderr);
return -1;
}
int screen = DefaultScreen(display);
Window root = RootWindow(display, screen);
XVisualInfo vinfo = {0};
if (!XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo)) {
/* TODO(djr): Logging */
fputs("X11: Unable to find supported visual info", stderr);
return -1;
}
Colormap colormap = XCreateColormap(
display, root, vinfo.visual, AllocNone);
const unsigned long wamask = CWColormap | CWBorderPixel;
XSetWindowAttributes wa;
wa.colormap = colormap;
wa.border_pixel = WhitePixel(display, screen);
Window window = XCreateWindow(
display,
root,
0, 0,
1600, 900,
1, /* border width */
vinfo.depth,
InputOutput,
vinfo.visual,
wamask,
&wa);
if (!window) {
/* TODO(djr): Logging */
fputs("X11: Unable to create window", stderr);
return -1;
}
XMapWindow(display, window);
XFlush(display);
pause();
XCloseDisplay(display);
return 0;
}
xcb.c:
int main()
{
xcb_connection_t *connection = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(connection)) {
fprintf(stderr, "ERROR: failed to connection to X server\n");
return -1;
}
const xcb_setup_t *setup = xcb_get_setup(connection);
xcb_screen_t *screen = xcb_setup_roots_iterator(setup).data;
xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(screen);
xcb_depth_t *depth = NULL;
while (depth_iter.rem) {
if (depth_iter.data->depth == 32 && depth_iter.data->visuals_len) {
depth = depth_iter.data;
break;
}
xcb_depth_next(&depth_iter);
}
if (!depth) {
fprintf(stderr, "ERROR: screen does not support 32 bit color depth\n");
xcb_disconnect(connection);
return -1;
}
xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth);
xcb_visualtype_t *visual = NULL;
while (visual_iter.rem) {
if (visual_iter.data->_class == XCB_VISUAL_CLASS_TRUE_COLOR) {
visual = visual_iter.data;
break;
}
xcb_visualtype_next(&visual_iter);
}
if (!visual) {
fprintf(stderr, "ERROR: screen does not support True Color\n");
xcb_disconnect(connection);
return -1;
}
xcb_colormap_t colormap = xcb_generate_id(connection);
xcb_void_cookie_t cookie = xcb_create_colormap_checked(
connection,
XCB_COLORMAP_ALLOC_NONE,
colormap,
screen->root,
visual->visual_id);
xcb_generic_error_t *error = xcb_request_check(connection, cookie);
if (error) {
fprintf(stderr, "ERROR: failed to create colormap: %s\n", xcb_errors[error->error_code]);
xcb_disconnect(connection);
return -1;
}
unsigned int cw_mask = XCB_CW_COLORMAP | XCB_CW_BORDER_PIXEL;
unsigned int cw_values[] = { screen->white_pixel, colormap };
xcb_window_t window = xcb_generate_id(connection);
cookie = xcb_create_window_checked(
connection,
depth->depth,
window,
screen->root,
0, 0,
1600, 900,
1,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
visual->visual_id,
cw_mask,
cw_values);
error = xcb_request_check(connection, cookie);
if (error) {
fprintf(stderr, "ERROR: failed to create window: %s\n", xcb_errors[error->error_code]);
xcb_disconnect(connection);
return -1;
}
xcb_map_window(connection, window);
xcb_flush(connection);
pause();
xcb_disconnect(connection);
return 0;
}
我刚试过你的程序,即使我没有指定颜色图,它也会失败,所以我认为颜色图与你的问题无关。
我不太确定,但我的猜测是默认边框像素图是 XCB_COPY_FROM_PARENT
,并且必须与 window 视觉和深度相匹配。但是您正在设置视觉和深度(与父级不同)。现在,边框视觉效果或深度与 window 的不同,因此您会得到一个 BadMatch。
通过指定边框像素颜色,X 创建了一个具有适当属性的像素图并将其设置为边框像素图,然后一切又恢复正常了。