GeezerVison is showing github.com — window.get_wm_name() is empty but not in window.get_property() equivalent · Issue #212 · python-xlib/python-xlib
window.get_wm_name() is empty but not in window.get_property() equivalent #212DescriptionI am trying to interact with chrome browser windows using X11 APIs but python-xlib wrapper always returns empty window names. Here is what xprop shows about chrome windows:
WM_STATE(WM_STATE):
window state: Normal
icon window: 0x0
_NET_WM_DESKTOP(CARDINAL) = 0
_GTK_EDGE_CONSTRAINTS(CARDINAL) = 85
_NET_WM_ALLOWED_ACTIONS(ATOM) = _NET_WM_ACTION_MOVE, _NET_WM_ACTION_RESIZE, _NET_WM_ACTION_FULLSCREEN, _NET_WM_ACTION_MINIMIZE, _NET_WM_ACTION_MAXIMIZE_HORZ, _NET_WM_ACTION_MAXIMIZE_VERT, _NET_WM_ACTION_CHANGE_DESKTOP, _NET_WM_ACTION_CLOSE, _NET_WM_ACTION_ABOVE, _NET_WM_ACTION_BELOW
_NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT
_NET_WM_USER_TIME(CARDINAL) = 19822488
WM_NORMAL_HINTS(WM_SIZE_HINTS):
program specified location: 65, 24
program specified minimum size: 500 by 72
_MOTIF_WM_HINTS(_MOTIF_WM_HINTS) = 0x2, 0x0, 0x0, 0x0, 0x0
WM_NAME(UTF8_STRING) = "New Issue · python-xlib/python-xlib - Google Chrome"
_NET_WM_NAME(UTF8_STRING) = "New Issue · python-xlib/python-xlib - Google Chrome"
XdndAware(ATOM) = BITMAP
_NET_WM_BYPASS_COMPOSITOR(CARDINAL) = 2
_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED(CARDINAL) = 1
WM_WINDOW_ROLE(STRING) = "browser"
WM_CLASS(STRING) = "google-chrome", "Google-chrome"
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
_NET_WM_PID(CARDINAL) = 5700
WM_CLIENT_MACHINE(STRING) = "ubuntu"
WM_PROTOCOLS(ATOM): protocols WM_DELETE_WINDOW, _NET_WM_PING, _NET_WM_SYNC_REQUEST
there WM_NAME property is not empty, so I tried the following which worked:
window.get_property(display.get_atom("WM_NAME"), display.get_atom("UTF8_STRING"), 0, 1024)
I guess xlib is using wrong property type, it must be UTF8_STRING, otherwise empty string is returned.
I am running python-xlib 0.31 on Python 3.8 on Ubuntu 20.04. Reacted by Andre Vallestero and Steven Xu Activitybenoit-pierre commented on Dec 2, 2021 I can reproduce with Chromium.
From looking at XGetWindowProperty's documentation:
If the specified property exists but its type does not match the specified
type, XGetWindowProperty returns the actual property type to actual_type_return,
the actual property format (never zero) to actual_format_return, and the property
length in bytes (even if the actual_format_return is 16 or 32) to bytes_after_return.
It also ignores the delete argument. The nitems_return argument is empty.
…it looks like our implementation of Window.get_full_property is wrong and should
call get_property again with the correct type if the previous attempt returned
a different type than asked for and bytes_after is not zero:
Xlib/xobject/drawable.py | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git i/Xlib/xobject/drawable.py w/Xlib/xobject/drawable.py
index c36a973..f79a7dc 100644
--- i/Xlib/xobject/drawable.py
+++ w/Xlib/xobject/drawable.py
@@ -470,17 +470,21 @@ def get_property(self, property, property_type, offset, length, delete = 0):
def get_full_property(self, property, property_type, sizehint = 10):
prop = self.get_property(property, property_type, 0, sizehint)
- if prop:
- val = prop.value
- if prop.bytes_after:
- prop = self.get_property(property, property_type, sizehint,
- prop.bytes_after // 4 + 1)
- val = val + prop.value
-
- prop.value = val
+ if not prop:
+ return None
+ if not prop.bytes_after:
return prop
+ val = prop.value
+ if prop.property_type == property_type:
+ offset = sizehint
+ sizehint = prop.bytes_after // 4 + 1
else:
- return None
+ assert not val
+ property_type = prop.property_type
+ offset = 0
+ prop = self.get_property(property, property_type, offset, sizehint)
+ prop.value = val + prop.value
+ return prop
def get_full_text_property(self, property, property_type=X.AnyPropertyType, sizehint = 10):
prop = self.get_full_property(property, property_type,Reacted by Heraldo, Jessica and Andre Vallestero MestreLion commented on Jan 23, 2023 If the property_type parameter in Python is meant as a sort of "filter" to specify what the returned property should be, then I believe repeating the request with a different type would be the wrong approach to the problem.
A better fix, IMHO, is to drop the Xatom.STRING argument when calling get_full_property in Window.get_wm_name() (and similar methods such as get_wm_icon_name). I wonder why it is using it instead of the default X.AnyPropertyType. MestreLion commented on Jan 23, 2023 get_full_property() should not change a caller's argument: in case of an inconsistency between the requested and the obtained type it should either raise an exception or just return the obtained property as-is (bytes_left included) and let the caller handle the inconsistency. Otherwise, what's the point of the property_type parameter?
MestreLion commented on Jan 23, 2023 In other words: the meaning (and usefulness) of property_type in both Window.get_property() and Window.get_full_property() is debatable (IMHO both should be hard-coded to X.AnyPropertyType (= 0)), but in this case the bug is in Windows.get_wm_name() and friends for specifying the wrong type (or for specifying a type at all).
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|