changeset 28586:3fd992496509 v8.2.4817

patch 8.2.4817: Win32 GUI: modifiers are not always used Commit: https://github.com/vim/vim/commit/45684c6ec458c43e20db0b2f5f19ce000d34dbd5 Author: LemonBoy <thatlemon@gmail.com> Date: Sun Apr 24 15:46:42 2022 +0100 patch 8.2.4817: Win32 GUI: modifiers are not always used Problem: Win32 GUI: modifiers are not always used. Solution: Handle more modifiers. (closes https://github.com/vim/vim/issues/10269)
author Bram Moolenaar <Bram@vim.org>
date Sun, 24 Apr 2022 17:00:02 +0200
parents d2e063c391ff
children 315269cfa4cc
files src/gui_w32.c src/version.c
diffstat 2 files changed, 42 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -818,6 +818,26 @@ char_to_string(int ch, char_u *string, i
     return len;
 }
 
+    static int
+get_active_modifiers(void)
+{
+    int modifiers = 0;
+
+    if (GetKeyState(VK_CONTROL) & 0x8000)
+	modifiers |= MOD_MASK_CTRL;
+    if (GetKeyState(VK_SHIFT) & 0x8000)
+	modifiers |= MOD_MASK_SHIFT;
+    if (GetKeyState(VK_MENU) & 0x8000)
+	modifiers |= MOD_MASK_ALT;
+    // Windows handles Ctrl + Alt as AltGr, in that case no modifier is actually
+    // pressed.
+    if ((modifiers & (MOD_MASK_CTRL | MOD_MASK_ALT)) ==
+	    (MOD_MASK_CTRL | MOD_MASK_ALT))
+	modifiers &= ~(MOD_MASK_CTRL | MOD_MASK_ALT);
+
+    return modifiers;
+}
+
 /*
  * Key hit, add it to the input buffer.
  */
@@ -829,15 +849,12 @@ char_to_string(int ch, char_u *string, i
 {
     char_u	string[40];
     int		len = 0;
-    int		modifiers = 0;
+    int		modifiers;
     int		ch = cch;   // special keys are negative
 
     dead_key = 0;
 
-    if (GetKeyState(VK_SHIFT) & 0x8000)
-	modifiers |= MOD_MASK_SHIFT;
-    if (GetKeyState(VK_CONTROL) & 0x8000)
-	modifiers |= MOD_MASK_CTRL;
+    modifiers = get_active_modifiers();
 
     ch = simplify_key(ch, &modifiers);
     // remove the SHIFT modifier for keys where it's already included, e.g.,
@@ -887,12 +904,7 @@ char_to_string(int ch, char_u *string, i
     // ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
     // that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless
     // CAPSLOCK is pressed) at this point.
-    modifiers = MOD_MASK_ALT;
-    if (GetKeyState(VK_SHIFT) & 0x8000)
-	modifiers |= MOD_MASK_SHIFT;
-    if (GetKeyState(VK_CONTROL) & 0x8000)
-	modifiers |= MOD_MASK_CTRL;
-
+    modifiers = get_active_modifiers();
     ch = simplify_key(ch, &modifiers);
     // remove the SHIFT modifier for keys where it's already included, e.g.,
     // '(' and '*'
@@ -1917,10 +1929,18 @@ process_message(void)
 	     * VK_BACK, or VK_ESCAPE it means that he actually wants to deal
 	     * with the dead char now, so do nothing special and let Windows
 	     * handle it.
+	     *
+	     * Note that VK_SPACE combines with the dead_key's character and
+	     * only one WM_CHAR will be generated by TranslateMessage(), in
+	     * the two other cases two WM_CHAR will be generated: the dead
+	     * char and VK_BACK or VK_ESCAPE. That is most likely what the
+	     * user expects.
 	     */
 	    if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE))
 	    {
 		dead_key = 0;
+		TranslateMessage(&msg);
+		return;
 	    }
 	    // In modes where we are not typing, dead keys should behave
 	    // normally
@@ -1976,21 +1996,7 @@ process_message(void)
 							  NULL, NULL) == NULL)
 		    break;
 #endif
-		if (GetKeyState(VK_SHIFT) & 0x8000)
-		    modifiers |= MOD_MASK_SHIFT;
-		/*
-		 * Don't use caps-lock as shift, because these are special keys
-		 * being considered here, and we only want letters to get
-		 * shifted -- webb
-		 */
-		/*
-		if (GetKeyState(VK_CAPITAL) & 0x0001)
-		    modifiers ^= MOD_MASK_SHIFT;
-		*/
-		if (GetKeyState(VK_CONTROL) & 0x8000)
-		    modifiers |= MOD_MASK_CTRL;
-		if (GetKeyState(VK_MENU) & 0x8000)
-		    modifiers |= MOD_MASK_ALT;
+		modifiers = get_active_modifiers();
 
 		if (special_keys[i].vim_code1 == NUL)
 		    key = special_keys[i].vim_code0;
@@ -2036,13 +2042,6 @@ process_message(void)
 	    int		i;
 	    UINT	scan_code;
 
-	    if (GetKeyState(VK_SHIFT) & 0x8000)
-		modifiers |= MOD_MASK_SHIFT;
-	    if (GetKeyState(VK_CONTROL) & 0x8000)
-		modifiers |= MOD_MASK_CTRL;
-	    if (GetKeyState(VK_LMENU) & 0x8000)
-		modifiers |= MOD_MASK_ALT;
-
 	    // Construct the state table with only a few modifiers, we don't
 	    // really care about the presence of Ctrl/Alt as those modifiers are
 	    // handled by Vim separately.
@@ -2051,7 +2050,9 @@ process_message(void)
 		keyboard_state[VK_SHIFT] = 0x80;
 	    if (GetKeyState(VK_CAPITAL) & 0x0001)
 		keyboard_state[VK_CAPITAL] = 0x01;
-	    if (GetKeyState(VK_RMENU) & 0x8000)
+	    // Alt-Gr is synthesized as Alt + Ctrl.
+	    if ((GetKeyState(VK_MENU) & 0x8000) &&
+		    (GetKeyState(VK_CONTROL) & 0x8000))
 	    {
 		keyboard_state[VK_MENU] = 0x80;
 		keyboard_state[VK_CONTROL] = 0x80;
@@ -3795,11 +3796,13 @@ gui_mch_browsedir(char_u *title, char_u 
 
     if (fnames != NULL)
     {
-	if ((GetKeyState(VK_SHIFT) & 0x8000) != 0)
+	int kbd_modifiers = get_active_modifiers();
+
+	if ((kbd_modifiers & MOD_MASK_SHIFT) != 0)
 	    modifiers |= MOUSE_SHIFT;
-	if ((GetKeyState(VK_CONTROL) & 0x8000) != 0)
+	if ((kbd_modifiers & MOD_MASK_CTRL) != 0)
 	    modifiers |= MOUSE_CTRL;
-	if ((GetKeyState(VK_MENU) & 0x8000) != 0)
+	if ((kbd_modifiers & MOD_MASK_ALT) != 0)
 	    modifiers |= MOUSE_ALT;
 
 	gui_handle_drop(pt.x, pt.y, modifiers, fnames, cFiles);
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4817,
+/**/
     4816,
 /**/
     4815,