patch 9.0.1084: code handling low level MS-Windows events cannot be tested
Problem: Code handling low level MS-Windows events cannot be tested.
Solution: Add test_mswin_event() and tests using it. (Christopher Plewright,
closes #11622)
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 886bb08..fdca9f4 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -210,6 +210,7 @@
test_modeless \
test_modeline \
test_move \
+ test_mswin_event \
test_mzscheme \
test_nested_function \
test_netbeans \
@@ -454,6 +455,7 @@
test_mksession.res \
test_modeless.res \
test_modeline.res \
+ test_mswin_event.res \
test_mzscheme.res \
test_nested_function.res \
test_netbeans.res \
diff --git a/src/testdir/mouse.vim b/src/testdir/mouse.vim
index d59ad0e..e2979b7 100644
--- a/src/testdir/mouse.vim
+++ b/src/testdir/mouse.vim
@@ -20,6 +20,27 @@
let g:Ttymouse_netterm = []
endif
+" Vim Mouse Codes.
+" Used by the GUI and by MS-Windows Consoles.
+" Keep these in sync with vim.h
+let s:MOUSE_CODE = {
+ \ 'BTN_LEFT' : 0x00,
+ \ 'BTN_MIDDLE' : 0x01,
+ \ 'BTN_RIGHT' : 0x02,
+ \ 'BTN_RELEASE' : 0x03,
+ \ 'BTN_X1' : 0x300,
+ \ 'BTN_X2' : 0x400,
+ \ 'SCRL_DOWN' : 0x100,
+ \ 'SCRL_UP' : 0x200,
+ \ 'SCRL_LEFT' : 0x500,
+ \ 'SCRL_RIGHT' : 0x600,
+ \ 'MOVE' : 0x700,
+ \ 'MOD_SHIFT' : 0x04,
+ \ 'MOD_ALT' : 0x08,
+ \ 'MOD_CTRL' : 0x10,
+ \ }
+
+
" Helper function to emit a terminal escape code.
func TerminalEscapeCode(code, row, col, m)
if &ttymouse ==# 'xterm2'
@@ -47,6 +68,31 @@
return printf("\<Esc>}%d,%d\r", a:row, a:col)
endfunc
+" Send low level mouse event to MS-Windows consoles or GUI
+func MSWinMouseEvent(button, row, col, move, multiclick, modifiers)
+ let args = { }
+ let args.button = a:button
+ " Scroll directions are inverted in the GUI, no idea why.
+ if has('gui_running')
+ if a:button == s:MOUSE_CODE.SCRL_UP
+ let args.button = s:MOUSE_CODE.SCRL_DOWN
+ elseif a:button == s:MOUSE_CODE.SCRL_DOWN
+ let args.button = s:MOUSE_CODE.SCRL_UP
+ elseif a:button == s:MOUSE_CODE.SCRL_LEFT
+ let args.button = s:MOUSE_CODE.SCRL_RIGHT
+ elseif a:button == s:MOUSE_CODE.SCRL_RIGHT
+ let args.button = s:MOUSE_CODE.SCRL_LEFT
+ endif
+ endif
+ let args.row = a:row
+ let args.col = a:col
+ let args.move = a:move
+ let args.multiclick = a:multiclick
+ let args.modifiers = a:modifiers
+ call test_mswin_event("mouse", args)
+ unlet args
+endfunc
+
func MouseLeftClickCode(row, col)
if &ttymouse ==# 'dec'
return DecEscapeCode(2, 4, a:row, a:col)
@@ -58,7 +104,11 @@
endfunc
func MouseLeftClick(row, col)
- call feedkeys(MouseLeftClickCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_LEFT, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseLeftClickCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseMiddleClickCode(row, col)
@@ -70,7 +120,11 @@
endfunc
func MouseMiddleClick(row, col)
- call feedkeys(MouseMiddleClickCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_MIDDLE, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseMiddleClickCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseRightClickCode(row, col)
@@ -82,7 +136,11 @@
endfunc
func MouseRightClick(row, col)
- call feedkeys(MouseRightClickCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_RIGHT, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseRightClickCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseCtrlLeftClickCode(row, col)
@@ -91,7 +149,12 @@
endfunc
func MouseCtrlLeftClick(row, col)
- call feedkeys(MouseCtrlLeftClickCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_LEFT, a:row, a:col, 0, 0,
+ \ s:MOUSE_CODE.MOD_CTRL)
+ else
+ call feedkeys(MouseCtrlLeftClickCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseCtrlRightClickCode(row, col)
@@ -100,7 +163,12 @@
endfunc
func MouseCtrlRightClick(row, col)
- call feedkeys(MouseCtrlRightClickCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_RIGHT, a:row, a:col, 0, 0,
+ \ s:MOUSE_CODE.MOD_CTRL)
+ else
+ call feedkeys(MouseCtrlRightClickCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseAltLeftClickCode(row, col)
@@ -109,7 +177,12 @@
endfunc
func MouseAltLeftClick(row, col)
- call feedkeys(MouseAltLeftClickCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_LEFT, a:row, a:col, 0, 0,
+ \ s:MOUSE_CODE.MOD_ALT)
+ else
+ call feedkeys(MouseAltLeftClickCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseAltRightClickCode(row, col)
@@ -118,7 +191,12 @@
endfunc
func MouseAltRightClick(row, col)
- call feedkeys(MouseAltRightClickCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_RIGHT, a:row, a:col, 0, 0,
+ \ s:MOUSE_CODE.MOD_ALT)
+ else
+ call feedkeys(MouseAltRightClickCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseLeftReleaseCode(row, col)
@@ -132,7 +210,11 @@
endfunc
func MouseLeftRelease(row, col)
- call feedkeys(MouseLeftReleaseCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_RELEASE, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseLeftReleaseCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseMiddleReleaseCode(row, col)
@@ -144,7 +226,11 @@
endfunc
func MouseMiddleRelease(row, col)
- call feedkeys(MouseMiddleReleaseCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_RELEASE, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseMiddleReleaseCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseRightReleaseCode(row, col)
@@ -156,7 +242,11 @@
endfunc
func MouseRightRelease(row, col)
- call feedkeys(MouseRightReleaseCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_RELEASE, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseRightReleaseCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseLeftDragCode(row, col)
@@ -168,7 +258,11 @@
endfunc
func MouseLeftDrag(row, col)
- call feedkeys(MouseLeftDragCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.BTN_LEFT, a:row, a:col, 1, 0, 0)
+ else
+ call feedkeys(MouseLeftDragCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseWheelUpCode(row, col)
@@ -176,7 +270,11 @@
endfunc
func MouseWheelUp(row, col)
- call feedkeys(MouseWheelUpCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.SCRL_UP, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseWheelUpCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseWheelDownCode(row, col)
@@ -184,7 +282,11 @@
endfunc
func MouseWheelDown(row, col)
- call feedkeys(MouseWheelDownCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.SCRL_DOWN, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseWheelDownCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseWheelLeftCode(row, col)
@@ -192,7 +294,11 @@
endfunc
func MouseWheelLeft(row, col)
- call feedkeys(MouseWheelLeftCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.SCRL_LEFT, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseWheelLeftCode(a:row, a:col), 'Lx!')
+ endif
endfunc
func MouseWheelRightCode(row, col)
@@ -200,7 +306,67 @@
endfunc
func MouseWheelRight(row, col)
- call feedkeys(MouseWheelRightCode(a:row, a:col), 'Lx!')
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.SCRL_RIGHT, a:row, a:col, 0, 0, 0)
+ else
+ call feedkeys(MouseWheelRightCode(a:row, a:col), 'Lx!')
+ endif
+endfunc
+
+func MouseShiftWheelUpCode(row, col)
+ " todo feed shift mod.
+ return TerminalEscapeCode(0x40, a:row, a:col, 'M')
+endfunc
+
+func MouseShiftWheelUp(row, col)
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.SCRL_UP, a:row, a:col, 0, 0,
+ \ s:MOUSE_CODE.MOD_SHIFT)
+ else
+ call feedkeys(MouseShiftWheelUpCode(a:row, a:col), 'Lx!')
+ endif
+endfunc
+
+func MouseShiftWheelDownCode(row, col)
+ " todo feed shift mod.
+ return TerminalEscapeCode(0x41, a:row, a:col, 'M')
+endfunc
+
+func MouseShiftWheelDown(row, col)
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.SCRL_DOWN, a:row, a:col, 0, 0,
+ \ s:MOUSE_CODE.MOD_SHIFT)
+ else
+ call feedkeys(MouseShiftWheelDownCode(a:row, a:col), 'Lx!')
+ endif
+endfunc
+
+func MouseShiftWheelLeftCode(row, col)
+ " todo feed shift mod.
+ return TerminalEscapeCode(0x42, a:row, a:col, 'M')
+endfunc
+
+func MouseShiftWheelLeft(row, col)
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.SCRL_LEFT, a:row, a:col, 0, 0,
+ \ s:MOUSE_CODE.MOD_SHIFT)
+ else
+ call feedkeys(MouseShiftWheelLeftCode(a:row, a:col), 'Lx!')
+ endif
+endfunc
+
+func MouseShiftWheelRightCode(row, col)
+ " todo feed shift mod.
+ return TerminalEscapeCode(0x43, a:row, a:col, 'M')
+endfunc
+
+func MouseShiftWheelRight(row, col)
+ if has('win32')
+ call MSWinMouseEvent(s:MOUSE_CODE.SCRL_RIGHT, a:row, a:col, 0, 0,
+ \ s:MOUSE_CODE.MOD_SHIFT)
+ else
+ call feedkeys(MouseShiftWheelRightCode(a:row, a:col), 'Lx!')
+ endif
endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim
index 3c7cfb9..0c1e0a5 100644
--- a/src/testdir/test_gui.vim
+++ b/src/testdir/test_gui.vim
@@ -1281,7 +1281,7 @@
let g:eventlist = g:eventlist[1 : ]
endif
- call assert_equal([#{row: 4, col: 31}, #{row: 11, col: 31}], g:eventlist)
+ call assert_equal([#{row: 3, col: 30}, #{row: 10, col: 30}], g:eventlist)
" wiggle the mouse around within a screen cell, shouldn't trigger events
call extend(args, #{cell: v:false})
@@ -1638,10 +1638,10 @@
" Test for sending low level key presses
func SendKeys(keylist)
for k in a:keylist
- call test_gui_event("sendevent", #{event: "keydown", keycode: k})
+ call test_gui_event("key", #{event: "keydown", keycode: k})
endfor
for k in reverse(a:keylist)
- call test_gui_event("sendevent", #{event: "keyup", keycode: k})
+ call test_gui_event("key", #{event: "keyup", keycode: k})
endfor
endfunc
diff --git a/src/testdir/test_mswin_event.vim b/src/testdir/test_mswin_event.vim
new file mode 100644
index 0000000..4e392a2
--- /dev/null
+++ b/src/testdir/test_mswin_event.vim
@@ -0,0 +1,651 @@
+" Test MS-Windows console event handling.
+
+source check.vim
+CheckMSWindows
+" The mswin events should also work in gui
+
+source mouse.vim
+
+" Helper function for sending a sequence of low level key presses
+" The modifer key(s) can be included as normal key presses in the sequence
+func SendKeys(keylist)
+ for k in a:keylist
+ call test_mswin_event("key", #{event: "keydown", keycode: k})
+ endfor
+ for k in reverse(copy(a:keylist))
+ call test_mswin_event("key", #{event: "keyup", keycode: k})
+ endfor
+endfunc
+
+" Send an individual key press
+" the modifers for the key press can be specified in the modifiers arg.
+func SendKey(key, modifiers)
+ let args = { }
+ let args.keycode = a:key
+ let args.modifiers = a:modifiers
+ let args.event = "keydown"
+ call test_mswin_event("key", args)
+ let args.event = "keyup"
+ call test_mswin_event("key", args)
+ unlet args
+endfunc
+
+" Test MS-Windows console key events
+func Test_mswin_key_event()
+ CheckMSWindows
+ new
+
+ " flush out any garbage left in the buffer
+ while getchar(0)
+ endwhile
+
+ let VK = #{
+ \ SPACE : 0x20,
+ \ SHIFT : 0x10,
+ \ LSHIFT : 0xA0,
+ \ RSHIFT : 0xA1,
+ \ CONTROL : 0x11,
+ \ LCONTROL : 0xA2,
+ \ RCONTROL : 0xA3,
+ \ MENU : 0x12,
+ \ ALT : 0x12,
+ \ LMENU : 0xA4,
+ \ LALT : 0xA4,
+ \ RMENU : 0xA5,
+ \ RALT : 0xA5,
+ \ OEM_1 : 0xBA,
+ \ OEM_2 : 0xBF,
+ \ OEM_3 : 0xC0,
+ \ OEM_4 : 0xDB,
+ \ OEM_5 : 0xDC,
+ \ OEM_6 : 0xDD,
+ \ OEM_7 : 0xDE,
+ \ OEM_PLUS : 0xBB,
+ \ OEM_COMMA : 0xBC,
+ \ OEM_MINUS : 0xBD,
+ \ OEM_PERIOD : 0xBE,
+ \ PRIOR : 0x21,
+ \ NEXT : 0x22,
+ \ END : 0x23,
+ \ HOME : 0x24,
+ \ LEFT : 0x25,
+ \ UP : 0x26,
+ \ RIGHT : 0x27,
+ \ DOWN : 0x28,
+ \ KEY_0 : 0x30,
+ \ KEY_1 : 0x31,
+ \ KEY_2 : 0x32,
+ \ KEY_3 : 0x33,
+ \ KEY_4 : 0x34,
+ \ KEY_5 : 0x35,
+ \ KEY_6 : 0x36,
+ \ KEY_7 : 0x37,
+ \ KEY_8 : 0x38,
+ \ KEY_9 : 0x39,
+ \ NUMPAD0 : 0x60,
+ \ NUMPAD1 : 0x61,
+ \ NUMPAD2 : 0x62,
+ \ NUMPAD3 : 0x63,
+ \ NUMPAD4 : 0x64,
+ \ NUMPAD5 : 0x65,
+ \ NUMPAD6 : 0x66,
+ \ NUMPAD7 : 0x67,
+ \ NUMPAD8 : 0x68,
+ \ NUMPAD9 : 0x69,
+ \ MULTIPLY : 0x6A,
+ \ ADD : 0x6B,
+ \ SUBTRACT : 0x6D,
+ \ F1 : 0x70,
+ \ F2 : 0x71,
+ \ F3 : 0x72,
+ \ F4 : 0x73,
+ \ F5 : 0x74,
+ \ F6 : 0x75,
+ \ F7 : 0x76,
+ \ F8 : 0x77,
+ \ F9 : 0x78,
+ \ F10 : 0x79,
+ \ F11 : 0x7A,
+ \ F12 : 0x7B,
+ \ KEY_A : 0x41,
+ \ KEY_B : 0x42,
+ \ KEY_C : 0x43,
+ \ KEY_D : 0x44,
+ \ KEY_E : 0x45,
+ \ KEY_F : 0x46,
+ \ KEY_G : 0x47,
+ \ KEY_H : 0x48,
+ \ KEY_I : 0x49,
+ \ KEY_J : 0x4A,
+ \ KEY_K : 0x4B,
+ \ KEY_L : 0x4C,
+ \ KEY_M : 0x4D,
+ \ KEY_N : 0x4E,
+ \ KEY_O : 0x4F,
+ \ KEY_P : 0x50,
+ \ KEY_Q : 0x51,
+ \ KEY_R : 0x52,
+ \ KEY_S : 0x53,
+ \ KEY_T : 0x54,
+ \ KEY_U : 0x55,
+ \ KEY_V : 0x56,
+ \ KEY_W : 0x57,
+ \ KEY_X : 0x58,
+ \ KEY_Y : 0x59,
+ \ KEY_Z : 0x5A
+ \ }
+
+ let vim_MOD_MASK_SHIFT = 0x02
+ let vim_MOD_MASK_CTRL = 0x04
+ let vim_MOD_MASK_ALT = 0x08
+
+ let vim_key_modifiers = [
+ \ ["", 0, []],
+ \ ["S-", 2, [VK.SHIFT]],
+ \ ["C-", 4, [VK.CONTROL]],
+ \ ["C-S-", 6, [VK.CONTROL, VK.SHIFT]],
+ \ ["A-", 8, [VK.MENU]],
+ \ ["A-S-", 10, [VK.MENU, VK.SHIFT]],
+ \ ["A-C-", 12, [VK.MENU, VK.CONTROL]],
+ \ ["A-C-S-", 14, [VK.MENU, VK.CONTROL, VK.SHIFT]],
+ \]
+
+ " Some punctuation characters
+ " Assuming Standard US PC Keyboard layout
+ let test_punctuation_keys = [
+ \ [[VK.SPACE], ' '],
+ \ [[VK.OEM_1], ';'],
+ \ [[VK.OEM_2], '/'],
+ \ [[VK.OEM_3], '`'],
+ \ [[VK.OEM_4], '['],
+ \ [[VK.OEM_5], '\'],
+ \ [[VK.OEM_6], ']'],
+ \ [[VK.OEM_7], ''''],
+ \ [[VK.OEM_PLUS], '='],
+ \ [[VK.OEM_COMMA], ','],
+ \ [[VK.OEM_MINUS], '-'],
+ \ [[VK.OEM_PERIOD], '.'],
+ \ [[VK.SHIFT, VK.OEM_1], ':'],
+ \ [[VK.SHIFT, VK.OEM_2], '?'],
+ \ [[VK.SHIFT, VK.OEM_3], '~'],
+ \ [[VK.SHIFT, VK.OEM_4], '{'],
+ \ [[VK.SHIFT, VK.OEM_5], '|'],
+ \ [[VK.SHIFT, VK.OEM_6], '}'],
+ \ [[VK.SHIFT, VK.OEM_7], '"'],
+ \ [[VK.SHIFT, VK.OEM_PLUS], '+'],
+ \ [[VK.SHIFT, VK.OEM_COMMA], '<'],
+ \ [[VK.SHIFT, VK.OEM_MINUS], '_'],
+ \ [[VK.SHIFT, VK.OEM_PERIOD], '>'],
+ \ [[VK.SHIFT, VK.KEY_1], '!'],
+ \ [[VK.SHIFT, VK.KEY_2], '@'],
+ \ [[VK.SHIFT, VK.KEY_3], '#'],
+ \ [[VK.SHIFT, VK.KEY_4], '$'],
+ \ [[VK.SHIFT, VK.KEY_5], '%'],
+ \ [[VK.SHIFT, VK.KEY_6], '^'],
+ \ [[VK.SHIFT, VK.KEY_7], '&'],
+ \ [[VK.SHIFT, VK.KEY_8], '*'],
+ \ [[VK.SHIFT, VK.KEY_9], '('],
+ \ [[VK.SHIFT, VK.KEY_0], ')'],
+ \ [[VK.LSHIFT, VK.KEY_9], '('],
+ \ [[VK.RSHIFT, VK.KEY_0], ')']
+ \ ]
+
+ for [kcodes, kstr] in test_punctuation_keys
+ call SendKeys(kcodes)
+ let ch = getcharstr(0)
+ call assert_equal($"{kstr}", $"{ch}")
+ let mod_mask = getcharmod()
+ " the mod_mask is zero when no modifiers are used
+ " and when the virtual termcap maps shift the character
+ call assert_equal(0, mod_mask, $"key = {kstr}")
+ endfor
+
+ " flush out any garbage left in the buffer
+ while getchar(0)
+ endwhile
+
+ for [kcodes, kstr] in test_punctuation_keys
+ let modifiers = 0
+ let key = kcodes[0]
+
+ for key in kcodes
+ if index([VK.SHIFT, VK.LSHIFT, VK.RSHIFT], key) >= 0
+ let modifiers = modifiers + vim_MOD_MASK_SHIFT
+ endif
+ if index([VK.CONTROL, VK.LCONTROL, VK.RCONTROL], key) >= 0
+ let modifiers = modifiers + vim_MOD_MASK_CTRL
+ endif
+ if index([VK.ALT, VK.LALT, VK.RALT], key) >= 0
+ let modifiers = modifiers + vim_MOD_MASK_ALT
+ endif
+ endfor
+
+ call SendKey(key, modifiers)
+ let ch = getcharstr(0)
+ call assert_equal($"{kstr}", $"{ch}")
+ let mod_mask = getcharmod()
+ " workaround for the virtual termcap maps changing the character instead
+ " of sending Shift
+ if index([VK.SHIFT, VK.LSHIFT, VK.RSHIFT], kcodes[0]) >= 0
+ let modifiers = modifiers - vim_MOD_MASK_SHIFT
+ endif
+ call assert_equal(modifiers, mod_mask, $"key = {kstr}")
+ endfor
+
+ " flush out any garbage left in the buffer
+ while getchar(0)
+ endwhile
+
+" Test keyboard codes for digits
+" (0x30 - 0x39) : VK_0 - VK_9 are the same as ASCII '0' - '9'
+ for kc in range(48, 57)
+ call SendKeys([kc])
+ let ch = getcharstr(0)
+ call assert_equal(nr2char(kc), ch)
+ call SendKey(kc, 0)
+ let ch = getcharstr(0)
+ call assert_equal(nr2char(kc), ch)
+ endfor
+
+" Test keyboard codes for Alt-0 to Alt-9
+" Expect +128 from the digit char codes
+ for modkey in [VK.ALT, VK.LALT, VK.RALT]
+ for kc in range(48, 57)
+ call SendKeys([modkey, kc])
+ let ch = getchar(0)
+ call assert_equal(kc+128, ch)
+ call SendKey(kc, vim_MOD_MASK_ALT)
+ let ch = getchar(0)
+ call assert_equal(kc+128, ch)
+ endfor
+ endfor
+
+" Test for lowercase 'a' to 'z', VK codes 65(0x41) - 90(0x5A)
+" Note: VK_A-VK_Z virtual key codes coincide with uppercase ASCII codes A-Z.
+" eg VK_A is 65, and the ASCII character code for uppercase 'A' is also 65.
+" Caution: these are interpreted as lowercase when Shift is NOT pressed.
+" eg, sending VK_A (65) 'A' Key code without shift modifier, will produce ASCII
+" char 'a' (91) as the output. The ASCII codes for the lowercase letters are
+" numbered 32 higher than their uppercase versions.
+ for kc in range(65, 90)
+ call SendKeys([kc])
+ let ch = getcharstr(0)
+ call assert_equal(nr2char(kc + 32), ch)
+ call SendKey(kc, 0)
+ let ch = getcharstr(0)
+ call assert_equal(nr2char(kc + 32), ch)
+ endfor
+
+" Test for Uppercase 'A' - 'Z' keys
+" ie. with VK_SHIFT, expect the keycode = character code.
+ for kc in range(65, 90)
+ call SendKeys([VK.SHIFT, kc])
+ let ch = getcharstr(0)
+ call assert_equal(nr2char(kc), ch)
+ call SendKey(kc, vim_MOD_MASK_SHIFT)
+ let ch = getcharstr(0)
+ call assert_equal(nr2char(kc), ch)
+ endfor
+
+ " Test for <Ctrl-A> to <Ctrl-Z> keys
+ " Same as for lowercase, except with Ctrl Key
+ " Expect the unicode characters 0x01 to 0x1A
+ for modkey in [VK.CONTROL, VK.LCONTROL, VK.RCONTROL]
+ for kc in range(65, 90)
+ call SendKeys([modkey, kc])
+ let ch = getcharstr(0)
+ call assert_equal(nr2char(kc - 64), ch)
+ call SendKey(kc, vim_MOD_MASK_CTRL)
+ let ch = getcharstr(0)
+ call assert_equal(nr2char(kc - 64), ch)
+ endfor
+ endfor
+
+ if !has("gui_running")
+ " Test for <Alt-A> to <Alt-Z> keys
+ " Expect the unicode characters 0xE1 to 0xFA
+ " ie. 160 higher than the lowercase equivalent
+ for kc in range(65, 90)
+ call SendKeys([VK.LMENU, kc])
+ let ch = getchar(0)
+ call assert_equal(kc+160, ch)
+ call SendKey(kc, vim_MOD_MASK_ALT)
+ let ch = getchar(0)
+ call assert_equal(kc+160, ch)
+ endfor
+ endif
+
+ if !has("gui_running")
+ " Test for Function Keys 'F1' to 'F12'
+ for n in range(1, 12)
+ let kstr = $"F{n}"
+ let keycode = eval('"\<' .. kstr .. '>"')
+ call SendKeys([111+n])
+ let ch = getcharstr(0)
+ call assert_equal(keycode, $"{ch}", $"key = <{kstr}>")
+ endfor
+ endif
+
+ bw!
+endfunc
+
+" Test MS-Windows console mouse events
+func Test_mswin_mouse_event()
+ CheckMSWindows
+ new
+
+ set mousemodel=extend
+ call test_override('no_query_mouse', 1)
+ call WaitForResponses()
+
+ let msg = ''
+
+ call setline(1, ['one two three', 'four five six'])
+
+ " Test mouse movement
+ " by default, no mouse move events are generated
+ " this setting enables it to generate move events
+ set mousemev
+
+ if !has('gui_running')
+ " console version needs a button pressed,
+ " otherwise it ignores mouse movements.
+ call MouseLeftClick(2, 3)
+ endif
+ call MSWinMouseEvent(0x700, 8, 13, 0, 0, 0)
+ if has('gui_running')
+ call feedkeys("\<Esc>", 'Lx!')
+ endif
+ let pos = getmousepos()
+ call assert_equal(8, pos.screenrow)
+ call assert_equal(13, pos.screencol)
+
+ if !has('gui_running')
+ call MouseLeftClick(2, 3)
+ call MSWinMouseEvent(0x700, 6, 4, 1, 0, 0)
+ let pos = getmousepos()
+ call assert_equal(6, pos.screenrow)
+ call assert_equal(4, pos.screencol)
+ endif
+
+ " test cells vs pixels
+ if has('gui_running')
+ let args = { }
+ let args.row = 9
+ let args.col = 7
+ let args.move = 1
+ let args.cell = 1
+ call test_mswin_event("mouse", args)
+ call feedkeys("\<Esc>", 'Lx!')
+ let pos = getmousepos()
+ call assert_equal(9, pos.screenrow)
+ call assert_equal(7, pos.screencol)
+
+ let args.cell = 0
+ call test_mswin_event("mouse", args)
+ call feedkeys("\<Esc>", 'Lx!')
+ let pos = getmousepos()
+ call assert_equal(1, pos.screenrow)
+ call assert_equal(1, pos.screencol)
+
+ unlet args
+ endif
+
+ " finish testing mouse movement
+ set mousemev&
+
+ " place the cursor using left click and release in normal mode
+ call MouseLeftClick(2, 4)
+ call MouseLeftRelease(2, 4)
+ if has('gui_running')
+ call feedkeys("\<Esc>", 'Lx!')
+ endif
+ call assert_equal([0, 2, 4, 0], getpos('.'))
+
+ " select and yank a word
+ let @" = ''
+ call MouseLeftClick(1, 9)
+ let args = #{button: 0, row: 1, col: 9, multiclick: 1, modifiers: 0}
+ call test_mswin_event('mouse', args)
+ call MouseLeftRelease(1, 9)
+ call feedkeys("y", 'Lx!')
+ call assert_equal('three', @")
+
+ " create visual selection using right click
+ let @" = ''
+
+ call MouseLeftClick(2 ,6)
+ call MouseLeftRelease(2, 6)
+ call MouseRightClick(2, 13)
+ call MouseRightRelease(2, 13)
+ call feedkeys("y", 'Lx!')
+ call assert_equal('five six', @")
+
+ " paste using middle mouse button
+ let @* = 'abc '
+ call feedkeys('""', 'Lx!')
+ call MouseMiddleClick(1, 9)
+ call MouseMiddleRelease(1, 9)
+ if has('gui_running')
+ call feedkeys("\<Esc>", 'Lx!')
+ endif
+ call assert_equal(['one two abc three', 'four five six'], getline(1, '$'))
+
+ " test mouse scrolling (aka touchpad scrolling.)
+ %d _
+ set scrolloff=0
+ call setline(1, range(1, 100))
+
+ " Scroll Down
+ call MouseWheelDown(2, 1)
+ call MouseWheelDown(2, 1)
+ call MouseWheelDown(2, 1)
+ call feedkeys("H", 'Lx!')
+ call assert_equal(10, line('.'))
+
+ " Scroll Up
+ call MouseWheelUp(2, 1)
+ call MouseWheelUp(2, 1)
+ call feedkeys("H", 'Lx!')
+ call assert_equal(4, line('.'))
+
+ " Shift Scroll Down
+ call MouseShiftWheelDown(2, 1)
+ call feedkeys("H", 'Lx!')
+ " should scroll from where it is (4) + visible buffer height - cmdheight
+ let shift_scroll_height = line('w$') - line('w0') - &cmdheight
+ call assert_equal(4 + shift_scroll_height, line('.'))
+
+ " Shift Scroll Up
+ call MouseShiftWheelUp(2, 1)
+ call feedkeys("H", 'Lx!')
+ call assert_equal(4, line('.'))
+
+ if !has('gui_running')
+ " Shift Scroll Down (using MOD)
+ call MSWinMouseEvent(0x100, 2, 1, 0, 0, 0x04)
+ call feedkeys("H", 'Lx!')
+ " should scroll from where it is (4) + visible buffer height - cmdheight
+ let shift_scroll_height = line('w$') - line('w0') - &cmdheight
+ call assert_equal(4 + shift_scroll_height, line('.'))
+
+ " Shift Scroll Up (using MOD)
+ call MSWinMouseEvent(0x200, 2, 1, 0, 0, 0x04)
+ call feedkeys("H", 'Lx!')
+ call assert_equal(4, line('.'))
+ endif
+
+ set scrolloff&
+
+ %d _
+ set nowrap
+ " make the buffer 500 wide.
+ call setline(1, range(10)->join('')->repeat(50))
+ " Scroll Right
+ call MouseWheelRight(1, 5)
+ call MouseWheelRight(1, 10)
+ call MouseWheelRight(1, 15)
+ call feedkeys('g0', 'Lx!')
+ call assert_equal(19, col('.'))
+
+ " Scroll Left
+ call MouseWheelLeft(1, 15)
+ call MouseWheelLeft(1, 10)
+ call feedkeys('g0', 'Lx!')
+ call assert_equal(7, col('.'))
+
+ " Shift Scroll Right
+ call MouseShiftWheelRight(1, 10)
+ call feedkeys('g0', 'Lx!')
+ " should scroll from where it is (7) + window width
+ call assert_equal(7 + winwidth(0), col('.'))
+
+ " Shift Scroll Left
+ call MouseShiftWheelLeft(1, 50)
+ call feedkeys('g0', 'Lx!')
+ call assert_equal(7, col('.'))
+ set wrap&
+
+ %d _
+ call setline(1, repeat([repeat('a', 60)], 10))
+
+ " record various mouse events
+ let mouseEventNames = [
+ \ 'LeftMouse', 'LeftRelease', '2-LeftMouse', '3-LeftMouse',
+ \ 'S-LeftMouse', 'A-LeftMouse', 'C-LeftMouse', 'MiddleMouse',
+ \ 'MiddleRelease', '2-MiddleMouse', '3-MiddleMouse',
+ \ 'S-MiddleMouse', 'A-MiddleMouse', 'C-MiddleMouse',
+ \ 'RightMouse', 'RightRelease', '2-RightMouse',
+ \ '3-RightMouse', 'S-RightMouse', 'A-RightMouse', 'C-RightMouse',
+ \ ]
+ let mouseEventCodes = map(copy(mouseEventNames), "'<' .. v:val .. '>'")
+ let g:events = []
+ for e in mouseEventCodes
+ exe 'nnoremap ' .. e .. ' <Cmd>call add(g:events, "' ..
+ \ substitute(e, '[<>]', '', 'g') .. '")<CR>'
+ endfor
+
+ " Test various mouse buttons
+ "(0 - Left, 1 - Middle, 2 - Right,
+ " 0x300 - MOUSE_X1/FROM_LEFT_3RD_BUTTON,
+ " 0x400 - MOUSE_X2/FROM_LEFT_4TH_BUTTON)
+ for button in [0, 1, 2, 0x300, 0x400]
+ " Single click
+ let args = #{button: button, row: 2, col: 5, multiclick: 0, modifiers: 0}
+ call test_mswin_event('mouse', args)
+ let args.button = 3
+ call test_mswin_event('mouse', args)
+
+ " Double Click
+ let args.button = button
+ call test_mswin_event('mouse', args)
+ let args.multiclick = 1
+ call test_mswin_event('mouse', args)
+ let args.button = 3
+ let args.multiclick = 0
+ call test_mswin_event('mouse', args)
+
+ " Triple Click
+ let args.button = button
+ call test_mswin_event('mouse', args)
+ let args.multiclick = 1
+ call test_mswin_event('mouse', args)
+ call test_mswin_event('mouse', args)
+ let args.button = 3
+ let args.multiclick = 0
+ call test_mswin_event('mouse', args)
+
+ " Shift click
+ let args = #{button: button, row: 3, col: 7, multiclick: 0, modifiers: 4}
+ call test_mswin_event('mouse', args)
+ let args.button = 3
+ call test_mswin_event('mouse', args)
+
+ " Alt click
+ let args.button = button
+ let args.modifiers = 8
+ call test_mswin_event('mouse', args)
+ let args.button = 3
+ call test_mswin_event('mouse', args)
+
+ " Ctrl click
+ let args.button = button
+ let args.modifiers = 16
+ call test_mswin_event('mouse', args)
+ let args.button = 3
+ call test_mswin_event('mouse', args)
+
+ call feedkeys("\<Esc>", 'Lx!')
+ endfor
+
+ if has('gui_running')
+ call assert_equal(['LeftMouse', 'LeftRelease', 'LeftMouse',
+ \ '2-LeftMouse', 'LeftMouse', '2-LeftMouse', '3-LeftMouse',
+ \ 'S-LeftMouse', 'A-LeftMouse', 'C-LeftMouse', 'MiddleMouse',
+ \ 'MiddleRelease', 'MiddleMouse', '2-MiddleMouse', 'MiddleMouse',
+ \ '2-MiddleMouse', '3-MiddleMouse', 'S-MiddleMouse', 'A-MiddleMouse',
+ \ 'C-MiddleMouse', 'RightMouse', 'RightRelease', 'RightMouse',
+ \ '2-RightMouse', 'RightMouse', '2-RightMouse', '3-RightMouse',
+ \ 'S-RightMouse', 'A-RightMouse', 'C-RightMouse'],
+ \ g:events)
+ else
+ call assert_equal(['MiddleRelease', 'LeftMouse', '2-LeftMouse',
+ \ '3-LeftMouse', 'S-LeftMouse', 'MiddleMouse', '2-MiddleMouse',
+ \ '3-MiddleMouse', 'MiddleMouse', 'S-MiddleMouse', 'RightMouse',
+ \ '2-RightMouse', '3-RightMouse'],
+ \ g:events)
+ endif
+
+ for e in mouseEventCodes
+ exe 'nunmap ' .. e
+ endfor
+
+ bw!
+ call test_override('no_query_mouse', 0)
+ set mousemodel&
+endfunc
+
+
+" Test MS-Windows test_mswin_event error handling
+func Test_mswin_event_error_handling()
+
+ let args = #{button: 0xfff, row: 2, col: 4, move: 0, multiclick: 0, modifiers: 0}
+ if !has('gui_running')
+ call assert_fails("call test_mswin_event('mouse', args)",'E475:')
+ endif
+ let args = #{button: 0, row: 2, col: 4, move: 0, multiclick: 0, modifiers: 0}
+ call assert_fails("call test_mswin_event('a1b2c3', args)", 'E475:')
+ call assert_fails("call test_mswin_event(test_null_string(), {})", 'E475:')
+
+ call assert_fails("call test_mswin_event([], args)", 'E1174:')
+ call assert_fails("call test_mswin_event('abc', [])", 'E1206:')
+
+ call assert_false(test_mswin_event('mouse', test_null_dict()))
+ let args = #{row: 2, col: 4, multiclick: 0, modifiers: 0}
+ call assert_false(test_mswin_event('mouse', args))
+ let args = #{button: 0, col: 4, multiclick: 0, modifiers: 0}
+ call assert_false(test_mswin_event('mouse', args))
+ let args = #{button: 0, row: 2, multiclick: 0, modifiers: 0}
+ call assert_false(test_mswin_event('mouse', args))
+ let args = #{button: 0, row: 2, col: 4, modifiers: 0}
+ call assert_false(test_mswin_event('mouse', args))
+ let args = #{button: 0, row: 2, col: 4, multiclick: 0}
+ call assert_false(test_mswin_event('mouse', args))
+
+ call assert_false(test_mswin_event('key', test_null_dict()))
+ call assert_fails("call test_mswin_event('key', [])", 'E1206:')
+ call assert_fails("call test_mswin_event('key', {'event': 'keydown', 'keycode': 0x0})", 'E1291:')
+ call assert_fails("call test_mswin_event('key', {'event': 'keydown', 'keycode': [15]})", 'E745:')
+ call assert_fails("call test_mswin_event('key', {'event': 'keys', 'keycode': 0x41})", 'E475:')
+ call assert_fails("call test_mswin_event('key', {'keycode': 0x41})", 'E417:')
+ call assert_fails("call test_mswin_event('key', {'event': 'keydown'})", 'E1291:')
+
+ call assert_fails("sandbox call test_mswin_event('key', {'event': 'keydown', 'keycode': 61 })", 'E48:')
+
+ " flush out any garbage left in the buffer.
+ while getchar(0)
+ endwhile
+endfunc
+
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim
index dd5280f..d3ab99c 100644
--- a/src/testdir/test_termcodes.vim
+++ b/src/testdir/test_termcodes.vim
@@ -437,25 +437,22 @@
call assert_equal(1, line('w0'), msg)
call assert_equal([0, 7, 1, 0], getpos('.'), msg)
- if has('gui')
- " Horizontal wheel scrolling currently only works when vim is
- " compiled with gui enabled.
- call MouseWheelRight(1, 1)
- call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
- call assert_equal([0, 7, 7, 0], getpos('.'), msg)
+ call MouseWheelRight(1, 1)
+ call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
+ call assert_equal([0, 7, 7, 0], getpos('.'), msg)
- call MouseWheelRight(1, 1)
- call assert_equal(13, 1 + virtcol(".") - wincol(), msg)
- call assert_equal([0, 7, 13, 0], getpos('.'), msg)
+ call MouseWheelRight(1, 1)
+ call assert_equal(13, 1 + virtcol(".") - wincol(), msg)
+ call assert_equal([0, 7, 13, 0], getpos('.'), msg)
- call MouseWheelLeft(1, 1)
- call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
- call assert_equal([0, 7, 13, 0], getpos('.'), msg)
+ call MouseWheelLeft(1, 1)
+ call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
+ call assert_equal([0, 7, 13, 0], getpos('.'), msg)
- call MouseWheelLeft(1, 1)
- call assert_equal(1, 1 + virtcol(".") - wincol(), msg)
- call assert_equal([0, 7, 13, 0], getpos('.'), msg)
- endif
+ call MouseWheelLeft(1, 1)
+ call assert_equal(1, 1 + virtcol(".") - wincol(), msg)
+ call assert_equal([0, 7, 13, 0], getpos('.'), msg)
+
endfor
let &mouse = save_mouse