Skip to content

Commit 4e6f6db

Browse files
committed
Merge pull request BurntSushi#1 from whitelynx/master
Several minor fixes to xpybutil
2 parents 6f93ed4 + c97fd14 commit 4e6f6db

File tree

4 files changed

+130
-118
lines changed

4 files changed

+130
-118
lines changed

README

Lines changed: 56 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
Introduction
22
============
3-
xpybutil is an abstraction over the X Python Binding (xpyb - the Python version
4-
of XCB). It exists because xpyb is a very low level library that communicates
3+
xpybutil is an abstraction over the X Python Binding (xpyb - the Python version
4+
of XCB). It exists because xpyb is a very low level library that communicates
55
with X.
66

7-
The most mature portions of xpybutil are the ICCCM and EWMH modules. Each
8-
implement their respective specifications of the same name. The EWMH module
9-
also implements the '_NET_WM_WINDOW_OPACITY' and '_NET_VISIBLE_DESKTOPS'
10-
non-standard features. The former is widely used by compositing managers and
11-
other utilities (i.e., xcompmgr and transset-df) while the latter is used by my
7+
The most mature portions of xpybutil are the ICCCM and EWMH modules. Each
8+
implement their respective specifications of the same name. The EWMH module
9+
also implements the '_NET_WM_WINDOW_OPACITY' and '_NET_VISIBLE_DESKTOPS'
10+
non-standard features. The former is widely used by compositing managers and
11+
other utilities (i.e., xcompmgr and transset-df) while the latter is used by my
1212
fork of Openbox called Openbox Multihead.
1313

1414

@@ -19,15 +19,15 @@ The API docs can be found here: http://burntsushi.net/X11/xpybutil/docs/
1919

2020
Examples
2121
========
22-
There are a few examples included in the 'examples' directory of the source of
23-
xpybutil. You could also look at my 'window-marker' or 'pytyle3' utilities. The
24-
former is a small script but the latter is on the order of ~1000 lines and
25-
encompasses a wide variety of use cases of xpybutil. (And still yet, other use
22+
There are a few examples included in the 'examples' directory of the source of
23+
xpybutil. You could also look at my 'window-marker' or 'pytyle3' utilities. The
24+
former is a small script but the latter is on the order of ~1000 lines and
25+
encompasses a wide variety of use cases of xpybutil. (And still yet, other use
2626
cases are probably more appropriate only for window manager development.)
2727

28-
Another program that uses xpybutil is 'pager-multihead'. I would advise not
29-
looking to it for inspiration, as it mixes xpybutil and GTK. (Namely, it uses
30-
GTK's event dispatcher, but interacts with the window manager mostly using
28+
Another program that uses xpybutil is 'pager-multihead'. I would advise not
29+
looking to it for inspiration, as it mixes xpybutil and GTK. (Namely, it uses
30+
GTK's event dispatcher, but interacts with the window manager mostly using
3131
xpybutil.)
3232

3333

@@ -46,7 +46,7 @@ event.py - A module that can send client events to windows. It also allows
4646

4747
icccm.py - A module that implements most of the ICCCM spec.
4848

49-
image.py - An incomplete and haphazard collection of functions that can
49+
image.py - An incomplete and haphazard collection of functions that can
5050
bridge a gap between PIL and drawing images with X.
5151

5252
keybind.py - A set of functions devoted to binding key presses and registering
@@ -58,35 +58,35 @@ keysymdef.py - The sole purpose of this module is to provide a mapping from
5858
by the user). This should probably never be used directly. It is
5959
used by the keysym module.
6060

61-
motif.py - Implements a subset of the Motif spec. This module exists
61+
motif.py - Implements a subset of the Motif spec. This module exists
6262
because some window managers still use this as the only way of
6363
toggling window decorations via events.
6464

6565
mousebind.py - Similar to keybind.py, but for mice.
6666

67-
rect.py - A few utility functions that do math associated with X style
67+
rect.py - A few utility functions that do math associated with X style
6868
rectangles. (i.e., a 4-tuple of (top_left_x, top_left_y, width,
6969
height).) It can also calculate monitor rectangles after
7070
accounting for struts.
7171

72-
render.py - A nearly exact port of the module by the same name from
72+
render.py - A nearly exact port of the module by the same name from
7373
xcb-util. I used it once to help with a compositing manager that
7474
I wrote with xpyb.
7575

76-
util.py - A vast assortment of utility functions. The ones of interest to
76+
util.py - A vast assortment of utility functions. The ones of interest to
7777
you are probably 'get_atom' and 'get_atom_name'. The rest are
7878
heavily used throughout the rest of xpybutil.
7979

80-
window.py - A few utility functions related to client windows. In
80+
window.py - A few utility functions related to client windows. In
8181
particular, getting an accurate geometry of a client window
8282
including the decorations (this can vary with the window
8383
manager). Also, a functon to move and/or resize a window
8484
accurately by the top-left corner. (Also can change based on
85-
the currently running window manager.)
85+
the currently running window manager.)
8686

87-
This module also contains a function 'listen' that must be used
88-
in order to receive certain events from a window. For example,
89-
if you wanted to run 'func' whenever a property on the root
87+
This module also contains a function 'listen' that must be used
88+
in order to receive certain events from a window. For example,
89+
if you wanted to run 'func' whenever a property on the root
9090
window changed, you could do something like:
9191

9292
import xpybutil
@@ -101,10 +101,10 @@ window.py - A few utility functions related to client windows. In
101101
active_window_id = ewmh.get_active_window().reply()
102102

103103
window.listen(xpybutil.root, 'PropertyChange')
104-
event.connect('PropertyNotify', xpybutil.root, func)
104+
event.connect('PropertyNotify', xpybutil.root, func)
105105

106106
The idea here is to tell X that you want events that fall under
107-
the 'PropertyChange' category. Then you bind 'func' to the
107+
the 'PropertyChange' category. Then you bind 'func' to the
108108
particular event 'PropertyNotify'.
109109

110110
xinerama.py - A couple of functions that support retrieving information about
@@ -120,14 +120,14 @@ xinerama.py - A couple of functions that support retrieving information about
120120
Unusable modules
121121
================
122122
font.py is pretty inadequate. Mostly because if you find
123-
yourself wanting to use font.py, you're probably doing something wrong.
123+
yourself wanting to use font.py, you're probably doing something wrong.
124124
(i.e., use pycairo or PIL.)
125125

126126

127127
EWMH and ICCCM
128128
==============
129-
xpybutil's primary purpose was to make accessing ICCCM and EWMH related
130-
information extremely easy. This can be done by using the ewmh or icccm
129+
xpybutil's primary purpose was to make accessing ICCCM and EWMH related
130+
information extremely easy. This can be done by using the ewmh or icccm
131131
modules. Here's a quick example (assuming xpybutil is installed):
132132

133133
import xpybutil.ewmh as ewmh
@@ -137,56 +137,55 @@ modules. Here's a quick example (assuming xpybutil is installed):
137137

138138
print names.get(current_desktop, current_desktop)
139139

140-
This imports the ewmh module (and by extension, connects to the X server) and
141-
fetches a list of the current desktop names and the current desktop index
142-
(starting from 0). Since not every desktop must be named, the desktop index is
140+
This imports the ewmh module (and by extension, connects to the X server) and
141+
fetches a list of the current desktop names and the current desktop index
142+
(starting from 0). Since not every desktop must be named, the desktop index is
143143
printed if it has no name.
144144

145-
Note that the functions in the ewmh and icccm module return *cookies*. In order
146-
to pull a response from the X server, call the 'reply()' method on a cookie
147-
object. To force a response sent to the X server, call the 'check()' method on
145+
Note that the functions in the ewmh and icccm module return *cookies*. In order
146+
to pull a response from the X server, call the 'reply()' method on a cookie
147+
object. To force a response sent to the X server, call the 'check()' method on
148148
the corresponding cookie.
149149

150-
Much of the EWMH and ICCCM modules encapsulate packing data from convenient
151-
Python data types into C structs (using the 'struct' Python module). For
152-
example, if one wants to fetch the partial struts set by some window with
150+
Much of the EWMH and ICCCM modules encapsulate packing data from convenient
151+
Python data types into C structs (using the 'struct' Python module). For
152+
example, if one wants to fetch the partial struts set by some window with
153153
identifier ID, you could do:
154154

155155
import xpybutil.ewmh as ewmh
156156

157157
print ewmh.get_wm_strut_partial(ID).reply()
158158

159-
Which outputs a dictionary with 12 entries, where each corresponds to a value
159+
Which outputs a dictionary with 12 entries, where each corresponds to a value
160160
in the partial strut. (i.e., 'left', 'top_end_x', 'right_start_y', etc...).
161161

162-
In general, particularly with the EWMH module, the ewmh module is very nearly
163-
representative of the spec itself. Functions that get property values start
164-
with 'get_', functions that set property values start with 'set_', and
165-
functions that send an event to a client (which typically requests the window
162+
In general, particularly with the EWMH module, the ewmh module is very nearly
163+
representative of the spec itself. Functions that get property values start
164+
with 'get_', functions that set property values start with 'set_', and
165+
functions that send an event to a client (which typically requests the window
166166
manager to DO something) start with 'request_'.
167167

168-
If a request has no reply (typically the 'set_' functions), then the
169-
default is to call it 'unchecked'. If you want to check the result (and force
168+
If a request has no reply (typically the 'set_' functions), then the
169+
default is to call it 'unchecked'. If you want to check the result (and force
170170
retrieval), then use the '_checked' variant.
171171

172-
The reverse goes for the 'get_' functions. By default, they are checked, but
172+
The reverse goes for the 'get_' functions. By default, they are checked, but
173173
you can use the '_unchecked' variant too.
174174

175-
Basically, you should probably almost always use the 'checked' variant of
176-
everything. The cases where you don't are when you want to send a whole bunch
177-
of requests to the X server at once. You could use the unchecked invariant, and
178-
after you've initialized all the cookies, calling 'flush' will force
175+
Basically, you should probably almost always use the 'checked' variant of
176+
everything. The cases where you don't are when you want to send a whole bunch
177+
of requests to the X server at once. You could use the unchecked invariant, and
178+
after you've initialized all the cookies, calling 'flush' will force
179179
communication with the X server.
180180

181-
Finally, unless you're writing a window manager or creating a client window
182-
from scratch, you'll almost always want to use the 'get_' and 'request_'
183-
functions. For exampe, if you want to change the current desktop...
181+
Finally, unless you're writing a window manager or creating a client window
182+
from scratch, you'll almost always want to use the 'get_' and 'request_'
183+
functions, not 'set_'. For example, if you want to change the current
184+
desktop...
184185

185-
DON'T DO: ewmh.get_current_desktop_checked(2).check()
186+
DON'T DO: ewmh.set_current_desktop_checked(2).check()
186187

187188
DO: ewmh.request_current_desktop_checked(2).check()
188189

189-
The former will probably not work, but the latter will. Just follow the EWMH
190+
The former will probably not work, but the latter will. Just follow the EWMH
190191
spec :-)
191-
192-

xpybutil/event.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,16 @@ def main():
130130
w = None
131131
if isinstance(e, xproto.MappingNotifyEvent):
132132
w = None
133+
elif isinstance(e, xproto.MapRequestEvent):
134+
# Force all MapRequestEvents to go to the root window so
135+
# a window manager using xpybutil can get them.
136+
w = root
133137
elif hasattr(e, 'window'):
134138
w = e.window
135139
elif hasattr(e, 'event'):
136140
w = e.event
141+
elif hasattr(e, 'owner'):
142+
w = e.owner
137143
elif hasattr(e, 'requestor'):
138144
w = e.requestor
139145

0 commit comments

Comments
 (0)