Commit 64543d13 authored by Mike O'Connor's avatar Mike O'Connor Committed by Andrej Shadura

Imported Debian patch 0.13-1

parents e177eb4d 89a047bd
......@@ -2,6 +2,10 @@
NEWS for Python X Library
* Version 0.13 6 Aug 2006 (trialed as 0.13pre1 on 22 Jul 2006)
A small release to incorporate a number of minor corrections and bug fixes, including small changes to keysym handling, .Xauthority parsing, several fixes to sending/receiving/flushing data, addition of WithdrawnState to WMHints. petli completed documentation for Display objects.
* Version 0.12 29 Mar 2002
** SHAPE extension
Metadata-Version: 1.0
Name: python-xlib
Version: 0.12
Version: 0.13pre1
Summary: Python X Library
Author: Peter Liljenberg
......@@ -97,8 +97,10 @@ approximately ordered by importance.
Author email: Peter Liljenberg <>
Mailing list:
The Python X Library is a SourceForged project. The project page is Source is available Source is available
from that page as tar.gz-releases and from the CVS tree.
There isn't any real web page yet, only a derivative of this file. It
2006-07-22 Mike Grant <>
Various typo fixes, general updates.
Changelog hasn't been maintained since 2002, but some of the more
significant comments from cvs logs follow:
* Xlib/ (petli) Fix bug in refresh_keyboard_mapping:
ignore modifier and pointer remappings. Plays nice with pydoc.
Copied some text from the docs to __doc__ strings in
Xlib/ so that they appear when you use pydoc.
Completed documentation for Display objects.
* Xlib/ (calroc99) Minor doc string changes. Called
load_keysym_group() for miscellany and latin1 keysyms, rather
than importing the modules.
* Xlib/keysymdef/*: (calroc99) Small change to keysym loading.
Works the same way.
* Xlib/support/*, Xlib/, Xlib/ (petli) Added
~/.Xauthority parsing by Python code instead of relying on
/usr/X11R6/bin/xauth. Not activated yet in all cases yet?
Activated in
* Xlib/xobject/ (petli) Fix bugs in definition and
method of GrabButton/Pointer
* Xlib/xobject/ (petli) Add WithdrawnState to WMHints
* doc/*: (petli) documentation updates, typos and completing
documentation for Display objects
2002-03-30 Peter Liljenberg <>
* support/ Handle fcntl/FCNTL changes in Python
2002-03-11 Peter Liljenberg <>
* xobject/ (Drawable.fill_arc): This should be a
Fri Jan 19 17:49:45 2001 Peter Liljenberg <>
* Moved all keysyms into separate modules, based on their
category. By default only the miscellany and latin1 keysyms are
loaded, and other have to be loaded by importing the
Xlib.keysymdef.<category> module, or calling
* (Display.lookup_string):
Functions to translate keysyms to strings, and binding keysyms to
new strings.
2001-01-16 <>
* xobject/ (Window.send_event):
* (Display.send_event): Changed the order of the
event_mask and propagate arguments.
2001-01-10 <>
* (Display._update_keymap): The first half of the
update algorithm operated on an earlier type of code->sym map than
the second half. Stupid, stupid. It would have been nice with a
type-checker now.
Tue Jan 9 13:03:19 2001 Peter Liljenberg <>
* (Display._update_keymap): Fixed call to append with
1.5.2 semantics, broke in newer Pythons.
2000-12-22 <>
* (Display.keycode_to_keysym):
Added keymap cache implementation.
2000-12-21 <>
* xobject/ (Colormap.alloc_named_color): Extended to
handle #000000 style color specifications.
* xobject/ (Window.reparent): Renamed from
* (Display.set_error_handler): Added.
2000-12-20 <>
* (_BaseDisplay):
Implement a cache of atom names.
# $Id:,v 1.4 2001/01/19 18:59:37 petli Exp $
# $Id:,v 1.6 2005/09/06 19:18:19 calroc99 Exp $
# Xlib.XK -- X keysym defs
......@@ -17,36 +17,62 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# This module defines some functions for working with X keysyms as well
# as a modular keysym definition and loading mechanism. See the keysym
# definition modules in the Xlib/keysymdef directory.
from X import NoSymbol
def string_to_keysym(str):
return globals().get('XK_' + str, NoSymbol)
def string_to_keysym(keysym):
'''Return the (16 bit) numeric code of keysym.
Given the name of a keysym as a string, return its numeric code.
Don't include the 'XK_' prefix, just use the base, i.e. 'Delete'
instead of 'XK_Delete'.'''
return globals().get('XK_' + keysym, NoSymbol)
def load_keysym_group(group):
'''Load all the keysyms in group.
Given a group name such as 'latin1' or 'katakana' load the keysyms
defined in module '' into this XK module.'''
if '.' in group:
raise ValueError('invalid keysym group name: %s' % group)
# Try to import the corresponding package. This will
# finally result in the package calling _load_keysyms_into_XK
__import__('Xlib.keysymdef.%s' % group, globals(), locals())
G = globals() #Get a reference to XK.__dict__ a.k.a. globals
def _load_keysyms_into_XK(mod):
# I reckon that this is the fastest way to import all
# keysyms into this modules global dict.
# To have some kind of security, check that we're only
# loading something out of Xlib.keysymdef
#Import just the keysyms module.
mod = __import__('Xlib.keysymdef.%s' % group, G, locals(), [group])
#Extract names of just the keysyms.
keysyms = [n for n in dir(mod) if n.startswith('XK_')]
if mod[:15] == 'Xlib.keysymdef.':
exec 'from %s import *' % mod in globals()
#Copy the named keysyms into XK.__dict__
for keysym in keysyms:
## k = mod.__dict__[keysym]; assert k == int(k) #probably too much.
G[keysym] = mod.__dict__[keysym]
#And get rid of the keysym module.
del mod
def _load_keysyms_into_XK(mod):
'''keysym definition modules need no longer call Xlib.XK._load_keysyms_into_XK().
You should remove any calls to that function from your keysym modules.'''
# Always import miscellany and latin1 keysyms
import Xlib.keysymdef.miscellany
import Xlib.keysymdef.latin1
def keysym_to_string(keysym):
'''Translate a keysym (16 bit number) into a python string.
This will pass 0 to 0xff as well as XK_BackSpace, XK_Tab, XK_Clear,
XK_Return, XK_Pause, XK_Scroll_Lock, XK_Escape, XK_Delete. For other
values it returns None.'''
# ISO latin 1, LSB is the code
if keysym & 0xff00 == 0:
return chr(keysym & 0xff)
# $Id:,v 1.17 2002/03/24 22:31:06 petli Exp $
# $Id:,v 1.20 2005/11/16 15:50:47 petli Exp $
# Xlib.display -- high level display object
......@@ -56,7 +56,7 @@ _resource_hierarchy = {
'drawable': ('window', 'pixmap'),
'fontable': ('font', 'gc')
class _BaseDisplay(protocol.display.Display):
resource_classes = _resource_baseclasses.copy()
......@@ -131,35 +131,77 @@ class Display:
def get_display_name(self):
"""Returns the name used to connect to the server, either
provided when creating the Display object, or fetched from the
environmental variable $DISPLAY."""
return self.display.get_display_name()
def fileno(self):
"""Returns the file descriptor number of the underlying socket.
This method is provided to allow Display objects to be passed"""
return self.display.fileno()
def close(self):
"""Close the display, freeing the resources that it holds."""
def set_error_handler(self, handler):
"""Set the default error handler which will be called for all
unhandled errors. handler should take two arguments as a normal
request error handler, but the second argument (the request) will
be None. See section Error Handling."""
def flush(self):
"""Flush the request queue, building and sending the queued
requests. This can be necessary in applications that never wait
for events, and in threaded applications."""
def sync(self):
"""Flush the queue and wait until the server has processed all
the queued requests. Use this e.g. when it is important that
errors caused by a certain request is trapped."""
# Do a light-weight replyrequest to sync. There must
# be a better way to do it...
def next_event(self):
"""Return the next event. If there are no events queued, it will
block until the next event is fetched from the server."""
return self.display.next_event()
def pending_events(self):
"""Return the number of events queued, i.e. the number of times
that Display.next_event() can be called without blocking."""
return self.display.pending_events()
def has_extension(self, extension):
"""Check if both the server and the client library support the X
extension named extension."""
return extension in self.extensions
def create_resource_object(self, type, id):
"""Create a resource object of type for the integer id. type
should be one of the following strings:
This function can be used when a resource ID has been fetched
e.g. from an resource or a command line argument. Resource
objects should never be created by instantiating the appropriate
class directly, since any X extensions dynamically added by the
library will not be available.
return self.display.resource_classes[type](self.display, id)
# We need this to handle display extension methods
......@@ -181,9 +223,12 @@ class Display:
def screen_count(self):
"""Return the total number of screens on the display."""
return len(
def get_default_screen(self):
"""Return the number of the default screen, extracted from the
display name."""
return self.display.get_default_screen()
......@@ -280,18 +325,29 @@ class Display:
# index is the keysyms index in the map for that keycode.
def keycode_to_keysym(self, keycode, index):
"""Convert a keycode to a keysym, looking in entry index.
Normally index 0 is unshifted, 1 is shifted, 2 is alt grid, and 3
is shift+alt grid. If that key entry is not bound, X.NoSymbol is
return self._keymap_codes[keycode][index]
except IndexError:
return X.NoSymbol
def keysym_to_keycode(self, keysym):
"""Look up the primary keycode that is bound to keysym. If
several keycodes are found, the one with the lowest index and
lowest code is returned. If keysym is not bound to any key, 0 is
return self._keymap_syms[keysym][0][1]
except (KeyError, IndexError):
return 0
def keysym_to_keycodes(self, keysym):
"""Look up all the keycodes that is bound to keysym. A list of
tuples (keycode, index) is returned, sorted primarily on the
lowest index and secondarily on the lowest keycode."""
# Copy the map list, reversing the arguments
return map(lambda x: (x[1], x[0]), self._keymap_syms[keysym])
......@@ -299,8 +355,12 @@ class Display:
return []
def refresh_keyboard_mapping(self, evt):
"""This method should be called once when a MappingNotify event
is received, to update the keymap cache. evt should be the event
if isinstance(evt, event.MappingNotify):
self._update_keymap(evt.first_keycode, evt.count)
if evt.request == X.MappingKeyboard:
self._update_keymap(evt.first_keycode, evt.count)
raise TypeError('expected a MappingNotify event')
......@@ -375,24 +435,36 @@ class Display:
def intern_atom(self, name, only_if_exists = 0):
"""Intern the string name, returning its atom number. If
only_if_exists is true and the atom does not already exist, it
will not be created and X.NONE is returned."""
r = request.InternAtom(display = self.display,
name = name,
only_if_exists = only_if_exists)
return r.atom
def get_atom_name(self, atom):
"""Look up the name of atom, returning it as a string. Will raise
BadAtom if atom does not exist."""
r = request.GetAtomName(display = self.display,
atom = atom)
def get_selection_owner(self, selection):
"""Return the window that owns selection (an atom), or X.NONE if
there is no owner for the selection. Can raise BadAtom."""
r = request.GetSelectionOwner(display = self.display,
selection = selection)
return r.owner
def send_event(self, destination, event, event_mask = 0, propagate = 0,
onerror = None):
"""Send a synthetic event to the window destination which can be
a window object, or X.PointerWindow or X.InputFocus. event is the
event object to send, instantiated from one of the classes in See XSendEvent(3X11) for details.
There is also a Window.send_event() method."""
request.SendEvent(display = self.display,
onerror = onerror,
propagate = propagate,
......@@ -401,11 +473,15 @@ class Display:
event = event)
def ungrab_pointer(self, time, onerror = None):
"""elease a grabbed pointer and any queued events. See
request.UngrabPointer(display = self.display,
onerror = onerror,
time = time)
def change_active_pointer_grab(self, event_mask, cursor, time, onerror = None):
"""Change the dynamic parameters of a pointer grab. See
request.ChangeActivePointerGrab(display = self.display,
onerror = onerror,
cursor = cursor,
......@@ -413,27 +489,43 @@ class Display:
event_mask = event_mask)
def ungrab_keyboard(self, time, onerror = None):
"""Ungrab a grabbed keyboard and any queued events. See
request.UngrabKeyboard(display = self.display,
onerror = onerror,
time = time)
def allow_events(self, mode, time, onerror = None):
"""Release some queued events. mode should be one of
X.AsyncPointer, X.SyncPointer, X.AsyncKeyboard, X.SyncKeyboard,
X.ReplayPointer, X.ReplayKeyboard, X.AsyncBoth, or X.SyncBoth.
time should be a timestamp or X.CurrentTime."""
request.AllowEvents(display = self.display,
onerror = onerror,
mode = mode,
time = time)
def grab_server(self, onerror = None):
"""Disable processing of requests on all other client connections
until the server is ungrabbed. Server grabbing should be avoided
as much as possible."""
request.GrabServer(display = self.display,
onerror = onerror)
def ungrab_server(self, onerror = None):
"""Release the server if it was previously grabbed by this client."""
request.UngrabServer(display = self.display,
onerror = onerror)
def warp_pointer(self, x, y, src_window = 0, src_x = 0, src_y = 0,
def warp_pointer(self, x, y, src_window = X.NONE, src_x = 0, src_y = 0,
src_width = 0, src_height = 0, onerror = None):
"""Move the pointer relative its current position by the offsets
(x, y). However, if src_window is a window the pointer is only
moved if the specified rectangle in src_window contains it. If
src_width is 0 it will be replaced with the width of src_window -
src_x. src_height is treated in a similar way.
To move the pointer to absolute coordinates, use Window.warp_pointer()."""
request.WarpPointer(display = self.display,
onerror = onerror,
src_window = src_window,
......@@ -446,6 +538,13 @@ class Display:
dst_y = y)
def set_input_focus(self, focus, revert_to, time, onerror = None):
"""Set input focus to focus, which should be a window,
X.PointerRoot or X.NONE. revert_to specifies where the focus
reverts to if the focused window becomes not visible, and should
be X.RevertToParent, RevertToPointerRoot, or RevertToNone. See
XSetInputFocus(3X11) for details.
There is also a Window.set_input_focus()."""
request.SetInputFocus(display = self.display,
onerror = onerror,
revert_to = revert_to,
......@@ -453,13 +552,28 @@ class Display:
time = time)
def get_input_focus(self):
"""Return an object with the following attributes:
The window which currently holds the input
focus, X.NONE or X.PointerRoot.
Where the focus will revert, one of X.RevertToParent,
RevertToPointerRoot, or RevertToNone. """
return request.GetInputFocus(display = self.display)
def query_keymap(self):
"""Return a bit vector for the logical state of the keyboard,
where each bit set to 1 indicates that the corresponding key is
currently pressed down. The vector is represented as a list of 32
integers. List item N contains the bits for keys 8N to 8N + 7
with the least significant bit in the byte representing key 8N."""
r = request.QueryKeymap(display = self.display)
def open_font(self, name):
"""Open the font identifed by the pattern name and return its
font object. If name does not match any font, None is returned."""
fid = self.display.allocate_resource_id()
ec = error.CatchError(error.BadName)
......@@ -477,26 +591,71 @@ class Display:
return cls(self.display, fid, owner = 1)
def list_fonts(self, pattern, max_names):
"""Return a list of font names matching pattern. No more than
max_names will be returned."""
r = request.ListFonts(display = self.display,
max_names = max_names,
pattern = pattern)
return r.fonts
def list_fonts_with_info(self, pattern, max_names):
"""Return a list of fonts matching pattern. No more than
max_names will be returned. Each list item represents one font
and has the following properties:
The name of the font.
See the descripton of XFontStruct in XGetFontProperty(3X11)
for details on these values.
A list of properties. Each entry has two attributes:
The atom identifying this property.
A 32-bit unsigned value.
return request.ListFontsWithInfo(display = self.display,
max_names = max_names,
pattern = pattern)
def set_font_path(self, path, onerror = None):
"""Set the font path to path, which should be a list of strings.
If path is empty, the default font path of the server will be
request.SetFontPath(display = self.display,
onerror = onerror,
path = path)
def get_font_path(self):
"""Return the current font path as a list of strings."""
r = request.GetFontPath(display = self.display)
return r.paths
def query_extension(self, name):
"""Ask the server if it supports the extension name. If it is
supported an object with the following attributes is returned:
The major opcode that the requests of this extension uses.
The base event code if the extension have additional events, or 0.
The base error code if the extension have additional errors, or 0.
If the extension is not supported, None is returned."""
r = request.QueryExtension(display = self.display,
name = name)
if r.present:
......@@ -505,36 +664,96 @@ class Display:
return None
def list_extensions(self):
"""Return a list of all the extensions provided by the server."""
r = request.ListExtensions(display = self.display)
return r.names
def change_keyboard_mapping(self, first_keycode, keysyms, onerror = None):
"""Modify the keyboard mapping, starting with first_keycode.
keysyms is a list of tuples of keysyms. keysyms[n][i] will be
assigned to keycode first_keycode+n at index i."""
request.ChangeKeyboardMapping(display = self.display,
onerror = onerror,
first_keycode = first_keycode,
keysyms = keysyms)
def get_keyboard_mapping(self, first_keycode, count):
"""Return the current keyboard mapping as a list of tuples,
starting at first_keycount and no more than count."""
r = request.GetKeyboardMapping(display = self.display,
first_keycode = first_keycode,
count = count)
return r.keysyms
def change_keyboard_control(self, onerror = None, **keys):
"""Change the parameters provided as keyword arguments:
The volume of key clicks between 0 (off) and 100 (load).
-1 will restore default setting.
The base volume of the bell, coded as above.
The pitch of the bell in Hz, -1 restores the default.
The duration of the bell in milliseconds, -1 restores
the default.
led_mode should be X.LedModeOff or X.LedModeOn. If led is
provided, it should be a 32-bit mask listing the LEDs that
should change. If led is not provided, all LEDs are changed.
auto_repeat_mode should be one of X.AutoRepeatModeOff,
X.AutoRepeatModeOn, or X.AutoRepeatModeDefault. If key is
provided, that key will be modified, otherwise the global
state for the entire keyboard will be modified."""
request.ChangeKeyboardControl(display = self.display,
onerror = onerror,
attrs = keys)
def get_keyboard_control(self):
"""Return an object with the following attributes:
X.AutoRepeatModeOn or X.AutoRepeatModeOff.
A list of 32 integers. List item N contains the bits for keys
8N to 8N + 7 with the least significant bit in the byte
representing key 8N. If a bit is on, autorepeat is enabled
for the corresponding key.
A 32-bit mask indicating which LEDs are on.
The volume of key click, from 0 to 100.
The volume, pitch and duration of the bell. """
return request.GetKeyboardControl(display = self.display)
def bell(self, percent = 0, onerror = None):
"""Ring the bell at the volume percent which is relative the base
volume. See XBell(3X11)."""
request.Bell(display = self.display,
onerror = onerror,
percent = percent)
def change_pointer_control(self, accel = None, threshold = None, onerror = None):
"""To change the pointer acceleration, set accel to a tuple (num,
denum). The pointer will then move num/denum times the normal
speed if it moves beyond the threshold number of pixels at once.
To change the threshold, set it to the number of pixels. -1
restores the default."""
if accel is None:
do_accel = 0
accel_num = 0
......@@ -557,9 +776,20 @@ class Display:
threshold = threshold)
def get_pointer_control(self):
"""Return an object with the following attributes:
The acceleration as numerator/denumerator.
The number of pixels the pointer must move before the
acceleration kicks in."""
return request.GetPointerControl(display = self.display)
def set_screen_saver(self, timeout, interval, prefer_blank, allow_exposures, onerror = None):
"""See XSetScreenSaver(3X11)."""
request.SetScreenSaver(display = self.display,
onerror = onerror,
timeout = timeout,
......@@ -568,9 +798,17 @@ class Display:
allow_exposures = allow_exposures)
def get_screen_saver(self):
"""Return an object with the attributes timeout, interval,
prefer_blanking, allow_exposures. See XGetScreenSaver(3X11) for
return request.GetScreenSaver(display = self.display)
def change_hosts(self, mode, host_family, host, onerror = None):
"""mode is either X.HostInsert or X.HostDelete. host_family is
one of X.FamilyInternet, X.FamilyDECnet or X.FamilyChaos.
host is a list of bytes. For the Internet family, it should be the
four bytes of an IPv4 address."""
request.ChangeHosts(display = self.display,
onerror = onerror,
mode = mode,
......@@ -578,42 +816,92 @@ class Display:
host = host)
def list_hosts(self):
"""Return an object with the following attributes:
X.EnableAccess if the access control list is used, X.DisableAccess otherwise.
The hosts on the access list. Each entry has the following attributes: