Skip to content

Add Kitty Keyboard Protocol support (Phase 1 + Phase 2 start)#4810

Merged
tig merged 50 commits intogui-cs:v2_developfrom
tig:feature/kitty
Mar 9, 2026
Merged

Add Kitty Keyboard Protocol support (Phase 1 + Phase 2 start)#4810
tig merged 50 commits intogui-cs:v2_developfrom
tig:feature/kitty

Conversation

@tig
Copy link
Copy Markdown
Collaborator

@tig tig commented Mar 7, 2026

Summary

  • Phase 1 complete: Kitty keyboard protocol detection, enable/disable lifecycle, CSI u parser, and compatibility mapping into the current Key model
  • Phase 2 started: Plan updated with detailed implementation steps for rich keyboard event model (KeyUp, KeyEventType, standalone modifier events)
  • Merged latest v2_develop and resolved all conflicts

Relates to #4809

What's included

Phase 1 — Compatibility plumbing

  • Kitty protocol query/enable/disable constants in EscSeqUtils
  • KittyKeyboardProtocolDetector with structured results
  • Startup detection wiring in MainLoopCoordinator
  • AnsiOutput enable/disable lifecycle with degraded mode safety
  • KittyKeyboardPattern parser (checked before generic CSI patterns)
  • Compatibility mapping: printable keys, modifiers, navigation, editing, function keys through F24
  • Comprehensive tests: detector, parser, input, lifecycle, and startup

Merge resolution

  • Resolved 8 merge conflicts from v2_develop integration
  • Fixed Trace ambiguity (System.Diagnostics.Trace vs Terminal.Gui.Tracing.Trace)
  • Adopted v2_develop's using Terminal.Gui.Tracing pattern and primary constructor style

Test plan

  • dotnet build --no-restore passes
  • dotnet test --project Tests/UnitTestsParallelizable --no-build — all pass
  • dotnet test --project Tests/UnitTests --no-build — all pass
  • Manual testing with kitty-capable terminal (Windows Terminal Preview 1.25+)

🤖 Generated with Claude Code

tig added 13 commits March 5, 2026 11:41
Refactor terminal attachment checks into Driver.IsAttachedToTerminal, which now handles platform-specific logic and honors the DisableRealDriverIO environment variable for test environments. Updated all drivers to use this unified method, and simplified AnsiTerminalHelper to delegate to it. Moved relevant P/Invoke code to Driver. Added comprehensive unit tests for all drivers and the environment variable gating. Introduced test.runsettings and Directory.Build.props changes to ensure DisableRealDriverIO is set during test runs, improving testability and consistency of degraded mode detection.
- Reformat method calls and declarations for readability
- Use C# pattern matching and switch expressions
- Refactor OutputBase properties to auto-properties
- Convert trivial methods to expression-bodied members
- Fix logic in OutputBase.Write, UnixInput init, and WindowsOutput error handling
- Remove AnsiTerminalHelper.IsAttachedToTerminal and related test
- Use explicit types for clarity
- Reformat and clarify P/Invoke signatures
- Update .DotSettings and documentation comments
- Improve maintainability and correctness throughout drivers
@tig tig marked this pull request as draft March 8, 2026 20:41
tig and others added 15 commits March 8, 2026 14:59
Add IsAttachedToTerminal to OutputBase and update all output drivers (AnsiOutput, NetOutput, UnixOutput, WindowsOutput) to check this property before performing terminal I/O. When not attached to a real terminal, output methods now return early, perform no-ops, or return default values. Constructors log lifecycle messages if no terminal is attached. Tests updated to verify no escape sequences or state changes occur in these scenarios. This prevents errors and unwanted output in redirected or non-interactive environments.
Move IsAttachedToTerminal checks after base logic in Output classes to ensure base behavior is always executed. Streamline and centralize terminal checks, reduce code duplication, and improve consistency across AnsiOutput, NetOutput, UnixOutput, and WindowsOutput. Adjust platform-specific logic and early returns for better maintainability and correct output buffer handling.
Centralize IsAttachedToTerminal logic in InputImpl<T> and update all input classes (AnsiInput, NetInput, UnixInput, WindowsInput) to use it for degraded mode detection and logging. Simplify AnsiOutput by removing redundant terminal checks and updating Kitty keyboard methods. Refactor MainLoopCoordinatorTests for modern C# syntax, restoring and improving Kitty protocol and error handling tests. Improves clarity, maintainability, and test reliability.
Refactor terminal attachment checks into Driver.IsAttachedToTerminal, which now handles platform-specific logic and honors the DisableRealDriverIO environment variable for test environments. Updated all drivers to use this unified method, and simplified AnsiTerminalHelper to delegate to it. Moved relevant P/Invoke code to Driver. Added comprehensive unit tests for all drivers and the environment variable gating. Introduced test.runsettings and Directory.Build.props changes to ensure DisableRealDriverIO is set during test runs, improving testability and consistency of degraded mode detection.
- Reformat method calls and declarations for readability
- Use C# pattern matching and switch expressions
- Refactor OutputBase properties to auto-properties
- Convert trivial methods to expression-bodied members
- Fix logic in OutputBase.Write, UnixInput init, and WindowsOutput error handling
- Remove AnsiTerminalHelper.IsAttachedToTerminal and related test
- Use explicit types for clarity
- Reformat and clarify P/Invoke signatures
- Update .DotSettings and documentation comments
- Improve maintainability and correctness throughout drivers
Add IsAttachedToTerminal to OutputBase and update all output drivers (AnsiOutput, NetOutput, UnixOutput, WindowsOutput) to check this property before performing terminal I/O. When not attached to a real terminal, output methods now return early, perform no-ops, or return default values. Constructors log lifecycle messages if no terminal is attached. Tests updated to verify no escape sequences or state changes occur in these scenarios. This prevents errors and unwanted output in redirected or non-interactive environments.
Move IsAttachedToTerminal checks after base logic in Output classes to ensure base behavior is always executed. Streamline and centralize terminal checks, reduce code duplication, and improve consistency across AnsiOutput, NetOutput, UnixOutput, and WindowsOutput. Adjust platform-specific logic and early returns for better maintainability and correct output buffer handling.
Centralize IsAttachedToTerminal logic in InputImpl<T> and update all input classes (AnsiInput, NetInput, UnixInput, WindowsInput) to use it for degraded mode detection and logging. Simplify AnsiOutput by removing redundant terminal checks and updating Kitty keyboard methods. Refactor MainLoopCoordinatorTests for modern C# syntax, restoring and improving Kitty protocol and error handling tests. Improves clarity, maintainability, and test reliability.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Moved and duplicated tests for DisableRealDriverIO env var and Driver.IsAttachedToTerminal from DriverTests to IntegrationTests. Also refactored test output usage to use the output parameter directly. This ensures environment variable handling is verified in both test contexts.
# Conflicts:
#	Terminal.Gui/Drivers/AnsiDriver/AnsiInput.cs
#	Terminal.Gui/Drivers/AnsiDriver/AnsiOutput.cs
#	Terminal.Gui/Drivers/DotNetDriver/NetInput.cs
#	Terminal.Gui/Drivers/UnixDriver/UnixInput.cs
#	Terminal.Gui/Drivers/WindowsDriver/WindowsInput.cs
#	Terminal.Gui/Drivers/WindowsDriver/WindowsOutput.cs
#	Tests/UnitTests/Application/MainLoopCoordinatorTests.cs
#	Tests/UnitTestsParallelizable/Application/MainLoopCoordinatorTests.cs
#	Tests/UnitTestsParallelizable/Drivers/Ansi/AnsiTerminalHelperTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
tig and others added 2 commits March 8, 2026 17:23
…l Logger

- Use ITestOutputHelper primary constructor for test output
- Replace manual Logging.Logger swap with TestLogging.BindTo scope
- Remove mock logger verification (exception propagation is the key assertion)
- Safe for parallel test execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tig tig marked this pull request as ready for review March 8, 2026 23:25
@tig tig requested review from BDisp and Copilot and removed request for Copilot March 8, 2026 23:25
@tig tig changed the title Fixes #4890 - Adds Kitty Keyboard Support Phase 1 of Fixing #4890 - Adds Kitty Keyboard Support Mar 8, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Phase-1 kitty keyboard protocol support to the ANSI driver (probe → enable → parse CSI u → disable on shutdown) and introduces a centralized “real terminal attached” detection/gating mechanism to make driver I/O deterministic in CI/test harnesses.

Changes:

  • Implement kitty keyboard protocol detection, enable/disable emission, and CSI u parsing with a Phase-1 compatibility mapping into the current Key model.
  • Centralize terminal-attachment detection in Driver.IsAttachedToTerminal(...) and use DisableRealDriverIO=1 to force degraded/no-op driver I/O in tests/CI.
  • Add/expand targeted unit + integration-style tests and wire CI workflows/runsettings to set DisableRealDriverIO.

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
plans/pr-4810-body.md PR body plan/summary for kitty keyboard Phase 1.
plans/kitty-keyboard-protocol-plan.md Detailed implementation plan and phased design notes.
Tests/test.runsettings Sets DisableRealDriverIO=1 for test runs via runsettings.
Tests/Directory.Build.props Points test projects at test.runsettings.
Tests/UnitTestsParallelizable/Drivers/Windows/WindowsInputOutputTests.cs Adds test asserting IsAttachedToTerminal is false in harness.
Tests/UnitTestsParallelizable/Drivers/Unix/UnixInputOutputTests.cs Adds test asserting IsAttachedToTerminal is false in harness.
Tests/UnitTestsParallelizable/Drivers/Dotnet/NetInputOutputTests.cs Adds test asserting IsAttachedToTerminal is false in harness.
Tests/UnitTestsParallelizable/Drivers/AnsiHandling/KittyKeyboardProtocolDetectorTests.cs New tests for kitty protocol detection + response parsing.
Tests/UnitTestsParallelizable/Drivers/AnsiHandling/AnsiKeyboardParserTests.cs Adds kitty CSI u parsing cases (printable, nav/edit, function keys).
Tests/UnitTestsParallelizable/Drivers/AnsiDriver/AnsiInputTestableTests.cs Integration-style tests injecting kitty sequences char-by-char.
Tests/UnitTestsParallelizable/Drivers/Ansi/AnsiTerminalHelperTests.cs New tests verifying env var propagation + IsAttachedToTerminal gating.
Tests/UnitTestsParallelizable/Drivers/Ansi/AnsiInputOutputTests.cs Adds low-level kitty enable/disable lifecycle assertions for AnsiOutput.
Tests/UnitTestsParallelizable/Application/MainLoopCoordinatorTests.cs Adds startup wiring test validating kitty probe/enable/disable flow.
Tests/UnitTests/Application/MainLoopCoordinatorTests.cs Removes/moves prior test content (file now minimal).
Tests/IntegrationTests/FluentTests/TestContextTests.cs Adds env-var gating assertions in integration tests.
Terminal.sln.DotSettings Adds csbi to dictionary (spellchecker exception).
Terminal.Gui/Drivers/WindowsDriver/WindowsOutput.cs Gates Windows output operations on terminal attachment; refactors formatting; adds fallback sizing behavior.
Terminal.Gui/Drivers/WindowsDriver/WindowsInput.cs Gates Windows input initialization on terminal attachment; refactors P/Invoke formatting.
Terminal.Gui/Drivers/UnixDriver/UnixTerminalHelper.cs Uses Driver.IsAttachedToTerminal instead of ANSI helper for suspend gating.
Terminal.Gui/Drivers/UnixDriver/UnixOutput.cs Adds terminal-attachment gating for output methods and sizing fallback.
Terminal.Gui/Drivers/UnixDriver/UnixInput.cs Adds terminal-attachment gating; reorganizes init flow; minor cleanups.
Terminal.Gui/Drivers/UnixDriver/UnixIOHelper.cs Formatting/interop signature tweaks; small logic/style improvements.
Terminal.Gui/Drivers/Output/OutputBase.cs Adds cached IsAttachedToTerminal; refactors properties/formatting; minor logic reshaping.
Terminal.Gui/Drivers/Input/InputImpl.cs Adds cached IsAttachedToTerminal for input implementations.
Terminal.Gui/Drivers/DriverImpl.cs Persists kitty protocol detection/enabled flags on driver instance.
Terminal.Gui/Drivers/Driver.cs Adds centralized IsAttachedToTerminal and env var override; refactors Force16Colors.
Terminal.Gui/Drivers/DotNetDriver/NetOutput.cs Adds terminal-attachment gating in ctor/write/size; minor refactors.
Terminal.Gui/Drivers/DotNetDriver/NetInput.cs Adds terminal-attachment gating and minor refactors.
Terminal.Gui/Drivers/AnsiHandling/KittyKeyboardProtocolDetector.cs New detector + KittyKeyboardProtocolResult and response parsing.
Terminal.Gui/Drivers/AnsiHandling/KittyKeyboardPattern.cs New CSI u parser pattern mapping kitty codes/modifiers into Key.
Terminal.Gui/Drivers/AnsiHandling/EscSeqUtils/EscSeqUtils.cs Adds kitty query/enable/disable sequences + Phase-1 flag constant(s).
Terminal.Gui/Drivers/AnsiHandling/AnsiResponseExpectation.cs Refactors expectation matching to avoid regex and support kitty query metadata.
Terminal.Gui/Drivers/AnsiHandling/AnsiKeyboardParser.cs Registers kitty pattern ahead of broader CSI patterns.
Terminal.Gui/Drivers/AnsiDriver/AnsiTerminalHelper.cs Removes duplicated terminal-attachment detection (now centralized).
Terminal.Gui/Drivers/AnsiDriver/AnsiOutput.cs Adds kitty enable/disable lifecycle on output; integrates degraded-mode gating adjustments.
Terminal.Gui/Drivers/AnsiDriver/AnsiInput.cs Switches to centralized terminal-attachment gating in init paths.
Terminal.Gui/App/MainLoop/MainLoopCoordinator.cs Wires kitty protocol detection and conditional enable into driver startup.
.github/workflows/unit-tests.yml Sets DisableRealDriverIO=1 in CI for unit tests.
.github/workflows/stress-tests.yml Sets DisableRealDriverIO=1 in CI for stress tests.
.github/workflows/integration-tests.yml Sets DisableRealDriverIO=1 in CI for integration tests.
Comments suppressed due to low confidence (1)

Terminal.Gui/Drivers/DotNetDriver/NetOutput.cs:175

  • SetCursorPositionImpl writes directly to Console.Out via EscSeqUtils.CSI_WriteCursorPosition even when IsAttachedToTerminal is false, bypassing the new degraded-mode gating in Write(...). Add an IsAttachedToTerminal guard (or route through Write(...)) so cursor movement is a true no-op when real driver I/O is disabled/redirected.
    /// <inheritdoc/>
    protected override bool SetCursorPositionImpl (int col, int row)
    {
        if (_currentCursor.Position is { } && _currentCursor.Position.Value.X == col && _currentCursor.Position.Value.Y == row)
        {
            return false;
        }

        if (_isWinPlatform)
        {
            try
            {
                Console.SetCursorPosition (col, row);
            }
            catch
            {
                // Could happen that the windows is still resizing and the col is bigger than Console.WindowWidth.
            }

            return true;
        }

        // + 1 is needed because non-Windows is based on 1 instead of 0 and
        // Console.CursorTop/CursorLeft isn't reliable.
        EscSeqUtils.CSI_WriteCursorPosition (Console.Out, row + 1, col + 1);

        return true;

Comment thread Tests/UnitTestsParallelizable/Application/MainLoopCoordinatorTests.cs Outdated
Comment thread Tests/UnitTests/Application/MainLoopCoordinatorTests.cs Outdated
Comment thread Terminal.Gui/Drivers/WindowsDriver/WindowsInput.cs
Comment thread Terminal.Gui/Drivers/DotNetDriver/NetOutput.cs
Comment thread Tests/UnitTestsParallelizable/Drivers/Ansi/AnsiInputOutputTests.cs
Copy link
Copy Markdown
Collaborator

@BDisp BDisp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic. Very good implementation.

tig and others added 14 commits March 9, 2026 08:21
Refactored tracing calls in input classes to remove unnecessary string interpolation and ensure consistent usage of Trace.Lifecycle. Added early return in AnsiOutput for degraded platforms. Simplified window size comparison in WindowsOutput. Cleaned up imports and removed redundant code in test files, including refactoring test output usage for clarity.
Remove commented-out logging/tracing statements from AnsiInput, AnsiOutput, and WindowsOutput for cleaner code. Refactor AnsiOutput to use an auto-property for KittyKeyboardEnabledFlags and update related logic. Add a descriptive trace message to AnsiOutput.Dispose(). Replace commented exception in WindowsOutput with a trace log on resize failure. Minor doc and formatting improvements in NetInput.
AnsiOutput.EnableKittyKeyboard now skips enablement when the platform is Degraded, making it a no-op in such environments. Updated related test to focus on detection rather than enable/disable, renamed the test for clarity, and adjusted assertions to match the new behavior. Removed checks for escape sequences that are not emitted in degraded mode.
Adds detailed implementation steps for Phase 2 (Rich Keyboard Event Model)
including Key.EventType, KeyUp pipeline, Windows/kitty driver integration,
standalone modifier events, and view-level keyboard updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tig tig changed the title Phase 1 of Fixing #4890 - Adds Kitty Keyboard Support Add Kitty Keyboard Protocol support (Phase 1 + Phase 2 start) Mar 9, 2026
@tig tig merged commit d67adcc into gui-cs:v2_develop Mar 9, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants