Browse Source

Code cleanup and refactor

Tig 9 tháng trước cách đây
mục cha
commit
304784cbe7

+ 3 - 3
Terminal.Gui/Application/Application.Run.cs

@@ -496,7 +496,7 @@ public static partial class Application // Run (Begin, Run, End, Stop)
     public static void Wakeup () { MainLoop?.Wakeup (); }
 
     /// <summary>
-    /// Causes any Toplevels that need layout to be laid out. Then draws any Toplevels that need dispplay. Only Views that need to be laid out (see <see cref="View.NeedsLayout"/>) will be laid out.
+    /// Causes any Toplevels that need layout to be laid out. Then draws any Toplevels that need display. Only Views that need to be laid out (see <see cref="View.NeedsLayout"/>) will be laid out.
     /// Only Views that need to be drawn (see <see cref="View.NeedsDraw"/>) will be drawn.
     /// </summary>
     /// <param name="forceDraw">If <see langword="true"/> the entire View hierarchy will be redrawn. The default is <see langword="false"/> and should only be overriden for testing.</param>
@@ -509,9 +509,9 @@ public static partial class Application // Run (Begin, Run, End, Stop)
             Driver?.ClearContents ();
         }
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         View.Draw (TopLevels, neededLayout || forceDraw);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
 
         Driver?.Refresh ();
     }

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

@@ -67,44 +67,4 @@ 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
-
 }

+ 3 - 3
Terminal.Gui/View/Adornment/Margin.cs

@@ -60,10 +60,10 @@ public class Margin : Adornment
             if (view.Margin is { CachedClip: { } })
             {
                 view.Margin.NeedsDraw = true;
-                Region? saved = Driver?.Clip;
-                Application.SetClip (view.Margin.CachedClip);
+                Region? saved = GetClip ();
+                View.SetClip (view.Margin.CachedClip);
                 view.Margin.Draw ();
-                Application.SetClip (saved);
+                View.SetClip (saved);
                 view.Margin.CachedClip = null;
             }
 

+ 1 - 1
Terminal.Gui/View/View.Diagnostics.cs

@@ -38,7 +38,7 @@ public partial class View
     ///     <see cref="Adornment.Diagnostics"/> gets set to this property by default, enabling <see cref="ViewDiagnosticFlags.Ruler"/> and <see cref="ViewDiagnosticFlags.Thickness"/>.
     /// </para>
     /// <para>
-    ///     <see cref="ViewDiagnosticFlags.Hover"/> is enabled for all Views independently of Adornments.
+    ///     <see cref="ViewDiagnosticFlags.Hover"/> and <see cref="ViewDiagnosticFlags.DrawIndicator"/> are enabled for all Views independently of Adornments.
     /// </para>
     /// </remarks>
     public static ViewDiagnosticFlags Diagnostics { get; set; }

+ 103 - 38
Terminal.Gui/View/View.Drawing.Clipping.cs

@@ -1,38 +1,123 @@
 #nullable enable
+using static Unix.Terminal.Curses;
+
 namespace Terminal.Gui;
 
 public partial class View
 {
-    internal Region? SetClipToFrame ()
+    /// <summary>
+    ///     Gets the current Clip region.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         There is a single clip region for the entire application.
+    ///     </para>
+    ///     <para>
+    ///         This method returns the current clip region, not a clone. If there is a need to modify the clip region, it is recommended to clone it first.
+    ///     </para>
+    /// </remarks>
+    /// <returns>The current Clip.</returns>
+    public static Region? GetClip ()
+    {
+        return Application.Driver?.Clip;
+    }
+
+    /// <summary>
+    ///     Sets the Clip to the specified region.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         There is a single clip region for the entire application. This method sets the clip region to the specified region.
+    ///     </para>
+    /// </remarks>
+    /// <param name="region"></param>
+    public static void SetClip (Region? region)
+    {
+        if (Driver is { } && region is { })
+        {
+            Driver.Clip = region;
+        }
+    }
+
+    /// <summary>
+    ///     Sets the Clip to be the rectangle of the screen.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         There is a single clip region for the entire application. This method sets the clip region to the screen.
+    ///     </para>
+    ///     <para>
+    ///         This method returns the current clip region, not a clone. If there is a need to modify the clip region, it is recommended to clone it first.
+    ///     </para>
+    /// </remarks>
+    /// <returns>
+    ///     The current Clip, which can be then re-applied <see cref="View.SetClip"/>
+    /// </returns>
+    public static Region? SetClipToScreen ()
+    {
+        Region? previous = GetClip ();
+        if (Driver is { })
+        {
+            Driver.Clip = new (Application.Screen);
+        }
+
+        return previous;
+    }
+
+    /// <summary>
+    ///      Removes the specified rectangle from the Clip.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         There is a single clip region for the entire application.
+    ///     </para>
+    /// </remarks>
+    /// <param name="rectangle"></param>
+    public static void ExcludeFromClip (Rectangle rectangle)
+    {
+        Driver?.Clip?.Exclude (rectangle);
+    }
+
+    /// <summary>
+    ///     Changes the Clip to the intersection of the current Clip and the <see cref="Frame"/> of this View.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         This method returns the current clip region, not a clone. If there is a need to modify the clip region, it is recommended to clone it first.
+    ///     </para>
+    /// </remarks>
+    /// <returns>
+    ///     The current Clip, which can be then re-applied <see cref="View.SetClip"/>
+    /// </returns>
+    internal Region? ClipFrame ()
     {
         if (Driver is null)
         {
             return null;
         }
 
-        Region previous = Driver.Clip ?? new (Application.Screen);
+        Region previous = GetClip () ?? new (Application.Screen);
 
-        Region frameRegion = Driver.Clip!.Clone ();
+        Region frameRegion = previous.Clone ();
         // Translate viewportRegion to screen-relative coords
         Rectangle screenRect = FrameToScreen ();
         frameRegion.Intersect (screenRect);
 
         if (this is Adornment adornment && adornment.Thickness != Thickness.Empty)
         {
-            // Ensure adornments can't draw outside thier thickness
+            // Ensure adornments can't draw outside their thickness
             frameRegion.Exclude (adornment.Thickness.GetInside (Frame));
         }
 
-        Application.SetClip (frameRegion);
+        View.SetClip (frameRegion);
 
         return previous;
-
     }
 
-    /// <summary>Sets the <see cref="ConsoleDriver"/>'s clip region to <see cref="Viewport"/>.</summary>
+    /// <summary>Changes the Clip to the intersection of the current Clip and the <see cref="Viewport"/> of this View.</summary>
     /// <remarks>
     ///     <para>
-    ///         By default, the clip rectangle is set to the intersection of the current clip region and the
+    ///         By default, sets the Clip to the intersection of the current clip region and the
     ///         <see cref="Viewport"/>. This ensures that drawing is constrained to the viewport, but allows
     ///         content to be drawn beyond the viewport.
     ///     </para>
@@ -40,21 +125,25 @@ public partial class View
     ///         If <see cref="ViewportSettings"/> has <see cref="Gui.ViewportSettings.ClipContentOnly"/> set, clipping will be
     ///         applied to just the visible content area.
     ///     </para>
+    /// <remarks>
+    ///     <para>
+    ///         This method returns the current clip region, not a clone. If there is a need to modify the clip region, it is recommended to clone it first.
+    ///     </para>
+    /// </remarks>
     /// </remarks>
     /// <returns>
-    ///     The current screen-relative clip region, which can be then re-applied by setting
-    ///     <see cref="ConsoleDriver.Clip"/>.
+    ///     The current Clip, which can be then re-applied <see cref="View.SetClip"/>
     /// </returns>
-    public Region? SetClipToViewport ()
+    public Region? ClipViewport ()
     {
         if (Driver is null)
         {
             return null;
         }
 
-        Region previous = Driver.Clip ?? new (Application.Screen);
+        Region previous = GetClip () ?? new (Application.Screen);
 
-        Region viewportRegion = Driver.Clip!.Clone ();
+        Region viewportRegion = previous.Clone ();
 
         Rectangle viewport = ViewportToScreen (new Rectangle (Point.Empty, Viewport.Size));
         viewportRegion?.Intersect (viewport);
@@ -72,32 +161,8 @@ public partial class View
             viewportRegion?.Exclude (adornment.Thickness.GetInside (viewport));
         }
 
-        Application.SetClip (viewportRegion);
+        View.SetClip (viewportRegion);
 
         return previous;
     }
-
-    /// <summary>Gets the view-relative clip region.</summary>
-    public Region? GetClip ()
-    {
-        // get just the portion of the application clip that is within this view's Viewport
-        if (Driver is null)
-        {
-            return null;
-        }
-
-        // Get our Viewport in screen coordinates
-        Rectangle screen = ViewportToScreen (Viewport with { Location = Point.Empty });
-
-        // Get the clip region in screen coordinates
-        Region? clip = Driver.Clip;
-        if (clip is null)
-        {
-            return null;
-        }
-        Region? previous = Driver.Clip;
-        clip = clip.Clone ();
-        clip.Intersect (screen);
-        return clip;
-    }
 }

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

@@ -116,12 +116,12 @@ public partial class View
             return;
         }
 
-        Region prevClip = SetClipToViewport ();
+        Region prevClip = ClipViewport ();
         Rectangle toClear = ViewportToScreen (rect);
         Attribute prev = SetAttribute (new (color ?? GetNormalColor ().Background));
         Driver.FillRect (toClear);
         SetAttribute (prev);
-        Application.SetClip (prevClip);
+        View.SetClip (prevClip);
     }
 
     #endregion Drawing Primitives

+ 37 - 59
Terminal.Gui/View/View.Drawing.cs

@@ -46,19 +46,19 @@ public partial class View // Drawing APIs
             return;
         }
 
-        Region? saved = Driver?.Clip;
+        Region? saved = GetClip ();
         if (NeedsDraw || SubViewNeedsDraw)
         {
-            saved = SetClipToFrame ();
-            DoDrawAdornments ();
-            Application.SetClip (saved);
+            saved = ClipFrame ();
+            DoDrawBorderAndPadding ();
+            View.SetClip (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 = ClipViewport ();
 
             // TODO: Simplify/optimize SetAttribute system.
             DoSetAttribute ();
@@ -79,15 +79,13 @@ public partial class View // Drawing APIs
 
             // Restore the clip before rendering the line canvas and adornment subviews
             // because they may draw outside the viewport.
-            Application.SetClip (saved);
+            SetClip (saved);
 
-            saved = SetClipToFrame ();
+            saved = ClipFrame ();
 
-            //DoSetAttribute ();
             DoRenderLineCanvas ();
 
-            //DoSetAttribute ();
-            DoDrawAdornmentSubViews ();
+            DoDrawBorderAndPaddingSubViews ();
 
             if (Border is { Diagnostics: ViewDiagnosticFlags.DrawIndicator, DrawIndicator: { } })
             {
@@ -99,19 +97,21 @@ public partial class View // Drawing APIs
         }
 
         // This causes the Margin to be drawn in a second pass
-        // TODO: Figure out how to make this more efficient
+        // PERFORMANCE: If there is a Margin, it will be redrawn each iteration of the main loop.
         if (Margin is { } && Margin?.Thickness != Thickness.Empty)
         {
-            Margin!.CachedClip = Application.Driver?.Clip?.Clone ();
+            // PERFORMANCE: How expensive are these clones?
+            Margin!.CachedClip = GetClip ()!.Clone ();
         }
 
         // We're done drawing
         DoDrawComplete ();
-        // QUESTION: SHould this go before DoDrawComplete?
-        Application.SetClip (saved);
 
-        // Exclude this view from the clip
-        if (this is not Adornment && Driver?.Clip is { })
+        // QUESTION: Should this go before DoDrawComplete? What is more correct?
+        View.SetClip (saved);
+
+        // Exclude this view (not including Margin) from the Clip
+        if (this is not Adornment && GetClip () is { })
         {
             Rectangle borderFrame = FrameToScreen ();
 
@@ -120,21 +120,14 @@ public partial class View // Drawing APIs
                 borderFrame = Border.FrameToScreen ();
             }
 
-            Application.ExcludeFromClip (borderFrame);
+            ExcludeFromClip (borderFrame);
         }
     }
 
     #region DrawAdornments
 
-    private void DoDrawAdornmentSubViews ()
+    private void DoDrawBorderAndPaddingSubViews ()
     {
-        //if (Margin?.Subviews is { } && Margin.Thickness != Thickness.Empty)
-        //{
-        //    //Region? saved = Margin?.SetClipToFrame ();
-        //    //Margin?.DoDrawSubviews ();
-        //    //Application.SetClip (saved);
-        //}
-
         if (Border?.Subviews is { } && Border.Thickness != Thickness.Empty)
         {
             foreach (View subview in Border.Subviews)
@@ -142,9 +135,9 @@ public partial class View // Drawing APIs
                 subview.SetNeedsDraw ();
             }
 
-            Region? saved = Border?.SetClipToFrame ();
+            Region? saved = Border?.ClipFrame ();
             Border?.DoDrawSubviews ();
-            Application.SetClip (saved);
+            SetClip (saved);
         }
 
         if (Padding?.Subviews is { } && Padding.Thickness != Thickness.Empty)
@@ -154,36 +147,38 @@ public partial class View // Drawing APIs
                 subview.SetNeedsDraw ();
             }
 
-            Region? saved = Padding?.SetClipToFrame ();
+            Region? saved = Padding?.ClipFrame ();
             Padding?.DoDrawSubviews ();
-            Application.SetClip (saved);
+            SetClip (saved);
         }
     }
 
-    private void DoDrawAdornments ()
+    private void DoDrawBorderAndPadding ()
     {
-        if (OnDrawingAdornments ())
+        if (OnDrawingBorderAndPadding ())
         {
             return;
         }
 
         // TODO: add event.
 
-        DrawAdornments ();
+        DrawBorderAndPadding ();
     }
 
     /// <summary>
-    ///     Causes each of the View's Adornments to be drawn. This includes the <see cref="Margin"/>, <see cref="Border"/>, and <see cref="Padding"/>.
+    ///     Causes <see cref="Border"/> and <see cref="Padding"/> to be drawn.
     /// </summary>
-    public void DrawAdornments ()
+    /// <remarks>
+    ///     <para>
+    ///         <see cref="Margin"/> is drawn in a separate pass.
+    ///     </para>
+    /// </remarks>
+    public void DrawBorderAndPadding ()
     {
+        // We do not attempt to draw Margin. It is drawn in a separate pass.
+
         // Each of these renders lines to either this View's LineCanvas 
         // Those lines will be finally rendered in OnRenderLineCanvas
-        if (Margin is { } && Margin.Thickness != Thickness.Empty)
-        {
-            //Margin?.Draw ();
-        }
-
         if (Border is { } && Border.Thickness != Thickness.Empty)
         {
             Border?.Draw ();
@@ -202,7 +197,7 @@ public partial class View // Drawing APIs
     ///     false (the default), this method will cause the <see cref="LineCanvas"/> be prepared to be rendered.
     /// </summary>
     /// <returns><see langword="true"/> to stop further drawing of the Adornments.</returns>
-    protected virtual bool OnDrawingAdornments () { return false; }
+    protected virtual bool OnDrawingBorderAndPadding () { return false; }
 
     #endregion DrawAdornments
 
@@ -379,7 +374,6 @@ public partial class View // Drawing APIs
             TextFormatter.NeedsFormat = true;
         }
 
-        // This should NOT clear 
         // TODO: If the output is not in the Viewport, do nothing
         var drawRect = new Rectangle (ContentToScreen (Point.Empty), GetContentSize ());
 
@@ -484,22 +478,8 @@ public partial class View // Drawing APIs
             return;
         }
 
-#if HACK_DRAW_OVERLAPPED
-        IEnumerable<View> subviewsNeedingDraw = _subviews.Where (view => (view.Visible && (view.NeedsDraw || view.SubViewNeedsDraw))
-                                                                      || view.Arrangement.HasFlag (ViewArrangement.Overlapped));
-#else
-        IEnumerable<View> subviewsNeedingDraw = _subviews.Where (view => (view.Visible));
-#endif
-
-        foreach (View view in subviewsNeedingDraw.Reverse ())
+        foreach (View view in _subviews.Where (view => view.Visible).Reverse ())
         {
-#if HACK_DRAW_OVERLAPPED
-            if (view.Arrangement.HasFlag (ViewArrangement.Overlapped))
-            {
-
-                view.SetNeedsDraw ();
-            }
-#endif
             view.Draw ();
         }
     }
@@ -533,7 +513,7 @@ public partial class View // Drawing APIs
     /// <summary>
     ///     Gets or sets whether this View will use it's SuperView's <see cref="LineCanvas"/> for rendering any
     ///     lines. If <see langword="true"/> the rendering of any borders drawn by this Frame will be done by its parent's
-    ///     SuperView. If <see langword="false"/> (the default) this View's <see cref="OnDrawingAdornments"/> method will be
+    ///     SuperView. If <see langword="false"/> (the default) this View's <see cref="OnDrawingBorderAndPadding"/> method will be
     ///     called to render the borders.
     /// </summary>
     public virtual bool SuperViewRendersLineCanvas { get; set; } = false;
@@ -608,7 +588,6 @@ public partial class View // Drawing APIs
         DrawComplete?.Invoke (this, new (Viewport, Viewport));
 
         // Default implementation does nothing.
-
     }
 
     /// <summary>
@@ -764,7 +743,6 @@ public partial class View // Drawing APIs
         _needsDrawRect = Rectangle.Empty;
         SubViewNeedsDraw = false;
 
-
         if (Margin is { } && Margin.Thickness != Thickness.Empty)
         {
             Margin?.ClearNeedsDraw ();

+ 1 - 1
Terminal.Gui/Views/GraphView/Annotations.cs

@@ -150,7 +150,7 @@ public class LegendAnnotation : View, IAnnotation
 
         if (BorderStyle != LineStyle.None)
         {
-            DrawAdornments ();
+            DrawBorderAndPadding ();
             RenderLineCanvas ();
         }
 

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

@@ -406,11 +406,11 @@ internal sealed class Menu : View
             return;
         }
 
-        DrawAdornments ();
+        DrawBorderAndPadding ();
         RenderLineCanvas ();
 
         // 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 ();
+        Region? savedClip = View.SetClipToScreen ();
 
         SetAttribute (GetNormalColor ());
 
@@ -579,7 +579,7 @@ internal sealed class Menu : View
             }
         }
 
-        Application.SetClip (savedClip);
+        View.SetClip (savedClip);
     }
 
     public override Point? PositionCursor ()

+ 8 - 8
Terminal.Gui/Views/ScrollView.cs

@@ -381,9 +381,9 @@ public class ScrollView : View
 
         if (!string.IsNullOrEmpty (_contentView.Text) || _contentView.Subviews.Count > 0)
         {
-            Region? saved = SetClipToFrame();
+            Region? saved = ClipFrame();
             _contentView.Draw ();
-            Application.SetClip (saved);
+            View.SetClip (saved);
         }
 
         DrawScrollBars ();
@@ -584,24 +584,24 @@ public class ScrollView : View
         {
             if (ShowVerticalScrollIndicator)
             {
-                Region? saved = Application.ClipToScreen ();
+                Region? saved = View.SetClipToScreen ();
                 _vertical.Draw ();
-                Application.SetClip (saved);
+                View.SetClip (saved);
             }
 
             if (ShowHorizontalScrollIndicator)
             {
-                Region? saved = Application.ClipToScreen ();
+                Region? saved = View.SetClipToScreen ();
                 _horizontal.Draw ();
-                Application.SetClip (saved);
+                View.SetClip (saved);
             }
 
             if (ShowVerticalScrollIndicator && ShowHorizontalScrollIndicator)
             {
                 SetContentBottomRightCornerVisibility ();
-                Region? saved = Application.ClipToScreen ();
+                Region? saved = View.SetClipToScreen ();
                 _contentBottomRightCorner.Draw ();
-                Application.SetClip (saved);
+                View.SetClip (saved);
             }
         }
     }

+ 2 - 2
Terminal.Gui/Views/TabView.cs

@@ -1296,7 +1296,7 @@ public class TabView : View
                 // BUGBUG: Layout should only be called from Mainloop iteration!
                 Layout ();
 
-                tab.DrawAdornments ();
+                tab.DrawBorderAndPadding ();
 
                 Attribute prevAttr = Driver?.GetAttribute () ?? Attribute.Default;
 
@@ -1321,7 +1321,7 @@ public class TabView : View
                                         ColorScheme.HotNormal
                                        );
 
-                tab.DrawAdornments ();
+                tab.DrawBorderAndPadding ();
 
 
                 SetAttribute (GetNormalColor ());

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

@@ -176,7 +176,7 @@ public class TileView : View
     /// <summary>Overridden so no Frames get drawn</summary>
     /// <param name="clipRegion"></param>
     /// <returns></returns>
-    protected override bool OnDrawingAdornments () { return true; }
+    protected override bool OnDrawingBorderAndPadding () { return true; }
 
     /// <param name="clipRegion"></param>
     /// <inheritdoc/>

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

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

+ 13 - 13
UnitTests/View/Draw/DrawTests.cs

@@ -93,7 +93,7 @@ public class DrawTests (ITestOutputHelper _output)
                                                       _output);
 
         Rectangle toFill = new (x, y, width, height);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         view.FillRect (toFill);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -135,7 +135,7 @@ public class DrawTests (ITestOutputHelper _output)
                                                       _output);
         toFill = new (-1, -1, width + 1, height + 1);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         view.FillRect (toFill);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -156,7 +156,7 @@ public class DrawTests (ITestOutputHelper _output)
  └─┘",
                                                       _output);
         toFill = new (0, 0, width * 2, height * 2);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         view.FillRect (toFill);
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -203,7 +203,7 @@ public class DrawTests (ITestOutputHelper _output)
  └─┘",
                                                       _output);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
 
         view.ClearViewport ();
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -241,7 +241,7 @@ public class DrawTests (ITestOutputHelper _output)
  │X│
  └─┘",
                                                       _output);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         view.ClearViewport ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -319,7 +319,7 @@ public class DrawTests (ITestOutputHelper _output)
         frameView.Border.Thickness = new (1, 0, 0, 0);
 
         top.Add (frameView);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Layout ();
         top.Draw ();
 
@@ -342,7 +342,7 @@ public class DrawTests (ITestOutputHelper _output)
 
         top.Add (view);
         top.Layout ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         //                            012345678901234567890123456789012345678
         //                            012 34 56 78 90 12 34 56 78 90 12 34 56 78
@@ -967,13 +967,13 @@ public class DrawTests (ITestOutputHelper _output)
         view.Border.Thickness = new (1);
         view.BeginInit ();
         view.EndInit ();
-        Assert.Equal (view.Frame, Application.Driver?.Clip?.GetBounds ());
+        Assert.Equal (view.Frame, View.GetClip ()!.GetBounds ());
 
         // Act
-        view.SetClipToViewport ();
+        view.ClipViewport ();
 
         // Assert
-        Assert.Equal (expectedClip, Application.Driver?.Clip?.GetBounds ());
+        Assert.Equal (expectedClip, View.GetClip ()!.GetBounds ());
         view.Dispose ();
     }
 
@@ -1000,14 +1000,14 @@ public class DrawTests (ITestOutputHelper _output)
         view.Border.Thickness = new (1);
         view.BeginInit ();
         view.EndInit ();
-        Assert.Equal (view.Frame, Application.Driver?.Clip.GetBounds ());
+        Assert.Equal (view.Frame, View.GetClip ()!.GetBounds ());
         view.Viewport = view.Viewport with { X = 1, Y = 1 };
 
         // Act
-        view.SetClipToViewport ();
+        view.ClipViewport ();
 
         // Assert
-        Assert.Equal (expectedClip, Application.Driver?.Clip.GetBounds ());
+        Assert.Equal (expectedClip, View.GetClip ()!.GetBounds ());
         view.Dispose ();
     }
 

+ 2 - 2
UnitTests/View/TextTests.cs

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

+ 6 - 6
UnitTests/View/ViewTests.cs

@@ -14,7 +14,7 @@ public class ViewTests (ITestOutputHelper output)
 
         view.DrawingContent += (s, e) =>
                             {
-                                Region savedClip = view.SetClipToViewport ();
+                                Region savedClip = view.ClipViewport ();
 
                                 for (var row = 0; row < view.Viewport.Height; row++)
                                 {
@@ -26,7 +26,7 @@ public class ViewTests (ITestOutputHelper output)
                                     }
                                 }
 
-                                Application.SetClip (savedClip);
+                                View.SetClip (savedClip);
                                 e.Cancel = true;
                             };
         var top = new Toplevel ();
@@ -77,7 +77,7 @@ public class ViewTests (ITestOutputHelper output)
 
         view.DrawingContent += (s, e) =>
                                {
-                                   Region savedClip = view.SetClipToViewport ();
+                                   Region savedClip = view.ClipViewport ();
 
                                    for (var row = 0; row < view.Viewport.Height; row++)
                                    {
@@ -89,7 +89,7 @@ public class ViewTests (ITestOutputHelper output)
                                        }
                                    }
 
-                                   Application.SetClip (savedClip);
+                                   View.SetClip (savedClip);
                                    e.Cancel = true;
                                };
         var top = new Toplevel ();
@@ -309,7 +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 ();
+        View.SetClipToScreen ();
         top.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -404,7 +404,7 @@ 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 ();
+        View.SetClipToScreen ();
 
         top.Draw ();
 

+ 19 - 19
UnitTests/Views/AppendAutocompleteTests.cs

@@ -9,7 +9,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
     public void TestAutoAppend_AfterCloseKey_NoAutocomplete ()
     {
         TextField tf = GetTextFieldsInViewSuggesting ("fish");
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         // f is typed and suggestion is "fish"
         Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
         tf.Draw ();
@@ -21,7 +21,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
         Application.Driver?.SendKeys ('e', ConsoleKey.Escape, false, false, false);
 
         // Suggestion should disappear
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("f", output);
         Assert.Equal ("f", tf.Text);
@@ -43,7 +43,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
 
         // f is typed and suggestion is "fish"
         Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("fish", output);
@@ -53,7 +53,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
         Application.Driver?.SendKeys ('\0', ConsoleKey.Escape, false, false, false);
 
         // Suggestion should disappear
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("f", output);
         Assert.Equal ("f", tf.Text);
@@ -61,7 +61,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
         // Should reappear when you press next letter
         Application.Driver?.SendKeys ('i', ConsoleKey.I, false, false, false);
         tf.PositionCursor ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("fish", output);
         Assert.Equal ("fi", tf.Text);
@@ -78,7 +78,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
 
         // f is typed and suggestion is "fish"
         Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("fish", output);
@@ -87,7 +87,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
         // When cycling autocomplete
         Application.Driver?.SendKeys (' ', cycleKey, false, false, false);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("friend", output);
@@ -95,7 +95,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
 
         // Should be able to cycle in circles endlessly
         Application.Driver?.SendKeys (' ', cycleKey, false, false, false);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("fish", output);
@@ -111,7 +111,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
 
         // f is typed and suggestion is "fish"
         Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("fish", output);
@@ -121,7 +121,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
         Application.Driver?.SendKeys (' ', ConsoleKey.Spacebar, false, false, false);
         Application.Driver?.SendKeys ('<', ConsoleKey.LeftArrow, false, false, false);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("f", output);
         Assert.Equal ("f ", tf.Text);
@@ -136,7 +136,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
 
         // f is typed and suggestion is "fish"
         Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("fish", output);
@@ -144,7 +144,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
 
         // x is typed and suggestion should disappear
         Application.Driver?.SendKeys ('x', ConsoleKey.X, false, false, false);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("fx", output);
         Assert.Equal ("fx", tf.Text);
@@ -161,7 +161,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
         var generator = (SingleWordSuggestionGenerator)tf.Autocomplete.SuggestionGenerator;
         generator.AllSuggestions = new List<string> { "FISH" };
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("", output);
@@ -172,7 +172,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
         Assert.Equal ("my f", tf.Text);
 
         // Even though there is no match on case we should still get the suggestion
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("my fISH", output);
@@ -180,7 +180,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
 
         // When tab completing the case of the whole suggestion should be applied
         Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("my FISH", output);
         Assert.Equal ("my FISH", tf.Text);
@@ -197,14 +197,14 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
         var generator = (SingleWordSuggestionGenerator)tf.Autocomplete.SuggestionGenerator;
         generator.AllSuggestions = new List<string> { "fish" };
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("", output);
 
         tf.NewKeyDownEvent (new Key ('f'));
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre ("fish", output);
@@ -212,7 +212,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
 
         Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("fish", output);
         Assert.Equal ("fish", tf.Text);
@@ -237,7 +237,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
 
         // f is typed we should only see 'f' up to size of View (10)
         Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         tf.PositionCursor ();
         TestHelpers.AssertDriverContentsAre (expectRender, output);

+ 7 - 7
UnitTests/Views/ComboBoxTests.cs

@@ -566,7 +566,7 @@ Three ",
         Assert.True (cb.IsShow);
         Assert.Equal (-1, cb.SelectedItem);
         Assert.Equal ("", cb.Text);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         cb.Draw ();
 
         TestHelpers.AssertDriverAttributesAre (
@@ -585,7 +585,7 @@ Three ",
         Assert.True (cb.IsShow);
         Assert.Equal (-1, cb.SelectedItem);
         Assert.Equal ("", cb.Text);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         cb.Draw ();
 
         TestHelpers.AssertDriverAttributesAre (
@@ -610,7 +610,7 @@ Three ",
         Assert.True (cb.IsShow);
         Assert.Equal (2, cb.SelectedItem);
         Assert.Equal ("Three", cb.Text);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         cb.Draw ();
 
         TestHelpers.AssertDriverAttributesAre (
@@ -629,7 +629,7 @@ Three ",
         Assert.True (cb.IsShow);
         Assert.Equal (2, cb.SelectedItem);
         Assert.Equal ("Three", cb.Text);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         cb.Draw ();
 
         TestHelpers.AssertDriverAttributesAre (
@@ -648,7 +648,7 @@ Three ",
         Assert.True (cb.IsShow);
         Assert.Equal (2, cb.SelectedItem);
         Assert.Equal ("Three", cb.Text);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         cb.Draw ();
 
         TestHelpers.AssertDriverAttributesAre (
@@ -928,7 +928,7 @@ One
         Assert.Equal (1, cb.SelectedItem);
         Assert.Equal ("Two", cb.Text);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         cb.Draw ();
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -943,7 +943,7 @@ Two
         Assert.Equal (2, cb.SelectedItem);
         Assert.Equal ("Three", cb.Text);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         cb.Draw ();
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"

+ 3 - 3
UnitTests/Views/ContextMenuTests.cs

@@ -132,7 +132,7 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
 
-        Assert.Equal (new Rectangle (0, 0, 20, 15), Application.Driver?.Clip.GetBounds ());
+        Assert.Equal (new Rectangle (0, 0, 20, 15), View.GetClip ()!.GetBounds ());
         TestHelpers.AssertDriverContentsWithFrameAre ("", output);
 
         var top = new Toplevel { X = 2, Y = 2, Width = 15, Height = 4 };
@@ -267,7 +267,7 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
 
-        Assert.Equal (new Rectangle (0, 0, 20, 15), Application.Driver?.Clip.GetBounds ());
+        Assert.Equal (new Rectangle (0, 0, 20, 15), View.GetClip ()!.GetBounds ());
         TestHelpers.AssertDriverContentsWithFrameAre ("", output);
 
         // Don't use Dialog here as it has more layout logic. Use Window instead.
@@ -1042,7 +1042,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         cm.Host.Height = 3;
 
         cm.Show (menuItems);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         Application.Top.Draw ();
         Assert.Equal (new Point (5, 12), cm.Position);
 

+ 6 - 6
UnitTests/Views/GraphViewTests.cs

@@ -685,7 +685,7 @@ public class MultiBarSeriesTests
         fakeXAxis.LabelPoints.Clear ();
         gv.LayoutSubviews ();
         gv.SetNeedsDraw ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         gv.Draw ();
 
         Assert.Equal (3, fakeXAxis.LabelPoints.Count);
@@ -1154,7 +1154,7 @@ public class TextAnnotationTests
         // user scrolls up one unit of graph space
         gv.ScrollOffset = new PointF (0, 1f);
         gv.SetNeedsDraw ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         gv.Draw ();
 
         // we expect the text annotation to go down one line since
@@ -1248,7 +1248,7 @@ public class TextAnnotationTests
                             new TextAnnotation { Text = "hey!", ScreenPosition = new Point (3, 1) }
                            );
         gv.LayoutSubviews ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         gv.Draw ();
 
         var expected =
@@ -1264,7 +1264,7 @@ public class TextAnnotationTests
         // user scrolls up one unit of graph space
         gv.ScrollOffset = new PointF (0, 1f);
         gv.SetNeedsDraw ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         gv.Draw ();
 
         // we expect no change in the location of the annotation (only the axis label changes)
@@ -1283,7 +1283,7 @@ public class TextAnnotationTests
         // user scrolls up one unit of graph space
         gv.ScrollOffset = new PointF (0, 1f);
         gv.SetNeedsDraw ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         gv.Draw ();
 
         // we expect no change in the location of the annotation (only the axis label changes)
@@ -1553,7 +1553,7 @@ public class PathAnnotationTests
             // change the text and redraw
             view.Text = "ff1234";
             mount.SetNeedsDraw ();
-            Application.ClipToScreen ();
+            View.SetClipToScreen ();
             mount.Draw ();
 
             // should have the new text rendered

+ 24 - 24
UnitTests/Views/MenuBarTests.cs

@@ -698,7 +698,7 @@ public class MenuBarTests (ITestOutputHelper output)
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
 
-        Assert.Equal (new (0, 0, 40, 15), Application.Driver?.Clip.GetBounds());
+        Assert.Equal (new (0, 0, 40, 15), View.GetClip ()!.GetBounds());
         TestHelpers.AssertDriverContentsWithFrameAre (@"", output);
 
         List<string> items = new ()
@@ -1595,7 +1595,7 @@ wo
 
         Assert.True (menu.NewMouseEvent (new () { Position = new (1, 0), Flags = MouseFlags.Button1Pressed, View = menu }));
         Assert.False (menu.IsMenuOpen);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output);
         top.Dispose ();
@@ -1693,7 +1693,7 @@ wo
                                                      );
 
         Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight));
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1805,7 +1805,7 @@ wo
                                                                                   );
 
                                      Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight));
-                                     Application.ClipToScreen ();
+                                     View.SetClipToScreen ();
                                      top.Draw ();
 
                                      TestHelpers.AssertDriverContentsWithFrameAre (
@@ -2013,7 +2013,7 @@ wo
                                      Assert.True (
                                                   ((MenuBar)top.Subviews [0])._openMenu.NewKeyDownEvent (Key.CursorRight)
                                                  );
-                                     Application.ClipToScreen ();
+                                     View.SetClipToScreen ();
                                      top.Draw ();
 
                                      TestHelpers.AssertDriverContentsWithFrameAre (
@@ -2088,14 +2088,14 @@ wo
         // Open second
         Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.CursorRight));
         Assert.True (menu.IsMenuOpen);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), output);
 
         // Close menu
         Assert.True (menu.NewKeyDownEvent (menu.Key));
         Assert.False (menu.IsMenuOpen);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output);
 
@@ -2129,21 +2129,21 @@ wo
         // Open first
         Assert.True (menu.NewKeyDownEvent (menu.Key));
         Assert.True (menu.IsMenuOpen);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), output);
 
         // Open second
         Assert.True (top.Subviews [1].NewKeyDownEvent (Key.CursorRight));
         Assert.True (menu.IsMenuOpen);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         Application.Top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), output);
 
         // Close menu
         Assert.True (menu.NewKeyDownEvent (menu.Key));
         Assert.False (menu.IsMenuOpen);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output);
         top.Dispose ();
@@ -2212,7 +2212,7 @@ wo
         top.Add (menu);
         Application.Begin (top);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output);
 
@@ -2220,7 +2220,7 @@ wo
         {
             menu.OpenMenu (i);
             Assert.True (menu.IsMenuOpen);
-            Application.ClipToScreen ();
+            View.SetClipToScreen ();
             top.Draw ();
             TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (i), output);
         }
@@ -2479,7 +2479,7 @@ Edit
         Assert.True (menu.NewKeyDownEvent (menu.Key));
         Assert.True (menu.IsMenuOpen);
         Assert.False (isMenuClosed);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
 
         expected = @"
@@ -2494,7 +2494,7 @@ Edit
         Assert.True (menu.NewKeyDownEvent (menu.Key));
         Assert.False (menu.IsMenuOpen);
         Assert.True (isMenuClosed);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
 
         expected = @"
@@ -2658,7 +2658,7 @@ Edit
         Assert.Equal (1, menu._selected);
         Assert.Equal (-1, menu._selectedSub);
         Assert.Null (menu._openSubMenu);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), output);
 
@@ -2666,7 +2666,7 @@ Edit
         Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight));
         Assert.True (menu.IsMenuOpen);
         Assert.False (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (2), output);
 
@@ -2674,21 +2674,21 @@ Edit
         Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorLeft));
         Assert.True (menu.IsMenuOpen);
         Assert.False (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), output);
 
         Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorLeft));
         Assert.True (menu.IsMenuOpen);
         Assert.False (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), output);
 
         Assert.True (Application.RaiseKeyDownEvent (menu.Key));
         Assert.False (menu.IsMenuOpen);
         Assert.True (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output);
         top.Dispose ();
@@ -2759,7 +2759,7 @@ Edit
                     );
         Assert.True (menu.IsMenuOpen);
         Assert.False (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), output);
 
@@ -2770,7 +2770,7 @@ Edit
                     );
         Assert.True (menu.IsMenuOpen);
         Assert.False (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (2), output);
 
@@ -2781,7 +2781,7 @@ Edit
                     );
         Assert.True (menu.IsMenuOpen);
         Assert.False (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output);
 
@@ -2792,14 +2792,14 @@ Edit
                     );
         Assert.True (menu.IsMenuOpen);
         Assert.False (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), output);
 
         Assert.True (menu.NewMouseEvent (new () { Position = new (8, 0), Flags = MouseFlags.Button1Pressed, View = menu }));
         Assert.False (menu.IsMenuOpen);
         Assert.True (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         top.Draw ();
         TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output);
         top.Dispose ();

+ 3 - 3
UnitTests/Views/ProgressBarTests.cs

@@ -36,7 +36,7 @@ public class ProgressBarTests
         for (var i = 0; i <= pb.Frame.Width; i++)
         {
             pb.Fraction += 0.2F;
-            Application.ClipToScreen ();
+            View.SetClipToScreen ();
             pb.Draw ();
 
             if (i == 0)
@@ -178,7 +178,7 @@ public class ProgressBarTests
         for (var i = 0; i < 38; i++)
         {
             pb.Pulse ();
-            Application.ClipToScreen ();
+            View.SetClipToScreen ();
             pb.Draw ();
 
             if (i == 0)
@@ -883,7 +883,7 @@ public class ProgressBarTests
         for (var i = 0; i < 38; i++)
         {
             pb.Pulse ();
-            Application.ClipToScreen ();
+            View.SetClipToScreen ();
             pb.Draw ();
 
             if (i == 0)

+ 1 - 1
UnitTests/Views/ScrollViewTests.cs

@@ -413,7 +413,7 @@ public class ScrollViewTests (ITestOutputHelper output)
 
         top.LayoutSubviews ();
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         top.Draw ();
 
         View contentBottomRightCorner = sv.Subviews.First (v => v is ScrollBarView.ContentBottomRightCorner);

+ 1 - 1
UnitTests/Views/SpinnerViewTests.cs

@@ -59,7 +59,7 @@ public class SpinnerViewTests
         TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
 
         view.AdvanceAnimation ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         view.Draw ();
 
         expected = "/";

+ 25 - 25
UnitTests/Views/TabViewTests.cs

@@ -610,7 +610,7 @@ public class TabViewTests (ITestOutputHelper output)
         tv.ApplyStyleChanges ();
         tv.Layout ();
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -679,7 +679,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         tv.SelectedTab = tab2;
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -698,7 +698,7 @@ public class TabViewTests (ITestOutputHelper output)
         tab1.DisplayText = "12345678910";
         tab2.DisplayText = "13";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -713,7 +713,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         //switch to tab2
         tv.SelectedTab = tab2;
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -730,7 +730,7 @@ public class TabViewTests (ITestOutputHelper output)
         tab1.DisplayText = "12345678910";
         tab2.DisplayText = "abcdefghijklmnopq";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -755,7 +755,7 @@ public class TabViewTests (ITestOutputHelper output)
         tv.ApplyStyleChanges ();
         tv.LayoutSubviews ();
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -809,7 +809,7 @@ public class TabViewTests (ITestOutputHelper output)
         // Test two tab names that fit 
         tab1.DisplayText = "12";
         tab2.DisplayText = "13";
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
 
         tv.Draw ();
 
@@ -825,7 +825,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         tv.SelectedTab = tab2;
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -844,7 +844,7 @@ public class TabViewTests (ITestOutputHelper output)
         tab1.DisplayText = "12345678910";
         tab2.DisplayText = "13";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -859,7 +859,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         //switch to tab2
         tv.SelectedTab = tab2;
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -876,7 +876,7 @@ public class TabViewTests (ITestOutputHelper output)
         tab1.DisplayText = "12345678910";
         tab2.DisplayText = "abcdefghijklmnopq";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -899,7 +899,7 @@ public class TabViewTests (ITestOutputHelper output)
         tv.Height = 5;
         tv.Layout ();
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -922,7 +922,7 @@ public class TabViewTests (ITestOutputHelper output)
         tv.Height = 5;
         tv.Layout ();
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -951,7 +951,7 @@ public class TabViewTests (ITestOutputHelper output)
         tab1.DisplayText = "12";
         tab2.DisplayText = "13";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -966,7 +966,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         tv.SelectedTab = tab2;
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -985,7 +985,7 @@ public class TabViewTests (ITestOutputHelper output)
         tab1.DisplayText = "12345678910";
         tab2.DisplayText = "13";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1000,7 +1000,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         //switch to tab2
         tv.SelectedTab = tab2;
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1017,7 +1017,7 @@ public class TabViewTests (ITestOutputHelper output)
         tab1.DisplayText = "12345678910";
         tab2.DisplayText = "abcdefghijklmnopq";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1045,7 +1045,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         tab2.DisplayText = "Les Mise" + char.ConvertFromUtf32 (int.Parse ("0301", NumberStyles.HexNumber)) + "rables";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1060,7 +1060,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         tv.SelectedTab = tab2;
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1138,7 +1138,7 @@ public class TabViewTests (ITestOutputHelper output)
         // Test two tab names that fit 
         tab1.DisplayText = "12";
         tab2.DisplayText = "13";
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
 
         tv.Draw ();
 
@@ -1156,7 +1156,7 @@ public class TabViewTests (ITestOutputHelper output)
         tab1.DisplayText = "12345678910";
         tab2.DisplayText = "13";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1171,7 +1171,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         //switch to tab2
         tv.SelectedTab = tab2;
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1188,7 +1188,7 @@ public class TabViewTests (ITestOutputHelper output)
         tab1.DisplayText = "12345678910";
         tab2.DisplayText = "abcdefghijklmnopq";
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1232,7 +1232,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         tv.SelectedTab = tab2;
 
-        Application.ClipToScreen ();
+        View.ClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (

+ 27 - 27
UnitTests/Views/TableViewTests.cs

@@ -723,7 +723,7 @@ public class TableViewTests (ITestOutputHelper output)
 
         // since A is now pushed off screen we get indicator showing
         // that user can scroll left to see first column
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tableView.Draw ();
 
         expected =
@@ -738,7 +738,7 @@ public class TableViewTests (ITestOutputHelper output)
         tableView.NewKeyDownEvent (new () { KeyCode = KeyCode.CursorRight });
         tableView.NewKeyDownEvent (new () { KeyCode = KeyCode.CursorRight });
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tableView.Draw ();
 
         expected =
@@ -797,7 +797,7 @@ public class TableViewTests (ITestOutputHelper output)
 
         // Scroll right
         tableView.NewKeyDownEvent (new () { KeyCode = KeyCode.CursorRight });
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tableView.Draw ();
 
         // Note that with SmoothHorizontalScrolling only a single new column
@@ -845,7 +845,7 @@ public class TableViewTests (ITestOutputHelper output)
 
         // select last visible column
         tableView.SelectedColumn = 2; // column C
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tableView.Draw ();
 
         var expected =
@@ -857,7 +857,7 @@ public class TableViewTests (ITestOutputHelper output)
 
         // Scroll right
         tableView.NewKeyDownEvent (new () { KeyCode = KeyCode.CursorRight });
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tableView.Draw ();
 
         // notice that without smooth scrolling we just update the first column
@@ -1980,7 +1980,7 @@ public class TableViewTests (ITestOutputHelper output)
 ◄─┼─┼─┤
 │2│3│4│";
         tableView.SetNeedsDraw ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tableView.Draw ();
 
         TestHelpers.AssertDriverContentsAre (expected, output);
@@ -1994,7 +1994,7 @@ public class TableViewTests (ITestOutputHelper output)
 ├─┼─┼─┤
 │2│3│4│";
         tableView.SetNeedsDraw ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tableView.Draw ();
 
         TestHelpers.AssertDriverContentsAre (expected, output);
@@ -2010,7 +2010,7 @@ public class TableViewTests (ITestOutputHelper output)
         tableView.Style.ShowHorizontalHeaderUnderline = true;
         tableView.LayoutSubviews ();
         tableView.SetNeedsDraw ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tableView.Draw ();
 
         // normally we should have scroll indicators because DEF are of screen
@@ -2033,7 +2033,7 @@ public class TableViewTests (ITestOutputHelper output)
 ├─┼─┼─┤
 │1│2│3│";
         tableView.SetNeedsDraw ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tableView.Draw ();
         TestHelpers.AssertDriverContentsAre (expected, output);
     }
@@ -2609,7 +2609,7 @@ A B C
 
         Assert.True (pets.First ().IsPicked);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2629,7 +2629,7 @@ A B C
         Assert.True (pets.ElementAt (0).IsPicked);
         Assert.True (pets.ElementAt (1).IsPicked);
         Assert.False (pets.ElementAt (2).IsPicked);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2649,7 +2649,7 @@ A B C
         Assert.False (pets.ElementAt (0).IsPicked);
         Assert.True (pets.ElementAt (1).IsPicked);
         Assert.False (pets.ElementAt (2).IsPicked);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2677,7 +2677,7 @@ A B C
         wrapper.CheckedRows.Add (0);
         wrapper.CheckedRows.Add (2);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         var expected =
@@ -2701,7 +2701,7 @@ A B C
         Assert.Contains (2, wrapper.CheckedRows);
         Assert.Equal (3, wrapper.CheckedRows.Count);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2717,7 +2717,7 @@ A B C
         // Untoggle the top 2
         tv.NewKeyDownEvent (Key.Space);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2746,7 +2746,7 @@ A B C
         tv.NewKeyDownEvent (Key.A.WithCtrl);
         tv.NewKeyDownEvent (Key.Space);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         var expected =
@@ -2766,7 +2766,7 @@ A B C
         // Untoggle all again
         tv.NewKeyDownEvent (Key.Space);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2807,7 +2807,7 @@ A B C
 
         Assert.True (pets.All (p => p.IsPicked));
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         var expected =
@@ -2827,7 +2827,7 @@ A B C
         Assert.Empty (pets.Where (p => p.IsPicked));
 #pragma warning restore xUnit2029
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2854,7 +2854,7 @@ A B C
         var wrapper = new CheckBoxTableSourceWrapperByIndex (tv, tv.Table);
         tv.Table = wrapper;
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         var expected =
@@ -2874,7 +2874,7 @@ A B C
 
         Assert.Single (wrapper.CheckedRows, 0);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2894,7 +2894,7 @@ A B C
         Assert.Contains (1, wrapper.CheckedRows);
         Assert.Equal (2, wrapper.CheckedRows.Count);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2913,7 +2913,7 @@ A B C
 
         Assert.Single (wrapper.CheckedRows, 1);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2945,7 +2945,7 @@ A B C
         wrapper.UseRadioButtons = true;
 
         tv.Table = wrapper;
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         var expected =
@@ -2968,7 +2968,7 @@ A B C
 
         Assert.True (pets.First ().IsPicked);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -2989,7 +2989,7 @@ A B C
         Assert.True (pets.ElementAt (1).IsPicked);
         Assert.False (pets.ElementAt (2).IsPicked);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -3010,7 +3010,7 @@ A B C
         Assert.False (pets.ElementAt (1).IsPicked);
         Assert.False (pets.ElementAt (2).IsPicked);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =

+ 5 - 5
UnitTests/Views/TextFieldTests.cs

@@ -210,13 +210,13 @@ public class TextFieldTests (ITestOutputHelper output)
 
         // Caption should appear when not focused and no text
         Assert.False (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("Enter txt", output);
 
         // but disapear when text is added
         tf.Text = content;
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre (content, output);
         Application.Top.Dispose ();
@@ -234,14 +234,14 @@ public class TextFieldTests (ITestOutputHelper output)
         // Caption has no effect when focused
         tf.Caption = "Enter txt";
         Assert.True (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("", output);
 
         Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
 
         Assert.False (tf.HasFocus);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
         TestHelpers.AssertDriverContentsAre ("Enter txt", output);
         Application.Top.Dispose ();
@@ -1997,7 +1997,7 @@ Les Misérables",
 
         // incorrect order will result with a wrong accent place
         tf.Text = "Les Mis" + char.ConvertFromUtf32 (int.Parse ("0301", NumberStyles.HexNumber)) + "erables";
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tf.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (

+ 1 - 1
UnitTests/Views/TextViewTests.cs

@@ -8353,7 +8353,7 @@ line.
         tv.CursorPosition = new Point (6, 2);
         Assert.Equal (new Point (5, 2), tv.CursorPosition);
         top.LayoutSubviews ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (

+ 7 - 7
UnitTests/Views/TreeTableSourceTests.cs

@@ -54,7 +54,7 @@ public class TreeTableSourceTests : IDisposable
         // when pressing right we should expand the top route
         tv.NewKeyDownEvent (Key.CursorRight);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -72,7 +72,7 @@ public class TreeTableSourceTests : IDisposable
         // when pressing left we should collapse the top route again
         tv.NewKeyDownEvent (Key.CursorLeft);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -96,7 +96,7 @@ public class TreeTableSourceTests : IDisposable
 
         tv.Style.GetOrCreateColumnStyle (1).MinAcceptableWidth = 1;
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         var expected =
@@ -116,7 +116,7 @@ public class TreeTableSourceTests : IDisposable
 
         Assert.True (tv.NewMouseEvent (new MouseEventArgs { Position = new (2, 2), Flags = MouseFlags.Button1Clicked }));
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -141,7 +141,7 @@ public class TreeTableSourceTests : IDisposable
 
         // Clicking on the + again should collapse
         tv.NewMouseEvent (new MouseEventArgs { Position = new (2, 2), Flags = MouseFlags.Button1Clicked });
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -194,7 +194,7 @@ public class TreeTableSourceTests : IDisposable
 
         Application.RaiseKeyDownEvent (Key.CursorRight);
 
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =
@@ -212,7 +212,7 @@ public class TreeTableSourceTests : IDisposable
 
         tv.NewKeyDownEvent (Key.CursorDown);
         tv.NewKeyDownEvent (Key.Space);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         expected =

+ 13 - 13
UnitTests/Views/TreeViewTests.cs

@@ -721,7 +721,7 @@ public class TreeViewTests
                                             );
         tv.MaxDepth = 3;
         tv.ExpandAll ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         // Normal drawing of the tree view
@@ -760,7 +760,7 @@ public class TreeViewTests
                                             );
         tv.MaxDepth = 5;
         tv.ExpandAll ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
 
         tv.Draw ();
 
@@ -788,7 +788,7 @@ public class TreeViewTests
 
         Assert.True (tv.CanExpand ("5"));
         Assert.False (tv.IsExpanded ("5"));
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
 
         tv.Draw ();
 
@@ -843,7 +843,7 @@ public class TreeViewTests
         Assert.Null (tv.GetObjectOnRow (4));
 
         tv.Collapse (n1);
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
 
         tv.Draw ();
 
@@ -880,7 +880,7 @@ public class TreeViewTests
 
         tv.ColorScheme = new ColorScheme ();
         tv.LayoutSubviews ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsAre (
@@ -900,7 +900,7 @@ public class TreeViewTests
         tv.Collapse (n1);
 
         tv.LayoutSubviews ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsAre (
@@ -918,7 +918,7 @@ public class TreeViewTests
         tv.ScrollOffsetVertical = 1;
 
         tv.LayoutSubviews ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsAre (
@@ -955,7 +955,7 @@ public class TreeViewTests
 
         tv.ColorScheme = new ColorScheme ();
         tv.LayoutSubviews ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         // Normal drawing of the tree view
@@ -1144,7 +1144,7 @@ oot two
 
         // matches nothing
         filter.Text = "asdfjhasdf";
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         // Normal drawing of the tree view
@@ -1155,7 +1155,7 @@ oot two
 
         // Matches everything
         filter.Text = "root";
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsAre (
@@ -1170,7 +1170,7 @@ oot two
 
         // Matches 2 leaf nodes
         filter.Text = "leaf";
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsAre (
@@ -1184,7 +1184,7 @@ oot two
 
         // Matches 1 leaf nodes
         filter.Text = "leaf 1";
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         TestHelpers.AssertDriverContentsAre (
@@ -1256,7 +1256,7 @@ oot two
         // redraw now that the custom color
         // delegate is registered
         tv.SetNeedsDraw ();
-        Application.ClipToScreen ();
+        View.SetClipToScreen ();
         tv.Draw ();
 
         // Same text

+ 28 - 14
docfx/docs/drawing.md

@@ -10,9 +10,9 @@ Terminal.Gui apps draw using the @Terminal.Gui.View.Move and @Terminal.Gui.View.
 
 Outputting unformatted text involves:
 
-a) Moving the draw cursor using @Terminal.Gui.ViewMove.
-b) Setting the attributes using @Terminal.Gui.ViewSetAttribute`
-c) Outputting glyphs by calling @Terminal.Gui.View.AddRune or @Terminal.Gui.View.AddStr
+a) Moving the draw cursor using @Terminal.Gui.View.Move.
+b) Setting the attributes using @Terminal.Gui.View.SetAttribute.
+c) Outputting glyphs by calling @Terminal.Gui.View.AddRune or @Terminal.Gui.View.AddStr.
 
 Outputting formatted text involves:
 
@@ -25,17 +25,29 @@ Line drawing is accomplished using the @Terminal.Gui.LineCanvas API:
 a) Add the lines via @Terminal.Gui.LineCanvas.Add.
 b) Either render the line canvas via @Terminal.Gui.LineCanvas.GetMap() or let the @Terminal.Gui.View do so automatically (which enables automatic line joining across Views).
 
-The @Terminal.Gui.Application MainLoop will iterate over all Views in an application looking for views have their @Terminal.Gui.View.NeedsDraw property set. The @Terminal.Gui.View.Draw method will be called which, in turn.
+### Drawing occurs each MainLoop Iteration
 
-1) Draws the Adornments (e.g. @Terminal.Gui.View.Border).
-2) Sets the Normal color scheme.
-3) Clears the @Terminal.Gui.View.Viewport.
-4) Draws @Terminal.Gui.View.Text.
-5) Draws any non-text or Subview content.
-6) Draws @Terminal.Gui.View.Subviews.
-7) Draws @Terminal.Gui.View.LineCanvas (which may have been added to by any of the steps above).
+The @Terminal.Gui.Application MainLoop will iterate over all Views in the view hierarchy, starting with @Terminal.Gui.Application.Toplevels. The @Terminal.Gui.View.Draw method will be called which, in turn:
+
+0) Determines if @Terminal.Gui.View.NeedsDraw or @Terminal.Gui.View.SubviewsNeedsDraw are set. If neither is set, processing stops.
+1) Sets the clip to the view's Frame.
+2) Draws the @Terminal.Gui.View.Border and @Terminal.Gui.View.Padding (but NOT the Margin).
+3) Sets the clip to the view's Viewport.
+4) Sets the Normal color scheme.
+5) Calls Draw on any @Terminal.Gui.View.Subviews.
+6) Draws @Terminal.Gui.View.Text.
+7) Draws any non-text content (the base View does nothing.)
+8) Sets the clip back to the view's Frame.
+9) Draws @Terminal.Gui.View.LineCanvas (which may have been added to by any of the steps above).
+10) Draws the @Terminal.Gui.View.Border and @Terminal.Gui.View.Padding Subviews (just the subviews). (but NOT the Margin).
+11) The Clip at this point excludes all Subviews NOT INCLUDING their Margins. This clip is cached so @Terminal.Gui.View.Margin can be rendered later.
+12) DrawComplete is raised.
+13) The current View's Frame NOT INCLUDING the Margin is excluded from the current Clip region.
+
+Most of the steps above can be overridden by developers using the standard [Terminal.Gui cancellable event pattern](events.md). For example, the base @Terminal.Gui.View always clears the viewport. To override this, a subclass can override @Terminal.Gui.View.OnClearingViewport to simply return `true`. Or, a user of `View` can subscribe to the @Terminal.Gui.View.ClearingViewport event and set the `Cancel` argument to `true`.
+
+Then, after the above steps have completed, the Mainloop will iterate through all views in the view hierarchy again, this time calling Draw on any @Terminal.Gui.View.Margin objects, using the cached Clip region mentioned above. This enables Margin to be transparent.
 
-Each of these steps can be overridden by developers using the standard [Terminal.Gui cancellable event pattern](events.md). For example, the base @Terminal.Gui.View always clears the viewport. To override this, a subclass can override @Terminal.Gui.View.OnClearingViewport to simply return `true`. Or, a user of `View` can subscribe to the @Terminal.Gui.View.ClearingViewport event and set the `Cancel` argument to `true`.
 
 ### Declaring that drawing is needed
 
@@ -45,7 +57,6 @@ If a View need to redraw because something changed within it's Content Area it c
 
 Clipping enables better performance by ensuring on regions of the terminal that need to be drawn actually get drawn by the @Terminal.Gui.ConsoleDriver. Terminal.Gui supports non-rectangular clip regions with @Terminal.Gui.Region. @Terminal.Gui.ConsoleDriver.Clip is the application managed clip region and is managed by @Terminal.Gui.Application. Developers cannot change this directly, but can use @Terminal.Gui.Application.ClipToScreen, @Terminal.Gui.Application.SetClip(Region), @Terminal.Gui.View.ClipToFrame, and @Terminal.Gui.ClipToViewPort.
 
-
 ## Coordinate System for Drawing
 
 The @Terminal.Gui.View draw APIs all take coordinates specified in *Viewport-Relative* coordinates. That is, `0, 0` is the top-left cell visible to the user.
@@ -107,7 +118,10 @@ Terminal.Gui supports drawing lines and shapes using box-drawing glyphs. The @Te
 
 ## Thickness
 
-Describes the thickness of a frame around a rectangle. The thickness is specified for each side of the rectangle using a @Terminal.Gui.Thickness object. The Thickness class contains properties for the left, top, right, and bottom thickness. The @Terminal.Gui.Adornment class uses @Terminal.Gui.Thickness to support drawing the frame around a view. The `View` class contains three Adornment-derived properties: 
+Describes the thickness of a frame around a rectangle. The thickness is specified for each side of the rectangle using a @Terminal.Gui.Thickness object. The Thickness class contains properties for the left, top, right, and bottom thickness. The @Terminal.Gui.Adornment class uses @Terminal.Gui.Thickness to support drawing the frame around a view. 
 
 See [View Deep Dive](View.md) for details.
 
+## Diagnostics
+
+The @Terminal.Gui.ViewDiagnostics.DisplayIndicator flag can be set on @Terminal.Gui.View.Diagnostics to cause an animated glyph to appear in the `Border` of each View. The glyph will animate each time that View's `Draw` method is called where either @Terminal.Gui.View.NeedsDraw or @Terminal.Gui.View.SubviewNeedsDraw is set.