Xlib XGetWindowProperty 返回零项
Xlib XGetWindowProperty Zero items returned
我在读取某些 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);
}
收到ClientMessage后调用get_property_value函数,这是处理事件的代码:
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;
但是当我读取属性时,有时我会得到一个没有值的 属性,这可能吗?
问题主要是当我尝试在 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-------
我还没有足够的代表发表评论(我对此有点陌生),但我自己已经花了一些时间研究 Xlib,我会尝试看看是否可以提供帮助。我写了一个包含你的代码的小程序:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
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,actual_type_return));
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 %s\n", XGetAtomName(display,*(Atom*)prop_to_return), XGetAtomName(display,((Atom*)prop_to_return)[1]));
}
printf("-----END OF GET_PROPERTY_VALUE-------\n");
return (0);
}
int main(int argc, char** argv) {
Display* dsp = XOpenDisplay(NULL);
unsigned long nitems_return;
unsigned char* prop_return;
get_property_value(dsp, (Window)atoi(argv[1]), "_NET_WM_STATE", 100000, &nitems_return, &prop_return);
return 0;
}
我确实更改了一些输出内容:我更改了 "Actual type" 输出以打印 actual_type_return
而不是 property
的名称(因为这似乎是一个错字)并且我将 "prop return" 输出更改为打印原子名称而不是二进制数据。无论如何,我将此版本的代码指向我计算机上的一个 Firefox 运行 实例,这就是我得到的:
$ ./xproptest 60817587
-----GET_PROPERTY_VALUE-------
Propname: _NET_WM_STATE
Actual Type: ATOM
Property format: 32
Byte after return: 0
nitems return: 2
prop return: _NET_WM_STATE_MAXIMIZED_VERT _NET_WM_STATE_MAXIMIZED_HORZ
-----END OF GET_PROPERTY_VALUE-------
所以,好消息是您的代码实际上在我的机器上运行完美。不过,我不确定为什么它对您不起作用。当然,上面的输出是Firefox最大化时的输出;如果不是,输出是这样的:
$ ./xproptest 60817587
-----GET_PROPERTY_VALUE-------
Propname: _NET_WM_STATE
Actual Type: ATOM
Property format: 32
Byte after return: 0
nitems return: 0
prop return:
…然后关于我如何读取无效原子的几个错误,因为上面的代码只是假设有两个。这是当 属性 为空且没有值时的正确输出;但是,请注意我的 属性 格式是 32 而你的是 0。从阅读手册来看,这似乎是成功调用 XGetWindowProperty
获得 0 属性 格式的唯一方法是在不存在的 属性 上调用它。不过,我不确定为什么你的 Firefox 没有设置 _NET_WM_STATE
。
总而言之,我的猜测是您的代码实际上可以完美运行(除了其中一个输出中的拼写错误),但由于某种原因,您尝试阅读的 属性 不存在在 window 你正试图从中读取它。如果我是对的,如果您在阅读 属性 后检查 actual_type_return
的值,您应该会发现它是 None
。此外,您应该能够(如果您还没有)打印您试图在代码中读取的 window id (window
) 并使用 xwininfo
和 xprop
与 -id
标志,以检查您正在阅读的 window 是否是您认为的那个,以及它是否实际上具有您正在阅读的 属性试图阅读。希望这能帮助您找出实际问题所在。
我在读取某些 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);
}
收到ClientMessage后调用get_property_value函数,这是处理事件的代码:
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;
但是当我读取属性时,有时我会得到一个没有值的 属性,这可能吗? 问题主要是当我尝试在 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-------
我还没有足够的代表发表评论(我对此有点陌生),但我自己已经花了一些时间研究 Xlib,我会尝试看看是否可以提供帮助。我写了一个包含你的代码的小程序:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
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,actual_type_return));
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 %s\n", XGetAtomName(display,*(Atom*)prop_to_return), XGetAtomName(display,((Atom*)prop_to_return)[1]));
}
printf("-----END OF GET_PROPERTY_VALUE-------\n");
return (0);
}
int main(int argc, char** argv) {
Display* dsp = XOpenDisplay(NULL);
unsigned long nitems_return;
unsigned char* prop_return;
get_property_value(dsp, (Window)atoi(argv[1]), "_NET_WM_STATE", 100000, &nitems_return, &prop_return);
return 0;
}
我确实更改了一些输出内容:我更改了 "Actual type" 输出以打印 actual_type_return
而不是 property
的名称(因为这似乎是一个错字)并且我将 "prop return" 输出更改为打印原子名称而不是二进制数据。无论如何,我将此版本的代码指向我计算机上的一个 Firefox 运行 实例,这就是我得到的:
$ ./xproptest 60817587
-----GET_PROPERTY_VALUE-------
Propname: _NET_WM_STATE
Actual Type: ATOM
Property format: 32
Byte after return: 0
nitems return: 2
prop return: _NET_WM_STATE_MAXIMIZED_VERT _NET_WM_STATE_MAXIMIZED_HORZ
-----END OF GET_PROPERTY_VALUE-------
所以,好消息是您的代码实际上在我的机器上运行完美。不过,我不确定为什么它对您不起作用。当然,上面的输出是Firefox最大化时的输出;如果不是,输出是这样的:
$ ./xproptest 60817587
-----GET_PROPERTY_VALUE-------
Propname: _NET_WM_STATE
Actual Type: ATOM
Property format: 32
Byte after return: 0
nitems return: 0
prop return:
…然后关于我如何读取无效原子的几个错误,因为上面的代码只是假设有两个。这是当 属性 为空且没有值时的正确输出;但是,请注意我的 属性 格式是 32 而你的是 0。从阅读手册来看,这似乎是成功调用 XGetWindowProperty
获得 0 属性 格式的唯一方法是在不存在的 属性 上调用它。不过,我不确定为什么你的 Firefox 没有设置 _NET_WM_STATE
。
总而言之,我的猜测是您的代码实际上可以完美运行(除了其中一个输出中的拼写错误),但由于某种原因,您尝试阅读的 属性 不存在在 window 你正试图从中读取它。如果我是对的,如果您在阅读 属性 后检查 actual_type_return
的值,您应该会发现它是 None
。此外,您应该能够(如果您还没有)打印您试图在代码中读取的 window id (window
) 并使用 xwininfo
和 xprop
与 -id
标志,以检查您正在阅读的 window 是否是您认为的那个,以及它是否实际上具有您正在阅读的 属性试图阅读。希望这能帮助您找出实际问题所在。