Quellcode durchsuchen

Fixes #2954. Modal view is always refreshing only by moving the mouse. (#2958)

* Fixes #2954. Modal view is always refreshing only by moving the mouse.

* Fixes invisible topLevel to be cleaned up which should be a drawing task.

* Forcing Shutdown.
BDisp vor 1 Jahr
Ursprung
Commit
e16205af85

+ 1 - 6
Terminal.Gui/Application.cs

@@ -665,8 +665,6 @@ namespace Terminal.Gui {
 					OverlappedTop?.OnActivate (state.Toplevel);
 					Top.SetSubViewNeedsDisplay ();
 					Refresh ();
-				} else if (Current.SuperView == null && Current?.Modal == true) {
-					Refresh ();
 				}
 			}
 
@@ -675,13 +673,11 @@ namespace Terminal.Gui {
 			if (state.Toplevel != Top &&
 				(Top.NeedsDisplay || Top.SubViewNeedsDisplay || Top.LayoutNeeded)) {
 				state.Toplevel.SetNeedsDisplay (state.Toplevel.Frame);
-				Top.Clear ();
 				Top.Draw ();
 				foreach (var top in _topLevels.Reverse ()) {
 					if (top != Top && top != state.Toplevel) {
 						top.SetNeedsDisplay ();
 						top.SetSubViewNeedsDisplay ();
-						top.Clear ();
 						top.Draw ();
 					}
 				}
@@ -690,14 +686,13 @@ namespace Terminal.Gui {
 				&& (Driver.Cols != state.Toplevel.Frame.Width || Driver.Rows != state.Toplevel.Frame.Height)
 				&& (state.Toplevel.NeedsDisplay || state.Toplevel.SubViewNeedsDisplay || state.Toplevel.LayoutNeeded)) {
 
-				state.Toplevel.Clear ();
+				state.Toplevel.Clear (new Rect (Point.Empty, new Size (Driver.Cols, Driver.Rows)));
 			}
 
 			if (state.Toplevel.NeedsDisplay ||
 				state.Toplevel.SubViewNeedsDisplay ||
 				state.Toplevel.LayoutNeeded ||
 				OverlappedChildNeedsDisplay ()) {
-				state.Toplevel.Clear ();
 				state.Toplevel.Draw ();
 				state.Toplevel.PositionCursor ();
 				Driver.Refresh ();

+ 107 - 2
UnitTests/Application/ApplicationTests.cs

@@ -1,10 +1,11 @@
-using System;
+using System;
 using System.Diagnostics;
 using System.Linq;
 using System.Runtime.InteropServices;
 using System.Threading;
 using System.Threading.Tasks;
 using Xunit;
+using Xunit.Abstractions;
 
 // Alias Console to MockConsole so we don't accidentally use Console
 using Console = Terminal.Gui.FakeConsole;
@@ -12,8 +13,11 @@ using Console = Terminal.Gui.FakeConsole;
 namespace Terminal.Gui.ApplicationTests;
 
 public class ApplicationTests {
-	public ApplicationTests ()
+	readonly ITestOutputHelper output;
+
+	public ApplicationTests (ITestOutputHelper output)
 	{
+		this.output = output;
 #if DEBUG_IDISPOSABLE
 		Responder.Instances.Clear ();
 		RunState.Instances.Clear ();
@@ -416,6 +420,107 @@ public class ApplicationTests {
 		Assert.Equal (3, count);
 	}
 
+	[Fact]
+	public void Run_Toplevel_With_Modal_View_Does_Not_Refresh_If_Not_Dirty ()
+	{
+		Init ();
+		var count = 0;
+		Dialog d = null;
+		var top = Application.Top;
+		top.DrawContent += (s, a) => count++;
+		var iteration = -1;
+		Application.Iteration += (s, a) => {
+			iteration++;
+			if (iteration == 0) {
+				d = new Dialog ();
+				d.DrawContent += (s, a) => count++;
+				Application.Run (d);
+			} else if (iteration < 3) {
+				Application.OnMouseEvent (new (new () { X = 0, Y = 0, Flags = MouseFlags.ReportMousePosition }));
+				Assert.False (top.NeedsDisplay);
+				Assert.False (top.SubViewNeedsDisplay);
+				Assert.False (top.LayoutNeeded);
+				Assert.False (d.NeedsDisplay);
+				Assert.False (d.SubViewNeedsDisplay);
+				Assert.False (d.LayoutNeeded);
+			} else {
+				Application.RequestStop ();
+			}
+		};
+		Application.Run ();
+		Application.Shutdown ();
+		// 1 - First top load, 1 - Dialog load, 1 - Dialog unload, Total - 3.
+		Assert.Equal (3, count);
+	}
+
+	[Fact]
+	public void Run_A_Modal_Toplevel_Refresh_Background_On_Moving ()
+	{
+		Init ();
+		var d = new Dialog () { Width = 5, Height = 5 };
+		((FakeDriver)Application.Driver).SetBufferSize (10, 10);
+		var rs = Application.Begin (d);
+		TestHelpers.AssertDriverContentsWithFrameAre (@"
+  ┌───┐
+  │   │
+  │   │
+  │   │
+  └───┘", output);
+
+		var attributes = new Attribute [] {
+			// 0
+			new Attribute (ColorName.White, ColorName.Black),
+			// 1
+			Colors.Dialog.Normal
+		};
+		TestHelpers.AssertDriverColorsAre (@"
+0000000000
+0000000000
+0011111000
+0011111000
+0011111000
+0011111000
+0011111000
+0000000000
+0000000000
+0000000000
+", null, attributes);
+
+		Application.OnMouseEvent (new MouseEventEventArgs (new MouseEvent () { X = 2, Y = 2, Flags = MouseFlags.Button1Pressed }));
+		Assert.Equal (d, Application.MouseGrabView);
+
+		Application.OnMouseEvent (new MouseEventEventArgs (new MouseEvent () { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition }));
+		Application.Refresh ();
+		TestHelpers.AssertDriverContentsWithFrameAre (@"
+ ┌───┐
+ │   │
+ │   │
+ │   │
+ └───┘", output);
+
+		attributes = new Attribute [] {
+			// 0
+			new Attribute (ColorName.White, ColorName.Black),
+			// 1
+			Colors.Dialog.Normal
+		};
+		TestHelpers.AssertDriverColorsAre (@"
+0000000000
+0111110000
+0111110000
+0111110000
+0111110000
+0111110000
+0000000000
+0000000000
+0000000000
+0000000000
+", null, attributes);
+
+		Application.End (rs);
+		Application.Shutdown ();
+	}
+
 	// TODO: Add tests for Run that test errorHandler
 
 	#endregion

+ 71 - 2
UnitTests/Views/OverlappedTests.cs

@@ -1,21 +1,27 @@
-using System;
+using System;
 using System.Diagnostics;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using Terminal.Gui;
 using Xunit;
+using Xunit.Abstractions;
 
 // Alias Console to MockConsole so we don't accidentally use Console
 using Console = Terminal.Gui.FakeConsole;
 
 namespace Terminal.Gui.ViewsTests {
 	public class OverlappedTests {
-		public OverlappedTests ()
+		readonly ITestOutputHelper output;
+
+		public OverlappedTests (ITestOutputHelper output)
 		{
+			this.output = output;
 #if DEBUG_IDISPOSABLE
 			Responder.Instances.Clear ();
 			RunState.Instances.Clear ();
+			this.output = output;
+
 #endif
 		}
 
@@ -674,5 +680,68 @@ namespace Terminal.Gui.ViewsTests {
 		{
 			Assert.Throws<NullReferenceException> (delegate { Application.MoveToOverlappedChild (null); });
 		}
+
+
+		[Fact, AutoInitShutdown]
+		public void Visible_False_Does_Not_Clear ()
+		{
+			var overlapped = new Overlapped ();
+			var win1 = new Window () { Width = 5, Height = 5, Visible = false };
+			var win2 = new Window () { X = 1, Y = 1, Width = 5, Height = 5 };
+			((FakeDriver)Application.Driver).SetBufferSize (10, 10);
+			var rs = Application.Begin (overlapped);
+			Application.Begin (win1);
+			Application.Begin (win2);
+			Assert.Equal (win2, Application.Current);
+			var firstIteration = false;
+			Application.RunIteration (ref rs, ref firstIteration);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+ ┌───┐
+ │   │
+ │   │
+ │   │
+ └───┘", output);
+			var attributes = new Attribute [] {
+				// 0
+				Colors.TopLevel.Normal,
+				// 1
+				Colors.Base.Normal
+			};
+			TestHelpers.AssertDriverColorsAre (@"
+0000000000
+0111110000
+0111110000
+0111110000
+0111110000
+0111110000
+0000000000
+0000000000
+0000000000
+0000000000", null, attributes);
+
+			Application.OnMouseEvent (new MouseEventEventArgs (new MouseEvent () { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed }));
+			Assert.Equal (win2, Application.MouseGrabView);
+			Application.OnMouseEvent (new MouseEventEventArgs (new MouseEvent () { X = 2, Y = 2, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition }));
+			Application.RunIteration (ref rs, ref firstIteration);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+  ┌───┐
+  │   │
+  │   │
+  │   │
+  └───┘", output);
+			TestHelpers.AssertDriverColorsAre (@"
+0000000000
+0000000000
+0011111000
+0011111000
+0011111000
+0011111000
+0011111000
+0000000000
+0000000000
+0000000000", null, attributes);
+
+			Application.Shutdown ();
+		}
 	}
 }