Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Several minor fixes to xpybutil #1

Merged
merged 10 commits into from

2 participants

@whitelynx
  • Updated keybind to pass the event object to callbacks like mousebind does.
  • Fixes for several functions: set_wm_pid, set_wm_pid_checked, request_desktop_geometry, request_desktop_geometry_checked, and get_keysym
  • Documentation corrections around the reason for using request_* functions instead of set_*.
  • Fixes to event routing for MapRequestEvent and SelectionRequest.

Sorry for the large lump of commits; I had forgotten to do pull requests for these, so they piled up a bit.

@BurntSushi BurntSushi merged commit 4e6f6db into from
@BurntSushi
Owner

Awesome. Thanks for all the fixes :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 21, 2012
  1. @whitelynx
  2. @whitelynx

    A dirty, dirty hack to allow WMs using xpybutil to actually get the M…

    whitelynx authored
    …apRequestEvents they subscribe to.
Commits on May 22, 2012
  1. @whitelynx
Commits on May 27, 2012
  1. @whitelynx

    Added a special case for e.owner to event.main, in order to ensure th…

    whitelynx authored
    …at selection owners get SelectionRequest events when appropriate.
  2. @whitelynx

    Corrected docstring for the 'ewmh' module to contrast 'set_' (instead…

    whitelynx authored
    … of 'get_') with 'request_'.
Commits on May 31, 2012
  1. @whitelynx

    Added the ability for callbacks in key bindings to act the same as ca…

    whitelynx authored
    …llbacks for mouse bindings, actually getting the event object.
    
    Uses a try/except to fall back to the old behavior.
Commits on Dec 31, 2012
  1. @whitelynx
Commits on Jan 15, 2013
  1. @whitelynx

    Updated README to match the ewmh.py docstring change from 96adc52, co…

    whitelynx authored
    …rrected spelling in both, and clarified both.
  2. @whitelynx
  3. @whitelynx
This page is out of date. Refresh to see the latest.
Showing with 130 additions and 118 deletions.
  1. +56 −57 README
  2. +6 −0 xpybutil/event.py
  3. +59 −55 xpybutil/ewmh.py
  4. +9 −6 xpybutil/keybind.py
View
113 README
@@ -1,14 +1,14 @@
Introduction
============
-xpybutil is an abstraction over the X Python Binding (xpyb - the Python version
-of XCB). It exists because xpyb is a very low level library that communicates
+xpybutil is an abstraction over the X Python Binding (xpyb - the Python version
+of XCB). It exists because xpyb is a very low level library that communicates
with X.
-The most mature portions of xpybutil are the ICCCM and EWMH modules. Each
-implement their respective specifications of the same name. The EWMH module
-also implements the '_NET_WM_WINDOW_OPACITY' and '_NET_VISIBLE_DESKTOPS'
-non-standard features. The former is widely used by compositing managers and
-other utilities (i.e., xcompmgr and transset-df) while the latter is used by my
+The most mature portions of xpybutil are the ICCCM and EWMH modules. Each
+implement their respective specifications of the same name. The EWMH module
+also implements the '_NET_WM_WINDOW_OPACITY' and '_NET_VISIBLE_DESKTOPS'
+non-standard features. The former is widely used by compositing managers and
+other utilities (i.e., xcompmgr and transset-df) while the latter is used by my
fork of Openbox called Openbox Multihead.
@@ -19,15 +19,15 @@ The API docs can be found here: http://burntsushi.net/X11/xpybutil/docs/
Examples
========
-There are a few examples included in the 'examples' directory of the source of
-xpybutil. You could also look at my 'window-marker' or 'pytyle3' utilities. The
-former is a small script but the latter is on the order of ~1000 lines and
-encompasses a wide variety of use cases of xpybutil. (And still yet, other use
+There are a few examples included in the 'examples' directory of the source of
+xpybutil. You could also look at my 'window-marker' or 'pytyle3' utilities. The
+former is a small script but the latter is on the order of ~1000 lines and
+encompasses a wide variety of use cases of xpybutil. (And still yet, other use
cases are probably more appropriate only for window manager development.)
-Another program that uses xpybutil is 'pager-multihead'. I would advise not
-looking to it for inspiration, as it mixes xpybutil and GTK. (Namely, it uses
-GTK's event dispatcher, but interacts with the window manager mostly using
+Another program that uses xpybutil is 'pager-multihead'. I would advise not
+looking to it for inspiration, as it mixes xpybutil and GTK. (Namely, it uses
+GTK's event dispatcher, but interacts with the window manager mostly using
xpybutil.)
@@ -46,7 +46,7 @@ event.py - A module that can send client events to windows. It also allows
icccm.py - A module that implements most of the ICCCM spec.
-image.py - An incomplete and haphazard collection of functions that can
+image.py - An incomplete and haphazard collection of functions that can
bridge a gap between PIL and drawing images with X.
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
by the user). This should probably never be used directly. It is
used by the keysym module.
-motif.py - Implements a subset of the Motif spec. This module exists
+motif.py - Implements a subset of the Motif spec. This module exists
because some window managers still use this as the only way of
toggling window decorations via events.
mousebind.py - Similar to keybind.py, but for mice.
-rect.py - A few utility functions that do math associated with X style
+rect.py - A few utility functions that do math associated with X style
rectangles. (i.e., a 4-tuple of (top_left_x, top_left_y, width,
height).) It can also calculate monitor rectangles after
accounting for struts.
-render.py - A nearly exact port of the module by the same name from
+render.py - A nearly exact port of the module by the same name from
xcb-util. I used it once to help with a compositing manager that
I wrote with xpyb.
-util.py - A vast assortment of utility functions. The ones of interest to
+util.py - A vast assortment of utility functions. The ones of interest to
you are probably 'get_atom' and 'get_atom_name'. The rest are
heavily used throughout the rest of xpybutil.
-window.py - A few utility functions related to client windows. In
+window.py - A few utility functions related to client windows. In
particular, getting an accurate geometry of a client window
including the decorations (this can vary with the window
manager). Also, a functon to move and/or resize a window
accurately by the top-left corner. (Also can change based on
- the currently running window manager.)
+ the currently running window manager.)
- This module also contains a function 'listen' that must be used
- in order to receive certain events from a window. For example,
- if you wanted to run 'func' whenever a property on the root
+ This module also contains a function 'listen' that must be used
+ in order to receive certain events from a window. For example,
+ if you wanted to run 'func' whenever a property on the root
window changed, you could do something like:
import xpybutil
@@ -101,10 +101,10 @@ window.py - A few utility functions related to client windows. In
active_window_id = ewmh.get_active_window().reply()
window.listen(xpybutil.root, 'PropertyChange')
- event.connect('PropertyNotify', xpybutil.root, func)
+ event.connect('PropertyNotify', xpybutil.root, func)
The idea here is to tell X that you want events that fall under
- the 'PropertyChange' category. Then you bind 'func' to the
+ the 'PropertyChange' category. Then you bind 'func' to the
particular event 'PropertyNotify'.
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
Unusable modules
================
font.py is pretty inadequate. Mostly because if you find
-yourself wanting to use font.py, you're probably doing something wrong.
+yourself wanting to use font.py, you're probably doing something wrong.
(i.e., use pycairo or PIL.)
EWMH and ICCCM
==============
-xpybutil's primary purpose was to make accessing ICCCM and EWMH related
-information extremely easy. This can be done by using the ewmh or icccm
+xpybutil's primary purpose was to make accessing ICCCM and EWMH related
+information extremely easy. This can be done by using the ewmh or icccm
modules. Here's a quick example (assuming xpybutil is installed):
import xpybutil.ewmh as ewmh
@@ -137,56 +137,55 @@ modules. Here's a quick example (assuming xpybutil is installed):
print names.get(current_desktop, current_desktop)
-This imports the ewmh module (and by extension, connects to the X server) and
-fetches a list of the current desktop names and the current desktop index
-(starting from 0). Since not every desktop must be named, the desktop index is
+This imports the ewmh module (and by extension, connects to the X server) and
+fetches a list of the current desktop names and the current desktop index
+(starting from 0). Since not every desktop must be named, the desktop index is
printed if it has no name.
-Note that the functions in the ewmh and icccm module return *cookies*. In order
-to pull a response from the X server, call the 'reply()' method on a cookie
-object. To force a response sent to the X server, call the 'check()' method on
+Note that the functions in the ewmh and icccm module return *cookies*. In order
+to pull a response from the X server, call the 'reply()' method on a cookie
+object. To force a response sent to the X server, call the 'check()' method on
the corresponding cookie.
-Much of the EWMH and ICCCM modules encapsulate packing data from convenient
-Python data types into C structs (using the 'struct' Python module). For
-example, if one wants to fetch the partial struts set by some window with
+Much of the EWMH and ICCCM modules encapsulate packing data from convenient
+Python data types into C structs (using the 'struct' Python module). For
+example, if one wants to fetch the partial struts set by some window with
identifier ID, you could do:
import xpybutil.ewmh as ewmh
print ewmh.get_wm_strut_partial(ID).reply()
-Which outputs a dictionary with 12 entries, where each corresponds to a value
+Which outputs a dictionary with 12 entries, where each corresponds to a value
in the partial strut. (i.e., 'left', 'top_end_x', 'right_start_y', etc...).
-In general, particularly with the EWMH module, the ewmh module is very nearly
-representative of the spec itself. Functions that get property values start
-with 'get_', functions that set property values start with 'set_', and
-functions that send an event to a client (which typically requests the window
+In general, particularly with the EWMH module, the ewmh module is very nearly
+representative of the spec itself. Functions that get property values start
+with 'get_', functions that set property values start with 'set_', and
+functions that send an event to a client (which typically requests the window
manager to DO something) start with 'request_'.
-If a request has no reply (typically the 'set_' functions), then the
-default is to call it 'unchecked'. If you want to check the result (and force
+If a request has no reply (typically the 'set_' functions), then the
+default is to call it 'unchecked'. If you want to check the result (and force
retrieval), then use the '_checked' variant.
-The reverse goes for the 'get_' functions. By default, they are checked, but
+The reverse goes for the 'get_' functions. By default, they are checked, but
you can use the '_unchecked' variant too.
-Basically, you should probably almost always use the 'checked' variant of
-everything. The cases where you don't are when you want to send a whole bunch
-of requests to the X server at once. You could use the unchecked invariant, and
-after you've initialized all the cookies, calling 'flush' will force
+Basically, you should probably almost always use the 'checked' variant of
+everything. The cases where you don't are when you want to send a whole bunch
+of requests to the X server at once. You could use the unchecked invariant, and
+after you've initialized all the cookies, calling 'flush' will force
communication with the X server.
-Finally, unless you're writing a window manager or creating a client window
-from scratch, you'll almost always want to use the 'get_' and 'request_'
-functions. For exampe, if you want to change the current desktop...
+Finally, unless you're writing a window manager or creating a client window
+from scratch, you'll almost always want to use the 'get_' and 'request_'
+functions, not 'set_'. For example, if you want to change the current
+desktop...
- DON'T DO: ewmh.get_current_desktop_checked(2).check()
+ DON'T DO: ewmh.set_current_desktop_checked(2).check()
DO: ewmh.request_current_desktop_checked(2).check()
-The former will probably not work, but the latter will. Just follow the EWMH
+The former will probably not work, but the latter will. Just follow the EWMH
spec :-)
-
-
View
6 xpybutil/event.py
@@ -130,10 +130,16 @@ def main():
w = None
if isinstance(e, xproto.MappingNotifyEvent):
w = None
+ elif isinstance(e, xproto.MapRequestEvent):
+ # Force all MapRequestEvents to go to the root window so
+ # a window manager using xpybutil can get them.
+ w = root
elif hasattr(e, 'window'):
w = e.window
elif hasattr(e, 'event'):
w = e.event
+ elif hasattr(e, 'owner'):
+ w = e.owner
elif hasattr(e, 'requestor'):
w = e.requestor
View
114 xpybutil/ewmh.py
@@ -2,8 +2,8 @@
Implements the entire EWMH spec. The spec can be found here:
http://standards.freedesktop.org/wm-spec/wm-spec-latest.html
-xpybutil's primary purpose was to make accessing ICCCM and EWMH related
-information extremely easy. This can be done by using the ewmh or icccm
+xpybutil's primary purpose was to make accessing ICCCM and EWMH related
+information extremely easy. This can be done by using the ewmh or icccm
modules. Here's a quick example (assuming xpybutil is installed):
::
@@ -15,19 +15,19 @@
print names.get(current_desktop, current_desktop)
-This imports the ewmh module (and by extension, connects to the X server) and
-fetches a list of the current desktop names and the current desktop index
-(starting from 0). Since not every desktop must be named, the desktop index is
+This imports the ewmh module (and by extension, connects to the X server) and
+fetches a list of the current desktop names and the current desktop index
+(starting from 0). Since not every desktop must be named, the desktop index is
printed if it has no name.
-Note that the functions in the ewmh and icccm module return *cookies*. In order
-to pull a response from the X server, call the 'reply()' method on a cookie
-object. To force a response sent to the X server, call the 'check()' method on
+Note that the functions in the ewmh and icccm module return *cookies*. In order
+to pull a response from the X server, call the 'reply()' method on a cookie
+object. To force a response sent to the X server, call the 'check()' method on
the corresponding cookie.
-Much of the EWMH and ICCCM modules encapsulate packing data from convenient
-Python data types into C structs (using the 'struct' Python module). For
-example, if one wants to fetch the partial struts set by some window with
+Much of the EWMH and ICCCM modules encapsulate packing data from convenient
+Python data types into C structs (using the 'struct' Python module). For
+example, if one wants to fetch the partial struts set by some window with
identifier ID, you could do:
::
@@ -36,37 +36,38 @@
print ewmh.get_wm_strut_partial(ID).reply()
-Which outputs a dictionary with 12 entries, where each corresponds to a value
+Which outputs a dictionary with 12 entries, where each corresponds to a value
in the partial strut. (i.e., 'left', 'top_end_x', 'right_start_y', etc...).
-In general, particularly with the EWMH module, the ewmh module is very nearly
-representative of the spec itself. Functions that get property values start
-with ``get_``, functions that set property values start with ``set_``, and
-functions that send an event to a client (which typically requests the window
+In general, particularly with the EWMH module, the ewmh module is very nearly
+representative of the spec itself. Functions that get property values start
+with ``get_``, functions that set property values start with ``set_``, and
+functions that send an event to a client (which typically requests the window
manager to DO something) start with ``request_``.
-If a request has no reply (typically the ``set_`` functions), then the
-default is to call it 'unchecked'. If you want to check the result (and force
+If a request has no reply (typically the ``set_`` functions), then the
+default is to call it 'unchecked'. If you want to check the result (and force
retrieval), then use the '_checked' variant.
-The reverse goes for the ``get_`` functions. By default, they are checked, but
+The reverse goes for the ``get_`` functions. By default, they are checked, but
you can use the '_unchecked' variant too.
-Basically, you should probably almost always use the 'checked' variant of
-everything. The cases where you don't are when you want to send a whole bunch
-of requests to the X server at once. You could use the unchecked invariant, and
-after you've initialized all the cookies, calling 'flush' will force
+Basically, you should probably almost always use the 'checked' variant of
+everything. The cases where you don't are when you want to send a whole bunch
+of requests to the X server at once. You could use the unchecked invariant, and
+after you've initialized all the cookies, calling 'flush' will force
communication with the X server.
-Finally, unless you're writing a window manager or creating a client window
-from scratch, you'll almost always want to use the ``get_`` and ``request_``
-functions. For exampe, if you want to change the current desktop...
+Finally, unless you're writing a window manager or creating a client window
+from scratch, you'll almost always want to use the ``get_`` and ``request_``
+functions, not ``set_``. For example, if you want to change the current
+desktop...
- DON'T DO: ``ewmh.get_current_desktop_checked(2).check()``
+ DON'T DO: ``ewmh.set_current_desktop_checked(2).check()``
DO: ``ewmh.request_current_desktop_checked(2).check()``
-The former will probably not work, but the latter will. Just follow the EWMH
+The former will probably not work, but the latter will. Just follow the EWMH
spec :-)
"""
import struct
@@ -191,7 +192,7 @@ def get_supported():
return util.PropertyCookie(util.get_property(root, '_NET_SUPPORTED'))
def get_supported_unchecked():
- return util.PropertyCookie(util.get_property_unchecked(root,
+ return util.PropertyCookie(util.get_property_unchecked(root,
'_NET_SUPPORTED'))
def set_supported(atoms):
@@ -225,7 +226,7 @@ def get_client_list():
return util.PropertyCookie(util.get_property(root, '_NET_CLIENT_LIST'))
def get_client_list_unchecked():
- return util.PropertyCookie(util.get_property_unchecked(root,
+ return util.PropertyCookie(util.get_property_unchecked(root,
'_NET_CLIENT_LIST'))
def set_client_list(windows):
@@ -256,7 +257,7 @@ def get_client_list_stacking():
:return: A list of window identifiers.
:rtype: util.PropertyCookie (ATOM[]/32)
"""
- return util.PropertyCookie(util.get_property(root,
+ return util.PropertyCookie(util.get_property(root,
'_NET_CLIENT_LIST_STACKING'))
def get_client_list_stacking_unchecked():
@@ -308,7 +309,7 @@ def set_number_of_desktops(number_of_desktops):
"""
packed = struct.pack('I', number_of_desktops)
return c.core.ChangeProperty(xcb.xproto.PropMode.Replace, root,
- atom('_NET_NUMBER_OF_DESKTOPS'), CARDINAL, 32,
+ atom('_NET_NUMBER_OF_DESKTOPS'), CARDINAL, 32,
1, packed)
def set_number_of_desktops_checked(number_of_desktops):
@@ -351,7 +352,7 @@ def get_desktop_geometry():
Keys: width, height
:rtype: DesktopGeometryCookie (CARDINAL[2]/32)
"""
- return DesktopGeometryCookie(util.get_property(root,
+ return DesktopGeometryCookie(util.get_property(root,
'_NET_DESKTOP_GEOMETRY'))
def get_desktop_geometry_unchecked():
@@ -389,10 +390,10 @@ def request_desktop_geometry(width, height):
:type height: CARDINAL/32
:rtype: xcb.VoidCookie
"""
- return revent(root, '_NET_NUMBER_OF_DESKTOPS', width, height)
+ return revent(root, '_NET_DESKTOP_GEOMETRY', width, height)
def request_desktop_geometry_checked(width, height):
- return revent_checked(root, '_NET_NUMBER_OF_DESKTOPS', width, height)
+ return revent_checked(root, '_NET_DESKTOP_GEOMETRY', width, height)
# _NET_DESKTOP_VIEWPORT
@@ -421,7 +422,7 @@ def get_desktop_viewport():
Keys: x, y
:rtype: DesktopViewportCookie (CARDINAL[][2]/32)
"""
- return DesktopViewportCookie(util.get_property(root,
+ return DesktopViewportCookie(util.get_property(root,
'_NET_DESKTOP_VIEWPORT'))
def get_desktop_viewport_unchecked():
@@ -516,7 +517,7 @@ def set_current_desktop(current_desktop):
"""
packed = struct.pack('I', current_desktop)
return c.core.ChangeProperty(xcb.xproto.PropMode.Replace, root,
- atom('_NET_CURRENT_DESKTOP'), CARDINAL, 32, 1,
+ atom('_NET_CURRENT_DESKTOP'), CARDINAL, 32, 1,
packed)
def set_current_desktop_checked(current_desktop):
@@ -634,7 +635,7 @@ def get_active_window():
:return: The window ID of the active window.
:rtype: util.PropertyCookieSingle (WINDOW/32)
"""
- return util.PropertyCookieSingle(util.get_property(root,
+ return util.PropertyCookieSingle(util.get_property(root,
'_NET_ACTIVE_WINDOW'))
def get_active_window_unchecked():
@@ -678,7 +679,7 @@ def request_active_window(active, source=1,
def request_active_window_checked(active, source=1,
timestamp=xcb.xproto.Time.CurrentTime,
current=0):
- return revent_checked(active, '_NET_ACTIVE_WINDOW', source, timestamp,
+ return revent_checked(active, '_NET_ACTIVE_WINDOW', source, timestamp,
current)
# _NET_WORKAREA
@@ -1107,7 +1108,7 @@ def get_wm_name(window):
return util.PropertyCookie(util.get_property(window, '_NET_WM_NAME'))
def get_wm_name_unchecked(window):
- return util.PropertyCookie(util.get_property_unchecked(window,
+ return util.PropertyCookie(util.get_property_unchecked(window,
'_NET_WM_NAME'))
def set_wm_name(window, wm_name):
@@ -1138,7 +1139,7 @@ def get_wm_visible_name(window):
:return: The window's visible title.
:rtype: util.PropertyCookie (UTF8_STRING)
"""
- return util.PropertyCookie(util.get_property(window,
+ return util.PropertyCookie(util.get_property(window,
'_NET_WM_VISIBLE_NAME'))
def get_wm_visible_name_unchecked(window):
@@ -1188,7 +1189,7 @@ def set_wm_icon_name(window, icon_name):
:rtype: xcb.VoidCookie
"""
return c.core.ChangeProperty(xcb.xproto.PropMode.Replace, window,
- atom('_NET_WM_ICON_NAME'), atom('UTF8_STRING'),
+ atom('_NET_WM_ICON_NAME'), atom('UTF8_STRING'),
8, len(icon_name), icon_name)
def set_wm_icon_name_checked(window, icon_name):
@@ -1207,7 +1208,7 @@ def get_wm_visible_icon_name(window):
:return: The window's visible icon name.
:rtype: util.PropertyCookie (UTF8_STRING)
"""
- return util.PropertyCookie(util.get_property(window,
+ return util.PropertyCookie(util.get_property(window,
'_NET_WM_VISIBLE_ICON_NAME'))
def get_wm_visible_icon_name_unchecked(window):
@@ -1255,7 +1256,7 @@ def get_wm_window_opacity(window):
:return: An opacity percentage between 0 and 1 (inclusive)
:rtype: util.PropertyCookieSingle (CARDINAL/32)
"""
- return OpacityCookieSingle(util.get_property(window,
+ return OpacityCookieSingle(util.get_property(window,
'_NET_WM_WINDOW_OPACITY'))
def get_wm_window_opacity_unchecked(window):
@@ -1299,7 +1300,7 @@ def get_wm_desktop(window):
:return: The window's virtual desktop index.
:rtype: util.PropertyCookieSingle (CARDINAL/32)
"""
- return util.PropertyCookieSingle(util.get_property(window,
+ return util.PropertyCookieSingle(util.get_property(window,
'_NET_WM_DESKTOP'))
def get_wm_desktop_unchecked(window):
@@ -1388,7 +1389,7 @@ def get_wm_state(window):
return util.PropertyCookie(util.get_property(window, '_NET_WM_STATE'))
def get_wm_state_unchecked(window):
- return util.PropertyCookie(util.get_property_unchecked(window,
+ return util.PropertyCookie(util.get_property_unchecked(window,
'_NET_WM_STATE'))
def set_wm_state(window, states):
@@ -1431,7 +1432,7 @@ def request_wm_state(window, action, first, second=0, source=1):
return revent(window, '_NET_WM_STATE', action, first, second, source)
def request_wm_state_checked(window, action, first, second=0, source=1):
- return revent_checked(window, '_NET_WM_STATE',
+ return revent_checked(window, '_NET_WM_STATE',
action, first, second, source)
# _NET_WM_ALLOWED_ACTIONS
@@ -1445,7 +1446,7 @@ def get_wm_allowed_actions(window):
actions through the window manager.
:rtype: util.PropertyCookie (ATOM[]/32)
"""
- return util.PropertyCookie(util.get_property(window,
+ return util.PropertyCookie(util.get_property(window,
'_NET_WM_ALLOWED_ACTIONS'))
def get_wm_allowed_actions_unchecked(window):
@@ -1564,7 +1565,7 @@ def get_wm_strut_partial(window):
bottom_start_x, bottom_end_x
:rtype: StrutPartialCookie (CARDINAL[12]/32)
"""
- return StrutPartialCookie(util.get_property(window,
+ return StrutPartialCookie(util.get_property(window,
'_NET_WM_STRUT_PARTIAL'))
def get_wm_strut_partial_unchecked(window):
@@ -1640,7 +1641,7 @@ def get_wm_icon_geometry(window):
Keys: x, y, width, height
:rtype: IconGeometryCookie (CARDINAL[4]/32)
"""
- return IconGeometryCookie(util.get_property(window,
+ return IconGeometryCookie(util.get_property(window,
'_NET_WM_ICON_GEOMETRY'))
def get_wm_icon_geometry_unchecked(window):
@@ -1773,13 +1774,16 @@ def set_wm_pid(window, pid):
:type pid: CARDINAL/32
:rtype: xcb.VoidCookie
"""
+ packed = struct.pack('I', pid)
return c.core.ChangeProperty(xcb.xproto.PropMode.Replace, window,
- atom('_NET_WM_PID'), CARDINAL, 32, 1, [pid])
+ atom('_NET_WM_PID'), CARDINAL, 32, 1,
+ packed)
def set_wm_pid_checked(window, pid):
+ packed = struct.pack('I', pid)
return c.core.ChangePropertyChecked(xcb.xproto.PropMode.Replace, window,
atom('_NET_WM_PID'), CARDINAL, 32, 1,
- [pid])
+ packed)
# _NET_WM_HANDLED_ICONS
@@ -1791,7 +1795,7 @@ def get_wm_handled_icons(window):
:return: Whether this property is set or not.
:rtype: util.PropertyCookieSingle (CARDINAL/32)
"""
- return util.PropertyCookieSingle(util.get_property(window,
+ return util.PropertyCookieSingle(util.get_property(window,
'_NET_WM_HANDLED_ICONS'))
def get_wm_handled_icons_unchecked(window):
@@ -1825,7 +1829,7 @@ def get_wm_user_time(window):
:return: The XServer time when user activity last occurred.
:rtype: util.PropertyCookieSingle (CARDINAL/32)
"""
- return util.PropertyCookieSingle(util.get_property(window,
+ return util.PropertyCookieSingle(util.get_property(window,
'_NET_WM_USER_TIME'))
def get_wm_user_time_unchecked(window):
@@ -1960,7 +1964,7 @@ def request_wm_ping(window, response=False,
def request_wm_ping_checked(window, response=False,
timestamp=xcb.xproto.Time.CurrentTime):
- return revent_checked(window if not response else root(c), 'WM_PROTOCOLS',
+ return revent_checked(window if not response else root(c), 'WM_PROTOCOLS',
atom('_NET_WM_PING'), timestamp, window)
# _NET_WM_SYNC_REQUEST
View
15 xpybutil/keybind.py
@@ -165,7 +165,7 @@ def get_keyboard_mapping():
def get_keyboard_mapping_unchecked():
"""
- Return an unchecked keyboard mapping cookie that can be used to fetch the
+ Return an unchecked keyboard mapping cookie that can be used to fetch the
table of keysyms in the current X environment.
:rtype: xcb.xproto.GetKeyboardMappingCookie
@@ -177,7 +177,7 @@ def get_keyboard_mapping_unchecked():
def get_keysym(keycode, col=0, kbmap=None):
"""
Get the keysym associated with a particular keycode in the current X
- environment. Although we get a list of keysyms from X in
+ environment. Although we get a list of keysyms from X in
'get_keyboard_mapping', this list is really a table with
'keysys_per_keycode' columns and ``mx - mn`` rows (where ``mx`` is the
maximum keycode and ``mn`` is the minimum keycode).
@@ -187,7 +187,7 @@ def get_keysym(keycode, col=0, kbmap=None):
In most cases, setting ``col`` to 0 will work.
- Witness the utter complexity:
+ Witness the utter complexity:
http://tronche.com/gui/x/xlib/input/keyboard-encoding.html
You may also pass in your own keyboard mapping using the ``kbmap``
@@ -209,7 +209,7 @@ def get_keysym(keycode, col=0, kbmap=None):
per = kbmap.keysyms_per_keycode
ind = (keycode - mn) * per + col
- return __kbmap.keysyms[ind]
+ return kbmap.keysyms[ind]
def get_keysym_string(keysym):
"""
@@ -449,7 +449,7 @@ def __run_keybind_callbacks(e):
their corresponding callback functions. Nothing much to see here, except
that we must mask out the trivial modifiers from the state in order to
find the right callback.
-
+
Callbacks are called in the order that they have been added. (FIFO.)
:param e: A Key{Press,Release} event.
@@ -462,7 +462,10 @@ def __run_keybind_callbacks(e):
key = (e.event, mods, kc)
for cb in __keybinds.get(key, []):
- cb()
+ try:
+ cb(e)
+ except TypeError:
+ cb()
def __regrab(changes):
"""
Something went wrong with that request. Please try again.