From 54679a9b683583321df5747673cdeae464c1405c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Mar 2026 22:56:24 +0000
Subject: [PATCH 1/3] Initial plan
From e5bfe5987a92d3e65ef71e71909b79fecba072dc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Mar 2026 23:09:24 +0000
Subject: [PATCH 2/3] Add Draw trace category and instrument View.Drawing.cs
and ApplicationImpl.LayoutAndDraw
Co-authored-by: tig <585482+tig@users.noreply.github.com>
---
Terminal.Gui/App/ApplicationImpl.Screen.cs | 6 +++
Terminal.Gui/App/Tracing/Trace.cs | 22 +++++++++++
Terminal.Gui/App/Tracing/TraceCategory.cs | 5 ++-
Terminal.Gui/ViewBase/View.Drawing.cs | 11 ++++++
.../Tracing/TraceTests.cs | 37 +++++++++++++++++++
5 files changed, 80 insertions(+), 1 deletion(-)
diff --git a/Terminal.Gui/App/ApplicationImpl.Screen.cs b/Terminal.Gui/App/ApplicationImpl.Screen.cs
index aa270eca8f..f9c12956fd 100644
--- a/Terminal.Gui/App/ApplicationImpl.Screen.cs
+++ b/Terminal.Gui/App/ApplicationImpl.Screen.cs
@@ -1,5 +1,7 @@
namespace Terminal.Gui.App;
+using Trace = Terminal.Gui.Tracing.Trace;
+
internal partial class ApplicationImpl
{
///
@@ -48,6 +50,8 @@ private void RaiseScreenChangedEvent (Rectangle screen)
///
public void LayoutAndDraw (bool forceRedraw = false)
{
+ Trace.Draw ("ApplicationImpl", "Start", $"forceRedraw={forceRedraw}");
+
if (ClearScreenNextIteration)
{
forceRedraw = true;
@@ -94,5 +98,7 @@ public void LayoutAndDraw (bool forceRedraw = false)
// Cause the driver to flush any pending updates to the terminal
Driver?.Refresh ();
}
+
+ Trace.Draw ("ApplicationImpl", "End", $"neededLayout={neededLayout}, needsDraw={needsDraw}");
}
}
diff --git a/Terminal.Gui/App/Tracing/Trace.cs b/Terminal.Gui/App/Tracing/Trace.cs
index f5ade35763..2855e6bdc4 100644
--- a/Terminal.Gui/App/Tracing/Trace.cs
+++ b/Terminal.Gui/App/Tracing/Trace.cs
@@ -286,6 +286,28 @@ public static void Configuration (string? id, string phase, string? message = nu
#endregion
+ #region Draw Tracing
+
+ ///
+ /// Traces a draw operation.
+ ///
+ /// An identifying string for the trace (e.g., ).
+ /// The phase of the draw operation (e.g., "Start", "End", "Adornments", "SubViews", "Text", "Content").
+ /// Optional additional context.
+ /// Automatically captured caller method name.
+ [Conditional ("DEBUG")]
+ public static void Draw (string? id, string phase, string? message = null, [CallerMemberName] string method = "")
+ {
+ if (!EnabledCategories.HasFlag (TraceCategory.Draw))
+ {
+ return;
+ }
+
+ Backend.Log (new TraceEntry (TraceCategory.Draw, id ?? string.Empty, phase, method, message, DateTime.UtcNow, null));
+ }
+
+ #endregion
+
#region Keyboard Tracing
///
diff --git a/Terminal.Gui/App/Tracing/TraceCategory.cs b/Terminal.Gui/App/Tracing/TraceCategory.cs
index 889d9e551c..ef1bfab0c8 100644
--- a/Terminal.Gui/App/Tracing/TraceCategory.cs
+++ b/Terminal.Gui/App/Tracing/TraceCategory.cs
@@ -29,6 +29,9 @@ public enum TraceCategory
/// Configuration management traces (property discovery, source loading, property assignment).
Configuration = 32,
+ /// Draw operation traces (layout-and-draw, view draw phases, adornments, subviews).
+ Draw = 64,
+
/// All trace categories enabled.
- All = Lifecycle | Command | Mouse | Keyboard | Navigation | Configuration
+ All = Lifecycle | Command | Mouse | Keyboard | Navigation | Configuration | Draw
}
diff --git a/Terminal.Gui/ViewBase/View.Drawing.cs b/Terminal.Gui/ViewBase/View.Drawing.cs
index 4cab2ec8ea..585cb9d2b3 100644
--- a/Terminal.Gui/ViewBase/View.Drawing.cs
+++ b/Terminal.Gui/ViewBase/View.Drawing.cs
@@ -1,4 +1,5 @@
using System.ComponentModel;
+using Terminal.Gui.Tracing;
namespace Terminal.Gui.ViewBase;
@@ -27,6 +28,7 @@ internal static void Draw (IEnumerable views, bool force)
view.SetNeedsDraw ();
}
+ Trace.Draw (view.ToIdentifyingString (), "Draw", $"force={force}");
view.Draw (context);
}
@@ -83,6 +85,8 @@ public void Draw (DrawContext? context = null)
return;
}
+ Trace.Draw (this.ToIdentifyingString (), "Start", $"NeedsDraw={NeedsDraw}, SubViewNeedsDraw={SubViewNeedsDraw}");
+
Region? originalClip = GetClip ();
// TODO: This can be further optimized by checking NeedsDraw below and only
@@ -93,6 +97,7 @@ public void Draw (DrawContext? context = null)
// Draw the Border and Padding Adornments.
// Note: Margin with a Shadow is special-cased and drawn in a separate pass to support
// transparent shadows.
+ Trace.Draw (this.ToIdentifyingString (), "Adornments");
DoDrawAdornments (originalClip);
SetClip (originalClip);
@@ -114,16 +119,19 @@ public void Draw (DrawContext? context = null)
// Draw the SubViews first (order matters: SubViews, Text, Content)
if (SubViewNeedsDraw)
{
+ Trace.Draw (this.ToIdentifyingString (), "SubViews");
DoDrawSubViews (context);
}
// ------------------------------------
// Draw the text
+ Trace.Draw (this.ToIdentifyingString (), "Text");
SetAttributeForRole (Enabled ? VisualRole.Normal : VisualRole.Disabled);
DoDrawText (context);
// ------------------------------------
// Draw the content
+ Trace.Draw (this.ToIdentifyingString (), "Content");
DoDrawContent (context);
// ------------------------------------
@@ -132,6 +140,7 @@ public void Draw (DrawContext? context = null)
// because they may draw outside the viewport.
SetClip (originalClip);
originalClip = AddFrameToClip ();
+ Trace.Draw (this.ToIdentifyingString (), "LineCanvas");
DoRenderLineCanvas (context);
// ------------------------------------
@@ -179,6 +188,8 @@ public void Draw (DrawContext? context = null)
// But the context contains the region that was drawn by this view
DoDrawComplete (context);
+ Trace.Draw (this.ToIdentifyingString (), "End");
+
// When DoDrawComplete returns, Driver.Clip has been updated to exclude this view's area.
// The next view drawn (earlier in Z-order, typically a peer view or the SuperView) will see
// a clip with "holes" where this view (and any SubViews drawn before it) are located.
diff --git a/Tests/UnitTestsParallelizable/Tracing/TraceTests.cs b/Tests/UnitTestsParallelizable/Tracing/TraceTests.cs
index cbf5cffed0..d78ee532ad 100644
--- a/Tests/UnitTestsParallelizable/Tracing/TraceTests.cs
+++ b/Tests/UnitTestsParallelizable/Tracing/TraceTests.cs
@@ -476,6 +476,43 @@ public void LoggingBackend_FormatsConfigurationCorrectly ()
#endregion
+ #region Draw Category Tests
+
+ // Copilot
+ [Fact]
+ public void TraceCategory_Draw_HasExpectedValue ()
+ {
+ Assert.Equal (64, (int)TraceCategory.Draw);
+ }
+
+ // Copilot
+ [Fact]
+ public void TraceCategory_All_IncludesDraw ()
+ {
+ Assert.True (TraceCategory.All.HasFlag (TraceCategory.Draw));
+ }
+
+ // Copilot
+ [Fact]
+ public void Draw_Category_CanBeEnabled ()
+ {
+ Trace.EnabledCategories = TraceCategory.None;
+
+ try
+ {
+ Trace.EnabledCategories = TraceCategory.Draw;
+
+ Assert.True (Trace.EnabledCategories.HasFlag (TraceCategory.Draw));
+ }
+ finally
+ {
+ Trace.EnabledCategories = TraceCategory.None;
+ Trace.Backend = new NullBackend ();
+ }
+ }
+
+ #endregion
+
#region Scenario Tests (merged from IssueScenarioTraceTests)
///
From 478c5f835136433ee88d0c6c5e2e9d87a3dd01ee Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 12 Mar 2026 13:38:49 +0000
Subject: [PATCH 3/3] Add Configuration and Draw menu items to UICatalog
Logging menu
Co-authored-by: tig <585482+tig@users.noreply.github.com>
---
Examples/UICatalog/UICatalogRunnable.cs | 42 +++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/Examples/UICatalog/UICatalogRunnable.cs b/Examples/UICatalog/UICatalogRunnable.cs
index 3f3a3b3c0e..c7e3b4bb1b 100644
--- a/Examples/UICatalog/UICatalogRunnable.cs
+++ b/Examples/UICatalog/UICatalogRunnable.cs
@@ -398,6 +398,48 @@ View [] CreateLoggingMenuItems ()
Enabled = false, CommandView = navTraceCheckBox, HelpText = "Toggle Focus & TabBehavior tracing", Key = Key.K.WithCtrl
});
+ CheckBox configTraceCheckBox = new ()
+ {
+ Text = "Con_figuration",
+ Value = Trace.EnabledCategories.HasFlag (TraceCategory.Configuration) ? CheckState.Checked : CheckState.UnChecked,
+ CanFocus = false
+ };
+
+ configTraceCheckBox.ValueChanging += (_, e) =>
+ {
+ if (e.NewValue == CheckState.Checked)
+ {
+ Trace.EnabledCategories |= TraceCategory.Configuration;
+ }
+ else
+ {
+ Trace.EnabledCategories &= ~TraceCategory.Configuration;
+ }
+ };
+
+ menuItems.Add (new MenuItem { CommandView = configTraceCheckBox, HelpText = "Toggle Configuration management tracing" });
+
+ CheckBox drawTraceCheckBox = new ()
+ {
+ Text = "_Draw",
+ Value = Trace.EnabledCategories.HasFlag (TraceCategory.Draw) ? CheckState.Checked : CheckState.UnChecked,
+ CanFocus = false
+ };
+
+ drawTraceCheckBox.ValueChanging += (_, e) =>
+ {
+ if (e.NewValue == CheckState.Checked)
+ {
+ Trace.EnabledCategories |= TraceCategory.Draw;
+ }
+ else
+ {
+ Trace.EnabledCategories &= ~TraceCategory.Draw;
+ }
+ };
+
+ menuItems.Add (new MenuItem { CommandView = drawTraceCheckBox, HelpText = "Toggle Draw operation tracing" });
+
// add a separator
menuItems.Add (new Line ());