为什么在 `XLookupColor()` 成功的情况下,`xcb_lookup_color()` 会失败?

编程语言 2026-07-09

我用这个代码来比较 XLookupColor()xcb_lookup_color() 的差异:

#include <X11/Xlib.h>
#include <string.h>
#include <xcb/xcb.h>
#include <stdio.h>

int main(void)
{
    const char *s = "#ff0000";

    Display *display = XOpenDisplay(NULL);
    XColor exact, screen_c;
    printf("%d\n", XLookupColor(display, XDefaultColormap(display, XDefaultScreen(display)), s, &exact, &screen_c));
    printf("rgb = %ld %ld %ld\n", exact.red, exact.green, exact.blue);


    int screen_index;
    xcb_connection_t *c = xcb_connect(NULL, &screen_index);
    const xcb_setup_t *setup = xcb_get_setup(c);;

    xcb_screen_t *screen;
    xcb_screen_iterator_t iterator;
    int i = screen_index;
    for (iterator = xcb_setup_roots_iterator(setup);
            iterator.rem > 0; i--, xcb_screen_next(&iterator)) {
        if (i == 0) {
            screen = iterator.data;
            break;
        }
    }
    xcb_lookup_color_cookie_t cookie = xcb_lookup_color(c, screen->default_colormap, strlen(s), s);
    xcb_generic_error_t *error;
    xcb_lookup_color_reply_t *reply = xcb_lookup_color_reply(c, cookie, &error);
    if (reply == NULL) {
        printf("error: %u\n", error->error_code);
    }
    return 0;
}

运行:cc a.c -lX11 -lxcb -o a.out ; ./a.outXLookupColor() 成功,我得到了正确的颜色。 xcb_lookup_color() 另一方面失败——也就是返回是 NULL,并带有错误15(对应名称错误)。当我把颜色字符串改成 "red" 时就能工作。这让我觉得 XLookupColor()xcb_lookup_color() 做了更多工作。

手册页中关于 XLookupColor() 的说明指出,不鼓励继续使用 #... 语法,这意味着它们可能在 xcb 中放弃了对它的支持。

我需要手动处理基本的 #... 情况吗?

解决方案

这让我觉得XLookupColor() 的工作量比xcb_lookup_color() 多。

没错,你说对了。

查看源代码,XLookupColor() 首先做一些本地解析:https://github.com/mirror/libX11/blob/ff8706a5eae25b8bafce300527079f68a201d27f/src/LookupCol.c#L59

这似乎在本地处理 #(但我只找到了这一段代码,尚未完整跟踪整个流程):https://github.com/mirror/libX11/blob/ff8706a5eae25b8bafce300527079f68a201d27f/src/xcms/cmsColNm.c#L219

只有当这段解析失败,XLookupColor() 才会去询问X11服务器:https://github.com/mirror/libX11/blob/ff8706a5eae25b8bafce300527079f68a201d27f/src/LookupCol.c#L83

XCB在本地不做任何处理。它只是一个协议绑定。libxcb不会做你没有显式让它做的花哨事。 关于 xcb_lookup_color() 的代码是由代码生成器生成的,因此我无法轻易链接到它,但它确实只是将提供的参数序列化并发送给X11服务器:

xcb_lookup_color_cookie_t
xcb_lookup_color (xcb_connection_t *c,
                  xcb_colormap_t    cmap,
                  uint16_t          name_len,
                  const char       *name)
{
    static const xcb_protocol_request_t xcb_req = {
        .count = 4,
        .ext = 0,
        .opcode = XCB_LOOKUP_COLOR,
        .isvoid = 0
    };

    struct iovec xcb_parts[6];
    xcb_lookup_color_cookie_t xcb_ret;
    xcb_lookup_color_request_t xcb_out;

    xcb_out.pad0 = 0;
    xcb_out.cmap = cmap;
    xcb_out.name_len = name_len;
    memset(xcb_out.pad1, 0, 2);

    xcb_parts[2].iov_base = (char *) &xcb_out;
    xcb_parts[2].iov_len = sizeof(xcb_out);
    xcb_parts[3].iov_base = 0;
    xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
    /* char name */
    xcb_parts[4].iov_base = (char *) name;
    xcb_parts[4].iov_len = name_len * sizeof(char);
    xcb_parts[5].iov_base = 0;
    xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;

    xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
    return xcb_ret;
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章