* Pulled from v2_release * Refactor migration guide for Terminal.Gui v2 Restructured and expanded the migration guide to provide a comprehensive resource for transitioning from Terminal.Gui v1 to v2. Key updates include: - Added a Table of Contents for easier navigation. - Summarized major architectural changes in v2, including the instance-based application model, IRunnable architecture, and 24-bit TrueColor support. - Updated examples to reflect new patterns, such as initializers replacing constructors and explicit disposal using `IDisposable`. - Documented changes to the layout system, including the removal of `Absolute`/`Computed` styles and the introduction of `Viewport`. - Standardized event patterns to use `object sender, EventArgs args`. - Detailed updates to the Keyboard, Mouse, and Navigation APIs, including configurable key bindings and viewport-relative mouse coordinates. - Replaced legacy components like `ScrollView` and `ContextMenu` with built-in scrolling and `PopoverMenu`. - Clarified disposal rules and introduced best practices for resource management. - Provided a complete migration example and a summary of breaking changes. This update aims to simplify the migration process by addressing breaking changes, introducing new features, and aligning with modern .NET conventions. * Refactor to use Application.Instance for lifecycle management Replaced all occurrences of `ApplicationImpl.Instance` with the new `Application.Instance` property across the codebase to align with the updated application lifecycle model. Encapsulated the `ApplicationImpl` class by making it `internal`, ensuring it is no longer directly accessible outside its assembly. Introduced the `[Obsolete]` `Application.Instance` property as a backward-compatible singleton for the legacy static `Application` model, while encouraging the use of `Application.Create()` for new code. Updated `MessageBox` methods to use `Application.Instance` for consistent modal dialog management. Improved documentation to reflect these changes and emphasize the transition to the instance-based application model. Performed code cleanup in multiple classes to ensure consistency and maintainability. These changes maintain backward compatibility while preparing the codebase for the eventual removal of the legacy `ApplicationImpl` class. * Fix doc bug * - Removed obsolete `.cd` class diagram files. - Introduced `IRunnable` interface for decoupling component execution. - Added fluent API for running dialogs and retrieving results. - Enhanced `View` with `App` and `Driver` properties for better decoupling. - Improved testability with support for mock and real applications. - Implemented `IDisposable` for proper resource cleanup. - Replaced `RunnableSessionStack` with `SessionStack` for session management. - Updated driver architecture to align with the new model. - Scoped `IKeyboard` to application contexts for modularity. - Updated documentation with migration strategies and best practices. These changes modernize the library, improve maintainability, and align with current development practices.
9.6 KiB
Cross-Platform Driver Model
Overview
The driver model is the mechanism by which Terminal.Gui supports multiple platforms. Windows, Mac, Linux, and unit test environments are all supported through a modular, component-based architecture.
Terminal.Gui v2 uses a sophisticated driver architecture that separates concerns and enables platform-specific optimizations while maintaining a consistent API. The architecture is based on the Component Factory pattern and uses multi-threading to ensure responsive input handling.
Available Drivers
Terminal.Gui provides console driver implementations optimized for different platforms:
- DotNetDriver (
dotnet) - A cross-platform driver that uses the .NETSystem.ConsoleAPI. Works on all platforms (Windows, macOS, Linux). Best for maximum compatibility. - WindowsDriver (
windows) - A Windows-optimized driver that uses native Windows Console APIs for enhanced performance and platform-specific features. - UnixDriver (
unix) - A Unix/Linux/macOS-optimized driver that uses platform-specific APIs for better integration and performance. - FakeDriver (
fake) - A mock driver designed for unit testing. Simulates console behavior without requiring a real terminal.
Automatic Driver Selection
The appropriate driver is automatically selected based on the platform when you call Application.Init():
- Windows (Win32NT, Win32S, Win32Windows) →
WindowsDriver - Unix/Linux/macOS →
UnixDriver
Explicit Driver Selection
You can explicitly specify a driver in three ways:
// Method 1: Set ForceDriver property before Init
Application.ForceDriver = "dotnet";
Application.Init();
// Method 2: Pass driver name to Init
Application.Init(driverName: "unix");
// Method 3: Pass a custom IDriver instance
var customDriver = new MyCustomDriver();
Application.Init(driver: customDriver);
Valid driver names: "dotnet", "windows", "unix", "fake"
Architecture
Component Factory Pattern
The v2 driver architecture uses the Component Factory pattern to create platform-specific components. Each driver has a corresponding factory:
NetComponentFactory- Creates components for DotNetDriverWindowsComponentFactory- Creates components for WindowsDriverUnixComponentFactory- Creates components for UnixDriverFakeComponentFactory- Creates components for FakeDriver
Core Components
Each driver is composed of specialized components, each with a single responsibility:
IInput<T>
Reads raw console input events from the terminal. The generic type T represents the platform-specific input type:
ConsoleKeyInfofor DotNetDriver and FakeDriverWindowsConsole.InputRecordfor WindowsDrivercharfor UnixDriver
Runs on a dedicated input thread to avoid blocking the UI.
IOutput
Renders the output buffer to the terminal. Handles:
- Writing text and ANSI escape sequences
- Setting cursor position
- Managing cursor visibility
- Detecting terminal window size
IInputProcessor
Translates raw console input into Terminal.Gui events:
- Converts raw input to
Keyevents (handles keyboard input) - Parses ANSI escape sequences (mouse events, special keys)
- Generates
MouseEventArgsfor mouse input - Handles platform-specific key mappings
IOutputBuffer
Manages the screen buffer and drawing operations:
- Maintains the
Contentsarray (what should be displayed) - Provides methods like
AddRune(),AddStr(),Move(),FillRect() - Handles clipping regions
- Tracks dirty regions for efficient rendering
IWindowSizeMonitor
Detects terminal size changes and raises SizeChanged events when the terminal is resized.
DriverFacade<T>
A unified facade that implements IDriver and coordinates all the components. This is what gets assigned to Application.Driver.
Threading Model
The driver architecture employs a multi-threaded design for optimal responsiveness:
┌─────────────────────────────────────────────┐
│ IApplication.Init() │
│ Creates MainLoopCoordinator<T> with │
│ ComponentFactory<T> │
└────────────────┬────────────────────────────┘
│
├──────────────────┬───────────────────┐
│ │ │
┌────────▼────────┐ ┌──────▼─────────┐ ┌──────▼──────────┐
│ Input Thread │ │ Main UI Thread│ │ Driver │
│ │ │ │ │ Facade │
│ IInput │ │ ApplicationMain│ │ │
│ reads console │ │ Loop processes │ │ Coordinates all │
│ input async │ │ events, layout,│ │ components │
│ into queue │ │ and rendering │ │ │
└─────────────────┘ └────────────────┘ └─────────────────┘
-
Input Thread: Started by
MainLoopCoordinator, runsIInput.Run()which continuously reads console input and queues it into a thread-safeConcurrentQueue<T>. -
Main UI Thread: Runs
ApplicationMainLoop.Iteration()which:- Processes input from the queue via
IInputProcessor - Executes timeout callbacks
- Checks for UI changes (layout/drawing)
- Renders updates via
IOutput
- Processes input from the queue via
This separation ensures that input is never lost and the UI remains responsive during intensive operations.
Initialization Flow
When you call Application.Init():
- IApplication.Init() is invoked
- Creates a
MainLoopCoordinator<T>with the appropriateComponentFactory<T> - MainLoopCoordinator.StartAsync() begins:
- Starts the input thread which creates
IInput<T> - Initializes the main UI loop which creates
IOutput - Creates
DriverFacade<T>and assigns toIApplication.Driver - Waits for both threads to be ready
- Starts the input thread which creates
- Returns control to the application
Shutdown Flow
When IApplication.Shutdown() is called:
- Cancellation token is triggered
- Input thread exits its read loop
IOutputis disposed- Main thread waits for input thread to complete
- All resources are cleaned up
Component Interfaces
IDriver
The main driver interface that the framework uses internally. Provides:
- Screen Management:
Screen,Cols,Rows,Contents - Drawing Operations:
AddRune(),AddStr(),Move(),FillRect() - Cursor Management:
SetCursorVisibility(),UpdateCursor() - Attribute Management:
CurrentAttribute,SetAttribute(),MakeColor() - Clipping:
Clipproperty - Events:
KeyDown,KeyUp,MouseEvent,SizeChanged - Platform Features:
SupportsTrueColor,Force16Colors,Clipboard
Note: The driver is internal to Terminal.Gui. View classes should not access Driver directly. Instead:
- Use @Terminal.Gui.App.Application.Screen to get screen dimensions
- Use @Terminal.Gui.ViewBase.View.Move for positioning (with viewport-relative coordinates)
- Use @Terminal.Gui.ViewBase.View.AddRune and @Terminal.Gui.ViewBase.View.AddStr for drawing
- ViewBase infrastructure classes (in
Terminal.Gui/ViewBase/) can access Driver when needed for framework implementation
Platform-Specific Details
DotNetDriver (NetComponentFactory)
- Uses
System.Consolefor all I/O operations - Input: Reads
ConsoleKeyInfoviaConsole.ReadKey() - Output: Uses
Console.Write()and ANSI escape sequences - Works on all platforms but may have limited features
- Best for maximum compatibility and simple applications
WindowsDriver (WindowsComponentFactory)
- Uses Windows Console API via P/Invoke
- Input: Reads
InputRecordstructs viaReadConsoleInput - Output: Uses Windows Console API for optimal performance
- Supports Windows-specific features and better performance
- Automatically selected on Windows platforms
Visual Studio Debug Console Support
When running in Visual Studio's debug console (VSDebugConsole.exe), WindowsDriver detects the VSAPPIDNAME environment variable and automatically adjusts its behavior:
- Disables the alternative screen buffer (which is not supported in VS debug console)
- Preserves the original console colors on startup
- Restores the original colors and clears the screen on shutdown
This ensures Terminal.Gui applications can be debugged directly in Visual Studio without rendering issues.
UnixDriver (UnixComponentFactory)
- Uses Unix/Linux terminal APIs
- Input: Reads raw
chardata from terminal - Output: Uses ANSI escape sequences
- Supports Unix-specific features
- Automatically selected on Unix/Linux/macOS platforms
FakeDriver (FakeComponentFactory)
- Simulates console behavior for unit testing
- Uses
FakeConsolefor all operations - Allows injection of predefined input
- Captures output for verification
- Always used when
IApplication.ForceDriverisfake
Important: View subclasses should not access Application.Driver. Use the View APIs instead:
View.Move(col, row)for positioningView.AddRune()andView.AddStr()for drawingView.App.Screenfor screen dimensions
See Also
- @Terminal.Gui.Drivers - API Reference
- @Terminal.Gui.App.IApplication - Application interface
- @Terminal.Gui.App.MainLoopCoordinator`1 - Main loop coordination