diff --git a/Terminal.Gui/App/Application.Driver.cs b/Terminal.Gui/App/Application.Driver.cs
index e7a3243e2..aa2ee80fe 100644
--- a/Terminal.Gui/App/Application.Driver.cs
+++ b/Terminal.Gui/App/Application.Driver.cs
@@ -6,7 +6,6 @@ public static partial class Application // Driver abstractions
{
internal static bool _forceFakeConsole;
- // TODO: Add to IApplication
/// Gets the that has been selected. See also .
public static IConsoleDriver? Driver
{
@@ -14,18 +13,18 @@ public static partial class Application // Driver abstractions
internal set => ApplicationImpl.Instance.Driver = value;
}
- // TODO: Add to IApplication
- // BUGBUG: Force16Colors should be nullable.
///
/// Gets or sets whether will be forced to output only the 16 colors defined in
/// . The default is , meaning 24-bit (TrueColor) colors will be output
/// as long as the selected supports TrueColor.
///
[ConfigurationProperty (Scope = typeof (SettingsScope))]
- public static bool Force16Colors { get; set; }
+ public static bool Force16Colors
+ {
+ get => ApplicationImpl.Instance.Force16Colors;
+ set => ApplicationImpl.Instance.Force16Colors = value;
+ }
- // TODO: Add to IApplication
- // BUGBUG: ForceDriver should be nullable.
///
/// Forces the use of the specified driver (one of "fake", "dotnet", "windows", or "unix"). If not
/// specified, the driver is selected based on the platform.
@@ -35,12 +34,15 @@ public static partial class Application // Driver abstractions
/// with either `driver` or `driverName` specified.
///
[ConfigurationProperty (Scope = typeof (SettingsScope))]
- public static string ForceDriver { get; set; } = string.Empty;
+ public static string ForceDriver
+ {
+ get => ApplicationImpl.Instance.ForceDriver;
+ set => ApplicationImpl.Instance.ForceDriver = value;
+ }
- // TODO: Add to IApplication
///
/// Collection of sixel images to write out to screen when updating.
/// Only add to this collection if you are sure terminal supports sixel format.
///
- public static List Sixel { get; } = new List ();
+ public static List Sixel => ApplicationImpl.Instance.Sixel;
}
diff --git a/Terminal.Gui/App/Application.Initialization.cs b/Terminal.Gui/App/Application.Lifecycle.cs
similarity index 88%
rename from Terminal.Gui/App/Application.Initialization.cs
rename to Terminal.Gui/App/Application.Lifecycle.cs
index 188545366..c69ad06f6 100644
--- a/Terminal.Gui/App/Application.Initialization.cs
+++ b/Terminal.Gui/App/Application.Lifecycle.cs
@@ -5,7 +5,7 @@ using System.Reflection;
namespace Terminal.Gui.App;
-public static partial class Application // Initialization (Init/Shutdown)
+public static partial class Application // Lifecycle (Init/Shutdown)
{
/// Initializes a new instance of a Terminal.Gui Application. must be called when the application is closing.
@@ -24,7 +24,7 @@ public static partial class Application // Initialization (Init/Shutdown)
/// The function combines
/// and
/// into a single
- /// call. An application cam use without explicitly calling
+ /// call. An application can use without explicitly calling
/// .
///
///
@@ -118,28 +118,9 @@ public static partial class Application // Initialization (Init/Shutdown)
// or go through the modern application architecture
if (Driver is null)
{
- //// Try to find a legacy IConsoleDriver type that matches the driver name
- //bool useLegacyDriver = false;
- //if (!string.IsNullOrEmpty (ForceDriver))
- //{
- // (List drivers, List driverTypeNames) = GetDriverTypes ();
- // Type? driverType = drivers.FirstOrDefault (t => t!.Name.Equals (ForceDriver, StringComparison.InvariantCultureIgnoreCase));
-
- // if (driverType is { } && !typeof (IConsoleDriverFacade).IsAssignableFrom (driverType))
- // {
- // // This is a legacy driver (not a ConsoleDriverFacade)
- // Driver = (IConsoleDriver)Activator.CreateInstance (driverType)!;
- // useLegacyDriver = true;
- // }
- //}
-
- //// Use the modern application architecture
- //if (!useLegacyDriver)
- {
- ApplicationImpl.Instance.Init (driver, driverName);
- Debug.Assert (Driver is { });
- return;
- }
+ ApplicationImpl.Instance.Init (driver, driverName);
+ Debug.Assert (Driver is { });
+ return;
}
Debug.Assert (Navigation is null);
@@ -203,7 +184,7 @@ public static partial class Application // Initialization (Init/Shutdown)
private static void Driver_KeyUp (object? sender, Key e) { RaiseKeyUpEvent (e); }
private static void Driver_MouseEvent (object? sender, MouseEventArgs e) { RaiseMouseEvent (e); }
- /// Gets of list of types and type names that are available.
+ /// Gets a list of types and type names that are available.
///
[RequiresUnreferencedCode ("AOT")]
public static (List, List) GetDriverTypes ()
@@ -229,8 +210,6 @@ public static partial class Application // Initialization (Init/Shutdown)
.Union (["dotnet", "windows", "unix", "fake"])
.ToList ()!;
-
-
return (driverTypes, driverTypeNames);
}
diff --git a/Terminal.Gui/App/Application.Screen.cs b/Terminal.Gui/App/Application.Screen.cs
index 0d9a932c5..879141412 100644
--- a/Terminal.Gui/App/Application.Screen.cs
+++ b/Terminal.Gui/App/Application.Screen.cs
@@ -4,9 +4,6 @@ namespace Terminal.Gui.App;
public static partial class Application // Screen related stuff; intended to hide Driver details
{
- private static readonly object _lockScreen = new ();
- private static Rectangle? _screen;
-
///
/// Gets or sets the size of the screen. By default, this is the size of the screen as reported by the .
///
@@ -17,30 +14,8 @@ public static partial class Application // Screen related stuff; intended to hid
///
public static Rectangle Screen
{
- get
- {
- lock (_lockScreen)
- {
- if (_screen == null)
- {
- _screen = Driver?.Screen ?? new (new (0, 0), new (2048, 2048));
- }
-
- return _screen.Value;
- }
- }
- set
- {
- if (value is {} && (value.X != 0 || value.Y != 0))
- {
- throw new NotImplementedException ($"Screen locations other than 0, 0 are not yet supported");
- }
-
- lock (_lockScreen)
- {
- _screen = value;
- }
- }
+ get => ApplicationImpl.Instance.Screen;
+ set => ApplicationImpl.Instance.Screen = value;
}
/// Invoked when the terminal's size changed. The new size of the terminal is provided.
@@ -85,5 +60,9 @@ public static partial class Application // Screen related stuff; intended to hid
/// This is typical set to true when a View's changes and that view has no
/// SuperView (e.g. when is moved or resized.
///
- internal static bool ClearScreenNextIteration { get; set; }
+ internal static bool ClearScreenNextIteration
+ {
+ get => ApplicationImpl.Instance.ClearScreenNextIteration;
+ set => ApplicationImpl.Instance.ClearScreenNextIteration = value;
+ }
}
diff --git a/Terminal.Gui/App/Application.cs b/Terminal.Gui/App/Application.cs
index 10c57beed..718c24772 100644
--- a/Terminal.Gui/App/Application.cs
+++ b/Terminal.Gui/App/Application.cs
@@ -232,7 +232,13 @@ public static partial class Application
Driver = null;
}
- _screen = null;
+ // Reset Screen to null so it will be recalculated on next access
+ // Note: ApplicationImpl.Shutdown() also calls ResetScreen() before calling this method
+ // to avoid potential circular reference issues. Calling it twice is harmless.
+ if (ApplicationImpl.Instance is ApplicationImpl impl)
+ {
+ impl.ResetScreen ();
+ }
// Don't reset ForceDriver; it needs to be set before Init is called.
//ForceDriver = string.Empty;
diff --git a/Terminal.Gui/App/ApplicationImpl.cs b/Terminal.Gui/App/ApplicationImpl.cs
index 5668d9450..426d7d238 100644
--- a/Terminal.Gui/App/ApplicationImpl.cs
+++ b/Terminal.Gui/App/ApplicationImpl.cs
@@ -24,6 +24,12 @@ public class ApplicationImpl : IApplication
private Toplevel? _top;
private readonly ConcurrentStack _topLevels = new ();
private int _mainThreadId = -1;
+ private bool _force16Colors;
+ private string _forceDriver = string.Empty;
+ private readonly List _sixel = new ();
+ private readonly object _lockScreen = new ();
+ private Rectangle? _screen;
+ private bool _clearScreenNextIteration;
// Private static readonly Lazy instance of Application
private static Lazy _lazyInstance = new (() => new ApplicationImpl ());
@@ -94,6 +100,59 @@ public class ApplicationImpl : IApplication
set => _initialized = value;
}
+ ///
+ public bool Force16Colors
+ {
+ get => _force16Colors;
+ set => _force16Colors = value;
+ }
+
+ ///
+ public string ForceDriver
+ {
+ get => _forceDriver;
+ set => _forceDriver = value;
+ }
+
+ ///
+ public List Sixel => _sixel;
+
+ ///
+ public Rectangle Screen
+ {
+ get
+ {
+ lock (_lockScreen)
+ {
+ if (_screen == null)
+ {
+ _screen = Driver?.Screen ?? new (new (0, 0), new (2048, 2048));
+ }
+
+ return _screen.Value;
+ }
+ }
+ set
+ {
+ if (value is {} && (value.X != 0 || value.Y != 0))
+ {
+ throw new NotImplementedException ($"Screen locations other than 0, 0 are not yet supported");
+ }
+
+ lock (_lockScreen)
+ {
+ _screen = value;
+ }
+ }
+ }
+
+ ///
+ public bool ClearScreenNextIteration
+ {
+ get => _clearScreenNextIteration;
+ set => _clearScreenNextIteration = value;
+ }
+
///
public ApplicationPopover? Popover
{
@@ -381,6 +440,9 @@ public class ApplicationImpl : IApplication
bool wasInitialized = _initialized;
+ // Reset Screen before calling Application.ResetState to avoid circular reference
+ ResetScreen ();
+
// Call ResetState FIRST so it can properly dispose Popover and other resources
// that are accessed via Application.* static properties that now delegate to instance fields
Application.ResetState ();
@@ -396,6 +458,10 @@ public class ApplicationImpl : IApplication
_top = null;
_topLevels.Clear ();
_mainThreadId = -1;
+ _screen = null;
+ _clearScreenNextIteration = false;
+ _sixel.Clear ();
+ // Don't reset ForceDriver and Force16Colors; they need to be set before Init is called
if (wasInitialized)
{
@@ -469,15 +535,12 @@ public class ApplicationImpl : IApplication
tops.Insert (0, visiblePopover);
}
- // BUGBUG: Application.Screen needs to be moved to IApplication
- bool neededLayout = View.Layout (tops.ToArray ().Reverse (), Application.Screen.Size);
+ bool neededLayout = View.Layout (tops.ToArray ().Reverse (), Screen.Size);
- // BUGBUG: Application.ClearScreenNextIteration needs to be moved to IApplication
- if (Application.ClearScreenNextIteration)
+ if (ClearScreenNextIteration)
{
forceRedraw = true;
- // BUGBUG: Application.Screen needs to be moved to IApplication
- Application.ClearScreenNextIteration = false;
+ ClearScreenNextIteration = false;
}
if (forceRedraw)
@@ -490,4 +553,15 @@ public class ApplicationImpl : IApplication
View.SetClipToScreen ();
_driver?.Refresh ();
}
+
+ ///
+ /// Resets the Screen field to null so it will be recalculated on next access.
+ ///
+ internal void ResetScreen ()
+ {
+ lock (_lockScreen)
+ {
+ _screen = null;
+ }
+ }
}
diff --git a/Terminal.Gui/App/IApplication.cs b/Terminal.Gui/App/IApplication.cs
index 44f058855..93a4c7c22 100644
--- a/Terminal.Gui/App/IApplication.cs
+++ b/Terminal.Gui/App/IApplication.cs
@@ -33,6 +33,35 @@ public interface IApplication
/// Gets or sets whether the application has been initialized.
bool Initialized { get; set; }
+ ///
+ /// Gets or sets whether will be forced to output only the 16 colors defined in
+ /// . The default is , meaning 24-bit (TrueColor) colors will be output
+ /// as long as the selected supports TrueColor.
+ ///
+ bool Force16Colors { get; set; }
+
+ ///
+ /// Forces the use of the specified driver (one of "fake", "dotnet", "windows", or "unix"). If not
+ /// specified, the driver is selected based on the platform.
+ ///
+ string ForceDriver { get; set; }
+
+ ///
+ /// Collection of sixel images to write out to screen when updating.
+ /// Only add to this collection if you are sure terminal supports sixel format.
+ ///
+ List Sixel { get; }
+
+ ///
+ /// Gets or sets the size of the screen. By default, this is the size of the screen as reported by the .
+ ///
+ Rectangle Screen { get; set; }
+
+ ///
+ /// Gets or sets whether the screen will be cleared, and all Views redrawn, during the next Application iteration.
+ ///
+ bool ClearScreenNextIteration { get; set; }
+
/// Gets or sets the popover manager.
ApplicationPopover? Popover { get; set; }