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); } } }