在X11中获取窗口属性长度的惯用方式?

问题描述 投票:0回答:1

我昨天刚开始学习X11,我很难找到有关它的信息。

我希望能够检索X11窗口的UTF-8标题_NET_WM_NAME。问题是您应该使用length参数来调用它。我当前的解决方案包括首先使用长度参数为0的XGetWindowProperty检索字符串的长度,然后使用XGetWindowPropertybytes_after_return信息再次调用length

问题是,这涉及两个分配和释放。我不是一个超高级的程序员,但这可能不好,对吗?在实践中,虽然为小而不常见的事情(例如获得窗口标题)分配了两次分配可能不会有太大的区别,但我到处都听到应该避免不必要的分配和释放。

这是我的代码:

Atom actualType;
int actualFormat;
unsigned long nItems;
unsigned long bytesAfter;
unsigned char* prop;

XGetWindowProperty(
    display, 
    window,
    _NET_WM_NAME,
    0UL,
    0UL,
    False,
    UTF8_STRING,
    &actualType,
    &actualFormat,
    &nItems,
    &bytesAfter,
    &prop
);

XFree(prop);

XGetWindowProperty(
    display, 
    window,
    _NET_WM_NAME,
    0UL,
    (bytesAfter + 3UL) / 4UL, // Divide by four and round up
    False,
    UTF8_STRING,
    &actualType,
    &actualFormat,
    &nItems,
    &bytesAfter,
    &prop
);

printf("title: %s", prop);

XFree(prop);

有更好的方法吗?

另一种解决方案是每次设置标题时都存储该标题,但是我不确定保存的标题与实际标题是否可能不同步。

感谢ppl <3

c utf-8 x11
1个回答
1
投票

如果不可避免,则多次分配没有错,对于大量数据,您可能仍然需要这样做。请求合理数量的字节,并根据需要使用循环处理传入的数据,利用offset参数指定从何处继续读取。如果4*length大于要返回的数据量,那么它将仅返回必要的数据量,因此您不必担心使用bytesAfter参数计算正确的长度:

Atom actualType;
int actualFormat;
unsigned long nItems;
unsigned long bytesAfter;
unsigned char* prop;

// specify length as number of bytes divided by 4
#define MB (1048576)
long length = (64 * MB) / 4;

printf("title: ");
for (long offset = 0;; offset += length) {

    XGetWindowProperty(
        display,
        window,
        _NET_WM_NAME,
        offset,
        length,
        False,
        UTF8_STRING,
        &actualType,
        &actualFormat,
        &nItems,
        &bytesAfter,
        &prop
    );

    printf("%s", prop);
    XFree(prop);
    if (bytesAfter == 0)
        break;
}

当然,如果需要,您可以请求更多的数据,根据需要根据length调整bytesAfter,并且这样做的确确实有效,因为需要的请求/响应周期更少,无需考虑分配。但是,有时要处理的数据太多,这就是为什么您可能仍需要循环的原因。如果您使用XConvertSelection并需要处理INCR属性,则尤其如此,因为这意味着显示服务器要发送大量数据。

© www.soinside.com 2019 - 2024. All rights reserved.