MouseTests.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. using UnitTests;
  2. namespace Terminal.Gui.ViewMouseTests;
  3. [Trait ("Category", "Input")]
  4. public class MouseTests : TestsAllViews
  5. {
  6. // TODO: Add more tests that ensure the above test works with positive adornments
  7. // Test drag to move
  8. [Theory]
  9. [InlineData (0, 0, 0, 0, false)]
  10. [InlineData (0, 0, 0, 4, false)]
  11. [InlineData (1, 0, 0, 4, false)]
  12. [InlineData (0, 1, 0, 4, true)]
  13. [InlineData (0, 0, 1, 4, false)]
  14. [InlineData (1, 1, 0, 3, false)]
  15. [InlineData (1, 1, 0, 4, false)]
  16. [InlineData (1, 1, 0, 5, true)]
  17. [InlineData (1, 1, 0, 6, false)]
  18. [InlineData (1, 1, 0, 11, false)]
  19. [InlineData (1, 1, 0, 12, true)]
  20. [InlineData (1, 1, 0, 13, false)]
  21. [InlineData (1, 1, 0, 14, false)]
  22. [AutoInitShutdown]
  23. public void ButtonPressed_In_Border_Starts_Drag (int marginThickness, int borderThickness, int paddingThickness, int xy, bool expectedMoved)
  24. {
  25. var testView = new View
  26. {
  27. CanFocus = true,
  28. X = 4,
  29. Y = 4,
  30. Width = 10,
  31. Height = 10,
  32. Arrangement = ViewArrangement.Movable
  33. };
  34. testView.Margin.Thickness = new (marginThickness);
  35. testView.Border.Thickness = new (borderThickness);
  36. testView.Padding.Thickness = new (paddingThickness);
  37. var top = new Toplevel ();
  38. top.Add (testView);
  39. RunState rs = Application.Begin (top);
  40. Assert.Equal (4, testView.Frame.X);
  41. Assert.Equal (new (4, 4), testView.Frame.Location);
  42. Application.RaiseMouseEvent (new () { ScreenPosition = new (xy, xy), Flags = MouseFlags.Button1Pressed });
  43. Application.RaiseMouseEvent (new () { ScreenPosition = new (xy + 1, xy + 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition });
  44. Application.RunIteration (ref rs);
  45. Assert.Equal (expectedMoved, new Point (5, 5) == testView.Frame.Location);
  46. top.Dispose ();
  47. }
  48. [Theory]
  49. [InlineData (MouseFlags.Button1Pressed, MouseFlags.Button1Released, MouseFlags.Button1Clicked)]
  50. [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released, MouseFlags.Button2Clicked)]
  51. [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released, MouseFlags.Button3Clicked)]
  52. [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released, MouseFlags.Button4Clicked)]
  53. public void WantContinuousButtonPressed_False_Button_Press_Release_DoesNotClick (MouseFlags pressed, MouseFlags released, MouseFlags clicked)
  54. {
  55. var me = new MouseEventArgs ();
  56. var view = new View
  57. {
  58. Width = 1,
  59. Height = 1,
  60. WantContinuousButtonPressed = false
  61. };
  62. var clickedCount = 0;
  63. view.MouseClick += (s, e) => clickedCount++;
  64. me.Flags = pressed;
  65. view.NewMouseEvent (me);
  66. Assert.Equal (0, clickedCount);
  67. me.Handled = false;
  68. me.Flags = pressed;
  69. view.NewMouseEvent (me);
  70. Assert.Equal (0, clickedCount);
  71. me.Handled = false;
  72. me.Flags = released;
  73. view.NewMouseEvent (me);
  74. Assert.Equal (0, clickedCount);
  75. me.Handled = false;
  76. me.Flags = clicked;
  77. view.NewMouseEvent (me);
  78. Assert.Equal (1, clickedCount);
  79. view.Dispose ();
  80. // Button1Pressed, Button1Released cause Application.MouseGrabView to be set
  81. Application.ResetState (true);
  82. }
  83. [Theory]
  84. [InlineData (MouseFlags.Button1Clicked)]
  85. [InlineData (MouseFlags.Button2Clicked)]
  86. [InlineData (MouseFlags.Button3Clicked)]
  87. [InlineData (MouseFlags.Button4Clicked)]
  88. public void WantContinuousButtonPressed_True_Button_Clicked_Raises_MouseClick (MouseFlags clicked)
  89. {
  90. var me = new MouseEventArgs ();
  91. var view = new View
  92. {
  93. Width = 1,
  94. Height = 1,
  95. WantContinuousButtonPressed = true
  96. };
  97. var clickedCount = 0;
  98. view.MouseClick += (s, e) => clickedCount++;
  99. me.Flags = clicked;
  100. view.NewMouseEvent (me);
  101. Assert.Equal (1, clickedCount);
  102. view.Dispose ();
  103. // Button1Pressed, Button1Released cause Application.MouseGrabView to be set
  104. Application.ResetState (true);
  105. }
  106. [Theory]
  107. [InlineData (MouseFlags.Button1Clicked)]
  108. [InlineData (MouseFlags.Button2Clicked)]
  109. [InlineData (MouseFlags.Button3Clicked)]
  110. [InlineData (MouseFlags.Button4Clicked)]
  111. public void WantContinuousButtonPressed_True_Button_Clicked_Raises_Selecting (MouseFlags clicked)
  112. {
  113. var me = new MouseEventArgs ();
  114. var view = new View
  115. {
  116. Width = 1,
  117. Height = 1,
  118. WantContinuousButtonPressed = true
  119. };
  120. var selectingCount = 0;
  121. view.Selecting += (s, e) => selectingCount++;
  122. me.Flags = clicked;
  123. view.NewMouseEvent (me);
  124. Assert.Equal (1, selectingCount);
  125. view.Dispose ();
  126. // Button1Pressed, Button1Released cause Application.MouseGrabView to be set
  127. Application.ResetState (true);
  128. }
  129. [Theory]
  130. [InlineData (MouseFlags.Button1Pressed, MouseFlags.Button1Released)]
  131. [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released)]
  132. [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released)]
  133. [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released)]
  134. public void WantContinuousButtonPressed_True_And_WantMousePositionReports_True_Button_Press_Release_Clicks (MouseFlags pressed, MouseFlags released)
  135. {
  136. var me = new MouseEventArgs ();
  137. var view = new View
  138. {
  139. Width = 1,
  140. Height = 1,
  141. WantContinuousButtonPressed = true,
  142. WantMousePositionReports = true
  143. };
  144. var clickedCount = 0;
  145. view.MouseClick += (s, e) => clickedCount++;
  146. me.Flags = pressed;
  147. view.NewMouseEvent (me);
  148. Assert.Equal (0, clickedCount);
  149. me.Handled = false;
  150. me.Flags = pressed;
  151. view.NewMouseEvent (me);
  152. Assert.Equal (1, clickedCount);
  153. me.Handled = false;
  154. me.Flags = released;
  155. view.NewMouseEvent (me);
  156. Assert.Equal (1, clickedCount);
  157. view.Dispose ();
  158. // Button1Pressed, Button1Released cause Application.MouseGrabView to be set
  159. Application.ResetState (true);
  160. }
  161. [Theory]
  162. [InlineData (MouseFlags.Button1Pressed, MouseFlags.Button1Released, MouseFlags.Button1Clicked)]
  163. [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released, MouseFlags.Button2Clicked)]
  164. [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released, MouseFlags.Button3Clicked)]
  165. [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released, MouseFlags.Button4Clicked)]
  166. public void WantContinuousButtonPressed_True_And_WantMousePositionReports_True_Button_Press_Release_Clicks_Repeatedly (
  167. MouseFlags pressed,
  168. MouseFlags released,
  169. MouseFlags clicked
  170. )
  171. {
  172. var me = new MouseEventArgs ();
  173. var view = new View
  174. {
  175. Width = 1,
  176. Height = 1,
  177. WantContinuousButtonPressed = true,
  178. WantMousePositionReports = true
  179. };
  180. var clickedCount = 0;
  181. view.MouseClick += (s, e) => clickedCount++;
  182. me.Flags = pressed;
  183. view.NewMouseEvent (me);
  184. Assert.Equal (0, clickedCount);
  185. me.Handled = false;
  186. me.Flags = pressed;
  187. view.NewMouseEvent (me);
  188. Assert.Equal (1, clickedCount);
  189. me.Handled = false;
  190. me.Flags = released;
  191. view.NewMouseEvent (me);
  192. Assert.Equal (1, clickedCount);
  193. me.Handled = false;
  194. me.Flags = clicked;
  195. view.NewMouseEvent (me);
  196. Assert.Equal (1, clickedCount);
  197. view.Dispose ();
  198. // Button1Pressed, Button1Released cause Application.MouseGrabView to be set
  199. Application.ResetState (true);
  200. }
  201. [Fact]
  202. public void WantContinuousButtonPressed_True_And_WantMousePositionReports_True_Move_InViewport_OutOfViewport_Keeps_Counting ()
  203. {
  204. var me = new MouseEventArgs ();
  205. var view = new View
  206. {
  207. Width = 1,
  208. Height = 1,
  209. WantContinuousButtonPressed = true,
  210. WantMousePositionReports = true
  211. };
  212. var clickedCount = 0;
  213. view.MouseClick += (s, e) => clickedCount++;
  214. // Start in Viewport
  215. me.Flags = MouseFlags.Button1Pressed;
  216. me.Position = me.Position with { X = 0 };
  217. view.NewMouseEvent (me);
  218. Assert.Equal (0, clickedCount);
  219. me.Handled = false;
  220. // Move out of Viewport
  221. me.Flags = MouseFlags.Button1Pressed;
  222. me.Position = me.Position with { X = 1 };
  223. view.NewMouseEvent (me);
  224. Assert.Equal (1, clickedCount);
  225. me.Handled = false;
  226. // Move into Viewport
  227. me.Flags = MouseFlags.Button1Pressed;
  228. me.Position = me.Position with { X = 0 };
  229. view.NewMouseEvent (me);
  230. Assert.Equal (2, clickedCount);
  231. me.Handled = false;
  232. view.Dispose ();
  233. // Button1Pressed, Button1Released cause Application.MouseGrabView to be set
  234. Application.ResetState (true);
  235. }
  236. [Theory]
  237. [InlineData (HighlightStyle.None, 0, 0)]
  238. [InlineData (HighlightStyle.Pressed | HighlightStyle.PressedOutside, 1, 1)]
  239. public void HighlightOnPress_Fires_Events_And_Highlights (HighlightStyle highlightOnPress, int expectedEnabling, int expectedDisabling)
  240. {
  241. var view = new View
  242. {
  243. CanFocus = true,
  244. HighlightStyle = highlightOnPress,
  245. Height = 1,
  246. Width = 1
  247. };
  248. var enablingHighlight = 0;
  249. var disablingHighlight = 0;
  250. view.Highlight += ViewHighlight;
  251. view.ColorScheme = new (new Attribute (ColorName16.Red, ColorName16.Blue));
  252. ColorScheme originalColorScheme = view.ColorScheme;
  253. view.NewMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
  254. if (highlightOnPress != HighlightStyle.None)
  255. {
  256. Assert.NotEqual (originalColorScheme, view.ColorScheme);
  257. }
  258. else
  259. {
  260. Assert.Equal (originalColorScheme, view.ColorScheme);
  261. }
  262. view.NewMouseEvent (new () { Flags = MouseFlags.Button1Released });
  263. Assert.Equal (originalColorScheme, view.ColorScheme);
  264. Assert.Equal (expectedEnabling, enablingHighlight);
  265. Assert.Equal (expectedDisabling, disablingHighlight);
  266. view.Dispose ();
  267. // Button1Pressed, Button1Released cause Application.MouseGrabView to be set
  268. Application.ResetState (true);
  269. return;
  270. void ViewHighlight (object sender, CancelEventArgs<HighlightStyle> e)
  271. {
  272. if (e.NewValue == HighlightStyle.None)
  273. {
  274. disablingHighlight++;
  275. }
  276. else
  277. {
  278. enablingHighlight++;
  279. }
  280. }
  281. }
  282. // TODO: Add tests for each combination of HighlightFlags
  283. [Theory]
  284. [InlineData (0)]
  285. [InlineData (1)]
  286. [InlineData (10)]
  287. public void HighlightOnPress_Move_Keeps_Highlight (int x)
  288. {
  289. var view = new View
  290. {
  291. CanFocus = true,
  292. HighlightStyle = HighlightStyle.Pressed | HighlightStyle.PressedOutside,
  293. Height = 1,
  294. Width = 1
  295. };
  296. var enablingHighlight = 0;
  297. var disablingHighlight = 0;
  298. view.Highlight += ViewHighlight;
  299. bool inViewport = view.Viewport.Contains (x, 0);
  300. // Start at 0,0 ; in viewport
  301. view.NewMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
  302. Assert.Equal (1, enablingHighlight);
  303. Assert.Equal (0, disablingHighlight);
  304. // Move to x,0
  305. view.NewMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
  306. if (inViewport)
  307. {
  308. Assert.Equal (2, enablingHighlight);
  309. Assert.Equal (0, disablingHighlight);
  310. }
  311. else
  312. {
  313. Assert.Equal (2, enablingHighlight);
  314. Assert.Equal (0, disablingHighlight);
  315. }
  316. // Move backto 0,0 ; in viewport
  317. view.NewMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
  318. if (inViewport)
  319. {
  320. Assert.Equal (3, enablingHighlight);
  321. Assert.Equal (0, disablingHighlight);
  322. }
  323. else
  324. {
  325. Assert.Equal (3, enablingHighlight);
  326. Assert.Equal (0, disablingHighlight);
  327. }
  328. view.Dispose ();
  329. // Button1Pressed, Button1Released cause Application.MouseGrabView to be set
  330. Application.ResetState (true);
  331. return;
  332. void ViewHighlight (object sender, CancelEventArgs<HighlightStyle> e)
  333. {
  334. if (e.NewValue == HighlightStyle.None)
  335. {
  336. disablingHighlight++;
  337. }
  338. else
  339. {
  340. enablingHighlight++;
  341. }
  342. }
  343. }
  344. }