#nullable enable using System.Collections.Concurrent; namespace Terminal.Gui.App; public partial class ApplicationImpl { /// public IDriver? Driver { get; set; } /// public bool Force16Colors { get; set; } /// public string ForceDriver { get; set; } = string.Empty; /// public List Sixel { get; } = new (); /// /// Creates the appropriate based on platform and driverName. /// /// /// /// /// private void CreateDriver (string? driverName) { PlatformID p = Environment.OSVersion.Platform; // Check component factory type first - this takes precedence over driverName bool factoryIsWindows = _componentFactory is IComponentFactory; bool factoryIsDotNet = _componentFactory is IComponentFactory; bool factoryIsUnix = _componentFactory is IComponentFactory; bool factoryIsFake = _componentFactory is IComponentFactory; // Then check driverName bool nameIsWindows = driverName?.Contains ("win", StringComparison.OrdinalIgnoreCase) ?? false; bool nameIsDotNet = driverName?.Contains ("dotnet", StringComparison.OrdinalIgnoreCase) ?? false; bool nameIsUnix = driverName?.Contains ("unix", StringComparison.OrdinalIgnoreCase) ?? false; bool nameIsFake = driverName?.Contains ("fake", StringComparison.OrdinalIgnoreCase) ?? false; // Decide which driver to use - component factory type takes priority if (factoryIsFake || (!factoryIsWindows && !factoryIsDotNet && !factoryIsUnix && nameIsFake)) { Coordinator = CreateSubcomponents (() => new FakeComponentFactory ()); _driverName = "fake"; } else if (factoryIsWindows || (!factoryIsDotNet && !factoryIsUnix && nameIsWindows)) { Coordinator = CreateSubcomponents (() => new WindowsComponentFactory ()); _driverName = "windows"; } else if (factoryIsDotNet || (!factoryIsWindows && !factoryIsUnix && nameIsDotNet)) { Coordinator = CreateSubcomponents (() => new NetComponentFactory ()); _driverName = "dotnet"; } else if (factoryIsUnix || (!factoryIsWindows && !factoryIsDotNet && nameIsUnix)) { Coordinator = CreateSubcomponents (() => new UnixComponentFactory ()); _driverName = "unix"; } else if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows) { Coordinator = CreateSubcomponents (() => new WindowsComponentFactory ()); _driverName = "windows"; } else if (p == PlatformID.Unix) { Coordinator = CreateSubcomponents (() => new UnixComponentFactory ()); _driverName = "unix"; } else { Logging.Information($"Falling back to dotnet driver."); Coordinator = CreateSubcomponents (() => new NetComponentFactory ()); _driverName = "dotnet"; } Logging.Trace ($"Created Subcomponents: {Coordinator}"); Coordinator.StartInputTaskAsync ().Wait (); if (Driver == null) { throw new ("Driver was null even after booting MainLoopCoordinator"); } } private readonly IComponentFactory? _componentFactory; /// /// INTERNAL: Gets or sets the main loop coordinator that orchestrates the application's event processing, /// input handling, and rendering pipeline. /// /// /// /// The is the central component responsible for: /// /// Managing the platform-specific input thread that reads from the console /// Coordinating the main application loop via /// Processing queued input events and translating them to Terminal.Gui events /// Managing the that handles rendering /// Executing scheduled timeouts and callbacks via /// /// /// /// The coordinator is created in based on the selected driver /// (Windows, Unix, .NET, or Fake) and is started by calling /// . /// /// internal IMainLoopCoordinator? Coordinator { get; private set; } /// /// INTERNAL: Creates a with the appropriate component factory /// for the specified input record type. /// /// /// Platform-specific input type: (.NET/Fake), /// (Windows), or (Unix). /// /// /// Factory function to create the component factory if /// is not of type . /// /// /// A configured with the input queue, /// main loop, timed events, and selected component factory. /// private IMainLoopCoordinator CreateSubcomponents (Func> fallbackFactory) where TInputRecord : struct { ConcurrentQueue inputQueue = new (); ApplicationMainLoop loop = new (); IComponentFactory cf; if (_componentFactory is IComponentFactory typedFactory) { cf = typedFactory; } else { cf = fallbackFactory (); } return new MainLoopCoordinator (_timedEvents, inputQueue, loop, cf); } internal void SubscribeDriverEvents () { ArgumentNullException.ThrowIfNull (Driver); Driver.SizeChanged += Driver_SizeChanged; Driver.KeyDown += Driver_KeyDown; Driver.KeyUp += Driver_KeyUp; Driver.MouseEvent += Driver_MouseEvent; } internal void UnsubscribeDriverEvents () { ArgumentNullException.ThrowIfNull (Driver); Driver.SizeChanged -= Driver_SizeChanged; Driver.KeyDown -= Driver_KeyDown; Driver.KeyUp -= Driver_KeyUp; Driver.MouseEvent -= Driver_MouseEvent; } private void Driver_KeyDown (object? sender, Key e) { Keyboard?.RaiseKeyDownEvent (e); } private void Driver_KeyUp (object? sender, Key e) { Keyboard?.RaiseKeyUpEvent (e); } private void Driver_MouseEvent (object? sender, MouseEventArgs e) { Mouse?.RaiseMouseEvent (e); } }