using Microsoft.Extensions.Logging;
namespace Terminal.Gui.Drivers;
///
/// implementation that uses native dotnet methods e.g. .
/// The and methods are executed
/// on the input thread created by .
///
public class NetInput : InputImpl, ITestableInput, IDisposable
{
///
/// Creates a new instance of the class. Implicitly sends
/// console mode settings that enable virtual input (mouse
/// reporting etc).
///
public NetInput ()
{
Logging.Information ($"Creating {nameof (NetInput)}");
PlatformID p = Environment.OSVersion.Platform;
if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
{
try
{
_adjustConsole = new ();
}
catch (ApplicationException ex)
{
// Likely running as a unit test, or in a non-interactive session.
Logging.Critical ($"NetWinVTConsole could not configure terminal modes. May indicate running in non-interactive session: {ex}");
return;
}
}
try
{
//Enable alternative screen buffer.
Console.Out.Write (EscSeqUtils.CSI_SaveCursorAndActivateAltBufferNoBackscroll);
//Set cursor key to application.
Console.Out.Write (EscSeqUtils.CSI_HideCursor);
Console.Out.Write (EscSeqUtils.CSI_EnableMouseEvents);
Console.TreatControlCAsInput = true;
}
catch
{
// Swallow any exceptions during initialization for unit tests
}
}
private readonly NetWinVTConsole _adjustConsole;
///
public override void Dispose ()
{
base.Dispose ();
try
{
// Disable mouse events first
Console.Out.Write (EscSeqUtils.CSI_DisableMouseEvents);
//Disable alternative screen buffer.
Console.Out.Write (EscSeqUtils.CSI_RestoreCursorAndRestoreAltBufferWithBackscroll);
//Set cursor key to cursor.
Console.Out.Write (EscSeqUtils.CSI_ShowCursor);
_adjustConsole?.Cleanup ();
// Flush any pending input so no stray events appear
FlushConsoleInput ();
}
catch
{
// Swallow any exceptions during Dispose for unit tests
}
}
///
public void AddInput (ConsoleKeyInfo input) { throw new NotImplementedException (); }
///
public override bool Peek ()
{
try
{
return Console.KeyAvailable;
}
catch
{
return false;
}
}
///
public override IEnumerable Read ()
{
while (true)
{
ConsoleKeyInfo keyInfo = default;
try
{
if (!Console.KeyAvailable)
{
break;
}
keyInfo = Console.ReadKey (true);
}
catch (InvalidOperationException)
{
// Not connected to a terminal (GitHub Actions, redirected input, etc.)
yield break;
}
catch (IOException)
{
// I/O error reading from console
yield break;
}
yield return keyInfo;
}
}
private void FlushConsoleInput ()
{
while (Console.KeyAvailable)
{
Console.ReadKey (true);
}
}
}