BDisp 4 лет назад
Родитель
Сommit
c0540b5de6

+ 3 - 3
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -647,16 +647,16 @@ namespace Terminal.Gui {
 		}
 
 		Action<MouseEvent> mouseHandler;
-		MainLoop mainLoop;
 
 		public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
 		{
 			// Note: Curses doesn't support keydown/up events and thus any passed keyDown/UpHandlers will never be called
 			Curses.timeout (0);
 			this.mouseHandler = mouseHandler;
-			this.mainLoop = mainLoop;
 
-			(mainLoop.Driver as UnixMainLoop).AddWatch (0, UnixMainLoop.Condition.PollIn, x => {
+			var mLoop = mainLoop.Driver as UnixMainLoop;
+
+			mLoop.AddWatch (0, UnixMainLoop.Condition.PollIn, x => {
 				ProcessInput (keyHandler, keyDownHandler, keyUpHandler, mouseHandler);
 				return true;
 			});

+ 37 - 23
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -36,25 +36,33 @@ namespace Terminal.Gui {
 
 		public override void AddRune (Rune rune)
 		{
+			if (contents.Length != Rows * Cols * 3) {
+				return;
+			}
 			rune = MakePrintable (rune);
-			if (Clip.Contains (ccol, crow)) {
+			var runeWidth = Rune.ColumnWidth (rune);
+			if (Clip.Contains (ccol, crow) && ccol + Math.Max (runeWidth, 1) <= Cols) {
 				contents [crow, ccol, 0] = (int)(uint)rune;
 				contents [crow, ccol, 1] = currentAttribute;
 				contents [crow, ccol, 2] = 1;
 				dirtyLine [crow] = true;
-			}
-			ccol++;
-			var runeWidth = Rune.ColumnWidth (rune);
-			if (runeWidth > 1) {
-				for (int i = 1; i < runeWidth; i++) {
-					contents [crow, ccol, 2] = 0;
-					if (ccol + 1 < cols) {
+
+				ccol++;
+				if (runeWidth > 1) {
+					for (int i = 1; i < runeWidth; i++) {
+						if (ccol < cols) {
+							contents [crow, ccol, 2] = 0;
+						} else {
+							break;
+						}
 						ccol++;
-					} else {
-						break;
 					}
 				}
+			} else if (ccol < cols && crow < rows) {
+				contents [crow, ccol, 2] = 1;
+				dirtyLine [crow] = true;
 			}
+
 			//if (ccol == Cols) {
 			//	ccol = 0;
 			//	if (crow + 1 < Rows)
@@ -107,7 +115,7 @@ namespace Terminal.Gui {
 
 			Clear ();
 			ResizeScreen ();
-			UpdateOffscreen ();
+			UpdateOffScreen ();
 
 			Colors.TopLevel = new ColorScheme ();
 			Colors.Base = new ColorScheme ();
@@ -193,15 +201,10 @@ namespace Terminal.Gui {
 
 			contents = new int [Rows, Cols, 3];
 			dirtyLine = new bool [Rows];
-
-			winChanging = false;
 		}
 
-		void UpdateOffscreen ()
+		void UpdateOffScreen ()
 		{
-			if (!winChanging) {
-				return;
-			}
 			// Can raise an exception while is still resizing.
 			try {
 				for (int row = 0; row < rows; row++) {
@@ -213,6 +216,8 @@ namespace Terminal.Gui {
 					}
 				}
 			} catch (IndexOutOfRangeException) { }
+
+			winChanging = false;
 		}
 
 		public override Attribute MakeAttribute (Color fore, Color back)
@@ -237,7 +242,7 @@ namespace Terminal.Gui {
 
 		public override void UpdateScreen ()
 		{
-			if (winChanging || Console.WindowHeight == 0
+			if (winChanging || Console.WindowHeight == 0 || contents.Length != Rows * Cols * 3
 				|| (!HeightAsBuffer && Rows != Console.WindowHeight)
 				|| (HeightAsBuffer && Rows != Console.BufferHeight)) {
 				return;
@@ -256,7 +261,6 @@ namespace Terminal.Gui {
 					if (contents [row, col, 2] != 1) {
 						continue;
 					}
-
 					if (Console.WindowHeight > 0) {
 						// Could happens that the windows is still resizing and the col is bigger than Console.WindowWidth.
 						try {
@@ -266,6 +270,10 @@ namespace Terminal.Gui {
 						}
 					}
 					for (; col < cols && contents [row, col, 2] == 1; col++) {
+						// Needed for the .Net Framework.
+						if (row == rows - 1 && col == cols - 1) {
+							break;
+						}
 						var color = contents [row, col, 1];
 						if (color != redrawColor) {
 							SetColor (color);
@@ -439,8 +447,10 @@ namespace Terminal.Gui {
 		bool winChanging;
 		public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
 		{
+			var mLoop = mainLoop.Driver as NetMainLoop;
+
 			// Note: Net doesn't support keydown/up events and thus any passed keyDown/UpHandlers will never be called
-			(mainLoop.Driver as NetMainLoop).KeyPressed = (consoleKey) => {
+			mLoop.KeyPressed = (consoleKey) => {
 				var map = MapKey (consoleKey);
 				if (map == (Key)0xffffffff) {
 					return;
@@ -460,7 +470,7 @@ namespace Terminal.Gui {
 				keyModifiers = new KeyModifiers ();
 			};
 
-			(mainLoop.Driver as NetMainLoop).WinChanged = (e) => {
+			mLoop.WinChanged = (e) => {
 				winChanging = true;
 				const int Min_WindowWidth = 14;
 				Size size = new Size ();
@@ -475,7 +485,7 @@ namespace Terminal.Gui {
 				cols = size.Width;
 				rows = size.Height;
 				ResizeScreen ();
-				UpdateOffscreen ();
+				UpdateOffScreen ();
 				if (!winChanging) {
 					TerminalResized.Invoke ();
 				}
@@ -529,6 +539,9 @@ namespace Terminal.Gui {
 		/// </summary>
 		public Action<ConsoleKeyInfo> KeyPressed;
 
+		/// <summary>
+		/// Invoked when the window is changed.
+		/// </summary>
 		public Action<int> WinChanged;
 
 		/// <summary>
@@ -581,6 +594,7 @@ namespace Terminal.Gui {
 					if (Console.BufferWidth != consoleDriver.Cols || Console.BufferHeight != consoleDriver.Rows
 						|| Console.WindowTop != consoleDriver.Top
 						|| Console.WindowHeight != lastWindowHeight) {
+						// Top only working on Windows.
 						newTop = Console.WindowTop;
 						lastWindowHeight = Console.WindowHeight;
 						return;
@@ -659,7 +673,7 @@ namespace Terminal.Gui {
 			}
 			if (winChanged) {
 				winChanged = false;
-				WinChanged.Invoke (newTop);
+				WinChanged?.Invoke (newTop);
 			}
 		}
 	}

+ 67 - 25
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -86,6 +86,13 @@ namespace Terminal.Gui {
 			return WriteConsoleOutput (ScreenBuffer, charInfoBuffer, coords, new Coord () { X = window.Left, Y = window.Top }, ref window);
 		}
 
+		public void ReadFromConsoleOutput (Size size, Coord coords, ref SmallRect window)
+		{
+			OriginalStdOutChars = new CharInfo [size.Height * size.Width];
+
+			ReadConsoleOutput (OutputHandle, OriginalStdOutChars, coords, new Coord () { X = 0, Y = 0 }, ref window);
+		}
+
 		public bool SetCursorPosition (Coord position)
 		{
 			return SetConsoleCursorPosition (ScreenBuffer, position);
@@ -540,6 +547,8 @@ namespace Terminal.Gui {
 			winConsole = new WindowsConsole ();
 		}
 
+		bool winChanging;
+
 		public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
 		{
 			this.keyHandler = keyHandler;
@@ -547,7 +556,33 @@ namespace Terminal.Gui {
 			this.keyUpHandler = keyUpHandler;
 			this.mouseHandler = mouseHandler;
 
-			(mainLoop.Driver as WindowsMainLoop).ProcessInput = (e) => ProcessInput (e);
+			var mLoop = mainLoop.Driver as WindowsMainLoop;
+
+			mLoop.ProcessInput = (e) => ProcessInput (e);
+
+			mLoop.WinChanged = (e) => {
+				ChangeWin (e);
+			};
+		}
+
+		private void ChangeWin (Size e)
+		{
+			winChanging = true;
+			if (!HeightAsBuffer) {
+				top = 0;
+				cols = e.Width;
+				rows = e.Height;
+				ResizeScreen ();
+				UpdateOffScreen ();
+				var bufferCoords = new WindowsConsole.Coord () {
+					X = (short)Clip.Width,
+					Y = (short)Clip.Height
+				};
+				winConsole.ReadFromConsoleOutput (e, bufferCoords, ref damageRegion);
+				if (!winChanging) {
+					TerminalResized.Invoke ();
+				}
+			}
 		}
 
 		void ProcessInput (WindowsConsole.InputRecord inputEvent)
@@ -1108,12 +1143,15 @@ namespace Terminal.Gui {
 
 		void UpdateOffScreen ()
 		{
-			for (int row = 0; row < rows; row++)
+			for (int row = 0; row < rows; row++) {
 				for (int col = 0; col < cols; col++) {
 					int position = row * cols + col;
 					OutputBuffer [position].Attributes = (ushort)Colors.TopLevel.Normal;
 					OutputBuffer [position].Char.UnicodeChar = ' ';
 				}
+			}
+
+			winChanging = false;
 		}
 
 		int ccol, crow;
@@ -1209,12 +1247,12 @@ namespace Terminal.Gui {
 				Y = (short)Clip.Height
 			};
 
-			var window = new WindowsConsole.SmallRect () {
-				Top = 0,
-				Left = 0,
-				Right = (short)Clip.Right,
-				Bottom = (short)Clip.Bottom
-			};
+			//var window = new WindowsConsole.SmallRect () {
+			//	Top = 0,
+			//	Left = 0,
+			//	Right = (short)Clip.Right,
+			//	Bottom = (short)Clip.Bottom
+			//};
 
 			UpdateCursor ();
 			winConsole.WriteToConsole (OutputBuffer, bufferCoords, damageRegion);
@@ -1282,6 +1320,7 @@ namespace Terminal.Gui {
 		ConsoleDriver consoleDriver;
 		WindowsConsole winConsole;
 		bool winChanged;
+		Size windowSize;
 		CancellationTokenSource tokenSource = new CancellationTokenSource ();
 
 		// The records that we keep fetching
@@ -1292,6 +1331,11 @@ namespace Terminal.Gui {
 		/// </summary>
 		public Action<WindowsConsole.InputRecord> ProcessInput;
 
+		/// <summary>
+		/// Invoked when the window is changed.
+		/// </summary>
+		public Action<Size> WinChanged;
+
 		public WindowsMainLoop (ConsoleDriver consoleDriver = null)
 		{
 			if (consoleDriver == null) {
@@ -1304,7 +1348,7 @@ namespace Terminal.Gui {
 		void IMainLoopDriver.Setup (MainLoop mainLoop)
 		{
 			this.mainLoop = mainLoop;
-			Task.Run ((Action)WindowsInputHandler);
+			Task.Run (WindowsInputHandler);
 			Task.Run (CheckWinChange);
 		}
 
@@ -1335,15 +1379,11 @@ namespace Terminal.Gui {
 		{
 			while (true) {
 				if (!consoleDriver.HeightAsBuffer) {
-					if (Console.WindowWidth != consoleDriver.Cols || Console.WindowHeight != consoleDriver.Rows
-						|| Console.WindowTop != consoleDriver.Top) {    // Top only working on Windows.
-						return;
-					}
-				} else {
-					if (Console.BufferWidth != consoleDriver.Cols || Console.BufferHeight != consoleDriver.Rows) {
-						return;
+					windowSize = new Size (Console.WindowWidth, Console.WindowHeight);
+					if (windowSize.Height < consoleDriver.Rows) {
+						// I still haven't been able to find a way to capture the shrinking in height.
+						//return;
 					}
-					break;
 				}
 			}
 		}
@@ -1351,7 +1391,6 @@ namespace Terminal.Gui {
 		void IMainLoopDriver.Wakeup ()
 		{
 			//tokenSource.Cancel ();
-			eventReady.Reset ();
 			eventReady.Set ();
 		}
 
@@ -1376,7 +1415,7 @@ namespace Terminal.Gui {
 			}
 
 			if (!tokenSource.IsCancellationRequested) {
-				return result != null || CheckTimers (wait, out waitTimeout);
+				return result != null || CheckTimers (wait, out waitTimeout) || winChanged;
 			}
 
 			tokenSource.Dispose ();
@@ -1409,12 +1448,15 @@ namespace Terminal.Gui {
 
 		void IMainLoopDriver.MainIteration ()
 		{
-			if (result == null)
-				return;
-
-			var inputEvent = result [0];
-			result = null;
-			ProcessInput.Invoke (inputEvent);
+			if (result != null) {
+				var inputEvent = result [0];
+				result = null;
+				ProcessInput?.Invoke (inputEvent);
+			}
+			if (winChanged) {
+				winChanged = false;
+				WinChanged?.Invoke (windowSize);
+			}
 		}
 	}
 }