--- a/plugins/keyboard/gsd-keyboard-manager.c +++ b/plugins/keyboard/gsd-keyboard-manager.c @@ -115,6 +115,7 @@ GdkDeviceManager *device_manager; guint device_added_id; guint device_removed_id; + guint n_xkb_layouts; GDBusConnection *dbus_connection; GDBusNodeInfo *dbus_introspection; @@ -591,8 +592,8 @@ XkbSelectEventDetails (dpy, XkbUseCoreKbd, XkbStateNotify, - XkbModifierLockMask, - XkbModifierLockMask); + XkbModifierLockMask | XkbGroupLockMask, + XkbModifierLockMask | XkbGroupLockMask); } static unsigned @@ -659,6 +660,15 @@ } } + if (xkbev->state.changed & XkbGroupLockMask) { + /* Fix the locked group to the last group if it was changed by a grp: option. */ + Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + gint n_xkb_layouts = manager->priv->n_xkb_layouts; + + if (n_xkb_layouts > 0) + XkbLockGroup (display, XkbUseCoreKbd, n_xkb_layouts - 1); + } + return GDK_FILTER_CONTINUE; } @@ -696,16 +706,12 @@ static void upload_xkb_description (const gchar *rules_file_path, XkbRF_VarDefsRec *var_defs, - XkbComponentNamesRec *comp_names) + XkbComponentNamesRec *comp_names, + gint n_xkb_layouts) { Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); XkbDescRec *xkb_desc; gchar *rules_file; - - /* The layout we want is always in the first XKB group index - * so we should enforce it to make sure we never end up with - * the wrong one. */ - XkbLockGroup (display, XkbUseCoreKbd, 0); /* Upload it to the X server using the same method as setxkbmap */ xkb_desc = XkbGetKeyboardByName (display, @@ -726,6 +732,12 @@ if (!XkbRF_SetNamesProp (display, rules_file, var_defs)) g_warning ("Couldn't update the XKB root window property"); + /* The layout we want is always in the last XKB group index + * so we should enforce it to make sure we never end up with + * the wrong one. */ + if (n_xkb_layouts > 0) + XkbLockGroup (display, XkbUseCoreKbd, n_xkb_layouts - 1); + g_free (rules_file); } @@ -753,11 +765,11 @@ string = malloc (length); if (locale && latin) - sprintf (string, "%s,%s,%s", user, locale, latin); + sprintf (string, "%s,%s,%s", latin, locale, user); else if (locale) - sprintf (string, "%s,%s", user, locale); + sprintf (string, "%s,%s", locale, user); else if (latin) - sprintf (string, "%s,%s", user, latin); + sprintf (string, "%s,%s", latin, user); else sprintf (string, "%s", user); @@ -807,12 +819,14 @@ variant); } -static void +static gint replace_layout_and_variant (GsdKeyboardManager *manager, XkbRF_VarDefsRec *xkb_var_defs, const gchar *layout, const gchar *variant) { + gint n_xkb_layouts = 0; + /* Toolkits need to know about both a latin layout to handle * accelerators which are usually defined like Ctrl+C and a * layout with the symbols for the language used in UI strings @@ -825,7 +839,7 @@ const gchar *locale_variant = NULL; if (!layout) - return; + return n_xkb_layouts; if (!variant) variant = ""; @@ -859,6 +873,15 @@ free (xkb_var_defs->variant); xkb_var_defs->variant = build_xkb_group_string (variant, locale_variant, latin_variant); + + n_xkb_layouts = 1; + + if (latin_layout) + n_xkb_layouts++; + if (locale_layout) + n_xkb_layouts++; + + return n_xkb_layouts; } static gchar * @@ -986,13 +1009,14 @@ XkbRF_RulesRec *xkb_rules; XkbRF_VarDefsRec *xkb_var_defs; gchar *rules_file_path; + gint n_xkb_layouts; gnome_xkb_info_get_var_defs (&rules_file_path, &xkb_var_defs); free (xkb_var_defs->options); xkb_var_defs->options = options; - replace_layout_and_variant (manager, xkb_var_defs, layout, variant); + n_xkb_layouts = replace_layout_and_variant (manager, xkb_var_defs, layout, variant); gdk_error_trap_push (); @@ -1002,10 +1026,12 @@ xkb_comp_names = g_new0 (XkbComponentNamesRec, 1); XkbRF_GetComponents (xkb_rules, xkb_var_defs, xkb_comp_names); - upload_xkb_description (rules_file_path, xkb_var_defs, xkb_comp_names); + upload_xkb_description (rules_file_path, xkb_var_defs, xkb_comp_names, n_xkb_layouts); free_xkb_component_names (xkb_comp_names); XkbRF_Free (xkb_rules, True); + + manager->priv->n_xkb_layouts = n_xkb_layouts; } else { g_warning ("Couldn't load XKB rules"); } @@ -1966,6 +1992,7 @@ { manager->priv = GSD_KEYBOARD_MANAGER_GET_PRIVATE (manager); manager->priv->active_input_source = -1; + manager->priv->n_xkb_layouts = -1; } static void