changeset 31674:edbadc330871 v9.0.1169

patch 9.0.1169: some key+modifier tests fail on some AppVeyor images Commit: https://github.com/vim/vim/commit/566f76e6566ccc418b25d51f454d2cc509ca7f8a Author: Christopher Plewright <chris@createng.com> Date: Tue Jan 10 13:43:04 2023 +0000 patch 9.0.1169: some key+modifier tests fail on some AppVeyor images Problem: Some key+modifier tests fail on some AppVeyor images. Solution: Adjust the tests for key movements and fix the revealed bugs. (Christopher Plewright, closes #11798)
author Bram Moolenaar <Bram@vim.org>
date Tue, 10 Jan 2023 14:45:07 +0100
parents 7ae148439320
children 3c3d2a267427
files src/os_win32.c src/testdir/test_gui.vim src/testdir/test_mswin_event.vim src/version.c
diffstat 4 files changed, 193 insertions(+), 202 deletions(-) [+]
line wrap: on
line diff
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -1043,7 +1043,7 @@ win32_kbd_patch_key(
     }
 
     // check if it already has a valid unicode character.
-    if (pker->uChar.UnicodeChar > 0 && pker->uChar.UnicodeChar < 0xFFFD)
+    if (pker->uChar.UnicodeChar != 0)
 	return 1;
 
     CLEAR_FIELD(abKeystate);
@@ -1154,12 +1154,9 @@ decode_key_event(
 			else if (pker->wVirtualKeyCode >= VK_END
 				&& pker->wVirtualKeyCode <= VK_DOWN)
 			{
-			    // VK_END   0x23
-			    // VK_HOME  0x24
-			    // VK_LEFT  0x25
-			    // VK_UP    0x26
-			    // VK_RIGHT 0x27
-			    // VK_DOWN  0x28
+			    // (0x23 - 0x28): VK_END, VK_HOME,
+			    // VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN
+
 			    *pmodifiers = 0;
 			    *pch2 = VirtKeyMap[i].chAlone;
 			    if ((nModifs & SHIFT) != 0
@@ -1167,7 +1164,7 @@ decode_key_event(
 			    {
 				*pch2 = VirtKeyMap[i].chShift;
 			    }
-			    else if ((nModifs & CTRL) != 0
+			    if ((nModifs & CTRL) != 0
 						     && (nModifs & ~CTRL) == 0)
 			    {
 				*pch2 = VirtKeyMap[i].chCtrl;
@@ -1178,17 +1175,38 @@ decode_key_event(
 				    *pch2 = VirtKeyMap[i].chAlone;
 				}
 			    }
-			    else if ((nModifs & ALT) != 0
-						      && (nModifs & ~ALT) == 0)
-			    {
-				*pch2 = VirtKeyMap[i].chAlt;
-			    }
-			    else if ((nModifs & SHIFT) != 0
+			    if ((nModifs & SHIFT) != 0
 						      && (nModifs & CTRL) != 0)
 			    {
 				*pmodifiers |= MOD_MASK_CTRL;
 				*pch2 = VirtKeyMap[i].chShift;
 			    }
+			    if ((nModifs & ALT) != 0)
+			    {
+				*pch2 = VirtKeyMap[i].chAlt;
+				*pmodifiers |= MOD_MASK_ALT;
+				if ((nModifs & ~ALT) == 0)
+				{
+				    *pch2 = VirtKeyMap[i].chAlone;
+				}
+				else if ((nModifs & SHIFT) != 0)
+				{
+				    *pch2 = VirtKeyMap[i].chShift;
+				}
+				else if ((nModifs & CTRL) != 0)
+				{
+				    if (pker->wVirtualKeyCode == VK_UP
+					|| pker->wVirtualKeyCode == VK_DOWN)
+				    {
+					*pmodifiers |= MOD_MASK_CTRL;
+					*pch2 = VirtKeyMap[i].chAlone;
+				    }
+				    else
+				    {
+					*pch2 = VirtKeyMap[i].chCtrl;
+				    }
+				}
+			    }
 			}
 			else
 			{
@@ -1319,7 +1337,7 @@ encode_key_event(dict_T *args, INPUT_REC
 	}
 	ker.dwControlKeyState |= s_dwMods;
 	ker.wVirtualKeyCode = vkCode;
-	ker.uChar.UnicodeChar = 0xFFFD;  // UNICODE REPLACEMENT CHARACTER
+	ker.uChar.UnicodeChar = 0;
 	ir->Event.KeyEvent = ker;
 	vim_free(action);
     }
--- a/src/testdir/test_gui.vim
+++ b/src/testdir/test_gui.vim
@@ -1656,94 +1656,8 @@ func Test_gui_lowlevel_keyevent()
     call assert_equal(nr2char(kc - 64), ch)
   endfor
 
-  " Test for the various Ctrl and Shift key combinations.
-  " Refer to the following page for the virtual key codes:
-  " https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
-  let keytests = [
-    \ [[0x10, 0x21], "S-Pageup", 2],
-    \ [[0xA0, 0x21], "S-Pageup", 2],
-    \ [[0xA1, 0x21], "S-Pageup", 2],
-    \ [[0x11, 0x21], "C-Pageup", 4],
-    \ [[0xA2, 0x21], "C-Pageup", 4],
-    \ [[0xA3, 0x21], "C-Pageup", 4],
-    \ [[0x11, 0x10, 0x21], "C-S-Pageup", 6],
-    \ [[0x10, 0x22], "S-PageDown", 2],
-    \ [[0xA0, 0x22], "S-PageDown", 2],
-    \ [[0xA1, 0x22], "S-PageDown", 2],
-    \ [[0x11, 0x22], "C-PageDown", 4],
-    \ [[0xA2, 0x22], "C-PageDown", 4],
-    \ [[0xA3, 0x22], "C-PageDown", 4],
-    \ [[0x11, 0x10, 0x22], "C-S-PageDown", 6],
-    \ [[0x10, 0x23], "S-End", 0],
-    \ [[0x11, 0x23], "C-End", 0],
-    \ [[0x11, 0x10, 0x23], "C-S-End", 4],
-    \ [[0x10, 0x24], "S-Home", 0],
-    \ [[0x11, 0x24], "C-Home", 0],
-    \ [[0x11, 0x10, 0x24], "C-S-Home", 4],
-    \ [[0x10, 0x25], "S-Left", 0],
-    \ [[0x11, 0x25], "C-Left", 0],
-    \ [[0x11, 0x10, 0x25], "C-S-Left", 4],
-    \ [[0x10, 0x26], "S-Up", 0],
-    \ [[0x11, 0x26], "C-Up", 4],
-    \ [[0x11, 0x10, 0x26], "C-S-Up", 4],
-    \ [[0x10, 0x27], "S-Right", 0],
-    \ [[0x11, 0x27], "C-Right", 0],
-    \ [[0x11, 0x10, 0x27], "C-S-Right", 4],
-    \ [[0x10, 0x28], "S-Down", 0],
-    \ [[0x11, 0x28], "C-Down", 4],
-    \ [[0x11, 0x10, 0x28], "C-S-Down", 4],
-    \ [[0x11, 0x30], "C-0", 4],
-    \ [[0x11, 0x31], "C-1", 4],
-    \ [[0x11, 0x32], "C-@", 0],
-    \ [[0x11, 0x33], "C-3", 4],
-    \ [[0x11, 0x34], "C-4", 4],
-    \ [[0x11, 0x35], "C-5", 4],
-    \ [[0x11, 0x36], "C-^", 0],
-    \ [[0x11, 0x37], "C-7", 4],
-    \ [[0x11, 0x38], "C-8", 4],
-    \ [[0x11, 0x39], "C-9", 4],
-    \ [[0x11, 0x60], "C-0", 4],
-    \ [[0x11, 0x61], "C-1", 4],
-    \ [[0x11, 0x62], "C-2", 4],
-    \ [[0x11, 0x63], "C-3", 4],
-    \ [[0x11, 0x64], "C-4", 4],
-    \ [[0x11, 0x65], "C-5", 4],
-    \ [[0x11, 0x66], "C-6", 4],
-    \ [[0x11, 0x67], "C-7", 4],
-    \ [[0x11, 0x68], "C-8", 4],
-    \ [[0x11, 0x69], "C-9", 4],
-    \ [[0x11, 0x6A], "C-*", 4],
-    \ [[0x11, 0x6B], "C-+", 4],
-    \ [[0x11, 0x6D], "C--", 4],
-    \ [[0x11, 0xBD], "C-_", 0],
-    \ [[0x11, 0x70], "C-F1", 4],
-    \ [[0x11, 0x10, 0x70], "C-S-F1", 4],
-    \ [[0x11, 0x71], "C-F2", 4],
-    \ [[0x11, 0x10, 0x71], "C-S-F2", 4],
-    \ [[0x11, 0x72], "C-F3", 4],
-    \ [[0x11, 0x10, 0x72], "C-S-F3", 4],
-    \ [[0x11, 0x73], "C-F4", 4],
-    \ [[0x11, 0x10, 0x73], "C-S-F4", 4],
-    \ [[0x11, 0x74], "C-F5", 4],
-    \ [[0x11, 0x10, 0x74], "C-S-F5", 4],
-    \ [[0x11, 0x75], "C-F6", 4],
-    \ [[0x11, 0x10, 0x75], "C-S-F6", 4],
-    \ [[0x11, 0x76], "C-F7", 4],
-    \ [[0x11, 0x10, 0x76], "C-S-F7", 4],
-    \ [[0x11, 0x77], "C-F8", 4],
-    \ [[0x11, 0x10, 0x77], "C-S-F8", 4],
-    \ [[0x11, 0x78], "C-F9", 4],
-    \ [[0x11, 0x10, 0x78], "C-S-F9", 4],
-    \ ]
-
-  for [kcodes, kstr, kmod] in keytests
-    call SendKeys(kcodes)
-    let ch = getcharstr()
-    let mod = getcharmod()
-    let keycode = eval('"\<' .. kstr .. '>"')
-    call assert_equal(keycode, ch, $"key = {kstr}")
-    call assert_equal(kmod, mod, $"key = {kstr}")
-  endfor
+  " Testing more extensive windows keyboard handling
+  " is covered in test_mswin_event.vim
 
   bw!
 endfunc
--- a/src/testdir/test_mswin_event.vim
+++ b/src/testdir/test_mswin_event.vim
@@ -155,19 +155,19 @@ let s:VK = {
     \ 'ESCAPE'     : 0x1B
     \ }
 
-  let s:vim_MOD_MASK_SHIFT = 0x02
-  let s:vim_MOD_MASK_CTRL  = 0x04
-  let s:vim_MOD_MASK_ALT   = 0x08
+  let s:MOD_MASK_SHIFT = 0x02
+  let s:MOD_MASK_CTRL  = 0x04
+  let s:MOD_MASK_ALT   = 0x08
   
   let s:vim_key_modifiers = [
     \ ["",       0,   []],
-    \ ["S-",     2,   [s:VK.SHIFT]],
-    \ ["C-",     4,   [s:VK.CONTROL]],
-    \ ["C-S-",   6,   [s:VK.CONTROL, s:VK.SHIFT]],
-    \ ["A-",     8,   [s:VK.MENU]],
-    \ ["A-S-",   10,  [s:VK.MENU, s:VK.SHIFT]],
-    \ ["A-C-",   12,  [s:VK.MENU, s:VK.CONTROL]],
-    \ ["A-C-S-", 14,  [s:VK.MENU, s:VK.CONTROL, s:VK.SHIFT]],
+    \ ["S-",     2,   [s:VK.LSHIFT]],
+    \ ["C-",     4,   [s:VK.LCONTROL]],
+    \ ["C-S-",   6,   [s:VK.LCONTROL, s:VK.LSHIFT]],
+    \ ["A-",     8,   [s:VK.LMENU]],
+    \ ["A-S-",   10,  [s:VK.LMENU, s:VK.LSHIFT]],
+    \ ["A-C-",   12,  [s:VK.LMENU, s:VK.LCONTROL]],
+    \ ["A-C-S-", 14,  [s:VK.LMENU, s:VK.LCONTROL, s:VK.LSHIFT]],
     \]
 
   " Assuming Standard US PC Keyboard layout
@@ -340,7 +340,7 @@ let s:test_extra_key_chars = [
     \ ]
 
 func s:LoopTestKeyArray(arr)
-  " flush out anything in the typeahead buffer
+  " flush out the typeahead buffer
   while getchar(0)
   endwhile
 
@@ -364,13 +364,13 @@ func s:LoopTestKeyArray(arr)
     let key = kcodes[0]
     for key in kcodes
       if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], key) >= 0
-        let modifiers = modifiers + s:vim_MOD_MASK_SHIFT
+        let modifiers = modifiers + s:MOD_MASK_SHIFT
       endif
       if index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], key) >= 0
-        let modifiers = modifiers + s:vim_MOD_MASK_CTRL
+        let modifiers = modifiers + s:MOD_MASK_CTRL
       endif
       if index([s:VK.ALT, s:VK.LALT, s:VK.RALT], key) >= 0
-        let modifiers = modifiers + s:vim_MOD_MASK_ALT
+        let modifiers = modifiers + s:MOD_MASK_ALT
       endif
     endfor
     call SendKeyWithModifiers(key, modifiers)
@@ -387,14 +387,14 @@ func s:LoopTestKeyArray(arr)
     call assert_equal(0, mod_mask, $"key = {kstr}")
   endfor
 
-  " flush out anything in the typeahead buffer
+  " flush out the typeahead buffer
   while getchar(0)
   endwhile
 
 endfunc
 
 " Test MS-Windows key events
-func Test_mswin_key_event()
+func Test_mswin_event_character_keys()
   CheckMSWindows
   new
 
@@ -422,7 +422,7 @@ func Test_mswin_key_event()
       call SendKeyGroup([modkey, kc])
       let ch = getchar(0)
       call assert_equal(kc+128, ch)
-      call SendKeyWithModifiers(kc, s:vim_MOD_MASK_ALT)
+      call SendKeyWithModifiers(kc, s:MOD_MASK_ALT)
       let ch = getchar(0)
       call assert_equal(kc+128, ch)
     endfor
@@ -451,7 +451,7 @@ func Test_mswin_key_event()
       call SendKeyGroup([modkey, kc])
       let ch = getcharstr(0)
       call assert_equal(nr2char(kc), ch)
-      call SendKeyWithModifiers(kc, s:vim_MOD_MASK_SHIFT)
+      call SendKeyWithModifiers(kc, s:MOD_MASK_SHIFT)
       let ch = getcharstr(0)
       call assert_equal(nr2char(kc), ch)
     endfor
@@ -464,7 +464,7 @@ func Test_mswin_key_event()
       call SendKeyGroup([modkey, kc])
       let ch = getcharstr(0)
       call assert_equal(nr2char(kc - 64), ch)
-      call SendKeyWithModifiers(kc, s:vim_MOD_MASK_CTRL)
+      call SendKeyWithModifiers(kc, s:MOD_MASK_CTRL)
       let ch = getcharstr(0)
       call assert_equal(nr2char(kc - 64), ch)
     endfor
@@ -480,109 +480,166 @@ func Test_mswin_key_event()
         call SendKeyGroup([modkey, kc])
         let ch = getchar(0)
         call assert_equal(kc+160, ch)
-        call SendKeyWithModifiers(kc, s:vim_MOD_MASK_ALT)
+        call SendKeyWithModifiers(kc, s:MOD_MASK_ALT)
         let ch = getchar(0)
         call assert_equal(kc+160, ch)
       endfor
     endfor
   endif
 
+endfun
+
   " Test for Function Keys 'F1' to 'F12'
   " VK codes 112(0x70) - 123(0x7B)
   " Also with ALL permutatios of modifiers; Shift, Ctrl & Alt
-  " NOTE: Windows intercepts some of these keys in the GUI
-  if !has("gui_running")
-    for [mod_str, vim_mod_mask, mod_keycodes] in s:vim_key_modifiers
-      for n in range(1, 12)
-        let kstr = $"{mod_str}F{n}"
+func Test_mswin_event_function_keys()
+
+  if has('gui_running')
+    let g:test_is_flaky = 1
+  endif
+
+  " NOTE: Windows intercepts these combinations in the GUI
+  let gui_nogo = ["A-F1", "A-F2", "A-F3", "A-F4", "A-S-F4", "A-C-S-F4",
+            \ "A-F5", "A-F6", "A-F7", "A-F8", "A-C-F8", "A-F9",
+	    \ "A-F10", "A-F11" , "A-C-F11", "A-C-F12"]
+
+  " flush out the typeahead buffer
+  while getchar(0)
+  endwhile
+
+  for [mod_str, vim_mod_mask, mod_keycodes] in s:vim_key_modifiers
+    for n in range(1, 12)
+      let expected_mod_mask = vim_mod_mask
+      let kstr = $"{mod_str}F{n}"
+      if !has('gui_running') || (has('gui_running') && n != 10
+                                             \  && index(gui_nogo, kstr) == -1)
         let keycode = eval('"\<' .. kstr .. '>"')
-        " flush out anything in the typeahead buffer
+        " flush out the typeahead buffer
         while getchar(0)
         endwhile
-        " call SendKeyGroup(mod_keycodes + [111+n])
         call SendKeyWithModifiers(111+n, vim_mod_mask)
         let ch = getcharstr(0)
         let mod_mask = getcharmod()
         call assert_equal(keycode, $"{ch}", $"key = {kstr}")
-        " workaround for the virtual termcap maps changing the character instead
-        " of sending Shift
+        " workaround for the virtual termcap maps changing the character
+        "instead of sending Shift
         for mod_key in mod_keycodes
           if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], mod_key) >= 0
-            let mod_mask = mod_mask + s:vim_MOD_MASK_SHIFT
+            let expected_mod_mask -= s:MOD_MASK_SHIFT
+            break
           endif
         endfor
-        call assert_equal(vim_mod_mask, mod_mask, $"mod = {vim_mod_mask} for key = {kstr}")
-      endfor
+        call assert_equal(expected_mod_mask, mod_mask, $"mod = {expected_mod_mask} for key = {kstr}")
+      endif
     endfor
+  endfor
+endfunc
+
+func ExtractModifiers(mod_keycodes)
+  let has_shift = 0
+  let has_ctrl = 0
+  let has_alt = 0
+  for mod_key in a:mod_keycodes
+    if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], mod_key) >= 0
+      let has_shift = 1
+    endif
+    if index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], mod_key) >= 0
+      let has_ctrl = 1
+    endif
+    if index([s:VK.MENU, s:VK.LMENU, s:VK.RMENU], mod_key) >= 0
+      let has_alt = 1
+    endif
+  endfor
+  return [has_shift, has_ctrl, has_alt]
+endfunc
+
+  " Test for Movement Keys;
+  "    VK_PRIOR 0x21,   VK_NEXT  0x22,
+  "    VK_END   0x23,   VK_HOME  0x24,
+  "    VK_LEFT  0x25,   VK_UP    0x26,
+  "    VK_RIGHT 0x27,   VK_DOWN  0x28
+  " With ALL permutations of modifiers; none, Shift, Ctrl & Alt
+func Test_mswin_event_movement_keys()
+
+  if has('gui_running')
+    let g:test_is_flaky = 1
   endif
 
-  " Test for the various Ctrl and Shift key combinations.
-  let keytests = [
-    \ [[s:VK.SHIFT,    s:VK.PRIOR], "S-Pageup", 2],
-    \ [[s:VK.LSHIFT,   s:VK.PRIOR], "S-Pageup", 2],
-    \ [[s:VK.RSHIFT,   s:VK.PRIOR], "S-Pageup", 2],
-    \ [[s:VK.CONTROL,  s:VK.PRIOR], "C-Pageup", 4],
-    \ [[s:VK.LCONTROL, s:VK.PRIOR], "C-Pageup", 4],
-    \ [[s:VK.RCONTROL, s:VK.PRIOR], "C-Pageup", 4],
-    \ [[s:VK.CONTROL,  s:VK.SHIFT, s:VK.PRIOR], "C-S-Pageup", 6],
-    \ [[s:VK.SHIFT,    s:VK.NEXT], "S-PageDown", 2],
-    \ [[s:VK.LSHIFT,   s:VK.NEXT], "S-PageDown", 2],
-    \ [[s:VK.RSHIFT,   s:VK.NEXT], "S-PageDown", 2],
-    \ [[s:VK.CONTROL,  s:VK.NEXT], "C-PageDown", 4],
-    \ [[s:VK.LCONTROL, s:VK.NEXT], "C-PageDown", 4],
-    \ [[s:VK.RCONTROL, s:VK.NEXT], "C-PageDown", 4],
-    \ [[s:VK.CONTROL,  s:VK.SHIFT, s:VK.NEXT], "C-S-PageDown", 6],
-    \ [[s:VK.SHIFT,    s:VK.END], "S-End", 0],
-    \ [[s:VK.CONTROL,  s:VK.END], "C-End", 0],
-    \ [[s:VK.CONTROL,  s:VK.SHIFT, s:VK.END], "C-S-End", 4],
-    \ [[s:VK.SHIFT,    s:VK.HOME], "S-Home", 0],
-    \ [[s:VK.CONTROL,  s:VK.HOME], "C-Home", 0],
-    \ [[s:VK.CONTROL,  s:VK.SHIFT, s:VK.HOME], "C-S-Home", 4],
-    \ [[s:VK.SHIFT,    s:VK.LEFT], "S-Left", 0],
-    \ [[s:VK.CONTROL,  s:VK.LEFT], "C-Left", 0],
-    \ [[s:VK.CONTROL,  s:VK.SHIFT, s:VK.LEFT], "C-S-Left", 4],
-    \ [[s:VK.SHIFT,    s:VK.UP], "S-Up", 0],
-    \ [[s:VK.CONTROL,  s:VK.UP], "C-Up", 4],
-    \ [[s:VK.CONTROL,  s:VK.SHIFT, s:VK.UP], "C-S-Up", 4],
-    \ [[s:VK.SHIFT,    s:VK.RIGHT], "S-Right", 0],
-    \ [[s:VK.CONTROL,  s:VK.RIGHT], "C-Right", 0],
-    \ [[s:VK.CONTROL,  s:VK.SHIFT, s:VK.RIGHT], "C-S-Right", 4],
-    \ [[s:VK.SHIFT,    s:VK.DOWN], "S-Down", 0],
-    \ [[s:VK.CONTROL,  s:VK.DOWN], "C-Down", 4],
-    \ [[s:VK.CONTROL,  s:VK.SHIFT, s:VK.DOWN], "C-S-Down", 4],
-    \ [[s:VK.CONTROL,  s:VK.KEY_0], "C-0", 4],
-    \ [[s:VK.CONTROL,  s:VK.KEY_1], "C-1", 4],
-    \ [[s:VK.CONTROL,  s:VK.KEY_2], "C-@", 0],
-    \ [[s:VK.CONTROL,  s:VK.KEY_3], "C-3", 4],
-    \ [[s:VK.CONTROL,  s:VK.KEY_4], "C-4", 4],
-    \ [[s:VK.CONTROL,  s:VK.KEY_5], "C-5", 4],
-    \ [[s:VK.CONTROL,  s:VK.KEY_6], "C-^", 0],
-    \ [[s:VK.CONTROL,  s:VK.KEY_7], "C-7", 4],
-    \ [[s:VK.CONTROL,  s:VK.KEY_8], "C-8", 4],
-    \ [[s:VK.CONTROL,  s:VK.KEY_9], "C-9", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD0], "C-0", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD1], "C-1", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD2], "C-2", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD3], "C-3", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD4], "C-4", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD5], "C-5", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD6], "C-6", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD7], "C-7", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD8], "C-8", 4],
-    \ [[s:VK.CONTROL,  s:VK.NUMPAD9], "C-9", 4],
-    \ [[s:VK.CONTROL,  s:VK.MULTIPLY], "C-*", 4],
-    \ [[s:VK.CONTROL,  s:VK.ADD], "C-+", 4],
-    \ [[s:VK.CONTROL,  s:VK.SUBTRACT], "C--", 4],
-    \ [[s:VK.CONTROL,  s:VK.OEM_MINUS], "C-_", 0]
+  let movement_keys = [
+    \ [s:VK.PRIOR, "PageUp"],
+    \ [s:VK.NEXT,  "PageDown"],
+    \ [s:VK.END,   "End"],
+    \ [s:VK.HOME,  "Home"],
+    \ [s:VK.LEFT,  "Left"],
+    \ [s:VK.UP,    "Up"],
+    \ [s:VK.RIGHT, "Right"],
+    \ [s:VK.DOWN,  "Down"],
     \ ]
 
-  for [kcodes, kstr, kmod] in keytests
-    call SendKeyGroup(kcodes)
-    let ch = getcharstr(0)
-    let mod = getcharmod()
-    let keycode = eval('"\<' .. kstr .. '>"')
-    call assert_equal(keycode, ch, $"key = {kstr}")
-    call assert_equal(kmod, mod, $"mod = {kmod} key = {kstr}")
+  " flush out the typeahead buffer
+  while getchar(0)
+  endwhile
+
+  for [mod_str, vim_mod_mask, mod_keycodes] in s:vim_key_modifiers
+    for [kcode, kname] in movement_keys
+      let exp_mod_mask = vim_mod_mask
+      let kstr = $"{mod_str}{kname}"
+      let chstr_eval = eval('"\<' .. kstr .. '>"')
+
+      " flush out the typeahead buffer
+      while getchar(0)
+      endwhile
+      execute 'call feedkeys("\<' .. kstr .. '>")'
+      let chstr_fk = getcharstr(0)
+      call assert_equal(chstr_eval, chstr_fk, $"feedkeys = <{kstr}>")
+
+      " flush out the typeahead buffer
+      while getchar(0)
+      endwhile
+      call SendKey(kcode)
+      let chstr_alone = getcharstr(0)
+      let chstr_alone_end = chstr_alone[len(chstr_alone)-2:len(chstr_alone)-1]
+
+      " flush out the typeahead buffer
+      while getchar(0)
+      endwhile
+      call SendKeyGroup(mod_keycodes + [kcode])
+      let chstr_mswin = getcharstr(0)
+      let chstr_mswin_end = chstr_mswin[len(chstr_mswin)-2:len(chstr_mswin)-1]
+      let mod_mask = getcharmod()
+
+      " The virtual termcap maps may** change the character and either;
+      " - remove the Shift modifier, or
+      " - remove the Ctrl modifier if the Shift modifier was not removed.
+      let [has_shift, has_ctrl, has_alt] = ExtractModifiers(mod_keycodes)
+      if chstr_alone_end != chstr_mswin_end
+        if has_shift != 0
+          let exp_mod_mask -= s:MOD_MASK_SHIFT
+        elseif has_ctrl != 0
+	  let exp_mod_mask -= s:MOD_MASK_CTRL
+        endif
+      endif
+      " **Note: The appveyor Windows GUI test environments, from VS2017 on,
+      " consistently intercepts the Shift modifier WITHOUT changing the
+      " MOVEMENT character.  This issue does not happen in any github actions
+      " CI Windows test environments.  Attempted to reproduce this manually
+      " on Windows versions;  7, 8.1, 10, 11, Server 2019 and Server 2022, but
+      " the issue did not occur on any of those environments.
+      " Below is a workaround for the issue.
+      if has('gui_running') && has_shift != 0
+        if exp_mod_mask != mod_mask && chstr_eval != chstr_mswin
+          let kstr_sub = substitute(kstr, "S-", "", "")
+          let chstr_eval = eval('"\<' .. kstr_sub .. '>"')
+          if exp_mod_mask - s:MOD_MASK_SHIFT == mod_mask
+            let exp_mod_mask -= s:MOD_MASK_SHIFT
+          elseif has_ctrl != 0 && exp_mod_mask - s:MOD_MASK_CTRL == mod_mask
+            let exp_mod_mask -= s:MOD_MASK_CTRL
+          endif
+        endif
+      endif
+      call assert_equal(chstr_eval, chstr_mswin, $"key = {kstr}")
+      call assert_equal(exp_mod_mask, mod_mask, $"mod_mask for key = {kstr}")
+    endfor
   endfor
 
   bw!
@@ -628,7 +685,7 @@ func Test_QWERTY_Ctrl_minus()
 endfunc
 
 "  Test MS-Windows mouse events
-func Test_mswin_mouse_event()
+func Test_mswin_event_mouse()
   CheckMSWindows
   new
 
@@ -940,7 +997,7 @@ func Test_mswin_event_error_handling()
 
   call assert_fails("sandbox call test_mswin_event('key', {'event': 'keydown', 'keycode': 61 })", 'E48:')
 
-  " flush out anything in the typeahead buffer
+  " flush out the typeahead buffer
   while getchar(0)
   endwhile
 endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1169,
+/**/
     1168,
 /**/
     1167,