def keymap_new_from_file(self, file, format=lib.XKB_KEYMAP_FORMAT_TEXT_V1): "Create a Keymap from an open file" try: fn = file.fileno() except: fn = None if fn: load_method = "mmap_file" mm = mmap.mmap(fn, 0) buf = ffi.from_buffer(mm) r = lib.xkb_keymap_new_from_buffer(self._context, buf, mm.size(), format, lib.XKB_KEYMAP_COMPILE_NO_FLAGS) del buf mm.close() else: load_method = "read_file" keymap = file.read() buf = ffi.new("char[]", keymap) r = lib.xkb_keymap_new_from_string(self._context, buf, format, lib.XKB_KEYMAP_COMPILE_NO_FLAGS) if r == ffi.NULL: raise XKBKeymapCreationFailure( "xkb_keymap_new_from_buffer or xkb_keymap_new_from_string " "returned NULL") return Keymap(self, r, load_method)
def keymap_new_from_names(self, rules=None, model=None, layout=None, variant=None, options=None): """Create a keymap from RMLVO names. The primary keymap entry point: creates a new XKB keymap from a set of RMLVO (Rules + Model + Layouts + Variants + Options) names. Returns a Keymap compiled according to the RMLVO names, or None if the compilation failed. """ names = ffi.new("struct xkb_rule_names *") if rules: names.rules = rules.encode() if model: names.model = model.encode() if layout: names.layout = layout.encode() if variant: names.variant = variant.encode() if options: names.options = options.encode() r = lib.xkb_keymap_new_from_names(self._context, names, lib.XKB_KEYMAP_COMPILE_NO_FLAGS) if r == ffi.NULL: raise XKBKeymapCreationFailure( "xkb_keymap_new_from_names returned NULL") return Keymap(self, r, "names")
def keysym_to_string(keysym): buffer = ffi.new("char[64]") r = lib.xkb_keysym_to_utf8(keysym, buffer, len(buffer)) if r == -1: raise XKBBufferTooSmall() if r == 0: return return ffi.string(buffer).decode('utf8')
def keysym_get_name(keysym): "Get the name of a keysym." name = ffi.new("char[64]") r = lib.xkb_keysym_get_name(keysym, name, len(name)) if r == -1: raise XKBInvalidKeysym() if r > len(name): raise XKBBufferTooSmall() return ffi.string(name).decode('ascii')
def led_get_index(self, name): """Get the index of a LED by name. Returns the index. If no LED with this name exists, returns lib.XKB_LED_INVALID. """ r = lib.xkb_keymap_led_get_index( self._keymap, ffi.new("char []", name.encode('ascii'))) if r == lib.XKB_LED_INVALID: raise XKBLEDDoesNotExist(name) return r
def mod_get_index(self, name): """Get the index of a modifier by name. Returns the index. If no modifier with this name exists, raises XKBModifierDoesNotExist. """ r = lib.xkb_keymap_mod_get_index( self._keymap, ffi.new("char []", name.encode('ascii'))) if r == lib.XKB_MOD_INVALID: raise XKBModifierDoesNotExist(name) return r
def keymap_new_from_string(self, string, format=lib.XKB_KEYMAP_FORMAT_TEXT_V1): "Create a Keymap from a keymap string." buf = ffi.new("char[]", string.encode("ascii")) r = lib.xkb_keymap_new_from_string(self._context, buf, format, lib.XKB_KEYMAP_COMPILE_NO_FLAGS) if r == ffi.NULL: raise XKBKeymapCreationFailure( "xkb_keymap_new_from_string returned NULL") return Keymap(self, r, "string")
def layout_get_index(self, name): """Get the index of a layout by name. Returns the index. If no layout exists with this name, raises XKBLayoutDoesNotExist. If more than one layout in the keymap has this name, returns the lowest index among them. """ r = lib.xkb_keymap_layout_get_index( self._keymap, ffi.new("char []", name.encode('ascii'))) if r == lib.XKB_LAYOUT_INVALID: raise XKBLayoutDoesNotExist(name) return r
def led_name_is_active(self, name): """Test whether a LED is active in a given keyboard state by name. Returns True if the LED is active, False if it is not. If no LED with this name exists in the keymap, raises XKBLEDDoesNotExist. """ buf = ffi.new("char []", name.encode('ascii')) r = lib.xkb_state_led_name_is_active(self._state, buf) if r == -1: raise XKBLEDDoesNotExist(name) return r == 1
def keymap_new_from_names(self, rules=None, model=None, layout=None, variant=None, options=None): """Create a keymap from RMLVO names. The primary keymap entry point: creates a new XKB keymap from a set of RMLVO (Rules + Model + Layouts + Variants + Options) names. Returns a Keymap compiled according to the RMLVO names, or None if the compilation failed. """ # CFFI memory management note: # The C strings allocated below using ffi.new("char[]", ...) # are automatically deallocated when there are no remaining # python references to them. Being assigned to members of the # 'names' struct does not count as a reference! We keep # references to them in the 'keep_alive' list until after the # call to xkb_keymap_new_from_names() to avoid problems with # use-after-free. names = ffi.new("struct xkb_rule_names *") keep_alive = [] for x in ("rules", "model", "layout", "variant", "options"): if locals()[x]: c = ffi.new("char[]", locals()[x].encode()) setattr(names, x, c) keep_alive.append(c) r = lib.xkb_keymap_new_from_names(self._context, names, lib.XKB_KEYMAP_COMPILE_NO_FLAGS) del keep_alive, names if r == ffi.NULL: raise XKBKeymapCreationFailure( "xkb_keymap_new_from_names returned NULL") return Keymap(self, r, "names")
def key_get_string(self, key): """Get the Unicode/UTF-8 string obtained from pressing a particular key in a given keyboard state. This function performs Capitalization and Control Keysym Transformations. Returns the string. If there is nothing to return, returns the empty string. """ buffer = ffi.new("char[64]") r = lib.xkb_state_key_get_utf8(self._state, key, buffer, len(buffer)) if r + 1 > len(buffer): raise XKBBufferTooSmall() return ffi.string(buffer).decode('utf8')
def layout_name_is_active(self, name, type): """Test whether a layout is active in a given keyboard state by name. Returns True if the layout is active, False if it is not. If no layout with this name exists in the keymap, raises XKBLayoutDoesNotExist. If multiple layouts in the keymap have this name, the one with the lowest index is tested. """ buf = ffi.new("char []", name.encode('ascii')) r = lib.xkb_state_layout_name_is_active(self._state, buf, type) if r == -1: raise XKBLayoutDoesNotExist(name) return r == 1
def mod_name_is_active(self, name, type): """Test whether a modifier is active in a given keyboard state by name. type is the component of the state against which to match the given modifiers. Returns True if the modifier is active, False if it is not. If the modifier name does not exist in the keymap, raises XKBModifierDoesNotExist. """ buf = ffi.new("char []", name.encode('ascii')) r = lib.xkb_state_mod_name_is_active(self._state, buf, type) if r == -1: raise XKBModifierDoesNotExist(name) return r == 1
def key_get_syms_by_level(self, key, layout, level): """Get the keysyms obtained from pressing a key in a given layout and shift level. This function is like State.key_get_syms(), only the layout and shift level are not derived from the keyboard state but are instead specified explicitly. Returns a list of keysyms. """ syms_out = ffi.new("const xkb_keysym_t **") r = lib.xkb_keymap_key_get_syms_by_level(self._keymap, key, layout, level, syms_out) syms = [] if r > 0: assert syms_out[0] != ffi.NULL for i in range(0, r): syms.append(syms_out[0][i]) return syms
def mod_names_are_active(self, type, match, names): """Test whether a set of modifiers are active in a given keyboard state by name. type is the component of the state against which to match the given modifiers. match is the manner by which to match the state against the given modifiers. names is an iterable of modifier names to test. Returns True if the modifiers are active, False if they are not. If any of the modifier names do not exist, raises XKBModifierDoesNotExist(None). """ args = [ffi.new("char []", n.encode('ascii')) for n in names] args.append(ffi.NULL) r = lib.xkb_state_mod_names_are_active(self._state, type, match, *args) if r == -1: raise XKBModifierDoesNotExist(None) return r == 1
def key_get_syms(self, key): """Get the keysyms obtained from pressing a particular key in a given keyboard state. Get the keysyms for a key according to the current active layout, modifiers and shift level for the key, as determined by a keyboard state. As an extension to XKB, this function can return more than one keysym. If you do not want to handle this case, you can use KeyboardState.key_get_one_sym() for a simpler interface. This function does not perform any Keysym Transformations. (This might change). """ syms_out = ffi.new("const xkb_keysym_t **") r = lib.xkb_state_key_get_syms(self._state, key, syms_out) syms = [] if r > 0: assert syms_out[0] != ffi.NULL for i in range(0, r): syms.append(syms_out[0][i]) return syms