def make_window_clicktrough(self): dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) # I have no idea why this works... win = X.XID(self.get_window().get_xid()) reg = X.create_region(dpy, None, 0) X.set_window_shape_region (dpy, win, X.SHAPE_BOUNDING, 0, 0, 0) X.set_window_shape_region (dpy, win, X.SHAPE_INPUT, 0, 0, reg) X.destroy_region (dpy, reg)
def __fill_layouts_dict(): """assemble dictionary of layout codes to corresponding layout name """ _xkl_engine = Xkl.Engine.get_instance(GdkX11.x11_get_default_xdisplay()) _xkl_registry = Xkl.ConfigRegistry.get_instance(_xkl_engine) _xkl_registry.load(False) layouts_dict = {} def variant_iter(registry, variant, layout): code = '%s/%s' % (xkl_strip(layout.name), xkl_strip(variant.name)) description = '%s - %s' % (xkl_strip(layout.description), xkl_strip(variant.description)) if code not in layouts_dict: layouts_dict[code] = description def layout_iter(registry, layout, _): code = xkl_strip(layout.name) description = xkl_strip(layout.description) if code not in layouts_dict: layouts_dict[code] = description _xkl_registry.foreach_layout_variant(code, variant_iter, layout) _xkl_registry.foreach_layout(layout_iter, None) return layouts_dict
def update_labels(self): """ Updates keyboard labels based on active X keymap """ labels = {} # Get current layout group dpy = X.Display(hash( GdkX11.x11_get_default_xdisplay())) # Still no idea why... group = X.get_xkb_state(dpy).group # Get state of shift/alt/ctrl key mt = Gdk.ModifierType(self.keymap.get_modifier_state()) for a in self.background.areas: # Iterate over all translatable keys... if hasattr(Keys, a.name) and getattr(Keys, a.name) in KEY_TO_GDK: # Try to convert GKD key to keycode gdkkey = KEY_TO_GDK[getattr(Keys, a.name)] found, entries = self.keymap.get_entries_for_keyval(gdkkey) if gdkkey == Gdk.KEY_equal: # Special case, GDK reports nonsense here entries = [[e for e in entries if e.level == 0][-1]] if not found: continue for k in sorted(entries, key=lambda a: a.level): # Try to convert keycode to label translation = self.keymap.translate_keyboard_state( k.keycode, mt, group) if hasattr(translation, "keyval"): code = Gdk.keyval_to_unicode(translation.keyval) else: code = Gdk.keyval_to_unicode(translation[1]) if code != 0: labels[a.name] = unichr(code) break self.background.set_labels(labels)
def make_window_clicktrough(self): dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) # I have no idea why this works... win = X.XID(self.get_window().get_xid()) reg = X.create_region(dpy, None, 0) X.set_window_shape_region (dpy, win, X.SHAPE_BOUNDING, 0, 0, 0) X.set_window_shape_region (dpy, win, X.SHAPE_INPUT, 0, 0, reg) X.destroy_region (dpy, reg)
def make_hole(self, border_width): """ Uses shape extension to create hole in window... Area needs only border, rest should be transparent. """ width, height = self.size dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay()) ) # I have no idea why this works... wid = X.XID(self.get_window().get_xid()) mask = X.create_pixmap(dpy, wid, width, height, 1) xgcv = X.c_void_p() gc = X.create_gc(dpy, mask, 0, xgcv) X.set_foreground(dpy, gc, 1) X.fill_rectangle(dpy, mask, gc, 0, 0, width, height) X.set_foreground(dpy, gc, 0) X.fill_rectangle(dpy, mask, gc, border_width, border_width, width - 2 * border_width, height - 2 * border_width) SHAPE_BOUNDING = 0 SHAPE_SET = 0 X.shape_combine_mask(dpy, wid, SHAPE_BOUNDING, 0, 0, mask, SHAPE_SET) X.free_gc(dpy, gc) X.free_pixmap(dpy, mask)
def __init__(self, cls="osd-menu"): OSDWindow.__init__(self, cls) self.daemon = None self.config = None self.feedback = None self.controller = None self.xdisplay = X.Display(hash(GdkX11.x11_get_default_xdisplay())) # Magic cursor = os.path.join(get_share_path(), "images", 'menu-cursor.svg') self.cursor = Gtk.Image.new_from_file(cursor) self.cursor.set_name("osd-menu-cursor") self.parent = self.create_parent() self.f = Gtk.Fixed() self.f.add(self.parent) self.add(self.f) self._submenu = None self._scon = StickController() self._scon.connect("direction", self.on_stick_direction) self._is_submenu = False self._selected = None self._menuid = None self._use_cursor = False self._eh_ids = [] self._control_with = STICK self._control_with_dpad = False self._confirm_with = 'A' self._cancel_with = 'B'
def __init__(self, cls="osd-menu"): OSDWindow.__init__(self, cls) self.daemon = None self.config = None self.xdisplay = X.Display(hash( GdkX11.x11_get_default_xdisplay())) # Magic cursor = os.path.join(get_share_path(), "images", 'menu-cursor.svg') self.cursor = Gtk.Image.new_from_file(cursor) self.cursor.set_name("osd-menu-cursor") self.parent = self.create_parent() self.f = Gtk.Fixed() self.f.add(self.parent) self.add(self.f) self._submenu = None self._scon = StickController() self._scon.connect("direction", self.on_stick_direction) self._is_submenu = False self._selected = None self._menuid = None self._use_cursor = False self._eh_ids = [] self._control_with = STICK self._confirm_with = 'A' self._cancel_with = 'B'
def make_hole(self, border_width): """ Uses shape extension to create hole in window... Area needs only border, rest should be transparent. """ width, height = self.size dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) # I have no idea why this works... wid = X.XID(self.get_window().get_xid()) mask = X.create_pixmap(dpy, wid, width, height, 1) xgcv = X.c_void_p() gc = X.create_gc(dpy, mask, 0, xgcv) X.set_foreground(dpy, gc, 1) X.fill_rectangle(dpy, mask, gc, 0, 0, width, height) X.set_foreground(dpy, gc, 0) X.fill_rectangle(dpy, mask, gc, border_width, border_width, width - 2 * border_width, height - 2 * border_width) SHAPE_BOUNDING = 0 SHAPE_SET = 0 X.shape_combine_mask(dpy, wid, SHAPE_BOUNDING, 0, 0, mask, SHAPE_SET) X.free_gc(dpy, gc) X.free_pixmap(dpy, mask)
def update_labels(self): """ Updates keyboard labels based on active X keymap """ labels = {} # Get current layout group dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) # Still no idea why... group = X.get_xkb_state(dpy).group # Get state of shift/alt/ctrl key mt = Gdk.ModifierType(self.keymap.get_modifier_state()) for a in self.background.areas: # Iterate over all translatable keys... if hasattr(Keys, a.name) and getattr(Keys, a.name) in KEY_TO_GDK: # Try to convert GKD key to keycode gdkkey = KEY_TO_GDK[getattr(Keys, a.name)] found, entries = self.keymap.get_entries_for_keyval(gdkkey) if gdkkey == Gdk.KEY_equal: # Special case, GDK reports nonsense here entries = [ [ e for e in entries if e.level == 0 ][-1] ] if not found: continue for k in sorted(entries, key=lambda a : a.level): # Try to convert keycode to label code = Gdk.keyval_to_unicode( self.keymap.translate_keyboard_state(k.keycode, mt, group) .keyval) if code != 0: labels[a.name] = unichr(code) break self.background.set_labels(labels)
def _make_window_clicktrough(self): """Make events pass through window.""" dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) win = X.XID(self.get_window().get_xid()) reg = X.create_region(dpy, None, 0) X.set_window_shape_region(dpy, win, X.SHAPE_BOUNDING, 0, 0, 0) X.set_window_shape_region(dpy, win, X.SHAPE_INPUT, 0, 0, reg) X.destroy_region(dpy, reg)
def __init__(self): # pylint: disable-msg=E0611 from gi.repository import GdkX11 #initialize Xkl-related stuff display = GdkX11.x11_get_default_xdisplay() self._engine = Xkl.Engine.get_instance(display) self._rec = Xkl.ConfigRec() if not self._rec.get_from_server(self._engine): raise XklWrapperError("Failed to get configuration from server") #X is probably initialized to the 'us' layout without any variant and #since we want to add layouts with variants we need the layouts and #variants lists to have the same length. Add "" padding to variants. #See docstring of the add_layout method for details. diff = len(self._rec.layouts) - len(self._rec.variants) if diff > 0 and flags.can_touch_runtime_system("activate layouts"): self._rec.set_variants(self._rec.variants + (diff * [""])) if not self._rec.activate(self._engine): # failed to activate layouts given e.g. by a kickstart (may be # invalid) lay_var_str = ",".join(map(_join_layout_variant, self._rec.layouts, self._rec.variants)) log.error("Failed to activate layouts: '%s', " "falling back to default 'us'" % lay_var_str) self._rec.set_layouts(["us"]) self._rec.set_variants([""]) if not self._rec.activate(self._engine): # failed to activate even the default "us" layout, something # is really wrong raise XklWrapperError("Failed to initialize layouts") #needed also for Gkbd.KeyboardDrawingDialog self.configreg = Xkl.ConfigRegistry.get_instance(self._engine) self.configreg.load(False) self._language_keyboard_variants = dict() self._country_keyboard_variants = dict() self._switching_options = list() #we want to display layouts as 'language (description)' self.name_to_show_str = dict() #we want to display layout switching options as e.g. "Alt + Shift" not #as "grp:alt_shift_toggle" self.switch_to_show_str = dict() #this might take quite a long time self.configreg.foreach_language(self._get_language_variants, None) self.configreg.foreach_country(self._get_country_variants, None) #'grp' means that we want layout (group) switching options self.configreg.foreach_option('grp', self._get_switch_option, None)
def setup(): if not _USE_XKL: return gconf_client = GConf.Client.get_default() have_config = False try: display = GdkX11.x11_get_default_xdisplay() if display is not None: engine = Xkl.Engine.get_instance(display) else: logging.debug('setup_keyboard_cb: Could not get default display.') return configrec = Xkl.ConfigRec() configrec.get_from_server(engine) # FIXME, gconf_client_get_list not introspectable #681433 layouts_from_gconf = gconf_client.get( '/desktop/sugar/peripherals/keyboard/layouts') layouts_list = [] variants_list = [] if layouts_from_gconf: for gval in layouts_from_gconf.get_list(): layout = gval.get_string() layouts_list.append(layout.split('(')[0]) variants_list.append(layout.split('(')[1][:-1]) if layouts_list and variants_list: have_config = True configrec.set_layouts(layouts_list) configrec.set_variants(variants_list) model = gconf_client.get_string(\ '/desktop/sugar/peripherals/keyboard/model') if model: have_config = True configrec.set_model(model) options = [] # FIXME, gconf_client_get_list not introspectable #681433 options_from_gconf = gconf_client.get(\ '/desktop/sugar/peripherals/keyboard/options') if options_from_gconf: for gval in options_from_gconf.get_list(): option = gval.get_string() options.append(option) if options: have_config = True configrec.set_options(options) if have_config: configrec.activate(engine) except Exception: logging.exception('Error during keyboard configuration')
def setup(): if not _USE_XKL: return gconf_client = GConf.Client.get_default() have_config = False try: display = GdkX11.x11_get_default_xdisplay() if display is not None: engine = Xkl.Engine.get_instance(display) else: logging.debug('setup_keyboard_cb: Could not get default display.') return configrec = Xkl.ConfigRec() configrec.get_from_server(engine) # FIXME, gconf_client_get_list not introspectable #681433 layouts_from_gconf = gconf_client.get( '/desktop/sugar/peripherals/keyboard/layouts') layouts_list = [] variants_list = [] if layouts_from_gconf: for gval in layouts_from_gconf.get_list(): layout = gval.get_string() layouts_list.append(layout.split('(')[0]) variants_list.append(layout.split('(')[1][:-1]) if layouts_list and variants_list: have_config = True configrec.set_layouts(layouts_list) configrec.set_variants(variants_list) model = gconf_client.get_string(\ '/desktop/sugar/peripherals/keyboard/model') if model: have_config = True configrec.set_model(model) options = [] # FIXME, gconf_client_get_list not introspectable #681433 options_from_gconf = gconf_client.get(\ '/desktop/sugar/peripherals/keyboard/options') if options_from_gconf: for gval in options_from_gconf.get_list(): option = gval.get_string() options.append(option) if options: have_config = True configrec.set_options(options) if have_config: configrec.activate(engine) except Exception: logging.exception('Error during keyboard configuration')
def _make_window_clickthrough(self): """Make events pass through window.""" dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) try: xid = self.get_window().get_xid() except AttributeError: # Probably on Wayland return win = X.XID(xid) reg = X.create_region(dpy, None, 0) X.set_window_shape_region(dpy, win, X.SHAPE_BOUNDING, 0, 0, 0) X.set_window_shape_region(dpy, win, X.SHAPE_INPUT, 0, 0, reg) X.destroy_region(dpy, reg)
def __init__(self): from gi.repository import GdkX11, Xkl self._xkl = Xkl #initialize Xkl-related stuff display = GdkX11.x11_get_default_xdisplay() self._engine = Xkl.Engine.get_instance(display) self._rec = Xkl.ConfigRec() if not self._rec.get_from_server(self._engine): raise XklWrapperError("Failed to get configuration from server") #X is probably initialized to the 'us' layout without any variant and #since we want to add layouts with variants we need the layouts and #variants lists to have the same length. Add "" padding to variants. #See docstring of the add_layout method for details. diff = len(self._rec.layouts) - len(self._rec.variants) if diff > 0 and flags.can_touch_runtime_system("activate layouts"): self._rec.set_variants(self._rec.variants + (diff * [""])) if not self._rec.activate(self._engine): # failed to activate layouts given e.g. by a kickstart (may be # invalid) lay_var_str = ",".join( map(_join_layout_variant, self._rec.layouts, self._rec.variants)) log.error( "Failed to activate layouts: '%s', " "falling back to default %s", lay_var_str, DEFAULT_KEYBOARD) self._rec.set_layouts([DEFAULT_KEYBOARD]) self._rec.set_variants([""]) if not self._rec.activate(self._engine): # failed to activate even the default layout, something is # really wrong raise XklWrapperError("Failed to initialize layouts") #needed also for Gkbd.KeyboardDrawingDialog self.configreg = Xkl.ConfigRegistry.get_instance(self._engine) self.configreg.load(False) self._layout_infos = dict() self._switch_opt_infos = dict() #this might take quite a long time self.configreg.foreach_language(self._get_language_variants, None) self.configreg.foreach_country(self._get_country_variants, None) #'grp' means that we want layout (group) switching options self.configreg.foreach_option('grp', self._get_switch_option, None)
def generate(self, menuhandler): rv = [] dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) # Magic root = X.get_default_root_window(dpy) count, wlist = X.get_window_prop(dpy, root, "_NET_CLIENT_LIST", 1024) skip_taskbar = X.intern_atom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", True) wlist = cast(wlist, POINTER(X.XID))[0:count] for win in wlist: if not skip_taskbar in X.get_wm_state(dpy, win): title = X.get_window_title(dpy, win)[0:self.MAX_LENGHT] menuitem = MenuItem(str(win), title) menuitem.callback = WindowListMenuGenerator.callback rv.append(menuitem) return rv
def generate(self, menuhandler): rv = [] dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) # Magic root = X.get_default_root_window(dpy) count, wlist = X.get_window_prop(dpy, root, "_NET_CLIENT_LIST", 1024) skip_taskbar = X.intern_atom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", True) wlist = cast(wlist, POINTER(X.XID))[0:count] for win in wlist: if not skip_taskbar in X.get_wm_state(dpy, win): title = X.get_window_title(dpy, win)[0:self.MAX_LENGHT] menuitem = MenuItem(str(win), title) menuitem.callback = WindowListMenuGenerator.callback rv.append(menuitem) return rv
def __init__(self, cls="osd-menu"): self._buttons = None self._string = "" OSDWindow.__init__(self, cls) self.daemon = None self.config = None self.feedback = None self.controller = None self.xdisplay = X.Display(hash( GdkX11.x11_get_default_xdisplay())) # Magic self.create_parent() self.create_app_list() self.create_buttons() cursor = os.path.join(get_share_path(), "images", 'menu-cursor.svg') self.cursors = [ Gtk.Image.new_from_file(cursor), Gtk.Image.new_from_file(cursor) ] for c in self.cursors: c.set_name("osd-menu-cursor") c.selected = None self.f.add(c) self.f.show_all() self._scon = StickController() self._scon.connect("direction", self.on_stick_direction) self._selected = None self._menuid = None self._eh_ids = [] self._confirm_with = 'A' self._cancel_with = 'B' if Launcher._app_db is None: Launcher._app_db = [] for x in Launcher.BUTTONS: for c in x: Launcher.CHAR_TO_NUMBER[c] = x[0] for x in Gio.AppInfo.get_all(): try: Launcher._app_db.append((Launcher.name_to_keys(x), x)) except UnicodeDecodeError: # Just f**k them... pass
def __init__(self): #initialize Xkl-related stuff display = GdkX11.x11_get_default_xdisplay() self._engine = Xkl.Engine.get_instance(display) self._rec = Xkl.ConfigRec() if not self._rec.get_from_server(self._engine): raise XklWrapperError("Failed to get configuration from server") #X is probably initialized to the 'us' layout without any variant and #since we want to add layouts with variants we need the layouts and #variants lists to have the same length. Add "" padding to variants. #See docstring of the add_layout method for details. diff = len(self._rec.layouts) - len(self._rec.variants) if diff > 0 and flags.can_touch_runtime_system("activate layouts"): self._rec.set_variants(self._rec.variants + (diff * [""])) if not self._rec.activate(self._engine): # failed to activate layouts given e.g. by a kickstart (may be # invalid) lay_var_str = ",".join(map(join_layout_variant, self._rec.layouts, self._rec.variants)) log.error("Failed to activate layouts: '%s', " "falling back to default %s", lay_var_str, DEFAULT_KEYBOARD) self._rec.set_layouts([DEFAULT_KEYBOARD]) self._rec.set_variants([""]) if not self._rec.activate(self._engine): # failed to activate even the default layout, something is # really wrong raise XklWrapperError("Failed to initialize layouts") #needed also for Gkbd.KeyboardDrawingDialog self.configreg = Xkl.ConfigRegistry.get_instance(self._engine) self.configreg.load(False) self._layout_infos = dict() self._layout_infos_lock = threading.RLock() self._switch_opt_infos = dict() self._switch_opt_infos_lock = threading.RLock() #this might take quite a long time self.configreg.foreach_language(self._get_language_variants, None) self.configreg.foreach_country(self._get_country_variants, None) #'grp' means that we want layout (group) switching options self.configreg.foreach_option('grp', self._get_switch_option, None)
def __init__(self, model, alerts): SectionView.__init__(self) self._model = model self._kmodel = None self._selected_kmodel = None self._klayouts = [] self._selected_klayouts = [] self._group_switch_option = None self._selected_group_switch_option = None self.set_border_width(style.DEFAULT_SPACING * 2) self.set_spacing(style.DEFAULT_SPACING) self._layout_table = Gtk.Table(rows=4, columns=2, homogeneous=False) _build_ISO_639_dictionary() self._keyboard_manager = model.KeyboardManager( GdkX11.x11_get_default_xdisplay()) self._layout_combo_list = [] self._layout_addremovebox_list = [] scrollwindow = Gtk.ScrolledWindow() scrollwindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.pack_start(scrollwindow, True, True, 0) scrollwindow.show() self._vbox = Gtk.VBox() scrollwindow.add_with_viewport(self._vbox) self.__kmodel_sid = None self.__layout_sid = None self.__group_switch_sid = None self._setup_kmodel() self._setup_layouts() self._setup_group_switch_option() self._vbox.show()
def __init__(self, cls="osd-menu"): self._buttons = None self._string = "" OSDWindow.__init__(self, cls) self.daemon = None self.config = None self.feedback = None self.controller = None self.xdisplay = X.Display(hash(GdkX11.x11_get_default_xdisplay())) # Magic self.create_parent() self.create_app_list() self.create_buttons() cursor = os.path.join(get_share_path(), "images", 'menu-cursor.svg') self.cursors = [ Gtk.Image.new_from_file(cursor), Gtk.Image.new_from_file(cursor) ] for c in self.cursors: c.set_name("osd-menu-cursor") c.selected = None self.f.add(c) self.f.show_all() self._scon = StickController() self._scon.connect("direction", self.on_stick_direction) self._selected = None self._menuid = None self._eh_ids = [] self._confirm_with = 'A' self._cancel_with = 'B' if Launcher._app_db is None: Launcher._app_db = [] for x in Launcher.BUTTONS: for c in x: Launcher.CHAR_TO_NUMBER[c] = x[0] for x in Gio.AppInfo.get_all(): try: Launcher._app_db.append(( Launcher.name_to_keys(x), x )) except UnicodeDecodeError: # Just f**k them... pass
def setup(): settings = Gio.Settings('org.sugarlabs.peripherals.keyboard') have_config = False try: display = GdkX11.x11_get_default_xdisplay() if display is not None: engine = Xkl.Engine.get_instance(display) else: logging.debug('setup_keyboard_cb: Could not get default display.') return configrec = Xkl.ConfigRec() configrec.get_from_server(engine) layouts = settings.get_strv('layouts') layouts_list = [] variants_list = [] if layouts: for layout in layouts: layouts_list.append(layout.split('(')[0]) variants_list.append(layout.split('(')[1][:-1]) if layouts_list and variants_list: have_config = True configrec.set_layouts(layouts_list) configrec.set_variants(variants_list) model = settings.get_string('model') if model: have_config = True configrec.set_model(model) options = settings.get_strv('options') if options: have_config = True configrec.set_options(options) if have_config: configrec.activate(engine) except Exception: logging.exception('Error during keyboard configuration')
def __init__(self, cls="osd-menu"): self._buttons = None self._text = None OSDWindow.__init__(self, cls) self.daemon = None self.config = None self.feedback = None self.controller = None self.xdisplay = X.Display(hash(GdkX11.x11_get_default_xdisplay())) # Magic self.parent = self.create_parent() self.f = Gtk.Fixed() self.f.add(self.parent) self.add(self.f) self._scon = StickController() self._scon.connect("direction", self.on_stick_direction) self._selected = None self._eh_ids = []
def __init__(self, config=None): self.kbimage = os.path.join(get_config_path(), 'keyboard.svg') if not os.path.exists(self.kbimage): # Prefer image in ~/.config/scc, but load default one as fallback self.kbimage = os.path.join(get_share_path(), "images", 'keyboard.svg') TimerManager.__init__(self) OSDWindow.__init__(self, "osd-keyboard") self.daemon = None self.mapper = None self.keymap = Gdk.Keymap.get_default() self.keymap.connect('state-changed', self.on_keymap_state_changed) Action.register_all(sys.modules['scc.osd.osk_actions'], prefix="OSK") self.profile = Profile(TalkingActionParser()) self.config = config or Config() self.dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) self.group = None self.limits = {} self.background = None cursor = os.path.join(get_share_path(), "images", 'menu-cursor.svg') self.cursors = {} self.cursors[LEFT] = Gtk.Image.new_from_file(cursor) self.cursors[LEFT].set_name("osd-keyboard-cursor") self.cursors[RIGHT] = Gtk.Image.new_from_file(cursor) self.cursors[RIGHT].set_name("osd-keyboard-cursor") self.cursors[CPAD] = Gtk.Image.new_from_file(cursor) self.cursors[CPAD].set_name("osd-keyboard-cursor") self._eh_ids = [] self._controller = None self._stick = 0, 0 self._hovers = {self.cursors[LEFT]: None, self.cursors[RIGHT]: None} self._pressed = {self.cursors[LEFT]: None, self.cursors[RIGHT]: None} self._pressed_areas = {} self.c = Gtk.Box() self.c.set_name("osd-keyboard-container") self.f = Gtk.Fixed()
def __init__(self, cls="osd-menu"): self._buttons = None self._text = None OSDWindow.__init__(self, cls) self.daemon = None self.config = None self.feedback = None self.controller = None self.xdisplay = X.Display(hash( GdkX11.x11_get_default_xdisplay())) # Magic self.parent = self.create_parent() self.f = Gtk.Fixed() self.f.add(self.parent) self.add(self.f) self._scon = StickController() self._scon.connect("direction", self.on_stick_direction) self._selected = None self._eh_ids = []
def __init__(self, config=None): self.kbimage = os.path.join(get_config_path(), 'keyboard.svg') if not os.path.exists(self.kbimage): # Prefer image in ~/.config/scc, but load default one as fallback self.kbimage = os.path.join(get_share_path(), "images", 'keyboard.svg') TimerManager.__init__(self) OSDWindow.__init__(self, "osd-keyboard") self.daemon = None self.mapper = None self.keymap = Gdk.Keymap.get_default() self.keymap.connect('state-changed', self.on_keymap_state_changed) Action.register_all(sys.modules['scc.osd.osk_actions'], prefix="OSK") self.profile = Profile(TalkingActionParser()) self.config = config or Config() self.dpy = X.Display(hash(GdkX11.x11_get_default_xdisplay())) self.group = None self.limits = {} self.background = None cursor = os.path.join(get_share_path(), "images", 'menu-cursor.svg') self.cursors = {} self.cursors[LEFT] = Gtk.Image.new_from_file(cursor) self.cursors[LEFT].set_name("osd-keyboard-cursor") self.cursors[RIGHT] = Gtk.Image.new_from_file(cursor) self.cursors[RIGHT].set_name("osd-keyboard-cursor") self.cursors[CPAD] = Gtk.Image.new_from_file(cursor) self.cursors[CPAD].set_name("osd-keyboard-cursor") self._eh_ids = [] self._controller = None self._stick = 0, 0 self._hovers = { self.cursors[LEFT]: None, self.cursors[RIGHT]: None } self._pressed = { self.cursors[LEFT]: None, self.cursors[RIGHT]: None } self._pressed_areas = {} self.c = Gtk.Box() self.c.set_name("osd-keyboard-container") self.f = Gtk.Fixed()
def __init__(self, usermanager_loaded_cb=None, locale_selected_cb=None): self._usermanager_loaded_cb = usermanager_loaded_cb self._locale_selected_cb = locale_selected_cb self.__act_user = None self.__actusermanager_loadedid = None self._xkl_engine = Xkl.Engine.get_instance(GdkX11.x11_get_default_xdisplay()) self._xkl_registry = Xkl.ConfigRegistry.get_instance(self._xkl_engine) self._xkl_registry.load(False) self._xkl_record = Xkl.ConfigRec() self._xkl_record.get_from_server(self._xkl_engine) self._system_locales_list = _langcodes self._system_locales_dict = self.__fill_locales_dict(self._system_locales_list) self._language = 'en' self._locale = 'en_US' self._layout = 'us' self._variant = '' actusermanager = AccountsService.UserManager.get_default() self.__actusermanager_loadedid = actusermanager.connect( "notify::is-loaded", self.__on_usermanager_loaded)
# Public License for more details. You should have received a copy of the # GNU General Public License along with this program; if not, write to the # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. Any Red Hat trademarks that are incorporated in the # source code or documentation are not subject to the GNU General Public # License and may only be used or replicated with the express permission of # Red Hat, Inc. # # Red Hat Author(s): Vratislav Podzimek <*****@*****.**> # import sys from gi.repository import Gkbd, Gtk, Xkl, Gdk, GdkX11 if len(sys.argv) < 2: print "Layout expected as the first argument!" sys.exit(1) dialog = Gkbd.KeyboardDrawing.dialog_new() dialog.connect("destroy", lambda x: Gtk.main_quit()) display = GdkX11.x11_get_default_xdisplay() engine = Xkl.Engine.get_instance(display) registry = Xkl.ConfigRegistry.get_instance(engine) registry.load(False) Gkbd.KeyboardDrawing.dialog_set_layout(dialog, registry, sys.argv[1]) dialog.show_all() Gtk.main()
def set_indicator_keymaps(lang): import xml.etree.cElementTree as ElementTree from gi.repository import Xkl, GdkX11 # GdkX11.x11_get_default_xdisplay() segfaults if Gtk hasn't been # imported; possibly finer-grained than this, but anything using this # will already have imported Gtk anyway ... from gi.repository import Gtk from ubiquity import gsettings gsettings_key = ['org.gnome.libgnomekbd.keyboard', 'layouts'] lang = lang.split('_')[0] variants = [] # Map inspired from that of gfxboot-theme-ubuntu that's itself # based on console-setup's. This one has been restricted to # language => keyboard layout not locale => keyboard layout as # we don't actually know the exact locale default_keymap = { 'ar': 'ara', 'bs': 'ba', 'de': 'de', 'el': 'gr', 'en': 'us', 'eo': 'epo', 'fr': 'fr_oss', 'gu': 'in_guj', 'hi': 'in', 'hr': 'hr', 'hy': 'am', 'ka': 'ge', 'kn': 'in_kan', 'lo': 'la', 'ml': 'in_mal', 'pa': 'in_guru', 'sr': 'rs', 'sv': 'se', 'ta': 'in_tam', 'te': 'in_tel', 'zh': 'cn', } def item_str(s): """ Convert a zero-terminated byte array to a proper str """ i = s.find(b'\x00') return s[:i].decode() def process_variant(*args): if hasattr(args[2], 'name'): variants.append('{0}\t{1}'.format((item_str(args[1].name), item_str(args[2].name)))) else: variants.append(item_str(args[1].name)) def restrict_list(variants): new_variants = [] # Start by looking by an explicit default layout in the keymap if lang in default_keymap: if default_keymap[lang] in variants: variants.remove(default_keymap[lang]) new_variants.append(default_keymap[lang]) else: tab_keymap = default_keymap[lang].replace('_', '\t') if tab_keymap in variants: variants.remove(tab_keymap) new_variants.append(tab_keymap) # Prioritize the layout matching the language (if any) if lang in variants: variants.remove(lang) new_variants.append(lang) # Uniquify our list (just in case) variants = list(set(variants)) if len(variants) > 4: # We have a problem, X only supports 4 # Add as many entry as we can that are layouts without variant country_variants = sorted( entry for entry in variants if '\t' not in entry) for entry in country_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # We can add some more simple_variants = sorted( entry for entry in variants if '_' not in entry) for entry in simple_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # Now just add anything left for entry in variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) else: new_variants = new_variants + list(variants) # gsettings doesn't understand utf8 new_variants = [str(variant) for variant in new_variants] return new_variants def call_setxkbmap(variants): kb_layouts = [] kb_variants = [] for entry in variants: fields = entry.split('\t') if len(fields) > 1: kb_layouts.append(fields[0]) kb_variants.append(fields[1]) else: kb_layouts.append(fields[0]) kb_variants.append("") execute( "setxkbmap", "-layout", ",".join(kb_layouts), "-variant", ",".join(kb_variants)) iso_639_3 = ElementTree.parse('/usr/share/xml/iso-codes/iso_639_3.xml') nodes = [element for element in iso_639_3.findall('iso_639_3_entry') if element.get('part1_code') == lang] display = GdkX11.x11_get_default_xdisplay() engine = Xkl.Engine.get_instance(display) if nodes: configreg = Xkl.ConfigRegistry.get_instance(engine) configreg.load(False) # Apparently part2_code doesn't always work (fails with French) for prop in ('part2_code', 'id', 'part1_code'): code = nodes[0].get(prop) if code is not None: configreg.foreach_language_variant(code, process_variant, None) if variants: restricted_variants = restrict_list(variants) call_setxkbmap(restricted_variants) gsettings.set_list( gsettings_key[0], gsettings_key[1], restricted_variants) break else: # Use the system default if no other keymaps can be determined. gsettings.set_list(gsettings_key[0], gsettings_key[1], []) engine.lock_group(0)
def set_indicator_keymaps(lang): import xml.etree.cElementTree as ElementTree from gi.repository import Xkl, GdkX11 # GdkX11.x11_get_default_xdisplay() segfaults if Gtk hasn't been # imported; possibly finer-grained than this, but anything using this # will already have imported Gtk anyway ... from gi.repository import Gtk from ubiquity import gsettings # pacify pyflakes Gtk gsettings_key = ['org.gnome.libgnomekbd.keyboard', 'layouts'] gsettings_sources = ('org.gnome.desktop.input-sources', 'sources') gsettings_options = ('org.gnome.desktop.input-sources', 'xkb-options') lang = lang.split('_')[0] variants = [] # Map inspired from that of gfxboot-theme-ubuntu that's itself # based on console-setup's. This one has been restricted to # language => keyboard layout not locale => keyboard layout as # we don't actually know the exact locale default_keymap = { 'ar': 'ara', 'bs': 'ba', 'de': 'de', 'el': 'gr', 'en': 'us', 'eo': 'epo', 'fr': 'fr_oss', 'gu': 'in_guj', 'hi': 'in', 'hr': 'hr', 'hy': 'am', 'ka': 'ge', 'kn': 'in_kan', 'lo': 'la', 'ml': 'in_mal', 'pa': 'in_guru', 'sr': 'rs', 'sv': 'se', 'ta': 'in_tam', 'te': 'in_tel', 'zh': 'cn', } def item_str(s): '''Convert a zero-terminated byte array to a proper str''' import array s = array.array('B', s).tobytes() i = s.find(b'\x00') return s[:i].decode() def process_variant(*args): if hasattr(args[2], 'name'): variants.append('%s\t%s' % (item_str(args[1].name), item_str(args[2].name))) else: variants.append(item_str(args[1].name)) def restrict_list(variants): new_variants = [] # Start by looking by an explicit default layout in the keymap if lang in default_keymap: if default_keymap[lang] in variants: variants.remove(default_keymap[lang]) new_variants.append(default_keymap[lang]) else: tab_keymap = default_keymap[lang].replace('_', '\t') if tab_keymap in variants: variants.remove(tab_keymap) new_variants.append(tab_keymap) # Prioritize the layout matching the language (if any) if lang in variants: variants.remove(lang) new_variants.append(lang) # Uniquify our list (just in case) variants = list(set(variants)) if len(variants) > 4: # We have a problem, X only supports 4 # Add as many entry as we can that are layouts without variant country_variants = sorted(entry for entry in variants if '\t' not in entry) for entry in country_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # We can add some more simple_variants = sorted(entry for entry in variants if '_' not in entry) for entry in simple_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # Now just add anything left for entry in variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) else: new_variants += list(variants) # gsettings doesn't understand utf8 new_variants = [str(variant) for variant in new_variants] return new_variants def call_setxkbmap(variants): kb_layouts = [] kb_variants = [] for entry in variants: fields = entry.split('\t') if len(fields) > 1: kb_layouts.append(fields[0]) kb_variants.append(fields[1]) else: kb_layouts.append(fields[0]) kb_variants.append("") execute("setxkbmap", "-layout", ",".join(kb_layouts), "-variant", ",".join(kb_variants)) iso_639 = ElementTree.parse('/usr/share/xml/iso-codes/iso_639.xml') nodes = [ element for element in iso_639.findall('iso_639_entry') if element.get('iso_639_1_code') == lang ] display = GdkX11.x11_get_default_xdisplay() engine = Xkl.Engine.get_instance(display) if nodes: configreg = Xkl.ConfigRegistry.get_instance(engine) configreg.load(False) # Apparently iso_639_2B_code doesn't always work (fails with French) for prop in ('iso_639_2B_code', 'iso_639_2T_code', 'iso_639_1_code'): code = nodes[0].get(prop) if code is not None: configreg.foreach_language_variant(code, process_variant, None) if variants: restricted_variants = restrict_list(variants) call_setxkbmap(restricted_variants) gsettings.set_list(gsettings_key[0], gsettings_key[1], restricted_variants) break else: # Use the system default if no other keymaps can be determined. gsettings.set_list(gsettings_key[0], gsettings_key[1], []) # Gnome Shell only does keyboard layout conversion from old # gsettings_key once. Recently we started to launch keyboard plugin # during ubiquity-dm, hence if we change that key, we should purge the # state that gsd uses, to determine if it should run the # conversion. Which are a stamp file, and having the new key set. # Ideally, I think ubiquity should be more universal and set the new key # directly, instead of relying on gsd keeping the conversion code # around. But it's too late for 20.10 release. gsettings_stamp = os.path.join( '/home', os.getenv("SUDO_USER", os.getenv("USER", "root")), '.local/share/gnome-settings-daemon/input-sources-converted') if os.path.exists(gsettings_stamp): os.remove(gsettings_stamp) gsettings.unset(*gsettings_sources) gsettings.unset(*gsettings_options) engine.lock_group(0)
def set_indicator_keymaps(lang): import xml.etree.cElementTree as ElementTree from gi.repository import Xkl, GdkX11 # GdkX11.x11_get_default_xdisplay() segfaults if Gtk hasn't been # imported; possibly finer-grained than this, but anything using this # will already have imported Gtk anyway ... from gi.repository import Gtk from ubiquity import gsettings # pacify pyflakes Gtk gsettings_key = ["org.gnome.libgnomekbd.keyboard", "layouts"] lang = lang.split("_")[0] variants = [] # Map inspired from that of gfxboot-theme-ubuntu that's itself # based on console-setup's. This one has been restricted to # language => keyboard layout not locale => keyboard layout as # we don't actually know the exact locale default_keymap = { "ar": "ara", "bs": "ba", "de": "de", "el": "gr", "en": "us", "eo": "epo", "fr": "fr_oss", "gu": "in_guj", "hi": "in", "hr": "hr", "hy": "am", "ka": "ge", "kn": "in_kan", "lo": "la", "ml": "in_mal", "pa": "in_guru", "sr": "rs", "sv": "se", "ta": "in_tam", "te": "in_tel", "zh": "cn", } def item_str(s): """Convert a zero-terminated byte array to a proper str""" i = s.find(b"\x00") return s[:i].decode() def process_variant(*args): if hasattr(args[2], "name"): variants.append("%s\t%s" % (item_str(args[1].name), item_str(args[2].name))) else: variants.append(item_str(args[1].name)) def restrict_list(variants): new_variants = [] # Start by looking by an explicit default layout in the keymap if lang in default_keymap: if default_keymap[lang] in variants: variants.remove(default_keymap[lang]) new_variants.append(default_keymap[lang]) else: tab_keymap = default_keymap[lang].replace("_", "\t") if tab_keymap in variants: variants.remove(tab_keymap) new_variants.append(tab_keymap) # Prioritize the layout matching the language (if any) if lang in variants: variants.remove(lang) new_variants.append(lang) # Uniquify our list (just in case) variants = list(set(variants)) if len(variants) > 4: # We have a problem, X only supports 4 # Add as many entry as we can that are layouts without variant country_variants = sorted(entry for entry in variants if "\t" not in entry) for entry in country_variants[: 4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # We can add some more simple_variants = sorted(entry for entry in variants if "_" not in entry) for entry in simple_variants[: 4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # Now just add anything left for entry in variants[: 4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) else: new_variants += list(variants) # gsettings doesn't understand utf8 new_variants = [str(variant) for variant in new_variants] return new_variants def call_setxkbmap(variants): kb_layouts = [] kb_variants = [] for entry in variants: fields = entry.split("\t") if len(fields) > 1: kb_layouts.append(fields[0]) kb_variants.append(fields[1]) else: kb_layouts.append(fields[0]) kb_variants.append("") execute("setxkbmap", "-layout", ",".join(kb_layouts), "-variant", ",".join(kb_variants)) iso_639_3 = ElementTree.parse("/usr/share/xml/iso-codes/iso_639_3.xml") nodes = [element for element in iso_639_3.findall("iso_639_3_entry") if element.get("part1_code") == lang] display = GdkX11.x11_get_default_xdisplay() engine = Xkl.Engine.get_instance(display) if nodes: configreg = Xkl.ConfigRegistry.get_instance(engine) configreg.load(False) # Apparently part2_code doesn't always work (fails with French) for prop in ("part2_code", "id", "part1_code"): code = nodes[0].get(prop) if code is not None: configreg.foreach_language_variant(code, process_variant, None) if variants: restricted_variants = restrict_list(variants) call_setxkbmap(restricted_variants) gsettings.set_list(gsettings_key[0], gsettings_key[1], restricted_variants) break else: # Use the system default if no other keymaps can be determined. gsettings.set_list(gsettings_key[0], gsettings_key[1], []) engine.lock_group(0)
def set_indicator_keymaps(lang): import xml.etree.cElementTree as ElementTree from gi.repository import Xkl, GdkX11 # GdkX11.x11_get_default_xdisplay() segfaults if Gtk hasn't been # imported; possibly finer-grained than this, but anything using this # will already have imported Gtk anyway ... from gi.repository import Gtk from ubiquity import gsettings # pacify pyflakes Gtk gsettings_key = ['org.gnome.libgnomekbd.keyboard', 'layouts'] lang = lang.split('_')[0] variants = [] # Map inspired from that of gfxboot-theme-ubuntu that's itself # based on console-setup's. This one has been restricted to # language => keyboard layout not locale => keyboard layout as # we don't actually know the exact locale default_keymap = { 'ar': 'ara', 'bs': 'ba', 'de': 'de', 'el': 'gr', 'en': 'us', 'eo': 'epo', 'fr': 'fr_oss', 'gu': 'in_guj', 'hi': 'in', 'hr': 'hr', 'hy': 'am', 'ka': 'ge', 'kn': 'in_kan', 'lo': 'la', 'ml': 'in_mal', 'pa': 'in_guru', 'sr': 'rs', 'sv': 'se', 'ta': 'in_tam', 'te': 'in_tel', 'zh': 'cn', } def item_str(s): '''Convert a zero-terminated byte array to a proper str''' import array s = array.array('B', s).tostring() i = s.find(b'\x00') return s[:i].decode() def process_variant(*args): if hasattr(args[2], 'name'): variants.append( '%s\t%s' % (item_str(args[1].name), item_str(args[2].name))) else: variants.append(item_str(args[1].name)) def restrict_list(variants): new_variants = [] # Start by looking by an explicit default layout in the keymap if lang in default_keymap: if default_keymap[lang] in variants: variants.remove(default_keymap[lang]) new_variants.append(default_keymap[lang]) else: tab_keymap = default_keymap[lang].replace('_', '\t') if tab_keymap in variants: variants.remove(tab_keymap) new_variants.append(tab_keymap) # Prioritize the layout matching the language (if any) if lang in variants: variants.remove(lang) new_variants.append(lang) # Uniquify our list (just in case) variants = list(set(variants)) if len(variants) > 4: # We have a problem, X only supports 4 # Add as many entry as we can that are layouts without variant country_variants = sorted( entry for entry in variants if '\t' not in entry) for entry in country_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # We can add some more simple_variants = sorted( entry for entry in variants if '_' not in entry) for entry in simple_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # Now just add anything left for entry in variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) else: new_variants += list(variants) # gsettings doesn't understand utf8 new_variants = [str(variant) for variant in new_variants] #Hack pt1 added for Bio-Linux to prefer gb keyboard over us if new_variants[0] == "us" and new_variants[2] == "gb" : new_variants[0] = str("gb") new_variants[2] = str("us") #end hack return new_variants def call_setxkbmap(variants): kb_layouts = [] kb_variants = [] for entry in variants: fields = entry.split('\t') if len(fields) > 1: kb_layouts.append(fields[0]) kb_variants.append(fields[1]) else: kb_layouts.append(fields[0]) kb_variants.append("") execute( "setxkbmap", "-layout", ",".join(kb_layouts), "-variant", ",".join(kb_variants)) #Hack pt2 added for Bio-Linux to actually make the keyboard settings stick #in 14.04. #It seems the upstream authors have attempted to get this fixed, but missed #the point that we need to preserve the DBUS address variable, which is lost #when Ubiquity gains root privileges. # os.environ['DBUS_SESSION_BUS_ADDRESS'] = "unix:abstract=/tmp/dbus-FaqRsE1MGY" #I tried signalling the keyboard indicator with "pkill -USR1", but that just #locks up the whole system. Meh, so frickin fragile. Hence this appalling #kludge instead. user = os.environ.get('PKEXEC_UID') user = '******' + user if user else '#999' try: if not os.environ.get('DBUS_SESSION_BUS_ADDRESS') : proc1 = subprocess.Popen('ps -p %i -o ppid=' % os.getppid(), shell=True, stdout=subprocess.PIPE, ) pppid = int(proc1.communicate()[0].rstrip()) proc2 = subprocess.Popen('sudo -u "%s" cat /proc/%i/environ' % (user, pppid), shell=True, stdout=subprocess.PIPE, ) os.environ['DBUS_SESSION_BUS_ADDRESS'] = [ x for x in proc2.communicate()[0].decode().split('\0') if x.startswith("DBUS_SESSION_BUS_ADDRESS=") ][0][25:] except: os.environ['DBUS_SESSION_BUS_ADDRESS'] = 'none' subprocess.call( ['sudo', '-E', '-u', user, 'gsettings', 'set', "org.gnome.desktop.input-sources", "sources", repr( [('xkb', l+'+'+v if v else l) for l,v in zip(kb_layouts, kb_variants)] ) ], preexec_fn=drop_all_privileges ) #subprocess.call(['sudo', '-u', user, 'pkill', '-USR1', 'indicator-keybo']) #end hack iso_639 = ElementTree.parse('/usr/share/xml/iso-codes/iso_639.xml') nodes = [element for element in iso_639.findall('iso_639_entry') if element.get('iso_639_1_code') == lang] display = GdkX11.x11_get_default_xdisplay() engine = Xkl.Engine.get_instance(display) if nodes: configreg = Xkl.ConfigRegistry.get_instance(engine) configreg.load(False) # Apparently iso_639_2B_code doesn't always work (fails with French) for prop in ('iso_639_2B_code', 'iso_639_2T_code', 'iso_639_1_code'): code = nodes[0].get(prop) if code is not None: configreg.foreach_language_variant(code, process_variant, None) if variants: restricted_variants = restrict_list(variants) call_setxkbmap(restricted_variants) gsettings.set_list( gsettings_key[0], gsettings_key[1], restricted_variants) break else: # Use the system default if no other keymaps can be determined. gsettings.set_list(gsettings_key[0], gsettings_key[1], []) engine.lock_group(0)
def __init__(self, editor): self._xdisplay = X.Display(hash(GdkX11.x11_get_default_xdisplay())) self.editor = editor
def __init__(self, editor): self._xdisplay = X.Display(hash(GdkX11.x11_get_default_xdisplay())) self.editor = editor
def set_indicator_keymaps(lang): import libxml2 from gi.repository import Xkl, GdkX11 # GdkX11.x11_get_default_xdisplay() segfaults if Gtk hasn't been # imported; possibly finer-grained than this, but anything using this # will already have imported Gtk anyway ... from gi.repository import Gtk from ubiquity import gsettings # pacify pyflakes Gtk xpath = "//iso_639_3_entry[@part1_code='%s']" gsettings_key = ['org.gnome.libgnomekbd.keyboard', 'layouts'] lang = lang.split('_')[0] variants = [] # Map inspired from that of gfxboot-theme-ubuntu that's itself # based on console-setup's. This one has been restricted to # language => keyboard layout not locale => keyboard layout as # we don't actually know the exact locale default_keymap = { 'ar': 'ara', 'bs': 'ba', 'de': 'de', 'el': 'gr', 'en': 'us', 'eo': 'epo', 'fr': 'fr_oss', 'gu': 'in_guj', 'hi': 'in', 'hr': 'hr', 'hy': 'am', 'ka': 'ge', 'kn': 'in_kan', 'lo': 'la', 'ml': 'in_mal', 'pa': 'in_guru', 'sr': 'rs', 'sv': 'se', 'ta': 'in_tam', 'te': 'in_tel', 'zh': 'cn', } def item_str(s): '''Convert a zero-terminated byte array to a proper str''' i = s.find(b'\x00') return s[:i].decode() def process_variant(*args): if hasattr(args[2], 'name'): variants.append('%s\t%s' % (item_str(args[1].name), item_str(args[2].name))) else: variants.append(item_str(args[1].name)) def restrict_list(variants): new_variants = [] # Start by looking by an explicit default layout in the keymap if lang in default_keymap: if default_keymap[lang] in variants: variants.remove(default_keymap[lang]) new_variants.append(default_keymap[lang]) else: tab_keymap = default_keymap[lang].replace('_', '\t') if tab_keymap in variants: variants.remove(tab_keymap) new_variants.append(tab_keymap) # Prioritize the layout matching the language (if any) if lang in variants: variants.remove(lang) new_variants.append(lang) # Uniquify our list (just in case) variants = list(set(variants)) if len(variants) > 4: # We have a problem, X only supports 4 # Add as many entry as we can that are layouts without variant country_variants = sorted( [entry for entry in variants if '\t' not in entry]) for entry in country_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # We can add some more simple_variants = sorted( [entry for entry in variants if '_' not in entry]) for entry in simple_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # Now just add anything left for entry in variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) else: new_variants += list(variants) # gsettings doesn't understand utf8 new_variants = [str(variant) for variant in new_variants] return new_variants def call_setxkbmap(variants): kb_layouts = [] kb_variants = [] for entry in variants: fields = entry.split('\t') if len(fields) > 1: kb_layouts.append(fields[0]) kb_variants.append(fields[1]) else: kb_layouts.append(fields[0]) kb_variants.append("") execute("setxkbmap", "-layout", ",".join(kb_layouts), "-variant", ",".join(kb_variants)) fp = libxml2.parseFile('/usr/share/xml/iso-codes/iso_639_3.xml') context = fp.xpathNewContext() nodes = context.xpathEvalExpression(xpath % lang) display = GdkX11.x11_get_default_xdisplay() engine = Xkl.Engine.get_instance(display) if nodes: configreg = Xkl.ConfigRegistry.get_instance(engine) configreg.load(False) # Apparently part2_code doesn't always work (fails with French) for prop in ('part2_code', 'id', 'part1_code'): if nodes[0].hasProp(prop): code = nodes[0].prop(prop) configreg.foreach_language_variant(code, process_variant, None) if variants: restricted_variants = restrict_list(variants) call_setxkbmap(restricted_variants) gsettings.set_list(gsettings_key[0], gsettings_key[1], restricted_variants) break else: # Use the system default if no other keymaps can be determined. gsettings.set_list(gsettings_key[0], gsettings_key[1], []) engine.lock_group(0)
def set_indicator_keymaps(lang): import xml.etree.cElementTree as ElementTree from gi.repository import Xkl, GdkX11 # GdkX11.x11_get_default_xdisplay() segfaults if Gtk hasn't been # imported; possibly finer-grained than this, but anything using this # will already have imported Gtk anyway ... from gi.repository import Gtk from ubiquity import gsettings # pacify pyflakes Gtk gsettings_key = ['org.gnome.libgnomekbd.keyboard', 'layouts'] lang = lang.split('_')[0] variants = [] # Map inspired from that of gfxboot-theme-ubuntu that's itself # based on console-setup's. This one has been restricted to # language => keyboard layout not locale => keyboard layout as # we don't actually know the exact locale default_keymap = { 'ar': 'ara', 'bs': 'ba', 'de': 'de', 'el': 'gr', 'en': 'us', 'eo': 'epo', 'fr': 'fr_oss', 'gu': 'in_guj', 'hi': 'in', 'hr': 'hr', 'hy': 'am', 'ka': 'ge', 'kn': 'in_kan', 'lo': 'la', 'ml': 'in_mal', 'pa': 'in_guru', 'sr': 'rs', 'sv': 'se', 'ta': 'in_tam', 'te': 'in_tel', 'zh': 'cn', } def item_str(s): '''Convert a zero-terminated byte array to a proper str''' import array s = array.array('B', s).tostring() i = s.find(b'\x00') return s[:i].decode() def process_variant(*args): if hasattr(args[2], 'name'): variants.append('%s\t%s' % (item_str(args[1].name), item_str(args[2].name))) else: variants.append(item_str(args[1].name)) def restrict_list(variants): new_variants = [] # Start by looking by an explicit default layout in the keymap if lang in default_keymap: if default_keymap[lang] in variants: variants.remove(default_keymap[lang]) new_variants.append(default_keymap[lang]) else: tab_keymap = default_keymap[lang].replace('_', '\t') if tab_keymap in variants: variants.remove(tab_keymap) new_variants.append(tab_keymap) # Prioritize the layout matching the language (if any) if lang in variants: variants.remove(lang) new_variants.append(lang) # Uniquify our list (just in case) variants = list(set(variants)) if len(variants) > 4: # We have a problem, X only supports 4 # Add as many entry as we can that are layouts without variant country_variants = sorted(entry for entry in variants if '\t' not in entry) for entry in country_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # We can add some more simple_variants = sorted(entry for entry in variants if '_' not in entry) for entry in simple_variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) if len(new_variants) < 4: # Now just add anything left for entry in variants[:4 - len(new_variants)]: new_variants.append(entry) variants.remove(entry) else: new_variants += list(variants) # gsettings doesn't understand utf8 new_variants = [str(variant) for variant in new_variants] #Hack pt1 added for Bio-Linux to prefer gb keyboard over us if new_variants[0] == "us" and new_variants[2] == "gb": new_variants[0] = str("gb") new_variants[2] = str("us") #end hack return new_variants def call_setxkbmap(variants): kb_layouts = [] kb_variants = [] for entry in variants: fields = entry.split('\t') if len(fields) > 1: kb_layouts.append(fields[0]) kb_variants.append(fields[1]) else: kb_layouts.append(fields[0]) kb_variants.append("") execute("setxkbmap", "-layout", ",".join(kb_layouts), "-variant", ",".join(kb_variants)) #Hack pt2 added for Bio-Linux to actually make the keyboard settings stick #in 14.04. #It seems the upstream authors have attempted to get this fixed, but missed #the point that we need to preserve the DBUS address variable, which is lost #when Ubiquity gains root privileges. # os.environ['DBUS_SESSION_BUS_ADDRESS'] = "unix:abstract=/tmp/dbus-FaqRsE1MGY" #I tried signalling the keyboard indicator with "pkill -USR1", but that just #locks up the whole system. Meh, so frickin fragile. Hence this appalling #kludge instead. user = os.environ.get('PKEXEC_UID') user = '******' + user if user else '#999' try: if not os.environ.get('DBUS_SESSION_BUS_ADDRESS'): proc1 = subprocess.Popen( 'ps -p %i -o ppid=' % os.getppid(), shell=True, stdout=subprocess.PIPE, ) pppid = int(proc1.communicate()[0].rstrip()) proc2 = subprocess.Popen( 'sudo -u "%s" cat /proc/%i/environ' % (user, pppid), shell=True, stdout=subprocess.PIPE, ) os.environ['DBUS_SESSION_BUS_ADDRESS'] = [ x for x in proc2.communicate()[0].decode().split('\0') if x.startswith("DBUS_SESSION_BUS_ADDRESS=") ][0][25:] except: os.environ['DBUS_SESSION_BUS_ADDRESS'] = 'none' subprocess.call([ 'sudo', '-E', '-u', user, 'gsettings', 'set', "org.gnome.desktop.input-sources", "sources", repr([('xkb', l + '+' + v if v else l) for l, v in zip(kb_layouts, kb_variants)]) ], preexec_fn=drop_all_privileges) #subprocess.call(['sudo', '-u', user, 'pkill', '-USR1', 'indicator-keybo']) #end hack iso_639 = ElementTree.parse('/usr/share/xml/iso-codes/iso_639.xml') nodes = [ element for element in iso_639.findall('iso_639_entry') if element.get('iso_639_1_code') == lang ] display = GdkX11.x11_get_default_xdisplay() engine = Xkl.Engine.get_instance(display) if nodes: configreg = Xkl.ConfigRegistry.get_instance(engine) configreg.load(False) # Apparently iso_639_2B_code doesn't always work (fails with French) for prop in ('iso_639_2B_code', 'iso_639_2T_code', 'iso_639_1_code'): code = nodes[0].get(prop) if code is not None: configreg.foreach_language_variant(code, process_variant, None) if variants: restricted_variants = restrict_list(variants) call_setxkbmap(restricted_variants) gsettings.set_list(gsettings_key[0], gsettings_key[1], restricted_variants) break else: # Use the system default if no other keymaps can be determined. gsettings.set_list(gsettings_key[0], gsettings_key[1], []) engine.lock_group(0)