瀏覽代碼

Fixing unit tests. WIP

Tig 9 月之前
父節點
當前提交
5a41d2c0fc

+ 4 - 8
Terminal.Gui/Application/Application.Run.cs

@@ -537,11 +537,7 @@ public static partial class Application // Run (Begin, Run, End, Stop)
     // TODO: Rename this to DrawRunnables in https://github.com/gui-cs/Terminal.Gui/issues/2491
     private static void DrawToplevels (bool forceDraw)
     {
-        // Reset the clip region to the entire screen
-        if (Driver is { })
-        {
-            Driver.Clip = new (Screen);
-        }
+        ClipToScreen ();
 
         foreach (Toplevel tl in TopLevels)
         {
@@ -550,11 +546,11 @@ public static partial class Application // Run (Begin, Run, End, Stop)
                 tl.SetNeedsDraw ();
             }
 
-            //Region? saved = Driver?.Clip.Clone ();
             tl.Draw ();
-            //Driver.Clip = saved;
-            Driver?.Clip.Exclude (tl.FrameToScreen ());
+            ExcludeFromClip (tl.FrameToScreen ());
         }
+
+        ClipToScreen ();
     }
 
 

+ 40 - 0
Terminal.Gui/Application/Application.Screen.cs

@@ -67,4 +67,44 @@ public static partial class Application // Screen related stuff
 
         return true;
     }
+
+    #region Clip Support
+    /// <summary>
+    ///     Sets the clip region to the screen.
+    /// </summary>
+    /// <returns>The previous clip region.</returns>>
+    public static Region? ClipToScreen ()
+    {
+        Region? previous = Driver?.Clip;
+        if (Driver is { })
+        {
+            Driver.Clip = new (Screen);
+        }
+
+        return previous;
+    }
+
+    /// <summary>
+    ///     Sets the clip to the specified region.
+    /// </summary>
+    /// <param name="region"></param>
+    public static void SetClip (Region? region)
+    {
+        if (Driver is { } && region is {})
+        {
+            Driver.Clip = region;
+        }
+    }
+
+    /// <summary>
+    ///      Removes the specified rectangle from the Clip.
+    /// </summary>
+    /// <param name="rectangle"></param>
+    public static void ExcludeFromClip (Rectangle rectangle)
+    {
+        Driver?.Clip?.Exclude (rectangle);
+    }
+
+    #endregion Clip Support
+
 }

+ 1 - 1
Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs

@@ -325,7 +325,7 @@ public abstract class ConsoleDriver
         //CONCURRENCY: Unsynchronized access to Clip isn't safe.
         // TODO: ClearContents should not clear the clip; it should only clear the contents. Move clearing it elsewhere.
         Clip = new (Screen);
-        
+
         _dirtyLines = new bool [Rows];
 
         lock (Contents)

+ 1 - 1
Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs

@@ -456,7 +456,7 @@ public class FakeDriver : ConsoleDriver
         }
 
         // CONCURRENCY: Unsynchronized access to Clip is not safe.
-        Clip = new (new (0, 0, Cols, Rows));
+        Clip = new (Screen);
     }
 
     public override void UpdateCursor ()

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

@@ -1237,12 +1237,12 @@ internal class NetDriver : ConsoleDriver
             catch (IOException)
             {
                 // CONCURRENCY: Unsynchronized access to Clip is not safe.
-                Clip = new (new (0, 0, Cols, Rows));
+                Clip = new (Screen);
             }
             catch (ArgumentOutOfRangeException)
             {
                 // CONCURRENCY: Unsynchronized access to Clip is not safe.
-                Clip = new (new (0, 0, Cols, Rows));
+                Clip = new (Screen);
             }
         }
         else
@@ -1251,7 +1251,7 @@ internal class NetDriver : ConsoleDriver
         }
 
         // CONCURRENCY: Unsynchronized access to Clip is not safe.
-        Clip = new (new (0, 0, Cols, Rows));
+        Clip = new (Screen);
     }
 
     #endregion

+ 2 - 2
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1439,7 +1439,7 @@ internal class WindowsDriver : ConsoleDriver
 
         _outputBuffer = new WindowsConsole.ExtendedCharInfo [Rows * Cols];
         // CONCURRENCY: Unsynchronized access to Clip is not safe.
-        Clip = new (new (0, 0, Cols, Rows));
+        Clip = new (Screen);
 
         _damageRegion = new WindowsConsole.SmallRect
         {
@@ -1859,7 +1859,7 @@ internal class WindowsDriver : ConsoleDriver
     {
         _outputBuffer = new WindowsConsole.ExtendedCharInfo [Rows * Cols];
         // CONCURRENCY: Unsynchronized access to Clip is not safe.
-        Clip = new (new (0, 0, Cols, Rows));
+        Clip = new (Screen);
 
         _damageRegion = new WindowsConsole.SmallRect
         {

+ 1 - 1
Terminal.Gui/Drawing/Region.cs

@@ -71,7 +71,7 @@ public class Region : IDisposable
     }
 
     /// <summary>
-    ///     Removes the portion of the specified rectangle from the region.
+    ///     Removes the specified rectangle from the region.
     /// </summary>
     /// <param name="rectangle">The rectangle to exclude from the region.</param>
     public void Exclude (Rectangle rectangle) { _rectangles = _rectangles.SelectMany (r => SubtractRectangle (r, rectangle)).ToList (); }

+ 2 - 2
Terminal.Gui/View/View.Drawing.Clipping.cs

@@ -23,7 +23,7 @@ public partial class View
             frameRegion.Exclude (adornment.Thickness.GetInside (Frame));
         }
 
-        Driver.Clip = frameRegion;
+        Application.SetClip (frameRegion);
 
         return previous;
 
@@ -72,7 +72,7 @@ public partial class View
             viewportRegion?.Exclude (adornment.Thickness.GetInside (viewport));
         }
 
-        Driver.Clip = viewportRegion;
+        Application.SetClip (viewportRegion);
 
         return previous;
     }

+ 1 - 1
Terminal.Gui/View/View.Drawing.Primitives.cs

@@ -121,7 +121,7 @@ public partial class View
         Attribute prev = SetAttribute (new (color ?? GetNormalColor ().Background));
         Driver.FillRect (toClear);
         SetAttribute (prev);
-        Driver.Clip = prevClip;
+        Application.SetClip (prevClip);
     }
 
     #endregion Drawing Primitives

+ 39 - 56
Terminal.Gui/View/View.Drawing.cs

@@ -22,71 +22,58 @@ public partial class View // Drawing APIs
     /// </remarks>
     public void Draw ()
     {
-        if (!CanBeVisible (this) || (!NeedsDraw && !SubViewNeedsDraw))
+        Region? saved = null;
+        if (CanBeVisible (this) && (NeedsDraw || SubViewNeedsDraw))
         {
-            if (this is not Adornment)
+            if (Border is { Diagnostics: ViewDiagnosticFlags.DrawIndicator })
             {
-                Driver?.Clip.Exclude (FrameToScreen ());
+                if (Border.DrawIndicator is { })
+                {
+                    Border.DrawIndicator.AdvanceAnimation (false);
+                    Border.DrawIndicator.DrawText ();
+
+                }
             }
 
-            return;
-        }
+            // Frame/View-relative relative, thus the bounds location should be 0,0
+            //Debug.Assert(clipRegion.GetBounds().X == 0 && clipRegion.GetBounds ().Y == 0);
 
-        if (Border is { Diagnostics: ViewDiagnosticFlags.DrawIndicator })
-        {
-            if (Border.DrawIndicator is { })
-            {
-                Border.DrawIndicator.AdvanceAnimation (false);
-                Border.DrawIndicator.DrawText ();
+            saved = SetClipToFrame ();
+            DoDrawAdornments ();
+            DoSetAttribute ();
 
-            }
-        }
+            Application.SetClip (saved);
 
-        // Frame/View-relative relative, thus the bounds location should be 0,0
-        //Debug.Assert(clipRegion.GetBounds().X == 0 && clipRegion.GetBounds ().Y == 0);
+            // By default, we clip to the viewport preventing drawing outside the viewport
+            // We also clip to the content, but if a developer wants to draw outside the viewport, they can do
+            // so via settings. SetClip honors the ViewportSettings.DisableVisibleContentClipping flag.
+            // Get our Viewport in screen coordinates
 
-        Region? saved = SetClipToFrame ();
-        DoDrawAdornments ();
-        DoSetAttribute ();
-        if (saved is { })
-        {
-            Driver!.Clip = saved;
-        }
-        // By default, we clip to the viewport preventing drawing outside the viewport
-        // We also clip to the content, but if a developer wants to draw outside the viewport, they can do
-        // so via settings. SetClip honors the ViewportSettings.DisableVisibleContentClipping flag.
-        // Get our Viewport in screen coordinates
+            saved = SetClipToViewport ();
 
-        saved = SetClipToViewport ();
+            DoClearViewport ();
+            DoDrawText ();
+            DoDrawContent ();
 
-        DoClearViewport ();
-        DoDrawText ();
-        DoDrawContent ();
+            DoDrawSubviews ();
 
-        DoDrawSubviews ();
+            // Restore the clip before rendering the line canvas and adornment subviews
+            // because they may draw outside the viewport.
+            Application.SetClip (saved);
 
-        // Restore the clip before rendering the line canvas and adornment subviews
-        // because they may draw outside the viewport.
-        if (saved is { })
-        {
-            Driver!.Clip = saved;
+            saved = SetClipToFrame ();
+            DoRenderLineCanvas ();
+            DoDrawAdornmentSubViews ();
+            ClearNeedsDraw ();
         }
 
-        saved = SetClipToFrame ();
-        DoRenderLineCanvas ();
-        DoDrawAdornmentSubViews ();
-        ClearNeedsDraw ();
-
         // We're done
         DoDrawComplete ();
-        if (saved is { })
-        {
-            Driver!.Clip = saved;
-        }
+        Application.SetClip (saved);
 
-        if (this is not Adornment)
+        if (this is not Adornment && Driver?.Clip is {})
         {
-            Driver?.Clip.Exclude (FrameToScreen ());
+            Application.ExcludeFromClip (FrameToScreen ());
         }
 
     }
@@ -106,10 +93,8 @@ public partial class View // Drawing APIs
 
             Region? saved = Margin?.SetClipToFrame ();
             Margin?.DoDrawSubviews ();
-            if (saved is { })
-            {
-                Driver!.Clip = saved;
-            }
+            Application.SetClip (saved);
+
         }
 
         if (Border?.Subviews is { } && Border.Thickness != Thickness.Empty)
@@ -119,7 +104,9 @@ public partial class View // Drawing APIs
                 subview.SetNeedsDraw ();
             }
 
+            Region? saved = Border?.SetClipToFrame ();
             Border?.DoDrawSubviews ();
+            Application.SetClip (saved);
         }
 
         if (Padding?.Subviews is { } && Padding.Thickness != Thickness.Empty)
@@ -131,11 +118,7 @@ public partial class View // Drawing APIs
 
             Region? saved = Padding?.SetClipToFrame ();
             Padding?.DoDrawSubviews ();
-            if (saved is { })
-            {
-                Driver!.Clip = saved;
-            }
-
+            Application.SetClip (saved);
         }
     }
 

+ 4 - 3
Terminal.Gui/Views/Menu/Menu.cs

@@ -409,8 +409,9 @@ internal sealed class Menu : View
         DrawAdornments ();
         RenderLineCanvas ();
 
-        Region savedClip = Driver.Clip;
-        Driver.Clip = new (new (0, 0, Driver.Cols, Driver.Rows));
+        // BUGBUG: Views should not change the clip. Doing so is an indcation of poor design or a bug in the framework.
+        Region? savedClip = Application.ClipToScreen ();
+
         SetAttribute (GetNormalColor ());
 
         for (int i = Viewport.Y; i < _barItems!.Children.Length; i++)
@@ -578,7 +579,7 @@ internal sealed class Menu : View
             }
         }
 
-        Driver.Clip = savedClip;
+        Application.SetClip (savedClip);
     }
 
     public override Point? PositionCursor ()

+ 3 - 3
Terminal.Gui/Views/TableView/TableView.cs

@@ -1282,19 +1282,19 @@ public class TableView : View, IDesignable
             {
                 // invert the color of the current cell for the first character
                 SetAttribute (new Attribute (cellColor.Background, cellColor.Foreground));
-                Driver.AddRune ((Rune)render [0]);
+                Driver?.AddRune ((Rune)render [0]);
 
                 if (render.Length > 1)
                 {
                     SetAttribute (cellColor);
-                    Driver.AddStr (render.Substring (1));
+                    Driver?.AddStr (render.Substring (1));
                 }
             }
         }
         else
         {
             SetAttribute (cellColor);
-            Driver.AddStr (render);
+            Driver?.AddStr (render);
         }
     }
 

+ 1 - 1
Terminal.Gui/Views/TextField.cs

@@ -1779,7 +1779,7 @@ public class TextField : View
             render = render [..Viewport.Width];
         }
 
-        Driver.AddStr (render);
+        Driver?.AddStr (render);
     }
 
     private void SetClipboard (IEnumerable<Rune> text)

+ 2 - 2
Terminal.Gui/Views/TreeView/Branch.cs

@@ -237,7 +237,7 @@ internal class Branch<T> where T : class
         };
         tree.OnDrawLine (e);
 
-        if (!e.Handled)
+        if (!e.Handled && driver != null)
         {
             foreach (Cell cell in cells)
             {
@@ -246,7 +246,7 @@ internal class Branch<T> where T : class
             }
         }
 
-        driver.SetAttribute (colorScheme.Normal);
+        driver?.SetAttribute (colorScheme.Normal);
     }
 
     /// <summary>Expands the current branch if possible.</summary>

+ 65 - 281
UnitTests/Drawing/RulerTests.cs

@@ -37,19 +37,11 @@ public class RulerTests
     }
 
     [Fact]
-    [AutoInitShutdown]
+    [SetupFakeDriver]
     public void Draw_Horizontal ()
     {
         var len = 15;
 
-        // Add a frame so we can see the ruler
-        var f = new FrameView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () };
-        var top = new Toplevel ();
-        top.Add (f);
-        Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (len + 5, 5);
-        Assert.Equal (new (0, 0, len + 5, 5), f.Frame);
-
         var r = new Ruler ();
         Assert.Equal (Orientation.Horizontal, r.Orientation);
 
@@ -58,123 +50,40 @@ public class RulerTests
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
-|123456789|1234────┐
-│                  │
-│                  │
-│                  │
-└──────────────────┘",
+|123456789|1234",
                                                       _output
                                                      );
 
         // Postive offset
-        top.SetNeedsDraw ();
-        Application.LayoutAndDrawToplevels ();
         r.Draw (new (1, 1));
 
-        TestHelpers.AssertDriverContentsWithFrameAre (
+        TestHelpers.AssertDriverContentsAre (
                                                       @"
-┌──────────────────┐
-│|123456789|1234   │
-│                  │
-│                  │
-└──────────────────┘",
+|123456789|1234
+ |123456789|1234
+",
                                                       _output
                                                      );
 
         // Negative offset
-        top.SetNeedsDraw ();
-        Application.LayoutAndDrawToplevels ();
-        r.Draw (new (-1, 1));
-
-        TestHelpers.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌──────────────────┐
-123456789|1234     │
-│                  │
-│                  │
-└──────────────────┘",
-                                                      _output
-                                                     );
-
-        // Clip
-        top.SetNeedsDraw ();
-        Application.LayoutAndDrawToplevels ();
-        r.Draw (new (10, 1));
-
-        TestHelpers.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌──────────────────┐
-│         |123456789
-│                  │
-│                  │
-└──────────────────┘",
-                                                      _output
-                                                     );
-        top.Dispose ();
+        r.Draw (new (-1, 3));
+
+        TestHelpers.AssertDriverContentsAre (
+                                             @"
+|123456789|1234
+ |123456789|1234
+123456789|1234
+",
+                                             _output
+                                            );
     }
 
     [Fact]
-    [AutoInitShutdown]
-    public void Draw_Horizontal_Start ()
-    {
-        var len = 15;
-
-        // Add a frame so we can see the ruler
-        var f = new FrameView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () };
-        var top = new Toplevel ();
-        top.Add (f);
-        Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (len + 5, 5);
-        Assert.Equal (new (0, 0, len + 5, 5), f.Frame);
-
-        var r = new Ruler ();
-        Assert.Equal (Orientation.Horizontal, r.Orientation);
-
-        r.Length = len;
-        r.Draw (Point.Empty, 1);
-
-        TestHelpers.AssertDriverContentsWithFrameAre (
-                                                      @"
-123456789|12345────┐
-│                  │
-│                  │
-│                  │
-└──────────────────┘",
-                                                      _output
-                                                     );
-
-        f.SetNeedsDraw();
-        Application.LayoutAndDrawToplevels ();
-        r.Length = len;
-        r.Draw (new (1, 0), 1);
-
-        TestHelpers.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌123456789|12345───┐
-│                  │
-│                  │
-│                  │
-└──────────────────┘",
-                                                      _output
-                                                     );
-        top.Dispose ();
-    }
-
-    [Fact]
-    [AutoInitShutdown]
+    [SetupFakeDriver]
     public void Draw_Vertical ()
     {
         var len = 15;
 
-        // Add a frame so we can see the ruler
-        var f = new FrameView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () };
-
-        var top = new Toplevel ();
-        top.Add (f);
-        Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, len + 5);
-        Assert.Equal (new (0, 0, 5, len + 5), f.Frame);
-
         var r = new Ruler ();
         r.Orientation = Orientation.Vertical;
         r.Length = len;
@@ -182,196 +91,71 @@ public class RulerTests
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
--───┐
-1   │
-2   │
-3   │
-4   │
-5   │
-6   │
-7   │
-8   │
-9   │
--   │
-1   │
-2   │
-3   │
-4   │
-│   │
-│   │
-│   │
-│   │
-└───┘",
+-
+1
+2
+3
+4
+5
+6
+7
+8
+9
+-
+1
+2
+3
+4",
                                                       _output
                                                      );
 
-        // Postive offset
-        f.SetNeedsDraw ();
-        Application.LayoutAndDrawToplevels (true);
         r.Draw (new (1, 1));
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
-┌───┐
-│-  │
-│1  │
-│2  │
-│3  │
-│4  │
-│5  │
-│6  │
-│7  │
-│8  │
-│9  │
-│-  │
-│1  │
-│2  │
-│3  │
-│4  │
-│   │
-│   │
-│   │
-└───┘",
+- 
+1-
+21
+32
+43
+54
+65
+76
+87
+98
+-9
+1-
+21
+32
+43
+ 4",
                                                       _output
                                                      );
 
         // Negative offset
-        f.SetNeedsDraw ();
-        Application.LayoutAndDrawToplevels ();
-        r.Draw (new (1, -1));
-
-        TestHelpers.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌1──┐
-│2  │
-│3  │
-│4  │
-│5  │
-│6  │
-│7  │
-│8  │
-│9  │
-│-  │
-│1  │
-│2  │
-│3  │
-│4  │
-│   │
-│   │
-│   │
-│   │
-│   │
-└───┘",
-                                                      _output
-                                                     );
-
-        // Clip
-        f.SetNeedsDraw ();
-
-        Application.LayoutAndDrawToplevels ();
-        r.Draw (new (1, 10));
+        r.Draw (new (2, -1));
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
-┌───┐
-│   │
-│   │
-│   │
-│   │
-│   │
-│   │
-│   │
-│   │
-│   │
-│-  │
-│1  │
-│2  │
-│3  │
-│4  │
-│5  │
-│6  │
-│7  │
-│8  │
-└9──┘",
+- 1
+1-2
+213
+324
+435
+546
+657
+768
+879
+98-
+-91
+1-2
+213
+324
+43 
+ 4 ",
                                                       _output
                                                      );
-        top.Dispose ();
-    }
 
-    [Fact]
-    [AutoInitShutdown]
-    public void Draw_Vertical_Start ()
-    {
-        var len = 15;
-
-        // Add a frame so we can see the ruler
-        var f = new FrameView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () };
-
-        var top = new Toplevel ();
-        top.Add (f);
-        Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, len + 5);
-        Assert.Equal (new (0, 0, 5, len + 5), f.Frame);
-
-        var r = new Ruler ();
-        r.Orientation = Orientation.Vertical;
-        r.Length = len;
-        r.Draw (Point.Empty, 1);
-
-        TestHelpers.AssertDriverContentsWithFrameAre (
-                                                      @"
-1───┐
-2   │
-3   │
-4   │
-5   │
-6   │
-7   │
-8   │
-9   │
--   │
-1   │
-2   │
-3   │
-4   │
-5   │
-│   │
-│   │
-│   │
-│   │
-└───┘",
-                                                      _output
-                                                     );
-        f.SetNeedsDraw ();
-        Application.LayoutAndDrawToplevels (true);
-        r.Length = len;
-        r.Draw (new (0, 1), 1);
-
-        TestHelpers.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌───┐
-1   │
-2   │
-3   │
-4   │
-5   │
-6   │
-7   │
-8   │
-9   │
--   │
-1   │
-2   │
-3   │
-4   │
-5   │
-│   │
-│   │
-│   │
-└───┘",
-                                                      _output
-                                                     );
-        top.Dispose ();
     }
 
     [Fact]

+ 1 - 0
UnitTests/View/Adornment/BorderTests.cs

@@ -38,6 +38,7 @@ public class BorderTests (ITestOutputHelper output)
 
         view.CanFocus = true;
         view.SetFocus ();
+        Application.ClipToScreen ();
         view.Draw ();
         Assert.Equal (view.GetFocusColor (), view.Border.GetFocusColor ());
         Assert.Equal (view.ColorScheme.Focus.Foreground, view.Border.GetFocusColor ().Foreground);

+ 18 - 3
UnitTests/View/Draw/DrawTests.cs

@@ -51,8 +51,9 @@ public class DrawTests (ITestOutputHelper _output)
         // Only valid location w/in Viewport is 0, 0 (view) - 2, 2 (screen)
         Assert.Equal ((Rune)' ', Application.Driver?.Contents! [2, 2].Rune);
 
+        // When we exit Draw, the view is excluded from the clip. So drawing at 0,0, is not valid and is clipped.
         view.AddRune (0, 0, Rune.ReplacementChar);
-        Assert.Equal (Rune.ReplacementChar, Application.Driver?.Contents! [2, 2].Rune);
+        Assert.Equal ((Rune)' ', Application.Driver?.Contents! [2, 2].Rune);
 
         view.AddRune (-1, -1, Rune.ReplacementChar);
         Assert.Equal ((Rune)'M', Application.Driver?.Contents! [1, 1].Rune);
@@ -92,6 +93,7 @@ public class DrawTests (ITestOutputHelper _output)
                                                       _output);
 
         Rectangle toFill = new (x, y, width, height);
+        Application.ClipToScreen ();
         view.FillRect (toFill);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -132,6 +134,8 @@ public class DrawTests (ITestOutputHelper _output)
  └─┘",
                                                       _output);
         toFill = new (-1, -1, width + 1, height + 1);
+
+        Application.ClipToScreen ();
         view.FillRect (toFill);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -152,6 +156,7 @@ public class DrawTests (ITestOutputHelper _output)
  └─┘",
                                                       _output);
         toFill = new (0, 0, width * 2, height * 2);
+        Application.ClipToScreen ();
         view.FillRect (toFill);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -189,8 +194,18 @@ public class DrawTests (ITestOutputHelper _output)
  └─┘",
                                                       _output);
 
+        // On Draw exit the view is excluded from the clip, so this will do nothing.
         view.ClearViewport ();
+        TestHelpers.AssertDriverContentsWithFrameAre (
+                                                      @"
+ ┌─┐
+ │X│
+ └─┘",
+                                                      _output);
+
+        Application.ClipToScreen ();
 
+        view.ClearViewport ();
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
  ┌─┐
@@ -226,7 +241,7 @@ public class DrawTests (ITestOutputHelper _output)
  │X│
  └─┘",
                                                       _output);
-
+        Application.ClipToScreen ();
         view.ClearViewport ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -950,7 +965,7 @@ public class DrawTests (ITestOutputHelper _output)
         view.SetClipToViewport ();
 
         // Assert
-        Assert.Equal (expectedClip, Application.Driver?.Clip?.GetBounds());
+        Assert.Equal (expectedClip, Application.Driver?.Clip?.GetBounds ());
         view.Dispose ();
     }
 

+ 2 - 1
UnitTests/View/TextTests.cs

@@ -67,6 +67,7 @@ Y
         Assert.Equal (new (0, 0, 10, 2), label.Frame);
 
         top.LayoutSubviews ();
+        Application.ClipToScreen ();
         top.Draw ();
 
         expected = @"
@@ -1257,7 +1258,7 @@ w ";
         verticalView.Width = 2;
         verticalView.TextFormatter.ConstrainToSize = new (2, 20);
         Assert.True (verticalView.TextFormatter.NeedsFormat);
-
+        Application.ClipToScreen ();
         top.Draw ();
         Assert.Equal (new (0, 3, 2, 20), verticalView.Frame);
 

+ 21 - 20
UnitTests/View/ViewTests.cs

@@ -14,8 +14,7 @@ public class ViewTests (ITestOutputHelper output)
 
         view.DrawingContent += (s, e) =>
                             {
-                                Region savedClip = Application.Driver!.Clip;
-                                Application.Driver!.Clip = new (new (1, 1, view.Viewport.Width, view.Viewport.Height));
+                                Region savedClip = view.SetClipToViewport ();
 
                                 for (var row = 0; row < view.Viewport.Height; row++)
                                 {
@@ -27,7 +26,7 @@ public class ViewTests (ITestOutputHelper output)
                                     }
                                 }
 
-                                Application.Driver!.Clip = savedClip;
+                                Application.SetClip (savedClip);
                                 e.Cancel = true;
                             };
         var top = new Toplevel ();
@@ -77,23 +76,22 @@ public class ViewTests (ITestOutputHelper output)
         var view = new FrameView { Width = Dim.Fill (), Height = Dim.Fill () };
 
         view.DrawingContent += (s, e) =>
-                            {
-                                Region savedClip = Application.Driver!.Clip;
-                                Application.Driver!.Clip = new (new (1, 1, view.Viewport.Width, view.Viewport.Height));
-
-                                for (var row = 0; row < view.Viewport.Height; row++)
-                                {
-                                    Application.Driver?.Move (1, row + 1);
-
-                                    for (var col = 0; col < view.Viewport.Width; col++)
-                                    {
-                                        Application.Driver?.AddStr ($"{col}");
-                                    }
-                                }
-
-                                Application.Driver!.Clip = savedClip;
-                                e.Cancel = true;
-                            };
+                               {
+                                   Region savedClip = view.SetClipToViewport ();
+
+                                   for (var row = 0; row < view.Viewport.Height; row++)
+                                   {
+                                       Application.Driver?.Move (1, row + 1);
+
+                                       for (var col = 0; col < view.Viewport.Width; col++)
+                                       {
+                                           Application.Driver?.AddStr ($"{col}");
+                                       }
+                                   }
+
+                                   Application.SetClip (savedClip);
+                                   e.Cancel = true;
+                               };
         var top = new Toplevel ();
         top.Add (view);
         Application.Begin (top);
@@ -311,6 +309,7 @@ At 0,0
         Assert.Equal (new (3, 3, 10, 1), view.Frame);
         Assert.Equal (new (0, 0, 10, 1), view.Viewport);
         Assert.Equal (new (0, 0, 10, 1), view._needsDrawRect);
+        Application.ClipToScreen ();
         top.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -405,6 +404,8 @@ At 0,0
         Assert.Equal (new (1, 1, 10, 1), view.Frame);
         Assert.Equal (new (0, 0, 10, 1), view.Viewport);
         Assert.Equal (new (0, 0, 10, 1), view._needsDrawRect);
+        Application.ClipToScreen ();
+
         top.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (

+ 11 - 12
UnitTests/Views/ListViewTests.cs

@@ -54,7 +54,7 @@ public class ListViewTests (ITestOutputHelper output)
         win.Add (lv);
         var top = new Toplevel ();
         top.Add (win);
-        Application.Begin (top);
+        RunState rs = Application.Begin (top);
         ((FakeDriver)Application.Driver!).SetBufferSize (12, 12);
         Application.LayoutAndDrawToplevels ();
 
@@ -78,8 +78,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.ScrollVertical (10));
-        //Application.Refresh ();
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (-1, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -100,7 +99,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveDown ());
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (0, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -121,7 +120,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveEnd ());
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (19, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -142,7 +141,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.ScrollVertical (-20));
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (19, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -163,7 +162,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveDown ());
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (19, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -184,7 +183,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.ScrollVertical (-20));
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (19, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -205,7 +204,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveDown ());
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (19, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -226,7 +225,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveHome ());
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (0, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -247,7 +246,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.ScrollVertical (20));
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (0, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -268,7 +267,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveUp ());
-        lv.Draw ();
+        Application.RunIteration (ref rs);
         Assert.Equal (0, lv.SelectedItem);
 
         TestHelpers.AssertDriverContentsWithFrameAre (