Xlib XGetWindowProperty 返回零项

Iva*_*van 4 c x11 xlib

我在读取某些 XWindow ICCCM 属性时遇到问题。

问题实际上是当我尝试读取 _NET_WM_STATUS 属性时。我正在使用的功能是:

int get_property_value(Display* display, Window window,char *propname, long max_length,
           unsigned long *nitems_return, unsigned char **prop_return){
    int result;
    Atom property;
    Atom actual_type_return;
    int actual_format_return;
    unsigned long bytes_after_return;
    unsigned char* prop_to_return;
    unsigned long n_items;
    printf("-----GET_PROPERTY_VALUE-------\n");
    printf("\tPropname: %s\n", propname);
    property = XInternAtom(display, propname, True);
    if(property==None){
      printf("\tWrong Atom\n");
      return;
    }

    result = XGetWindowProperty(display, window, property, 0,   /* long_offset */
            (~0L),  /* long_length */
            False,  /* delete */
            AnyPropertyType,    /* req_type */
            &actual_type_return,
            &actual_format_return,
            &n_items, &bytes_after_return, &prop_to_return);
    if (result != Success){
        printf("\tXGetWindowProperty failed\n");
        return (-1);
    }   else {
        printf("\tActual Type: %s\n", XGetAtomName(display,property));
        printf("\tProperty format: %d\n", actual_format_return);
        //printf("Actual property return: %s\n", XGetAtomName(display,actual_type_return));
        printf("\tByte after return: %ld\n", bytes_after_return);
        printf("\tnitems return: %d\n", n_items);
        printf("\tprop return: %s\n", prop_to_return);
    }
    printf("-----END OF GET_PROPERTY_VALUE-------\n");

    return (0);
}
Run Code Online (Sandbox Code Playgroud)

get_property_value 函数在收到 ClientMessage 后被调用,这是处理事件的代码片段:

    case ClientMessage:
        printf("ClientMessage\n");
        printf("Message: %s\n", XGetAtomName(display,local_event.xclient.message_type));
        unsigned long nitems_return;
        unsigned char *prop_return;
        get_property_value(display, local_event.xclient.window, XGetAtomName(display,local_event.xclient.message_type), 256, &nitems_return, (unsigned char **)&prop_return);
    break;
Run Code Online (Sandbox Code Playgroud)

但是,当我读取属性时,有时我会得到一个没有值的属性,这可能吗?问题主要是当我尝试在 ClientMessage 事件中读取从 Firefox 发送的 AtomProperties (我尝试读取 _NET_WM_STATE 值)时。

正如您从输出中看到的,属性名称已正确读取,但似乎它不包含任何项目。

ClientMessage
Message: _NET_WM_STATE
-----GET_PROPERTY_VALUE-------
    Propname: _NET_WM_STATE
    Actual Type: _NET_WM_STATE
    Property format: 0
    Byte after return: 0
    nitems return: 0
    prop return: (null)
-----END OF GET_PROPERTY_VALUE-------
Run Code Online (Sandbox Code Playgroud)

小智 5

我还没有足够的代表来发表评论(我对此有点陌生),但我自己花了一些时间与 Xlib 搏斗,我会尝试看看是否可以提供帮助。我写了一个包含您的代码的小程序:

\n\n
#include <X11/Xlib.h>\n#include <stdlib.h>\n#include <stdio.h>\n\nint get_property_value(Display* display, Window window,char *propname, long max_length,\n           unsigned long *nitems_return, unsigned char **prop_return){\n    int result;\n    Atom property;\n    Atom actual_type_return;\n    int actual_format_return;\n    unsigned long bytes_after_return;\n    unsigned char* prop_to_return;\n    unsigned long n_items;\n    printf("-----GET_PROPERTY_VALUE-------\\n");\n    printf("\\tPropname: %s\\n", propname);\n    property = XInternAtom(display, propname, True);\n    if(property==None){\n      printf("\\tWrong Atom\\n");\n      return;\n    }\n\n    result = XGetWindowProperty(display, window, property, 0,   /* long_offset */\n            (~0L),  /* long_length */\n            False,  /* delete */\n            AnyPropertyType,    /* req_type */\n            &actual_type_return,\n            &actual_format_return,\n            &n_items, &bytes_after_return, &prop_to_return);\n    if (result != Success){\n        printf("\\tXGetWindowProperty failed\\n");\n        return (-1);\n    }   else {\n        printf("\\tActual Type: %s\\n", XGetAtomName(display,actual_type_return));\n        printf("\\tProperty format: %d\\n", actual_format_return);\n        //printf("Actual property return: %s\\n", XGetAtomName(display,actual_type_return));\n        printf("\\tByte after return: %ld\\n", bytes_after_return);\n        printf("\\tnitems return: %d\\n", n_items);\n        printf("\\tprop return: %s %s\\n", XGetAtomName(display,*(Atom*)prop_to_return), XGetAtomName(display,((Atom*)prop_to_return)[1]));\n    }\n    printf("-----END OF GET_PROPERTY_VALUE-------\\n");\n\n    return (0);\n}\n\nint main(int argc, char** argv) {\n    Display* dsp = XOpenDisplay(NULL);\n    unsigned long nitems_return;\n    unsigned char* prop_return;\n    get_property_value(dsp, (Window)atoi(argv[1]), "_NET_WM_STATE", 100000, &nitems_return, &prop_return);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我确实更改了一些输出内容:我更改了“实际类型”输出以打印名称actual_type_return而不是property(因为这似乎是一个拼写错误),并且我更改了“prop return”输出以打印原子名称而不是二进制数据。无论如何,我将这个版本的代码指向我计算机上运行的 Firefox 实例,这就是我得到的结果:

\n\n
$ ./xproptest 60817587\n-----GET_PROPERTY_VALUE-------\n    Propname: _NET_WM_STATE\n    Actual Type: ATOM\n    Property format: 32\n    Byte after return: 0\n    nitems return: 2\n    prop return: _NET_WM_STATE_MAXIMIZED_VERT _NET_WM_STATE_MAXIMIZED_HORZ\n-----END OF GET_PROPERTY_VALUE-------\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以,好消息是您的代码实际上在我的机器上完美运行。但我不确定为什么它对你不起作用。当然,上面的输出是 Firefox 最大化时的;如果不是,则输出如下:

\n\n
$ ./xproptest 60817587\n-----GET_PROPERTY_VALUE-------\n    Propname: _NET_WM_STATE\n    Actual Type: ATOM\n    Property format: 32\n    Byte after return: 0\n    nitems return: 0\n    prop return:\n
Run Code Online (Sandbox Code Playgroud)\n\n

\xe2\x80\xa6 然后是关于我如何读取无效原子的几个错误,因为上面的代码只是假设有两个。这是当属性为空并且没有值时的正确输出;但是,请注意我的属性格式是 32,而你的属性格式是 0。通过阅读手册,看​​起来从成功调用中获取 0 属性格式的唯一方法XGetWindowProperty是在不存在的属性上调用它。不过,我不确定为什么你的 Firefox 没有_NET_WM_STATE设置。

\n\n

总之,我的猜测是,您的代码实际上功能完美(除了其中一个输出上的拼写错误),但由于某种原因,您尝试读取的属性在您所在的窗口上不存在试图从中读取它。如果我是对的,如果您actual_type_return在阅读该属性后检查 的值,您应该会发现它是None。此外,您应该能够(如果您还没有)打印您尝试在代码中读取的窗口 ID ( window) 并使用xwininfoxprop-id标志来检查您正在使用的窗口是否是读取的是您认为的那个,以及它是否确实具有您要读取的属性。希望这能帮助您找出真正的问题是什么。

\n