GetViewsUnderMouseTests.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. #nullable enable
  2. namespace Terminal.Gui.ViewMouseTests;
  3. [Trait ("Category", "Input")]
  4. public class GetViewsUnderMouseTests
  5. {
  6. [Theory]
  7. [InlineData (0, 0, 0, 0, 0, -1, -1, null)]
  8. [InlineData (0, 0, 0, 0, 0, 0, 0, typeof (Toplevel))]
  9. [InlineData (0, 0, 0, 0, 0, 1, 1, typeof (Toplevel))]
  10. [InlineData (0, 0, 0, 0, 0, 4, 4, typeof (Toplevel))]
  11. [InlineData (0, 0, 0, 0, 0, 9, 9, typeof (Toplevel))]
  12. [InlineData (0, 0, 0, 0, 0, 10, 10, null)]
  13. [InlineData (1, 1, 0, 0, 0, -1, -1, null)]
  14. [InlineData (1, 1, 0, 0, 0, 0, 0, null)]
  15. [InlineData (1, 1, 0, 0, 0, 1, 1, typeof (Toplevel))]
  16. [InlineData (1, 1, 0, 0, 0, 4, 4, typeof (Toplevel))]
  17. [InlineData (1, 1, 0, 0, 0, 9, 9, typeof (Toplevel))]
  18. [InlineData (1, 1, 0, 0, 0, 10, 10, typeof (Toplevel))]
  19. [InlineData (0, 0, 1, 0, 0, -1, -1, null)]
  20. [InlineData (0, 0, 1, 0, 0, 0, 0, typeof (Margin))]
  21. [InlineData (0, 0, 1, 0, 0, 1, 1, typeof (Toplevel))]
  22. [InlineData (0, 0, 1, 0, 0, 4, 4, typeof (Toplevel))]
  23. [InlineData (0, 0, 1, 0, 0, 9, 9, typeof (Margin))]
  24. [InlineData (0, 0, 1, 0, 0, 10, 10, null)]
  25. [InlineData (0, 0, 1, 1, 0, -1, -1, null)]
  26. [InlineData (0, 0, 1, 1, 0, 0, 0, typeof (Margin))]
  27. [InlineData (0, 0, 1, 1, 0, 1, 1, typeof (Border))]
  28. [InlineData (0, 0, 1, 1, 0, 4, 4, typeof (Toplevel))]
  29. [InlineData (0, 0, 1, 1, 0, 9, 9, typeof (Margin))]
  30. [InlineData (0, 0, 1, 1, 0, 10, 10, null)]
  31. [InlineData (0, 0, 1, 1, 1, -1, -1, null)]
  32. [InlineData (0, 0, 1, 1, 1, 0, 0, typeof (Margin))]
  33. [InlineData (0, 0, 1, 1, 1, 1, 1, typeof (Border))]
  34. [InlineData (0, 0, 1, 1, 1, 2, 2, typeof (Padding))]
  35. [InlineData (0, 0, 1, 1, 1, 4, 4, typeof (Toplevel))]
  36. [InlineData (0, 0, 1, 1, 1, 9, 9, typeof (Margin))]
  37. [InlineData (0, 0, 1, 1, 1, 10, 10, null)]
  38. [InlineData (1, 1, 1, 0, 0, -1, -1, null)]
  39. [InlineData (1, 1, 1, 0, 0, 0, 0, null)]
  40. [InlineData (1, 1, 1, 0, 0, 1, 1, typeof (Margin))]
  41. [InlineData (1, 1, 1, 0, 0, 4, 4, typeof (Toplevel))]
  42. [InlineData (1, 1, 1, 0, 0, 9, 9, typeof (Toplevel))]
  43. [InlineData (1, 1, 1, 0, 0, 10, 10, typeof (Margin))]
  44. [InlineData (1, 1, 1, 1, 0, -1, -1, null)]
  45. [InlineData (1, 1, 1, 1, 0, 0, 0, null)]
  46. [InlineData (1, 1, 1, 1, 0, 1, 1, typeof (Margin))]
  47. [InlineData (1, 1, 1, 1, 0, 4, 4, typeof (Toplevel))]
  48. [InlineData (1, 1, 1, 1, 0, 9, 9, typeof (Border))]
  49. [InlineData (1, 1, 1, 1, 0, 10, 10, typeof (Margin))]
  50. [InlineData (1, 1, 1, 1, 1, -1, -1, null)]
  51. [InlineData (1, 1, 1, 1, 1, 0, 0, null)]
  52. [InlineData (1, 1, 1, 1, 1, 1, 1, typeof (Margin))]
  53. [InlineData (1, 1, 1, 1, 1, 2, 2, typeof (Border))]
  54. [InlineData (1, 1, 1, 1, 1, 3, 3, typeof (Padding))]
  55. [InlineData (1, 1, 1, 1, 1, 4, 4, typeof (Toplevel))]
  56. [InlineData (1, 1, 1, 1, 1, 8, 8, typeof (Padding))]
  57. [InlineData (1, 1, 1, 1, 1, 9, 9, typeof (Border))]
  58. [InlineData (1, 1, 1, 1, 1, 10, 10, typeof (Margin))]
  59. public void GetViewsUnderMouse_Top_Adornments_Returns_Correct_View (
  60. int frameX,
  61. int frameY,
  62. int marginThickness,
  63. int borderThickness,
  64. int paddingThickness,
  65. int testX,
  66. int testY,
  67. Type? expectedViewType
  68. )
  69. {
  70. // Arrange
  71. Application.Top = new ()
  72. {
  73. Frame = new (frameX, frameY, 10, 10)
  74. };
  75. Application.Top.Margin!.Thickness = new (marginThickness);
  76. Application.Top.Border!.Thickness = new (borderThickness);
  77. Application.Top.Padding!.Thickness = new (paddingThickness);
  78. var location = new Point (testX, testY);
  79. // Act
  80. List<View?> viewsUnderMouse = View.GetViewsUnderMouse (location);
  81. // Assert
  82. if (expectedViewType == null)
  83. {
  84. Assert.Empty (viewsUnderMouse);
  85. }
  86. else
  87. {
  88. Assert.Contains (viewsUnderMouse, v => v?.GetType () == expectedViewType);
  89. }
  90. Application.Top.Dispose ();
  91. Application.ResetState (true);
  92. }
  93. [Theory]
  94. [InlineData (0, 0)]
  95. [InlineData (1, 1)]
  96. [InlineData (2, 2)]
  97. public void GetViewsUnderMouse_Returns_Top_If_No_SubViews (int testX, int testY)
  98. {
  99. // Arrange
  100. Application.Top = new ()
  101. {
  102. Frame = new (0, 0, 10, 10)
  103. };
  104. var location = new Point (testX, testY);
  105. // Act
  106. List<View?> viewsUnderMouse = View.GetViewsUnderMouse (location);
  107. // Assert
  108. Assert.Contains (viewsUnderMouse, v => v == Application.Top);
  109. Application.Top.Dispose ();
  110. Application.ResetState (true);
  111. }
  112. [Theory]
  113. [InlineData (0, 0, false)]
  114. [InlineData (1, 1, true)]
  115. [InlineData (9, 9, false)]
  116. [InlineData (10, 10, false)]
  117. [InlineData (6, 7, true)]
  118. [InlineData (1, 2, true)]
  119. [InlineData (5, 6, true)]
  120. public void GetViewsUnderMouse_Returns_Correct_If_SubViews (int testX, int testY, bool expected)
  121. {
  122. // Arrange
  123. Application.Top = new ()
  124. {
  125. Frame = new (0, 0, 10, 10)
  126. };
  127. var subView = new View
  128. {
  129. Frame = new (1, 1, 8, 8)
  130. };
  131. Application.Top.Add (subView);
  132. var location = new Point (testX, testY);
  133. // Act
  134. List<View?> viewsUnderMouse = View.GetViewsUnderMouse (location);
  135. // Assert
  136. if (expected)
  137. {
  138. Assert.Contains (viewsUnderMouse, v => v == subView);
  139. }
  140. else
  141. {
  142. Assert.DoesNotContain (viewsUnderMouse, v => v == subView);
  143. }
  144. Application.Top.Dispose ();
  145. Application.ResetState (true);
  146. }
  147. // Test that GetViewsUnderMouse returns the correct view if the start view has no subviews
  148. [Theory]
  149. [InlineData (0, 0)]
  150. [InlineData (1, 1)]
  151. [InlineData (2, 2)]
  152. public void Returns_Start_If_No_SubViews (int testX, int testY)
  153. {
  154. Application.Top = new ()
  155. {
  156. Width = 10, Height = 10
  157. };
  158. Assert.Same (Application.Top, View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ());
  159. Application.Top.Dispose ();
  160. Application.ResetState (true);
  161. }
  162. // Test that GetViewsUnderMouse returns null if the start view has no subviews and coords are outside the view
  163. [Theory]
  164. [InlineData (0, 0)]
  165. [InlineData (2, 1)]
  166. [InlineData (20, 20)]
  167. public void Returns_Null_If_No_SubViews_Coords_Outside (int testX, int testY)
  168. {
  169. Application.Top = new ()
  170. {
  171. X = 1, Y = 2,
  172. Width = 10, Height = 10
  173. };
  174. Assert.Null (View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ());
  175. Application.Top.Dispose ();
  176. Application.ResetState (true);
  177. }
  178. [Theory]
  179. [InlineData (0, 0)]
  180. [InlineData (2, 1)]
  181. [InlineData (20, 20)]
  182. public void Returns_Null_If_Start_Not_Visible (int testX, int testY)
  183. {
  184. Application.Top = new ()
  185. {
  186. X = 1, Y = 2,
  187. Width = 10, Height = 10,
  188. Visible = false
  189. };
  190. Assert.Null (View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ());
  191. Application.Top.Dispose ();
  192. Application.ResetState (true);
  193. }
  194. // Test that GetViewsUnderMouse returns the correct view if the start view has subviews
  195. [Theory]
  196. [InlineData (0, 0, false)]
  197. [InlineData (1, 1, false)]
  198. [InlineData (9, 9, false)]
  199. [InlineData (10, 10, false)]
  200. [InlineData (6, 7, false)]
  201. [InlineData (1, 2, true)]
  202. [InlineData (5, 6, true)]
  203. public void Returns_Correct_If_SubViews (int testX, int testY, bool expectedSubViewFound)
  204. {
  205. Application.Top = new ()
  206. {
  207. Width = 10, Height = 10
  208. };
  209. var subview = new View
  210. {
  211. X = 1, Y = 2,
  212. Width = 5, Height = 5
  213. };
  214. Application.Top.Add (subview);
  215. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  216. Assert.Equal (expectedSubViewFound, found == subview);
  217. Application.Top.Dispose ();
  218. Application.ResetState (true);
  219. }
  220. [Theory]
  221. [InlineData (0, 0, false)]
  222. [InlineData (1, 1, false)]
  223. [InlineData (9, 9, false)]
  224. [InlineData (10, 10, false)]
  225. [InlineData (6, 7, false)]
  226. [InlineData (1, 2, false)]
  227. [InlineData (5, 6, false)]
  228. public void Returns_Null_If_SubView_NotVisible (int testX, int testY, bool expectedSubViewFound)
  229. {
  230. Application.Top = new ()
  231. {
  232. Width = 10, Height = 10
  233. };
  234. var subview = new View
  235. {
  236. X = 1, Y = 2,
  237. Width = 5, Height = 5,
  238. Visible = false
  239. };
  240. Application.Top.Add (subview);
  241. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  242. Assert.Equal (expectedSubViewFound, found == subview);
  243. Application.Top.Dispose ();
  244. Application.ResetState (true);
  245. }
  246. [Theory]
  247. [InlineData (0, 0, false)]
  248. [InlineData (1, 1, false)]
  249. [InlineData (9, 9, false)]
  250. [InlineData (10, 10, false)]
  251. [InlineData (6, 7, false)]
  252. [InlineData (1, 2, false)]
  253. [InlineData (5, 6, false)]
  254. public void Returns_Null_If_Not_Visible_And_SubView_Visible (int testX, int testY, bool expectedSubViewFound)
  255. {
  256. Application.Top = new ()
  257. {
  258. Width = 10, Height = 10,
  259. Visible = false
  260. };
  261. var subview = new View
  262. {
  263. X = 1, Y = 2,
  264. Width = 5, Height = 5
  265. };
  266. Application.Top.Add (subview);
  267. subview.Visible = true;
  268. Assert.True (subview.Visible);
  269. Assert.False (Application.Top.Visible);
  270. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  271. Assert.Equal (expectedSubViewFound, found == subview);
  272. Application.Top.Dispose ();
  273. Application.ResetState (true);
  274. }
  275. // Test that GetViewsUnderMouse works if the start view has positive Adornments
  276. [Theory]
  277. [InlineData (0, 0, false)]
  278. [InlineData (1, 1, false)]
  279. [InlineData (9, 9, false)]
  280. [InlineData (10, 10, false)]
  281. [InlineData (7, 8, false)]
  282. [InlineData (1, 2, false)]
  283. [InlineData (2, 3, true)]
  284. [InlineData (5, 6, true)]
  285. [InlineData (6, 7, true)]
  286. public void Returns_Correct_If_Start_Has_Adornments (int testX, int testY, bool expectedSubViewFound)
  287. {
  288. Application.Top = new ()
  289. {
  290. Width = 10, Height = 10
  291. };
  292. Application.Top.Margin!.Thickness = new (1);
  293. var subview = new View
  294. {
  295. X = 1, Y = 2,
  296. Width = 5, Height = 5
  297. };
  298. Application.Top.Add (subview);
  299. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  300. Assert.Equal (expectedSubViewFound, found == subview);
  301. Application.Top.Dispose ();
  302. Application.ResetState (true);
  303. }
  304. // Test that GetViewsUnderMouse works if the start view has offset Viewport location
  305. [Theory]
  306. [InlineData (1, 0, 0, true)]
  307. [InlineData (1, 1, 1, true)]
  308. [InlineData (1, 2, 2, false)]
  309. [InlineData (-1, 3, 3, true)]
  310. [InlineData (-1, 2, 2, true)]
  311. [InlineData (-1, 1, 1, false)]
  312. [InlineData (-1, 0, 0, false)]
  313. public void Returns_Correct_If_Start_Has_Offset_Viewport (int offset, int testX, int testY, bool expectedSubViewFound)
  314. {
  315. Application.Top = new ()
  316. {
  317. Width = 10, Height = 10,
  318. ViewportSettings = ViewportSettings.AllowNegativeLocation
  319. };
  320. Application.Top.Viewport = new (offset, offset, 10, 10);
  321. var subview = new View
  322. {
  323. X = 1, Y = 1,
  324. Width = 2, Height = 2
  325. };
  326. Application.Top.Add (subview);
  327. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  328. Assert.Equal (expectedSubViewFound, found == subview);
  329. Application.Top.Dispose ();
  330. Application.ResetState (true);
  331. }
  332. [Theory]
  333. [InlineData (9, 9, true)]
  334. [InlineData (0, 0, false)]
  335. [InlineData (1, 1, false)]
  336. [InlineData (10, 10, false)]
  337. [InlineData (7, 8, false)]
  338. [InlineData (1, 2, false)]
  339. [InlineData (2, 3, false)]
  340. [InlineData (5, 6, false)]
  341. [InlineData (6, 7, false)]
  342. public void Returns_Correct_If_Start_Has_Adornment_WithSubView (int testX, int testY, bool expectedSubViewFound)
  343. {
  344. Application.Top = new ()
  345. {
  346. Width = 10, Height = 10
  347. };
  348. Application.Top.Padding!.Thickness = new (1);
  349. var subview = new View
  350. {
  351. X = Pos.AnchorEnd (1), Y = Pos.AnchorEnd (1),
  352. Width = 1, Height = 1
  353. };
  354. Application.Top.Padding.Add (subview);
  355. Application.Top.BeginInit ();
  356. Application.Top.EndInit ();
  357. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  358. Assert.Equal (expectedSubViewFound, found == subview);
  359. Application.Top.Dispose ();
  360. Application.ResetState (true);
  361. }
  362. [Theory]
  363. [InlineData (0, 0, typeof (Margin))]
  364. [InlineData (9, 9, typeof (Margin))]
  365. [InlineData (1, 1, typeof (Border))]
  366. [InlineData (8, 8, typeof (Border))]
  367. [InlineData (2, 2, typeof (Padding))]
  368. [InlineData (7, 7, typeof (Padding))]
  369. [InlineData (5, 5, typeof (Toplevel))]
  370. public void Returns_Adornment_If_Start_Has_Adornments (int testX, int testY, Type expectedAdornmentType)
  371. {
  372. Application.Top = new ()
  373. {
  374. Width = 10, Height = 10
  375. };
  376. Application.Top.Margin!.Thickness = new (1);
  377. Application.Top.Border!.Thickness = new (1);
  378. Application.Top.Padding!.Thickness = new (1);
  379. var subview = new View
  380. {
  381. X = 1, Y = 1,
  382. Width = 1, Height = 1
  383. };
  384. Application.Top.Add (subview);
  385. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  386. Assert.Equal (expectedAdornmentType, found!.GetType ());
  387. Application.Top.Dispose ();
  388. Application.ResetState (true);
  389. }
  390. // Test that GetViewsUnderMouse works if the subview has positive Adornments
  391. [Theory]
  392. [InlineData (0, 0, false)]
  393. [InlineData (1, 1, false)]
  394. [InlineData (9, 9, false)]
  395. [InlineData (10, 10, false)]
  396. [InlineData (7, 8, false)]
  397. [InlineData (6, 7, false)]
  398. [InlineData (1, 2, false)]
  399. [InlineData (5, 6, false)]
  400. [InlineData (2, 3, true)]
  401. public void Returns_Correct_If_SubView_Has_Adornments (int testX, int testY, bool expectedSubViewFound)
  402. {
  403. Application.Top = new ()
  404. {
  405. Width = 10, Height = 10
  406. };
  407. var subview = new View
  408. {
  409. X = 1, Y = 2,
  410. Width = 5, Height = 5
  411. };
  412. subview.Margin!.Thickness = new (1);
  413. Application.Top.Add (subview);
  414. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  415. Assert.Equal (expectedSubViewFound, found == subview);
  416. Application.Top.Dispose ();
  417. Application.ResetState (true);
  418. }
  419. [Theory]
  420. [InlineData (0, 0, false)]
  421. [InlineData (1, 1, false)]
  422. [InlineData (9, 9, false)]
  423. [InlineData (10, 10, false)]
  424. [InlineData (7, 8, false)]
  425. [InlineData (6, 7, false)]
  426. [InlineData (1, 2, false)]
  427. [InlineData (5, 6, false)]
  428. [InlineData (6, 5, false)]
  429. [InlineData (5, 5, true)]
  430. public void Returns_Correct_If_SubView_Has_Adornment_WithSubView (int testX, int testY, bool expectedSubViewFound)
  431. {
  432. Application.Top = new ()
  433. {
  434. Width = 10, Height = 10
  435. };
  436. // A subview with + Padding
  437. var subview = new View
  438. {
  439. X = 1, Y = 1,
  440. Width = 5, Height = 5
  441. };
  442. subview.Padding!.Thickness = new (1);
  443. // This subview will be at the bottom-right-corner of subview
  444. // So screen-relative location will be X + Width - 1 = 5
  445. var paddingSubView = new View
  446. {
  447. X = Pos.AnchorEnd (1),
  448. Y = Pos.AnchorEnd (1),
  449. Width = 1,
  450. Height = 1
  451. };
  452. subview.Padding.Add (paddingSubView);
  453. Application.Top.Add (subview);
  454. Application.Top.BeginInit ();
  455. Application.Top.EndInit ();
  456. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  457. Assert.Equal (expectedSubViewFound, found == paddingSubView);
  458. Application.Top.Dispose ();
  459. Application.ResetState (true);
  460. }
  461. [Theory]
  462. [InlineData (0, 0, false)]
  463. [InlineData (1, 1, false)]
  464. [InlineData (9, 9, false)]
  465. [InlineData (10, 10, false)]
  466. [InlineData (7, 8, false)]
  467. [InlineData (6, 7, false)]
  468. [InlineData (1, 2, false)]
  469. [InlineData (5, 6, false)]
  470. [InlineData (6, 5, false)]
  471. [InlineData (5, 5, true)]
  472. public void Returns_Correct_If_SubView_Is_Scrolled_And_Has_Adornment_WithSubView (int testX, int testY, bool expectedSubViewFound)
  473. {
  474. Application.Top = new ()
  475. {
  476. Width = 10, Height = 10
  477. };
  478. // A subview with + Padding
  479. var subview = new View
  480. {
  481. X = 1, Y = 1,
  482. Width = 5, Height = 5
  483. };
  484. subview.Padding!.Thickness = new (1);
  485. // Scroll the subview
  486. subview.SetContentSize (new (10, 10));
  487. subview.Viewport = subview.Viewport with { Location = new (1, 1) };
  488. // This subview will be at the bottom-right-corner of subview
  489. // So screen-relative location will be X + Width - 1 = 5
  490. var paddingSubView = new View
  491. {
  492. X = Pos.AnchorEnd (1),
  493. Y = Pos.AnchorEnd (1),
  494. Width = 1,
  495. Height = 1
  496. };
  497. subview.Padding.Add (paddingSubView);
  498. Application.Top.Add (subview);
  499. Application.Top.BeginInit ();
  500. Application.Top.EndInit ();
  501. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  502. Assert.Equal (expectedSubViewFound, found == paddingSubView);
  503. Application.Top.Dispose ();
  504. Application.ResetState (true);
  505. }
  506. // Test that GetViewsUnderMouse works with nested subviews
  507. [Theory]
  508. [InlineData (0, 0, -1)]
  509. [InlineData (9, 9, -1)]
  510. [InlineData (10, 10, -1)]
  511. [InlineData (1, 1, 0)]
  512. [InlineData (1, 2, 0)]
  513. [InlineData (2, 2, 1)]
  514. [InlineData (3, 3, 2)]
  515. [InlineData (5, 5, 2)]
  516. public void Returns_Correct_With_NestedSubViews (int testX, int testY, int expectedSubViewFound)
  517. {
  518. Application.Top = new ()
  519. {
  520. Width = 10, Height = 10
  521. };
  522. var numSubViews = 3;
  523. List<View> subviews = new ();
  524. for (var i = 0; i < numSubViews; i++)
  525. {
  526. var subview = new View
  527. {
  528. X = 1, Y = 1,
  529. Width = 5, Height = 5
  530. };
  531. subviews.Add (subview);
  532. if (i > 0)
  533. {
  534. subviews [i - 1].Add (subview);
  535. }
  536. }
  537. Application.Top.Add (subviews [0]);
  538. View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
  539. Assert.Equal (expectedSubViewFound, subviews.IndexOf (found!));
  540. Application.Top.Dispose ();
  541. Application.ResetState (true);
  542. }
  543. [Theory]
  544. [InlineData (0, 0, new [] { "top" })]
  545. [InlineData (9, 9, new [] { "top" })]
  546. [InlineData (10, 10, new string [] { })]
  547. [InlineData (1, 1, new [] { "top", "view" })]
  548. [InlineData (1, 2, new [] { "top", "view" })]
  549. [InlineData (2, 1, new [] { "top", "view" })]
  550. [InlineData (2, 2, new [] { "top", "view", "subView" })]
  551. [InlineData (3, 3, new [] { "top" })] // clipped
  552. [InlineData (2, 3, new [] { "top" })] // clipped
  553. public void GetViewsUnderMouse_Tiled_SubViews (int mouseX, int mouseY, string [] viewIdStrings)
  554. {
  555. // Arrange
  556. Application.Top = new ()
  557. {
  558. Frame = new (0, 0, 10, 10),
  559. Id = "top"
  560. };
  561. var view = new View
  562. {
  563. Id = "view",
  564. X = 1,
  565. Y = 1,
  566. Width = 2,
  567. Height = 2,
  568. Arrangement = ViewArrangement.Overlapped
  569. }; // at 1,1 to 3,2 (screen)
  570. var subView = new View
  571. {
  572. Id = "subView",
  573. X = 1,
  574. Y = 1,
  575. Width = 2,
  576. Height = 2,
  577. Arrangement = ViewArrangement.Overlapped
  578. }; // at 2,2 to 4,3 (screen)
  579. view.Add (subView);
  580. Application.Top.Add (view);
  581. List<View?> found = View.GetViewsUnderMouse (new (mouseX, mouseY));
  582. string [] foundIds = found.Select (v => v!.Id).ToArray ();
  583. Assert.Equal (viewIdStrings, foundIds);
  584. Application.Top.Dispose ();
  585. Application.ResetState (true);
  586. }
  587. }