mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Replace IsWindowsTerminal with IsVirtualTerminal
This commit is contained in:
@@ -20,7 +20,7 @@ public class SixelSupportDetector
|
||||
public void Detect (Action<SixelSupportResult> resultCallback)
|
||||
{
|
||||
var result = new SixelSupportResult ();
|
||||
result.SupportsTransparency = IsWindowsTerminal () || IsXtermWithTransparency ();
|
||||
result.SupportsTransparency = IsVirtualTerminal () || IsXtermWithTransparency ();
|
||||
IsSixelSupportedByDar (result, resultCallback);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public class SixelSupportDetector
|
||||
|
||||
private static bool ResponseIndicatesSupport (string response) { return response.Split (';').Contains ("4"); }
|
||||
|
||||
private static bool IsWindowsTerminal ()
|
||||
private static bool IsVirtualTerminal ()
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace (Environment.GetEnvironmentVariable ("WT_SESSION"));
|
||||
|
||||
|
||||
@@ -28,6 +28,15 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
||||
_outputBuffer = outputBuffer;
|
||||
_ansiRequestScheduler = ansiRequestScheduler;
|
||||
|
||||
if (InputProcessor is WindowsInputProcessor)
|
||||
{
|
||||
SupportsTrueColor = new WindowsInput ().IsVirtualTerminal ();
|
||||
}
|
||||
else if (InputProcessor is NetInputProcessor)
|
||||
{
|
||||
SupportsTrueColor = Application.Driver.SupportsTrueColor;
|
||||
}
|
||||
|
||||
InputProcessor.KeyDown += (s, e) => KeyDown?.Invoke (s, e);
|
||||
InputProcessor.KeyUp += (s, e) => KeyUp?.Invoke (s, e);
|
||||
InputProcessor.MouseEvent += (s, e) =>
|
||||
@@ -145,7 +154,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
||||
// TODO: Probably not everyone right?
|
||||
|
||||
/// <summary>Gets whether the <see cref="ConsoleDriver"/> supports TrueColor output.</summary>
|
||||
public bool SupportsTrueColor => true;
|
||||
public bool SupportsTrueColor { get; init; } = true;
|
||||
|
||||
// TODO: Currently ignored
|
||||
/// <summary>
|
||||
|
||||
@@ -25,7 +25,6 @@ internal class MainLoopCoordinator<T> : IMainLoopCoordinator
|
||||
private ConsoleDriverFacade<T> _facade;
|
||||
private Task _inputTask;
|
||||
private readonly ITimedEvents _timedEvents;
|
||||
private readonly bool _isWindowsTerminal;
|
||||
|
||||
private readonly SemaphoreSlim _startupSemaphore = new (0, 1);
|
||||
|
||||
@@ -61,7 +60,6 @@ internal class MainLoopCoordinator<T> : IMainLoopCoordinator
|
||||
_inputProcessor = inputProcessor;
|
||||
_outputFactory = outputFactory;
|
||||
_loop = loop;
|
||||
_isWindowsTerminal = Environment.GetEnvironmentVariable ("WT_SESSION") is { } || Environment.GetEnvironmentVariable ("VSAPPIDNAME") != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -162,7 +160,15 @@ internal class MainLoopCoordinator<T> : IMainLoopCoordinator
|
||||
_loop.AnsiRequestScheduler,
|
||||
_loop.WindowSizeMonitor);
|
||||
|
||||
if (!_isWindowsTerminal)
|
||||
if (_facade.SupportsTrueColor)
|
||||
{
|
||||
if (!ConsoleDriver.RunningUnitTests)
|
||||
{
|
||||
// Enable alternative screen buffer.
|
||||
Console.Out.Write (EscSeqUtils.CSI_SaveCursorAndActivateAltBufferNoBackscroll);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.Force16Colors = _facade.Force16Colors = true;
|
||||
}
|
||||
@@ -187,6 +193,13 @@ internal class MainLoopCoordinator<T> : IMainLoopCoordinator
|
||||
_stopCalled = true;
|
||||
|
||||
_tokenSource.Cancel ();
|
||||
|
||||
if (!ConsoleDriver.RunningUnitTests && _facade.SupportsTrueColor)
|
||||
{
|
||||
// Disable alternative screen buffer.
|
||||
Console.Out.Write (EscSeqUtils.CSI_RestoreCursorAndRestoreAltBufferWithBackscroll);
|
||||
}
|
||||
|
||||
_output.Dispose ();
|
||||
|
||||
// Wait for input infinite loop to exit
|
||||
|
||||
@@ -56,6 +56,12 @@ internal class WindowsInput : ConsoleInput<WindowsConsole.InputRecord>, IWindows
|
||||
SetConsoleMode (_inputHandle, newConsoleMode);
|
||||
}
|
||||
|
||||
internal bool IsVirtualTerminal ()
|
||||
{
|
||||
nint outputHandle = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
return GetConsoleMode (outputHandle, out uint mode) && (mode & (uint)ConsoleModes.EnableVirtualTerminalProcessing) != 0;
|
||||
}
|
||||
|
||||
protected override bool Peek ()
|
||||
{
|
||||
const int bufferSize = 1; // We only need to check if there's at least one event
|
||||
|
||||
@@ -59,7 +59,17 @@ internal partial class WindowsOutput : IConsoleOutput
|
||||
[DllImport ("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool SetConsoleCursorInfo (nint hConsoleOutput, [In] ref WindowsConsole.ConsoleCursorInfo lpConsoleCursorInfo);
|
||||
|
||||
private readonly nint _screenBuffer;
|
||||
[DllImport ("kernel32.dll", SetLastError = true)]
|
||||
private static extern nint GetStdHandle (int nStdHandle);
|
||||
|
||||
[DllImport ("kernel32.dll")]
|
||||
private static extern bool GetConsoleMode (nint hConsoleHandle, out uint lpMode);
|
||||
|
||||
[DllImport ("kernel32.dll")]
|
||||
private static extern bool SetConsoleMode (nint hConsoleHandle, uint dwMode);
|
||||
|
||||
private nint _screenBuffer;
|
||||
private nint _outputHandle;
|
||||
|
||||
// Last text style used, for updating style with EscSeqUtils.CSI_AppendTextStyleChange().
|
||||
private TextStyle _redrawTextStyle = TextStyle.None;
|
||||
@@ -73,33 +83,61 @@ internal partial class WindowsOutput : IConsoleOutput
|
||||
return;
|
||||
}
|
||||
|
||||
_screenBuffer = CreateConsoleScreenBuffer (
|
||||
DesiredAccess.GenericRead | DesiredAccess.GenericWrite,
|
||||
ShareMode.FileShareRead | ShareMode.FileShareWrite,
|
||||
nint.Zero,
|
||||
1,
|
||||
nint.Zero
|
||||
);
|
||||
_outputHandle = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
|
||||
if (_screenBuffer == INVALID_HANDLE_VALUE)
|
||||
if (!GetConsoleMode (_outputHandle, out uint mode))
|
||||
{
|
||||
int err = Marshal.GetLastWin32Error ();
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
throw new Win32Exception (err);
|
||||
}
|
||||
throw new ApplicationException ($"Failed to get _outputHandle console mode, error code: {Marshal.GetLastWin32Error ()}.");
|
||||
}
|
||||
|
||||
if (!SetConsoleActiveScreenBuffer (_screenBuffer))
|
||||
IsVirtualTerminal = (mode & (uint)ConsoleModes.EnableVirtualTerminalProcessing) != 0;
|
||||
|
||||
if (!IsVirtualTerminal)
|
||||
{
|
||||
throw new Win32Exception (Marshal.GetLastWin32Error ());
|
||||
_screenBuffer = CreateConsoleScreenBuffer (
|
||||
DesiredAccess.GenericRead | DesiredAccess.GenericWrite,
|
||||
ShareMode.FileShareRead | ShareMode.FileShareWrite,
|
||||
nint.Zero,
|
||||
1,
|
||||
nint.Zero
|
||||
);
|
||||
|
||||
if (_screenBuffer == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
int err = Marshal.GetLastWin32Error ();
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
throw new Win32Exception (err);
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetConsoleActiveScreenBuffer (_screenBuffer))
|
||||
{
|
||||
throw new Win32Exception (Marshal.GetLastWin32Error ());
|
||||
}
|
||||
|
||||
if (!GetConsoleMode (_screenBuffer, out mode))
|
||||
{
|
||||
throw new ApplicationException ($"Failed to get screenBuffer console mode, error code: {Marshal.GetLastWin32Error ()}.");
|
||||
}
|
||||
|
||||
const uint ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002;
|
||||
|
||||
mode &= ~ENABLE_WRAP_AT_EOL_OUTPUT; // Disable wrap
|
||||
|
||||
if (!SetConsoleMode (_screenBuffer, mode))
|
||||
{
|
||||
throw new ApplicationException ($"Failed to set screenBuffer console mode, error code: {Marshal.GetLastWin32Error ()}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsVirtualTerminal { get; init; }
|
||||
|
||||
public void Write (ReadOnlySpan<char> str)
|
||||
{
|
||||
if (!WriteConsole (_screenBuffer, str, (uint)str.Length, out uint _, nint.Zero))
|
||||
if (!WriteConsole (IsVirtualTerminal ? _outputHandle : _screenBuffer, str, (uint)str.Length, out uint _, nint.Zero))
|
||||
{
|
||||
throw new Win32Exception (Marshal.GetLastWin32Error (), "Failed to write to console screen buffer.");
|
||||
}
|
||||
@@ -270,7 +308,7 @@ internal partial class WindowsOutput : IConsoleOutput
|
||||
stringBuilder.CopyTo (0, writeBuffer, stringBuilder.Length);
|
||||
|
||||
// Supply console with the new content.
|
||||
result = WriteConsole (_screenBuffer, writeBuffer, (uint)writeBuffer.Length, out uint _, nint.Zero);
|
||||
result = WriteConsole (IsVirtualTerminal ? _outputHandle : _screenBuffer, writeBuffer, (uint)writeBuffer.Length, out uint _, nint.Zero);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -280,7 +318,7 @@ internal partial class WindowsOutput : IConsoleOutput
|
||||
foreach (SixelToRender sixel in Application.Sixel)
|
||||
{
|
||||
SetCursorPosition ((short)sixel.ScreenPosition.X, (short)sixel.ScreenPosition.Y);
|
||||
WriteConsole (_screenBuffer, sixel.SixelData, (uint)sixel.SixelData.Length, out uint _, nint.Zero);
|
||||
WriteConsole (IsVirtualTerminal ? _outputHandle : _screenBuffer, sixel.SixelData, (uint)sixel.SixelData.Length, out uint _, nint.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ internal partial class WindowsConsole
|
||||
newConsoleMode &= ~(uint)ConsoleModes.EnableProcessedInput;
|
||||
ConsoleMode = newConsoleMode;
|
||||
|
||||
_inputReadyCancellationTokenSource = new ();
|
||||
IsVirtualTerminal = GetConsoleMode (_outputHandle, out uint mode) && (mode & (uint)ConsoleModes.EnableVirtualTerminalProcessing) != 0;
|
||||
|
||||
_inputReadyCancellationTokenSource = new ();
|
||||
Task.Run (ProcessInputQueue, _inputReadyCancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
@@ -150,7 +152,7 @@ internal partial class WindowsConsole
|
||||
{
|
||||
//Debug.WriteLine ("WriteToConsole");
|
||||
|
||||
if (!IsWindowsTerminal && _screenBuffer == nint.Zero)
|
||||
if (!IsVirtualTerminal && _screenBuffer == nint.Zero)
|
||||
{
|
||||
ReadFromConsoleOutput (size, bufferSize, ref window);
|
||||
}
|
||||
@@ -229,7 +231,7 @@ internal partial class WindowsConsole
|
||||
foreach (var sixel in Application.Sixel)
|
||||
{
|
||||
SetCursorPosition (new Coord ((short)sixel.ScreenPosition.X, (short)sixel.ScreenPosition.Y));
|
||||
WriteConsole (IsWindowsTerminal ? _outputHandle : _screenBuffer, sixel.SixelData, (uint)sixel.SixelData.Length, out uint _, nint.Zero);
|
||||
WriteConsole (IsVirtualTerminal ? _outputHandle : _screenBuffer, sixel.SixelData, (uint)sixel.SixelData.Length, out uint _, nint.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +294,7 @@ internal partial class WindowsConsole
|
||||
|
||||
public bool SetCursorPosition (Coord position)
|
||||
{
|
||||
return SetConsoleCursorPosition (IsWindowsTerminal ? _outputHandle : _screenBuffer, position);
|
||||
return SetConsoleCursorPosition (IsVirtualTerminal ? _outputHandle : _screenBuffer, position);
|
||||
}
|
||||
|
||||
public void SetInitialCursorVisibility ()
|
||||
@@ -305,14 +307,14 @@ internal partial class WindowsConsole
|
||||
|
||||
public bool GetCursorVisibility (out CursorVisibility visibility)
|
||||
{
|
||||
if ((IsWindowsTerminal ? _outputHandle : _screenBuffer) == nint.Zero)
|
||||
if ((IsVirtualTerminal ? _outputHandle : _screenBuffer) == nint.Zero)
|
||||
{
|
||||
visibility = CursorVisibility.Invisible;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetConsoleCursorInfo (IsWindowsTerminal ? _outputHandle : _screenBuffer, out ConsoleCursorInfo info))
|
||||
if (!GetConsoleCursorInfo (IsVirtualTerminal ? _outputHandle : _screenBuffer, out ConsoleCursorInfo info))
|
||||
{
|
||||
int err = Marshal.GetLastWin32Error ();
|
||||
|
||||
@@ -380,7 +382,7 @@ internal partial class WindowsConsole
|
||||
bVisible = ((uint)visibility & 0xFF00) != 0
|
||||
};
|
||||
|
||||
if (!SetConsoleCursorInfo (IsWindowsTerminal ? _outputHandle : _screenBuffer, ref info))
|
||||
if (!SetConsoleCursorInfo (IsVirtualTerminal ? _outputHandle : _screenBuffer, ref info))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -430,7 +432,7 @@ internal partial class WindowsConsole
|
||||
|
||||
internal Size GetConsoleBufferWindow (out Point position)
|
||||
{
|
||||
if ((IsWindowsTerminal ? _outputHandle : _screenBuffer) == nint.Zero)
|
||||
if ((IsVirtualTerminal ? _outputHandle : _screenBuffer) == nint.Zero)
|
||||
{
|
||||
position = Point.Empty;
|
||||
|
||||
@@ -440,7 +442,7 @@ internal partial class WindowsConsole
|
||||
var csbi = new CONSOLE_SCREEN_BUFFER_INFOEX ();
|
||||
csbi.cbSize = (uint)Marshal.SizeOf (csbi);
|
||||
|
||||
if (!GetConsoleScreenBufferInfoEx (IsWindowsTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
if (!GetConsoleScreenBufferInfoEx (IsVirtualTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
{
|
||||
//throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ());
|
||||
position = Point.Empty;
|
||||
@@ -479,19 +481,19 @@ internal partial class WindowsConsole
|
||||
var csbi = new CONSOLE_SCREEN_BUFFER_INFOEX ();
|
||||
csbi.cbSize = (uint)Marshal.SizeOf (csbi);
|
||||
|
||||
if (!GetConsoleScreenBufferInfoEx (IsWindowsTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
if (!GetConsoleScreenBufferInfoEx (IsVirtualTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
{
|
||||
throw new Win32Exception (Marshal.GetLastWin32Error ());
|
||||
}
|
||||
|
||||
Coord maxWinSize = GetLargestConsoleWindowSize (IsWindowsTerminal ? _outputHandle : _screenBuffer);
|
||||
Coord maxWinSize = GetLargestConsoleWindowSize (IsVirtualTerminal ? _outputHandle : _screenBuffer);
|
||||
short newCols = Math.Min (cols, maxWinSize.X);
|
||||
short newRows = Math.Min (rows, maxWinSize.Y);
|
||||
csbi.dwSize = new Coord (newCols, Math.Max (newRows, (short)1));
|
||||
csbi.srWindow = new SmallRect (0, 0, newCols, newRows);
|
||||
csbi.dwMaximumWindowSize = new Coord (newCols, newRows);
|
||||
|
||||
if (!SetConsoleScreenBufferInfoEx (IsWindowsTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
if (!SetConsoleScreenBufferInfoEx (IsVirtualTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
{
|
||||
throw new Win32Exception (Marshal.GetLastWin32Error ());
|
||||
}
|
||||
@@ -511,9 +513,9 @@ internal partial class WindowsConsole
|
||||
|
||||
private void SetConsoleOutputWindow (CONSOLE_SCREEN_BUFFER_INFOEX csbi)
|
||||
{
|
||||
if ((IsWindowsTerminal
|
||||
if ((IsVirtualTerminal
|
||||
? _outputHandle
|
||||
: _screenBuffer) != nint.Zero && !SetConsoleScreenBufferInfoEx (IsWindowsTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
: _screenBuffer) != nint.Zero && !SetConsoleScreenBufferInfoEx (IsVirtualTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
{
|
||||
throw new Win32Exception (Marshal.GetLastWin32Error ());
|
||||
}
|
||||
@@ -521,7 +523,7 @@ internal partial class WindowsConsole
|
||||
|
||||
internal Size SetConsoleOutputWindow (out Point position)
|
||||
{
|
||||
if ((IsWindowsTerminal ? _outputHandle : _screenBuffer) == nint.Zero)
|
||||
if ((IsVirtualTerminal ? _outputHandle : _screenBuffer) == nint.Zero)
|
||||
{
|
||||
position = Point.Empty;
|
||||
|
||||
@@ -531,7 +533,7 @@ internal partial class WindowsConsole
|
||||
var csbi = new CONSOLE_SCREEN_BUFFER_INFOEX ();
|
||||
csbi.cbSize = (uint)Marshal.SizeOf (csbi);
|
||||
|
||||
if (!GetConsoleScreenBufferInfoEx (IsWindowsTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
if (!GetConsoleScreenBufferInfoEx (IsVirtualTerminal ? _outputHandle : _screenBuffer, ref csbi))
|
||||
{
|
||||
throw new Win32Exception (Marshal.GetLastWin32Error ());
|
||||
}
|
||||
@@ -556,7 +558,7 @@ internal partial class WindowsConsole
|
||||
return sz;
|
||||
}
|
||||
|
||||
internal bool IsWindowsTerminal { get; set; }
|
||||
internal bool IsVirtualTerminal { get; init; }
|
||||
|
||||
private uint ConsoleMode
|
||||
{
|
||||
@@ -573,6 +575,7 @@ internal partial class WindowsConsole
|
||||
public enum ConsoleModes : uint
|
||||
{
|
||||
EnableProcessedInput = 1,
|
||||
EnableVirtualTerminalProcessing = 4,
|
||||
EnableMouseInput = 16,
|
||||
EnableQuickEditMode = 64,
|
||||
EnableExtendedFlags = 128
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Terminal.Gui.Drivers;
|
||||
|
||||
internal class WindowsDriver : ConsoleDriver
|
||||
{
|
||||
private readonly bool _isWindowsTerminal;
|
||||
private readonly bool _isVirtualTerminal;
|
||||
|
||||
private WindowsConsole.SmallRect _damageRegion;
|
||||
private bool _isButtonDoubleClicked;
|
||||
@@ -57,18 +57,16 @@ internal class WindowsDriver : ConsoleDriver
|
||||
// force 16color mode (.e.g ConEmu which really doesn't work well at all).
|
||||
if (!RunningUnitTests)
|
||||
{
|
||||
WinConsole!.IsWindowsTerminal = _isWindowsTerminal =
|
||||
Environment.GetEnvironmentVariable ("WT_SESSION") is { }
|
||||
|| Environment.GetEnvironmentVariable ("VSAPPIDNAME") != null;
|
||||
_isVirtualTerminal = WinConsole!.IsVirtualTerminal;
|
||||
}
|
||||
|
||||
if (!_isWindowsTerminal)
|
||||
if (!_isVirtualTerminal)
|
||||
{
|
||||
Force16Colors = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SupportsTrueColor => RunningUnitTests || (Environment.OSVersion.Version.Build >= 14931 && _isWindowsTerminal);
|
||||
public override bool SupportsTrueColor => RunningUnitTests || (Environment.OSVersion.Version.Build >= 14931 && _isVirtualTerminal);
|
||||
|
||||
public WindowsConsole? WinConsole { get; private set; }
|
||||
|
||||
@@ -405,7 +403,7 @@ internal class WindowsDriver : ConsoleDriver
|
||||
WinConsole?.Cleanup ();
|
||||
WinConsole = null;
|
||||
|
||||
if (!RunningUnitTests && _isWindowsTerminal)
|
||||
if (!RunningUnitTests && _isVirtualTerminal)
|
||||
{
|
||||
// Disable alternative screen buffer.
|
||||
Console.Out.Write (EscSeqUtils.CSI_RestoreCursorAndRestoreAltBufferWithBackscroll);
|
||||
@@ -432,7 +430,7 @@ internal class WindowsDriver : ConsoleDriver
|
||||
|
||||
WindowsConsole.SmallRect.MakeEmpty (ref _damageRegion);
|
||||
|
||||
if (_isWindowsTerminal)
|
||||
if (_isVirtualTerminal)
|
||||
{
|
||||
Console.Out.Write (EscSeqUtils.CSI_SaveCursorAndActivateAltBufferNoBackscroll);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user