diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index e69b42e373..6d484b6052 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -132,6 +132,7 @@ public: #pragma region ITerminalApi // These methods are defined in TerminalApi.cpp void ReturnResponse(const std::wstring_view response) override; + bool IsConPTY() const noexcept override; Microsoft::Console::VirtualTerminal::StateMachine& GetStateMachine() noexcept override; BufferState GetBufferAndViewport() noexcept override; void SetViewportPosition(const til::point position) noexcept override; diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index e87dc765f2..bf7ed1ea8d 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -28,6 +28,11 @@ void Terminal::ReturnResponse(const std::wstring_view response) } } +bool Terminal::IsConPTY() const noexcept +{ + return false; +} + Microsoft::Console::VirtualTerminal::StateMachine& Terminal::GetStateMachine() noexcept { return *_stateMachine; diff --git a/src/host/outputStream.cpp b/src/host/outputStream.cpp index 4f359dba13..e0931b5847 100644 --- a/src/host/outputStream.cpp +++ b/src/host/outputStream.cpp @@ -48,6 +48,12 @@ void ConhostInternalGetSet::ReturnResponse(const std::wstring_view response) _io.GetActiveInputBuffer()->WriteString(response); } +bool ConhostInternalGetSet::IsConPTY() const noexcept +{ + const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); + return gci.IsInVtIoMode(); +} + // Routine Description: // - Retrieves the state machine for the active output buffer. // Arguments: diff --git a/src/host/outputStream.hpp b/src/host/outputStream.hpp index c80df20ffe..f358d9941d 100644 --- a/src/host/outputStream.hpp +++ b/src/host/outputStream.hpp @@ -31,6 +31,7 @@ public: void ReturnResponse(const std::wstring_view response) override; + bool IsConPTY() const noexcept override; Microsoft::Console::VirtualTerminal::StateMachine& GetStateMachine() override; BufferState GetBufferAndViewport() override; void SetViewportPosition(const til::point position) override; diff --git a/src/terminal/adapter/ITerminalApi.hpp b/src/terminal/adapter/ITerminalApi.hpp index fb613c4e12..c289543c3a 100644 --- a/src/terminal/adapter/ITerminalApi.hpp +++ b/src/terminal/adapter/ITerminalApi.hpp @@ -46,6 +46,7 @@ namespace Microsoft::Console::VirtualTerminal bool isMainBuffer; }; + virtual bool IsConPTY() const noexcept = 0; virtual StateMachine& GetStateMachine() = 0; virtual BufferState GetBufferAndViewport() = 0; virtual void SetViewportPosition(const til::point position) = 0; diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index d49bbfad8f..67bfa4445b 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -2073,6 +2073,13 @@ void AdaptDispatch::SetAnsiMode(const bool ansiMode) // CSI = flags ; mode u - Sets kitty keyboard protocol flags void AdaptDispatch::SetKittyKeyboardProtocol(const VTParameter flags, const VTParameter mode) noexcept { + // Avoid setting KKP flags in `_terminalInput` when we're ConPTY. Otherwise, we'd be translating + // W32IM to KKP, even when KKP is not supported by the hosting terminal (possibly intentionally). + if (_api.IsConPTY()) + { + return; + } + const auto kittyFlags = gsl::narrow_cast(flags.value_or(0)); const auto KittyKeyboardProtocol = static_cast(mode.value_or(1)); _terminalInput.SetKittyKeyboardProtocol(kittyFlags, KittyKeyboardProtocol); @@ -2081,6 +2088,11 @@ void AdaptDispatch::SetKittyKeyboardProtocol(const VTParameter flags, const VTPa // CSI ? u - Queries current kitty keyboard protocol flags void AdaptDispatch::QueryKittyKeyboardProtocol() { + if (_api.IsConPTY()) + { + return; + } + const auto flags = static_cast(_terminalInput.GetKittyFlags()); _ReturnCsiResponse(fmt::format(FMT_COMPILE(L"?{}u"), flags)); } @@ -2088,6 +2100,11 @@ void AdaptDispatch::QueryKittyKeyboardProtocol() // CSI > flags u - Pushes current kitty keyboard flags onto the stack and sets new flags void AdaptDispatch::PushKittyKeyboardProtocol(const VTParameter flags) { + if (_api.IsConPTY()) + { + return; + } + const auto kittyFlags = gsl::narrow_cast(flags.value_or(0)); _terminalInput.PushKittyFlags(kittyFlags); } @@ -2095,6 +2112,11 @@ void AdaptDispatch::PushKittyKeyboardProtocol(const VTParameter flags) // CSI < count u - Pops one or more entries from the kitty keyboard stack void AdaptDispatch::PopKittyKeyboardProtocol(const VTParameter count) { + if (_api.IsConPTY()) + { + return; + } + const auto popCount = static_cast(count.value_or(1)); _terminalInput.PopKittyFlags(popCount); } diff --git a/src/terminal/adapter/ut_adapter/adapterTest.cpp b/src/terminal/adapter/ut_adapter/adapterTest.cpp index 9edc155e99..bd79a98844 100644 --- a/src/terminal/adapter/ut_adapter/adapterTest.cpp +++ b/src/terminal/adapter/ut_adapter/adapterTest.cpp @@ -76,6 +76,11 @@ public: } } + bool IsConPTY() const noexcept override + { + return false; + } + StateMachine& GetStateMachine() override { return *_stateMachine; diff --git a/src/terminal/input/terminalInput.cpp b/src/terminal/input/terminalInput.cpp index 9755b0da8c..2c2401cd80 100644 --- a/src/terminal/input/terminalInput.cpp +++ b/src/terminal/input/terminalInput.cpp @@ -228,7 +228,8 @@ TerminalInput::OutputType TerminalInput::HandleKey(const INPUT_RECORD& event) // GH#4999 - If we're in win32-input mode, skip straight to doing that. // Since this mode handles all types of key events, do nothing else. // - // The kitty keyboard protocol takes precedence, because it's cross-platform. + // ConPTY assumes that W32IM always remains enabled. We have to prefer + // the kitty keyboard protocol, because otherwise it would never be used. if (_inputMode.test(Mode::Win32) && !_forceDisableWin32InputMode && !_kittyFlags) { return _makeWin32Output(event.Event.KeyEvent);