Spaces:
Runtime error
Runtime error
| # Xlib.display -- high level display object | |
| # | |
| # Copyright (C) 2000 Peter Liljenberg <petli@ctrl-c.liu.se> | |
| # | |
| # This library is free software; you can redistribute it and/or | |
| # modify it under the terms of the GNU Lesser General Public License | |
| # as published by the Free Software Foundation; either version 2.1 | |
| # of the License, or (at your option) any later version. | |
| # | |
| # This library is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
| # See the GNU Lesser General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU Lesser General Public | |
| # License along with this library; if not, write to the | |
| # Free Software Foundation, Inc., | |
| # 59 Temple Place, | |
| # Suite 330, | |
| # Boston, MA 02111-1307 USA | |
| # Python modules | |
| import types | |
| # Python 2/3 compatibility. | |
| from six import create_unbound_method | |
| # Xlib modules | |
| from . import error | |
| from . import ext | |
| from . import X | |
| # Xlib.protocol modules | |
| from .protocol import display as protocol_display | |
| from .protocol import request, event, rq | |
| # Xlib.xobjects modules | |
| from .xobject import resource | |
| from .xobject import drawable | |
| from .xobject import fontable | |
| from .xobject import colormap | |
| from .xobject import cursor | |
| _resource_baseclasses = { | |
| 'resource': resource.Resource, | |
| 'drawable': drawable.Drawable, | |
| 'window': drawable.Window, | |
| 'pixmap': drawable.Pixmap, | |
| 'fontable': fontable.Fontable, | |
| 'font': fontable.Font, | |
| 'gc': fontable.GC, | |
| 'colormap': colormap.Colormap, | |
| 'cursor': cursor.Cursor, | |
| } | |
| _resource_hierarchy = { | |
| 'resource': ('drawable', 'window', 'pixmap', | |
| 'fontable', 'font', 'gc', | |
| 'colormap', 'cursor'), | |
| 'drawable': ('window', 'pixmap'), | |
| 'fontable': ('font', 'gc') | |
| } | |
| class _BaseDisplay(protocol_display.Display): | |
| # Implement a cache of atom names, used by Window objects when | |
| # dealing with some ICCCM properties not defined in Xlib.Xatom | |
| def __init__(self, *args, **keys): | |
| self.resource_classes = _resource_baseclasses.copy() | |
| protocol_display.Display.__init__(self, *args, **keys) | |
| self._atom_cache = {} | |
| def get_atom(self, atomname, only_if_exists=False): | |
| if atomname in self._atom_cache: | |
| return self._atom_cache[atomname] | |
| r = request.InternAtom(display = self, name = atomname, only_if_exists = only_if_exists) | |
| # don't cache NONE responses in case someone creates this later | |
| if r.atom != X.NONE: | |
| self._atom_cache[atomname] = r.atom | |
| return r.atom | |
| class Display(object): | |
| def __init__(self, display = None): | |
| self.display = _BaseDisplay(display) | |
| # Create the keymap cache | |
| self._keymap_codes = [()] * 256 | |
| self._keymap_syms = {} | |
| self._update_keymap(self.display.info.min_keycode, | |
| (self.display.info.max_keycode | |
| - self.display.info.min_keycode + 1)) | |
| # Translations for keysyms to strings. | |
| self.keysym_translations = {} | |
| # Find all supported extensions | |
| self.extensions = [] | |
| self.class_extension_dicts = {} | |
| self.display_extension_methods = {} | |
| # a dict that maps the event name to the code | |
| # or, when it's an event with a subcode, to a tuple of (event,subcode) | |
| # note this wraps the dict so you address it as | |
| # extension_event.EXTENSION_EVENT_NAME rather than | |
| # extension_event["EXTENSION_EVENT_NAME"] | |
| self.extension_event = rq.DictWrapper({}) | |
| exts = self.list_extensions() | |
| # Go through all extension modules | |
| for extname, modname in ext.__extensions__: | |
| if extname in exts: | |
| # Import the module and fetch it | |
| __import__('Xlib.ext.' + modname) | |
| mod = getattr(ext, modname) | |
| info = self.query_extension(extname) | |
| self.display.set_extension_major(extname, info.major_opcode) | |
| # Call initialiasation function | |
| mod.init(self, info) | |
| self.extensions.append(extname) | |
| # Finalize extensions by creating new classes | |
| for class_name, dictionary in self.class_extension_dicts.items(): | |
| origcls = self.display.resource_classes[class_name] | |
| self.display.resource_classes[class_name] = type(origcls.__name__, | |
| (origcls,), | |
| dictionary) | |
| # Problem: we have already created some objects without the | |
| # extensions: the screen roots and default colormaps. | |
| # Fix that by reinstantiating them. | |
| for screen in self.display.info.roots: | |
| screen.root = self.display.resource_classes['window'](self.display, screen.root.id) | |
| screen.default_colormap = self.display.resource_classes['colormap'](self.display, screen.default_colormap.id) | |
| 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 | |
| select.select().""" | |
| return self.display.fileno() | |
| def close(self): | |
| """Close the display, freeing the resources that it holds.""" | |
| self.display.close() | |
| 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.""" | |
| self.display.set_error_handler(handler) | |
| 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.""" | |
| self.display.flush() | |
| 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... | |
| self.get_pointer_control() | |
| 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: | |
| resource | |
| drawable | |
| window | |
| pixmap | |
| fontable | |
| font | |
| gc | |
| colormap | |
| cursor | |
| 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 | |
| def __getattr__(self, attr): | |
| try: | |
| function = self.display_extension_methods[attr] | |
| return types.MethodType(function, self) | |
| except KeyError: | |
| raise AttributeError(attr) | |
| ### | |
| ### display information retrieval | |
| ### | |
| def screen(self, sno = None): | |
| if sno is None: | |
| return self.display.info.roots[self.display.default_screen] | |
| else: | |
| return self.display.info.roots[sno] | |
| def screen_count(self): | |
| """Return the total number of screens on the display.""" | |
| return len(self.display.info.roots) | |
| def get_default_screen(self): | |
| """Return the number of the default screen, extracted from the | |
| display name.""" | |
| return self.display.get_default_screen() | |
| ### | |
| ### Extension module interface | |
| ### | |
| def extension_add_method(self, object, name, function): | |
| """extension_add_method(object, name, function) | |
| Add an X extension module method. OBJECT is the type of | |
| object to add the function to, a string from this list: | |
| display | |
| resource | |
| drawable | |
| window | |
| pixmap | |
| fontable | |
| font | |
| gc | |
| colormap | |
| cursor | |
| NAME is the name of the method, a string. FUNCTION is a | |
| normal function whose first argument is a 'self'. | |
| """ | |
| if object == 'display': | |
| if hasattr(self, name): | |
| raise AssertionError('attempting to replace display method: %s' % name) | |
| self.display_extension_methods[name] = function | |
| else: | |
| class_list = (object, ) + _resource_hierarchy.get(object, ()) | |
| for class_name in class_list: | |
| cls = _resource_baseclasses[class_name] | |
| if hasattr(cls, name): | |
| raise AssertionError('attempting to replace %s method: %s' % (class_name, name)) | |
| method = create_unbound_method(function, cls) | |
| # Maybe should check extension overrides too | |
| try: | |
| self.class_extension_dicts[class_name][name] = method | |
| except KeyError: | |
| self.class_extension_dicts[class_name] = { name: method } | |
| def extension_add_event(self, code, evt, name = None): | |
| """extension_add_event(code, evt, [name]) | |
| Add an extension event. CODE is the numeric code, and EVT is | |
| the event class. EVT will be cloned, and the attribute _code | |
| of the new event class will be set to CODE. | |
| If NAME is omitted, it will be set to the name of EVT. This | |
| name is used to insert an entry in the DictWrapper | |
| extension_event. | |
| """ | |
| newevt = type(evt.__name__, evt.__bases__, | |
| evt.__dict__.copy()) | |
| newevt._code = code | |
| self.display.add_extension_event(code, newevt) | |
| if name is None: | |
| name = evt.__name__ | |
| setattr(self.extension_event, name, code) | |
| def extension_add_subevent(self, code, subcode, evt, name = None): | |
| """extension_add_subevent(code, evt, [name]) | |
| Add an extension subevent. CODE is the numeric code, subcode | |
| is the sub-ID of this event that shares the code ID with other | |
| sub-events and EVT is the event class. EVT will be cloned, and | |
| the attribute _code of the new event class will be set to CODE. | |
| If NAME is omitted, it will be set to the name of EVT. This | |
| name is used to insert an entry in the DictWrapper | |
| extension_event. | |
| """ | |
| newevt = type(evt.__name__, evt.__bases__, | |
| evt.__dict__.copy()) | |
| newevt._code = code | |
| self.display.add_extension_event(code, newevt, subcode) | |
| if name is None: | |
| name = evt.__name__ | |
| # store subcodes as a tuple of (event code, subcode) in the | |
| # extension dict maintained in the display object | |
| setattr(self.extension_event, name, (code,subcode)) | |
| def extension_add_error(self, code, err): | |
| """extension_add_error(code, err) | |
| Add an extension error. CODE is the numeric code, and ERR is | |
| the error class. | |
| """ | |
| self.display.add_extension_error(code, err) | |
| ### | |
| ### keymap cache implementation | |
| ### | |
| # The keycode->keysym map is stored in a list with 256 elements. | |
| # Each element represents a keycode, and the tuple elements are | |
| # the keysyms bound to the key. | |
| # The keysym->keycode map is stored in a mapping, where the keys | |
| # are keysyms. The values are a sorted list of tuples with two | |
| # elements each: (index, keycode) | |
| # keycode is the code for a key to which this keysym is bound, and | |
| # 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 | |
| returned.""" | |
| try: | |
| 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 | |
| returned.""" | |
| try: | |
| 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.""" | |
| try: | |
| # Copy the map list, reversing the arguments | |
| return map(lambda x: (x[1], x[0]), self._keymap_syms[keysym]) | |
| except KeyError: | |
| 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 | |
| object.""" | |
| if isinstance(evt, event.MappingNotify): | |
| if evt.request == X.MappingKeyboard: | |
| self._update_keymap(evt.first_keycode, evt.count) | |
| else: | |
| raise TypeError('expected a MappingNotify event') | |
| def _update_keymap(self, first_keycode, count): | |
| """Internal function, called to refresh the keymap cache. | |
| """ | |
| # Delete all sym->code maps for the changed codes | |
| lastcode = first_keycode + count | |
| for keysym, codes in self._keymap_syms.items(): | |
| i = 0 | |
| while i < len(codes): | |
| code = codes[i][1] | |
| if code >= first_keycode and code < lastcode: | |
| del codes[i] | |
| else: | |
| i = i + 1 | |
| # Get the new keyboard mapping | |
| keysyms = self.get_keyboard_mapping(first_keycode, count) | |
| # Replace code->sym map with the new map | |
| self._keymap_codes[first_keycode:lastcode] = keysyms | |
| # Update sym->code map | |
| code = first_keycode | |
| for syms in keysyms: | |
| index = 0 | |
| for sym in syms: | |
| if sym != X.NoSymbol: | |
| if sym in self._keymap_syms: | |
| symcodes = self._keymap_syms[sym] | |
| symcodes.append((index, code)) | |
| symcodes.sort() | |
| else: | |
| self._keymap_syms[sym] = [(index, code)] | |
| index = index + 1 | |
| code = code + 1 | |
| ### | |
| ### client-internal keysym to string translations | |
| ### | |
| def lookup_string(self, keysym): | |
| """Return a string corresponding to KEYSYM, or None if no | |
| reasonable translation is found. | |
| """ | |
| s = self.keysym_translations.get(keysym) | |
| if s is not None: | |
| return s | |
| import Xlib.XK | |
| return Xlib.XK.keysym_to_string(keysym) | |
| def rebind_string(self, keysym, newstring): | |
| """Change the translation of KEYSYM to NEWSTRING. | |
| If NEWSTRING is None, remove old translation if any. | |
| """ | |
| if newstring is None: | |
| try: | |
| del self.keysym_translations[keysym] | |
| except KeyError: | |
| pass | |
| else: | |
| self.keysym_translations[keysym] = newstring | |
| ### | |
| ### X requests | |
| ### | |
| def intern_atom(self, name, only_if_exists = False): | |
| """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(self, atom, only_if_exists = False): | |
| """Alias for intern_atom, using internal cache""" | |
| return self.display.get_atom(atom, only_if_exists) | |
| 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) | |
| return r.name | |
| 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 = False, | |
| 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 | |
| protocol.events. See XSendEvent(3X11) for details. | |
| There is also a Window.send_event() method.""" | |
| request.SendEvent(display = self.display, | |
| onerror = onerror, | |
| propagate = propagate, | |
| destination = destination, | |
| event_mask = event_mask, | |
| event = event) | |
| def ungrab_pointer(self, time, onerror = None): | |
| """Release a grabbed pointer and any queued events. See | |
| XUngrabPointer(3X11).""" | |
| 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 | |
| XChangeActivePointerGrab(3X11).""" | |
| request.ChangeActivePointerGrab(display = self.display, | |
| onerror = onerror, | |
| cursor = cursor, | |
| time = time, | |
| event_mask = event_mask) | |
| def ungrab_keyboard(self, time, onerror = None): | |
| """Ungrab a grabbed keyboard and any queued events. See | |
| XUngrabKeyboard(3X11).""" | |
| 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 = 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, | |
| dst_window = X.NONE, | |
| src_x = src_x, | |
| src_y = src_y, | |
| src_width = src_width, | |
| src_height = src_height, | |
| dst_x = x, | |
| 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, | |
| focus = focus, | |
| time = time) | |
| def get_input_focus(self): | |
| """Return an object with the following attributes: | |
| focus | |
| The window which currently holds the input | |
| focus, X.NONE or X.PointerRoot. | |
| revert_to | |
| 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) | |
| return r.map | |
| 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) | |
| request.OpenFont(display = self.display, | |
| onerror = ec, | |
| fid = fid, | |
| name = name) | |
| self.sync() | |
| if ec.get_error(): | |
| self.display.free_resource_id(fid) | |
| return None | |
| else: | |
| cls = self.display.get_resource_class('font', fontable.Font) | |
| 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: | |
| name | |
| The name of the font. | |
| min_bounds | |
| max_bounds | |
| min_char_or_byte2 | |
| max_char_or_byte2 | |
| default_char | |
| draw_direction | |
| min_byte1 | |
| max_byte1 | |
| all_chars_exist | |
| font_ascent | |
| font_descent | |
| replies_hint | |
| See the description of XFontStruct in XGetFontProperty(3X11) | |
| for details on these values. | |
| properties | |
| A list of properties. Each entry has two attributes: | |
| name | |
| The atom identifying this property. | |
| value | |
| 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 | |
| restored.""" | |
| 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: | |
| major_opcode | |
| The major opcode that the requests of this extension uses. | |
| first_event | |
| The base event code if the extension have additional events, or 0. | |
| first_error | |
| 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: | |
| return r | |
| else: | |
| 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: | |
| key_click_percent | |
| The volume of key clicks between 0 (off) and 100 (load). | |
| -1 will restore default setting. | |
| bell_percent | |
| The base volume of the bell, coded as above. | |
| bell_pitch | |
| The pitch of the bell in Hz, -1 restores the default. | |
| bell_duration | |
| The duration of the bell in milliseconds, -1 restores | |
| the default. | |
| led | |
| led_mode | |
| 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. | |
| key | |
| auto_repeat_mode | |
| 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: | |
| global_auto_repeat | |
| X.AutoRepeatModeOn or X.AutoRepeatModeOff. | |
| auto_repeats | |
| 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. | |
| led_mask | |
| A 32-bit mask indicating which LEDs are on. | |
| key_click_percent | |
| The volume of key click, from 0 to 100. | |
| bell_percent | |
| bell_pitch | |
| bell_duration | |
| 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 | |
| accel_denum = 0 | |
| else: | |
| do_accel = 1 | |
| accel_num, accel_denum = accel | |
| if threshold is None: | |
| do_threshold = 0 | |
| else: | |
| do_threshold = 1 | |
| request.ChangePointerControl(display = self.display, | |
| onerror = onerror, | |
| do_accel = do_accel, | |
| do_thresh = do_threshold, | |
| accel_num = accel_num, | |
| accel_denum = accel_denum, | |
| threshold = threshold) | |
| def get_pointer_control(self): | |
| """Return an object with the following attributes: | |
| accel_num | |
| accel_denom | |
| The acceleration as numerator/denumerator. | |
| threshold | |
| 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, | |
| interval = interval, | |
| prefer_blank = prefer_blank, | |
| 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 | |
| details.""" | |
| 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, X.FamilyChaos, | |
| X.FamilyServerInterpreted or X.FamilyInternetV6. | |
| 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, | |
| host_family = host_family, | |
| host = host) | |
| def list_hosts(self): | |
| """Return an object with the following attributes: | |
| mode | |
| X.EnableAccess if the access control list is used, X.DisableAccess otherwise. | |
| hosts | |
| The hosts on the access list. Each entry has the following attributes: | |
| family | |
| X.FamilyInternet, X.FamilyDECnet, X.FamilyChaos, X.FamilyServerInterpreted or X.FamilyInternetV6. | |
| name | |
| A list of byte values, the coding depends on family. For the Internet family, it is the 4 bytes of an IPv4 address. | |
| """ | |
| return request.ListHosts(display = self.display) | |
| def set_access_control(self, mode, onerror = None): | |
| """Enable use of access control lists at connection setup if mode | |
| is X.EnableAccess, disable if it is X.DisableAccess.""" | |
| request.SetAccessControl(display = self.display, | |
| onerror = onerror, | |
| mode = mode) | |
| def set_close_down_mode(self, mode, onerror = None): | |
| """Control what will happen with the client's resources at | |
| connection close. The default is X.DestroyAll, the other values | |
| are X.RetainPermanent and X.RetainTemporary.""" | |
| request.SetCloseDownMode(display = self.display, | |
| onerror = onerror, | |
| mode = mode) | |
| def force_screen_saver(self, mode, onerror = None): | |
| """If mode is X.ScreenSaverActive the screen saver is activated. | |
| If it is X.ScreenSaverReset, the screen saver is deactivated as | |
| if device input had been received.""" | |
| request.ForceScreenSaver(display = self.display, | |
| onerror = onerror, | |
| mode = mode) | |
| def set_pointer_mapping(self, map): | |
| """Set the mapping of the pointer buttons. map is a list of | |
| logical button numbers. map must be of the same length as the | |
| list returned by Display.get_pointer_mapping(). | |
| map[n] sets the | |
| logical number for the physical button n+1. Logical number 0 | |
| disables the button. Two physical buttons cannot be mapped to the | |
| same logical number. | |
| If one of the buttons to be altered are | |
| logically in the down state, X.MappingBusy is returned and the | |
| mapping is not changed. Otherwise the mapping is changed and | |
| X.MappingSuccess is returned.""" | |
| r = request.SetPointerMapping(display = self.display, | |
| map = map) | |
| return r.status | |
| def get_pointer_mapping(self): | |
| """Return a list of the pointer button mappings. Entry N in the | |
| list sets the logical button number for the physical button N+1.""" | |
| r = request.GetPointerMapping(display = self.display) | |
| return r.map | |
| def set_modifier_mapping(self, keycodes): | |
| """Set the keycodes for the eight modifiers X.Shift, X.Lock, | |
| X.Control, X.Mod1, X.Mod2, X.Mod3, X.Mod4 and X.Mod5. keycodes | |
| should be a eight-element list where each entry is a list of the | |
| keycodes that should be bound to that modifier. | |
| If any changed | |
| key is logically in the down state, X.MappingBusy is returned and | |
| the mapping is not changed. If the mapping violates some server | |
| restriction, X.MappingFailed is returned. Otherwise the mapping | |
| is changed and X.MappingSuccess is returned.""" | |
| r = request.SetModifierMapping(display = self.display, | |
| keycodes = keycodes) | |
| return r.status | |
| def get_modifier_mapping(self): | |
| """Return a list of eight lists, one for each modifier. The list | |
| can be indexed using X.ShiftMapIndex, X.Mod1MapIndex, and so on. | |
| The sublists list the keycodes bound to that modifier.""" | |
| r = request.GetModifierMapping(display = self.display) | |
| return r.keycodes | |
| def no_operation(self, onerror = None): | |
| """Do nothing but send a request to the server.""" | |
| request.NoOperation(display = self.display, | |
| onerror = onerror) | |