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