~bennabiy/+junk/python-xlib

« back to all changes in this revision

Viewing changes to .pc/python3.patch/Xlib/display.py

  • Committer: Package Import Robot
  • Author(s): Andrew Shadura, Ramkumar Ramachandra, Andrew Shadura
  • Date: 2015-08-13 08:14:19 UTC
  • mfrom: (6.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20150813081419-hdefinnghp2iydkx
Tags: 0.14+20091101-3
[ Ramkumar Ramachandra ]
* Remove useless debugging output (Closes: #565996)

[ Andrew Shadura ]
* Switch to 3.0 (quilt) format.
* Rename patches.
* Use debhelper 9 in its short form.
* Use pybuild.
* Bump Standards-Version.
* Don't build or install PostScript documentation and info files.
* Use system-provided texi2html instead of a shipped version
  (Closes: #795057).
* Update debian/copyright (Closes: #795057).
* Don't install Makefile or texi2html with the documentation.
* Set executable bit for examples.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Xlib.display -- high level display object
 
2
#
 
3
#    Copyright (C) 2000 Peter Liljenberg <petli@ctrl-c.liu.se>
 
4
#
 
5
#    This program is free software; you can redistribute it and/or modify
 
6
#    it under the terms of the GNU General Public License as published by
 
7
#    the Free Software Foundation; either version 2 of the License, or
 
8
#    (at your option) any later version.
 
9
#
 
10
#    This program is distributed in the hope that it will be useful,
 
11
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
#    GNU General Public License for more details.
 
14
#
 
15
#    You should have received a copy of the GNU General Public License
 
16
#    along with this program; if not, write to the Free Software
 
17
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
# Python modules
 
20
import new
 
21
 
 
22
# Xlib modules
 
23
import error
 
24
import ext
 
25
import X
 
26
 
 
27
# Xlib.protocol modules
 
28
import protocol.display
 
29
from protocol import request, event, rq
 
30
 
 
31
# Xlib.xobjects modules
 
32
import xobject.resource
 
33
import xobject.drawable
 
34
import xobject.fontable
 
35
import xobject.colormap
 
36
import xobject.cursor
 
37
 
 
38
_resource_baseclasses = {
 
39
    'resource': xobject.resource.Resource,
 
40
    'drawable': xobject.drawable.Drawable,
 
41
    'window': xobject.drawable.Window,
 
42
    'pixmap': xobject.drawable.Pixmap,
 
43
    'fontable': xobject.fontable.Fontable,
 
44
    'font': xobject.fontable.Font,
 
45
    'gc': xobject.fontable.GC,
 
46
    'colormap': xobject.colormap.Colormap,
 
47
    'cursor': xobject.cursor.Cursor,
 
48
    }
 
49
 
 
50
_resource_hierarchy = {
 
51
    'resource': ('drawable', 'window', 'pixmap',
 
52
                 'fontable', 'font', 'gc',
 
53
                 'colormap', 'cursor'),
 
54
    'drawable': ('window', 'pixmap'),
 
55
    'fontable': ('font', 'gc')
 
56
    }
 
57
 
 
58
class _BaseDisplay(protocol.display.Display):
 
59
    resource_classes = _resource_baseclasses.copy()
 
60
 
 
61
    # Implement a cache of atom names, used by Window objects when
 
62
    # dealing with some ICCCM properties not defined in Xlib.Xatom
 
63
 
 
64
    def __init__(self, *args, **keys):
 
65
        apply(protocol.display.Display.__init__, (self, ) + args, keys)
 
66
        self._atom_cache = {}
 
67
 
 
68
    def get_atom(self, atomname, only_if_exists=0):
 
69
        if self._atom_cache.has_key(atomname):
 
70
            return self._atom_cache[atomname]
 
71
 
 
72
        r = request.InternAtom(display = self, name = atomname, only_if_exists = only_if_exists)
 
73
 
 
74
         # don't cache NONE responses in case someone creates this later
 
75
        if r.atom != X.NONE:
 
76
            self._atom_cache[atomname] = r.atom
 
77
 
 
78
        return r.atom
 
79
 
 
80
 
 
81
class Display:
 
82
    def __init__(self, display = None):
 
83
        self.display = _BaseDisplay(display)
 
84
 
 
85
        # Create the keymap cache
 
86
        self._keymap_codes = [()] * 256
 
87
        self._keymap_syms = {}
 
88
        self._update_keymap(self.display.info.min_keycode,
 
89
                            (self.display.info.max_keycode
 
90
                             - self.display.info.min_keycode + 1))
 
91
 
 
92
        # Translations for keysyms to strings.
 
93
        self.keysym_translations = {}
 
94
 
 
95
        # Find all supported extensions
 
96
        self.extensions = []
 
97
        self.class_extension_dicts = {}
 
98
        self.display_extension_methods = {}
 
99
 
 
100
        self.extension_event = rq.DictWrapper({})
 
101
 
 
102
        exts = self.list_extensions()
 
103
 
 
104
        # Go through all extension modules
 
105
        for extname, modname in ext.__extensions__:
 
106
            if extname in exts:
 
107
 
 
108
                # Import the module and fetch it
 
109
                __import__('Xlib.ext.' + modname)
 
110
                mod = getattr(ext, modname)
 
111
 
 
112
                info = self.query_extension(extname)
 
113
                self.display.set_extension_major(extname, info.major_opcode)
 
114
 
 
115
                # Call initialiasation function
 
116
                mod.init(self, info)
 
117
 
 
118
                self.extensions.append(extname)
 
119
 
 
120
 
 
121
        # Finalize extensions by creating new classes
 
122
        for type, dict in self.class_extension_dicts.items():
 
123
            origcls = self.display.resource_classes[type]
 
124
            self.display.resource_classes[type] = new.classobj(origcls.__name__,
 
125
                                                               (origcls,),
 
126
                                                               dict)
 
127
 
 
128
        # Problem: we have already created some objects without the
 
129
        # extensions: the screen roots and default colormaps.
 
130
        # Fix that by reinstantiating them.
 
131
        for screen in self.display.info.roots:
 
132
            screen.root = self.display.resource_classes['window'](self.display, screen.root.id)
 
133
            screen.default_colormap = self.display.resource_classes['colormap'](self.display, screen.default_colormap.id)
 
134
 
 
135
 
 
136
    def get_display_name(self):
 
137
        """Returns the name used to connect to the server, either
 
138
        provided when creating the Display object, or fetched from the
 
139
        environmental variable $DISPLAY."""
 
140
        return self.display.get_display_name()
 
141
 
 
142
    def fileno(self):
 
143
        """Returns the file descriptor number of the underlying socket.
 
144
        This method is provided to allow Display objects to be passed
 
145
        select.select()."""
 
146
        return self.display.fileno()
 
147
 
 
148
    def close(self):
 
149
        """Close the display, freeing the resources that it holds."""
 
150
        self.display.close()
 
151
 
 
152
    def set_error_handler(self, handler):
 
153
        """Set the default error handler which will be called for all
 
154
        unhandled errors. handler should take two arguments as a normal
 
155
        request error handler, but the second argument (the request) will
 
156
        be None.  See section Error Handling."""
 
157
        self.display.set_error_handler(handler)
 
158
 
 
159
    def flush(self):
 
160
        """Flush the request queue, building and sending the queued
 
161
        requests. This can be necessary in applications that never wait
 
162
        for events, and in threaded applications."""
 
163
        self.display.flush()
 
164
 
 
165
    def sync(self):
 
166
        """Flush the queue and wait until the server has processed all
 
167
        the queued requests. Use this e.g. when it is important that
 
168
        errors caused by a certain request is trapped."""
 
169
        # Do a light-weight replyrequest to sync.  There must
 
170
        # be a better way to do it...
 
171
        self.get_pointer_control()
 
172
 
 
173
    def next_event(self):
 
174
        """Return the next event. If there are no events queued, it will
 
175
        block until the next event is fetched from the server."""
 
176
        return self.display.next_event()
 
177
 
 
178
    def pending_events(self):
 
179
        """Return the number of events queued, i.e. the number of times
 
180
        that Display.next_event() can be called without blocking."""
 
181
        return self.display.pending_events()
 
182
 
 
183
    def has_extension(self, extension):
 
184
        """Check if both the server and the client library support the X
 
185
        extension named extension."""
 
186
        return extension in self.extensions
 
187
 
 
188
    def create_resource_object(self, type, id):
 
189
        """Create a resource object of type for the integer id. type
 
190
        should be one of the following strings:
 
191
 
 
192
        resource
 
193
        drawable
 
194
        window
 
195
        pixmap
 
196
        fontable
 
197
        font
 
198
        gc
 
199
        colormap
 
200
        cursor
 
201
 
 
202
        This function can be used when a resource ID has been fetched
 
203
        e.g. from an resource or a command line argument. Resource
 
204
        objects should never be created by instantiating the appropriate
 
205
        class directly, since any X extensions dynamically added by the
 
206
        library will not be available.
 
207
        """
 
208
        return self.display.resource_classes[type](self.display, id)
 
209
 
 
210
    # We need this to handle display extension methods
 
211
    def __getattr__(self, attr):
 
212
        try:
 
213
            function = self.display_extension_methods[attr]
 
214
            return new.instancemethod(function, self, self.__class__)
 
215
        except KeyError:
 
216
            raise AttributeError(attr)
 
217
 
 
218
    ###
 
219
    ### display information retrieval
 
220
    ###
 
221
 
 
222
    def screen(self, sno = None):
 
223
        if sno is None:
 
224
            return self.display.info.roots[self.display.default_screen]
 
225
        else:
 
226
            return self.display.info.roots[sno]
 
227
 
 
228
    def screen_count(self):
 
229
        """Return the total number of screens on the display."""
 
230
        return len(self.display.info.roots)
 
231
 
 
232
    def get_default_screen(self):
 
233
        """Return the number of the default screen, extracted from the
 
234
        display name."""
 
235
        return self.display.get_default_screen()
 
236
 
 
237
    ###
 
238
    ### Extension module interface
 
239
    ###
 
240
 
 
241
    def extension_add_method(self, object, name, function):
 
242
        """extension_add_method(object, name, function)
 
243
 
 
244
        Add an X extension module method.  OBJECT is the type of
 
245
        object to add the function to, a string from this list:
 
246
 
 
247
            display
 
248
            resource
 
249
            drawable
 
250
            window
 
251
            pixmap
 
252
            fontable
 
253
            font
 
254
            gc
 
255
            colormap
 
256
            cursor
 
257
 
 
258
        NAME is the name of the method, a string.  FUNCTION is a
 
259
        normal function whose first argument is a 'self'.
 
260
        """
 
261
 
 
262
        if object == 'display':
 
263
            if hasattr(self, name):
 
264
                raise error.MethodOverrideError('attempting to replace display method: %s' % name)
 
265
 
 
266
            self.display_extension_methods[name] = function
 
267
 
 
268
        else:
 
269
            types = (object, ) + _resource_hierarchy.get(object, ())
 
270
            for type in types:
 
271
                cls = _resource_baseclasses[type]
 
272
                if hasattr(cls, name):
 
273
                    raise error.MethodOverrideError('attempting to replace %s method: %s' % (type, name))
 
274
 
 
275
                method = new.instancemethod(function, None, cls)
 
276
 
 
277
                # Maybe should check extension overrides too
 
278
                try:
 
279
                    self.class_extension_dicts[type][name] = method
 
280
                except KeyError:
 
281
                    self.class_extension_dicts[type] = { name: method }
 
282
 
 
283
    def extension_add_event(self, code, evt, name = None):
 
284
        """extension_add_event(code, evt, [name])
 
285
 
 
286
        Add an extension event.  CODE is the numeric code, and EVT is
 
287
        the event class.  EVT will be cloned, and the attribute _code
 
288
        of the new event class will be set to CODE.
 
289
 
 
290
        If NAME is ommitted, it will be set to the name of EVT.  This
 
291
        name is used to insert an entry in the DictWrapper
 
292
        extension_event.
 
293
        """
 
294
 
 
295
        newevt = new.classobj(evt.__name__, evt.__bases__,
 
296
                              evt.__dict__.copy())
 
297
        newevt._code = code
 
298
 
 
299
        self.display.add_extension_event(code, newevt)
 
300
 
 
301
        if name is None:
 
302
            name = evt.__name__
 
303
 
 
304
        setattr(self.extension_event, name, code)
 
305
 
 
306
 
 
307
    def add_extension_error(self, code, err):
 
308
        """add_extension_error(code, err)
 
309
 
 
310
        Add an extension error.  CODE is the numeric code, and ERR is
 
311
        the error class.
 
312
        """
 
313
 
 
314
        self.display.add_extension_error(code, err)
 
315
 
 
316
    ###
 
317
    ### keymap cache implementation
 
318
    ###
 
319
 
 
320
    # The keycode->keysym map is stored in a list with 256 elements.
 
321
    # Each element represents a keycode, and the tuple elements are
 
322
    # the keysyms bound to the key.
 
323
 
 
324
    # The keysym->keycode map is stored in a mapping, where the keys
 
325
    # are keysyms.  The values are a sorted list of tuples with two
 
326
    # elements each: (index, keycode)
 
327
    # keycode is the code for a key to which this keysym is bound, and
 
328
    # index is the keysyms index in the map for that keycode.
 
329
 
 
330
    def keycode_to_keysym(self, keycode, index):
 
331
        """Convert a keycode to a keysym, looking in entry index.
 
332
        Normally index 0 is unshifted, 1 is shifted, 2 is alt grid, and 3
 
333
        is shift+alt grid. If that key entry is not bound, X.NoSymbol is
 
334
        returned."""
 
335
        try:
 
336
            return self._keymap_codes[keycode][index]
 
337
        except IndexError:
 
338
            return X.NoSymbol
 
339
 
 
340
    def keysym_to_keycode(self, keysym):
 
341
        """Look up the primary keycode that is bound to keysym. If
 
342
        several keycodes are found, the one with the lowest index and
 
343
        lowest code is returned. If keysym is not bound to any key, 0 is
 
344
        returned."""
 
345
        try:
 
346
            return self._keymap_syms[keysym][0][1]
 
347
        except (KeyError, IndexError):
 
348
            return 0
 
349
 
 
350
    def keysym_to_keycodes(self, keysym):
 
351
        """Look up all the keycodes that is bound to keysym. A list of
 
352
        tuples (keycode, index) is returned, sorted primarily on the
 
353
        lowest index and secondarily on the lowest keycode."""
 
354
        try:
 
355
            # Copy the map list, reversing the arguments
 
356
            return map(lambda x: (x[1], x[0]), self._keymap_syms[keysym])
 
357
        except KeyError:
 
358
            return []
 
359
 
 
360
    def refresh_keyboard_mapping(self, evt):
 
361
        """This method should be called once when a MappingNotify event
 
362
        is received, to update the keymap cache. evt should be the event
 
363
        object."""
 
364
        if isinstance(evt, event.MappingNotify):
 
365
            if evt.request == X.MappingKeyboard:
 
366
                self._update_keymap(evt.first_keycode, evt.count)
 
367
        else:
 
368
            raise TypeError('expected a MappingNotify event')
 
369
 
 
370
    def _update_keymap(self, first_keycode, count):
 
371
        """Internal function, called to refresh the keymap cache.
 
372
        """
 
373
 
 
374
        # Delete all sym->code maps for the changed codes
 
375
 
 
376
        lastcode = first_keycode + count
 
377
        for keysym, codes in self._keymap_syms.items():
 
378
            i = 0
 
379
            while i < len(codes):
 
380
                code = codes[i][1]
 
381
                if code >= first_keycode and code < lastcode:
 
382
                    del codes[i]
 
383
                else:
 
384
                    i = i + 1
 
385
 
 
386
        # Get the new keyboard mapping
 
387
        keysyms = self.get_keyboard_mapping(first_keycode, count)
 
388
 
 
389
        # Replace code->sym map with the new map
 
390
        self._keymap_codes[first_keycode:lastcode] = keysyms
 
391
 
 
392
        # Update sym->code map
 
393
        code = first_keycode
 
394
        for syms in keysyms:
 
395
            index = 0
 
396
            for sym in syms:
 
397
                if sym != X.NoSymbol:
 
398
                    if self._keymap_syms.has_key(sym):
 
399
                        symcodes = self._keymap_syms[sym]
 
400
                        symcodes.append((index, code))
 
401
                        symcodes.sort()
 
402
                    else:
 
403
                        self._keymap_syms[sym] = [(index, code)]
 
404
 
 
405
                index = index + 1
 
406
            code = code + 1
 
407
 
 
408
    ###
 
409
    ### client-internal keysym to string translations
 
410
    ###
 
411
 
 
412
    def lookup_string(self, keysym):
 
413
        """Return a string corresponding to KEYSYM, or None if no
 
414
        reasonable translation is found.
 
415
        """
 
416
        s = self.keysym_translations.get(keysym)
 
417
        if s is not None:
 
418
            return s
 
419
 
 
420
        import Xlib.XK
 
421
        return Xlib.XK.keysym_to_string(keysym)
 
422
 
 
423
    def rebind_string(self, keysym, newstring):
 
424
        """Change the translation of KEYSYM to NEWSTRING.
 
425
        If NEWSTRING is None, remove old translation if any.
 
426
        """
 
427
        if newstring is None:
 
428
            try:
 
429
                del self.keysym_translations[keysym]
 
430
            except KeyError:
 
431
                pass
 
432
        else:
 
433
            self.keysym_translations[keysym] = newstring
 
434
 
 
435
 
 
436
    ###
 
437
    ### X requests
 
438
    ###
 
439
 
 
440
    def intern_atom(self, name, only_if_exists = 0):
 
441
        """Intern the string name, returning its atom number. If
 
442
        only_if_exists is true and the atom does not already exist, it
 
443
        will not be created and X.NONE is returned."""
 
444
        r = request.InternAtom(display = self.display,
 
445
                               name = name,
 
446
                               only_if_exists = only_if_exists)
 
447
        return r.atom
 
448
 
 
449
    def get_atom(self, atom, only_if_exists = 0):
 
450
        """Alias for intern_atom, using internal cache"""
 
451
        return self.display.get_atom(atom, only_if_exists)
 
452
 
 
453
 
 
454
    def get_atom_name(self, atom):
 
455
        """Look up the name of atom, returning it as a string. Will raise
 
456
        BadAtom if atom does not exist."""
 
457
        r = request.GetAtomName(display = self.display,
 
458
                                atom = atom)
 
459
        return r.name
 
460
 
 
461
    def get_selection_owner(self, selection):
 
462
        """Return the window that owns selection (an atom), or X.NONE if
 
463
        there is no owner for the selection. Can raise BadAtom."""
 
464
        r = request.GetSelectionOwner(display = self.display,
 
465
                                      selection = selection)
 
466
        return r.owner
 
467
 
 
468
    def send_event(self, destination, event, event_mask = 0, propagate = 0,
 
469
                   onerror = None):
 
470
        """Send a synthetic event to the window destination which can be
 
471
        a window object, or X.PointerWindow or X.InputFocus. event is the
 
472
        event object to send, instantiated from one of the classes in
 
473
        protocol.events. See XSendEvent(3X11) for details.
 
474
 
 
475
        There is also a Window.send_event() method."""
 
476
        request.SendEvent(display = self.display,
 
477
                          onerror = onerror,
 
478
                          propagate = propagate,
 
479
                          destination = destination,
 
480
                          event_mask = event_mask,
 
481
                          event = event)
 
482
 
 
483
    def ungrab_pointer(self, time, onerror = None):
 
484
        """elease a grabbed pointer and any queued events. See
 
485
        XUngrabPointer(3X11)."""
 
486
        request.UngrabPointer(display = self.display,
 
487
                              onerror = onerror,
 
488
                              time = time)
 
489
 
 
490
    def change_active_pointer_grab(self, event_mask, cursor, time, onerror = None):
 
491
        """Change the dynamic parameters of a pointer grab. See
 
492
        XChangeActivePointerGrab(3X11)."""
 
493
        request.ChangeActivePointerGrab(display = self.display,
 
494
                                        onerror = onerror,
 
495
                                        cursor = cursor,
 
496
                                        time = time,
 
497
                                        event_mask = event_mask)
 
498
 
 
499
    def ungrab_keyboard(self, time, onerror = None):
 
500
        """Ungrab a grabbed keyboard and any queued events. See
 
501
        XUngrabKeyboard(3X11)."""
 
502
        request.UngrabKeyboard(display = self.display,
 
503
                               onerror = onerror,
 
504
                               time = time)
 
505
 
 
506
    def allow_events(self, mode, time, onerror = None):
 
507
        """Release some queued events. mode should be one of
 
508
        X.AsyncPointer, X.SyncPointer, X.AsyncKeyboard, X.SyncKeyboard,
 
509
        X.ReplayPointer, X.ReplayKeyboard, X.AsyncBoth, or X.SyncBoth.
 
510
        time should be a timestamp or X.CurrentTime."""
 
511
        request.AllowEvents(display = self.display,
 
512
                            onerror = onerror,
 
513
                            mode = mode,
 
514
                            time = time)
 
515
 
 
516
    def grab_server(self, onerror = None):
 
517
        """Disable processing of requests on all other client connections
 
518
        until the server is ungrabbed. Server grabbing should be avoided
 
519
        as much as possible."""
 
520
        request.GrabServer(display = self.display,
 
521
                           onerror = onerror)
 
522
 
 
523
    def ungrab_server(self, onerror = None):
 
524
        """Release the server if it was previously grabbed by this client."""
 
525
        request.UngrabServer(display = self.display,
 
526
                             onerror = onerror)
 
527
 
 
528
    def warp_pointer(self, x, y, src_window = X.NONE, src_x = 0, src_y = 0,
 
529
                     src_width = 0, src_height = 0, onerror = None):
 
530
        """Move the pointer relative its current position by the offsets
 
531
        (x, y). However, if src_window is a window the pointer is only
 
532
        moved if the specified rectangle in src_window contains it. If
 
533
        src_width is 0 it will be replaced with the width of src_window -
 
534
        src_x. src_height is treated in a similar way.
 
535
 
 
536
        To move the pointer to absolute coordinates, use Window.warp_pointer()."""
 
537
        request.WarpPointer(display = self.display,
 
538
                            onerror = onerror,
 
539
                            src_window = src_window,
 
540
                            dst_window = X.NONE,
 
541
                            src_x = src_x,
 
542
                            src_y = src_y,
 
543
                            src_width = src_width,
 
544
                            src_height = src_height,
 
545
                            dst_x = x,
 
546
                            dst_y = y)
 
547
 
 
548
    def set_input_focus(self, focus, revert_to, time, onerror = None):
 
549
        """Set input focus to focus, which should be a window,
 
550
        X.PointerRoot or X.NONE. revert_to specifies where the focus
 
551
        reverts to if the focused window becomes not visible, and should
 
552
        be X.RevertToParent, RevertToPointerRoot, or RevertToNone. See
 
553
        XSetInputFocus(3X11) for details.
 
554
 
 
555
        There is also a Window.set_input_focus()."""
 
556
        request.SetInputFocus(display = self.display,
 
557
                              onerror = onerror,
 
558
                              revert_to = revert_to,
 
559
                              focus = focus,
 
560
                              time = time)
 
561
 
 
562
    def get_input_focus(self):
 
563
        """Return an object with the following attributes:
 
564
 
 
565
        focus
 
566
            The window which currently holds the input
 
567
            focus, X.NONE or X.PointerRoot.
 
568
        revert_to
 
569
            Where the focus will revert, one of X.RevertToParent,
 
570
            RevertToPointerRoot, or RevertToNone. """
 
571
        return request.GetInputFocus(display = self.display)
 
572
 
 
573
    def query_keymap(self):
 
574
        """Return a bit vector for the logical state of the keyboard,
 
575
        where each bit set to 1 indicates that the corresponding key is
 
576
        currently pressed down. The vector is represented as a list of 32
 
577
        integers. List item N contains the bits for keys 8N to 8N + 7
 
578
        with the least significant bit in the byte representing key 8N."""
 
579
        r = request.QueryKeymap(display = self.display)
 
580
        return r.map
 
581
 
 
582
    def open_font(self, name):
 
583
        """Open the font identifed by the pattern name and return its
 
584
        font object. If name does not match any font, None is returned."""
 
585
        fid = self.display.allocate_resource_id()
 
586
        ec = error.CatchError(error.BadName)
 
587
 
 
588
        request.OpenFont(display = self.display,
 
589
                         onerror = ec,
 
590
                         fid = fid,
 
591
                         name = name)
 
592
        self.sync()
 
593
 
 
594
        if ec.get_error():
 
595
            self.display.free_resource_id(fid)
 
596
            return None
 
597
        else:
 
598
            cls = self.display.get_resource_class('font', xobject.fontable.Font)
 
599
            return cls(self.display, fid, owner = 1)
 
600
 
 
601
    def list_fonts(self, pattern, max_names):
 
602
        """Return a list of font names matching pattern. No more than
 
603
        max_names will be returned."""
 
604
        r = request.ListFonts(display = self.display,
 
605
                              max_names = max_names,
 
606
                              pattern = pattern)
 
607
        return r.fonts
 
608
 
 
609
    def list_fonts_with_info(self, pattern, max_names):
 
610
        """Return a list of fonts matching pattern. No more than
 
611
        max_names will be returned. Each list item represents one font
 
612
        and has the following properties:
 
613
 
 
614
        name
 
615
            The name of the font.
 
616
        min_bounds
 
617
        max_bounds
 
618
        min_char_or_byte2
 
619
        max_char_or_byte2
 
620
        default_char
 
621
        draw_direction
 
622
        min_byte1
 
623
        max_byte1
 
624
        all_chars_exist
 
625
        font_ascent
 
626
        font_descent
 
627
        replies_hint
 
628
            See the descripton of XFontStruct in XGetFontProperty(3X11)
 
629
            for details on these values.
 
630
        properties
 
631
            A list of properties. Each entry has two attributes:
 
632
 
 
633
            name
 
634
                The atom identifying this property.
 
635
            value
 
636
                A 32-bit unsigned value.
 
637
        """
 
638
        return request.ListFontsWithInfo(display = self.display,
 
639
                                         max_names = max_names,
 
640
                                         pattern = pattern)
 
641
 
 
642
    def set_font_path(self, path, onerror = None):
 
643
        """Set the font path to path, which should be a list of strings.
 
644
        If path is empty, the default font path of the server will be
 
645
        restored."""
 
646
        request.SetFontPath(display = self.display,
 
647
                            onerror = onerror,
 
648
                            path = path)
 
649
 
 
650
    def get_font_path(self):
 
651
        """Return the current font path as a list of strings."""
 
652
        r = request.GetFontPath(display = self.display)
 
653
        return r.paths
 
654
 
 
655
    def query_extension(self, name):
 
656
        """Ask the server if it supports the extension name. If it is
 
657
        supported an object with the following attributes is returned:
 
658
 
 
659
        major_opcode
 
660
            The major opcode that the requests of this extension uses.
 
661
        first_event
 
662
            The base event code if the extension have additional events, or 0.
 
663
        first_error
 
664
            The base error code if the extension have additional errors, or 0.
 
665
 
 
666
        If the extension is not supported, None is returned."""
 
667
        r = request.QueryExtension(display = self.display,
 
668
                                   name = name)
 
669
        if r.present:
 
670
            return r
 
671
        else:
 
672
            return None
 
673
 
 
674
    def list_extensions(self):
 
675
        """Return a list of all the extensions provided by the server."""
 
676
        r = request.ListExtensions(display = self.display)
 
677
        return r.names
 
678
 
 
679
    def change_keyboard_mapping(self, first_keycode, keysyms, onerror = None):
 
680
        """Modify the keyboard mapping, starting with first_keycode.
 
681
        keysyms is a list of tuples of keysyms. keysyms[n][i] will be
 
682
        assigned to keycode first_keycode+n at index i."""
 
683
        request.ChangeKeyboardMapping(display = self.display,
 
684
                                      onerror = onerror,
 
685
                                      first_keycode = first_keycode,
 
686
                                      keysyms = keysyms)
 
687
 
 
688
    def get_keyboard_mapping(self, first_keycode, count):
 
689
        """Return the current keyboard mapping as a list of tuples,
 
690
        starting at first_keycount and no more than count."""
 
691
        r = request.GetKeyboardMapping(display = self.display,
 
692
                                       first_keycode = first_keycode,
 
693
                                       count = count)
 
694
        return r.keysyms
 
695
 
 
696
    def change_keyboard_control(self, onerror = None, **keys):
 
697
        """Change the parameters provided as keyword arguments:
 
698
 
 
699
        key_click_percent
 
700
            The volume of key clicks between 0 (off) and 100 (load).
 
701
            -1 will restore default setting.
 
702
        bell_percent
 
703
            The base volume of the bell, coded as above.
 
704
        bell_pitch
 
705
            The pitch of the bell in Hz, -1 restores the default.
 
706
        bell_duration
 
707
            The duration of the bell in milliseconds, -1 restores
 
708
            the default.
 
709
        led
 
710
 
 
711
        led_mode
 
712
            led_mode should be X.LedModeOff or X.LedModeOn. If led is
 
713
            provided, it should be a 32-bit mask listing the LEDs that
 
714
            should change. If led is not provided, all LEDs are changed.
 
715
        key
 
716
 
 
717
        auto_repeat_mode
 
718
            auto_repeat_mode should be one of X.AutoRepeatModeOff,
 
719
            X.AutoRepeatModeOn, or X.AutoRepeatModeDefault. If key is
 
720
            provided, that key will be modified, otherwise the global
 
721
            state for the entire keyboard will be modified."""
 
722
        request.ChangeKeyboardControl(display = self.display,
 
723
                                      onerror = onerror,
 
724
                                      attrs = keys)
 
725
 
 
726
    def get_keyboard_control(self):
 
727
        """Return an object with the following attributes:
 
728
 
 
729
        global_auto_repeat
 
730
            X.AutoRepeatModeOn or X.AutoRepeatModeOff.
 
731
 
 
732
        auto_repeats
 
733
            A list of 32 integers. List item N contains the bits for keys
 
734
            8N to 8N + 7 with the least significant bit in the byte
 
735
            representing key 8N. If a bit is on, autorepeat is enabled
 
736
            for the corresponding key.
 
737
 
 
738
        led_mask
 
739
            A 32-bit mask indicating which LEDs are on.
 
740
 
 
741
        key_click_percent
 
742
            The volume of key click, from 0 to 100.
 
743
 
 
744
        bell_percent
 
745
 
 
746
        bell_pitch
 
747
 
 
748
        bell_duration
 
749
            The volume, pitch and duration of the bell. """
 
750
        return request.GetKeyboardControl(display = self.display)
 
751
 
 
752
    def bell(self, percent = 0, onerror = None):
 
753
        """Ring the bell at the volume percent which is relative the base
 
754
        volume. See XBell(3X11)."""
 
755
        request.Bell(display = self.display,
 
756
                     onerror = onerror,
 
757
                     percent = percent)
 
758
 
 
759
    def change_pointer_control(self, accel = None, threshold = None, onerror = None):
 
760
        """To change the pointer acceleration, set accel to a tuple (num,
 
761
        denum). The pointer will then move num/denum times the normal
 
762
        speed if it moves beyond the threshold number of pixels at once.
 
763
        To change the threshold, set it to the number of pixels. -1
 
764
        restores the default."""
 
765
        if accel is None:
 
766
            do_accel = 0
 
767
            accel_num = 0
 
768
            accel_denum = 0
 
769
        else:
 
770
            do_accel = 1
 
771
            accel_num, accel_denum = accel
 
772
 
 
773
        if threshold is None:
 
774
            do_threshold = 0
 
775
        else:
 
776
            do_threshold = 1
 
777
 
 
778
        request.ChangePointerControl(display = self.display,
 
779
                                     onerror = onerror,
 
780
                                     do_accel = do_accel,
 
781
                                     do_thres = do_threshold,
 
782
                                     accel_num = accel_num,
 
783
                                     accel_denum = accel_denum,
 
784
                                     threshold = threshold)
 
785
 
 
786
    def get_pointer_control(self):
 
787
        """Return an object with the following attributes:
 
788
 
 
789
        accel_num
 
790
 
 
791
        accel_denom
 
792
            The acceleration as numerator/denumerator.
 
793
 
 
794
        threshold
 
795
            The number of pixels the pointer must move before the
 
796
            acceleration kicks in."""
 
797
        return request.GetPointerControl(display = self.display)
 
798
 
 
799
    def set_screen_saver(self, timeout, interval, prefer_blank, allow_exposures, onerror = None):
 
800
        """See XSetScreenSaver(3X11)."""
 
801
        request.SetScreenSaver(display = self.display,
 
802
                               onerror = onerror,
 
803
                               timeout = timeout,
 
804
                               interval = interval,
 
805
                               prefer_blank = prefer_blank,
 
806
                               allow_exposures = allow_exposures)
 
807
 
 
808
    def get_screen_saver(self):
 
809
        """Return an object with the attributes timeout, interval,
 
810
        prefer_blanking, allow_exposures. See XGetScreenSaver(3X11) for
 
811
        details."""
 
812
        return request.GetScreenSaver(display = self.display)
 
813
 
 
814
    def change_hosts(self, mode, host_family, host, onerror = None):
 
815
        """mode is either X.HostInsert or X.HostDelete. host_family is
 
816
        one of X.FamilyInternet, X.FamilyDECnet or X.FamilyChaos.
 
817
 
 
818
        host is a list of bytes. For the Internet family, it should be the
 
819
        four bytes of an IPv4 address."""
 
820
        request.ChangeHosts(display = self.display,
 
821
                            onerror = onerror,
 
822
                            mode = mode,
 
823
                            host_family = host_family,
 
824
                            host = host)
 
825
 
 
826
    def list_hosts(self):
 
827
        """Return an object with the following attributes:
 
828
 
 
829
mode
 
830
    X.EnableAccess if the access control list is used, X.DisableAccess otherwise.
 
831
hosts
 
832
    The hosts on the access list. Each entry has the following attributes:
 
833
 
 
834
    family
 
835
        X.FamilyInternet, X.FamilyDECnet, or X.FamilyChaos.
 
836
    name
 
837
        A list of byte values, the coding depends on family. For the Internet family, it is the 4 bytes of an IPv4 address.
 
838
 
 
839
"""
 
840
        return request.ListHosts(display = self.display)
 
841
 
 
842
    def set_access_control(self, mode, onerror = None):
 
843
        """Enable use of access control lists at connection setup if mode
 
844
        is X.EnableAccess, disable if it is X.DisableAccess."""
 
845
        request.SetAccessControl(display = self.display,
 
846
                                 onerror = onerror,
 
847
                                 mode = mode)
 
848
 
 
849
    def set_close_down_mode(self, mode, onerror = None):
 
850
        """Control what will happen with the client's resources at
 
851
        connection close. The default is X.DestroyAll, the other values
 
852
        are X.RetainPermanent and X.RetainTemporary."""
 
853
        request.SetCloseDownMode(display = self.display,
 
854
                                 onerror = onerror,
 
855
                                 mode = mode)
 
856
 
 
857
    def force_screen_saver(self, mode, onerror = None):
 
858
        """If mode is X.ScreenSaverActive the screen saver is activated.
 
859
        If it is X.ScreenSaverReset, the screen saver is deactivated as
 
860
        if device input had been received."""
 
861
        request.ForceScreenSaver(display = self.display,
 
862
                                 onerror = onerror,
 
863
                                 mode = mode)
 
864
 
 
865
    def set_pointer_mapping(self, map):
 
866
        """Set the mapping of the pointer buttons. map is a list of
 
867
        logical button numbers. map must be of the same length as the
 
868
        list returned by Display.get_pointer_mapping().
 
869
 
 
870
        map[n] sets the
 
871
        logical number for the physical button n+1. Logical number 0
 
872
        disables the button. Two physical buttons cannot be mapped to the
 
873
        same logical number.
 
874
 
 
875
        If one of the buttons to be altered are
 
876
        logically in the down state, X.MappingBusy is returned and the
 
877
        mapping is not changed. Otherwise the mapping is changed and
 
878
        X.MappingSuccess is returned."""
 
879
        r = request.SetPointerMapping(display = self.display,
 
880
                                      map = map)
 
881
        return r.status
 
882
 
 
883
    def get_pointer_mapping(self):
 
884
        """Return a list of the pointer button mappings. Entry N in the
 
885
        list sets the logical button number for the physical button N+1."""
 
886
        r = request.GetPointerMapping(display = self.display)
 
887
        return r.map
 
888
 
 
889
    def set_modifier_mapping(self, keycodes):
 
890
        """Set the keycodes for the eight modifiers X.Shift, X.Lock,
 
891
        X.Control, X.Mod1, X.Mod2, X.Mod3, X.Mod4 and X.Mod5. keycodes
 
892
        should be a eight-element list where each entry is a list of the
 
893
        keycodes that should be bound to that modifier.
 
894
 
 
895
        If any changed
 
896
        key is logically in the down state, X.MappingBusy is returned and
 
897
        the mapping is not changed. If the mapping violates some server
 
898
        restriction, X.MappingFailed is returned. Otherwise the mapping
 
899
        is changed and X.MappingSuccess is returned."""
 
900
        r = request.SetModifierMapping(display = self.display,
 
901
                                       keycodes = keycodes)
 
902
        return r.status
 
903
 
 
904
    def get_modifier_mapping(self):
 
905
        """Return a list of eight lists, one for each modifier. The list
 
906
        can be indexed using X.ShiftMapIndex, X.Mod1MapIndex, and so on.
 
907
        The sublists list the keycodes bound to that modifier."""
 
908
        r = request.GetModifierMapping(display = self.display)
 
909
        return r.keycodes
 
910
 
 
911
    def no_operation(self, onerror = None):
 
912
        """Do nothing but send a request to the server."""
 
913
        request.NoOperation(display = self.display,
 
914
                            onerror = onerror)