WindowsInputProcessorTests.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. using System.Collections.Concurrent;
  2. using Terminal.Gui.ConsoleDrivers;
  3. using InputRecord = Terminal.Gui.WindowsConsole.InputRecord;
  4. using ButtonState = Terminal.Gui.WindowsConsole.ButtonState;
  5. using MouseEventRecord = Terminal.Gui.WindowsConsole.MouseEventRecord;
  6. namespace UnitTests.ConsoleDrivers.V2;
  7. public class WindowsInputProcessorTests
  8. {
  9. [Fact]
  10. public void Test_ProcessQueue_CapitalHLowerE ()
  11. {
  12. var queue = new ConcurrentQueue<InputRecord> ();
  13. queue.Enqueue (new InputRecord()
  14. {
  15. EventType = WindowsConsole.EventType.Key,
  16. KeyEvent = new WindowsConsole.KeyEventRecord ()
  17. {
  18. bKeyDown = true,
  19. UnicodeChar = 'H',
  20. dwControlKeyState = WindowsConsole.ControlKeyState.CapslockOn,
  21. wVirtualKeyCode = (ConsoleKeyMapping.VK)72,
  22. wVirtualScanCode = 35
  23. }
  24. });
  25. queue.Enqueue (new InputRecord ()
  26. {
  27. EventType = WindowsConsole.EventType.Key,
  28. KeyEvent = new WindowsConsole.KeyEventRecord ()
  29. {
  30. bKeyDown = false,
  31. UnicodeChar = 'H',
  32. dwControlKeyState = WindowsConsole.ControlKeyState.CapslockOn,
  33. wVirtualKeyCode = (ConsoleKeyMapping.VK)72,
  34. wVirtualScanCode = 35
  35. }
  36. });
  37. queue.Enqueue (new InputRecord ()
  38. {
  39. EventType = WindowsConsole.EventType.Key,
  40. KeyEvent = new WindowsConsole.KeyEventRecord ()
  41. {
  42. bKeyDown = true,
  43. UnicodeChar = 'i',
  44. dwControlKeyState = WindowsConsole.ControlKeyState.NoControlKeyPressed,
  45. wVirtualKeyCode = (ConsoleKeyMapping.VK)73,
  46. wVirtualScanCode = 23
  47. }
  48. });
  49. queue.Enqueue (new InputRecord ()
  50. {
  51. EventType = WindowsConsole.EventType.Key,
  52. KeyEvent = new WindowsConsole.KeyEventRecord ()
  53. {
  54. bKeyDown = false,
  55. UnicodeChar = 'i',
  56. dwControlKeyState = WindowsConsole.ControlKeyState.NoControlKeyPressed,
  57. wVirtualKeyCode = (ConsoleKeyMapping.VK)73,
  58. wVirtualScanCode = 23
  59. }
  60. });
  61. var processor = new WindowsInputProcessor (queue);
  62. List<Key> ups = new List<Key> ();
  63. List<Key> downs = new List<Key> ();
  64. processor.KeyUp += (s, e) => { ups.Add (e); };
  65. processor.KeyDown += (s, e) => { downs.Add (e); };
  66. Assert.Empty (ups);
  67. Assert.Empty (downs);
  68. processor.ProcessQueue ();
  69. Assert.Equal (Key.H.WithShift, ups [0]);
  70. Assert.Equal (Key.H.WithShift, downs [0]);
  71. Assert.Equal (Key.I, ups [1]);
  72. Assert.Equal (Key.I, downs [1]);
  73. }
  74. [Fact]
  75. public void Test_ProcessQueue_Mouse_Move ()
  76. {
  77. var queue = new ConcurrentQueue<InputRecord> ();
  78. queue.Enqueue (new InputRecord ()
  79. {
  80. EventType = WindowsConsole.EventType.Mouse,
  81. MouseEvent = new WindowsConsole.MouseEventRecord
  82. {
  83. MousePosition = new WindowsConsole.Coord(32,31),
  84. ButtonState = WindowsConsole.ButtonState.NoButtonPressed,
  85. ControlKeyState = WindowsConsole.ControlKeyState.NoControlKeyPressed,
  86. EventFlags = WindowsConsole.EventFlags.MouseMoved
  87. }
  88. });
  89. var processor = new WindowsInputProcessor (queue);
  90. List<MouseEventArgs> mouseEvents = new List<MouseEventArgs> ();
  91. processor.MouseEvent += (s, e) => { mouseEvents.Add (e); };
  92. Assert.Empty (mouseEvents);
  93. processor.ProcessQueue ();
  94. var s = Assert.Single (mouseEvents);
  95. Assert.Equal (s.Flags,MouseFlags.ReportMousePosition);
  96. Assert.Equal (s.ScreenPosition,new Point (32,31));
  97. }
  98. [Theory]
  99. [InlineData(WindowsConsole.ButtonState.Button1Pressed,MouseFlags.Button1Pressed)]
  100. [InlineData (WindowsConsole.ButtonState.Button2Pressed, MouseFlags.Button2Pressed)]
  101. [InlineData (WindowsConsole.ButtonState.Button3Pressed, MouseFlags.Button3Pressed)]
  102. [InlineData (WindowsConsole.ButtonState.Button4Pressed, MouseFlags.Button4Pressed)]
  103. internal void Test_ProcessQueue_Mouse_Pressed (WindowsConsole.ButtonState state,MouseFlags expectedFlag )
  104. {
  105. var queue = new ConcurrentQueue<InputRecord> ();
  106. queue.Enqueue (new InputRecord ()
  107. {
  108. EventType = WindowsConsole.EventType.Mouse,
  109. MouseEvent = new WindowsConsole.MouseEventRecord
  110. {
  111. MousePosition = new WindowsConsole.Coord (32, 31),
  112. ButtonState = state,
  113. ControlKeyState = WindowsConsole.ControlKeyState.NoControlKeyPressed,
  114. EventFlags = WindowsConsole.EventFlags.MouseMoved
  115. }
  116. });
  117. var processor = new WindowsInputProcessor (queue);
  118. List<MouseEventArgs> mouseEvents = new List<MouseEventArgs> ();
  119. processor.MouseEvent += (s, e) => { mouseEvents.Add (e); };
  120. Assert.Empty (mouseEvents);
  121. processor.ProcessQueue ();
  122. var s = Assert.Single (mouseEvents);
  123. Assert.Equal (s.Flags, MouseFlags.ReportMousePosition | expectedFlag);
  124. Assert.Equal (s.ScreenPosition, new Point (32, 31));
  125. }
  126. [Theory]
  127. [InlineData (100, MouseFlags.WheeledUp)]
  128. [InlineData ( -100, MouseFlags.WheeledDown)]
  129. internal void Test_ProcessQueue_Mouse_Wheel (int wheelValue, MouseFlags expectedFlag)
  130. {
  131. var queue = new ConcurrentQueue<InputRecord> ();
  132. queue.Enqueue (new InputRecord ()
  133. {
  134. EventType = WindowsConsole.EventType.Mouse,
  135. MouseEvent = new WindowsConsole.MouseEventRecord
  136. {
  137. MousePosition = new WindowsConsole.Coord (32, 31),
  138. ButtonState = (WindowsConsole.ButtonState)wheelValue,
  139. ControlKeyState = WindowsConsole.ControlKeyState.NoControlKeyPressed,
  140. EventFlags = WindowsConsole.EventFlags.MouseWheeled
  141. }
  142. });
  143. var processor = new WindowsInputProcessor (queue);
  144. List<MouseEventArgs> mouseEvents = new List<MouseEventArgs> ();
  145. processor.MouseEvent += (s, e) => { mouseEvents.Add (e); };
  146. Assert.Empty (mouseEvents);
  147. processor.ProcessQueue ();
  148. var s = Assert.Single (mouseEvents);
  149. Assert.Equal (s.Flags,expectedFlag);
  150. Assert.Equal (s.ScreenPosition, new Point (32, 31));
  151. }
  152. public static IEnumerable<object []> MouseFlagTestData ()
  153. {
  154. yield return new object []
  155. {
  156. new Tuple<ButtonState, MouseFlags>[]
  157. {
  158. Tuple.Create(ButtonState.Button1Pressed, MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition),
  159. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.Button1Released | MouseFlags.ReportMousePosition),
  160. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition)
  161. }
  162. };
  163. yield return new object []
  164. {
  165. new Tuple<ButtonState, MouseFlags>[]
  166. {
  167. Tuple.Create ( ButtonState.Button2Pressed, MouseFlags.Button2Pressed | MouseFlags.ReportMousePosition),
  168. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.Button2Released | MouseFlags.ReportMousePosition),
  169. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition)
  170. }
  171. };
  172. yield return new object []
  173. {
  174. new Tuple<ButtonState, MouseFlags>[]
  175. {
  176. Tuple.Create(ButtonState.Button3Pressed, MouseFlags.Button3Pressed | MouseFlags.ReportMousePosition),
  177. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.Button3Released | MouseFlags.ReportMousePosition),
  178. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition)
  179. }
  180. };
  181. yield return new object []
  182. {
  183. new Tuple<ButtonState, MouseFlags>[]
  184. {
  185. Tuple.Create(ButtonState.Button4Pressed, MouseFlags.Button4Pressed | MouseFlags.ReportMousePosition),
  186. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.Button4Released | MouseFlags.ReportMousePosition),
  187. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition)
  188. }
  189. };
  190. yield return new object []
  191. {
  192. new Tuple<ButtonState, MouseFlags>[]
  193. {
  194. Tuple.Create(ButtonState.RightmostButtonPressed, MouseFlags.Button3Pressed | MouseFlags.ReportMousePosition),
  195. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.Button3Released | MouseFlags.ReportMousePosition),
  196. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition | MouseFlags.ReportMousePosition)
  197. }
  198. };
  199. // Tests for holding down 2 buttons at once and releasing them one after the other
  200. yield return new object []
  201. {
  202. new Tuple<ButtonState, MouseFlags>[]
  203. {
  204. Tuple.Create(ButtonState.Button1Pressed | ButtonState.Button2Pressed, MouseFlags.Button1Pressed | MouseFlags.Button2Pressed | MouseFlags.ReportMousePosition),
  205. Tuple.Create(ButtonState.Button1Pressed, MouseFlags.Button1Pressed | MouseFlags.Button2Released | MouseFlags.ReportMousePosition),
  206. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.Button1Released | MouseFlags.ReportMousePosition),
  207. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition)
  208. }
  209. };
  210. yield return new object []
  211. {
  212. new Tuple<ButtonState, MouseFlags>[]
  213. {
  214. Tuple.Create(ButtonState.Button3Pressed | ButtonState.Button4Pressed, MouseFlags.Button3Pressed | MouseFlags.Button4Pressed | MouseFlags.ReportMousePosition),
  215. Tuple.Create(ButtonState.Button3Pressed, MouseFlags.Button3Pressed | MouseFlags.Button4Released | MouseFlags.ReportMousePosition),
  216. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.Button3Released | MouseFlags.ReportMousePosition),
  217. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition)
  218. }
  219. };
  220. // Test for holding down 2 buttons at once and releasing them simultaneously
  221. yield return new object []
  222. {
  223. new Tuple<ButtonState, MouseFlags>[]
  224. {
  225. Tuple.Create(ButtonState.Button1Pressed | ButtonState.Button2Pressed, MouseFlags.Button1Pressed | MouseFlags.Button2Pressed | MouseFlags.ReportMousePosition),
  226. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.Button1Released | MouseFlags.Button2Released | MouseFlags.ReportMousePosition),
  227. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition)
  228. }
  229. };
  230. // Test that rightmost and button 3 are the same button so 2 states is still only 1 flag
  231. yield return new object []
  232. {
  233. new Tuple<ButtonState, MouseFlags>[]
  234. {
  235. Tuple.Create(ButtonState.Button3Pressed | ButtonState.RightmostButtonPressed, MouseFlags.Button3Pressed | MouseFlags.ReportMousePosition),
  236. // Can swap between without raising the released
  237. Tuple.Create(ButtonState.Button3Pressed, MouseFlags.Button3Pressed | MouseFlags.ReportMousePosition),
  238. Tuple.Create(ButtonState.RightmostButtonPressed, MouseFlags.Button3Pressed | MouseFlags.ReportMousePosition),
  239. // Now with neither we get released
  240. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.Button3Released | MouseFlags.ReportMousePosition),
  241. Tuple.Create(ButtonState.NoButtonPressed, MouseFlags.ReportMousePosition)
  242. }
  243. };
  244. }
  245. [Theory]
  246. [MemberData (nameof (MouseFlagTestData))]
  247. internal void MouseFlags_Should_Map_Correctly (Tuple<ButtonState, MouseFlags>[] inputOutputPairs)
  248. {
  249. var processor = new WindowsInputProcessor (new ());
  250. foreach (var pair in inputOutputPairs)
  251. {
  252. var mockEvent = new MouseEventRecord { ButtonState = pair.Item1 };
  253. var result = processor.ToDriverMouse (mockEvent);
  254. Assert.Equal (pair.Item2, result.Flags);
  255. }
  256. }
  257. }