forked from AuroraMiddleware/gtk
gdkevents: Don't ignore modifiers that are not currently active
The X11 backend can mark modifiers like Shift as consumed even if they aren't actually active, which seems to be something to do with making shortcuts like `<Control><Shift>plus` and `<Control>plus` work as intended regardless of whether the plus symbol is obtained by pressing Shift and a key (like `+/=` on American, British or French keyboards) or not (like `*/+` on German keyboards). However, this can go badly wrong when the modifier is *not* pressed. For example, terminals normally have separate bindings for `<Control>c` (send SIGINT) and `<Control><Shift>c` (copy). If we disregard the consumed modifiers completely, when the X11 backend marks Shift as consumed, pressing Ctrl+c would send SIGINT *and* copy to the clipboard, which is not what was intended. By masking out the members of `consumed` that are not in `state`, we get the same interpretation for X11 and Wayland, and ensure that keyboard shortcuts that explicitly mention Shift can only be triggered while holding Shift. It continues to be possible to trigger keyboard shortcuts that do not explicitly mention Shift (such as `<Control>plus`) while holding Shift, if the backend reports Shift as having been consumed in order to generate the plus keysym. Resolves: https://gitlab.gnome.org/GNOME/gtk/-/issues/5095 Bug-Debian: https://bugs.debian.org/1016927 Signed-off-by: Simon McVittie <smcv@debian.org>
This commit is contained in:
parent
3a941eff4a
commit
79285bd63e
@ -1773,7 +1773,7 @@ gdk_key_event_matches (GdkEvent *event,
|
||||
guint ev_keyval;
|
||||
int layout;
|
||||
int level;
|
||||
GdkModifierType consumed_modifiers;
|
||||
GdkModifierType ignored_modifiers;
|
||||
GdkModifierType shift_group_mask;
|
||||
gboolean group_mod_is_accel_mod = FALSE;
|
||||
const GdkModifierType mask = GDK_CONTROL_MASK |
|
||||
@ -1792,7 +1792,23 @@ gdk_key_event_matches (GdkEvent *event,
|
||||
ev_keyval = self->translated[1].keyval;
|
||||
layout = self->translated[1].layout;
|
||||
level = self->translated[1].level;
|
||||
consumed_modifiers = self->translated[1].consumed;
|
||||
|
||||
/*
|
||||
* If a modifier is currently active (e.g. Shift is pressed) and was marked
|
||||
* as consumed, we ignore it for the purposes of matching shortcuts.
|
||||
* For example, when Ctrl+Shift+[plus/equals key] is translated into
|
||||
* Ctrl+plus on a keyboard where Shift+equals is the plus sign, we want
|
||||
* shortcuts for either <Control><Shift>plus or <Control>plus to match.
|
||||
* (See https://bugzilla.gnome.org/show_bug.cgi?id=100439)
|
||||
*
|
||||
* If a modifier is *not* currently active, the X11 backend can sometimes
|
||||
* mark it as consumed where the Wayland and Windows backends do not.
|
||||
* In this case, we still want to pay attention to its state.
|
||||
* For example, when Ctrl+x is translated into Ctrl+x, we only want to
|
||||
* trigger shortcuts for <Control>x, not for <Control><Shift>x.
|
||||
* (See https://gitlab.gnome.org/GNOME/gtk/-/issues/5095)
|
||||
*/
|
||||
ignored_modifiers = (self->translated[1].consumed & state);
|
||||
|
||||
/* if the group-toggling modifier is part of the default accel mod
|
||||
* mask, and it is active, disable it for matching
|
||||
@ -1804,7 +1820,7 @@ gdk_key_event_matches (GdkEvent *event,
|
||||
if (mask & shift_group_mask)
|
||||
group_mod_is_accel_mod = TRUE;
|
||||
|
||||
if ((modifiers & ~consumed_modifiers & mask) == (state & ~consumed_modifiers & mask))
|
||||
if ((modifiers & ~ignored_modifiers & mask) == (state & ~ignored_modifiers & mask))
|
||||
{
|
||||
/* modifier match */
|
||||
GdkKeymapKey *keys;
|
||||
|
Loading…
Reference in New Issue
Block a user