IMContextSimple/IMContextIME: Fix AltGr not working on Win32
authorPhilip Zander <philip.zander@gmail.com>
Thu, 13 Jan 2022 12:43:23 +0000 (13:43 +0100)
committerPhilip Zander <philip.zander@gmail.com>
Thu, 13 Jan 2022 16:26:59 +0000 (17:26 +0100)
The old code assumed that any key press containing Ctrl or Alt cannot be
regular text input. This is not correct on Win32 as AltGr = Ctrl + Alt.

gdk/win32/gdkevents-win32.c
gtk/gtkimcontextime.c
gtk/gtkimcontextsimple.c

index 9e752d12f577d3b5fae58aa21493f0e63b43944d..66c11d194c983e4640422b2491f7f8bc144e273a 100644 (file)
@@ -1772,10 +1772,11 @@ gdk_event_translate (MSG *msg,
 
   int i;
 
-  GdkModifierType state;
+  GdkModifierType state, consumed_modifiers;
   guint keyval;
   guint16 keycode;
   guint8 group;
+  int level;
   gboolean is_modifier;
 
   double delta_x, delta_y;
@@ -2003,6 +2004,10 @@ gdk_event_translate (MSG *msg,
            {
              keyval = gdk_unicode_to_keyval (wbuf[0]);
            }
+
+          /* TODO: What values to use for level and consumed_modifiers? */
+          level = 0;
+          consumed_modifiers = 0;
        }
       else
        {
@@ -2011,7 +2016,7 @@ gdk_event_translate (MSG *msg,
                                               state,
                                               group,
                                               &keyval,
-                                              NULL, NULL, NULL);
+                                              NULL, &level, &consumed_modifiers);
        }
 
       if (msg->message == WM_KEYDOWN)
@@ -2055,11 +2060,11 @@ gdk_event_translate (MSG *msg,
       if (msg->wParam == VK_MENU)
        state &= ~GDK_ALT_MASK;
 
-      /* FIXME do proper translation */
       translated.keyval = keyval;
-      translated.consumed = 0;
+      translated.consumed = consumed_modifiers;
       translated.layout = group;
-      translated.level = 0;
+      translated.level = level;
+
       event = gdk_key_event_new ((msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
                                    ? GDK_KEY_PRESS
                                    : GDK_KEY_RELEASE,
index c5ca85997c3a697d7fd8ce9fb93a97d36236b2eb..6025239543fa4c03819fa968c900d5ff1ebe8808 100644 (file)
@@ -344,7 +344,7 @@ gtk_im_context_ime_filter_keypress (GtkIMContext *context,
   GtkIMContextIME *context_ime;
   gboolean retval = FALSE;
   guint32 c;
-  GdkModifierType state;
+  GdkModifierType state, consumed_modifiers, no_text_input_mask;
   guint keyval;
 
   g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (context), FALSE);
@@ -353,9 +353,12 @@ gtk_im_context_ime_filter_keypress (GtkIMContext *context,
   if (gdk_event_get_event_type ((GdkEvent *) event) == GDK_KEY_RELEASE)
     return FALSE;
 
+  no_text_input_mask = GDK_ALT_MASK|GDK_CONTROL_MASK;
+
   state = gdk_event_get_modifier_state ((GdkEvent *) event);
+  consumed_modifiers = gdk_key_event_get_consumed_modifiers (event);
 
-  if (state & GDK_CONTROL_MASK)
+  if (state & no_text_input_mask & ~consumed_modifiers)
     return FALSE;
 
   context_ime = GTK_IM_CONTEXT_IME (context);
index 515219b493b44e4c9c9c0d97510a6ec3b3508ea8..a0e278c257813d0c4839f63ab786431b6ecd2793 100644 (file)
@@ -901,9 +901,24 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
        !is_hex_start && !is_hex_end && !is_escape && !is_backspace))
     {
       GdkModifierType no_text_input_mask;
+      GdkModifierType consumed_modifiers = 0;
 
       no_text_input_mask = GDK_ALT_MASK|GDK_CONTROL_MASK;
 
+#ifdef G_OS_WIN32
+     /* On Win32, even Ctrl + Alt could be text input because AltGr = Ctrl
+      * + Alt. For example, Ctrl + Alt + e = € on a German keyboard. The
+      * GdkEvent's state, however, reports *all* modifiers that were
+      * active at the time the key was pressed, including the ones that
+      * were consumed to generate the keyval. So we cannot just assume
+      * that any key event containing Ctrl or Alt is a keybinding. We have
+      * to first check if those modifiers were actually used to generate
+      * the keyval. If so, then the keypress is regular input and we
+      * should not exit here.
+      */
+      consumed_modifiers = gdk_key_event_get_consumed_modifiers (event);
+#endif
+
       if (priv->in_hex_sequence && priv->modifiers_dropped &&
          (keyval == GDK_KEY_Return ||
           keyval == GDK_KEY_ISO_Enter ||
@@ -912,7 +927,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
          return FALSE;
        }
 
-      if (state & no_text_input_mask)
+      if (state & no_text_input_mask & ~consumed_modifiers)
         {
           if (priv->in_hex_sequence || priv->in_compose_sequence)
             return TRUE; /* Don't leak random key events during preedit */