【问题标题】:Cannot draw polygons using XCB in C无法在 C 中使用 XCB 绘制多边形
【发布时间】:2020-09-17 11:38:35
【问题描述】:

刚开始使用 C 进行 XCB 编程。我编写了这段代码,它将创建一个窗口并绘制一些点和一个矩形:

#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;
}

它已正确编译,运行时没有警告或错误。但是,我只是得到一个没有图形的窗口。我做错了什么?

【问题讨论】:

  • 你得到一个暴露事件吗?
  • 是的,我明白了。程序启动后,每当我调整窗口大小时,都会在终端中打印Expose event called,这表明调用了expose事件。

标签: c xcb


【解决方案1】:

我认为您的xcb_poly_fill_rectangle() 等正在尝试在根窗口上绘图。至少,您将 screen-&gt;root 作为 drawable 参数传递。如果我在这里通过window_id,它对我有用。

我真的不知道为什么 XCB 需要所有这些不同的上下文参数,而且每个参数的确切功能似乎都没有很好的记录。

【讨论】:

  • 您对哪个论点感到困惑? context_id 是图形上下文 ID (GC) 或相当于 windows HDC
  • @user253751 -- 不,我想这很公平。我更习惯于在对象中传递这种上下文信息,或者至少在structs 中传递。一堆数字句柄就是 90 年代。
  • 这是一个网络协议。每次绘制时都会将整个上下文数据发送到服务器吗?
  • @user253751 -- 我有点希望库能够处理这些低级的东西,我只需要处理一个封装了上下文的数据结构。例如,这就是 GTK 的工作原理。我并不是说 XCB 方式是错误的或更糟,只是说我已经养成了在那个级别工作的习惯。
【解决方案2】:

Kevin Boone 是正确的:您正在绘制到根窗口。

我对您的程序进行了以下更改(与 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);

这会导致显示以下窗口内容。您可以看到显示的矩形和单个像素:

请不要接受这个答案,而是接受 Kevin Boone 的答案。我只想添加截图。

【讨论】:

  • 你太慷慨了:)
猜你喜欢
  • 2015-02-05
  • 2016-12-09
  • 2020-04-13
  • 2011-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多