mouse_spec.lua 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local clear, feed, api = n.clear, n.feed, n.api
  5. local insert, feed_command = n.insert, n.feed_command
  6. local eq, fn = t.eq, n.fn
  7. local poke_eventloop = n.poke_eventloop
  8. local command = n.command
  9. local exec = n.exec
  10. describe('ui/mouse/input', function()
  11. local screen
  12. before_each(function()
  13. clear()
  14. api.nvim_set_option_value('mouse', 'a', {})
  15. api.nvim_set_option_value('list', true, {})
  16. -- NB: this is weird, but mostly irrelevant to the test
  17. -- So I didn't bother to change it
  18. command('set listchars=eol:$')
  19. command('setl listchars=nbsp:x')
  20. screen = Screen.new(25, 5)
  21. screen:add_extra_attr_ids {
  22. [100] = {
  23. bold = true,
  24. background = Screen.colors.LightGrey,
  25. foreground = Screen.colors.Blue1,
  26. },
  27. }
  28. command('set mousemodel=extend')
  29. feed('itesting<cr>mouse<cr>support and selection<esc>')
  30. screen:expect([[
  31. testing |
  32. mouse |
  33. support and selectio^n |
  34. {1:~ }|
  35. |
  36. ]])
  37. end)
  38. it('single left click moves cursor', function()
  39. feed('<LeftMouse><2,1>')
  40. screen:expect {
  41. grid = [[
  42. testing |
  43. mo^use |
  44. support and selection |
  45. {1:~ }|
  46. |
  47. ]],
  48. mouse_enabled = true,
  49. }
  50. feed('<LeftMouse><0,0>')
  51. screen:expect([[
  52. ^testing |
  53. mouse |
  54. support and selection |
  55. {1:~ }|
  56. |
  57. ]])
  58. end)
  59. it("in external ui works with unset 'mouse'", function()
  60. api.nvim_set_option_value('mouse', '', {})
  61. feed('<LeftMouse><2,1>')
  62. screen:expect {
  63. grid = [[
  64. testing |
  65. mo^use |
  66. support and selection |
  67. {1:~ }|
  68. |
  69. ]],
  70. mouse_enabled = false,
  71. }
  72. feed('<LeftMouse><0,0>')
  73. screen:expect([[
  74. ^testing |
  75. mouse |
  76. support and selection |
  77. {1:~ }|
  78. |
  79. ]])
  80. end)
  81. it('double left click enters visual mode', function()
  82. feed('<LeftMouse><0,0>')
  83. feed('<LeftRelease><0,0>')
  84. feed('<LeftMouse><0,0>')
  85. feed('<LeftRelease><0,0>')
  86. screen:expect([[
  87. {17:testin}^g |
  88. mouse |
  89. support and selection |
  90. {1:~ }|
  91. {5:-- VISUAL --} |
  92. ]])
  93. end)
  94. it('triple left click enters visual line mode', function()
  95. feed('<LeftMouse><0,0>')
  96. feed('<LeftRelease><0,0>')
  97. feed('<LeftMouse><0,0>')
  98. feed('<LeftRelease><0,0>')
  99. feed('<LeftMouse><0,0>')
  100. feed('<LeftRelease><0,0>')
  101. screen:expect([[
  102. ^t{17:esting} |
  103. mouse |
  104. support and selection |
  105. {1:~ }|
  106. {5:-- VISUAL LINE --} |
  107. ]])
  108. end)
  109. it('quadruple left click enters visual block mode', function()
  110. feed('<LeftMouse><0,0>')
  111. feed('<LeftRelease><0,0>')
  112. feed('<LeftMouse><0,0>')
  113. feed('<LeftRelease><0,0>')
  114. feed('<LeftMouse><0,0>')
  115. feed('<LeftRelease><0,0>')
  116. feed('<LeftMouse><0,0>')
  117. feed('<LeftRelease><0,0>')
  118. screen:expect([[
  119. ^testing |
  120. mouse |
  121. support and selection |
  122. {1:~ }|
  123. {5:-- VISUAL BLOCK --} |
  124. ]])
  125. end)
  126. describe('tab drag', function()
  127. it('in tabline on filler space moves tab to the end', function()
  128. feed_command('%delete')
  129. insert('this is foo')
  130. feed_command('silent file foo | tabnew | file bar')
  131. insert('this is bar')
  132. screen:expect([[
  133. {24: + foo }{5: + bar }{2: }{24:X}|
  134. this is ba^r{1:$} |
  135. {1:~ }|*2
  136. |
  137. ]])
  138. feed('<LeftMouse><4,0>')
  139. screen:expect([[
  140. {5: + foo }{24: + bar }{2: }{24:X}|
  141. this is fo^o |
  142. {1:~ }|*2
  143. |
  144. ]])
  145. feed('<LeftDrag><14,0>')
  146. screen:expect([[
  147. {24: + bar }{5: + foo }{2: }{24:X}|
  148. this is fo^o |
  149. {1:~ }|*2
  150. |
  151. ]])
  152. end)
  153. it('in tabline to the left moves tab left', function()
  154. feed_command('%delete')
  155. insert('this is foo')
  156. feed_command('silent file foo | tabnew | file bar')
  157. insert('this is bar')
  158. screen:expect([[
  159. {24: + foo }{5: + bar }{2: }{24:X}|
  160. this is ba^r{1:$} |
  161. {1:~ }|*2
  162. |
  163. ]])
  164. feed('<LeftMouse><11,0>')
  165. -- Prevent the case where screen:expect() with "unchanged" returns too early,
  166. -- causing the click position to be overwritten by the next drag.
  167. poke_eventloop()
  168. screen:expect {
  169. grid = [[
  170. {24: + foo }{5: + bar }{2: }{24:X}|
  171. this is ba^r{1:$} |
  172. {1:~ }|*2
  173. |
  174. ]],
  175. unchanged = true,
  176. }
  177. feed('<LeftDrag><6,0>')
  178. screen:expect([[
  179. {5: + bar }{24: + foo }{2: }{24:X}|
  180. this is ba^r{1:$} |
  181. {1:~ }|*2
  182. |
  183. ]])
  184. end)
  185. it('in tabline to the right moves tab right', function()
  186. feed_command('%delete')
  187. insert('this is foo')
  188. feed_command('silent file foo | tabnew | file bar')
  189. insert('this is bar')
  190. screen:expect([[
  191. {24: + foo }{5: + bar }{2: }{24:X}|
  192. this is ba^r{1:$} |
  193. {1:~ }|*2
  194. |
  195. ]])
  196. feed('<LeftMouse><4,0>')
  197. screen:expect([[
  198. {5: + foo }{24: + bar }{2: }{24:X}|
  199. this is fo^o |
  200. {1:~ }|*2
  201. |
  202. ]])
  203. feed('<LeftDrag><7,0>')
  204. screen:expect([[
  205. {24: + bar }{5: + foo }{2: }{24:X}|
  206. this is fo^o |
  207. {1:~ }|*2
  208. |
  209. ]])
  210. end)
  211. it('out of tabline under filler space moves tab to the end', function()
  212. feed_command('%delete')
  213. insert('this is foo')
  214. feed_command('silent file foo | tabnew | file bar')
  215. insert('this is bar')
  216. screen:expect([[
  217. {24: + foo }{5: + bar }{2: }{24:X}|
  218. this is ba^r{1:$} |
  219. {1:~ }|*2
  220. |
  221. ]])
  222. feed('<LeftMouse><4,0>')
  223. screen:expect([[
  224. {5: + foo }{24: + bar }{2: }{24:X}|
  225. this is fo^o |
  226. {1:~ }|*2
  227. |
  228. ]])
  229. feed('<LeftDrag><4,1>')
  230. screen:expect {
  231. grid = [[
  232. {5: + foo }{24: + bar }{2: }{24:X}|
  233. this is fo^o |
  234. {1:~ }|*2
  235. |
  236. ]],
  237. unchanged = true,
  238. }
  239. feed('<LeftDrag><14,1>')
  240. screen:expect([[
  241. {24: + bar }{5: + foo }{2: }{24:X}|
  242. this is fo^o |
  243. {1:~ }|*2
  244. |
  245. ]])
  246. end)
  247. it('out of tabline to the left moves tab left', function()
  248. feed_command('%delete')
  249. insert('this is foo')
  250. feed_command('silent file foo | tabnew | file bar')
  251. insert('this is bar')
  252. screen:expect([[
  253. {24: + foo }{5: + bar }{2: }{24:X}|
  254. this is ba^r{1:$} |
  255. {1:~ }|*2
  256. |
  257. ]])
  258. feed('<LeftMouse><11,0>')
  259. -- Prevent the case where screen:expect() with "unchanged" returns too early,
  260. -- causing the click position to be overwritten by the next drag.
  261. poke_eventloop()
  262. screen:expect {
  263. grid = [[
  264. {24: + foo }{5: + bar }{2: }{24:X}|
  265. this is ba^r{1:$} |
  266. {1:~ }|*2
  267. |
  268. ]],
  269. unchanged = true,
  270. }
  271. feed('<LeftDrag><11,1>')
  272. screen:expect {
  273. grid = [[
  274. {24: + foo }{5: + bar }{2: }{24:X}|
  275. this is ba^r{1:$} |
  276. {1:~ }|*2
  277. |
  278. ]],
  279. unchanged = true,
  280. }
  281. feed('<LeftDrag><6,1>')
  282. screen:expect([[
  283. {5: + bar }{24: + foo }{2: }{24:X}|
  284. this is ba^r{1:$} |
  285. {1:~ }|*2
  286. |
  287. ]])
  288. end)
  289. it('out of tabline to the right moves tab right', function()
  290. feed_command('%delete')
  291. insert('this is foo')
  292. feed_command('silent file foo | tabnew | file bar')
  293. insert('this is bar')
  294. screen:expect([[
  295. {24: + foo }{5: + bar }{2: }{24:X}|
  296. this is ba^r{1:$} |
  297. {1:~ }|*2
  298. |
  299. ]])
  300. feed('<LeftMouse><4,0>')
  301. screen:expect([[
  302. {5: + foo }{24: + bar }{2: }{24:X}|
  303. this is fo^o |
  304. {1:~ }|*2
  305. |
  306. ]])
  307. feed('<LeftDrag><4,1>')
  308. screen:expect {
  309. grid = [[
  310. {5: + foo }{24: + bar }{2: }{24:X}|
  311. this is fo^o |
  312. {1:~ }|*2
  313. |
  314. ]],
  315. unchanged = true,
  316. }
  317. feed('<LeftDrag><7,1>')
  318. screen:expect([[
  319. {24: + bar }{5: + foo }{2: }{24:X}|
  320. this is fo^o |
  321. {1:~ }|*2
  322. |
  323. ]])
  324. end)
  325. end)
  326. describe('tabline', function()
  327. it('left click in default tabline (tabpage label) switches to tab', function()
  328. feed_command('%delete')
  329. insert('this is foo')
  330. feed_command('silent file foo | tabnew | file bar')
  331. insert('this is bar')
  332. screen:expect([[
  333. {24: + foo }{5: + bar }{2: }{24:X}|
  334. this is ba^r{1:$} |
  335. {1:~ }|*2
  336. |
  337. ]])
  338. feed('<LeftMouse><4,0>')
  339. screen:expect([[
  340. {5: + foo }{24: + bar }{2: }{24:X}|
  341. this is fo^o |
  342. {1:~ }|*2
  343. |
  344. ]])
  345. feed('<LeftMouse><6,0>')
  346. screen:expect_unchanged()
  347. feed('<LeftMouse><10,0>')
  348. screen:expect([[
  349. {24: + foo }{5: + bar }{2: }{24:X}|
  350. this is ba^r{1:$} |
  351. {1:~ }|*2
  352. |
  353. ]])
  354. feed('<LeftMouse><12,0>')
  355. screen:expect_unchanged()
  356. end)
  357. it('left click in default tabline (blank space) switches tab', function()
  358. feed_command('%delete')
  359. insert('this is foo')
  360. feed_command('silent file foo | tabnew | file bar')
  361. insert('this is bar')
  362. screen:expect([[
  363. {24: + foo }{5: + bar }{2: }{24:X}|
  364. this is ba^r{1:$} |
  365. {1:~ }|*2
  366. |
  367. ]])
  368. feed('<LeftMouse><20,0>')
  369. screen:expect([[
  370. {5: + foo }{24: + bar }{2: }{24:X}|
  371. this is fo^o |
  372. {1:~ }|*2
  373. |
  374. ]])
  375. feed('<LeftMouse><22,0>')
  376. screen:expect([[
  377. {24: + foo }{5: + bar }{2: }{24:X}|
  378. this is ba^r{1:$} |
  379. {1:~ }|*2
  380. |
  381. ]])
  382. end)
  383. it('left click in default tabline (close label) closes tab', function()
  384. api.nvim_set_option_value('hidden', true, {})
  385. feed_command('%delete')
  386. insert('this is foo')
  387. feed_command('silent file foo | tabnew | file bar')
  388. insert('this is bar')
  389. screen:expect([[
  390. {24: + foo }{5: + bar }{2: }{24:X}|
  391. this is ba^r{1:$} |
  392. {1:~ }|*2
  393. |
  394. ]])
  395. feed('<LeftMouse><24,0>')
  396. screen:expect([[
  397. this is fo^o |
  398. {1:~ }|*3
  399. |
  400. ]])
  401. end)
  402. it('double click in default tabline opens new tab before', function()
  403. feed_command('%delete')
  404. insert('this is foo')
  405. feed_command('silent file foo | tabnew | file bar')
  406. insert('this is bar')
  407. screen:expect([[
  408. {24: + foo }{5: + bar }{2: }{24:X}|
  409. this is ba^r{1:$} |
  410. {1:~ }|*2
  411. |
  412. ]])
  413. feed('<2-LeftMouse><4,0>')
  414. screen:expect([[
  415. {5: Name] }{24: + foo + bar }{2: }{24:X}|
  416. {1:^$} |
  417. {1:~ }|*2
  418. |
  419. ]])
  420. command('tabclose')
  421. screen:expect([[
  422. {5: + foo }{24: + bar }{2: }{24:X}|
  423. this is fo^o |
  424. {1:~ }|*2
  425. |
  426. ]])
  427. feed('<2-LeftMouse><20,0>')
  428. screen:expect([[
  429. {24: + foo + bar }{5: Name] }{2: }{24:X}|
  430. {1:^$} |
  431. {1:~ }|*2
  432. |
  433. ]])
  434. command('tabclose')
  435. screen:expect([[
  436. {24: + foo }{5: + bar }{2: }{24:X}|
  437. this is ba^r{1:$} |
  438. {1:~ }|*2
  439. |
  440. ]])
  441. feed('<2-LeftMouse><10,0>')
  442. screen:expect([[
  443. {24: + foo }{5: Name] }{24: + bar }{2: }{24:X}|
  444. {1:^$} |
  445. {1:~ }|*2
  446. |
  447. ]])
  448. end)
  449. describe('%@ label', function()
  450. before_each(function()
  451. feed_command([[
  452. function Test(...)
  453. let g:reply = a:000
  454. return copy(a:000) " Check for memory leaks: return should be freed
  455. endfunction
  456. ]])
  457. feed_command([[
  458. function Test2(...)
  459. return call('Test', a:000 + [2])
  460. endfunction
  461. ]])
  462. api.nvim_set_option_value('tabline', '%@Test@test%X-%5@Test2@test2', {})
  463. api.nvim_set_option_value('showtabline', 2, {})
  464. screen:expect([[
  465. {2:test-test2 }|
  466. testing |
  467. mouse |
  468. support and selectio^n |
  469. |
  470. ]])
  471. api.nvim_set_var('reply', {})
  472. end)
  473. local check_reply = function(expected)
  474. eq(expected, api.nvim_get_var('reply'))
  475. api.nvim_set_var('reply', {})
  476. end
  477. local test_click = function(name, click_str, click_num, mouse_button, modifiers)
  478. local function doit(do_click)
  479. eq(1, fn.has('tablineat'))
  480. do_click(0, 3)
  481. check_reply({ 0, click_num, mouse_button, modifiers })
  482. do_click(0, 4)
  483. check_reply({})
  484. do_click(0, 6)
  485. check_reply({ 5, click_num, mouse_button, modifiers, 2 })
  486. do_click(0, 13)
  487. check_reply({ 5, click_num, mouse_button, modifiers, 2 })
  488. end
  489. it(name .. ' works (pseudokey)', function()
  490. doit(function(row, col)
  491. feed(click_str .. '<' .. col .. ',' .. row .. '>')
  492. end)
  493. end)
  494. it(name .. ' works (nvim_input_mouse)', function()
  495. doit(function(row, col)
  496. local buttons = { l = 'left', m = 'middle', r = 'right' }
  497. local modstr = (click_num > 1) and tostring(click_num) or ''
  498. for char in string.gmatch(modifiers, '%w') do
  499. modstr = modstr .. char .. '-' -- - not needed but should be accepted
  500. end
  501. api.nvim_input_mouse(buttons[mouse_button], 'press', modstr, 0, row, col)
  502. end)
  503. end)
  504. end
  505. test_click('single left click', '<LeftMouse>', 1, 'l', ' ')
  506. test_click('shifted single left click', '<S-LeftMouse>', 1, 'l', 's ')
  507. test_click('shifted single left click with alt modifier', '<S-A-LeftMouse>', 1, 'l', 's a ')
  508. test_click(
  509. 'shifted single left click with alt and ctrl modifiers',
  510. '<S-C-A-LeftMouse>',
  511. 1,
  512. 'l',
  513. 'sca '
  514. )
  515. -- <C-RightMouse> does not work
  516. test_click('shifted single right click with alt modifier', '<S-A-RightMouse>', 1, 'r', 's a ')
  517. -- Modifiers do not work with MiddleMouse
  518. test_click(
  519. 'shifted single middle click with alt and ctrl modifiers',
  520. '<MiddleMouse>',
  521. 1,
  522. 'm',
  523. ' '
  524. )
  525. -- Modifiers do not work with N-*Mouse
  526. test_click('double left click', '<2-LeftMouse>', 2, 'l', ' ')
  527. test_click('triple left click', '<3-LeftMouse>', 3, 'l', ' ')
  528. test_click('quadruple left click', '<4-LeftMouse>', 4, 'l', ' ')
  529. test_click('double right click', '<2-RightMouse>', 2, 'r', ' ')
  530. test_click('triple right click', '<3-RightMouse>', 3, 'r', ' ')
  531. test_click('quadruple right click', '<4-RightMouse>', 4, 'r', ' ')
  532. test_click('double middle click', '<2-MiddleMouse>', 2, 'm', ' ')
  533. test_click('triple middle click', '<3-MiddleMouse>', 3, 'm', ' ')
  534. test_click('quadruple middle click', '<4-MiddleMouse>', 4, 'm', ' ')
  535. end)
  536. end)
  537. it('left drag changes visual selection', function()
  538. -- drag events must be preceded by a click
  539. feed('<LeftMouse><2,1>')
  540. screen:expect([[
  541. testing |
  542. mo^use |
  543. support and selection |
  544. {1:~ }|
  545. |
  546. ]])
  547. feed('<LeftDrag><4,1>')
  548. screen:expect([[
  549. testing |
  550. mo{17:us}^e |
  551. support and selection |
  552. {1:~ }|
  553. {5:-- VISUAL --} |
  554. ]])
  555. feed('<LeftDrag><2,2>')
  556. screen:expect([[
  557. testing |
  558. mo{17:use} |
  559. {17:su}^pport and selection |
  560. {1:~ }|
  561. {5:-- VISUAL --} |
  562. ]])
  563. feed('<LeftDrag><0,0>')
  564. screen:expect([[
  565. ^t{17:esting} |
  566. {17:mou}se |
  567. support and selection |
  568. {1:~ }|
  569. {5:-- VISUAL --} |
  570. ]])
  571. end)
  572. it('left drag changes visual selection after tab click', function()
  573. feed_command('silent file foo | tabnew | file bar')
  574. insert('this is bar')
  575. feed_command('tabprevious') -- go to first tab
  576. screen:expect([[
  577. {5: + foo }{24: + bar }{2: }{24:X}|
  578. testing |
  579. mouse |
  580. support and selectio^n |
  581. :tabprevious |
  582. ]])
  583. feed('<LeftMouse><10,0><LeftRelease>') -- go to second tab
  584. n.poke_eventloop()
  585. feed('<LeftMouse><0,1>')
  586. screen:expect([[
  587. {24: + foo }{5: + bar }{2: }{24:X}|
  588. ^this is bar{1:$} |
  589. {1:~ }|*2
  590. :tabprevious |
  591. ]])
  592. feed('<LeftDrag><4,1>')
  593. screen:expect([[
  594. {24: + foo }{5: + bar }{2: }{24:X}|
  595. {17:this}^ is bar{1:$} |
  596. {1:~ }|*2
  597. {5:-- VISUAL --} |
  598. ]])
  599. end)
  600. it('left drag changes visual selection in split layout', function()
  601. screen:try_resize(53, 14)
  602. command('set mouse=a')
  603. command('vsplit')
  604. command('wincmd l')
  605. command('below split')
  606. command('enew')
  607. feed('ifoo\nbar<esc>')
  608. screen:expect {
  609. grid = [[
  610. testing │testing |
  611. mouse │mouse |
  612. support and selection │support and selection |
  613. {1:~ }│{1:~ }|*2
  614. {1:~ }│{2:[No Name] [+] }|
  615. {1:~ }│foo{1:$} |
  616. {1:~ }│ba^r{1:$} |
  617. {1:~ }│{1:~ }|*4
  618. {2:[No Name] [+] }{3:[No Name] [+] }|
  619. |
  620. ]],
  621. }
  622. api.nvim_input_mouse('left', 'press', '', 0, 6, 27)
  623. screen:expect {
  624. grid = [[
  625. testing │testing |
  626. mouse │mouse |
  627. support and selection │support and selection |
  628. {1:~ }│{1:~ }|*2
  629. {1:~ }│{2:[No Name] [+] }|
  630. {1:~ }│^foo{1:$} |
  631. {1:~ }│bar{1:$} |
  632. {1:~ }│{1:~ }|*4
  633. {2:[No Name] [+] }{3:[No Name] [+] }|
  634. |
  635. ]],
  636. }
  637. api.nvim_input_mouse('left', 'drag', '', 0, 7, 30)
  638. screen:expect {
  639. grid = [[
  640. testing │testing |
  641. mouse │mouse |
  642. support and selection │support and selection |
  643. {1:~ }│{1:~ }|*2
  644. {1:~ }│{2:[No Name] [+] }|
  645. {1:~ }│{17:foo}{100:$} |
  646. {1:~ }│{17:bar}{1:^$} |
  647. {1:~ }│{1:~ }|*4
  648. {2:[No Name] [+] }{3:[No Name] [+] }|
  649. {5:-- VISUAL --} |
  650. ]],
  651. }
  652. end)
  653. it('two clicks will enter VISUAL and dragging selects words', function()
  654. feed('<LeftMouse><2,2>')
  655. feed('<LeftRelease><2,2>')
  656. feed('<LeftMouse><2,2>')
  657. screen:expect([[
  658. testing |
  659. mouse |
  660. {17:suppor}^t and selection |
  661. {1:~ }|
  662. {5:-- VISUAL --} |
  663. ]])
  664. feed('<LeftDrag><0,1>')
  665. screen:expect([[
  666. testing |
  667. ^m{17:ouse} |
  668. {17:support} and selection |
  669. {1:~ }|
  670. {5:-- VISUAL --} |
  671. ]])
  672. feed('<LeftDrag><4,0>')
  673. screen:expect([[
  674. ^t{17:esting} |
  675. {17:mouse} |
  676. {17:support} and selection |
  677. {1:~ }|
  678. {5:-- VISUAL --} |
  679. ]])
  680. feed('<LeftDrag><14,2>')
  681. screen:expect([[
  682. testing |
  683. mouse |
  684. {17:support and selectio}^n |
  685. {1:~ }|
  686. {5:-- VISUAL --} |
  687. ]])
  688. end)
  689. it('three clicks will enter VISUAL LINE and dragging selects lines', function()
  690. feed('<LeftMouse><2,2>')
  691. feed('<LeftRelease><2,2>')
  692. feed('<LeftMouse><2,2>')
  693. feed('<LeftRelease><2,2>')
  694. feed('<LeftMouse><2,2>')
  695. screen:expect([[
  696. testing |
  697. mouse |
  698. {17:su}^p{17:port and selection} |
  699. {1:~ }|
  700. {5:-- VISUAL LINE --} |
  701. ]])
  702. feed('<LeftDrag><0,1>')
  703. screen:expect([[
  704. testing |
  705. ^m{17:ouse} |
  706. {17:support and selection} |
  707. {1:~ }|
  708. {5:-- VISUAL LINE --} |
  709. ]])
  710. feed('<LeftDrag><4,0>')
  711. screen:expect([[
  712. {17:test}^i{17:ng} |
  713. {17:mouse} |
  714. {17:support and selection} |
  715. {1:~ }|
  716. {5:-- VISUAL LINE --} |
  717. ]])
  718. feed('<LeftDrag><14,2>')
  719. screen:expect([[
  720. testing |
  721. mouse |
  722. {17:support and se}^l{17:ection} |
  723. {1:~ }|
  724. {5:-- VISUAL LINE --} |
  725. ]])
  726. end)
  727. it('four clicks will enter VISUAL BLOCK and dragging selects blockwise', function()
  728. feed('<LeftMouse><2,2>')
  729. feed('<LeftRelease><2,2>')
  730. feed('<LeftMouse><2,2>')
  731. feed('<LeftRelease><2,2>')
  732. feed('<LeftMouse><2,2>')
  733. feed('<LeftRelease><2,2>')
  734. feed('<LeftMouse><2,2>')
  735. screen:expect([[
  736. testing |
  737. mouse |
  738. su^pport and selection |
  739. {1:~ }|
  740. {5:-- VISUAL BLOCK --} |
  741. ]])
  742. feed('<LeftDrag><0,1>')
  743. screen:expect([[
  744. testing |
  745. ^m{17:ou}se |
  746. {17:sup}port and selection |
  747. {1:~ }|
  748. {5:-- VISUAL BLOCK --} |
  749. ]])
  750. feed('<LeftDrag><4,0>')
  751. screen:expect([[
  752. te{17:st}^ing |
  753. mo{17:use} |
  754. su{17:ppo}rt and selection |
  755. {1:~ }|
  756. {5:-- VISUAL BLOCK --} |
  757. ]])
  758. feed('<LeftDrag><14,2>')
  759. screen:expect([[
  760. testing |
  761. mouse |
  762. su{17:pport and se}^lection |
  763. {1:~ }|
  764. {5:-- VISUAL BLOCK --} |
  765. ]])
  766. end)
  767. it('right click extends visual selection to the clicked location', function()
  768. feed('<LeftMouse><0,0>')
  769. screen:expect([[
  770. ^testing |
  771. mouse |
  772. support and selection |
  773. {1:~ }|
  774. |
  775. ]])
  776. feed('<RightMouse><2,2>')
  777. screen:expect([[
  778. {17:testing} |
  779. {17:mouse} |
  780. {17:su}^pport and selection |
  781. {1:~ }|
  782. {5:-- VISUAL --} |
  783. ]])
  784. end)
  785. it('ctrl + left click will search for a tag', function()
  786. api.nvim_set_option_value('tags', './non-existent-tags-file', {})
  787. feed('<C-LeftMouse><0,0>')
  788. screen:expect([[
  789. {9:E433: No tags file} |
  790. {9:E426: Tag not found: test}|
  791. {9:ing} |
  792. {6:Press ENTER or type comma}|
  793. {6:nd to continue}^ |
  794. ]])
  795. feed('<cr>')
  796. end)
  797. it('x1 and x2 can be triggered by api', function()
  798. api.nvim_set_var('x1_pressed', 0)
  799. api.nvim_set_var('x1_released', 0)
  800. api.nvim_set_var('x2_pressed', 0)
  801. api.nvim_set_var('x2_released', 0)
  802. command('nnoremap <X1Mouse> <Cmd>let g:x1_pressed += 1<CR>')
  803. command('nnoremap <X1Release> <Cmd>let g:x1_released += 1<CR>')
  804. command('nnoremap <X2Mouse> <Cmd>let g:x2_pressed += 1<CR>')
  805. command('nnoremap <X2Release> <Cmd>let g:x2_released += 1<CR>')
  806. api.nvim_input_mouse('x1', 'press', '', 0, 0, 0)
  807. api.nvim_input_mouse('x1', 'release', '', 0, 0, 0)
  808. api.nvim_input_mouse('x2', 'press', '', 0, 0, 0)
  809. api.nvim_input_mouse('x2', 'release', '', 0, 0, 0)
  810. eq(1, api.nvim_get_var('x1_pressed'), 'x1 pressed once')
  811. eq(1, api.nvim_get_var('x1_released'), 'x1 released once')
  812. eq(1, api.nvim_get_var('x2_pressed'), 'x2 pressed once')
  813. eq(1, api.nvim_get_var('x2_released'), 'x2 released once')
  814. end)
  815. it('dragging vertical separator', function()
  816. screen:try_resize(45, 5)
  817. command('setlocal nowrap')
  818. local oldwin = api.nvim_get_current_win()
  819. command('rightbelow vnew')
  820. screen:expect([[
  821. testing │{1:^$} |
  822. mouse │{1:~ }|
  823. support and selection │{1:~ }|
  824. {2:[No Name] [+] }{3:[No Name] }|
  825. |
  826. ]])
  827. api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
  828. poke_eventloop()
  829. api.nvim_input_mouse('left', 'drag', '', 0, 1, 12)
  830. screen:expect([[
  831. testing │{1:^$} |
  832. mouse │{1:~ }|
  833. support and │{1:~ }|
  834. {2:< Name] [+] }{3:[No Name] }|
  835. |
  836. ]])
  837. api.nvim_input_mouse('left', 'drag', '', 0, 2, 2)
  838. screen:expect([[
  839. te│{1:^$} |
  840. mo│{1:~ }|
  841. su│{1:~ }|
  842. {2:< }{3:[No Name] }|
  843. |
  844. ]])
  845. api.nvim_input_mouse('left', 'release', '', 0, 2, 2)
  846. api.nvim_set_option_value('statuscolumn', 'foobar', { win = oldwin })
  847. screen:expect([[
  848. {8:fo}│{1:^$} |
  849. {8:fo}│{1:~ }|*2
  850. {2:< }{3:[No Name] }|
  851. |
  852. ]])
  853. api.nvim_input_mouse('left', 'press', '', 0, 0, 2)
  854. poke_eventloop()
  855. api.nvim_input_mouse('left', 'drag', '', 0, 1, 12)
  856. screen:expect([[
  857. {8:foobar}testin│{1:^$} |
  858. {8:foobar}mouse │{1:~ }|
  859. {8:foobar}suppor│{1:~ }|
  860. {2:< Name] [+] }{3:[No Name] }|
  861. |
  862. ]])
  863. api.nvim_input_mouse('left', 'drag', '', 0, 2, 22)
  864. screen:expect([[
  865. {8:foobar}testing │{1:^$} |
  866. {8:foobar}mouse │{1:~ }|
  867. {8:foobar}support and sele│{1:~ }|
  868. {2:[No Name] [+] }{3:[No Name] }|
  869. |
  870. ]])
  871. api.nvim_input_mouse('left', 'release', '', 0, 2, 22)
  872. end)
  873. local function wheel(use_api)
  874. feed('ggdG')
  875. insert([[
  876. Inserting
  877. text
  878. with
  879. many
  880. lines
  881. to
  882. test
  883. mouse scrolling
  884. ]])
  885. screen:try_resize(53, 14)
  886. feed('k')
  887. feed_command('sp', 'vsp')
  888. screen:expect([[
  889. lines │lines |
  890. to │to |
  891. test │test |
  892. ^mouse scrolling │mouse scrolling |
  893. │ |
  894. {1:~ }│{1:~ }|
  895. {3:[No Name] [+] }{2:[No Name] [+] }|
  896. to |
  897. test |
  898. mouse scrolling |
  899. |
  900. {1:~ }|
  901. {2:[No Name] [+] }|
  902. :vsp |
  903. ]])
  904. if use_api then
  905. api.nvim_input_mouse('wheel', 'down', '', 0, 0, 0)
  906. else
  907. feed('<ScrollWheelDown><0,0>')
  908. end
  909. screen:expect([[
  910. ^mouse scrolling │lines |
  911. │to |
  912. {1:~ }│test |
  913. {1:~ }│mouse scrolling |
  914. {1:~ }│ |
  915. {1:~ }│{1:~ }|
  916. {3:[No Name] [+] }{2:[No Name] [+] }|
  917. to |
  918. test |
  919. mouse scrolling |
  920. |
  921. {1:~ }|
  922. {2:[No Name] [+] }|
  923. :vsp |
  924. ]])
  925. if use_api then
  926. api.nvim_input_mouse('wheel', 'up', '', 0, 0, 27)
  927. else
  928. feed('<ScrollWheelUp><27,0>')
  929. end
  930. screen:expect([[
  931. ^mouse scrolling │text |
  932. │with |
  933. {1:~ }│many |
  934. {1:~ }│lines |
  935. {1:~ }│to |
  936. {1:~ }│test |
  937. {3:[No Name] [+] }{2:[No Name] [+] }|
  938. to |
  939. test |
  940. mouse scrolling |
  941. |
  942. {1:~ }|
  943. {2:[No Name] [+] }|
  944. :vsp |
  945. ]])
  946. if use_api then
  947. api.nvim_input_mouse('wheel', 'up', '', 0, 7, 27)
  948. api.nvim_input_mouse('wheel', 'up', '', 0, 7, 27)
  949. else
  950. feed('<ScrollWheelUp><27,7><ScrollWheelUp>')
  951. end
  952. screen:expect([[
  953. ^mouse scrolling │text |
  954. │with |
  955. {1:~ }│many |
  956. {1:~ }│lines |
  957. {1:~ }│to |
  958. {1:~ }│test |
  959. {3:[No Name] [+] }{2:[No Name] [+] }|
  960. Inserting |
  961. text |
  962. with |
  963. many |
  964. lines |
  965. {2:[No Name] [+] }|
  966. :vsp |
  967. ]])
  968. end
  969. it('mouse wheel will target the hovered window (pseudokey)', function()
  970. wheel(false)
  971. end)
  972. it('mouse wheel will target the hovered window (nvim_input_mouse)', function()
  973. wheel(true)
  974. end)
  975. it('horizontal scrolling (pseudokey)', function()
  976. command('set sidescroll=0')
  977. feed('<esc>:set nowrap<cr>')
  978. feed('a <esc>17Ab<esc>3Ab<esc>')
  979. screen:expect([[
  980. |*2
  981. bbbbbbbbbbbbbbb^b |
  982. {1:~ }|
  983. |
  984. ]])
  985. feed('<ScrollWheelLeft><0,0>')
  986. screen:expect([[
  987. |*2
  988. n bbbbbbbbbbbbbbbbbbb^b |
  989. {1:~ }|
  990. |
  991. ]])
  992. feed('^<ScrollWheelRight><0,0>')
  993. screen:expect([[
  994. g |
  995. |
  996. ^t and selection bbbbbbbbb|
  997. {1:~ }|
  998. |
  999. ]])
  1000. end)
  1001. it('horizontal scrolling (nvim_input_mouse)', function()
  1002. command('set sidescroll=0')
  1003. feed('<esc>:set nowrap<cr>')
  1004. feed('a <esc>17Ab<esc>3Ab<esc>')
  1005. screen:expect([[
  1006. |*2
  1007. bbbbbbbbbbbbbbb^b |
  1008. {1:~ }|
  1009. |
  1010. ]])
  1011. api.nvim_input_mouse('wheel', 'left', '', 0, 0, 27)
  1012. screen:expect([[
  1013. |*2
  1014. n bbbbbbbbbbbbbbbbbbb^b |
  1015. {1:~ }|
  1016. |
  1017. ]])
  1018. feed('^')
  1019. api.nvim_input_mouse('wheel', 'right', '', 0, 0, 0)
  1020. screen:expect([[
  1021. g |
  1022. |
  1023. ^t and selection bbbbbbbbb|
  1024. {1:~ }|
  1025. |
  1026. ]])
  1027. end)
  1028. it("'sidescrolloff' applies to horizontal scrolling", function()
  1029. command('set nowrap')
  1030. command('set sidescrolloff=4')
  1031. feed('I <esc>020ib<esc>0')
  1032. screen:expect([[
  1033. testing |
  1034. mouse |
  1035. ^bbbbbbbbbbbbbbbbbbbb supp|
  1036. {1:~ }|
  1037. |
  1038. ]])
  1039. api.nvim_input_mouse('wheel', 'right', '', 0, 0, 27)
  1040. screen:expect([[
  1041. g |
  1042. |
  1043. bbbb^bbbbbbbbbb support an|
  1044. {1:~ }|
  1045. |
  1046. ]])
  1047. -- window-local 'sidescrolloff' should override global value. #21162
  1048. command('setlocal sidescrolloff=2')
  1049. feed('0')
  1050. screen:expect([[
  1051. testing |
  1052. mouse |
  1053. ^bbbbbbbbbbbbbbbbbbbb supp|
  1054. {1:~ }|
  1055. |
  1056. ]])
  1057. api.nvim_input_mouse('wheel', 'right', '', 0, 0, 27)
  1058. screen:expect([[
  1059. g |
  1060. |
  1061. bb^bbbbbbbbbbbb support an|
  1062. {1:~ }|
  1063. |
  1064. ]])
  1065. end)
  1066. local function test_mouse_click_conceal()
  1067. it('(level 1) click on non-wrapped lines', function()
  1068. feed_command('let &conceallevel=1', 'echo')
  1069. feed('<esc><LeftMouse><0,0>')
  1070. screen:expect([[
  1071. ^Section{1:>>--->--->---}{14: }t1{14: } |
  1072. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1073. {14:>} 私は猫が大好き{1:>---}{14: X } {1:>}|
  1074. |
  1075. {1:~ }|*2
  1076. |
  1077. ]])
  1078. feed('<esc><LeftMouse><1,0>')
  1079. screen:expect([[
  1080. S^ection{1:>>--->--->---}{14: }t1{14: } |
  1081. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1082. {14:>} 私は猫が大好き{1:>---}{14: X } {1:>}|
  1083. |
  1084. {1:~ }|*2
  1085. |
  1086. ]])
  1087. feed('<esc><LeftMouse><21,0>')
  1088. screen:expect([[
  1089. Section{1:>>--->--->---}{14: }^t1{14: } |
  1090. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1091. {14:>} 私は猫が大好き{1:>---}{14: X } {1:>}|
  1092. |
  1093. {1:~ }|*2
  1094. |
  1095. ]])
  1096. feed('<esc><LeftMouse><21,1>')
  1097. screen:expect([[
  1098. Section{1:>>--->--->---}{14: }t1{14: } |
  1099. {1:>--->--->---} {14: }t2{14: } {14: }t^3{14: } {14: }|
  1100. {14:>} 私は猫が大好き{1:>---}{14: X } {1:>}|
  1101. |
  1102. {1:~ }|*2
  1103. |
  1104. ]])
  1105. feed('<esc><LeftMouse><0,2>')
  1106. screen:expect([[
  1107. Section{1:>>--->--->---}{14: }t1{14: } |
  1108. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1109. {14:^>} 私は猫が大好き{1:>---}{14: X } {1:>}|
  1110. |
  1111. {1:~ }|*2
  1112. |
  1113. ]])
  1114. feed('<esc><LeftMouse><7,2>')
  1115. screen:expect([[
  1116. Section{1:>>--->--->---}{14: }t1{14: } |
  1117. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1118. {14:>} 私は^猫が大好き{1:>---}{14: X } {1:>}|
  1119. |
  1120. {1:~ }|*2
  1121. |
  1122. ]])
  1123. feed('<esc><LeftMouse><21,2>')
  1124. screen:expect([[
  1125. Section{1:>>--->--->---}{14: }t1{14: } |
  1126. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1127. {14:>} 私は猫が大好き{1:>---}{14: ^X } {1:>}|
  1128. |
  1129. {1:~ }|*2
  1130. |
  1131. ]])
  1132. end) -- level 1 - non wrapped
  1133. it('(level 1) click on wrapped lines', function()
  1134. feed_command('let &conceallevel=1', 'let &wrap=1', 'echo')
  1135. feed('<esc><LeftMouse><24,1>')
  1136. screen:expect([[
  1137. Section{1:>>--->--->---}{14: }t1{14: } |
  1138. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14:^ }|
  1139. t4{14: } |
  1140. {14:>} 私は猫が大好き{1:>---}{14: X} |
  1141. {14: } ✨🐈✨ |
  1142. |*2
  1143. ]])
  1144. feed('<esc><LeftMouse><0,2>')
  1145. screen:expect([[
  1146. Section{1:>>--->--->---}{14: }t1{14: } |
  1147. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1148. ^t4{14: } |
  1149. {14:>} 私は猫が大好き{1:>---}{14: X} |
  1150. {14: } ✨🐈✨ |
  1151. |*2
  1152. ]])
  1153. feed('<esc><LeftMouse><8,3>')
  1154. screen:expect([[
  1155. Section{1:>>--->--->---}{14: }t1{14: } |
  1156. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1157. t4{14: } |
  1158. {14:>} 私は猫^が大好き{1:>---}{14: X} |
  1159. {14: } ✨🐈✨ |
  1160. |*2
  1161. ]])
  1162. feed('<esc><LeftMouse><21,3>')
  1163. screen:expect([[
  1164. Section{1:>>--->--->---}{14: }t1{14: } |
  1165. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1166. t4{14: } |
  1167. {14:>} 私は猫が大好き{1:>---}{14: ^X} |
  1168. {14: } ✨🐈✨ |
  1169. |*2
  1170. ]])
  1171. feed('<esc><LeftMouse><4,4>')
  1172. screen:expect([[
  1173. Section{1:>>--->--->---}{14: }t1{14: } |
  1174. {1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }|
  1175. t4{14: } |
  1176. {14:>} 私は猫が大好き{1:>---}{14: X} |
  1177. {14: } ✨^🐈✨ |
  1178. |*2
  1179. ]])
  1180. end) -- level 1 - wrapped
  1181. it('(level 2) click on non-wrapped lines', function()
  1182. feed_command('let &conceallevel=2', 'echo')
  1183. feed('<esc><LeftMouse><20,0>')
  1184. screen:expect([[
  1185. Section{1:>>--->--->---}^t1 |
  1186. {1:>--->--->---} t2 t3 t4 |
  1187. {14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}|
  1188. |
  1189. {1:~ }|*2
  1190. |
  1191. ]])
  1192. feed('<esc><LeftMouse><14,1>')
  1193. screen:expect([[
  1194. Section{1:>>--->--->---}t1 |
  1195. {1:>--->--->---} ^t2 t3 t4 |
  1196. {14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}|
  1197. |
  1198. {1:~ }|*2
  1199. |
  1200. ]])
  1201. feed('<esc><LeftMouse><18,1>')
  1202. screen:expect([[
  1203. Section{1:>>--->--->---}t1 |
  1204. {1:>--->--->---} t2 t^3 t4 |
  1205. {14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}|
  1206. |
  1207. {1:~ }|*2
  1208. |
  1209. ]])
  1210. feed('<esc><LeftMouse><0,2>') -- Weirdness
  1211. screen:expect([[
  1212. Section{1:>>--->--->---}t1 |
  1213. {1:>--->--->---} t2 t3 t4 |
  1214. {14:^>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}|
  1215. |
  1216. {1:~ }|*2
  1217. |
  1218. ]])
  1219. feed('<esc><LeftMouse><8,2>')
  1220. screen:expect([[
  1221. Section{1:>>--->--->---}t1 |
  1222. {1:>--->--->---} t2 t3 t4 |
  1223. {14:>} 私は猫^が大好き{1:>---}{14:X} ✨{1:>}|
  1224. |
  1225. {1:~ }|*2
  1226. |
  1227. ]])
  1228. feed('<esc><LeftMouse><20,2>')
  1229. screen:expect([[
  1230. Section{1:>>--->--->---}t1 |
  1231. {1:>--->--->---} t2 t3 t4 |
  1232. {14:>} 私は猫が大好き{1:>---}{14:^X} ✨{1:>}|
  1233. |
  1234. {1:~ }|*2
  1235. |
  1236. ]])
  1237. end) -- level 2 - non wrapped
  1238. it('(level 2) click on non-wrapped lines (insert mode)', function()
  1239. feed_command('let &conceallevel=2', 'echo')
  1240. feed('<esc>i<LeftMouse><20,0>')
  1241. screen:expect([[
  1242. Section{1:>>--->--->---}^t1 |
  1243. {1:>--->--->---} t2 t3 t4 |
  1244. {14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}|
  1245. |
  1246. {1:~ }|*2
  1247. {5:-- INSERT --} |
  1248. ]])
  1249. feed('<LeftMouse><14,1>')
  1250. screen:expect([[
  1251. Section{1:>>--->--->---}t1 |
  1252. {1:>--->--->---} ^t2 t3 t4 |
  1253. {14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}|
  1254. |
  1255. {1:~ }|*2
  1256. {5:-- INSERT --} |
  1257. ]])
  1258. feed('<LeftMouse><18,1>')
  1259. screen:expect([[
  1260. Section{1:>>--->--->---}t1 |
  1261. {1:>--->--->---} t2 t^3 t4 |
  1262. {14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}|
  1263. |
  1264. {1:~ }|*2
  1265. {5:-- INSERT --} |
  1266. ]])
  1267. feed('<LeftMouse><0,2>') -- Weirdness
  1268. screen:expect([[
  1269. Section{1:>>--->--->---}t1 |
  1270. {1:>--->--->---} t2 t3 t4 |
  1271. {14:^>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}|
  1272. |
  1273. {1:~ }|*2
  1274. {5:-- INSERT --} |
  1275. ]])
  1276. feed('<LeftMouse><8,2>')
  1277. screen:expect([[
  1278. Section{1:>>--->--->---}t1 |
  1279. {1:>--->--->---} t2 t3 t4 |
  1280. {14:>} 私は猫^が大好き{1:>---}{14:X} ✨{1:>}|
  1281. |
  1282. {1:~ }|*2
  1283. {5:-- INSERT --} |
  1284. ]])
  1285. feed('<LeftMouse><20,2>')
  1286. screen:expect([[
  1287. Section{1:>>--->--->---}t1 |
  1288. {1:>--->--->---} t2 t3 t4 |
  1289. {14:>} 私は猫が大好き{1:>---}{14:^X} ✨{1:>}|
  1290. |
  1291. {1:~ }|*2
  1292. {5:-- INSERT --} |
  1293. ]])
  1294. end) -- level 2 - non wrapped (insert mode)
  1295. it('(level 2) click on wrapped lines', function()
  1296. feed_command('let &conceallevel=2', 'let &wrap=1', 'echo')
  1297. feed('<esc><LeftMouse><20,0>')
  1298. screen:expect([[
  1299. Section{1:>>--->--->---}^t1 |
  1300. {1:>--->--->---} t2 t3 |
  1301. t4 |
  1302. {14:>} 私は猫が大好き{1:>---}{14:X} |
  1303. ✨🐈✨ |
  1304. |*2
  1305. ]])
  1306. feed('<esc><LeftMouse><14,1>')
  1307. screen:expect([[
  1308. Section{1:>>--->--->---}t1 |
  1309. {1:>--->--->---} ^t2 t3 |
  1310. t4 |
  1311. {14:>} 私は猫が大好き{1:>---}{14:X} |
  1312. ✨🐈✨ |
  1313. |*2
  1314. ]])
  1315. feed('<esc><LeftMouse><18,1>')
  1316. screen:expect([[
  1317. Section{1:>>--->--->---}t1 |
  1318. {1:>--->--->---} t2 t^3 |
  1319. t4 |
  1320. {14:>} 私は猫が大好き{1:>---}{14:X} |
  1321. ✨🐈✨ |
  1322. |*2
  1323. ]])
  1324. -- NOTE: The click would ideally be on the 't' in 't4', but wrapping
  1325. -- caused the invisible '*' right before 't4' to remain on the previous
  1326. -- screen line. This is being treated as expected because fixing this is
  1327. -- out of scope for mouse clicks. Should the wrapping behavior of
  1328. -- concealed characters change in the future, this case should be
  1329. -- reevaluated.
  1330. feed('<esc><LeftMouse><0,2>')
  1331. screen:expect([[
  1332. Section{1:>>--->--->---}t1 |
  1333. {1:>--->--->---} t2 t3 ^ |
  1334. t4 |
  1335. {14:>} 私は猫が大好き{1:>---}{14:X} |
  1336. ✨🐈✨ |
  1337. |*2
  1338. ]])
  1339. feed('<esc><LeftMouse><1,2>')
  1340. screen:expect([[
  1341. Section{1:>>--->--->---}t1 |
  1342. {1:>--->--->---} t2 t3 |
  1343. t^4 |
  1344. {14:>} 私は猫が大好き{1:>---}{14:X} |
  1345. ✨🐈✨ |
  1346. |*2
  1347. ]])
  1348. feed('<esc><LeftMouse><0,3>')
  1349. screen:expect([[
  1350. Section{1:>>--->--->---}t1 |
  1351. {1:>--->--->---} t2 t3 |
  1352. t4 |
  1353. {14:^>} 私は猫が大好き{1:>---}{14:X} |
  1354. ✨🐈✨ |
  1355. |*2
  1356. ]])
  1357. feed('<esc><LeftMouse><20,3>')
  1358. screen:expect([[
  1359. Section{1:>>--->--->---}t1 |
  1360. {1:>--->--->---} t2 t3 |
  1361. t4 |
  1362. {14:>} 私は猫が大好き{1:>---}{14:^X} |
  1363. ✨🐈✨ |
  1364. |*2
  1365. ]])
  1366. feed('<esc><LeftMouse><1,4>')
  1367. screen:expect([[
  1368. Section{1:>>--->--->---}t1 |
  1369. {1:>--->--->---} t2 t3 |
  1370. t4 |
  1371. {14:>} 私は猫が大好き{1:>---}{14:X} |
  1372. ^✨🐈✨ |
  1373. |*2
  1374. ]])
  1375. feed('<esc><LeftMouse><5,4>')
  1376. screen:expect([[
  1377. Section{1:>>--->--->---}t1 |
  1378. {1:>--->--->---} t2 t3 |
  1379. t4 |
  1380. {14:>} 私は猫が大好き{1:>---}{14:X} |
  1381. ✨🐈^✨ |
  1382. |*2
  1383. ]])
  1384. end) -- level 2 - wrapped
  1385. it('(level 3) click on non-wrapped lines', function()
  1386. feed_command('let &conceallevel=3', 'echo')
  1387. feed('<esc><LeftMouse><0,2>')
  1388. screen:expect([[
  1389. Section{1:>>--->--->---}t1 |
  1390. {1:>--->--->---} t2 t3 t4 |
  1391. ^ 私は猫が大好き{1:>----} ✨🐈|
  1392. |
  1393. {1:~ }|*2
  1394. |
  1395. ]])
  1396. feed('<esc><LeftMouse><1,2>')
  1397. screen:expect([[
  1398. Section{1:>>--->--->---}t1 |
  1399. {1:>--->--->---} t2 t3 t4 |
  1400. ^私は猫が大好き{1:>----} ✨🐈|
  1401. |
  1402. {1:~ }|*2
  1403. |
  1404. ]])
  1405. feed('<esc><LeftMouse><13,2>')
  1406. screen:expect([[
  1407. Section{1:>>--->--->---}t1 |
  1408. {1:>--->--->---} t2 t3 t4 |
  1409. 私は猫が大好^き{1:>----} ✨🐈|
  1410. |
  1411. {1:~ }|*2
  1412. |
  1413. ]])
  1414. feed('<esc><LeftMouse><20,2>')
  1415. feed('zH') -- FIXME: unnecessary horizontal scrolling
  1416. screen:expect([[
  1417. Section{1:>>--->--->---}t1 |
  1418. {1:>--->--->---} t2 t3 t4 |
  1419. 私は猫が大好き{1:>----}^ ✨🐈|
  1420. |
  1421. {1:~ }|*2
  1422. |
  1423. ]])
  1424. end) -- level 3 - non wrapped
  1425. it('(level 3) click on wrapped lines', function()
  1426. feed_command('let &conceallevel=3', 'let &wrap=1', 'echo')
  1427. feed('<esc><LeftMouse><14,1>')
  1428. screen:expect([[
  1429. Section{1:>>--->--->---}t1 |
  1430. {1:>--->--->---} ^t2 t3 |
  1431. t4 |
  1432. 私は猫が大好き{1:>----} |
  1433. ✨🐈✨ |
  1434. |*2
  1435. ]])
  1436. feed('<esc><LeftMouse><18,1>')
  1437. screen:expect([[
  1438. Section{1:>>--->--->---}t1 |
  1439. {1:>--->--->---} t2 t^3 |
  1440. t4 |
  1441. 私は猫が大好き{1:>----} |
  1442. ✨🐈✨ |
  1443. |*2
  1444. ]])
  1445. feed('<esc><LeftMouse><1,2>')
  1446. screen:expect([[
  1447. Section{1:>>--->--->---}t1 |
  1448. {1:>--->--->---} t2 t3 |
  1449. t^4 |
  1450. 私は猫が大好き{1:>----} |
  1451. ✨🐈✨ |
  1452. |*2
  1453. ]])
  1454. feed('<esc><LeftMouse><0,3>')
  1455. screen:expect([[
  1456. Section{1:>>--->--->---}t1 |
  1457. {1:>--->--->---} t2 t3 |
  1458. t4 |
  1459. ^ 私は猫が大好き{1:>----} |
  1460. ✨🐈✨ |
  1461. |*2
  1462. ]])
  1463. feed('<esc><LeftMouse><20,3>')
  1464. screen:expect([[
  1465. Section{1:>>--->--->---}t1 |
  1466. {1:>--->--->---} t2 t3 |
  1467. t4 |
  1468. 私は猫が大好き{1:>----}^ |
  1469. ✨🐈✨ |
  1470. |*2
  1471. ]])
  1472. feed('<esc><LeftMouse><1,4>')
  1473. screen:expect([[
  1474. Section{1:>>--->--->---}t1 |
  1475. {1:>--->--->---} t2 t3 |
  1476. t4 |
  1477. 私は猫が大好き{1:>----} |
  1478. ^✨🐈✨ |
  1479. |*2
  1480. ]])
  1481. feed('<esc><LeftMouse><3,4>')
  1482. screen:expect([[
  1483. Section{1:>>--->--->---}t1 |
  1484. {1:>--->--->---} t2 t3 |
  1485. t4 |
  1486. 私は猫が大好き{1:>----} |
  1487. ✨^🐈✨ |
  1488. |*2
  1489. ]])
  1490. feed('<esc><LeftMouse><5,4>')
  1491. screen:expect([[
  1492. Section{1:>>--->--->---}t1 |
  1493. {1:>--->--->---} t2 t3 |
  1494. t4 |
  1495. 私は猫が大好き{1:>----} |
  1496. ✨🐈^✨ |
  1497. |*2
  1498. ]])
  1499. end) -- level 3 - wrapped
  1500. end
  1501. describe('on concealed text', function()
  1502. -- Helpful for reading the test expectations:
  1503. -- :match Error /\^/
  1504. before_each(function()
  1505. screen:try_resize(25, 7)
  1506. feed('ggdG')
  1507. command([[setlocal concealcursor=ni nowrap shiftwidth=2 tabstop=4 list listchars=tab:>-]])
  1508. command([[highlight link X0 Normal]])
  1509. command([[highlight link X1 NonText]])
  1510. command([[highlight link X2 NonText]])
  1511. command([[highlight link X3 NonText]])
  1512. -- First column is there to retain the tabs.
  1513. insert([[
  1514. |Section *t1*
  1515. | *t2* *t3* *t4*
  1516. |x 私は猫が大好き *cats* ✨🐈✨
  1517. ]])
  1518. feed('gg<c-v>Gxgg')
  1519. end)
  1520. describe('(syntax)', function()
  1521. before_each(function()
  1522. command([[syntax region X0 matchgroup=X1 start=/\*/ end=/\*/ concealends contains=X2]])
  1523. command([[syntax match X2 /cats/ conceal cchar=X contained]])
  1524. command([[syntax match X3 /\n\@<=x/ conceal cchar=>]])
  1525. end)
  1526. test_mouse_click_conceal()
  1527. end)
  1528. describe('(matchadd())', function()
  1529. before_each(function()
  1530. fn.matchadd('Conceal', [[\*]])
  1531. fn.matchadd('Conceal', [[cats]], 10, -1, { conceal = 'X' })
  1532. fn.matchadd('Conceal', [[\n\@<=x]], 10, -1, { conceal = '>' })
  1533. end)
  1534. test_mouse_click_conceal()
  1535. end)
  1536. describe('(extmarks)', function()
  1537. before_each(function()
  1538. local ns = api.nvim_create_namespace('conceal')
  1539. api.nvim_buf_set_extmark(0, ns, 0, 11, { end_col = 12, conceal = '' })
  1540. api.nvim_buf_set_extmark(0, ns, 0, 14, { end_col = 15, conceal = '' })
  1541. api.nvim_buf_set_extmark(0, ns, 1, 5, { end_col = 6, conceal = '' })
  1542. api.nvim_buf_set_extmark(0, ns, 1, 8, { end_col = 9, conceal = '' })
  1543. api.nvim_buf_set_extmark(0, ns, 1, 10, { end_col = 11, conceal = '' })
  1544. api.nvim_buf_set_extmark(0, ns, 1, 13, { end_col = 14, conceal = '' })
  1545. api.nvim_buf_set_extmark(0, ns, 1, 15, { end_col = 16, conceal = '' })
  1546. api.nvim_buf_set_extmark(0, ns, 1, 18, { end_col = 19, conceal = '' })
  1547. api.nvim_buf_set_extmark(0, ns, 2, 24, { end_col = 25, conceal = '' })
  1548. api.nvim_buf_set_extmark(0, ns, 2, 29, { end_col = 30, conceal = '' })
  1549. api.nvim_buf_set_extmark(0, ns, 2, 25, { end_col = 29, conceal = 'X' })
  1550. api.nvim_buf_set_extmark(0, ns, 2, 0, { end_col = 1, conceal = '>' })
  1551. end)
  1552. test_mouse_click_conceal()
  1553. end)
  1554. end)
  1555. it('virtual text does not change cursor placement on concealed line', function()
  1556. command('%delete')
  1557. insert('aaaaaaaaaa|hidden|bbbbbbbbbb|hidden|cccccccccc')
  1558. command('syntax match test /|hidden|/ conceal cchar=X')
  1559. command('set conceallevel=2 concealcursor=n virtualedit=all')
  1560. screen:expect([[
  1561. aaaaaaaaaa{14:X}bbbbbbb |
  1562. bbb{14:X}ccccccccc^c |
  1563. {1:~ }|*2
  1564. |
  1565. ]])
  1566. api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
  1567. screen:expect([[
  1568. aaaaaaaaaa{14:X}bbbbbb^b |
  1569. bbb{14:X}cccccccccc |
  1570. {1:~ }|*2
  1571. |
  1572. ]])
  1573. api.nvim_input_mouse('left', 'press', '', 0, 1, 16)
  1574. screen:expect([[
  1575. aaaaaaaaaa{14:X}bbbbbbb |
  1576. bbb{14:X}cccccccccc ^ |
  1577. {1:~ }|*2
  1578. |
  1579. ]])
  1580. api.nvim_buf_set_extmark(0, api.nvim_create_namespace(''), 0, 0, {
  1581. virt_text = { { '?', 'ErrorMsg' } },
  1582. virt_text_pos = 'right_align',
  1583. virt_text_repeat_linebreak = true,
  1584. })
  1585. screen:expect([[
  1586. aaaaaaaaaa{14:X}bbbbbbb {9:?}|
  1587. bbb{14:X}cccccccccc ^ {9:?}|
  1588. {1:~ }|*2
  1589. |
  1590. ]])
  1591. api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
  1592. screen:expect([[
  1593. aaaaaaaaaa{14:X}bbbbbb^b {9:?}|
  1594. bbb{14:X}cccccccccc {9:?}|
  1595. {1:~ }|*2
  1596. |
  1597. ]])
  1598. api.nvim_input_mouse('left', 'press', '', 0, 1, 16)
  1599. screen:expect([[
  1600. aaaaaaaaaa{14:X}bbbbbbb {9:?}|
  1601. bbb{14:X}cccccccccc ^ {9:?}|
  1602. {1:~ }|*2
  1603. |
  1604. ]])
  1605. end)
  1606. it('getmousepos() works correctly', function()
  1607. local winwidth = api.nvim_get_option_value('winwidth', {})
  1608. -- Set winwidth=1 so that window sizes don't change.
  1609. api.nvim_set_option_value('winwidth', 1, {})
  1610. command('tabedit')
  1611. local tabpage = api.nvim_get_current_tabpage()
  1612. insert('hello')
  1613. command('vsplit')
  1614. local opts = {
  1615. relative = 'editor',
  1616. width = 12,
  1617. height = 1,
  1618. col = 8,
  1619. row = 1,
  1620. anchor = 'NW',
  1621. style = 'minimal',
  1622. border = 'single',
  1623. focusable = 1,
  1624. }
  1625. local float = api.nvim_open_win(api.nvim_get_current_buf(), false, opts)
  1626. command('redraw')
  1627. local lines = api.nvim_get_option_value('lines', {})
  1628. local columns = api.nvim_get_option_value('columns', {})
  1629. -- Test that screenrow and screencol are set properly for all positions.
  1630. for row = 0, lines - 1 do
  1631. for col = 0, columns - 1 do
  1632. -- Skip the X button that would close the tab.
  1633. if row ~= 0 or col ~= columns - 1 then
  1634. api.nvim_input_mouse('left', 'press', '', 0, row, col)
  1635. api.nvim_set_current_tabpage(tabpage)
  1636. local mousepos = fn.getmousepos()
  1637. eq(row + 1, mousepos.screenrow)
  1638. eq(col + 1, mousepos.screencol)
  1639. -- All other values should be 0 when clicking on the command line.
  1640. if row == lines - 1 then
  1641. eq(0, mousepos.winid)
  1642. eq(0, mousepos.winrow)
  1643. eq(0, mousepos.wincol)
  1644. eq(0, mousepos.line)
  1645. eq(0, mousepos.column)
  1646. eq(0, mousepos.coladd)
  1647. end
  1648. end
  1649. end
  1650. end
  1651. -- Test that mouse position values are properly set for the floating window
  1652. -- with a border. 1 is added to the height and width to account for the
  1653. -- border.
  1654. for win_row = 0, opts.height + 1 do
  1655. for win_col = 0, opts.width + 1 do
  1656. local row = win_row + opts.row
  1657. local col = win_col + opts.col
  1658. api.nvim_input_mouse('left', 'press', '', 0, row, col)
  1659. local mousepos = fn.getmousepos()
  1660. eq(float, mousepos.winid)
  1661. eq(win_row + 1, mousepos.winrow)
  1662. eq(win_col + 1, mousepos.wincol)
  1663. local line = 0
  1664. local column = 0
  1665. local coladd = 0
  1666. if
  1667. win_row > 0
  1668. and win_row < opts.height + 1
  1669. and win_col > 0
  1670. and win_col < opts.width + 1
  1671. then
  1672. -- Because of border, win_row and win_col don't need to be
  1673. -- incremented by 1.
  1674. line = math.min(win_row, fn.line('$'))
  1675. column = math.min(win_col, #fn.getline(line) + 1)
  1676. coladd = win_col - column
  1677. end
  1678. eq(line, mousepos.line)
  1679. eq(column, mousepos.column)
  1680. eq(coladd, mousepos.coladd)
  1681. end
  1682. end
  1683. -- Test that mouse position values are properly set for the floating
  1684. -- window, after removing the border.
  1685. opts.border = 'none'
  1686. api.nvim_win_set_config(float, opts)
  1687. command('redraw')
  1688. for win_row = 0, opts.height - 1 do
  1689. for win_col = 0, opts.width - 1 do
  1690. local row = win_row + opts.row
  1691. local col = win_col + opts.col
  1692. api.nvim_input_mouse('left', 'press', '', 0, row, col)
  1693. local mousepos = fn.getmousepos()
  1694. eq(float, mousepos.winid)
  1695. eq(win_row + 1, mousepos.winrow)
  1696. eq(win_col + 1, mousepos.wincol)
  1697. local line = math.min(win_row + 1, fn.line('$'))
  1698. local column = math.min(win_col + 1, #fn.getline(line) + 1)
  1699. local coladd = win_col + 1 - column
  1700. eq(line, mousepos.line)
  1701. eq(column, mousepos.column)
  1702. eq(coladd, mousepos.coladd)
  1703. end
  1704. end
  1705. -- Test that mouse position values are properly set for ordinary windows.
  1706. -- Set the float to be unfocusable instead of closing, to additionally test
  1707. -- that getmousepos() does not consider unfocusable floats. (see discussion
  1708. -- in PR #14937 for details).
  1709. opts.focusable = false
  1710. api.nvim_win_set_config(float, opts)
  1711. command('redraw')
  1712. for nr = 1, 2 do
  1713. for win_row = 0, fn.winheight(nr) - 1 do
  1714. for win_col = 0, fn.winwidth(nr) - 1 do
  1715. local row = win_row + fn.win_screenpos(nr)[1] - 1
  1716. local col = win_col + fn.win_screenpos(nr)[2] - 1
  1717. api.nvim_input_mouse('left', 'press', '', 0, row, col)
  1718. local mousepos = fn.getmousepos()
  1719. eq(fn.win_getid(nr), mousepos.winid)
  1720. eq(win_row + 1, mousepos.winrow)
  1721. eq(win_col + 1, mousepos.wincol)
  1722. local line = math.min(win_row + 1, fn.line('$'))
  1723. local column = math.min(win_col + 1, #fn.getline(line) + 1)
  1724. local coladd = win_col + 1 - column
  1725. eq(line, mousepos.line)
  1726. eq(column, mousepos.column)
  1727. eq(coladd, mousepos.coladd)
  1728. end
  1729. end
  1730. end
  1731. -- Restore state and release mouse.
  1732. command('tabclose!')
  1733. api.nvim_set_option_value('winwidth', winwidth, {})
  1734. api.nvim_input_mouse('left', 'release', '', 0, 0, 0)
  1735. end)
  1736. it('scroll keys are not translated into multiclicks and can be mapped #6211 #6989', function()
  1737. api.nvim_set_var('mouse_up', 0)
  1738. api.nvim_set_var('mouse_up2', 0)
  1739. command('nnoremap <ScrollWheelUp> <Cmd>let g:mouse_up += 1<CR>')
  1740. command('nnoremap <2-ScrollWheelUp> <Cmd>let g:mouse_up2 += 1<CR>')
  1741. feed('<ScrollWheelUp><0,0>')
  1742. feed('<ScrollWheelUp><0,0>')
  1743. api.nvim_input_mouse('wheel', 'up', '', 0, 0, 0)
  1744. api.nvim_input_mouse('wheel', 'up', '', 0, 0, 0)
  1745. eq(4, api.nvim_get_var('mouse_up'))
  1746. eq(0, api.nvim_get_var('mouse_up2'))
  1747. end)
  1748. it('<MouseMove> to different locations can be mapped', function()
  1749. api.nvim_set_var('mouse_move', 0)
  1750. api.nvim_set_var('mouse_move2', 0)
  1751. command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
  1752. command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
  1753. feed('<MouseMove><1,0>')
  1754. feed('<MouseMove><2,0>')
  1755. api.nvim_input_mouse('move', '', '', 0, 0, 3)
  1756. api.nvim_input_mouse('move', '', '', 0, 0, 4)
  1757. eq(4, api.nvim_get_var('mouse_move'))
  1758. eq(0, api.nvim_get_var('mouse_move2'))
  1759. end)
  1760. it('<MouseMove> to same location does not generate events #31103', function()
  1761. api.nvim_set_var('mouse_move', 0)
  1762. api.nvim_set_var('mouse_move2', 0)
  1763. command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
  1764. command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
  1765. api.nvim_input_mouse('move', '', '', 0, 0, 3)
  1766. eq(1, api.nvim_get_var('mouse_move'))
  1767. eq(0, api.nvim_get_var('mouse_move2'))
  1768. feed('<MouseMove><3,0>')
  1769. feed('<MouseMove><3,0>')
  1770. api.nvim_input_mouse('move', '', '', 0, 0, 3)
  1771. api.nvim_input_mouse('move', '', '', 0, 0, 3)
  1772. eq(1, api.nvim_get_var('mouse_move'))
  1773. eq(0, api.nvim_get_var('mouse_move2'))
  1774. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  1775. feed('<MouseMove><3,0><Insert>')
  1776. eq(1, api.nvim_get_var('mouse_move'))
  1777. eq(0, api.nvim_get_var('mouse_move2'))
  1778. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  1779. end)
  1780. it('feeding <MouseMove> in Normal mode does not use uninitialized memory #19480', function()
  1781. feed('<MouseMove>')
  1782. n.poke_eventloop()
  1783. n.assert_alive()
  1784. end)
  1785. it('mousemodel=popup_setpos', function()
  1786. screen:try_resize(80, 24)
  1787. exec([[
  1788. 5new
  1789. call setline(1, ['the dish ran away with the spoon',
  1790. \ 'the cow jumped over the moon' ])
  1791. set mouse=a mousemodel=popup_setpos
  1792. aunmenu PopUp
  1793. nmenu PopUp.foo :let g:menustr = 'foo'<CR>
  1794. nmenu PopUp.bar :let g:menustr = 'bar'<CR>
  1795. nmenu PopUp.baz :let g:menustr = 'baz'<CR>
  1796. vmenu PopUp.foo y:<C-U>let g:menustr = 'foo'<CR>
  1797. vmenu PopUp.bar y:<C-U>let g:menustr = 'bar'<CR>
  1798. vmenu PopUp.baz y:<C-U>let g:menustr = 'baz'<CR>
  1799. ]])
  1800. api.nvim_win_set_cursor(0, { 1, 0 })
  1801. api.nvim_input_mouse('right', 'press', '', 0, 0, 4)
  1802. api.nvim_input_mouse('right', 'release', '', 0, 0, 4)
  1803. feed('<Down><Down><CR>')
  1804. eq('bar', api.nvim_get_var('menustr'))
  1805. eq({ 1, 4 }, api.nvim_win_get_cursor(0))
  1806. -- Test for right click in visual mode inside the selection
  1807. fn.setreg('"', '')
  1808. api.nvim_win_set_cursor(0, { 1, 9 })
  1809. feed('vee')
  1810. api.nvim_input_mouse('right', 'press', '', 0, 0, 11)
  1811. api.nvim_input_mouse('right', 'release', '', 0, 0, 11)
  1812. feed('<Down><CR>')
  1813. eq({ 1, 9 }, api.nvim_win_get_cursor(0))
  1814. eq('ran away', fn.getreg('"'))
  1815. -- Test for right click in visual mode right before the selection
  1816. fn.setreg('"', '')
  1817. api.nvim_win_set_cursor(0, { 1, 9 })
  1818. feed('vee')
  1819. api.nvim_input_mouse('right', 'press', '', 0, 0, 8)
  1820. api.nvim_input_mouse('right', 'release', '', 0, 0, 8)
  1821. feed('<Down><CR>')
  1822. eq({ 1, 8 }, api.nvim_win_get_cursor(0))
  1823. eq('', fn.getreg('"'))
  1824. -- Test for right click in visual mode right after the selection
  1825. fn.setreg('"', '')
  1826. api.nvim_win_set_cursor(0, { 1, 9 })
  1827. feed('vee')
  1828. api.nvim_input_mouse('right', 'press', '', 0, 0, 17)
  1829. api.nvim_input_mouse('right', 'release', '', 0, 0, 17)
  1830. feed('<Down><CR>')
  1831. eq({ 1, 17 }, api.nvim_win_get_cursor(0))
  1832. eq('', fn.getreg('"'))
  1833. -- Test for right click in block-wise visual mode inside the selection
  1834. fn.setreg('"', '')
  1835. api.nvim_win_set_cursor(0, { 1, 15 })
  1836. feed('<C-V>j3l')
  1837. api.nvim_input_mouse('right', 'press', '', 0, 1, 16)
  1838. api.nvim_input_mouse('right', 'release', '', 0, 1, 16)
  1839. feed('<Down><CR>')
  1840. eq({ 1, 15 }, api.nvim_win_get_cursor(0))
  1841. eq('\0224', fn.getregtype('"'))
  1842. -- Test for right click in block-wise visual mode outside the selection
  1843. fn.setreg('"', '')
  1844. api.nvim_win_set_cursor(0, { 1, 15 })
  1845. feed('<C-V>j3l')
  1846. api.nvim_input_mouse('right', 'press', '', 0, 1, 1)
  1847. api.nvim_input_mouse('right', 'release', '', 0, 1, 1)
  1848. feed('<Down><CR>')
  1849. eq({ 2, 1 }, api.nvim_win_get_cursor(0))
  1850. eq('v', fn.getregtype('"'))
  1851. eq('', fn.getreg('"'))
  1852. -- Test for right click in line-wise visual mode inside the selection
  1853. fn.setreg('"', '')
  1854. api.nvim_win_set_cursor(0, { 1, 15 })
  1855. feed('V')
  1856. api.nvim_input_mouse('right', 'press', '', 0, 0, 9)
  1857. api.nvim_input_mouse('right', 'release', '', 0, 0, 9)
  1858. feed('<Down><CR>')
  1859. eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
  1860. eq('V', fn.getregtype('"'))
  1861. eq(1, #fn.getreg('"', 1, true))
  1862. -- Test for right click in multi-line line-wise visual mode inside the selection
  1863. fn.setreg('"', '')
  1864. api.nvim_win_set_cursor(0, { 1, 15 })
  1865. feed('Vj')
  1866. api.nvim_input_mouse('right', 'press', '', 0, 1, 19)
  1867. api.nvim_input_mouse('right', 'release', '', 0, 1, 19)
  1868. feed('<Down><CR>')
  1869. eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
  1870. eq('V', fn.getregtype('"'))
  1871. eq(2, #fn.getreg('"', 1, true))
  1872. -- Test for right click in line-wise visual mode outside the selection
  1873. fn.setreg('"', '')
  1874. api.nvim_win_set_cursor(0, { 1, 15 })
  1875. feed('V')
  1876. api.nvim_input_mouse('right', 'press', '', 0, 1, 9)
  1877. api.nvim_input_mouse('right', 'release', '', 0, 1, 9)
  1878. feed('<Down><CR>')
  1879. eq({ 2, 9 }, api.nvim_win_get_cursor(0))
  1880. eq('', fn.getreg('"'))
  1881. -- Try clicking outside the window
  1882. fn.setreg('"', '')
  1883. api.nvim_win_set_cursor(0, { 2, 1 })
  1884. feed('vee')
  1885. api.nvim_input_mouse('right', 'press', '', 0, 6, 1)
  1886. api.nvim_input_mouse('right', 'release', '', 0, 6, 1)
  1887. feed('<Down><CR>')
  1888. eq(2, fn.winnr())
  1889. eq('', fn.getreg('"'))
  1890. -- Test for right click in visual mode inside the selection with vertical splits
  1891. command('wincmd t')
  1892. command('rightbelow vsplit')
  1893. fn.setreg('"', '')
  1894. api.nvim_win_set_cursor(0, { 1, 9 })
  1895. feed('vee')
  1896. api.nvim_input_mouse('right', 'press', '', 0, 0, 52)
  1897. api.nvim_input_mouse('right', 'release', '', 0, 0, 52)
  1898. feed('<Down><CR>')
  1899. eq({ 1, 9 }, api.nvim_win_get_cursor(0))
  1900. eq('ran away', fn.getreg('"'))
  1901. -- Test for right click inside visual selection at bottom of window with winbar
  1902. command('setlocal winbar=WINBAR')
  1903. feed('2yyP')
  1904. fn.setreg('"', '')
  1905. feed('G$vbb')
  1906. api.nvim_input_mouse('right', 'press', '', 0, 4, 61)
  1907. api.nvim_input_mouse('right', 'release', '', 0, 4, 61)
  1908. feed('<Down><CR>')
  1909. eq({ 4, 20 }, api.nvim_win_get_cursor(0))
  1910. eq('the moon', fn.getreg('"'))
  1911. -- Try clicking in the cmdline
  1912. api.nvim_input_mouse('right', 'press', '', 0, 23, 0)
  1913. api.nvim_input_mouse('right', 'release', '', 0, 23, 0)
  1914. feed('<Down><Down><Down><CR>')
  1915. eq('baz', api.nvim_get_var('menustr'))
  1916. -- Try clicking in horizontal separator with global statusline
  1917. command('set laststatus=3')
  1918. api.nvim_input_mouse('right', 'press', '', 0, 5, 0)
  1919. api.nvim_input_mouse('right', 'release', '', 0, 5, 0)
  1920. feed('<Down><CR>')
  1921. eq('foo', api.nvim_get_var('menustr'))
  1922. -- Try clicking in the cmdline with global statusline
  1923. api.nvim_input_mouse('right', 'press', '', 0, 23, 0)
  1924. api.nvim_input_mouse('right', 'release', '', 0, 23, 0)
  1925. feed('<Down><Down><CR>')
  1926. eq('bar', api.nvim_get_var('menustr'))
  1927. end)
  1928. end)