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.
Terminal.Gui provides console driver implementations optimized for different platforms:
dotnet) - A cross-platform driver that uses the .NET System.Console API. Works on all platforms (Windows, macOS, Linux). Best for maximum compatibility.windows) - A Windows-optimized driver that uses native Windows Console APIs for enhanced performance and platform-specific features.unix) - A Unix/Linux/macOS-optimized driver that uses platform-specific APIs for better integration and performance.fake) - A mock driver designed for unit testing. Simulates console behavior without requiring a real terminal.The appropriate driver is automatically selected based on the platform when you call Application.Init():
WindowsDriverUnixDriverYou 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"
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 FakeDriverEach driver is composed of specialized components, each with a single responsibility:
Reads raw console input events from the terminal. The generic type T represents the platform-specific input type:
ConsoleKeyInfo for DotNetDriver and FakeDriverWindowsConsole.InputRecord for WindowsDriverchar for UnixDriverRuns on a dedicated input thread to avoid blocking the UI.
Renders the output buffer to the terminal. Handles:
Translates raw console input into Terminal.Gui events:
Key events (handles keyboard input)MouseEventArgs for mouse inputManages the screen buffer and drawing operations:
Contents array (what should be displayed)AddRune(), AddStr(), Move(), FillRect()Detects terminal size changes and raises SizeChanged events when the terminal is resized.
A unified facade that implements IDriver and coordinates all the components. This is what gets assigned to Application.Driver.
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, runs IInput.Run() which continuously reads console input and queues it into a thread-safe ConcurrentQueue<T>.
Main UI Thread: Runs ApplicationMainLoop.Iteration() which:
IInputProcessorIOutputThis separation ensures that input is never lost and the UI remains responsive during intensive operations.
When you call Application.Init():
MainLoopCoordinator<T> with the appropriate ComponentFactory<T>IInput<T>IOutputDriverFacade<T> and assigns to IApplication.DriverWhen IApplication.Shutdown() is called:
IOutput is disposedThe main driver interface that the framework uses internally. Provides:
Screen, Cols, Rows, ContentsAddRune(), AddStr(), Move(), FillRect()SetCursorVisibility(), UpdateCursor()CurrentAttribute, SetAttribute(), MakeColor()Clip propertyKeyDown, KeyUp, MouseEvent, SizeChangedSupportsTrueColor, Force16Colors, ClipboardNote: The driver is internal to Terminal.Gui. View classes should not access Driver directly. Instead:
Terminal.Gui/ViewBase/) can access Driver when needed for framework implementationSystem.Console for all I/O operationsConsoleKeyInfo via Console.ReadKey()Console.Write() and ANSI escape sequencesInputRecord structs via ReadConsoleInputWhen running in Visual Studio's debug console (VSDebugConsole.exe), WindowsDriver detects the VSAPPIDNAME environment variable and automatically adjusts its behavior:
This ensures Terminal.Gui applications can be debugged directly in Visual Studio without rendering issues.
char data from terminalFakeConsole for all operationsIApplication.ForceDriver is fakeImportant: View subclasses should not access Application.Driver. Use the View APIs instead:
View.Move(col, row) for positioningView.AddRune() and View.AddStr() for drawingView.App.Screen for screen dimensions