Beispiel #1
0
def do_set_keymap(xkbmap_layout, xkbmap_variant, xkbmap_options,
                  xkbmap_print, xkbmap_query, xkbmap_query_struct={}):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        xkbmap_query_struct is xkbmap_query parsed into a dictionary
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query,
    #preferably as structured data:
    if xkbmap_query and not xkbmap_query_struct:
        from xpra.keyboard.layouts import parse_xkbmap_query
        xkbmap_query_struct = parse_xkbmap_query(xkbmap_query)
    if xkbmap_query_struct:
        log("do_set_keymap using xkbmap_query struct=%s", xkbmap_query_struct)
        """ The xkbmap_query_struct data will look something like this:
            {
            b"rules"       : b"evdev",
            b"model"       : b"pc105",
            b"layout"      : b"gb",
            b"options"     : b"grp:shift_caps_toggle",
            }
        """
        #parse the data into a dict:
        rules = xkbmap_query_struct.get(b"rules")
        model = xkbmap_query_struct.get(b"model")
        layout = xkbmap_query_struct.get(b"layout")
        variant = xkbmap_query_struct.get(b"variant")
        options = xkbmap_query_struct.get(b"options")
        if layout:
            log.info("setting keymap: %s",
                     csv("%s=%s" % (std(k), std(v)) for k,v in xkbmap_query_struct.items()
                         if k in ("rules", "model", "layout") and v))
            safe_setxkbmap(rules, model, layout, variant, options)
        else:
            safe_setxkbmap(rules, model, "", "", "")
    if xkbmap_print:
        #TODO: this is no longer used with any client, remove it
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile(r"\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    safe_setxkbmap("evdev", "pc105", layout, "", xkbmap_options)
                    return
        except Exception as e:
            log.info("error setting keymap: %s" % e)
    #fallback for non X11 clients:
    layout = xkbmap_layout or "us"
    log.info("setting keyboard layout to '%s'", std(layout))
    safe_setxkbmap("evdev", "pc105", layout, xkbmap_variant, xkbmap_options)
Beispiel #2
0
def do_set_keymap(xkbmap_layout, xkbmap_variant,
                  xkbmap_print, xkbmap_query):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query
    if xkbmap_query:
        log("do_set_keymap using xkbmap_query")
        """ The xkbmap_query data will look something like this:
        rules:      evdev
        model:      evdev
        layout:     gb
        options:    grp:shift_caps_toggle
        (we execute the options separately in case that fails..)
        """
        #parse the data into a dict:
        settings = parse_xkbmap_query(xkbmap_query)
        rules = settings.get("rules")
        model = settings.get("model")
        layout = settings.get("layout")
        variant = settings.get("variant")
        options = settings.get("options")
        if layout:
            log.info("setting keymap: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in settings.items() if k in ["rules", "model", "layout"] and v]))
            try:
                X11Keyboard.setxkbmap(rules, model, layout, variant, options)
                return
            except:
                log.warn("failed to set exact keymap using %s", settings)
            if options:
                #try again with no options:
                try:
                    X11Keyboard.setxkbmap(rules, model, layout, variant, "")
                except:
                    log.error("failed to set exact keymap even without applying options")
    if xkbmap_print:
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    X11Keyboard.setxkbmap("", "pc104", layout, "", "")
                    return
        except Exception as e:
            log.info("error setting keymap: %s" % e)
    #fallback:
    layout = xkbmap_layout or "us"
    log.info("setting keyboard layout to '%s'", std(layout))
    X11Keyboard.setxkbmap("", "", layout, xkbmap_variant, "")
    def test_parse_xkbmap_query(self):
        d = parse_xkbmap_query("""rules:      evdev
model:      pc105
layout:     gb,us,gb
variant:    ,,
""")
        assert d.get("rules") == "evdev"
        assert d.get("layout") == "gb,us,gb"
        assert not d.get("variant")
Beispiel #4
0
def do_set_keymap(xkbmap_layout, xkbmap_variant,
                  xkbmap_print, xkbmap_query):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query
    if xkbmap_query:
        log("do_set_keymap using xkbmap_query")
        """ The xkbmap_query data will look something like this:
        rules:      evdev
        model:      evdev
        layout:     gb
        options:    grp:shift_caps_toggle
        And we want to call something like:
        setxkbmap -rules evdev -model evdev -layout gb
        setxkbmap -option "" -option grp:shift_caps_toggle
        (we execute the options separately in case that fails..)
        """
        #parse the data into a dict:
        settings = parse_xkbmap_query(xkbmap_query)
        #construct the command line arguments for setxkbmap:
        args = ["setxkbmap"]
        used_settings = {}
        for setting in ["rules", "model", "layout"]:
            if setting in settings:
                value = settings.get(setting)
                args += ["-%s" % setting, value]
                used_settings[setting] = value
        if len(args)==1:
            log.warn("do_set_keymap could not find rules, model or layout in the xkbmap query string..")
        else:
            log.info("setting keymap: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in used_settings.items()]))
        exec_keymap_command(args)
        #try to set the options:
        if "options" in settings:
            log.info("setting keymap options: %s", std(str(settings.get("options"))))
            exec_keymap_command(["setxkbmap", "-option", "", "-option", settings.get("options")])
    elif xkbmap_print:
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    exec_keymap_command(["setxkbmap", layout])
                    break
        except Exception, e:
            log.info("error setting keymap: %s" % e)
Beispiel #5
0
def do_set_keymap(xkbmap_layout, xkbmap_variant,
                  xkbmap_print, xkbmap_query):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query
    if xkbmap_query:
        log("do_set_keymap using xkbmap_query")
        """ The xkbmap_query data will look something like this:
        rules:      evdev
        model:      evdev
        layout:     gb
        options:    grp:shift_caps_toggle
        (we execute the options separately in case that fails..)
        """
        #parse the data into a dict:
        settings = parse_xkbmap_query(xkbmap_query)
        rules = settings.get("rules")
        model = settings.get("model")
        layout = settings.get("layout")
        variant = settings.get("variant")
        options = settings.get("options")
        log.info("setting keymap: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in settings.items() if k in ["rules", "model", "layout"] and v]))
        try:
            X11Keyboard.setxkbmap(rules, model, layout, variant, options)
        except:
            log.warn("failed to set exact keymap using %s", settings)
            #try again with no options:
            try:
                X11Keyboard.setxkbmap(rules, model, layout, variant, "")
            except:
                log.error("failed to set exact keymap even without applying options")
    elif xkbmap_print:
        log("do_set_keymap using xkbmap_print")
        #try to guess the layout by parsing "setxkbmap -print"
        try:
            sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)")
            for line in xkbmap_print.splitlines():
                m = sym_re.match(line)
                if m:
                    layout = std(m.group(1))
                    log.info("guessing keyboard layout='%s'" % layout)
                    X11Keyboard.setxkbmap("", "pc104", layout, "", "")
        except Exception as e:
            log.info("error setting keymap: %s" % e)
    else:
        layout = xkbmap_layout or "us"
        log.info("setting keyboard layout to '%s'", std(layout))
        X11Keyboard.setxkbmap("", "", layout, xkbmap_variant, "")
Beispiel #6
0
 def get_keymap_spec_using_setxkbmap(self):
     xkbmap_print = self.exec_get_keyboard_data(["setxkbmap", "-print"])
     if xkbmap_print is None:
         log.error("your keyboard mapping will probably be incorrect unless you are using a 'us' layout")
     xkbmap_query = self.exec_get_keyboard_data(["setxkbmap", "-query"])
     if xkbmap_query is None and xkbmap_print is not None:
         log.error("the server will try to guess your keyboard mapping, which works reasonably well in most cases")
         log.error("however, upgrading 'setxkbmap' to a version that supports the '-query' parameter is preferred")
         xkbmap_query_struct = parse_xkbmap_query(xkbmap_query)
     else:
         xkbmap_query_struct = {}
     return xkbmap_print, xkbmap_query, xkbmap_query_struct
Beispiel #7
0
def do_set_keymap(xkbmap_layout, xkbmap_variant, xkbmap_options, xkbmap_query,
                  xkbmap_query_struct):
    """ xkbmap_layout is the generic layout name (used on non posix platforms)
        xkbmap_variant is the layout variant (may not be set)
        xkbmap_print is the output of "setxkbmap -print" on the client
        xkbmap_query is the output of "setxkbmap -query" on the client
        xkbmap_query_struct is xkbmap_query parsed into a dictionary
        Use those to try to setup the correct keyboard map for the client
        so that all the keycodes sent will be mapped
    """
    #First we try to use data from setxkbmap -query,
    #preferably as structured data:
    if xkbmap_query and not xkbmap_query_struct:
        xkbmap_query_struct = parse_xkbmap_query(xkbmap_query)
    xkbmap_query_struct = typedict(xkbmap_query_struct)
    if xkbmap_query_struct:
        log("do_set_keymap using xkbmap_query struct=%s", xkbmap_query_struct)
        #The xkbmap_query_struct data will look something like this:
        #    {
        #    b"rules"       : b"evdev",
        #    b"model"       : b"pc105",
        #    b"layout"      : b"gb",
        #    b"options"     : b"grp:shift_caps_toggle",
        #    }
        #parse the data into a dict:
        rules = xkbmap_query_struct.strget("rules")
        model = xkbmap_query_struct.strget("model")
        layout = xkbmap_query_struct.strget("layout")
        variant = xkbmap_query_struct.strget("variant")
        options = xkbmap_query_struct.strget("options")
        if layout:
            log.info(
                "setting keymap: %s",
                csv("%s=%s" % (std(k), std(v))
                    for k, v in xkbmap_query_struct.items()
                    if k in ("rules", "model", "layout", "variant",
                             "options") and v))
            safe_setxkbmap(rules, model, layout, variant, options)
        else:
            safe_setxkbmap(rules, model, "", "", "")
    #fallback for non X11 clients:
    layout = xkbmap_layout or "us"
    log.info("setting keyboard layout to '%s'", std(layout))
    safe_setxkbmap("evdev", "pc105", layout, xkbmap_variant, xkbmap_options)
Beispiel #8
0
 def log_keyboard_info(self):
     #show the user a summary of what we have detected:
     kb_info = {}
     if self.xkbmap_query_struct or self.xkbmap_query:
         xkbqs = self.xkbmap_query_struct
         if xkbqs:
             #parse query into a dict
             from xpra.keyboard.layouts import parse_xkbmap_query
             xkbqs = parse_xkbmap_query(self.xkbmap_query)
         for x in ["rules", "model", "layout"]:
             v = xkbqs.get(x)
             if v:
                 kb_info[x] = v
     if self.xkbmap_layout:
         kb_info["layout"] = self.xkbmap_layout
     if len(kb_info)==0:
         log.info(" using default keyboard settings")
     else:
         log.info(" keyboard settings: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in kb_info.items()]))
Beispiel #9
0
 def log_keyboard_info(self):
     #show the user a summary of what we have detected:
     kb_info = {}
     if self.xkbmap_query_struct or self.xkbmap_query:
         xkbqs = self.xkbmap_query_struct
         if xkbqs:
             #parse query into a dict
             from xpra.keyboard.layouts import parse_xkbmap_query
             xkbqs = parse_xkbmap_query(self.xkbmap_query)
         for x in ["rules", "model", "layout"]:
             v = xkbqs.get(x)
             if v:
                 kb_info[x] = v
     if self.xkbmap_layout:
         kb_info["layout"] = self.xkbmap_layout
     if len(kb_info)==0:
         log.info(" using default keyboard settings")
     else:
         log.info(" keyboard settings: %s", ", ".join(["%s=%s" % (std(k), std(v)) for k,v in kb_info.items()]))