Esempio n. 1
0
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
Esempio n. 2
0
    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)
Esempio n. 3
0
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
Esempio n. 4
0
    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)