Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Terminal.Gui/Drivers/AnsiDriver/AnsiOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,11 @@ public void Dispose ()
{
Trace.Lifecycle (nameof (AnsiOutput), "Dispose", "Flushing output and releasing resources.");

if (_platform == AnsiPlatform.WindowsVT)
{
WindowsVTInputHelper.WakePendingRead ();
}

_windowsVTOutput?.Dispose ();
}
}
Expand Down
42 changes: 42 additions & 0 deletions Terminal.Gui/Drivers/WindowsHelpers/WindowsVTInputHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,17 @@ internal sealed class WindowsVTInputHelper : IDisposable
[DllImport ("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile (nint hFile, byte [] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, nint lpOverlapped);

[DllImport ("kernel32.dll", SetLastError = true)]
private static extern bool CancelIoEx (nint hFile, nint lpOverlapped);

[DllImport ("kernel32.dll")]
private static extern uint GetConsoleCP ();

#endregion

private const int ERROR_NOT_FOUND = 1168;
private const int ERROR_OPERATION_ABORTED = 995;

// Console mode flags
private const uint ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200;
private const uint ENABLE_PROCESSED_INPUT = 0x0001;
Expand Down Expand Up @@ -183,6 +189,12 @@ public bool TryRead (byte [] buffer, out int bytesRead)
if (!success)
{
int error = Marshal.GetLastWin32Error ();

if (error == ERROR_OPERATION_ABORTED)
{
return false;
}

Logging.Warning ($"{nameof (WindowsVTInputHelper)}: ReadFile failed with error code: {error}");

return false;
Expand Down Expand Up @@ -253,6 +265,36 @@ public void Dispose ()
/// <returns><c>true</c> if there is at least one input event available.</returns>
public bool Peek () => GetNumberOfConsoleInputEvents (InputHandle, out uint count) && count > 0;

/// <summary>
/// Cancels any pending synchronous <see cref="ReadFile"/> on the Windows console input handle.
/// </summary>
public static void WakePendingRead ()
{
if (!RuntimeInformation.IsOSPlatform (OSPlatform.Windows))
{
return;
}

nint inputHandle = TerminalDevice.InputHandle;

if (inputHandle == nint.Zero || inputHandle == new nint (-1))
{
return;
}

if (CancelIoEx (inputHandle, nint.Zero))
{
return;
}

int error = Marshal.GetLastWin32Error ();

if (error != ERROR_NOT_FOUND)
{
Logging.Warning ($"{nameof (WindowsVTInputHelper)}: CancelIoEx failed with error code: {error}");
}
}

[DllImport ("kernel32.dll", SetLastError = true)]
private static extern bool FlushConsoleInputBuffer (nint hConsoleInput);

Expand Down
Loading