def set_modifiers_from_text(xkbmap_mod_add): """ This is the old, backwards compatibility method.. We are given some modifiers instructions in plain text, and if missing we use the ones from XMODMAP_MOD_ADD. We parse those and then must ensure all the key names actually exist before trying to change the keymap. We must also ensure that keycodes are only assigned to a single modifier. This is also used to ensure that the keynames_for_mod dict we return is valid. """ import gtk.gdk root = gtk.gdk.get_default_root_window() from xpra.keys import XMODMAP_MOD_ADD, ALL_X11_MODIFIERS instructions = parse_xmodmap(xkbmap_mod_add or XMODMAP_MOD_ADD) log.debug("instructions=%s", instructions) oked = [] keycodes_used = {} modifiers = {} for instr in instructions: if not instr or instr[0]!="add": log.error("invalid instruction in modifier text: %s", instr) continue modifier_int = instr[1] modifier = -1 for m,v in ALL_X11_MODIFIERS.items(): if v==modifier_int: modifier = m break if modifier<0: log.error("unknown modifier int: %s", modifier) continue keysyms_strs = instr[2] keysyms = [] for keysym_str in keysyms_strs: keycodes = get_keycodes(root, keysym_str) if len(keycodes)==0: log.debug("keysym '%s' does not have a keycode, ignoring: %s", keysym_str, keysym_str) continue #found some keycodes, so we can use this keysym #after first verifying they aren't used yet: keycodes_free = True for keycode in keycodes: if keycode in keycodes_used: log.debug("%s as keycode %s is already used by %s, ignoring: %s", keysym_str, keycode, keycodes_used.get(keycode), instr) keycodes_free = False break if keycodes_free: for keycode in keycodes: keycodes_used[keycode] = modifier keysyms.append(keysym_str) if len(keysyms)>0: modifiers[modifier] = keysyms oked.append(("add", modifier_int, keysyms)) log.debug("set_modifiers_from_text: %s", oked) unset = apply_xmodmap(oked) log.debug("set_modifiers_from_text failed on: %s", unset) log.debug("set_modifiers_from_text(..)=%s", modifiers) return modifiers
def set_keymap(self, client_platform): if not self.enabled: return clean_keyboard_state() try: do_set_keymap(self.xkbmap_layout, self.xkbmap_variant, self.xkbmap_print, self.xkbmap_query) except: log.error("error setting new keymap", exc_info=True) self.is_native_keymap = self.xkbmap_print!="" or self.xkbmap_query!="" self.make_modifiers_match = (client_platform and not client_platform.startswith("win")) or self.is_native_keymap try: #first clear all existing modifiers: clean_keyboard_state() clear_modifiers(ALL_X11_MODIFIERS.keys()) #just clear all of them (set or not) #now set all the keycodes: clean_keyboard_state() self.keycode_translation = {} has_keycodes = (self.xkbmap_x11_keycodes and len(self.xkbmap_x11_keycodes)>0) or \ (self.xkbmap_keycodes and len(self.xkbmap_keycodes)>0) assert has_keycodes, "client failed to provide any keycodes!" #first compute the modifier maps as this may have an influence #on the keycode mappings (at least for the from_keycodes case): if self.xkbmap_mod_meanings: #Unix-like OS provides modifier meanings: self.keynames_for_mod = get_modifiers_from_meanings(self.xkbmap_mod_meanings) elif self.xkbmap_keycodes: #non-Unix-like OS provides just keycodes for now: self.keynames_for_mod = get_modifiers_from_keycodes(self.xkbmap_keycodes) else: log.error("missing both xkbmap_mod_meanings and xkbmap_keycodes, modifiers will probably not work as expected!") self.keynames_for_mod = {} #if the client does not provide a full keymap, #try to preserve the initial server keycodes #(used by non X11 clients like osx,win32 or Android) preserve_server_keycodes = not self.xkbmap_print and not self.xkbmap_query self.keycode_translation = set_all_keycodes(self.xkbmap_x11_keycodes, self.xkbmap_keycodes, preserve_server_keycodes, self.keynames_for_mod) #now set the new modifier mappings: clean_keyboard_state() debug("going to set modifiers, xkbmap_mod_meanings=%s, len(xkbmap_keycodes)=%s", self.xkbmap_mod_meanings, len(self.xkbmap_keycodes or [])) if self.keynames_for_mod: set_modifiers(self.keynames_for_mod) self.compute_modifier_keynames() self.compute_client_modifier_keycodes() debug("keyname_for_mod=%s", self.keynames_for_mod) except: log.error("error setting xmodmap", exc_info=True)
def set_modifiers_from_text(xkbmap_mod_add): """ This is the old, backwards compatibility method.. We are given some modifiers instructions in plain text, and if missing we use the ones from XMODMAP_MOD_ADD. We parse those and then must ensure all the key names actually exist before trying to change the keymap. We must also ensure that keycodes are only assigned to a single modifier. This is also used to ensure that the keynames_for_mod dict we return is valid. """ import gtk.gdk root = gtk.gdk.get_default_root_window() from xpra.keys import XMODMAP_MOD_ADD, ALL_X11_MODIFIERS instructions = parse_xmodmap(xkbmap_mod_add or XMODMAP_MOD_ADD) log.debug("instructions=%s", instructions) oked = [] keycodes_used = {} modifiers = {} for instr in instructions: if not instr or instr[0] != "add": log.error("invalid instruction in modifier text: %s", instr) continue modifier_int = instr[1] modifier = -1 for m, v in ALL_X11_MODIFIERS.items(): if v == modifier_int: modifier = m break if modifier < 0: log.error("unknown modifier int: %s", modifier) continue keysyms_strs = instr[2] keysyms = [] for keysym_str in keysyms_strs: keycodes = get_keycodes(root, keysym_str) if len(keycodes) == 0: log.debug("keysym '%s' does not have a keycode, ignoring: %s", keysym_str, keysym_str) continue #found some keycodes, so we can use this keysym #after first verifying they aren't used yet: keycodes_free = True for keycode in keycodes: if keycode in keycodes_used: log.debug( "%s as keycode %s is already used by %s, ignoring: %s", keysym_str, keycode, keycodes_used.get(keycode), instr) keycodes_free = False break if keycodes_free: for keycode in keycodes: keycodes_used[keycode] = modifier keysyms.append(keysym_str) if len(keysyms) > 0: modifiers[modifier] = keysyms oked.append(("add", modifier_int, keysyms)) log.debug("set_modifiers_from_text: %s", oked) unset = apply_xmodmap(oked) log.debug("set_modifiers_from_text failed on: %s", unset) log.debug("set_modifiers_from_text(..)=%s", modifiers) return modifiers
def set_keymap(self, client_platform): if not self.enabled: return clean_keyboard_state() try: do_set_keymap(self.xkbmap_layout, self.xkbmap_variant, self.xkbmap_print, self.xkbmap_query) except: log.error("error setting new keymap", exc_info=True) self.is_native_keymap = self.xkbmap_print != "" or self.xkbmap_query != "" try: #first clear all existing modifiers: clean_keyboard_state() clear_modifiers( ALL_X11_MODIFIERS.keys()) #just clear all of them (set or not) #now set all the keycodes: clean_keyboard_state() self.keycode_translation = {} has_keycodes = (self.xkbmap_x11_keycodes and len(self.xkbmap_x11_keycodes)>0) or \ (self.xkbmap_keycodes and len(self.xkbmap_keycodes)>0) assert has_keycodes, "client failed to provide any keycodes!" #first compute the modifier maps as this may have an influence #on the keycode mappings (at least for the from_keycodes case): if self.xkbmap_mod_meanings: #Unix-like OS provides modifier meanings: self.keynames_for_mod = get_modifiers_from_meanings( self.xkbmap_mod_meanings) elif self.xkbmap_keycodes: #non-Unix-like OS provides just keycodes for now: self.keynames_for_mod = get_modifiers_from_keycodes( self.xkbmap_keycodes) else: log.error( "missing both xkbmap_mod_meanings and xkbmap_keycodes, modifiers will probably not work as expected!" ) self.keynames_for_mod = {} #if the client does not provide a full keymap, #try to preserve the initial server keycodes #(used by non X11 clients like osx,win32 or Android) preserve_server_keycodes = not self.xkbmap_print and not self.xkbmap_query self.keycode_translation = set_all_keycodes( self.xkbmap_x11_keycodes, self.xkbmap_keycodes, preserve_server_keycodes, self.keynames_for_mod) #now set the new modifier mappings: clean_keyboard_state() debug( "going to set modifiers, xkbmap_mod_meanings=%s, len(xkbmap_keycodes)=%s", self.xkbmap_mod_meanings, len(self.xkbmap_keycodes or [])) if self.keynames_for_mod: set_modifiers(self.keynames_for_mod) self.compute_modifier_keynames() self.compute_client_modifier_keycodes() debug("keyname_for_mod=%s", self.keynames_for_mod) except: log.error("error setting xmodmap", exc_info=True) if (client_platform and client_platform.startswith("win") ) and not self.is_native_keymap: self.modifiers_filter = ["lock"] num_mods = [ mod for mod, keynames in self.keynames_for_mod.items() if "Num_Lock" in keynames ] if len(num_mods) == 1: self.modifiers_filter.append(num_mods[0]) else: log.warn("found more than one modifier for 'Num_Lock': %s", num_mods)