diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index e31fe0b5ce..036804e6bc 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -2125,23 +2125,25 @@ static void Init (Func topLevelFactory) { if (_initialized) return; - var p = Environment.OSVersion.Platform; - Mono.Terminal.IMainLoopDriver mainLoopDriver; - - if (UseSystemConsole) { - mainLoopDriver = new Mono.Terminal.NetMainLoop (); - Driver = new NetDriver (); - } else if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows) { - var windowsDriver = new WindowsDriver (); - mainLoopDriver = windowsDriver; - Driver = windowsDriver; - } else { - mainLoopDriver = new Mono.Terminal.UnixMainLoop (); - Driver = new CursesDriver (); + if (Driver == null) { + var p = Environment.OSVersion.Platform; + Mono.Terminal.IMainLoopDriver mainLoopDriver; + + if (UseSystemConsole) { + mainLoopDriver = new Mono.Terminal.NetMainLoop (); + Driver = new NetDriver (); + } else if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows) { + var windowsDriver = new WindowsDriver (); + mainLoopDriver = windowsDriver; + Driver = windowsDriver; + } else { + mainLoopDriver = new Mono.Terminal.UnixMainLoop (); + Driver = new CursesDriver (); + } + Driver.Init (TerminalResized); + MainLoop = new Mono.Terminal.MainLoop (mainLoopDriver); + SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext (MainLoop)); } - Driver.Init (TerminalResized); - MainLoop = new Mono.Terminal.MainLoop (mainLoopDriver); - SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext (MainLoop)); Top = topLevelFactory (); Current = Top; CurrentView = Top; @@ -2152,6 +2154,8 @@ static void Init (Func topLevelFactory) /// Captures the execution state for the provided view. /// public class RunState : IDisposable { + internal bool closeDriver = true; + internal RunState (Toplevel view) { Toplevel = view; @@ -2168,7 +2172,7 @@ internal RunState (Toplevel view) /// was occupying. public void Dispose () { - Dispose (true); + Dispose (closeDriver); GC.SuppressFinalize (this); } @@ -2180,7 +2184,7 @@ public void Dispose () protected virtual void Dispose (bool disposing) { if (Toplevel != null) { - End (Toplevel); + End (Toplevel, disposing); Toplevel = null; } } @@ -2373,14 +2377,14 @@ static bool OutsideFrame (Point p, Rect r) /// /// Building block API: Prepares the provided for execution. /// - /// The runstate handle that needs to be passed to the method upon completion. + /// The runstate handle that needs to be passed to the method upon completion. /// Toplevel to prepare execution for. /// /// This method prepares the provided toplevel for running with the focus, /// it adds this to the list of toplevels, sets up the mainloop to process the /// event, lays out the subviews, focuses the first element, and draws the /// toplevel in the screen. This is usually followed by executing - /// the method, and then the method upon termination which will + /// the method, and then the method upon termination which will /// undo these changes. /// public static RunState Begin (Toplevel toplevel) @@ -2417,19 +2421,21 @@ public static RunState Begin (Toplevel toplevel) /// Building block API: completes the execution of a that was started with . /// /// The runstate returned by the method. - public static void End (RunState runState) + /// trueCloses the application.falseCloses the toplevels only. + public static void End (RunState runState, bool closeDriver = true) { if (runState == null) throw new ArgumentNullException (nameof (runState)); + runState.closeDriver = closeDriver; runState.Dispose (); - runState = null; } /// - /// Shutdown an application initalized with + /// Shutdown an application initialized with /// - public static void Shutdown () + /// /// trueCloses the application.falseCloses toplevels only. + public static void Shutdown (bool closeDriver = true) { // Shutdown is the bookend for Init. As such it needs to clean up all resources // Init created. Apps that do any threading will need to code defensively for this. @@ -2443,10 +2449,12 @@ public static void Shutdown () CurrentView = null; Top = null; - // - MainLoop = null; + // Closes the application if it's true. + if (closeDriver) { + MainLoop = null; + Driver.End (); + } - Driver.End (); _initialized = false; } @@ -2480,13 +2488,13 @@ public static void Refresh () Driver.Refresh (); } - internal static void End (View view) + internal static void End (View view, bool closeDriver = true) { if (toplevels.Peek () != view) throw new ArgumentException ("The view that you end with must be balanced"); toplevels.Pop (); if (toplevels.Count == 0) - Shutdown (); + Shutdown (closeDriver); else { Current = toplevels.Peek (); Refresh (); @@ -2545,7 +2553,7 @@ static void DrawBounds (View v) } /// - /// Runs the application by calling with the value of + /// Runs the application by calling with the value of /// public static void Run () { @@ -2553,7 +2561,7 @@ public static void Run () } /// - /// Runs the application by calling with a new instance of the specified -derived class + /// Runs the application by calling with a new instance of the specified -derived class /// public static void Run () where T : Toplevel, new() { @@ -2571,11 +2579,11 @@ public static void Run () /// run other modal s such as boxes. /// /// - /// To make a stop execution, call . + /// To make a stop execution, call . /// /// - /// Calling is equivalent to calling , followed by , - /// and then calling . + /// Calling is equivalent to calling , followed by , + /// and then calling . /// /// /// Alternatively, to have a program control the main loop and @@ -2585,11 +2593,11 @@ public static void Run () /// then return control immediately. /// /// - public static void Run (Toplevel view) + public static void Run (Toplevel view, bool closeDriver = true) { var runToken = Begin (view); RunLoop (runToken); - End (runToken); + End (runToken, closeDriver); } /// diff --git a/UICatalog/Scenario.cs b/UICatalog/Scenario.cs index f8b22cb682..f422bdefa4 100644 --- a/UICatalog/Scenario.cs +++ b/UICatalog/Scenario.cs @@ -195,11 +195,8 @@ public virtual void Setup () /// public virtual void Run () { - Application.Run (Top); - - // Every call to Application.Init must be bound by a call to Shutdown - // or Init doesn't do anything - Application.Shutdown (); + // This method already performs a later automatic shutdown. + Application.Run (Top, false); } /// diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 29cacd3d8d..baff0e932a 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -79,6 +79,8 @@ static void Main (string [] args) scenario.Run (); scenario = GetScenarioToRun (); } + // Now closes the driver too. + Application.Shutdown (); } /// @@ -197,7 +199,7 @@ private static Scenario GetScenarioToRun () }; #endif - Application.Run (_top); + Application.Run (_top, false); return _runningScenario; }