C语言 X11中获取窗口属性长度的惯用方法?

oxcyiej7  于 2023-04-11  发布在  其他
关注(0)|答案(2)|浏览(188)

我昨天刚开始学习X11,我很难找到有关它的信息。
我希望能够检索X11窗口的UTF-8 title _NET_WM_NAME。问题是您应该使用length参数来调用它。我目前的解决方案包括首先使用带有0 length参数的XGetWindowProperty检索字符串的长度,然后使用lengthbytes_after_return信息再次调用XGetWindowProperty
问题是这涉及到两个分配和释放。我不是一个超级高级的程序员,但这可能不太好,对吧?虽然在实践中,对于一些小而不常见的事情,如获得窗口标题,两个分配可能不会有太大的区别,我到处都听到不必要的分配和释放仍然应该避免。
下面是我的代码:

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

3pvhb19x

3pvhb19x1#

如果不可避免地需要多次分配,那么这并没有什么错,而且对于更大的数据量,您可能需要这样做。请求合理的字节数,并在必要时使用循环来处理传入的数据,利用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;
}

当然,如果您愿意,您可以请求更多的数据,根据需要调整bytesAfter,这样做确实更有效,因为需要更少的请求/响应周期,更不用说分配了。这就是为什么你可能仍然需要一个循环的原因。如果你使用XConvertSelection并且需要处理 INCR 属性,因为它意味着有一个循环。显示服务器需要发送大量数据。

csbfibhn

csbfibhn2#

我自己也遇到了这个问题,最终使用了XGetTextProperty(更干净可靠)。

int get_window_title(Window window, XTextProperty *wm_name)
{
    int found = XGetTextProperty(local.dpy, window, wm_name, local.netatoms[NET_WM_NAME]) &&
                wm_name->nitems;
    return found ? found : XGetTextProperty(local.dpy, window, wm_name, local.wmatoms[WM_NAME]);
}

https://github.com/lycuid/cluless/blob/e00bd1e3/src/cluless/core.c#L142

相关问题