blob: 950fc61ea10c56d34f590341cc08df9109c70081 [file] [log] [blame]
Christopher Plewright7b0afc12022-12-30 16:54:58 +00001" Test MS-Windows input event handling.
2" Most of this works the same in Windows GUI as well as Windows console.
Christopher Plewright20b795e2022-12-20 20:01:58 +00003
4source check.vim
5CheckMSWindows
Christopher Plewright20b795e2022-12-20 20:01:58 +00006source mouse.vim
7
Christopher Plewright7b0afc12022-12-30 16:54:58 +00008" Helper function for sending a grouped sequence of low level key presses
Dominique Pelleb49dfd02023-04-14 21:54:25 +01009" The modifier key(s) can be included as VK Key Codes in the sequence
Christopher Plewright7b0afc12022-12-30 16:54:58 +000010" Keydown events will be sent, to to the end of the group, then keyup events
11" will be sent in reverse order to release the keys.
12func SendKeyGroup(keygroup)
13 for k in a:keygroup
14 call test_mswin_event("key", {'event': "keydown", 'keycode': k})
Christopher Plewright20b795e2022-12-20 20:01:58 +000015 endfor
Christopher Plewright7b0afc12022-12-30 16:54:58 +000016 for k in reverse(copy(a:keygroup))
17 call test_mswin_event("key", {'event': "keyup", 'keycode': k})
Christopher Plewright20b795e2022-12-20 20:01:58 +000018 endfor
19endfunc
20
Christopher Plewright7b0afc12022-12-30 16:54:58 +000021" Send individual key press and release events.
Dominique Pelleb49dfd02023-04-14 21:54:25 +010022" the modifiers for the key press can be specified in the modifiers arg.
Christopher Plewright7b0afc12022-12-30 16:54:58 +000023func SendKeyWithModifiers(key, modifiers)
Christopher Plewright20b795e2022-12-20 20:01:58 +000024 let args = { }
25 let args.keycode = a:key
26 let args.modifiers = a:modifiers
27 let args.event = "keydown"
28 call test_mswin_event("key", args)
29 let args.event = "keyup"
30 call test_mswin_event("key", args)
31 unlet args
32endfunc
33
Christopher Plewright7b0afc12022-12-30 16:54:58 +000034" Send an individual key press, without modifiers.
35func SendKey(key)
36 call SendKeyWithModifiers(a:key, 0)
37endfunc
38
Christian Brabandtf6ebaa72024-01-25 20:44:49 +010039" getcharstr(0) but catch Vim:Interrupt
40func Getcharstr()
41 try
42 let ch = getcharstr(0)
43 catch /^Vim:Interrupt$/
44 let ch = "\<c-c>"
45 endtry
46 return ch
47endfunc
48
49
Christopher Plewright7b0afc12022-12-30 16:54:58 +000050" Send a string of individual key-press events, without modifiers.
51func SendKeyStr(keystring)
52 for k in a:keystring
53 call SendKey(k)
54 endfor
55endfunc
56
Bram Moolenaar94722c52023-01-28 19:19:03 +000057" This tells Vim to execute the buffered keys as user commands,
Christopher Plewright7b0afc12022-12-30 16:54:58 +000058" ie. same as feekdeys with mode X would do.
59func ExecuteBufferedKeys()
60 if has('gui_running')
61 call feedkeys("\<Esc>", 'Lx!')
62 else
63 call test_mswin_event("key", {'execute': v:true})
64 endif
65endfunc
66
Christopher Plewrightc8b20492023-01-04 18:06:00 +000067" Refer to the following page for the virtual key codes:
68" https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
Christopher Plewright7b0afc12022-12-30 16:54:58 +000069let s:VK = {
70 \ 'ENTER' : 0x0D,
71 \ 'SPACE' : 0x20,
72 \ 'SHIFT' : 0x10,
73 \ 'LSHIFT' : 0xA0,
74 \ 'RSHIFT' : 0xA1,
75 \ 'CONTROL' : 0x11,
76 \ 'LCONTROL' : 0xA2,
77 \ 'RCONTROL' : 0xA3,
78 \ 'MENU' : 0x12,
79 \ 'ALT' : 0x12,
80 \ 'LMENU' : 0xA4,
81 \ 'LALT' : 0xA4,
82 \ 'RMENU' : 0xA5,
83 \ 'RALT' : 0xA5,
84 \ 'OEM_1' : 0xBA,
85 \ 'OEM_2' : 0xBF,
86 \ 'OEM_3' : 0xC0,
87 \ 'OEM_4' : 0xDB,
88 \ 'OEM_5' : 0xDC,
89 \ 'OEM_6' : 0xDD,
90 \ 'OEM_7' : 0xDE,
91 \ 'OEM_PLUS' : 0xBB,
92 \ 'OEM_COMMA' : 0xBC,
93 \ 'OEM_MINUS' : 0xBD,
94 \ 'OEM_PERIOD' : 0xBE,
95 \ 'PRIOR' : 0x21,
96 \ 'NEXT' : 0x22,
97 \ 'END' : 0x23,
98 \ 'HOME' : 0x24,
99 \ 'LEFT' : 0x25,
100 \ 'UP' : 0x26,
101 \ 'RIGHT' : 0x27,
102 \ 'DOWN' : 0x28,
103 \ 'KEY_0' : 0x30,
104 \ 'KEY_1' : 0x31,
105 \ 'KEY_2' : 0x32,
106 \ 'KEY_3' : 0x33,
107 \ 'KEY_4' : 0x34,
108 \ 'KEY_5' : 0x35,
109 \ 'KEY_6' : 0x36,
110 \ 'KEY_7' : 0x37,
111 \ 'KEY_8' : 0x38,
112 \ 'KEY_9' : 0x39,
113 \ 'KEY_A' : 0x41,
114 \ 'KEY_B' : 0x42,
115 \ 'KEY_C' : 0x43,
116 \ 'KEY_D' : 0x44,
117 \ 'KEY_E' : 0x45,
118 \ 'KEY_F' : 0x46,
119 \ 'KEY_G' : 0x47,
120 \ 'KEY_H' : 0x48,
121 \ 'KEY_I' : 0x49,
122 \ 'KEY_J' : 0x4A,
123 \ 'KEY_K' : 0x4B,
124 \ 'KEY_L' : 0x4C,
125 \ 'KEY_M' : 0x4D,
126 \ 'KEY_N' : 0x4E,
127 \ 'KEY_O' : 0x4F,
128 \ 'KEY_P' : 0x50,
129 \ 'KEY_Q' : 0x51,
130 \ 'KEY_R' : 0x52,
131 \ 'KEY_S' : 0x53,
132 \ 'KEY_T' : 0x54,
133 \ 'KEY_U' : 0x55,
134 \ 'KEY_V' : 0x56,
135 \ 'KEY_W' : 0x57,
136 \ 'KEY_X' : 0x58,
137 \ 'KEY_Y' : 0x59,
138 \ 'KEY_Z' : 0x5A,
139 \ 'NUMPAD0' : 0x60,
140 \ 'NUMPAD1' : 0x61,
141 \ 'NUMPAD2' : 0x62,
142 \ 'NUMPAD3' : 0x63,
143 \ 'NUMPAD4' : 0x64,
144 \ 'NUMPAD5' : 0x65,
145 \ 'NUMPAD6' : 0x66,
146 \ 'NUMPAD7' : 0x67,
147 \ 'NUMPAD8' : 0x68,
148 \ 'NUMPAD9' : 0x69,
149 \ 'MULTIPLY' : 0x6A,
150 \ 'ADD' : 0x6B,
151 \ 'SUBTRACT' : 0x6D,
152 \ 'F1' : 0x70,
153 \ 'F2' : 0x71,
154 \ 'F3' : 0x72,
155 \ 'F4' : 0x73,
156 \ 'F5' : 0x74,
157 \ 'F6' : 0x75,
158 \ 'F7' : 0x76,
159 \ 'F8' : 0x77,
160 \ 'F9' : 0x78,
161 \ 'F10' : 0x79,
162 \ 'F11' : 0x7A,
163 \ 'F12' : 0x7B,
164 \ 'DELETE' : 0x2E,
165 \ 'BACK' : 0x08,
166 \ 'ESCAPE' : 0x1B
167 \ }
168
Christopher Plewright566f76e2023-01-10 13:43:04 +0000169 let s:MOD_MASK_SHIFT = 0x02
170 let s:MOD_MASK_CTRL = 0x04
171 let s:MOD_MASK_ALT = 0x08
Bram Moolenaar94722c52023-01-28 19:19:03 +0000172
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000173 let s:vim_key_modifiers = [
174 \ ["", 0, []],
Christopher Plewright566f76e2023-01-10 13:43:04 +0000175 \ ["S-", 2, [s:VK.LSHIFT]],
176 \ ["C-", 4, [s:VK.LCONTROL]],
177 \ ["C-S-", 6, [s:VK.LCONTROL, s:VK.LSHIFT]],
178 \ ["A-", 8, [s:VK.LMENU]],
179 \ ["A-S-", 10, [s:VK.LMENU, s:VK.LSHIFT]],
180 \ ["A-C-", 12, [s:VK.LMENU, s:VK.LCONTROL]],
181 \ ["A-C-S-", 14, [s:VK.LMENU, s:VK.LCONTROL, s:VK.LSHIFT]],
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000182 \]
183
184 " Assuming Standard US PC Keyboard layout
185 let s:test_ascii_key_chars = [
186 \ [[s:VK.SPACE], ' '],
187 \ [[s:VK.OEM_1], ';'],
188 \ [[s:VK.OEM_2], '/'],
189 \ [[s:VK.OEM_3], '`'],
190 \ [[s:VK.OEM_4], '['],
191 \ [[s:VK.OEM_5], '\'],
192 \ [[s:VK.OEM_6], ']'],
193 \ [[s:VK.OEM_7], ''''],
194 \ [[s:VK.OEM_PLUS], '='],
195 \ [[s:VK.OEM_COMMA], ','],
196 \ [[s:VK.OEM_MINUS], '-'],
197 \ [[s:VK.OEM_PERIOD], '.'],
198 \ [[s:VK.SHIFT, s:VK.OEM_1], ':'],
199 \ [[s:VK.SHIFT, s:VK.OEM_2], '?'],
200 \ [[s:VK.SHIFT, s:VK.OEM_3], '~'],
201 \ [[s:VK.SHIFT, s:VK.OEM_4], '{'],
202 \ [[s:VK.SHIFT, s:VK.OEM_5], '|'],
203 \ [[s:VK.SHIFT, s:VK.OEM_6], '}'],
204 \ [[s:VK.SHIFT, s:VK.OEM_7], '"'],
205 \ [[s:VK.SHIFT, s:VK.OEM_PLUS], '+'],
206 \ [[s:VK.SHIFT, s:VK.OEM_COMMA], '<'],
207 \ [[s:VK.SHIFT, s:VK.OEM_MINUS], '_'],
208 \ [[s:VK.SHIFT, s:VK.OEM_PERIOD], '>'],
209 \ [[s:VK.KEY_1], '1'],
210 \ [[s:VK.KEY_2], '2'],
211 \ [[s:VK.KEY_3], '3'],
212 \ [[s:VK.KEY_4], '4'],
213 \ [[s:VK.KEY_5], '5'],
214 \ [[s:VK.KEY_6], '6'],
215 \ [[s:VK.KEY_7], '7'],
216 \ [[s:VK.KEY_8], '8'],
217 \ [[s:VK.KEY_9], '9'],
218 \ [[s:VK.KEY_0], '0'],
219 \ [[s:VK.SHIFT, s:VK.KEY_1], '!'],
220 \ [[s:VK.SHIFT, s:VK.KEY_2], '@'],
221 \ [[s:VK.SHIFT, s:VK.KEY_3], '#'],
222 \ [[s:VK.SHIFT, s:VK.KEY_4], '$'],
223 \ [[s:VK.SHIFT, s:VK.KEY_5], '%'],
224 \ [[s:VK.SHIFT, s:VK.KEY_6], '^'],
225 \ [[s:VK.SHIFT, s:VK.KEY_7], '&'],
226 \ [[s:VK.SHIFT, s:VK.KEY_8], '*'],
227 \ [[s:VK.SHIFT, s:VK.KEY_9], '('],
228 \ [[s:VK.SHIFT, s:VK.KEY_0], ')'],
229 \ [[s:VK.KEY_A], 'a'],
230 \ [[s:VK.KEY_B], 'b'],
231 \ [[s:VK.KEY_C], 'c'],
232 \ [[s:VK.KEY_D], 'd'],
233 \ [[s:VK.KEY_E], 'e'],
234 \ [[s:VK.KEY_F], 'f'],
235 \ [[s:VK.KEY_G], 'g'],
236 \ [[s:VK.KEY_H], 'h'],
237 \ [[s:VK.KEY_I], 'i'],
238 \ [[s:VK.KEY_J], 'j'],
239 \ [[s:VK.KEY_K], 'k'],
240 \ [[s:VK.KEY_L], 'l'],
241 \ [[s:VK.KEY_M], 'm'],
242 \ [[s:VK.KEY_N], 'n'],
243 \ [[s:VK.KEY_O], 'o'],
244 \ [[s:VK.KEY_P], 'p'],
245 \ [[s:VK.KEY_Q], 'q'],
246 \ [[s:VK.KEY_R], 'r'],
247 \ [[s:VK.KEY_S], 's'],
248 \ [[s:VK.KEY_T], 't'],
249 \ [[s:VK.KEY_U], 'u'],
250 \ [[s:VK.KEY_V], 'v'],
251 \ [[s:VK.KEY_W], 'w'],
252 \ [[s:VK.KEY_X], 'x'],
253 \ [[s:VK.KEY_Y], 'y'],
254 \ [[s:VK.KEY_Z], 'z'],
255 \ [[s:VK.SHIFT, s:VK.KEY_A], 'A'],
256 \ [[s:VK.SHIFT, s:VK.KEY_B], 'B'],
257 \ [[s:VK.SHIFT, s:VK.KEY_C], 'C'],
258 \ [[s:VK.SHIFT, s:VK.KEY_D], 'D'],
259 \ [[s:VK.SHIFT, s:VK.KEY_E], 'E'],
260 \ [[s:VK.SHIFT, s:VK.KEY_F], 'F'],
261 \ [[s:VK.SHIFT, s:VK.KEY_G], 'G'],
262 \ [[s:VK.SHIFT, s:VK.KEY_H], 'H'],
263 \ [[s:VK.SHIFT, s:VK.KEY_I], 'I'],
264 \ [[s:VK.SHIFT, s:VK.KEY_J], 'J'],
265 \ [[s:VK.SHIFT, s:VK.KEY_K], 'K'],
266 \ [[s:VK.SHIFT, s:VK.KEY_L], 'L'],
267 \ [[s:VK.SHIFT, s:VK.KEY_M], 'M'],
268 \ [[s:VK.SHIFT, s:VK.KEY_N], 'N'],
269 \ [[s:VK.SHIFT, s:VK.KEY_O], 'O'],
270 \ [[s:VK.SHIFT, s:VK.KEY_P], 'P'],
271 \ [[s:VK.SHIFT, s:VK.KEY_Q], 'Q'],
272 \ [[s:VK.SHIFT, s:VK.KEY_R], 'R'],
273 \ [[s:VK.SHIFT, s:VK.KEY_S], 'S'],
274 \ [[s:VK.SHIFT, s:VK.KEY_T], 'T'],
275 \ [[s:VK.SHIFT, s:VK.KEY_U], 'U'],
276 \ [[s:VK.SHIFT, s:VK.KEY_V], 'V'],
277 \ [[s:VK.SHIFT, s:VK.KEY_W], 'W'],
278 \ [[s:VK.SHIFT, s:VK.KEY_X], 'X'],
279 \ [[s:VK.SHIFT, s:VK.KEY_Y], 'Y'],
280 \ [[s:VK.SHIFT, s:VK.KEY_Z], 'Z'],
281 \ [[s:VK.CONTROL, s:VK.KEY_A], 0x01],
282 \ [[s:VK.CONTROL, s:VK.KEY_B], 0x02],
283 \ [[s:VK.CONTROL, s:VK.KEY_C], 0x03],
284 \ [[s:VK.CONTROL, s:VK.KEY_D], 0x04],
285 \ [[s:VK.CONTROL, s:VK.KEY_E], 0x05],
286 \ [[s:VK.CONTROL, s:VK.KEY_F], 0x06],
287 \ [[s:VK.CONTROL, s:VK.KEY_G], 0x07],
288 \ [[s:VK.CONTROL, s:VK.KEY_H], 0x08],
289 \ [[s:VK.CONTROL, s:VK.KEY_I], 0x09],
290 \ [[s:VK.CONTROL, s:VK.KEY_J], 0x0A],
291 \ [[s:VK.CONTROL, s:VK.KEY_K], 0x0B],
292 \ [[s:VK.CONTROL, s:VK.KEY_L], 0x0C],
293 \ [[s:VK.CONTROL, s:VK.KEY_M], 0x0D],
294 \ [[s:VK.CONTROL, s:VK.KEY_N], 0x0E],
295 \ [[s:VK.CONTROL, s:VK.KEY_O], 0x0F],
296 \ [[s:VK.CONTROL, s:VK.KEY_P], 0x10],
297 \ [[s:VK.CONTROL, s:VK.KEY_Q], 0x11],
298 \ [[s:VK.CONTROL, s:VK.KEY_R], 0x12],
299 \ [[s:VK.CONTROL, s:VK.KEY_S], 0x13],
300 \ [[s:VK.CONTROL, s:VK.KEY_T], 0x14],
301 \ [[s:VK.CONTROL, s:VK.KEY_U], 0x15],
302 \ [[s:VK.CONTROL, s:VK.KEY_V], 0x16],
303 \ [[s:VK.CONTROL, s:VK.KEY_W], 0x17],
304 \ [[s:VK.CONTROL, s:VK.KEY_X], 0x18],
305 \ [[s:VK.CONTROL, s:VK.KEY_Y], 0x19],
306 \ [[s:VK.CONTROL, s:VK.KEY_Z], 0x1A],
307 \ [[s:VK.CONTROL, s:VK.OEM_4], 0x1B],
308 \ [[s:VK.CONTROL, s:VK.OEM_5], 0x1C],
309 \ [[s:VK.CONTROL, s:VK.OEM_6], 0x1D],
Christopher Plewrightc8b20492023-01-04 18:06:00 +0000310 \ [[s:VK.CONTROL, s:VK.KEY_6], 0x1E],
311 \ [[s:VK.CONTROL, s:VK.OEM_MINUS], 0x1F],
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000312 \ ]
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000313
314let s:test_extra_key_chars = [
315 \ [[s:VK.ALT, s:VK.KEY_1], '±'],
316 \ [[s:VK.ALT, s:VK.KEY_2], '²'],
317 \ [[s:VK.ALT, s:VK.KEY_3], '³'],
318 \ [[s:VK.ALT, s:VK.KEY_4], '´'],
319 \ [[s:VK.ALT, s:VK.KEY_5], 'µ'],
320 \ [[s:VK.ALT, s:VK.KEY_6], '¶'],
321 \ [[s:VK.ALT, s:VK.KEY_7], '·'],
322 \ [[s:VK.ALT, s:VK.KEY_8], '¸'],
323 \ [[s:VK.ALT, s:VK.KEY_9], '¹'],
324 \ [[s:VK.ALT, s:VK.KEY_0], '°'],
325 \ [[s:VK.ALT, s:VK.KEY_A], 'á'],
326 \ [[s:VK.ALT, s:VK.KEY_B], 'â'],
327 \ [[s:VK.ALT, s:VK.KEY_C], 'ã'],
328 \ [[s:VK.ALT, s:VK.KEY_D], 'ä'],
329 \ [[s:VK.ALT, s:VK.KEY_E], 'Ã¥'],
330 \ [[s:VK.ALT, s:VK.KEY_F], 'æ'],
331 \ [[s:VK.ALT, s:VK.KEY_G], 'ç'],
332 \ [[s:VK.ALT, s:VK.KEY_H], 'è'],
333 \ [[s:VK.ALT, s:VK.KEY_I], 'é'],
334 \ [[s:VK.ALT, s:VK.KEY_J], 'ê'],
335 \ [[s:VK.ALT, s:VK.KEY_K], 'ë'],
336 \ [[s:VK.ALT, s:VK.KEY_L], 'ì'],
337 \ [[s:VK.ALT, s:VK.KEY_M], 'í'],
338 \ [[s:VK.ALT, s:VK.KEY_N], 'î'],
339 \ [[s:VK.ALT, s:VK.KEY_O], 'ï'],
340 \ [[s:VK.ALT, s:VK.KEY_P], 'ð'],
341 \ [[s:VK.ALT, s:VK.KEY_Q], 'ñ'],
342 \ [[s:VK.ALT, s:VK.KEY_R], 'ò'],
343 \ [[s:VK.ALT, s:VK.KEY_S], 'ó'],
344 \ [[s:VK.ALT, s:VK.KEY_T], 'ô'],
345 \ [[s:VK.ALT, s:VK.KEY_U], 'õ'],
346 \ [[s:VK.ALT, s:VK.KEY_V], 'ö'],
347 \ [[s:VK.ALT, s:VK.KEY_W], '÷'],
348 \ [[s:VK.ALT, s:VK.KEY_X], 'ø'],
349 \ [[s:VK.ALT, s:VK.KEY_Y], 'ù'],
350 \ [[s:VK.ALT, s:VK.KEY_Z], 'ú'],
351 \ ]
352
353func s:LoopTestKeyArray(arr)
Christopher Plewright566f76e2023-01-10 13:43:04 +0000354 " flush out the typeahead buffer
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000355 while getchar(0)
356 endwhile
357
358 for [kcodes, kstr] in a:arr
359 " Send as a sequence of key presses.
360 call SendKeyGroup(kcodes)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100361 let ch = Getcharstr()
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000362 " need to deal a bit differently with the non-printable ascii chars < 0x20
Christopher Plewrightc8b20492023-01-04 18:06:00 +0000363 if kstr < 0x20 && index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], kcodes[0]) >= 0
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000364 call assert_equal(nr2char(kstr), $"{ch}")
365 else
366 call assert_equal(kstr, $"{ch}")
367 endif
368 let mod_mask = getcharmod()
369 " the mod_mask is zero when no modifiers are used
370 " and when the virtual termcap maps the character
371 call assert_equal(0, mod_mask, $"key = {kstr}")
372
Dominique Pelleb49dfd02023-04-14 21:54:25 +0100373 " Send as a single key press with a modifiers mask.
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000374 let modifiers = 0
375 let key = kcodes[0]
376 for key in kcodes
377 if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], key) >= 0
Christopher Plewright566f76e2023-01-10 13:43:04 +0000378 let modifiers = modifiers + s:MOD_MASK_SHIFT
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000379 endif
380 if index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], key) >= 0
Christopher Plewright566f76e2023-01-10 13:43:04 +0000381 let modifiers = modifiers + s:MOD_MASK_CTRL
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000382 endif
383 if index([s:VK.ALT, s:VK.LALT, s:VK.RALT], key) >= 0
Christopher Plewright566f76e2023-01-10 13:43:04 +0000384 let modifiers = modifiers + s:MOD_MASK_ALT
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000385 endif
386 endfor
387 call SendKeyWithModifiers(key, modifiers)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100388 let ch = Getcharstr()
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000389 " need to deal a bit differently with the non-printable ascii chars < 0x20
390 if kstr < 0x20 && index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], kcodes[0]) >= 0
391 call assert_equal(nr2char(kstr), $"{ch}")
392 else
393 call assert_equal(kstr, $"{ch}")
394 endif
395 let mod_mask = getcharmod()
396 " the mod_mask is zero when no modifiers are used
397 " and when the virtual termcap maps the character
398 call assert_equal(0, mod_mask, $"key = {kstr}")
399 endfor
400
Christopher Plewright566f76e2023-01-10 13:43:04 +0000401 " flush out the typeahead buffer
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000402 while getchar(0)
403 endwhile
404
405endfunc
406
407" Test MS-Windows key events
Christopher Plewright566f76e2023-01-10 13:43:04 +0000408func Test_mswin_event_character_keys()
Christopher Plewright20b795e2022-12-20 20:01:58 +0000409 CheckMSWindows
410 new
411
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000412 call s:LoopTestKeyArray(s:test_ascii_key_chars)
Christopher Plewright20b795e2022-12-20 20:01:58 +0000413
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000414 if !has('gui_running')
415 call s:LoopTestKeyArray(s:test_extra_key_chars)
416 endif
Christopher Plewright20b795e2022-12-20 20:01:58 +0000417
418" Test keyboard codes for digits
419" (0x30 - 0x39) : VK_0 - VK_9 are the same as ASCII '0' - '9'
420 for kc in range(48, 57)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000421 call SendKey(kc)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100422 let ch = Getcharstr()
Christopher Plewright20b795e2022-12-20 20:01:58 +0000423 call assert_equal(nr2char(kc), ch)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000424 call SendKeyWithModifiers(kc, 0)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100425 let ch = Getcharstr()
Christopher Plewright20b795e2022-12-20 20:01:58 +0000426 call assert_equal(nr2char(kc), ch)
427 endfor
428
429" Test keyboard codes for Alt-0 to Alt-9
430" Expect +128 from the digit char codes
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000431 for modkey in [s:VK.ALT, s:VK.LALT, s:VK.RALT]
Christopher Plewright20b795e2022-12-20 20:01:58 +0000432 for kc in range(48, 57)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000433 call SendKeyGroup([modkey, kc])
Christopher Plewright20b795e2022-12-20 20:01:58 +0000434 let ch = getchar(0)
435 call assert_equal(kc+128, ch)
Christopher Plewright566f76e2023-01-10 13:43:04 +0000436 call SendKeyWithModifiers(kc, s:MOD_MASK_ALT)
Christopher Plewright20b795e2022-12-20 20:01:58 +0000437 let ch = getchar(0)
438 call assert_equal(kc+128, ch)
439 endfor
440 endfor
441
442" Test for lowercase 'a' to 'z', VK codes 65(0x41) - 90(0x5A)
443" Note: VK_A-VK_Z virtual key codes coincide with uppercase ASCII codes A-Z.
444" eg VK_A is 65, and the ASCII character code for uppercase 'A' is also 65.
Bram Moolenaar94722c52023-01-28 19:19:03 +0000445" Caution: these are interpreted as lowercase when Shift is NOT pressed.
Christopher Plewright20b795e2022-12-20 20:01:58 +0000446" eg, sending VK_A (65) 'A' Key code without shift modifier, will produce ASCII
447" char 'a' (91) as the output. The ASCII codes for the lowercase letters are
448" numbered 32 higher than their uppercase versions.
449 for kc in range(65, 90)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000450 call SendKey(kc)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100451 let ch = Getcharstr()
Christopher Plewright20b795e2022-12-20 20:01:58 +0000452 call assert_equal(nr2char(kc + 32), ch)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000453 call SendKeyWithModifiers(kc, 0)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100454 let ch = Getcharstr()
Christopher Plewright20b795e2022-12-20 20:01:58 +0000455 call assert_equal(nr2char(kc + 32), ch)
456 endfor
457
458" Test for Uppercase 'A' - 'Z' keys
459" ie. with VK_SHIFT, expect the keycode = character code.
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000460 for modkey in [s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT]
461 for kc in range(65, 90)
462 call SendKeyGroup([modkey, kc])
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100463 let ch = Getcharstr()
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000464 call assert_equal(nr2char(kc), ch)
Christopher Plewright566f76e2023-01-10 13:43:04 +0000465 call SendKeyWithModifiers(kc, s:MOD_MASK_SHIFT)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100466 let ch = Getcharstr()
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000467 call assert_equal(nr2char(kc), ch)
468 endfor
Christopher Plewright20b795e2022-12-20 20:01:58 +0000469 endfor
470
Christian Brabandt12b92772024-01-25 21:23:22 +0100471" Test for <Ctrl-A> to <Ctrl-Z> keys
472" Expect the unicode characters 0x01 to 0x1A
473" Note: May cause an Interrupt to be triggered for Ctrl-C
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000474 for modkey in [s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL]
Christopher Plewright20b795e2022-12-20 20:01:58 +0000475 for kc in range(65, 90)
Christian Brabandt12b92772024-01-25 21:23:22 +0100476 try
477 call SendKeyGroup([modkey, kc])
478 let ch = Getcharstr()
479 call assert_equal(nr2char(kc - 64), ch)
480 call SendKeyWithModifiers(kc, s:MOD_MASK_CTRL)
481 let ch = Getcharstr()
482 call assert_equal(nr2char(kc - 64), ch)
483 catch /^Vim:Interrupt$/
484 " ignore
485 endtry
Christopher Plewright20b795e2022-12-20 20:01:58 +0000486 endfor
487 endfor
488
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000489 " Windows intercepts some of these keys in the GUI.
Christopher Plewright20b795e2022-12-20 20:01:58 +0000490 if !has("gui_running")
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000491 " Test for <Alt-A> to <Alt-Z> keys
Christopher Plewright20b795e2022-12-20 20:01:58 +0000492 " Expect the unicode characters 0xE1 to 0xFA
493 " ie. 160 higher than the lowercase equivalent
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000494 for modkey in [s:VK.ALT, s:VK.LALT, s:VK.RALT]
495 for kc in range(65, 90)
496 call SendKeyGroup([modkey, kc])
497 let ch = getchar(0)
498 call assert_equal(kc+160, ch)
Christopher Plewright566f76e2023-01-10 13:43:04 +0000499 call SendKeyWithModifiers(kc, s:MOD_MASK_ALT)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000500 let ch = getchar(0)
501 call assert_equal(kc+160, ch)
502 endfor
Christopher Plewright20b795e2022-12-20 20:01:58 +0000503 endfor
504 endif
505
Christopher Plewright566f76e2023-01-10 13:43:04 +0000506endfun
507
Christopher Plewrightc8b20492023-01-04 18:06:00 +0000508 " Test for Function Keys 'F1' to 'F12'
509 " VK codes 112(0x70) - 123(0x7B)
510 " Also with ALL permutatios of modifiers; Shift, Ctrl & Alt
Christopher Plewright566f76e2023-01-10 13:43:04 +0000511func Test_mswin_event_function_keys()
512
513 if has('gui_running')
514 let g:test_is_flaky = 1
515 endif
516
517 " NOTE: Windows intercepts these combinations in the GUI
518 let gui_nogo = ["A-F1", "A-F2", "A-F3", "A-F4", "A-S-F4", "A-C-S-F4",
519 \ "A-F5", "A-F6", "A-F7", "A-F8", "A-C-F8", "A-F9",
520 \ "A-F10", "A-F11" , "A-C-F11", "A-C-F12"]
521
522 " flush out the typeahead buffer
523 while getchar(0)
524 endwhile
525
526 for [mod_str, vim_mod_mask, mod_keycodes] in s:vim_key_modifiers
527 for n in range(1, 12)
528 let expected_mod_mask = vim_mod_mask
529 let kstr = $"{mod_str}F{n}"
530 if !has('gui_running') || (has('gui_running') && n != 10
531 \ && index(gui_nogo, kstr) == -1)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000532 let keycode = eval('"\<' .. kstr .. '>"')
Christopher Plewright566f76e2023-01-10 13:43:04 +0000533 " flush out the typeahead buffer
Christopher Plewrightc8b20492023-01-04 18:06:00 +0000534 while getchar(0)
535 endwhile
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000536 call SendKeyWithModifiers(111+n, vim_mod_mask)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100537 let ch = Getcharstr()
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000538 let mod_mask = getcharmod()
Christopher Plewrightc8b20492023-01-04 18:06:00 +0000539 call assert_equal(keycode, $"{ch}", $"key = {kstr}")
Christopher Plewright566f76e2023-01-10 13:43:04 +0000540 " workaround for the virtual termcap maps changing the character
541 "instead of sending Shift
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000542 for mod_key in mod_keycodes
543 if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], mod_key) >= 0
Christopher Plewright566f76e2023-01-10 13:43:04 +0000544 let expected_mod_mask -= s:MOD_MASK_SHIFT
545 break
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000546 endif
547 endfor
Christopher Plewright566f76e2023-01-10 13:43:04 +0000548 call assert_equal(expected_mod_mask, mod_mask, $"mod = {expected_mod_mask} for key = {kstr}")
549 endif
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000550 endfor
Christopher Plewright566f76e2023-01-10 13:43:04 +0000551 endfor
552endfunc
553
554func ExtractModifiers(mod_keycodes)
555 let has_shift = 0
556 let has_ctrl = 0
557 let has_alt = 0
558 for mod_key in a:mod_keycodes
559 if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], mod_key) >= 0
560 let has_shift = 1
561 endif
562 if index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], mod_key) >= 0
563 let has_ctrl = 1
564 endif
565 if index([s:VK.MENU, s:VK.LMENU, s:VK.RMENU], mod_key) >= 0
566 let has_alt = 1
567 endif
568 endfor
569 return [has_shift, has_ctrl, has_alt]
570endfunc
571
572 " Test for Movement Keys;
573 " VK_PRIOR 0x21, VK_NEXT 0x22,
574 " VK_END 0x23, VK_HOME 0x24,
575 " VK_LEFT 0x25, VK_UP 0x26,
576 " VK_RIGHT 0x27, VK_DOWN 0x28
577 " With ALL permutations of modifiers; none, Shift, Ctrl & Alt
578func Test_mswin_event_movement_keys()
579
580 if has('gui_running')
581 let g:test_is_flaky = 1
Christopher Plewright20b795e2022-12-20 20:01:58 +0000582 endif
583
Christopher Plewright566f76e2023-01-10 13:43:04 +0000584 let movement_keys = [
585 \ [s:VK.PRIOR, "PageUp"],
586 \ [s:VK.NEXT, "PageDown"],
587 \ [s:VK.END, "End"],
588 \ [s:VK.HOME, "Home"],
589 \ [s:VK.LEFT, "Left"],
590 \ [s:VK.UP, "Up"],
591 \ [s:VK.RIGHT, "Right"],
592 \ [s:VK.DOWN, "Down"],
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000593 \ ]
594
Christopher Plewright566f76e2023-01-10 13:43:04 +0000595 " flush out the typeahead buffer
596 while getchar(0)
597 endwhile
598
599 for [mod_str, vim_mod_mask, mod_keycodes] in s:vim_key_modifiers
600 for [kcode, kname] in movement_keys
601 let exp_mod_mask = vim_mod_mask
602 let kstr = $"{mod_str}{kname}"
603 let chstr_eval = eval('"\<' .. kstr .. '>"')
604
605 " flush out the typeahead buffer
606 while getchar(0)
607 endwhile
608 execute 'call feedkeys("\<' .. kstr .. '>")'
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100609 let chstr_fk = Getcharstr()
Christopher Plewright566f76e2023-01-10 13:43:04 +0000610 call assert_equal(chstr_eval, chstr_fk, $"feedkeys = <{kstr}>")
611
612 " flush out the typeahead buffer
613 while getchar(0)
614 endwhile
615 call SendKey(kcode)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100616 let chstr_alone = Getcharstr()
Christopher Plewright566f76e2023-01-10 13:43:04 +0000617 let chstr_alone_end = chstr_alone[len(chstr_alone)-2:len(chstr_alone)-1]
618
619 " flush out the typeahead buffer
620 while getchar(0)
621 endwhile
622 call SendKeyGroup(mod_keycodes + [kcode])
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100623 let chstr_mswin = Getcharstr()
Christopher Plewright566f76e2023-01-10 13:43:04 +0000624 let chstr_mswin_end = chstr_mswin[len(chstr_mswin)-2:len(chstr_mswin)-1]
625 let mod_mask = getcharmod()
626
627 " The virtual termcap maps may** change the character and either;
628 " - remove the Shift modifier, or
629 " - remove the Ctrl modifier if the Shift modifier was not removed.
630 let [has_shift, has_ctrl, has_alt] = ExtractModifiers(mod_keycodes)
631 if chstr_alone_end != chstr_mswin_end
632 if has_shift != 0
633 let exp_mod_mask -= s:MOD_MASK_SHIFT
634 elseif has_ctrl != 0
635 let exp_mod_mask -= s:MOD_MASK_CTRL
636 endif
637 endif
638 " **Note: The appveyor Windows GUI test environments, from VS2017 on,
639 " consistently intercepts the Shift modifier WITHOUT changing the
640 " MOVEMENT character. This issue does not happen in any github actions
641 " CI Windows test environments. Attempted to reproduce this manually
642 " on Windows versions; 7, 8.1, 10, 11, Server 2019 and Server 2022, but
643 " the issue did not occur on any of those environments.
644 " Below is a workaround for the issue.
645 if has('gui_running') && has_shift != 0
646 if exp_mod_mask != mod_mask && chstr_eval != chstr_mswin
647 let kstr_sub = substitute(kstr, "S-", "", "")
648 let chstr_eval = eval('"\<' .. kstr_sub .. '>"')
649 if exp_mod_mask - s:MOD_MASK_SHIFT == mod_mask
650 let exp_mod_mask -= s:MOD_MASK_SHIFT
651 elseif has_ctrl != 0 && exp_mod_mask - s:MOD_MASK_CTRL == mod_mask
652 let exp_mod_mask -= s:MOD_MASK_CTRL
653 endif
654 endif
655 endif
656 call assert_equal(chstr_eval, chstr_mswin, $"key = {kstr}")
657 call assert_equal(exp_mod_mask, mod_mask, $"mod_mask for key = {kstr}")
658 endfor
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000659 endfor
660
Christopher Plewright20b795e2022-12-20 20:01:58 +0000661 bw!
662endfunc
663
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000664
665" Test for QWERTY Ctrl+- which should result in ^_
666" issue #10817
667func Test_QWERTY_Ctrl_minus()
668 CheckMSWindows
669 new
670
671 call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS])
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100672 let ch = Getcharstr()
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000673 call assert_equal(nr2char(0x1f),ch)
674
675 call SendKey(s:VK.KEY_I)
676 call SendKeyGroup([s:VK.CONTROL, s:VK.SUBTRACT])
677 call SendKey(s:VK.ESCAPE)
678 call ExecuteBufferedKeys()
679 call assert_equal('-', getline('$'))
680
681 %d _
682 imapclear
683 imap <C-_> BINGO
684 call SendKey(s:VK.KEY_I)
685 call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS])
686 call SendKey(s:VK.ESCAPE)
687 call ExecuteBufferedKeys()
688 call assert_equal('BINGO', getline('$'))
689
690 %d _
691 imapclear
692 exec "imap \x1f BILBO"
693 call SendKey(s:VK.KEY_I)
694 call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS])
695 call SendKey(s:VK.ESCAPE)
696 call ExecuteBufferedKeys()
697 call assert_equal('BILBO', getline('$'))
698
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000699 imapclear
700 bw!
701endfunc
702
703" Test MS-Windows mouse events
Christopher Plewright566f76e2023-01-10 13:43:04 +0000704func Test_mswin_event_mouse()
Christopher Plewright20b795e2022-12-20 20:01:58 +0000705 CheckMSWindows
706 new
707
708 set mousemodel=extend
709 call test_override('no_query_mouse', 1)
710 call WaitForResponses()
711
712 let msg = ''
713
714 call setline(1, ['one two three', 'four five six'])
715
716 " Test mouse movement
717 " by default, no mouse move events are generated
718 " this setting enables it to generate move events
719 set mousemev
720
721 if !has('gui_running')
722 " console version needs a button pressed,
723 " otherwise it ignores mouse movements.
724 call MouseLeftClick(2, 3)
725 endif
726 call MSWinMouseEvent(0x700, 8, 13, 0, 0, 0)
727 if has('gui_running')
728 call feedkeys("\<Esc>", 'Lx!')
729 endif
730 let pos = getmousepos()
731 call assert_equal(8, pos.screenrow)
732 call assert_equal(13, pos.screencol)
733
734 if !has('gui_running')
735 call MouseLeftClick(2, 3)
736 call MSWinMouseEvent(0x700, 6, 4, 1, 0, 0)
737 let pos = getmousepos()
738 call assert_equal(6, pos.screenrow)
739 call assert_equal(4, pos.screencol)
740 endif
741
742 " test cells vs pixels
743 if has('gui_running')
744 let args = { }
745 let args.row = 9
Ken Takatad8cb1dd2024-01-12 18:09:43 +0100746 let args.col = 5
Christopher Plewright20b795e2022-12-20 20:01:58 +0000747 let args.move = 1
748 let args.cell = 1
749 call test_mswin_event("mouse", args)
750 call feedkeys("\<Esc>", 'Lx!')
751 let pos = getmousepos()
752 call assert_equal(9, pos.screenrow)
Ken Takatad8cb1dd2024-01-12 18:09:43 +0100753 call assert_equal(5, pos.screencol)
Christopher Plewright20b795e2022-12-20 20:01:58 +0000754
755 let args.cell = 0
756 call test_mswin_event("mouse", args)
757 call feedkeys("\<Esc>", 'Lx!')
758 let pos = getmousepos()
759 call assert_equal(1, pos.screenrow)
760 call assert_equal(1, pos.screencol)
761
762 unlet args
763 endif
764
765 " finish testing mouse movement
766 set mousemev&
767
768 " place the cursor using left click and release in normal mode
769 call MouseLeftClick(2, 4)
770 call MouseLeftRelease(2, 4)
771 if has('gui_running')
772 call feedkeys("\<Esc>", 'Lx!')
773 endif
774 call assert_equal([0, 2, 4, 0], getpos('.'))
775
776 " select and yank a word
777 let @" = ''
778 call MouseLeftClick(1, 9)
779 let args = #{button: 0, row: 1, col: 9, multiclick: 1, modifiers: 0}
780 call test_mswin_event('mouse', args)
781 call MouseLeftRelease(1, 9)
782 call feedkeys("y", 'Lx!')
783 call assert_equal('three', @")
784
785 " create visual selection using right click
786 let @" = ''
787
788 call MouseLeftClick(2 ,6)
789 call MouseLeftRelease(2, 6)
790 call MouseRightClick(2, 13)
791 call MouseRightRelease(2, 13)
792 call feedkeys("y", 'Lx!')
793 call assert_equal('five six', @")
794
795 " paste using middle mouse button
796 let @* = 'abc '
797 call feedkeys('""', 'Lx!')
798 call MouseMiddleClick(1, 9)
799 call MouseMiddleRelease(1, 9)
800 if has('gui_running')
801 call feedkeys("\<Esc>", 'Lx!')
802 endif
803 call assert_equal(['one two abc three', 'four five six'], getline(1, '$'))
804
805 " test mouse scrolling (aka touchpad scrolling.)
806 %d _
807 set scrolloff=0
808 call setline(1, range(1, 100))
809
810 " Scroll Down
811 call MouseWheelDown(2, 1)
812 call MouseWheelDown(2, 1)
813 call MouseWheelDown(2, 1)
814 call feedkeys("H", 'Lx!')
815 call assert_equal(10, line('.'))
816
817 " Scroll Up
818 call MouseWheelUp(2, 1)
819 call MouseWheelUp(2, 1)
820 call feedkeys("H", 'Lx!')
821 call assert_equal(4, line('.'))
822
823 " Shift Scroll Down
824 call MouseShiftWheelDown(2, 1)
825 call feedkeys("H", 'Lx!')
826 " should scroll from where it is (4) + visible buffer height - cmdheight
Bram Moolenaar94722c52023-01-28 19:19:03 +0000827 let shift_scroll_height = line('w$') - line('w0') - &cmdheight
Christopher Plewright20b795e2022-12-20 20:01:58 +0000828 call assert_equal(4 + shift_scroll_height, line('.'))
829
830 " Shift Scroll Up
831 call MouseShiftWheelUp(2, 1)
832 call feedkeys("H", 'Lx!')
833 call assert_equal(4, line('.'))
834
835 if !has('gui_running')
836 " Shift Scroll Down (using MOD)
837 call MSWinMouseEvent(0x100, 2, 1, 0, 0, 0x04)
838 call feedkeys("H", 'Lx!')
839 " should scroll from where it is (4) + visible buffer height - cmdheight
Bram Moolenaar94722c52023-01-28 19:19:03 +0000840 let shift_scroll_height = line('w$') - line('w0') - &cmdheight
Christopher Plewright20b795e2022-12-20 20:01:58 +0000841 call assert_equal(4 + shift_scroll_height, line('.'))
842
843 " Shift Scroll Up (using MOD)
844 call MSWinMouseEvent(0x200, 2, 1, 0, 0, 0x04)
845 call feedkeys("H", 'Lx!')
846 call assert_equal(4, line('.'))
847 endif
848
849 set scrolloff&
850
851 %d _
852 set nowrap
853 " make the buffer 500 wide.
854 call setline(1, range(10)->join('')->repeat(50))
855 " Scroll Right
856 call MouseWheelRight(1, 5)
857 call MouseWheelRight(1, 10)
858 call MouseWheelRight(1, 15)
859 call feedkeys('g0', 'Lx!')
860 call assert_equal(19, col('.'))
861
862 " Scroll Left
863 call MouseWheelLeft(1, 15)
864 call MouseWheelLeft(1, 10)
865 call feedkeys('g0', 'Lx!')
866 call assert_equal(7, col('.'))
867
868 " Shift Scroll Right
869 call MouseShiftWheelRight(1, 10)
870 call feedkeys('g0', 'Lx!')
871 " should scroll from where it is (7) + window width
872 call assert_equal(7 + winwidth(0), col('.'))
Bram Moolenaar94722c52023-01-28 19:19:03 +0000873
Christopher Plewright20b795e2022-12-20 20:01:58 +0000874 " Shift Scroll Left
875 call MouseShiftWheelLeft(1, 50)
876 call feedkeys('g0', 'Lx!')
877 call assert_equal(7, col('.'))
878 set wrap&
879
880 %d _
881 call setline(1, repeat([repeat('a', 60)], 10))
882
883 " record various mouse events
884 let mouseEventNames = [
885 \ 'LeftMouse', 'LeftRelease', '2-LeftMouse', '3-LeftMouse',
886 \ 'S-LeftMouse', 'A-LeftMouse', 'C-LeftMouse', 'MiddleMouse',
887 \ 'MiddleRelease', '2-MiddleMouse', '3-MiddleMouse',
888 \ 'S-MiddleMouse', 'A-MiddleMouse', 'C-MiddleMouse',
889 \ 'RightMouse', 'RightRelease', '2-RightMouse',
890 \ '3-RightMouse', 'S-RightMouse', 'A-RightMouse', 'C-RightMouse',
891 \ ]
892 let mouseEventCodes = map(copy(mouseEventNames), "'<' .. v:val .. '>'")
893 let g:events = []
894 for e in mouseEventCodes
895 exe 'nnoremap ' .. e .. ' <Cmd>call add(g:events, "' ..
896 \ substitute(e, '[<>]', '', 'g') .. '")<CR>'
897 endfor
898
Bram Moolenaar94722c52023-01-28 19:19:03 +0000899 " Test various mouse buttons
900 "(0 - Left, 1 - Middle, 2 - Right,
Christopher Plewright20b795e2022-12-20 20:01:58 +0000901 " 0x300 - MOUSE_X1/FROM_LEFT_3RD_BUTTON,
902 " 0x400 - MOUSE_X2/FROM_LEFT_4TH_BUTTON)
903 for button in [0, 1, 2, 0x300, 0x400]
904 " Single click
905 let args = #{button: button, row: 2, col: 5, multiclick: 0, modifiers: 0}
906 call test_mswin_event('mouse', args)
907 let args.button = 3
908 call test_mswin_event('mouse', args)
909
910 " Double Click
911 let args.button = button
912 call test_mswin_event('mouse', args)
913 let args.multiclick = 1
914 call test_mswin_event('mouse', args)
915 let args.button = 3
916 let args.multiclick = 0
917 call test_mswin_event('mouse', args)
918
919 " Triple Click
920 let args.button = button
921 call test_mswin_event('mouse', args)
922 let args.multiclick = 1
923 call test_mswin_event('mouse', args)
924 call test_mswin_event('mouse', args)
925 let args.button = 3
926 let args.multiclick = 0
927 call test_mswin_event('mouse', args)
928
929 " Shift click
930 let args = #{button: button, row: 3, col: 7, multiclick: 0, modifiers: 4}
931 call test_mswin_event('mouse', args)
932 let args.button = 3
933 call test_mswin_event('mouse', args)
934
935 " Alt click
936 let args.button = button
937 let args.modifiers = 8
938 call test_mswin_event('mouse', args)
939 let args.button = 3
940 call test_mswin_event('mouse', args)
941
942 " Ctrl click
943 let args.button = button
944 let args.modifiers = 16
945 call test_mswin_event('mouse', args)
946 let args.button = 3
947 call test_mswin_event('mouse', args)
948
949 call feedkeys("\<Esc>", 'Lx!')
950 endfor
951
952 if has('gui_running')
953 call assert_equal(['LeftMouse', 'LeftRelease', 'LeftMouse',
954 \ '2-LeftMouse', 'LeftMouse', '2-LeftMouse', '3-LeftMouse',
955 \ 'S-LeftMouse', 'A-LeftMouse', 'C-LeftMouse', 'MiddleMouse',
956 \ 'MiddleRelease', 'MiddleMouse', '2-MiddleMouse', 'MiddleMouse',
957 \ '2-MiddleMouse', '3-MiddleMouse', 'S-MiddleMouse', 'A-MiddleMouse',
958 \ 'C-MiddleMouse', 'RightMouse', 'RightRelease', 'RightMouse',
959 \ '2-RightMouse', 'RightMouse', '2-RightMouse', '3-RightMouse',
960 \ 'S-RightMouse', 'A-RightMouse', 'C-RightMouse'],
961 \ g:events)
962 else
963 call assert_equal(['MiddleRelease', 'LeftMouse', '2-LeftMouse',
964 \ '3-LeftMouse', 'S-LeftMouse', 'MiddleMouse', '2-MiddleMouse',
965 \ '3-MiddleMouse', 'MiddleMouse', 'S-MiddleMouse', 'RightMouse',
966 \ '2-RightMouse', '3-RightMouse'],
967 \ g:events)
968 endif
969
970 for e in mouseEventCodes
971 exe 'nunmap ' .. e
972 endfor
973
974 bw!
975 call test_override('no_query_mouse', 0)
976 set mousemodel&
977endfunc
978
979
980" Test MS-Windows test_mswin_event error handling
981func Test_mswin_event_error_handling()
982
983 let args = #{button: 0xfff, row: 2, col: 4, move: 0, multiclick: 0, modifiers: 0}
984 if !has('gui_running')
985 call assert_fails("call test_mswin_event('mouse', args)",'E475:')
986 endif
987 let args = #{button: 0, row: 2, col: 4, move: 0, multiclick: 0, modifiers: 0}
988 call assert_fails("call test_mswin_event('a1b2c3', args)", 'E475:')
989 call assert_fails("call test_mswin_event(test_null_string(), {})", 'E475:')
Bram Moolenaar94722c52023-01-28 19:19:03 +0000990
Christopher Plewright20b795e2022-12-20 20:01:58 +0000991 call assert_fails("call test_mswin_event([], args)", 'E1174:')
992 call assert_fails("call test_mswin_event('abc', [])", 'E1206:')
Bram Moolenaar94722c52023-01-28 19:19:03 +0000993
Christopher Plewright20b795e2022-12-20 20:01:58 +0000994 call assert_false(test_mswin_event('mouse', test_null_dict()))
995 let args = #{row: 2, col: 4, multiclick: 0, modifiers: 0}
996 call assert_false(test_mswin_event('mouse', args))
997 let args = #{button: 0, col: 4, multiclick: 0, modifiers: 0}
998 call assert_false(test_mswin_event('mouse', args))
999 let args = #{button: 0, row: 2, multiclick: 0, modifiers: 0}
1000 call assert_false(test_mswin_event('mouse', args))
1001 let args = #{button: 0, row: 2, col: 4, modifiers: 0}
1002 call assert_false(test_mswin_event('mouse', args))
1003 let args = #{button: 0, row: 2, col: 4, multiclick: 0}
1004 call assert_false(test_mswin_event('mouse', args))
1005
1006 call assert_false(test_mswin_event('key', test_null_dict()))
1007 call assert_fails("call test_mswin_event('key', [])", 'E1206:')
1008 call assert_fails("call test_mswin_event('key', {'event': 'keydown', 'keycode': 0x0})", 'E1291:')
1009 call assert_fails("call test_mswin_event('key', {'event': 'keydown', 'keycode': [15]})", 'E745:')
1010 call assert_fails("call test_mswin_event('key', {'event': 'keys', 'keycode': 0x41})", 'E475:')
1011 call assert_fails("call test_mswin_event('key', {'keycode': 0x41})", 'E417:')
1012 call assert_fails("call test_mswin_event('key', {'event': 'keydown'})", 'E1291:')
1013
1014 call assert_fails("sandbox call test_mswin_event('key', {'event': 'keydown', 'keycode': 61 })", 'E48:')
1015
Christopher Plewright566f76e2023-01-10 13:43:04 +00001016 " flush out the typeahead buffer
Christopher Plewright20b795e2022-12-20 20:01:58 +00001017 while getchar(0)
1018 endwhile
1019endfunc
1020
1021
1022" vim: shiftwidth=2 sts=2 expandtab