[gnome-control-center] keyboard: Handle shift shortcut modifier the same way as the shell does
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] keyboard: Handle shift shortcut modifier the same way as the shell does
- Date: Mon, 22 Aug 2022 12:54:09 +0000 (UTC)
commit bad61a2229e2485ac37211ea5ebf1fa6b7ce2ca1
Author: Sebastian Keller <skeller gnome org>
Date: Thu Dec 16 23:48:57 2021 +0100
keyboard: Handle shift shortcut modifier the same way as the shell does
The way shortcuts in mutter/gnome-shell work is that it looks up the
keycode that generates the shortcut keyval at the lowest shift level and
then checks if all the modifiers match. This does not work for shortcuts
that for example include "dollar" to represent "<Shift>4", because on
some keyboards/layout there is a separate dollar key key with its own
keycode. This would be at a lower shift level than "<Shift>4".
By always translating such shortcuts to "<Shift>number", we make sure
the resulting shortcut will work in the shell and is closer to what the
user likely intended the shortcut to be, because numbers are usually
assigned to things that can be enumerated, such as workspaces or
favorite applications.
This also special cases the num-row key on layouts such as AZERTY, where
the number is the shifted keyval, to always prefer the number. Due to
the way the shell interprets these shortcuts, they still work and by
always using numbers they work across different layouts.
This change also fixes that pressing "<Shift><Super>4" was turned into
"<Shift><Super>dollar", which effectively included the "<Shift>" twice.
Fixes: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1528
panels/keyboard/cc-keyboard-shortcut-editor.c | 2 +-
panels/keyboard/keyboard-shortcuts.c | 73 ++++++++++++++++++++-------
2 files changed, 57 insertions(+), 18 deletions(-)
---
diff --git a/panels/keyboard/cc-keyboard-shortcut-editor.c b/panels/keyboard/cc-keyboard-shortcut-editor.c
index 95fa3aa65..66cf02460 100644
--- a/panels/keyboard/cc-keyboard-shortcut-editor.c
+++ b/panels/keyboard/cc-keyboard-shortcut-editor.c
@@ -687,7 +687,7 @@ on_key_pressed_cb (GtkEventControllerKey *key_controller,
if (!editing)
return GDK_EVENT_PROPAGATE;
- normalize_keyval_and_mask (keyval, state,
+ normalize_keyval_and_mask (keycode, state,
gtk_event_controller_key_get_group (key_controller),
&keyval_lower, &real_mask);
diff --git a/panels/keyboard/keyboard-shortcuts.c b/panels/keyboard/keyboard-shortcuts.c
index c40794d80..cfaa11ecb 100644
--- a/panels/keyboard/keyboard-shortcuts.c
+++ b/panels/keyboard/keyboard-shortcuts.c
@@ -377,35 +377,74 @@ convert_keysym_state_to_string (const CcKeyCombo *combo)
return name;
}
+/* This adjusts the keyval and modifiers such that it matches how
+ * gnome-shell detects shortcuts, which works as follows:
+ * First for the non-modifier key, the keycode that generates this
+ * keyval at the lowest shift level is determined, which might be a
+ * level > 0, such as for numbers in the num-row in AZERTY.
+ * Next it checks if all the specified modifiers were pressed.
+ */
void
-normalize_keyval_and_mask (guint keyval,
+normalize_keyval_and_mask (guint keycode,
GdkModifierType mask,
guint group,
guint *out_keyval,
GdkModifierType *out_mask)
{
- guint keyval_lower;
- GdkModifierType real_mask;
-
- real_mask = mask & gtk_accelerator_get_default_mod_mask ();
-
- keyval_lower = gdk_keyval_to_lower (keyval);
+ guint unmodified_keyval;
+ guint shifted_keyval;
+ GdkModifierType explicit_modifiers;
+ GdkModifierType used_modifiers;
+
+ /* We want shift to always be included as explicit modifier for
+ * gnome-shell shortcuts. That's because users usually think of
+ * shortcuts as including the shift key rather than being defined
+ * for the shifted keyval.
+ * This helps with num-row keys which have different keyvals on
+ * different layouts for example, but also with keys that have
+ * explicit key codes at shift level 0, that gnome-shell would prefer
+ * over shifted ones, such the DOLLAR key.
+ */
+ explicit_modifiers = gtk_accelerator_get_default_mod_mask () | GDK_SHIFT_MASK;
+ used_modifiers = mask & explicit_modifiers;
+
+ /* Find the base keyval of the pressed key without the explicit
+ * modifiers. */
+ gdk_display_translate_key (gdk_display_get_default (),
+ keycode,
+ mask & ~explicit_modifiers,
+ group,
+ &unmodified_keyval,
+ NULL,
+ NULL,
+ NULL);
+
+ /* Normalize num-row keys to the number value. This allows these
+ * shortcuts to work when switching between AZERTY and layouts where
+ * the numbers are at shift level 0. */
+ gdk_display_translate_key (gdk_display_get_default (),
+ keycode,
+ GDK_SHIFT_MASK | (mask & ~explicit_modifiers),
+ group,
+ &shifted_keyval,
+ NULL,
+ NULL,
+ NULL);
+
+ if (shifted_keyval >= GDK_KEY_0 && shifted_keyval <= GDK_KEY_9)
+ unmodified_keyval = shifted_keyval;
/* Normalise <Tab> */
- if (keyval_lower == GDK_KEY_ISO_Left_Tab)
- keyval_lower = GDK_KEY_Tab;
-
- /* Put shift back if it changed the case of the key, not otherwise. */
- if (keyval_lower != keyval)
- real_mask |= GDK_SHIFT_MASK;
+ if (unmodified_keyval == GDK_KEY_ISO_Left_Tab)
+ unmodified_keyval = GDK_KEY_Tab;
- if (keyval_lower == GDK_KEY_Sys_Req && (real_mask & GDK_ALT_MASK) != 0)
+ if (unmodified_keyval == GDK_KEY_Sys_Req && (used_modifiers & GDK_ALT_MASK) != 0)
{
/* HACK: we don't want to use SysRq as a keybinding (but we do
* want Alt+Print), so we avoid translation from Alt+Print to SysRq */
- keyval_lower = GDK_KEY_Print;
+ unmodified_keyval = GDK_KEY_Print;
}
- *out_keyval = keyval_lower;
- *out_mask = real_mask;
+ *out_keyval = unmodified_keyval;
+ *out_mask = used_modifiers;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]