|
@@ -113,7 +113,9 @@ namespace Terminal.Gui {
|
|
ConsoleDriver consoleDriver;
|
|
ConsoleDriver consoleDriver;
|
|
volatile ConsoleKeyInfo [] cki = null;
|
|
volatile ConsoleKeyInfo [] cki = null;
|
|
static volatile bool isEscSeq;
|
|
static volatile bool isEscSeq;
|
|
- bool stopTasks;
|
|
|
|
|
|
+
|
|
|
|
+ internal CancellationTokenSource TokenSource = new CancellationTokenSource ();
|
|
|
|
+
|
|
#if PROCESS_REQUEST
|
|
#if PROCESS_REQUEST
|
|
bool neededProcessRequest;
|
|
bool neededProcessRequest;
|
|
#endif
|
|
#endif
|
|
@@ -125,21 +127,13 @@ namespace Terminal.Gui {
|
|
throw new ArgumentNullException ("Console driver instance must be provided.");
|
|
throw new ArgumentNullException ("Console driver instance must be provided.");
|
|
}
|
|
}
|
|
this.consoleDriver = consoleDriver;
|
|
this.consoleDriver = consoleDriver;
|
|
- Task.Run (ProcessInputResultQueue);
|
|
|
|
- Task.Run (CheckWinChange);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- internal void StopTasks ()
|
|
|
|
- {
|
|
|
|
- stopTasks = true;
|
|
|
|
|
|
+ Task.Run (ProcessInputResultQueue, TokenSource.Token);
|
|
|
|
+ Task.Run (CheckWinChange, TokenSource.Token);
|
|
}
|
|
}
|
|
|
|
|
|
public InputResult? ReadConsoleInput ()
|
|
public InputResult? ReadConsoleInput ()
|
|
{
|
|
{
|
|
- while (true) {
|
|
|
|
- if (stopTasks) {
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
|
|
+ while (!TokenSource.IsCancellationRequested) {
|
|
waitForStart.Set ();
|
|
waitForStart.Set ();
|
|
winChange.Set ();
|
|
winChange.Set ();
|
|
|
|
|
|
@@ -154,11 +148,13 @@ namespace Terminal.Gui {
|
|
return inputResultQueue.Dequeue ();
|
|
return inputResultQueue.Dequeue ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return null;
|
|
}
|
|
}
|
|
|
|
|
|
void ProcessInputResultQueue ()
|
|
void ProcessInputResultQueue ()
|
|
{
|
|
{
|
|
- while (true) {
|
|
|
|
|
|
+ while (!TokenSource.IsCancellationRequested) {
|
|
waitForStart.Wait ();
|
|
waitForStart.Wait ();
|
|
waitForStart.Reset ();
|
|
waitForStart.Reset ();
|
|
|
|
|
|
@@ -176,8 +172,23 @@ namespace Terminal.Gui {
|
|
ConsoleModifiers mod = 0;
|
|
ConsoleModifiers mod = 0;
|
|
ConsoleKeyInfo newConsoleKeyInfo = default;
|
|
ConsoleKeyInfo newConsoleKeyInfo = default;
|
|
|
|
|
|
- while (true) {
|
|
|
|
- ConsoleKeyInfo consoleKeyInfo = Console.ReadKey (true);
|
|
|
|
|
|
+ while (!TokenSource.IsCancellationRequested) {
|
|
|
|
+ ConsoleKeyInfo consoleKeyInfo = default;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ if (Console.KeyAvailable) {
|
|
|
|
+ consoleKeyInfo = Console.ReadKey (true);
|
|
|
|
+ } else {
|
|
|
|
+ Task.Delay (100, TokenSource.Token).Wait (TokenSource.Token);
|
|
|
|
+ if (Console.KeyAvailable) {
|
|
|
|
+ consoleKeyInfo = Console.ReadKey (true);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (OperationCanceledException) {
|
|
|
|
+
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
if ((consoleKeyInfo.KeyChar == (char)Key.Esc && !isEscSeq)
|
|
if ((consoleKeyInfo.KeyChar == (char)Key.Esc && !isEscSeq)
|
|
|| (consoleKeyInfo.KeyChar != (char)Key.Esc && isEscSeq)) {
|
|
|| (consoleKeyInfo.KeyChar != (char)Key.Esc && isEscSeq)) {
|
|
if (cki == null && consoleKeyInfo.KeyChar != (char)Key.Esc && isEscSeq) {
|
|
if (cki == null && consoleKeyInfo.KeyChar != (char)Key.Esc && isEscSeq) {
|
|
@@ -201,18 +212,19 @@ namespace Terminal.Gui {
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
} else {
|
|
} else {
|
|
- GetConsoleInputType (consoleKeyInfo);
|
|
|
|
- break;
|
|
|
|
|
|
+ if (consoleKeyInfo != default) {
|
|
|
|
+ GetConsoleInputType (consoleKeyInfo);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ TokenSource.Token.ThrowIfCancellationRequested ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CheckWinChange ()
|
|
void CheckWinChange ()
|
|
{
|
|
{
|
|
- while (true) {
|
|
|
|
- if (stopTasks) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ while (!TokenSource.IsCancellationRequested) {
|
|
winChange.Wait ();
|
|
winChange.Wait ();
|
|
winChange.Reset ();
|
|
winChange.Reset ();
|
|
WaitWinChange ();
|
|
WaitWinChange ();
|
|
@@ -222,13 +234,16 @@ namespace Terminal.Gui {
|
|
|
|
|
|
void WaitWinChange ()
|
|
void WaitWinChange ()
|
|
{
|
|
{
|
|
- while (true) {
|
|
|
|
- // Wait for a while then check if screen has changed sizes
|
|
|
|
- Task.Delay (500).Wait ();
|
|
|
|
|
|
+ while (!TokenSource.IsCancellationRequested) {
|
|
|
|
+ try {
|
|
|
|
+ // Wait for a while then check if screen has changed sizes
|
|
|
|
+ Task.Delay (500, TokenSource.Token).Wait (TokenSource.Token);
|
|
|
|
+
|
|
|
|
+ } catch (OperationCanceledException) {
|
|
|
|
|
|
- if (stopTasks) {
|
|
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+
|
|
int buffHeight, buffWidth;
|
|
int buffHeight, buffWidth;
|
|
if (((NetDriver)consoleDriver).IsWinPlatform) {
|
|
if (((NetDriver)consoleDriver).IsWinPlatform) {
|
|
buffHeight = Math.Max (Console.BufferHeight, 0);
|
|
buffHeight = Math.Max (Console.BufferHeight, 0);
|
|
@@ -691,7 +706,7 @@ namespace Terminal.Gui {
|
|
|
|
|
|
public override void End ()
|
|
public override void End ()
|
|
{
|
|
{
|
|
- mainLoop.netEvents.StopTasks ();
|
|
|
|
|
|
+ mainLoop.Dispose ();
|
|
|
|
|
|
if (IsWinPlatform) {
|
|
if (IsWinPlatform) {
|
|
NetWinConsole.Cleanup ();
|
|
NetWinConsole.Cleanup ();
|
|
@@ -1019,8 +1034,28 @@ namespace Terminal.Gui {
|
|
|
|
|
|
public override void Suspend ()
|
|
public override void Suspend ()
|
|
{
|
|
{
|
|
- }
|
|
|
|
|
|
+ if (Environment.OSVersion.Platform != PlatformID.Unix) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ StopReportingMouseMoves ();
|
|
|
|
+ Console.ResetColor ();
|
|
|
|
+ Console.Clear ();
|
|
|
|
+
|
|
|
|
+ //Disable alternative screen buffer.
|
|
|
|
+ Console.Out.Write ("\x1b[?1049l");
|
|
|
|
+
|
|
|
|
+ //Set cursor key to cursor.
|
|
|
|
+ Console.Out.Write ("\x1b[?25h");
|
|
|
|
+
|
|
|
|
+ Platform.Suspend ();
|
|
|
|
+
|
|
|
|
+ //Enable alternative screen buffer.
|
|
|
|
+ Console.Out.Write ("\x1b[?1049h");
|
|
|
|
|
|
|
|
+ Application.Refresh ();
|
|
|
|
+ StartReportingMouseMoves ();
|
|
|
|
+ }
|
|
|
|
|
|
public override void SetAttribute (Attribute c)
|
|
public override void SetAttribute (Attribute c)
|
|
{
|
|
{
|
|
@@ -1343,7 +1378,11 @@ namespace Terminal.Gui {
|
|
public override bool SetCursorVisibility (CursorVisibility visibility)
|
|
public override bool SetCursorVisibility (CursorVisibility visibility)
|
|
{
|
|
{
|
|
savedCursorVisibility = visibility;
|
|
savedCursorVisibility = visibility;
|
|
- return Console.CursorVisible = visibility == CursorVisibility.Default;
|
|
|
|
|
|
+ Console.Out.Write (visibility == CursorVisibility.Default
|
|
|
|
+ ? "\x1b[?25h"
|
|
|
|
+ : "\x1b[?25l");
|
|
|
|
+
|
|
|
|
+ return visibility == CursorVisibility.Default;
|
|
}
|
|
}
|
|
|
|
|
|
/// <inheritdoc/>
|
|
/// <inheritdoc/>
|
|
@@ -1423,7 +1462,7 @@ namespace Terminal.Gui {
|
|
/// <remarks>
|
|
/// <remarks>
|
|
/// This implementation is used for NetDriver.
|
|
/// This implementation is used for NetDriver.
|
|
/// </remarks>
|
|
/// </remarks>
|
|
- internal class NetMainLoop : IMainLoopDriver {
|
|
|
|
|
|
+ internal class NetMainLoop : IMainLoopDriver, IDisposable {
|
|
ManualResetEventSlim keyReady = new ManualResetEventSlim (false);
|
|
ManualResetEventSlim keyReady = new ManualResetEventSlim (false);
|
|
ManualResetEventSlim waitForProbe = new ManualResetEventSlim (false);
|
|
ManualResetEventSlim waitForProbe = new ManualResetEventSlim (false);
|
|
Queue<NetEvents.InputResult?> inputResult = new Queue<NetEvents.InputResult?> ();
|
|
Queue<NetEvents.InputResult?> inputResult = new Queue<NetEvents.InputResult?> ();
|
|
@@ -1453,27 +1492,25 @@ namespace Terminal.Gui {
|
|
|
|
|
|
void NetInputHandler ()
|
|
void NetInputHandler ()
|
|
{
|
|
{
|
|
- while (true) {
|
|
|
|
|
|
+ while (!tokenSource.IsCancellationRequested) {
|
|
waitForProbe.Wait ();
|
|
waitForProbe.Wait ();
|
|
waitForProbe.Reset ();
|
|
waitForProbe.Reset ();
|
|
if (inputResult.Count == 0) {
|
|
if (inputResult.Count == 0) {
|
|
inputResult.Enqueue (netEvents.ReadConsoleInput ());
|
|
inputResult.Enqueue (netEvents.ReadConsoleInput ());
|
|
}
|
|
}
|
|
- try {
|
|
|
|
- while (inputResult.Peek () == null) {
|
|
|
|
- inputResult.Dequeue ();
|
|
|
|
- }
|
|
|
|
- if (inputResult.Count > 0) {
|
|
|
|
- keyReady.Set ();
|
|
|
|
- }
|
|
|
|
- } catch (InvalidOperationException) { }
|
|
|
|
|
|
+ while (inputResult.Count > 0 && inputResult.Peek () == null) {
|
|
|
|
+ inputResult.Dequeue ();
|
|
|
|
+ }
|
|
|
|
+ if (inputResult.Count > 0) {
|
|
|
|
+ keyReady.Set ();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void IMainLoopDriver.Setup (MainLoop mainLoop)
|
|
void IMainLoopDriver.Setup (MainLoop mainLoop)
|
|
{
|
|
{
|
|
this.mainLoop = mainLoop;
|
|
this.mainLoop = mainLoop;
|
|
- Task.Run (NetInputHandler);
|
|
|
|
|
|
+ Task.Run (NetInputHandler, tokenSource.Token);
|
|
}
|
|
}
|
|
|
|
|
|
void IMainLoopDriver.Wakeup ()
|
|
void IMainLoopDriver.Wakeup ()
|
|
@@ -1503,8 +1540,7 @@ namespace Terminal.Gui {
|
|
return inputResult.Count > 0 || CheckTimers (wait, out _);
|
|
return inputResult.Count > 0 || CheckTimers (wait, out _);
|
|
}
|
|
}
|
|
|
|
|
|
- tokenSource.Dispose ();
|
|
|
|
- tokenSource = new CancellationTokenSource ();
|
|
|
|
|
|
+ tokenSource.Token.ThrowIfCancellationRequested ();
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1537,5 +1573,11 @@ namespace Terminal.Gui {
|
|
ProcessInput?.Invoke (inputResult.Dequeue ().Value);
|
|
ProcessInput?.Invoke (inputResult.Dequeue ().Value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ public void Dispose ()
|
|
|
|
+ {
|
|
|
|
+ tokenSource.Cancel ();
|
|
|
|
+ netEvents.TokenSource.Cancel ();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|