MouseDeviceTests.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. using Avalonia.Controls;
  2. using Avalonia.Input.Raw;
  3. using Avalonia.Interactivity;
  4. using Avalonia.Media;
  5. using Avalonia.Rendering;
  6. using Avalonia.UnitTests;
  7. using Avalonia.VisualTree;
  8. using Moq;
  9. using System;
  10. using System.Collections.Generic;
  11. using Xunit;
  12. namespace Avalonia.Input.UnitTests
  13. {
  14. public class MouseDeviceTests
  15. {
  16. [Fact]
  17. public void Capture_Is_Transferred_To_Parent_When_Control_Removed()
  18. {
  19. Canvas control;
  20. var root = new TestRoot
  21. {
  22. Child = control = new Canvas(),
  23. };
  24. var target = new MouseDevice();
  25. target.Capture(control);
  26. Assert.Same(control, target.Captured);
  27. root.Child = null;
  28. Assert.Same(root, target.Captured);
  29. }
  30. [Fact]
  31. public void MouseMove_Should_Update_IsPointerOver()
  32. {
  33. var renderer = new Mock<IRenderer>();
  34. using (TestApplication(renderer.Object))
  35. {
  36. var inputManager = InputManager.Instance;
  37. Canvas canvas;
  38. Border border;
  39. Decorator decorator;
  40. var root = new TestRoot
  41. {
  42. MouseDevice = new MouseDevice(),
  43. Renderer = renderer.Object,
  44. Child = new Panel
  45. {
  46. Children =
  47. {
  48. (canvas = new Canvas()),
  49. (border = new Border
  50. {
  51. Child = decorator = new Decorator(),
  52. })
  53. }
  54. }
  55. };
  56. SetHit(renderer, decorator);
  57. SendMouseMove(inputManager, root);
  58. Assert.True(decorator.IsPointerOver);
  59. Assert.True(border.IsPointerOver);
  60. Assert.False(canvas.IsPointerOver);
  61. Assert.True(root.IsPointerOver);
  62. SetHit(renderer, canvas);
  63. SendMouseMove(inputManager, root);
  64. Assert.False(decorator.IsPointerOver);
  65. Assert.False(border.IsPointerOver);
  66. Assert.True(canvas.IsPointerOver);
  67. Assert.True(root.IsPointerOver);
  68. }
  69. }
  70. [Fact]
  71. public void IsPointerOver_Should_Be_Updated_When_Child_Sets_Handled_True()
  72. {
  73. var renderer = new Mock<IRenderer>();
  74. using (TestApplication(renderer.Object))
  75. {
  76. var inputManager = InputManager.Instance;
  77. Canvas canvas;
  78. Border border;
  79. Decorator decorator;
  80. var root = new TestRoot
  81. {
  82. MouseDevice = new MouseDevice(),
  83. Renderer = renderer.Object,
  84. Child = new Panel
  85. {
  86. Children =
  87. {
  88. (canvas = new Canvas()),
  89. (border = new Border
  90. {
  91. Child = decorator = new Decorator(),
  92. })
  93. }
  94. }
  95. };
  96. SetHit(renderer, canvas);
  97. SendMouseMove(inputManager, root);
  98. Assert.False(decorator.IsPointerOver);
  99. Assert.False(border.IsPointerOver);
  100. Assert.True(canvas.IsPointerOver);
  101. Assert.True(root.IsPointerOver);
  102. // Ensure that e.Handled is reset between controls.
  103. decorator.PointerEnter += (s, e) => e.Handled = true;
  104. SetHit(renderer, decorator);
  105. SendMouseMove(inputManager, root);
  106. Assert.True(decorator.IsPointerOver);
  107. Assert.True(border.IsPointerOver);
  108. Assert.False(canvas.IsPointerOver);
  109. Assert.True(root.IsPointerOver);
  110. }
  111. }
  112. [Fact]
  113. public void PointerEnter_Leave_Should_Be_Raised_In_Correct_Order()
  114. {
  115. var renderer = new Mock<IRenderer>();
  116. var result = new List<(object, string)>();
  117. void HandleEvent(object sender, PointerEventArgs e)
  118. {
  119. result.Add((sender, e.RoutedEvent.Name));
  120. }
  121. using (TestApplication(renderer.Object))
  122. {
  123. var inputManager = InputManager.Instance;
  124. Canvas canvas;
  125. Border border;
  126. Decorator decorator;
  127. var root = new TestRoot
  128. {
  129. MouseDevice = new MouseDevice(),
  130. Renderer = renderer.Object,
  131. Child = new Panel
  132. {
  133. Children =
  134. {
  135. (canvas = new Canvas()),
  136. (border = new Border
  137. {
  138. Child = decorator = new Decorator(),
  139. })
  140. }
  141. }
  142. };
  143. SetHit(renderer, canvas);
  144. SendMouseMove(inputManager, root);
  145. AddEnterLeaveHandlers(HandleEvent, root, canvas, border, decorator);
  146. SetHit(renderer, decorator);
  147. SendMouseMove(inputManager, root);
  148. Assert.Equal(
  149. new[]
  150. {
  151. ((object)canvas, "PointerLeave"),
  152. ((object)decorator, "PointerEnter"),
  153. ((object)border, "PointerEnter"),
  154. },
  155. result);
  156. }
  157. }
  158. [Fact]
  159. public void GetPosition_Should_Respect_Control_RenderTransform()
  160. {
  161. var renderer = new Mock<IRenderer>();
  162. using (TestApplication(renderer.Object))
  163. {
  164. var inputManager = InputManager.Instance;
  165. var root = new TestRoot
  166. {
  167. MouseDevice = new MouseDevice(),
  168. Child = new Border
  169. {
  170. Background = Brushes.Black,
  171. RenderTransform = new TranslateTransform(10, 0),
  172. }
  173. };
  174. SendMouseMove(inputManager, root, new Point(11, 11));
  175. var result = root.MouseDevice.GetPosition(root.Child);
  176. Assert.Equal(new Point(1, 11), result);
  177. }
  178. }
  179. private void AddEnterLeaveHandlers(
  180. EventHandler<PointerEventArgs> handler,
  181. params IControl[] controls)
  182. {
  183. foreach (var c in controls)
  184. {
  185. c.PointerEnter += handler;
  186. c.PointerLeave += handler;
  187. }
  188. }
  189. private void SendMouseMove(IInputManager inputManager, TestRoot root, Point p = new Point())
  190. {
  191. inputManager.ProcessInput(new RawPointerEventArgs(
  192. root.MouseDevice,
  193. 0,
  194. root,
  195. RawPointerEventType.Move,
  196. p,
  197. RawInputModifiers.None));
  198. }
  199. private void SetHit(Mock<IRenderer> renderer, IControl hit)
  200. {
  201. renderer.Setup(x => x.HitTest(It.IsAny<Point>(), It.IsAny<IVisual>(), It.IsAny<Func<IVisual, bool>>()))
  202. .Returns(new[] { hit });
  203. }
  204. private IDisposable TestApplication(IRenderer renderer)
  205. {
  206. return UnitTestApplication.Start(
  207. new TestServices(inputManager: new InputManager()));
  208. }
  209. }
  210. }