无法在 C 中使用 XCB 绘制多边形
Cannot draw polygons using XCB in C
刚开始使用 C 进行 XCB 编程。我编写了这段代码,它将创建一个 window 并绘制一些点和一个矩形:
#include <stdlib.h>
#include <stdio.h>
#include <xcb/xcb.h>
int main() {
xcb_connection_t *connection = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(connection)) {
printf("Error setting up connection to X\n");
exit(1);
}
const xcb_setup_t *setup = xcb_get_setup(connection);
xcb_screen_t *screen = xcb_setup_roots_iterator(setup).data;
// Create wndow
xcb_window_t window_id = xcb_generate_id(connection);
uint32_t prop_name = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
uint32_t prop_value[2];
prop_value[0] = screen->white_pixel;
prop_value[1] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_EXPOSURE;
xcb_create_window(connection, screen->root_depth, window_id, screen->root, 100, 100, 500, 400, 1,
XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, prop_name, &prop_value);
xcb_map_window(connection, window_id);
xcb_flush(connection);
uint32_t gc_value_mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
uint32_t gc_value_list[2];
gc_value_list[0] = screen->black_pixel;
gc_value_list[1] = 0;
xcb_drawable_t drawable_window = screen->root;
xcb_gcontext_t context_id = xcb_generate_id(connection);
xcb_void_cookie_t cookie = xcb_create_gc(connection, context_id, drawable_window, gc_value_mask, gc_value_list);
// Create polygons
xcb_point_t points[5] = {{10, 10}, {10, 50}, {40, 70}, {70, 40}, {50, 10}};
xcb_rectangle_t rect = {50, 50, 100, 50};
// Main loop
xcb_generic_event_t *event;
while ((event = xcb_wait_for_event(connection))) {
switch (event->response_type) {
case XCB_KEY_PRESS:
break;
case XCB_BUTTON_PRESS:
break;
case XCB_EXPOSE:
printf("Expose event called\n");
// Draw polygons
xcb_poly_point(connection, XCB_COORD_MODE_ORIGIN, drawable_window, context_id, 4, points);
xcb_poly_fill_rectangle(connection, drawable_window, context_id, 1, &rect);
xcb_flush(connection);
default:
break;
}
free(event);
}
return 0;
}
编译正确,运行时没有警告或错误。但是,我只得到一个没有图形的 window。我做错了什么?
我认为您的 xcb_poly_fill_rectangle()
等正在尝试在根 window 上绘制。至少,您将 screen->root
作为 drawable
参数传递。如果我在这里通过 window_id
,它对我有用。
我真的不确定为什么 XCB 需要所有这些不同的上下文参数,而且每个参数的确切功能似乎都不是 well-documented。
Kevin Boone 是正确的:您绘制到根 window。
我对您的程序进行了以下更改(与 Kevin 建议的相同):
--- t.c.orig 2020-09-18 15:06:38.344441255 +0200
+++ t.c 2020-09-18 15:06:48.104167556 +0200
@@ -26,7 +26,7 @@ int main() {
uint32_t gc_value_list[2];
gc_value_list[0] = screen->black_pixel;
gc_value_list[1] = 0;
- xcb_drawable_t drawable_window = screen->root;
+ xcb_drawable_t drawable_window = window_id;
xcb_gcontext_t context_id = xcb_generate_id(connection);
xcb_void_cookie_t cookie = xcb_create_gc(connection, context_id, drawable_window, gc_value_mask, gc_value_list);
这导致显示以下 window 内容。您可以看到显示的矩形和单个像素:
请不要接受这个答案,而是 Kevin Boone 的答案。我只想添加屏幕截图。
刚开始使用 C 进行 XCB 编程。我编写了这段代码,它将创建一个 window 并绘制一些点和一个矩形:
#include <stdlib.h>
#include <stdio.h>
#include <xcb/xcb.h>
int main() {
xcb_connection_t *connection = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(connection)) {
printf("Error setting up connection to X\n");
exit(1);
}
const xcb_setup_t *setup = xcb_get_setup(connection);
xcb_screen_t *screen = xcb_setup_roots_iterator(setup).data;
// Create wndow
xcb_window_t window_id = xcb_generate_id(connection);
uint32_t prop_name = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
uint32_t prop_value[2];
prop_value[0] = screen->white_pixel;
prop_value[1] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_EXPOSURE;
xcb_create_window(connection, screen->root_depth, window_id, screen->root, 100, 100, 500, 400, 1,
XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, prop_name, &prop_value);
xcb_map_window(connection, window_id);
xcb_flush(connection);
uint32_t gc_value_mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
uint32_t gc_value_list[2];
gc_value_list[0] = screen->black_pixel;
gc_value_list[1] = 0;
xcb_drawable_t drawable_window = screen->root;
xcb_gcontext_t context_id = xcb_generate_id(connection);
xcb_void_cookie_t cookie = xcb_create_gc(connection, context_id, drawable_window, gc_value_mask, gc_value_list);
// Create polygons
xcb_point_t points[5] = {{10, 10}, {10, 50}, {40, 70}, {70, 40}, {50, 10}};
xcb_rectangle_t rect = {50, 50, 100, 50};
// Main loop
xcb_generic_event_t *event;
while ((event = xcb_wait_for_event(connection))) {
switch (event->response_type) {
case XCB_KEY_PRESS:
break;
case XCB_BUTTON_PRESS:
break;
case XCB_EXPOSE:
printf("Expose event called\n");
// Draw polygons
xcb_poly_point(connection, XCB_COORD_MODE_ORIGIN, drawable_window, context_id, 4, points);
xcb_poly_fill_rectangle(connection, drawable_window, context_id, 1, &rect);
xcb_flush(connection);
default:
break;
}
free(event);
}
return 0;
}
编译正确,运行时没有警告或错误。但是,我只得到一个没有图形的 window。我做错了什么?
我认为您的 xcb_poly_fill_rectangle()
等正在尝试在根 window 上绘制。至少,您将 screen->root
作为 drawable
参数传递。如果我在这里通过 window_id
,它对我有用。
我真的不确定为什么 XCB 需要所有这些不同的上下文参数,而且每个参数的确切功能似乎都不是 well-documented。
Kevin Boone 是正确的:您绘制到根 window。
我对您的程序进行了以下更改(与 Kevin 建议的相同):
--- t.c.orig 2020-09-18 15:06:38.344441255 +0200
+++ t.c 2020-09-18 15:06:48.104167556 +0200
@@ -26,7 +26,7 @@ int main() {
uint32_t gc_value_list[2];
gc_value_list[0] = screen->black_pixel;
gc_value_list[1] = 0;
- xcb_drawable_t drawable_window = screen->root;
+ xcb_drawable_t drawable_window = window_id;
xcb_gcontext_t context_id = xcb_generate_id(connection);
xcb_void_cookie_t cookie = xcb_create_gc(connection, context_id, drawable_window, gc_value_mask, gc_value_list);
这导致显示以下 window 内容。您可以看到显示的矩形和单个像素:
请不要接受这个答案,而是 Kevin Boone 的答案。我只想添加屏幕截图。