FakeMainLoop.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using System;
  2. using System.Threading;
  3. namespace Terminal.Gui {
  4. /// <summary>
  5. /// Mainloop intended to be used with the .NET System.Console API, and can
  6. /// be used on Windows and Unix, it is cross platform but lacks things like
  7. /// file descriptor monitoring.
  8. /// </summary>
  9. /// <remarks>
  10. /// This implementation is used for FakeDriver.
  11. /// </remarks>
  12. public class FakeMainLoop : IMainLoopDriver {
  13. AutoResetEvent keyReady = new AutoResetEvent (false);
  14. AutoResetEvent waitForProbe = new AutoResetEvent (false);
  15. ConsoleKeyInfo? keyResult = null;
  16. MainLoop mainLoop;
  17. //Func<ConsoleKeyInfo> consoleKeyReaderFn = () => ;
  18. /// <summary>
  19. /// Invoked when a Key is pressed.
  20. /// </summary>
  21. public Action<ConsoleKeyInfo> KeyPressed;
  22. /// <summary>
  23. /// Creates an instance of the FakeMainLoop. <paramref name="consoleDriver"/> is not used.
  24. /// </summary>
  25. /// <param name="consoleDriver"></param>
  26. public FakeMainLoop (ConsoleDriver consoleDriver = null)
  27. {
  28. // consoleDriver is not needed/used in FakeConsole
  29. }
  30. void MockKeyReader ()
  31. {
  32. while (true) {
  33. waitForProbe.WaitOne ();
  34. keyResult = FakeConsole.ReadKey (true);
  35. keyReady.Set ();
  36. }
  37. }
  38. void IMainLoopDriver.Setup (MainLoop mainLoop)
  39. {
  40. this.mainLoop = mainLoop;
  41. Thread readThread = new Thread (MockKeyReader);
  42. readThread.Start ();
  43. }
  44. void IMainLoopDriver.Wakeup ()
  45. {
  46. }
  47. bool IMainLoopDriver.EventsPending (bool wait)
  48. {
  49. keyResult = null;
  50. waitForProbe.Set ();
  51. if (CheckTimers (wait, out var waitTimeout)) {
  52. return true;
  53. }
  54. keyReady.WaitOne (waitTimeout);
  55. return keyResult.HasValue;
  56. }
  57. bool CheckTimers (bool wait, out int waitTimeout)
  58. {
  59. long now = DateTime.UtcNow.Ticks;
  60. if (mainLoop.timeouts.Count > 0) {
  61. waitTimeout = (int)((mainLoop.timeouts.Keys [0] - now) / TimeSpan.TicksPerMillisecond);
  62. if (waitTimeout < 0)
  63. return true;
  64. } else {
  65. waitTimeout = -1;
  66. }
  67. if (!wait)
  68. waitTimeout = 0;
  69. int ic;
  70. lock (mainLoop.idleHandlers) {
  71. ic = mainLoop.idleHandlers.Count;
  72. }
  73. return ic > 0;
  74. }
  75. void IMainLoopDriver.Iteration ()
  76. {
  77. if (keyResult.HasValue) {
  78. KeyPressed?.Invoke (keyResult.Value);
  79. keyResult = null;
  80. }
  81. }
  82. }
  83. }