blob: 10e7a812e0655382302998e40974ede20f7631c4 [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
471 " Test for <Ctrl-A> to <Ctrl-Z> keys
Christopher Plewright20b795e2022-12-20 20:01:58 +0000472 " Expect the unicode characters 0x01 to 0x1A
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000473 for modkey in [s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL]
Christopher Plewright20b795e2022-12-20 20:01:58 +0000474 for kc in range(65, 90)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000475 call SendKeyGroup([modkey, kc])
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100476 let ch = Getcharstr()
Christopher Plewright20b795e2022-12-20 20:01:58 +0000477 call assert_equal(nr2char(kc - 64), ch)
Christopher Plewright566f76e2023-01-10 13:43:04 +0000478 call SendKeyWithModifiers(kc, s:MOD_MASK_CTRL)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100479 let ch = Getcharstr()
Christopher Plewright20b795e2022-12-20 20:01:58 +0000480 call assert_equal(nr2char(kc - 64), ch)
481 endfor
482 endfor
483
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000484 " Windows intercepts some of these keys in the GUI.
Christopher Plewright20b795e2022-12-20 20:01:58 +0000485 if !has("gui_running")
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000486 " Test for <Alt-A> to <Alt-Z> keys
Christopher Plewright20b795e2022-12-20 20:01:58 +0000487 " Expect the unicode characters 0xE1 to 0xFA
488 " ie. 160 higher than the lowercase equivalent
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000489 for modkey in [s:VK.ALT, s:VK.LALT, s:VK.RALT]
490 for kc in range(65, 90)
491 call SendKeyGroup([modkey, kc])
492 let ch = getchar(0)
493 call assert_equal(kc+160, ch)
Christopher Plewright566f76e2023-01-10 13:43:04 +0000494 call SendKeyWithModifiers(kc, s:MOD_MASK_ALT)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000495 let ch = getchar(0)
496 call assert_equal(kc+160, ch)
497 endfor
Christopher Plewright20b795e2022-12-20 20:01:58 +0000498 endfor
499 endif
500
Christopher Plewright566f76e2023-01-10 13:43:04 +0000501endfun
502
Christopher Plewrightc8b20492023-01-04 18:06:00 +0000503 " Test for Function Keys 'F1' to 'F12'
504 " VK codes 112(0x70) - 123(0x7B)
505 " Also with ALL permutatios of modifiers; Shift, Ctrl & Alt
Christopher Plewright566f76e2023-01-10 13:43:04 +0000506func Test_mswin_event_function_keys()
507
508 if has('gui_running')
509 let g:test_is_flaky = 1
510 endif
511
512 " NOTE: Windows intercepts these combinations in the GUI
513 let gui_nogo = ["A-F1", "A-F2", "A-F3", "A-F4", "A-S-F4", "A-C-S-F4",
514 \ "A-F5", "A-F6", "A-F7", "A-F8", "A-C-F8", "A-F9",
515 \ "A-F10", "A-F11" , "A-C-F11", "A-C-F12"]
516
517 " flush out the typeahead buffer
518 while getchar(0)
519 endwhile
520
521 for [mod_str, vim_mod_mask, mod_keycodes] in s:vim_key_modifiers
522 for n in range(1, 12)
523 let expected_mod_mask = vim_mod_mask
524 let kstr = $"{mod_str}F{n}"
525 if !has('gui_running') || (has('gui_running') && n != 10
526 \ && index(gui_nogo, kstr) == -1)
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000527 let keycode = eval('"\<' .. kstr .. '>"')
Christopher Plewright566f76e2023-01-10 13:43:04 +0000528 " flush out the typeahead buffer
Christopher Plewrightc8b20492023-01-04 18:06:00 +0000529 while getchar(0)
530 endwhile
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000531 call SendKeyWithModifiers(111+n, vim_mod_mask)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100532 let ch = Getcharstr()
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000533 let mod_mask = getcharmod()
Christopher Plewrightc8b20492023-01-04 18:06:00 +0000534 call assert_equal(keycode, $"{ch}", $"key = {kstr}")
Christopher Plewright566f76e2023-01-10 13:43:04 +0000535 " workaround for the virtual termcap maps changing the character
536 "instead of sending Shift
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000537 for mod_key in mod_keycodes
538 if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], mod_key) >= 0
Christopher Plewright566f76e2023-01-10 13:43:04 +0000539 let expected_mod_mask -= s:MOD_MASK_SHIFT
540 break
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000541 endif
542 endfor
Christopher Plewright566f76e2023-01-10 13:43:04 +0000543 call assert_equal(expected_mod_mask, mod_mask, $"mod = {expected_mod_mask} for key = {kstr}")
544 endif
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000545 endfor
Christopher Plewright566f76e2023-01-10 13:43:04 +0000546 endfor
547endfunc
548
549func ExtractModifiers(mod_keycodes)
550 let has_shift = 0
551 let has_ctrl = 0
552 let has_alt = 0
553 for mod_key in a:mod_keycodes
554 if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], mod_key) >= 0
555 let has_shift = 1
556 endif
557 if index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], mod_key) >= 0
558 let has_ctrl = 1
559 endif
560 if index([s:VK.MENU, s:VK.LMENU, s:VK.RMENU], mod_key) >= 0
561 let has_alt = 1
562 endif
563 endfor
564 return [has_shift, has_ctrl, has_alt]
565endfunc
566
567 " Test for Movement Keys;
568 " VK_PRIOR 0x21, VK_NEXT 0x22,
569 " VK_END 0x23, VK_HOME 0x24,
570 " VK_LEFT 0x25, VK_UP 0x26,
571 " VK_RIGHT 0x27, VK_DOWN 0x28
572 " With ALL permutations of modifiers; none, Shift, Ctrl & Alt
573func Test_mswin_event_movement_keys()
574
575 if has('gui_running')
576 let g:test_is_flaky = 1
Christopher Plewright20b795e2022-12-20 20:01:58 +0000577 endif
578
Christopher Plewright566f76e2023-01-10 13:43:04 +0000579 let movement_keys = [
580 \ [s:VK.PRIOR, "PageUp"],
581 \ [s:VK.NEXT, "PageDown"],
582 \ [s:VK.END, "End"],
583 \ [s:VK.HOME, "Home"],
584 \ [s:VK.LEFT, "Left"],
585 \ [s:VK.UP, "Up"],
586 \ [s:VK.RIGHT, "Right"],
587 \ [s:VK.DOWN, "Down"],
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000588 \ ]
589
Christopher Plewright566f76e2023-01-10 13:43:04 +0000590 " flush out the typeahead buffer
591 while getchar(0)
592 endwhile
593
594 for [mod_str, vim_mod_mask, mod_keycodes] in s:vim_key_modifiers
595 for [kcode, kname] in movement_keys
596 let exp_mod_mask = vim_mod_mask
597 let kstr = $"{mod_str}{kname}"
598 let chstr_eval = eval('"\<' .. kstr .. '>"')
599
600 " flush out the typeahead buffer
601 while getchar(0)
602 endwhile
603 execute 'call feedkeys("\<' .. kstr .. '>")'
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100604 let chstr_fk = Getcharstr()
Christopher Plewright566f76e2023-01-10 13:43:04 +0000605 call assert_equal(chstr_eval, chstr_fk, $"feedkeys = <{kstr}>")
606
607 " flush out the typeahead buffer
608 while getchar(0)
609 endwhile
610 call SendKey(kcode)
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100611 let chstr_alone = Getcharstr()
Christopher Plewright566f76e2023-01-10 13:43:04 +0000612 let chstr_alone_end = chstr_alone[len(chstr_alone)-2:len(chstr_alone)-1]
613
614 " flush out the typeahead buffer
615 while getchar(0)
616 endwhile
617 call SendKeyGroup(mod_keycodes + [kcode])
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100618 let chstr_mswin = Getcharstr()
Christopher Plewright566f76e2023-01-10 13:43:04 +0000619 let chstr_mswin_end = chstr_mswin[len(chstr_mswin)-2:len(chstr_mswin)-1]
620 let mod_mask = getcharmod()
621
622 " The virtual termcap maps may** change the character and either;
623 " - remove the Shift modifier, or
624 " - remove the Ctrl modifier if the Shift modifier was not removed.
625 let [has_shift, has_ctrl, has_alt] = ExtractModifiers(mod_keycodes)
626 if chstr_alone_end != chstr_mswin_end
627 if has_shift != 0
628 let exp_mod_mask -= s:MOD_MASK_SHIFT
629 elseif has_ctrl != 0
630 let exp_mod_mask -= s:MOD_MASK_CTRL
631 endif
632 endif
633 " **Note: The appveyor Windows GUI test environments, from VS2017 on,
634 " consistently intercepts the Shift modifier WITHOUT changing the
635 " MOVEMENT character. This issue does not happen in any github actions
636 " CI Windows test environments. Attempted to reproduce this manually
637 " on Windows versions; 7, 8.1, 10, 11, Server 2019 and Server 2022, but
638 " the issue did not occur on any of those environments.
639 " Below is a workaround for the issue.
640 if has('gui_running') && has_shift != 0
641 if exp_mod_mask != mod_mask && chstr_eval != chstr_mswin
642 let kstr_sub = substitute(kstr, "S-", "", "")
643 let chstr_eval = eval('"\<' .. kstr_sub .. '>"')
644 if exp_mod_mask - s:MOD_MASK_SHIFT == mod_mask
645 let exp_mod_mask -= s:MOD_MASK_SHIFT
646 elseif has_ctrl != 0 && exp_mod_mask - s:MOD_MASK_CTRL == mod_mask
647 let exp_mod_mask -= s:MOD_MASK_CTRL
648 endif
649 endif
650 endif
651 call assert_equal(chstr_eval, chstr_mswin, $"key = {kstr}")
652 call assert_equal(exp_mod_mask, mod_mask, $"mod_mask for key = {kstr}")
653 endfor
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000654 endfor
655
Christopher Plewright20b795e2022-12-20 20:01:58 +0000656 bw!
657endfunc
658
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000659
660" Test for QWERTY Ctrl+- which should result in ^_
661" issue #10817
662func Test_QWERTY_Ctrl_minus()
663 CheckMSWindows
664 new
665
666 call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS])
Christian Brabandtf6ebaa72024-01-25 20:44:49 +0100667 let ch = Getcharstr()
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000668 call assert_equal(nr2char(0x1f),ch)
669
670 call SendKey(s:VK.KEY_I)
671 call SendKeyGroup([s:VK.CONTROL, s:VK.SUBTRACT])
672 call SendKey(s:VK.ESCAPE)
673 call ExecuteBufferedKeys()
674 call assert_equal('-', getline('$'))
675
676 %d _
677 imapclear
678 imap <C-_> BINGO
679 call SendKey(s:VK.KEY_I)
680 call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS])
681 call SendKey(s:VK.ESCAPE)
682 call ExecuteBufferedKeys()
683 call assert_equal('BINGO', getline('$'))
684
685 %d _
686 imapclear
687 exec "imap \x1f BILBO"
688 call SendKey(s:VK.KEY_I)
689 call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS])
690 call SendKey(s:VK.ESCAPE)
691 call ExecuteBufferedKeys()
692 call assert_equal('BILBO', getline('$'))
693
Christopher Plewright7b0afc12022-12-30 16:54:58 +0000694 imapclear
695 bw!
696endfunc
697
698" Test MS-Windows mouse events
Christopher Plewright566f76e2023-01-10 13:43:04 +0000699func Test_mswin_event_mouse()
Christopher Plewright20b795e2022-12-20 20:01:58 +0000700 CheckMSWindows
701 new
702
703 set mousemodel=extend
704 call test_override('no_query_mouse', 1)
705 call WaitForResponses()
706
707 let msg = ''
708
709 call setline(1, ['one two three', 'four five six'])
710
711 " Test mouse movement
712 " by default, no mouse move events are generated
713 " this setting enables it to generate move events
714 set mousemev
715
716 if !has('gui_running')
717 " console version needs a button pressed,
718 " otherwise it ignores mouse movements.
719 call MouseLeftClick(2, 3)
720 endif
721 call MSWinMouseEvent(0x700, 8, 13, 0, 0, 0)
722 if has('gui_running')
723 call feedkeys("\<Esc>", 'Lx!')
724 endif
725 let pos = getmousepos()
726 call assert_equal(8, pos.screenrow)
727 call assert_equal(13, pos.screencol)
728
729 if !has('gui_running')
730 call MouseLeftClick(2, 3)
731 call MSWinMouseEvent(0x700, 6, 4, 1, 0, 0)
732 let pos = getmousepos()
733 call assert_equal(6, pos.screenrow)
734 call assert_equal(4, pos.screencol)
735 endif
736
737 " test cells vs pixels
738 if has('gui_running')
739 let args = { }
740 let args.row = 9
Ken Takatad8cb1dd2024-01-12 18:09:43 +0100741 let args.col = 5
Christopher Plewright20b795e2022-12-20 20:01:58 +0000742 let args.move = 1
743 let args.cell = 1
744 call test_mswin_event("mouse", args)
745 call feedkeys("\<Esc>", 'Lx!')
746 let pos = getmousepos()
747 call assert_equal(9, pos.screenrow)
Ken Takatad8cb1dd2024-01-12 18:09:43 +0100748 call assert_equal(5, pos.screencol)
Christopher Plewright20b795e2022-12-20 20:01:58 +0000749
750 let args.cell = 0
751 call test_mswin_event("mouse", args)
752 call feedkeys("\<Esc>", 'Lx!')
753 let pos = getmousepos()
754 call assert_equal(1, pos.screenrow)
755 call assert_equal(1, pos.screencol)
756
757 unlet args
758 endif
759
760 " finish testing mouse movement
761 set mousemev&
762
763 " place the cursor using left click and release in normal mode
764 call MouseLeftClick(2, 4)
765 call MouseLeftRelease(2, 4)
766 if has('gui_running')
767 call feedkeys("\<Esc>", 'Lx!')
768 endif
769 call assert_equal([0, 2, 4, 0], getpos('.'))
770
771 " select and yank a word
772 let @" = ''
773 call MouseLeftClick(1, 9)
774 let args = #{button: 0, row: 1, col: 9, multiclick: 1, modifiers: 0}
775 call test_mswin_event('mouse', args)
776 call MouseLeftRelease(1, 9)
777 call feedkeys("y", 'Lx!')
778 call assert_equal('three', @")
779
780 " create visual selection using right click
781 let @" = ''
782
783 call MouseLeftClick(2 ,6)
784 call MouseLeftRelease(2, 6)
785 call MouseRightClick(2, 13)
786 call MouseRightRelease(2, 13)
787 call feedkeys("y", 'Lx!')
788 call assert_equal('five six', @")
789
790 " paste using middle mouse button
791 let @* = 'abc '
792 call feedkeys('""', 'Lx!')
793 call MouseMiddleClick(1, 9)
794 call MouseMiddleRelease(1, 9)
795 if has('gui_running')
796 call feedkeys("\<Esc>", 'Lx!')
797 endif
798 call assert_equal(['one two abc three', 'four five six'], getline(1, '$'))
799
800 " test mouse scrolling (aka touchpad scrolling.)
801 %d _
802 set scrolloff=0
803 call setline(1, range(1, 100))
804
805 " Scroll Down
806 call MouseWheelDown(2, 1)
807 call MouseWheelDown(2, 1)
808 call MouseWheelDown(2, 1)
809 call feedkeys("H", 'Lx!')
810 call assert_equal(10, line('.'))
811
812 " Scroll Up
813 call MouseWheelUp(2, 1)
814 call MouseWheelUp(2, 1)
815 call feedkeys("H", 'Lx!')
816 call assert_equal(4, line('.'))
817
818 " Shift Scroll Down
819 call MouseShiftWheelDown(2, 1)
820 call feedkeys("H", 'Lx!')
821 " should scroll from where it is (4) + visible buffer height - cmdheight
Bram Moolenaar94722c52023-01-28 19:19:03 +0000822 let shift_scroll_height = line('w$') - line('w0') - &cmdheight
Christopher Plewright20b795e2022-12-20 20:01:58 +0000823 call assert_equal(4 + shift_scroll_height, line('.'))
824
825 " Shift Scroll Up
826 call MouseShiftWheelUp(2, 1)
827 call feedkeys("H", 'Lx!')
828 call assert_equal(4, line('.'))
829
830 if !has('gui_running')
831 " Shift Scroll Down (using MOD)
832 call MSWinMouseEvent(0x100, 2, 1, 0, 0, 0x04)
833 call feedkeys("H", 'Lx!')
834 " should scroll from where it is (4) + visible buffer height - cmdheight
Bram Moolenaar94722c52023-01-28 19:19:03 +0000835 let shift_scroll_height = line('w$') - line('w0') - &cmdheight
Christopher Plewright20b795e2022-12-20 20:01:58 +0000836 call assert_equal(4 + shift_scroll_height, line('.'))
837
838 " Shift Scroll Up (using MOD)
839 call MSWinMouseEvent(0x200, 2, 1, 0, 0, 0x04)
840 call feedkeys("H", 'Lx!')
841 call assert_equal(4, line('.'))
842 endif
843
844 set scrolloff&
845
846 %d _
847 set nowrap
848 " make the buffer 500 wide.
849 call setline(1, range(10)->join('')->repeat(50))
850 " Scroll Right
851 call MouseWheelRight(1, 5)
852 call MouseWheelRight(1, 10)
853 call MouseWheelRight(1, 15)
854 call feedkeys('g0', 'Lx!')
855 call assert_equal(19, col('.'))
856
857 " Scroll Left
858 call MouseWheelLeft(1, 15)
859 call MouseWheelLeft(1, 10)
860 call feedkeys('g0', 'Lx!')
861 call assert_equal(7, col('.'))
862
863 " Shift Scroll Right
864 call MouseShiftWheelRight(1, 10)
865 call feedkeys('g0', 'Lx!')
866 " should scroll from where it is (7) + window width
867 call assert_equal(7 + winwidth(0), col('.'))
Bram Moolenaar94722c52023-01-28 19:19:03 +0000868
Christopher Plewright20b795e2022-12-20 20:01:58 +0000869 " Shift Scroll Left
870 call MouseShiftWheelLeft(1, 50)
871 call feedkeys('g0', 'Lx!')
872 call assert_equal(7, col('.'))
873 set wrap&
874
875 %d _
876 call setline(1, repeat([repeat('a', 60)], 10))
877
878 " record various mouse events
879 let mouseEventNames = [
880 \ 'LeftMouse', 'LeftRelease', '2-LeftMouse', '3-LeftMouse',
881 \ 'S-LeftMouse', 'A-LeftMouse', 'C-LeftMouse', 'MiddleMouse',
882 \ 'MiddleRelease', '2-MiddleMouse', '3-MiddleMouse',
883 \ 'S-MiddleMouse', 'A-MiddleMouse', 'C-MiddleMouse',
884 \ 'RightMouse', 'RightRelease', '2-RightMouse',
885 \ '3-RightMouse', 'S-RightMouse', 'A-RightMouse', 'C-RightMouse',
886 \ ]
887 let mouseEventCodes = map(copy(mouseEventNames), "'<' .. v:val .. '>'")
888 let g:events = []
889 for e in mouseEventCodes
890 exe 'nnoremap ' .. e .. ' <Cmd>call add(g:events, "' ..
891 \ substitute(e, '[<>]', '', 'g') .. '")<CR>'
892 endfor
893
Bram Moolenaar94722c52023-01-28 19:19:03 +0000894 " Test various mouse buttons
895 "(0 - Left, 1 - Middle, 2 - Right,
Christopher Plewright20b795e2022-12-20 20:01:58 +0000896 " 0x300 - MOUSE_X1/FROM_LEFT_3RD_BUTTON,
897 " 0x400 - MOUSE_X2/FROM_LEFT_4TH_BUTTON)
898 for button in [0, 1, 2, 0x300, 0x400]
899 " Single click
900 let args = #{button: button, row: 2, col: 5, multiclick: 0, modifiers: 0}
901 call test_mswin_event('mouse', args)
902 let args.button = 3
903 call test_mswin_event('mouse', args)
904
905 " Double Click
906 let args.button = button
907 call test_mswin_event('mouse', args)
908 let args.multiclick = 1
909 call test_mswin_event('mouse', args)
910 let args.button = 3
911 let args.multiclick = 0
912 call test_mswin_event('mouse', args)
913
914 " Triple Click
915 let args.button = button
916 call test_mswin_event('mouse', args)
917 let args.multiclick = 1
918 call test_mswin_event('mouse', args)
919 call test_mswin_event('mouse', args)
920 let args.button = 3
921 let args.multiclick = 0
922 call test_mswin_event('mouse', args)
923
924 " Shift click
925 let args = #{button: button, row: 3, col: 7, multiclick: 0, modifiers: 4}
926 call test_mswin_event('mouse', args)
927 let args.button = 3
928 call test_mswin_event('mouse', args)
929
930 " Alt click
931 let args.button = button
932 let args.modifiers = 8
933 call test_mswin_event('mouse', args)
934 let args.button = 3
935 call test_mswin_event('mouse', args)
936
937 " Ctrl click
938 let args.button = button
939 let args.modifiers = 16
940 call test_mswin_event('mouse', args)
941 let args.button = 3
942 call test_mswin_event('mouse', args)
943
944 call feedkeys("\<Esc>", 'Lx!')
945 endfor
946
947 if has('gui_running')
948 call assert_equal(['LeftMouse', 'LeftRelease', 'LeftMouse',
949 \ '2-LeftMouse', 'LeftMouse', '2-LeftMouse', '3-LeftMouse',
950 \ 'S-LeftMouse', 'A-LeftMouse', 'C-LeftMouse', 'MiddleMouse',
951 \ 'MiddleRelease', 'MiddleMouse', '2-MiddleMouse', 'MiddleMouse',
952 \ '2-MiddleMouse', '3-MiddleMouse', 'S-MiddleMouse', 'A-MiddleMouse',
953 \ 'C-MiddleMouse', 'RightMouse', 'RightRelease', 'RightMouse',
954 \ '2-RightMouse', 'RightMouse', '2-RightMouse', '3-RightMouse',
955 \ 'S-RightMouse', 'A-RightMouse', 'C-RightMouse'],
956 \ g:events)
957 else
958 call assert_equal(['MiddleRelease', 'LeftMouse', '2-LeftMouse',
959 \ '3-LeftMouse', 'S-LeftMouse', 'MiddleMouse', '2-MiddleMouse',
960 \ '3-MiddleMouse', 'MiddleMouse', 'S-MiddleMouse', 'RightMouse',
961 \ '2-RightMouse', '3-RightMouse'],
962 \ g:events)
963 endif
964
965 for e in mouseEventCodes
966 exe 'nunmap ' .. e
967 endfor
968
969 bw!
970 call test_override('no_query_mouse', 0)
971 set mousemodel&
972endfunc
973
974
975" Test MS-Windows test_mswin_event error handling
976func Test_mswin_event_error_handling()
977
978 let args = #{button: 0xfff, row: 2, col: 4, move: 0, multiclick: 0, modifiers: 0}
979 if !has('gui_running')
980 call assert_fails("call test_mswin_event('mouse', args)",'E475:')
981 endif
982 let args = #{button: 0, row: 2, col: 4, move: 0, multiclick: 0, modifiers: 0}
983 call assert_fails("call test_mswin_event('a1b2c3', args)", 'E475:')
984 call assert_fails("call test_mswin_event(test_null_string(), {})", 'E475:')
Bram Moolenaar94722c52023-01-28 19:19:03 +0000985
Christopher Plewright20b795e2022-12-20 20:01:58 +0000986 call assert_fails("call test_mswin_event([], args)", 'E1174:')
987 call assert_fails("call test_mswin_event('abc', [])", 'E1206:')
Bram Moolenaar94722c52023-01-28 19:19:03 +0000988
Christopher Plewright20b795e2022-12-20 20:01:58 +0000989 call assert_false(test_mswin_event('mouse', test_null_dict()))
990 let args = #{row: 2, col: 4, multiclick: 0, modifiers: 0}
991 call assert_false(test_mswin_event('mouse', args))
992 let args = #{button: 0, col: 4, multiclick: 0, modifiers: 0}
993 call assert_false(test_mswin_event('mouse', args))
994 let args = #{button: 0, row: 2, multiclick: 0, modifiers: 0}
995 call assert_false(test_mswin_event('mouse', args))
996 let args = #{button: 0, row: 2, col: 4, modifiers: 0}
997 call assert_false(test_mswin_event('mouse', args))
998 let args = #{button: 0, row: 2, col: 4, multiclick: 0}
999 call assert_false(test_mswin_event('mouse', args))
1000
1001 call assert_false(test_mswin_event('key', test_null_dict()))
1002 call assert_fails("call test_mswin_event('key', [])", 'E1206:')
1003 call assert_fails("call test_mswin_event('key', {'event': 'keydown', 'keycode': 0x0})", 'E1291:')
1004 call assert_fails("call test_mswin_event('key', {'event': 'keydown', 'keycode': [15]})", 'E745:')
1005 call assert_fails("call test_mswin_event('key', {'event': 'keys', 'keycode': 0x41})", 'E475:')
1006 call assert_fails("call test_mswin_event('key', {'keycode': 0x41})", 'E417:')
1007 call assert_fails("call test_mswin_event('key', {'event': 'keydown'})", 'E1291:')
1008
1009 call assert_fails("sandbox call test_mswin_event('key', {'event': 'keydown', 'keycode': 61 })", 'E48:')
1010
Christopher Plewright566f76e2023-01-10 13:43:04 +00001011 " flush out the typeahead buffer
Christopher Plewright20b795e2022-12-20 20:01:58 +00001012 while getchar(0)
1013 endwhile
1014endfunc
1015
1016
1017" vim: shiftwidth=2 sts=2 expandtab