mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Try to fix NetDriver compilation
This commit is contained in:
@@ -1804,7 +1804,7 @@ public static class EscSeqUtils
|
||||
/// <summary>
|
||||
/// The terminal reply to <see cref="CSI_RequestCursorPositionReport"/>. ESC [ ? (y) ; (x) R
|
||||
/// </summary>
|
||||
public static readonly string CSI_RequestCursorPositionReport_Terminator = "R";
|
||||
public const string CSI_RequestCursorPositionReport_Terminator = "R";
|
||||
|
||||
/// <summary>
|
||||
/// ESC [ 0 c - Send Device Attributes (Primary DA)
|
||||
@@ -1855,13 +1855,13 @@ public static class EscSeqUtils
|
||||
/// <summary>
|
||||
/// The terminator indicating a reply to <see cref="CSI_ReportTerminalSizeInChars"/> : ESC [ 8 ; height ; width t
|
||||
/// </summary>
|
||||
public static readonly string CSI_ReportTerminalSizeInChars_Terminator = "t";
|
||||
public const string CSI_ReportTerminalSizeInChars_Terminator = "t";
|
||||
|
||||
/// <summary>
|
||||
/// The value of the response to <see cref="CSI_ReportTerminalSizeInChars"/> indicating value 1 and 2 are the terminal
|
||||
/// size in chars.
|
||||
/// </summary>
|
||||
public static readonly string CSI_ReportTerminalSizeInChars_ResponseValue = "8";
|
||||
public const string CSI_ReportTerminalSizeInChars_ResponseValue = "8";
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -40,6 +40,9 @@ public class FakeDriver : ConsoleDriver
|
||||
public static Behaviors FakeBehaviors = new ();
|
||||
public override bool SupportsTrueColor => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void WriteRaw (string ansi) { throw new NotImplementedException (); }
|
||||
|
||||
public FakeDriver ()
|
||||
{
|
||||
Cols = FakeConsole.WindowWidth = FakeConsole.BufferWidth = FakeConsole.WIDTH;
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
// NetDriver.cs: The System.Console-based .NET driver, works on Windows and Unix, but is not particularly efficient.
|
||||
//
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Terminal.Gui.NetEvents;
|
||||
|
||||
@@ -11,9 +13,11 @@ namespace Terminal.Gui;
|
||||
|
||||
internal class NetDriver : ConsoleDriver
|
||||
{
|
||||
|
||||
public bool IsWinPlatform { get; private set; }
|
||||
public NetWinVTConsole? NetWinConsole { get; private set; }
|
||||
|
||||
|
||||
public override void Suspend ()
|
||||
{
|
||||
if (Environment.OSVersion.Platform != PlatformID.Unix)
|
||||
@@ -132,33 +136,30 @@ internal class NetDriver : ConsoleDriver
|
||||
{
|
||||
output.Append (
|
||||
EscSeqUtils.CSI_SetGraphicsRendition (
|
||||
MapColors (
|
||||
(ConsoleColor)attr.Background
|
||||
.GetClosestNamedColor16 (),
|
||||
false
|
||||
),
|
||||
MapColors (
|
||||
(ConsoleColor)attr.Foreground
|
||||
.GetClosestNamedColor16 ())
|
||||
)
|
||||
MapColors (
|
||||
(ConsoleColor)attr.Background.GetClosestNamedColor16 (),
|
||||
false
|
||||
),
|
||||
MapColors ((ConsoleColor)attr.Foreground.GetClosestNamedColor16 ())
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
output.Append (
|
||||
EscSeqUtils.CSI_SetForegroundColorRGB (
|
||||
attr.Foreground.R,
|
||||
attr.Foreground.G,
|
||||
attr.Foreground.B
|
||||
)
|
||||
attr.Foreground.R,
|
||||
attr.Foreground.G,
|
||||
attr.Foreground.B
|
||||
)
|
||||
);
|
||||
|
||||
output.Append (
|
||||
EscSeqUtils.CSI_SetBackgroundColorRGB (
|
||||
attr.Background.R,
|
||||
attr.Background.G,
|
||||
attr.Background.B
|
||||
)
|
||||
attr.Background.R,
|
||||
attr.Background.G,
|
||||
attr.Background.B
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -221,10 +222,17 @@ internal class NetDriver : ConsoleDriver
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
#region Init/End/MainLoop
|
||||
|
||||
/// <inheritdoc />
|
||||
internal override IAnsiResponseParser GetParser () => _mainLoopDriver._netEvents.Parser;
|
||||
internal NetMainLoop? _mainLoopDriver;
|
||||
/// <inheritdoc />
|
||||
internal override void RawWrite (string str)
|
||||
{
|
||||
Console.Write (str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override MainLoop Init ()
|
||||
{
|
||||
@@ -236,7 +244,7 @@ internal class NetDriver : ConsoleDriver
|
||||
|
||||
try
|
||||
{
|
||||
NetWinConsole = new ();
|
||||
NetWinConsole = new NetWinVTConsole ();
|
||||
}
|
||||
catch (ApplicationException)
|
||||
{
|
||||
@@ -295,6 +303,7 @@ internal class NetDriver : ConsoleDriver
|
||||
_mainLoopDriver.ProcessInput = ProcessInput;
|
||||
|
||||
return new (_mainLoopDriver);
|
||||
return new MainLoop (_mainLoopDriver);
|
||||
}
|
||||
|
||||
private void ProcessInput (InputResult inputEvent)
|
||||
@@ -323,7 +332,6 @@ internal class NetDriver : ConsoleDriver
|
||||
break;
|
||||
case EventType.Mouse:
|
||||
MouseEventArgs me = ToDriverMouse (inputEvent.MouseEvent);
|
||||
|
||||
//Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}");
|
||||
OnMouseEvent (me);
|
||||
|
||||
@@ -334,7 +342,7 @@ internal class NetDriver : ConsoleDriver
|
||||
Left = 0;
|
||||
Cols = inputEvent.WindowSizeEvent.Size.Width;
|
||||
Rows = Math.Max (inputEvent.WindowSizeEvent.Size.Height, 0);
|
||||
|
||||
;
|
||||
ResizeScreen ();
|
||||
ClearContents ();
|
||||
_winSizeChanging = false;
|
||||
@@ -349,7 +357,6 @@ internal class NetDriver : ConsoleDriver
|
||||
throw new ArgumentOutOfRangeException ();
|
||||
}
|
||||
}
|
||||
|
||||
public override void End ()
|
||||
{
|
||||
if (IsWinPlatform)
|
||||
@@ -374,6 +381,9 @@ internal class NetDriver : ConsoleDriver
|
||||
|
||||
#endregion Init/End/MainLoop
|
||||
|
||||
|
||||
|
||||
|
||||
#region Color Handling
|
||||
|
||||
public override bool SupportsTrueColor => Environment.OSVersion.Platform == PlatformID.Unix
|
||||
@@ -787,4 +797,4 @@ internal class NetDriver : ConsoleDriver
|
||||
}
|
||||
|
||||
#endregion Low-Level DotNet tuff
|
||||
}
|
||||
}
|
||||
@@ -1,238 +1,150 @@
|
||||
#nullable enable
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Terminal.Gui;
|
||||
|
||||
internal class NetEvents : IDisposable
|
||||
{
|
||||
private readonly ManualResetEventSlim _inputReady = new (false);
|
||||
private CancellationTokenSource? _inputReadyCancellationTokenSource;
|
||||
private readonly Queue<InputResult> _inputQueue = new ();
|
||||
private readonly IConsoleDriver _consoleDriver;
|
||||
private ConsoleKeyInfo []? _cki;
|
||||
private bool _isEscSeq;
|
||||
#if PROCESS_REQUEST
|
||||
bool _neededProcessRequest;
|
||||
#endif
|
||||
public NetEvents (IConsoleDriver consoleDriver)
|
||||
private readonly CancellationTokenSource _netEventsDisposed = new CancellationTokenSource ();
|
||||
|
||||
//CancellationTokenSource _waitForStartCancellationTokenSource;
|
||||
private readonly ManualResetEventSlim _winChange = new (false);
|
||||
private readonly BlockingCollection<InputResult?> _inputQueue = new (new ConcurrentQueue<InputResult?> ());
|
||||
private readonly ConsoleDriver _consoleDriver;
|
||||
|
||||
public AnsiResponseParser<ConsoleKeyInfo> Parser { get; private set; } = new ();
|
||||
|
||||
public NetEvents (ConsoleDriver consoleDriver)
|
||||
{
|
||||
_consoleDriver = consoleDriver ?? throw new ArgumentNullException (nameof (consoleDriver));
|
||||
_inputReadyCancellationTokenSource = new ();
|
||||
|
||||
Task.Run (ProcessInputQueue, _inputReadyCancellationTokenSource.Token);
|
||||
|
||||
Task.Run (CheckWindowSizeChange, _inputReadyCancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
public InputResult? DequeueInput ()
|
||||
{
|
||||
while (_inputReadyCancellationTokenSource is { Token.IsCancellationRequested: false })
|
||||
Task.Run (() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_inputReadyCancellationTokenSource.Token.IsCancellationRequested)
|
||||
{
|
||||
if (_inputQueue.Count == 0)
|
||||
{
|
||||
_inputReady.Wait (_inputReadyCancellationTokenSource.Token);
|
||||
}
|
||||
}
|
||||
ProcessInputQueue ();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{ }
|
||||
}, _netEventsDisposed.Token);
|
||||
|
||||
if (_inputQueue.Count > 0)
|
||||
Task.Run (() => {
|
||||
try
|
||||
{
|
||||
CheckWindowSizeChange ();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{ }
|
||||
}, _netEventsDisposed.Token);
|
||||
|
||||
Parser.UnexpectedResponseHandler = ProcessRequestResponse;
|
||||
}
|
||||
|
||||
|
||||
public InputResult? DequeueInput ()
|
||||
{
|
||||
while (!_netEventsDisposed.Token.IsCancellationRequested)
|
||||
{
|
||||
_winChange.Set ();
|
||||
|
||||
try
|
||||
{
|
||||
if (_inputQueue.TryTake (out var item, -1, _netEventsDisposed.Token))
|
||||
{
|
||||
return _inputQueue.Dequeue ();
|
||||
return item;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_inputReadyCancellationTokenSource is { IsCancellationRequested: false })
|
||||
{
|
||||
_inputReady.Reset ();
|
||||
}
|
||||
}
|
||||
|
||||
#if PROCESS_REQUEST
|
||||
_neededProcessRequest = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ConsoleKeyInfo ReadConsoleKeyInfo (CancellationToken cancellationToken, bool intercept = true)
|
||||
private ConsoleKeyInfo ReadConsoleKeyInfo (bool intercept = true)
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
// if there is a key available, return it without waiting
|
||||
// (or dispatching work to the thread queue)
|
||||
if (Console.KeyAvailable)
|
||||
{
|
||||
// if there is a key available, return it without waiting
|
||||
// (or dispatching work to the thread queue)
|
||||
return Console.ReadKey (intercept);
|
||||
}
|
||||
|
||||
while (!_netEventsDisposed.IsCancellationRequested)
|
||||
{
|
||||
Task.Delay (100, _netEventsDisposed.Token).Wait (_netEventsDisposed.Token);
|
||||
|
||||
foreach (var k in ShouldRelease ())
|
||||
{
|
||||
ProcessMapConsoleKeyInfo (k);
|
||||
}
|
||||
|
||||
if (Console.KeyAvailable)
|
||||
{
|
||||
return Console.ReadKey (intercept);
|
||||
}
|
||||
|
||||
// The delay must be here because it may have a request response after a while
|
||||
// In WSL it takes longer for keys to be available.
|
||||
Task.Delay (100, cancellationToken).Wait (cancellationToken);
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested ();
|
||||
_netEventsDisposed.Token.ThrowIfCancellationRequested ();
|
||||
|
||||
return default (ConsoleKeyInfo);
|
||||
}
|
||||
|
||||
public IEnumerable<ConsoleKeyInfo> ShouldRelease ()
|
||||
{
|
||||
if (Parser.State == AnsiResponseParserState.ExpectingBracket &&
|
||||
DateTime.Now - Parser.StateChangedAt > _consoleDriver.EscTimeout)
|
||||
{
|
||||
return Parser.Release ().Select (o => o.Item2);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private void ProcessInputQueue ()
|
||||
{
|
||||
while (_inputReadyCancellationTokenSource is { IsCancellationRequested: false })
|
||||
while (!_netEventsDisposed.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
if (_inputQueue.Count == 0)
|
||||
{
|
||||
ConsoleKey key = 0;
|
||||
ConsoleModifiers mod = 0;
|
||||
ConsoleKeyInfo newConsoleKeyInfo = default;
|
||||
|
||||
while (_inputReadyCancellationTokenSource is { IsCancellationRequested: false })
|
||||
while (!_netEventsDisposed.IsCancellationRequested)
|
||||
{
|
||||
ConsoleKeyInfo consoleKeyInfo;
|
||||
|
||||
try
|
||||
consoleKeyInfo = ReadConsoleKeyInfo ();
|
||||
|
||||
// Parse
|
||||
foreach (var k in Parser.ProcessInput (Tuple.Create (consoleKeyInfo.KeyChar, consoleKeyInfo)))
|
||||
{
|
||||
consoleKeyInfo = ReadConsoleKeyInfo (_inputReadyCancellationTokenSource.Token);
|
||||
ProcessMapConsoleKeyInfo (k.Item2);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ckiAlreadyResized = false;
|
||||
|
||||
if (EscSeqUtils.IncompleteCkInfos is { })
|
||||
{
|
||||
ckiAlreadyResized = true;
|
||||
|
||||
_cki = EscSeqUtils.ResizeArray (consoleKeyInfo, _cki);
|
||||
_cki = EscSeqUtils.InsertArray (EscSeqUtils.IncompleteCkInfos, _cki);
|
||||
EscSeqUtils.IncompleteCkInfos = null;
|
||||
|
||||
if (_cki.Length > 1 && _cki [0].KeyChar == '\u001B')
|
||||
{
|
||||
_isEscSeq = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((consoleKeyInfo.KeyChar == (char)KeyCode.Esc && !_isEscSeq)
|
||||
|| (consoleKeyInfo.KeyChar != (char)KeyCode.Esc && _isEscSeq))
|
||||
{
|
||||
if (_cki is null && consoleKeyInfo.KeyChar != (char)KeyCode.Esc && _isEscSeq)
|
||||
{
|
||||
_cki = EscSeqUtils.ResizeArray (
|
||||
new (
|
||||
(char)KeyCode.Esc,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
),
|
||||
_cki
|
||||
);
|
||||
}
|
||||
|
||||
_isEscSeq = true;
|
||||
|
||||
if ((_cki is { } && _cki [^1].KeyChar != Key.Esc && consoleKeyInfo.KeyChar != Key.Esc && consoleKeyInfo.KeyChar <= Key.Space)
|
||||
|| (_cki is { } && _cki [^1].KeyChar != '\u001B' && consoleKeyInfo.KeyChar == 127)
|
||||
|| (_cki is { }
|
||||
&& char.IsLetter (_cki [^1].KeyChar)
|
||||
&& char.IsLower (consoleKeyInfo.KeyChar)
|
||||
&& char.IsLetter (consoleKeyInfo.KeyChar))
|
||||
|| (_cki is { Length: > 2 } && char.IsLetter (_cki [^1].KeyChar) && char.IsLetterOrDigit (consoleKeyInfo.KeyChar))
|
||||
|| (_cki is { Length: > 2 } && char.IsLetter (_cki [^1].KeyChar) && char.IsPunctuation (consoleKeyInfo.KeyChar))
|
||||
|| (_cki is { Length: > 2 } && char.IsLetter (_cki [^1].KeyChar) && char.IsSymbol (consoleKeyInfo.KeyChar)))
|
||||
{
|
||||
ProcessRequestResponse (ref newConsoleKeyInfo, ref key, _cki, ref mod);
|
||||
_cki = null;
|
||||
_isEscSeq = false;
|
||||
|
||||
ProcessMapConsoleKeyInfo (consoleKeyInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
newConsoleKeyInfo = consoleKeyInfo;
|
||||
|
||||
if (!ckiAlreadyResized)
|
||||
{
|
||||
_cki = EscSeqUtils.ResizeArray (consoleKeyInfo, _cki);
|
||||
}
|
||||
|
||||
if (Console.KeyAvailable)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ProcessRequestResponse (ref newConsoleKeyInfo, ref key, _cki!, ref mod);
|
||||
_cki = null;
|
||||
_isEscSeq = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (consoleKeyInfo.KeyChar == (char)KeyCode.Esc && _isEscSeq && _cki is { })
|
||||
{
|
||||
ProcessRequestResponse (ref newConsoleKeyInfo, ref key, _cki, ref mod);
|
||||
_cki = null;
|
||||
|
||||
if (Console.KeyAvailable)
|
||||
{
|
||||
_cki = EscSeqUtils.ResizeArray (consoleKeyInfo, _cki);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessMapConsoleKeyInfo (consoleKeyInfo);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessMapConsoleKeyInfo (consoleKeyInfo);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (_inputQueue.Count > 0)
|
||||
{
|
||||
_inputReady.Set ();
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessMapConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
|
||||
{
|
||||
_inputQueue.Enqueue (
|
||||
new ()
|
||||
{
|
||||
EventType = EventType.Key, ConsoleKeyInfo = EscSeqUtils.MapConsoleKeyInfo (consoleKeyInfo)
|
||||
}
|
||||
);
|
||||
_isEscSeq = false;
|
||||
}
|
||||
void ProcessMapConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
|
||||
{
|
||||
_inputQueue.Add (
|
||||
new InputResult
|
||||
{
|
||||
EventType = EventType.Key, ConsoleKeyInfo = EscSeqUtils.MapConsoleKeyInfo (consoleKeyInfo)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void CheckWindowSizeChange ()
|
||||
{
|
||||
void RequestWindowSize (CancellationToken cancellationToken)
|
||||
void RequestWindowSize ()
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
while (!_netEventsDisposed.IsCancellationRequested)
|
||||
{
|
||||
// Wait for a while then check if screen has changed sizes
|
||||
Task.Delay (500, cancellationToken).Wait (cancellationToken);
|
||||
Task.Delay (500, _netEventsDisposed.Token).Wait (_netEventsDisposed.Token);
|
||||
|
||||
int buffHeight, buffWidth;
|
||||
|
||||
@@ -258,19 +170,17 @@ internal class NetEvents : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested ();
|
||||
_netEventsDisposed.Token.ThrowIfCancellationRequested ();
|
||||
}
|
||||
|
||||
while (_inputReadyCancellationTokenSource is { IsCancellationRequested: false })
|
||||
while (!_netEventsDisposed.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
RequestWindowSize (_inputReadyCancellationTokenSource.Token);
|
||||
_winChange.Wait (_netEventsDisposed.Token);
|
||||
_winChange.Reset ();
|
||||
|
||||
if (_inputQueue.Count > 0)
|
||||
{
|
||||
_inputReady.Set ();
|
||||
}
|
||||
RequestWindowSize ();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -295,16 +205,29 @@ internal class NetEvents : IDisposable
|
||||
int w = Math.Max (winWidth, 0);
|
||||
int h = Math.Max (winHeight, 0);
|
||||
|
||||
_inputQueue.Enqueue (
|
||||
new ()
|
||||
_inputQueue.Add (
|
||||
new InputResult
|
||||
{
|
||||
EventType = EventType.WindowSize, WindowSizeEvent = new () { Size = new (w, h) }
|
||||
EventType = EventType.WindowSize, WindowSizeEvent = new WindowSizeEvent { Size = new (w, h) }
|
||||
}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ProcessRequestResponse (IEnumerable<Tuple<char, ConsoleKeyInfo>> obj)
|
||||
{
|
||||
// Added for signature compatibility with existing method, not sure what they are even for.
|
||||
ConsoleKeyInfo newConsoleKeyInfo = default;
|
||||
ConsoleKey key = default;
|
||||
ConsoleModifiers mod = default;
|
||||
|
||||
ProcessRequestResponse (ref newConsoleKeyInfo, ref key, obj.Select (v => v.Item2).ToArray (), ref mod);
|
||||
|
||||
// Handled
|
||||
return true;
|
||||
}
|
||||
|
||||
// Process a CSI sequence received by the driver (key pressed, mouse event, or request/response event)
|
||||
private void ProcessRequestResponse (
|
||||
ref ConsoleKeyInfo newConsoleKeyInfo,
|
||||
@@ -313,22 +236,23 @@ internal class NetEvents : IDisposable
|
||||
ref ConsoleModifiers mod
|
||||
)
|
||||
{
|
||||
|
||||
// isMouse is true if it's CSI<, false otherwise
|
||||
EscSeqUtils.DecodeEscSeq (
|
||||
ref newConsoleKeyInfo,
|
||||
ref key,
|
||||
cki,
|
||||
ref mod,
|
||||
out string c1Control,
|
||||
out string code,
|
||||
out string [] values,
|
||||
out string terminating,
|
||||
out bool isMouse,
|
||||
out List<MouseFlags> mouseFlags,
|
||||
out Point pos,
|
||||
out bool isReq,
|
||||
(f, p) => HandleMouseEvent (MapMouseFlags (f), p)
|
||||
);
|
||||
ref newConsoleKeyInfo,
|
||||
ref key,
|
||||
cki,
|
||||
ref mod,
|
||||
out string c1Control,
|
||||
out string code,
|
||||
out string [] values,
|
||||
out string terminating,
|
||||
out bool isMouse,
|
||||
out List<MouseFlags> mouseFlags,
|
||||
out Point pos,
|
||||
out bool isReq,
|
||||
(f, p) => HandleMouseEvent (MapMouseFlags (f), p)
|
||||
);
|
||||
|
||||
if (isMouse)
|
||||
{
|
||||
@@ -347,10 +271,7 @@ internal class NetEvents : IDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
if (newConsoleKeyInfo != default)
|
||||
{
|
||||
HandleKeyboardEvent (newConsoleKeyInfo);
|
||||
}
|
||||
HandleKeyboardEvent (newConsoleKeyInfo);
|
||||
}
|
||||
|
||||
[UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
|
||||
@@ -491,51 +412,53 @@ internal class NetEvents : IDisposable
|
||||
|
||||
private void HandleRequestResponseEvent (string c1Control, string code, string [] values, string terminating)
|
||||
{
|
||||
if (terminating ==
|
||||
|
||||
switch (terminating)
|
||||
{
|
||||
// BUGBUG: I can't find where we send a request for cursor position (ESC[?6n), so I'm not sure if this is needed.
|
||||
// The observation is correct because the response isn't immediate and this is useless
|
||||
EscSeqUtils.CSI_RequestCursorPositionReport_Terminator)
|
||||
{
|
||||
var point = new Point { X = int.Parse (values [1]) - 1, Y = int.Parse (values [0]) - 1 };
|
||||
case EscSeqUtils.CSI_RequestCursorPositionReport_Terminator:
|
||||
var point = new Point { X = int.Parse (values [1]) - 1, Y = int.Parse (values [0]) - 1 };
|
||||
|
||||
if (_lastCursorPosition.Y != point.Y)
|
||||
{
|
||||
_lastCursorPosition = point;
|
||||
var eventType = EventType.WindowPosition;
|
||||
var winPositionEv = new WindowPositionEvent { CursorPosition = point };
|
||||
if (_lastCursorPosition.Y != point.Y)
|
||||
{
|
||||
_lastCursorPosition = point;
|
||||
var eventType = EventType.WindowPosition;
|
||||
var winPositionEv = new WindowPositionEvent { CursorPosition = point };
|
||||
|
||||
_inputQueue.Enqueue (
|
||||
new InputResult { EventType = eventType, WindowPositionEvent = winPositionEv }
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (terminating == EscSeqUtils.CSI_ReportTerminalSizeInChars_Terminator)
|
||||
{
|
||||
if (values [0] == EscSeqUtils.CSI_ReportTerminalSizeInChars_ResponseValue)
|
||||
{
|
||||
EnqueueWindowSizeEvent (
|
||||
Math.Max (int.Parse (values [1]), 0),
|
||||
Math.Max (int.Parse (values [2]), 0),
|
||||
Math.Max (int.Parse (values [1]), 0),
|
||||
Math.Max (int.Parse (values [2]), 0)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_inputQueue.Add (
|
||||
new InputResult { EventType = eventType, WindowPositionEvent = winPositionEv }
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EscSeqUtils.CSI_ReportTerminalSizeInChars_Terminator:
|
||||
switch (values [0])
|
||||
{
|
||||
case EscSeqUtils.CSI_ReportTerminalSizeInChars_ResponseValue:
|
||||
EnqueueWindowSizeEvent (
|
||||
Math.Max (int.Parse (values [1]), 0),
|
||||
Math.Max (int.Parse (values [2]), 0),
|
||||
Math.Max (int.Parse (values [1]), 0),
|
||||
Math.Max (int.Parse (values [2]), 0)
|
||||
);
|
||||
|
||||
break;
|
||||
default:
|
||||
EnqueueRequestResponseEvent (c1Control, code, values, terminating);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
EnqueueRequestResponseEvent (c1Control, code, values, terminating);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnqueueRequestResponseEvent (c1Control, code, values, terminating);
|
||||
}
|
||||
|
||||
_inputReady.Set ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnqueueRequestResponseEvent (string c1Control, string code, string [] values, string terminating)
|
||||
@@ -543,7 +466,7 @@ internal class NetEvents : IDisposable
|
||||
var eventType = EventType.RequestResponse;
|
||||
var requestRespEv = new RequestResponseEvent { ResultTuple = (c1Control, code, values, terminating) };
|
||||
|
||||
_inputQueue.Enqueue (
|
||||
_inputQueue.Add (
|
||||
new InputResult { EventType = eventType, RequestResponseEvent = requestRespEv }
|
||||
);
|
||||
}
|
||||
@@ -552,8 +475,8 @@ internal class NetEvents : IDisposable
|
||||
{
|
||||
var mouseEvent = new MouseEvent { Position = pos, ButtonState = buttonState };
|
||||
|
||||
_inputQueue.Enqueue (
|
||||
new () { EventType = EventType.Mouse, MouseEvent = mouseEvent }
|
||||
_inputQueue.Add (
|
||||
new InputResult { EventType = EventType.Mouse, MouseEvent = mouseEvent }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -634,15 +557,15 @@ internal class NetEvents : IDisposable
|
||||
|
||||
public readonly override string ToString ()
|
||||
{
|
||||
return (EventType switch
|
||||
{
|
||||
EventType.Key => ToString (ConsoleKeyInfo),
|
||||
EventType.Mouse => MouseEvent.ToString (),
|
||||
return EventType switch
|
||||
{
|
||||
EventType.Key => ToString (ConsoleKeyInfo),
|
||||
EventType.Mouse => MouseEvent.ToString (),
|
||||
|
||||
//EventType.WindowSize => WindowSize.ToString (),
|
||||
//EventType.RequestResponse => RequestResponse.ToString (),
|
||||
_ => "Unknown event type: " + EventType
|
||||
})!;
|
||||
//EventType.WindowSize => WindowSize.ToString (),
|
||||
//EventType.RequestResponse => RequestResponse.ToString (),
|
||||
_ => "Unknown event type: " + EventType
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Prints a ConsoleKeyInfoEx structure</summary>
|
||||
@@ -667,16 +590,13 @@ internal class NetEvents : IDisposable
|
||||
{
|
||||
var inputResult = new InputResult { EventType = EventType.Key, ConsoleKeyInfo = cki };
|
||||
|
||||
_inputQueue.Enqueue (inputResult);
|
||||
_inputQueue.Add (inputResult);
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
_inputReadyCancellationTokenSource?.Cancel ();
|
||||
_inputReadyCancellationTokenSource?.Dispose ();
|
||||
_inputReadyCancellationTokenSource = null;
|
||||
|
||||
_inputReady.Dispose ();
|
||||
_netEventsDisposed?.Cancel ();
|
||||
_netEventsDisposed?.Dispose ();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -692,4 +612,4 @@ internal class NetEvents : IDisposable
|
||||
// Ignore - Console input has already been closed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user