Merge lp:~attente/unity-settings-daemon/1226962 into lp:unity-settings-daemon

Proposed by William Hua
Status: Merged
Approved by: Sebastien Bacher
Approved revision: 4123
Merged at revision: 4125
Proposed branch: lp:~attente/unity-settings-daemon/1226962
Merge into: lp:unity-settings-daemon
Diff against target: 323 lines (+139/-23)
2 files modified
debian/changelog (+9/-0)
plugins/keyboard/gsd-keyboard-manager.c (+130/-23)
To merge this branch: bzr merge lp:~attente/unity-settings-daemon/1226962
Reviewer Review Type Date Requested Status
Sebastien Bacher Approve
Review via email: mp+280783@code.launchpad.net

Commit message

* plugins/keyboard/gsd-keyboard-manager.c:
  - Fix shortcuts for non-latin keyboard layouts in certain programs,
    but only when the user's layout switching shortcuts are not
    Shift_L, Shift_R, <Shift>Shift_L, or <Shift>Shift_R (LP: #1226962)

Description of the change

I'm currently maintaining a PPA (https://launchpad.net/~attente/+archive/ubuntu/java-non-latin-shortcuts) for this long-standing annoying bug. The PPA works for probably 99% of cases, however, it could not be merged because it causes a severe regression when the user chooses Shift_L, Shift_R, <Shift>Shift_L, or <Shift>Shift_R as a layout-switching shortcut: the user is unable to type uppercase text. This change contains the behaviour of that PPA, but monitors the switching shortcut to decide whether to do it or not.

To post a comment you must log in.
Revision history for this message
William Hua (attente) wrote :

Simple test case:

- add Greek keyboard layout in unity-control-center Text Entry panel
- launch Inkscape
- switch to Greek using the keyboard indicator
- try some shortcuts
  - Ctrl+Shift+D (normally opens the Document Preferences dialog)
  - Ctrl+Shift+F (normally opens the Fill and Stroke panel)
  - Ctrl+Shift+A (normally opens the Align and Distribute panel)

The shortcuts don't work with the current version of unity-settings-daemon, this patch should fix it.

Revision history for this message
Sebastien Bacher (seb128) wrote :

I'm not going to claim to understand the details of thosse keyboard layout and hotkeys but the approach and code look fine to me

review: Approve
Revision history for this message
Iain Lane (laney) wrote :

It broke shortcuts in terminator for me, so I reverted this for now - sorry.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2015-12-14 10:02:41 +0000
+++ debian/changelog 2015-12-16 23:50:53 +0000
@@ -1,3 +1,12 @@
1unity-settings-daemon (15.04.1+16.04.20151214-0ubuntu2) UNRELEASED; urgency=medium
2
3 * plugins/keyboard/gsd-keyboard-manager.c:
4 - Fix shortcuts for non-latin keyboard layouts in certain programs,
5 but only when the user's layout switching shortcuts are not
6 Shift_L, Shift_R, <Shift>Shift_L, or <Shift>Shift_R (LP: #1226962)
7
8 -- William Hua <william.hua@canonical.com> Wed, 16 Dec 2015 18:34:53 -0500
9
1unity-settings-daemon (15.04.1+16.04.20151214-0ubuntu1) xenial; urgency=medium10unity-settings-daemon (15.04.1+16.04.20151214-0ubuntu1) xenial; urgency=medium
211
3 [ David Henningsson ]12 [ David Henningsson ]
413
=== modified file 'plugins/keyboard/gsd-keyboard-manager.c'
--- plugins/keyboard/gsd-keyboard-manager.c 2015-10-28 17:52:16 +0000
+++ plugins/keyboard/gsd-keyboard-manager.c 2015-12-16 23:50:53 +0000
@@ -108,6 +108,11 @@
108#define DEFAULT_LANGUAGE "en_US"108#define DEFAULT_LANGUAGE "en_US"
109#define DEFAULT_LAYOUT "us"109#define DEFAULT_LAYOUT "us"
110110
111#define SWITCH_SETTINGS_DIR "org.gnome.desktop.wm.keybindings"
112
113#define SWITCH_INPUT_SOURCE_KEY "switch-input-source"
114#define SWITCH_INPUT_SOURCE_BACKWARD_KEY "switch-input-source-backward"
115
111#define GSD_KEYBOARD_DBUS_NAME "org.gnome.SettingsDaemon.Keyboard"116#define GSD_KEYBOARD_DBUS_NAME "org.gnome.SettingsDaemon.Keyboard"
112#define GSD_KEYBOARD_DBUS_PATH "/org/gnome/SettingsDaemon/Keyboard"117#define GSD_KEYBOARD_DBUS_PATH "/org/gnome/SettingsDaemon/Keyboard"
113118
@@ -118,6 +123,7 @@
118 GSettings *gsettings;123 GSettings *gsettings;
119 GSettings *input_sources_settings;124 GSettings *input_sources_settings;
120 GSettings *interface_settings;125 GSettings *interface_settings;
126 GSettings *switch_settings;
121 GnomeXkbInfo *xkb_info;127 GnomeXkbInfo *xkb_info;
122 GDBusProxy *localed;128 GDBusProxy *localed;
123 GCancellable *cancellable;129 GCancellable *cancellable;
@@ -138,6 +144,9 @@
138 GdkDeviceManager *device_manager;144 GdkDeviceManager *device_manager;
139 guint device_added_id;145 guint device_added_id;
140 guint device_removed_id;146 guint device_removed_id;
147 guint n_xkb_layouts;
148 gboolean latin_first;
149 gboolean shift_switch;
141150
142 GDBusConnection *dbus_connection;151 GDBusConnection *dbus_connection;
143 GDBusNodeInfo *dbus_introspection;152 GDBusNodeInfo *dbus_introspection;
@@ -623,8 +632,8 @@
623 XkbSelectEventDetails (dpy,632 XkbSelectEventDetails (dpy,
624 XkbUseCoreKbd,633 XkbUseCoreKbd,
625 XkbStateNotify,634 XkbStateNotify,
626 XkbModifierLockMask,635 XkbModifierLockMask | XkbGroupLockMask,
627 XkbModifierLockMask);636 XkbModifierLockMask | XkbGroupLockMask);
628}637}
629638
630static unsigned639static unsigned
@@ -691,6 +700,13 @@
691 }700 }
692 }701 }
693702
703 if (manager->priv->latin_first && (xkbev->state.changed & XkbGroupLockMask) && manager->priv->n_xkb_layouts > 0) {
704 Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
705
706 /* Fix the locked group to the last group if it was changed by a grp: option. */
707 XkbLockGroup (display, XkbUseCoreKbd, manager->priv->n_xkb_layouts - 1);
708 }
709
694 return GDK_FILTER_CONTINUE;710 return GDK_FILTER_CONTINUE;
695}711}
696712
@@ -728,16 +744,20 @@
728static void744static void
729upload_xkb_description (const gchar *rules_file_path,745upload_xkb_description (const gchar *rules_file_path,
730 XkbRF_VarDefsRec *var_defs,746 XkbRF_VarDefsRec *var_defs,
731 XkbComponentNamesRec *comp_names)747 XkbComponentNamesRec *comp_names,
748 gint n_xkb_layouts,
749 gboolean latin_first)
732{750{
733 Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());751 Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
734 XkbDescRec *xkb_desc;752 XkbDescRec *xkb_desc;
735 gchar *rules_file;753 gchar *rules_file;
736754
737 /* The layout we want is always in the first XKB group index755 if (!latin_first) {
738 * so we should enforce it to make sure we never end up with756 /* The layout we want is always in the first XKB group index
739 * the wrong one. */757 * so we should enforce it to make sure we never end up with
740 XkbLockGroup (display, XkbUseCoreKbd, 0);758 * the wrong one. */
759 XkbLockGroup (display, XkbUseCoreKbd, 0);
760 }
741761
742 /* Upload it to the X server using the same method as setxkbmap */762 /* Upload it to the X server using the same method as setxkbmap */
743 xkb_desc = XkbGetKeyboardByName (display,763 xkb_desc = XkbGetKeyboardByName (display,
@@ -758,13 +778,21 @@
758 if (!XkbRF_SetNamesProp (display, rules_file, var_defs))778 if (!XkbRF_SetNamesProp (display, rules_file, var_defs))
759 g_warning ("Couldn't update the XKB root window property");779 g_warning ("Couldn't update the XKB root window property");
760780
781 if (latin_first && n_xkb_layouts > 0) {
782 /* The layout we want is always in the last XKB group index
783 * so we should enforce it to make sure we never end up with
784 * the wrong one. */
785 XkbLockGroup (display, XkbUseCoreKbd, n_xkb_layouts - 1);
786 }
787
761 g_free (rules_file);788 g_free (rules_file);
762}789}
763790
764static gchar *791static gchar *
765build_xkb_group_string (const gchar *user,792build_xkb_group_string (const gchar *user,
766 const gchar *locale,793 const gchar *locale,
767 const gchar *latin)794 const gchar *latin,
795 gboolean shift_switch)
768{796{
769 gchar *string;797 gchar *string;
770 gsize length = 0;798 gsize length = 0;
@@ -784,14 +812,25 @@
784812
785 string = malloc (length);813 string = malloc (length);
786814
787 if (locale && latin)815 if (shift_switch) {
788 sprintf (string, "%s,%s,%s", user, locale, latin);816 if (locale && latin)
789 else if (locale)817 sprintf (string, "%s,%s,%s", user, locale, latin);
790 sprintf (string, "%s,%s", user, locale);818 else if (locale)
791 else if (latin)819 sprintf (string, "%s,%s", user, locale);
792 sprintf (string, "%s,%s", user, latin);820 else if (latin)
793 else821 sprintf (string, "%s,%s", user, latin);
794 sprintf (string, "%s", user);822 else
823 sprintf (string, "%s", user);
824 } else {
825 if (locale && latin)
826 sprintf (string, "%s,%s,%s", latin, locale, user);
827 else if (locale)
828 sprintf (string, "%s,%s", locale, user);
829 else if (latin)
830 sprintf (string, "%s,%s", latin, user);
831 else
832 sprintf (string, "%s", user);
833 }
795834
796 return string;835 return string;
797}836}
@@ -839,7 +878,7 @@
839 variant);878 variant);
840}879}
841880
842static void881static gint
843replace_layout_and_variant (GsdKeyboardManager *manager,882replace_layout_and_variant (GsdKeyboardManager *manager,
844 XkbRF_VarDefsRec *xkb_var_defs,883 XkbRF_VarDefsRec *xkb_var_defs,
845 const gchar *layout,884 const gchar *layout,
@@ -855,9 +894,10 @@
855 const gchar *latin_variant = "";894 const gchar *latin_variant = "";
856 const gchar *locale_layout = NULL;895 const gchar *locale_layout = NULL;
857 const gchar *locale_variant = NULL;896 const gchar *locale_variant = NULL;
897 gint n_xkb_layouts = 0;
858898
859 if (!layout)899 if (!layout)
860 return;900 return n_xkb_layouts;
861901
862 if (!variant)902 if (!variant)
863 variant = "";903 variant = "";
@@ -887,10 +927,19 @@
887 }927 }
888928
889 free (xkb_var_defs->layout);929 free (xkb_var_defs->layout);
890 xkb_var_defs->layout = build_xkb_group_string (layout, locale_layout, latin_layout);930 xkb_var_defs->layout = build_xkb_group_string (layout, locale_layout, latin_layout, manager->priv->shift_switch);
891931
892 free (xkb_var_defs->variant);932 free (xkb_var_defs->variant);
893 xkb_var_defs->variant = build_xkb_group_string (variant, locale_variant, latin_variant);933 xkb_var_defs->variant = build_xkb_group_string (variant, locale_variant, latin_variant, manager->priv->shift_switch);
934
935 n_xkb_layouts = 1;
936
937 if (latin_layout)
938 n_xkb_layouts++;
939 if (locale_layout)
940 n_xkb_layouts++;
941
942 return n_xkb_layouts;
894}943}
895944
896static gchar *945static gchar *
@@ -1018,13 +1067,14 @@
1018 XkbRF_RulesRec *xkb_rules;1067 XkbRF_RulesRec *xkb_rules;
1019 XkbRF_VarDefsRec *xkb_var_defs;1068 XkbRF_VarDefsRec *xkb_var_defs;
1020 gchar *rules_file_path;1069 gchar *rules_file_path;
1070 gint n_xkb_layouts;
10211071
1022 gsd_xkb_get_var_defs (&rules_file_path, &xkb_var_defs);1072 gsd_xkb_get_var_defs (&rules_file_path, &xkb_var_defs);
10231073
1024 free (xkb_var_defs->options);1074 free (xkb_var_defs->options);
1025 xkb_var_defs->options = options;1075 xkb_var_defs->options = options;
10261076
1027 replace_layout_and_variant (manager, xkb_var_defs, layout, variant);1077 n_xkb_layouts = replace_layout_and_variant (manager, xkb_var_defs, layout, variant);
10281078
1029 gdk_error_trap_push ();1079 gdk_error_trap_push ();
10301080
@@ -1034,10 +1084,14 @@
1034 xkb_comp_names = g_new0 (XkbComponentNamesRec, 1);1084 xkb_comp_names = g_new0 (XkbComponentNamesRec, 1);
10351085
1036 XkbRF_GetComponents (xkb_rules, xkb_var_defs, xkb_comp_names);1086 XkbRF_GetComponents (xkb_rules, xkb_var_defs, xkb_comp_names);
1037 upload_xkb_description (rules_file_path, xkb_var_defs, xkb_comp_names);1087 upload_xkb_description (rules_file_path, xkb_var_defs, xkb_comp_names,
1088 n_xkb_layouts, !manager->priv->shift_switch);
1089 manager->priv->latin_first = !manager->priv->shift_switch;
10381090
1039 free_xkb_component_names (xkb_comp_names);1091 free_xkb_component_names (xkb_comp_names);
1040 XkbRF_Free (xkb_rules, True);1092 XkbRF_Free (xkb_rules, True);
1093
1094 manager->priv->n_xkb_layouts = n_xkb_layouts;
1041 } else {1095 } else {
1042 g_warning ("Couldn't load XKB rules");1096 g_warning ("Couldn't load XKB rules");
1043 }1097 }
@@ -2393,6 +2447,54 @@
2393#endif2447#endif
23942448
2395static gboolean2449static gboolean
2450is_shift (const gchar *shortcut)
2451{
2452 return shortcut && (g_str_equal (shortcut, "Shift_L") || g_str_equal (shortcut, "<Shift>Shift_L")
2453 || g_str_equal (shortcut, "Shift_R") || g_str_equal (shortcut, "<Shift>Shift_R"));
2454}
2455
2456static gboolean
2457is_shift_switch (GSettings *settings)
2458{
2459 gboolean shift_switch = FALSE;
2460 gchar **shortcuts;
2461 gchar **i;
2462
2463 shortcuts = g_settings_get_strv (settings, SWITCH_INPUT_SOURCE_KEY);
2464
2465 for (i = shortcuts; !shift_switch && *i; i++)
2466 shift_switch = is_shift (*i);
2467
2468 g_strfreev (shortcuts);
2469
2470 if (shift_switch)
2471 return shift_switch;
2472
2473 shortcuts = g_settings_get_strv (settings, SWITCH_INPUT_SOURCE_BACKWARD_KEY);
2474
2475 for (i = shortcuts; !shift_switch && *i; i++)
2476 shift_switch = is_shift (*i);
2477
2478 g_strfreev (shortcuts);
2479
2480 return shift_switch;
2481}
2482
2483static void
2484switch_settings_changed (GSettings *settings,
2485 gchar *key,
2486 gpointer user_data)
2487{
2488 GsdKeyboardManager *manager = user_data;
2489 GsdKeyboardManagerPrivate *priv = manager->priv;
2490
2491 if (is_shift_switch (settings) != priv->shift_switch) {
2492 priv->shift_switch = !priv->shift_switch;
2493 apply_input_source (manager, priv->active_input_source);
2494 }
2495}
2496
2497static gboolean
2396start_keyboard_idle_cb (GsdKeyboardManager *manager)2498start_keyboard_idle_cb (GsdKeyboardManager *manager)
2397{2499{
2398 const gchar *module;2500 const gchar *module;
@@ -2419,6 +2521,8 @@
24192521
2420 manager->priv->input_sources_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);2522 manager->priv->input_sources_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
2421 manager->priv->interface_settings = g_settings_new (GNOME_DESKTOP_INTERFACE_DIR);2523 manager->priv->interface_settings = g_settings_new (GNOME_DESKTOP_INTERFACE_DIR);
2524 manager->priv->switch_settings = g_settings_new (SWITCH_SETTINGS_DIR);
2525 manager->priv->shift_switch = is_shift_switch (manager->priv->switch_settings);
2422 manager->priv->xkb_info = gnome_xkb_info_new ();2526 manager->priv->xkb_info = gnome_xkb_info_new ();
24232527
2424#ifdef HAVE_FCITX2528#ifdef HAVE_FCITX
@@ -2473,7 +2577,8 @@
2473 G_CALLBACK (settings_changed), manager);2577 G_CALLBACK (settings_changed), manager);
2474 g_signal_connect (G_OBJECT (manager->priv->gsettings), "changed",2578 g_signal_connect (G_OBJECT (manager->priv->gsettings), "changed",
2475 G_CALLBACK (gsettings_changed), manager);2579 G_CALLBACK (gsettings_changed), manager);
24762580 g_signal_connect (G_OBJECT (manager->priv->switch_settings), "changed",
2581 G_CALLBACK (switch_settings_changed), manager);
2477 g_signal_connect (G_OBJECT (manager->priv->input_sources_settings), "change-event",2582 g_signal_connect (G_OBJECT (manager->priv->input_sources_settings), "change-event",
2478 G_CALLBACK (apply_input_sources_settings), manager);2583 G_CALLBACK (apply_input_sources_settings), manager);
24792584
@@ -2527,6 +2632,7 @@
2527 g_clear_object (&p->cancellable);2632 g_clear_object (&p->cancellable);
25282633
2529 g_clear_object (&p->settings);2634 g_clear_object (&p->settings);
2635 g_clear_object (&p->switch_settings);
2530 g_clear_object (&p->input_sources_settings);2636 g_clear_object (&p->input_sources_settings);
2531 g_clear_object (&p->interface_settings);2637 g_clear_object (&p->interface_settings);
2532 g_clear_object (&p->xkb_info);2638 g_clear_object (&p->xkb_info);
@@ -2577,6 +2683,7 @@
2577{2683{
2578 manager->priv = GSD_KEYBOARD_MANAGER_GET_PRIVATE (manager);2684 manager->priv = GSD_KEYBOARD_MANAGER_GET_PRIVATE (manager);
2579 manager->priv->active_input_source = -1;2685 manager->priv->active_input_source = -1;
2686 manager->priv->n_xkb_layouts = -1;
2580}2687}
25812688
2582static void2689static void

Subscribers

People subscribed via source and target branches