瀏覽代碼

Documenting hack for changewin

Tigger Kindel 1 年之前
父節點
當前提交
482a956646
共有 1 個文件被更改,包括 57 次插入8 次删除
  1. 57 8
      Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

+ 57 - 8
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1,6 +1,19 @@
 //
 //
 // WindowsDriver.cs: Windows specific driver
 // WindowsDriver.cs: Windows specific driver
 //
 //
+
+// HACK:
+// WindowsConsole/Terminal has two issues:
+// 1) Tearing can occur when the console is resized.
+// 2) The values provided during Init (and the first WindowsConsole.EventType.WindowBufferSize) are not correct.
+//
+// If HACK_CHECK_WINCHANGED is defined then we ignore WindowsConsole.EventType.WindowBufferSize events
+// and instead check the console size every every 500ms in a thread in WidowsMainLoop. 
+// As of Windows 11 23H2 25947.1000 and/or WT 1.19.2682 tearing no longer occurs when using 
+// the WindowsConsole.EventType.WindowBufferSize event. However, on Init the window size is
+// still incorrect so we still need this hack.
+#define HACK_CHECK_WINCHANGED
+
 using System.Text;
 using System.Text;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
@@ -14,6 +27,7 @@ using System.Management;
 
 
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
+
 internal class WindowsConsole {
 internal class WindowsConsole {
 	public const int STD_OUTPUT_HANDLE = -11;
 	public const int STD_OUTPUT_HANDLE = -11;
 	public const int STD_INPUT_HANDLE = -10;
 	public const int STD_INPUT_HANDLE = -10;
@@ -40,10 +54,10 @@ internal class WindowsConsole {
 
 
 	CharInfo [] _originalStdOutChars;
 	CharInfo [] _originalStdOutChars;
 
 
-	public bool WriteToConsole (Size size, ExtendedCharInfo [] charInfoBuffer, Coord coords, SmallRect window, bool force16Colors)
+	public bool WriteToConsole (Size size, ExtendedCharInfo [] charInfoBuffer, Coord bufferSize, SmallRect window, bool force16Colors)
 	{
 	{
 		if (_screenBuffer == IntPtr.Zero) {
 		if (_screenBuffer == IntPtr.Zero) {
-			ReadFromConsoleOutput (size, coords, ref window);
+			ReadFromConsoleOutput (size, bufferSize, ref window);
 		}
 		}
 
 
 		bool result = false;
 		bool result = false;
@@ -57,7 +71,7 @@ internal class WindowsConsole {
 				};
 				};
 			}
 			}
 
 
-			result = WriteConsoleOutput (_screenBuffer, ci, coords, new Coord () { X = window.Left, Y = window.Top }, ref window);
+			result = WriteConsoleOutput (_screenBuffer, ci, bufferSize, new Coord () { X = window.Left, Y = window.Top }, ref window);
 		} else {
 		} else {
 
 
 			_stringBuilder.Clear ();
 			_stringBuilder.Clear ();
@@ -848,9 +862,12 @@ internal class WindowsDriver : ConsoleDriver {
 
 
 		_mainLoop = mainLoop.MainLoopDriver as WindowsMainLoop;
 		_mainLoop = mainLoop.MainLoopDriver as WindowsMainLoop;
 		_mainLoop.ProcessInput += ProcessInput;
 		_mainLoop.ProcessInput += ProcessInput;
+#if HACK_CHECK_WINCHANGED
 		_mainLoop.WinChanged += ChangeWin;
 		_mainLoop.WinChanged += ChangeWin;
+#endif
 	}
 	}
 
 
+#if HACK_CHECK_WINCHANGED
 	private void ChangeWin (Object s, SizeChangedEventArgs e)
 	private void ChangeWin (Object s, SizeChangedEventArgs e)
 	{
 	{
 		var w = e.Size.Width;
 		var w = e.Size.Width;
@@ -874,6 +891,7 @@ internal class WindowsDriver : ConsoleDriver {
 		ClearContents ();
 		ClearContents ();
 		TerminalResized.Invoke ();
 		TerminalResized.Invoke ();
 	}
 	}
+#endif
 
 
 	void ProcessInput (WindowsConsole.InputRecord inputEvent)
 	void ProcessInput (WindowsConsole.InputRecord inputEvent)
 	{
 	{
@@ -988,6 +1006,18 @@ internal class WindowsDriver : ConsoleDriver {
 
 
 		case WindowsConsole.EventType.Focus:
 		case WindowsConsole.EventType.Focus:
 			break;
 			break;
+
+#if !HACK_CHECK_WINCHANGED
+		case WindowsConsole.EventType.WindowBufferSize:
+			
+			Cols = inputEvent.WindowBufferSizeEvent._size.X;
+			Rows = inputEvent.WindowBufferSizeEvent._size.Y;
+
+			ResizeScreen ();
+			ClearContents ();
+			TerminalResized.Invoke ();
+			break;
+#endif
 		}
 		}
 	}
 	}
 
 
@@ -1485,6 +1515,8 @@ internal class WindowsDriver : ConsoleDriver {
 
 
 		try {
 		try {
 			if (WinConsole != null) {
 			if (WinConsole != null) {
+				// BUGBUG: The results from GetConsoleOutputWindow are incorrect when called from Init. 
+				// Our thread in WindowsMainLoop.CheckWin will get the correct results. See #if HACK_CHECK_WINCHANGED
 				var winSize = WinConsole.GetConsoleOutputWindow (out Point pos);
 				var winSize = WinConsole.GetConsoleOutputWindow (out Point pos);
 				Cols = winSize.Width;
 				Cols = winSize.Width;
 				Rows = winSize.Height;
 				Rows = winSize.Height;
@@ -1735,8 +1767,9 @@ internal class WindowsDriver : ConsoleDriver {
 	{
 	{
 		if (_mainLoop != null) {
 		if (_mainLoop != null) {
 			_mainLoop.ProcessInput -= ProcessInput;
 			_mainLoop.ProcessInput -= ProcessInput;
-			_mainLoop.WinChanged -= ChangeWin;
-			//_mainLoop.Dispose ();
+#if HACK_CHECK_WINCHANGED
+			//_mainLoop.WinChanged -= ChangeWin;
+#endif
 		}
 		}
 		_mainLoop = null;
 		_mainLoop = null;
 
 
@@ -1767,12 +1800,9 @@ internal class WindowsDriver : ConsoleDriver {
 internal class WindowsMainLoop : IMainLoopDriver {
 internal class WindowsMainLoop : IMainLoopDriver {
 	readonly ManualResetEventSlim _eventReady = new ManualResetEventSlim (false);
 	readonly ManualResetEventSlim _eventReady = new ManualResetEventSlim (false);
 	readonly ManualResetEventSlim _waitForProbe = new ManualResetEventSlim (false);
 	readonly ManualResetEventSlim _waitForProbe = new ManualResetEventSlim (false);
-	readonly ManualResetEventSlim _winChange = new ManualResetEventSlim (false);
 	MainLoop _mainLoop;
 	MainLoop _mainLoop;
 	readonly ConsoleDriver _consoleDriver;
 	readonly ConsoleDriver _consoleDriver;
 	readonly WindowsConsole _winConsole;
 	readonly WindowsConsole _winConsole;
-	bool _winChanged;
-	Size _windowSize;
 	CancellationTokenSource _eventReadyTokenSource = new CancellationTokenSource ();
 	CancellationTokenSource _eventReadyTokenSource = new CancellationTokenSource ();
 	CancellationTokenSource _inputHandlerTokenSource = new CancellationTokenSource ();
 	CancellationTokenSource _inputHandlerTokenSource = new CancellationTokenSource ();
 
 
@@ -1799,7 +1829,9 @@ internal class WindowsMainLoop : IMainLoopDriver {
 	{
 	{
 		_mainLoop = mainLoop;
 		_mainLoop = mainLoop;
 		Task.Run (WindowsInputHandler, _inputHandlerTokenSource.Token);
 		Task.Run (WindowsInputHandler, _inputHandlerTokenSource.Token);
+#if HACK_CHECK_WINCHANGED
 		Task.Run (CheckWinChange);
 		Task.Run (CheckWinChange);
+#endif
 	}
 	}
 
 
 	void WindowsInputHandler ()
 	void WindowsInputHandler ()
@@ -1824,12 +1856,18 @@ internal class WindowsMainLoop : IMainLoopDriver {
 		}
 		}
 	}
 	}
 
 
+#if HACK_CHECK_WINCHANGED
+	readonly ManualResetEventSlim _winChange = new ManualResetEventSlim (false);
+	bool _winChanged;
+	Size _windowSize;
 	void CheckWinChange ()
 	void CheckWinChange ()
 	{
 	{
 		while (_mainLoop != null) {
 		while (_mainLoop != null) {
 			_winChange.Wait ();
 			_winChange.Wait ();
 			_winChange.Reset ();
 			_winChange.Reset ();
 
 
+			// Check if the window size changed every half second. 
+			// We do this to minimize the weird tearing seen on Windows when resizing the console
 			while (_mainLoop != null) {
 			while (_mainLoop != null) {
 				Task.Delay (500).Wait ();
 				Task.Delay (500).Wait ();
 				_windowSize = _winConsole.GetConsoleBufferWindow (out _);
 				_windowSize = _winConsole.GetConsoleBufferWindow (out _);
@@ -1843,6 +1881,7 @@ internal class WindowsMainLoop : IMainLoopDriver {
 			_eventReady.Set ();
 			_eventReady.Set ();
 		}
 		}
 	}
 	}
+#endif
 
 
 	void IMainLoopDriver.Wakeup ()
 	void IMainLoopDriver.Wakeup ()
 	{
 	{
@@ -1852,7 +1891,9 @@ internal class WindowsMainLoop : IMainLoopDriver {
 	bool IMainLoopDriver.EventsPending ()
 	bool IMainLoopDriver.EventsPending ()
 	{
 	{
 		_waitForProbe.Set ();
 		_waitForProbe.Set ();
+#if HACK_CHECK_WINCHANGED          
 		_winChange.Set ();
 		_winChange.Set ();
+#endif
 		if (_mainLoop.CheckTimersAndIdleHandlers (out var waitTimeout)) {
 		if (_mainLoop.CheckTimersAndIdleHandlers (out var waitTimeout)) {
 			return true;
 			return true;
 		}
 		}
@@ -1870,7 +1911,11 @@ internal class WindowsMainLoop : IMainLoopDriver {
 		}
 		}
 
 
 		if (!_eventReadyTokenSource.IsCancellationRequested) {
 		if (!_eventReadyTokenSource.IsCancellationRequested) {
+#if HACK_CHECK_WINCHANGED
 			return _resultQueue.Count > 0 || _mainLoop.CheckTimersAndIdleHandlers (out _) || _winChanged;
 			return _resultQueue.Count > 0 || _mainLoop.CheckTimersAndIdleHandlers (out _) || _winChanged;
+#else
+			return _resultQueue.Count > 0 || _mainLoop.CheckTimersAndIdleHandlers (out _);
+#endif
 		}
 		}
 
 
 		_eventReadyTokenSource.Dispose ();
 		_eventReadyTokenSource.Dispose ();
@@ -1887,10 +1932,12 @@ internal class WindowsMainLoop : IMainLoopDriver {
 				ProcessInput?.Invoke (inputEvent);
 				ProcessInput?.Invoke (inputEvent);
 			}
 			}
 		}
 		}
+#if HACK_CHECK_WINCHANGED
 		if (_winChanged) {
 		if (_winChanged) {
 			_winChanged = false;
 			_winChanged = false;
 			WinChanged?.Invoke (this, new SizeChangedEventArgs (_windowSize));
 			WinChanged?.Invoke (this, new SizeChangedEventArgs (_windowSize));
 		}
 		}
+#endif
 	}
 	}
 
 
 	void IMainLoopDriver.TearDown ()
 	void IMainLoopDriver.TearDown ()
@@ -1902,7 +1949,9 @@ internal class WindowsMainLoop : IMainLoopDriver {
 		_eventReadyTokenSource?.Dispose ();
 		_eventReadyTokenSource?.Dispose ();
 		_eventReady?.Dispose ();
 		_eventReady?.Dispose ();
 
 
+#if HACK_CHECK_WINCHANGED
 		_winChange?.Dispose ();
 		_winChange?.Dispose ();
+#endif
 		_waitForProbe?.Dispose ();
 		_waitForProbe?.Dispose ();
 
 
 		_mainLoop = null;
 		_mainLoop = null;