diff --git a/src/terminal/parser/IStateMachineEngine.hpp b/src/terminal/parser/IStateMachineEngine.hpp index 371ba96c1d5..3f0356ebb84 100644 --- a/src/terminal/parser/IStateMachineEngine.hpp +++ b/src/terminal/parser/IStateMachineEngine.hpp @@ -28,6 +28,8 @@ namespace Microsoft::Console::VirtualTerminal IStateMachineEngine& operator=(const IStateMachineEngine&) = default; IStateMachineEngine& operator=(IStateMachineEngine&&) = default; + virtual bool EncounteredWin32InputModeSequence() const noexcept = 0; + virtual bool ActionExecute(const wchar_t wch) = 0; virtual bool ActionExecuteFromEscape(const wchar_t wch) = 0; virtual bool ActionPrint(const wchar_t wch) = 0; diff --git a/src/terminal/parser/InputStateMachineEngine.cpp b/src/terminal/parser/InputStateMachineEngine.cpp index 7ea26ce9c84..cdc270c1858 100644 --- a/src/terminal/parser/InputStateMachineEngine.cpp +++ b/src/terminal/parser/InputStateMachineEngine.cpp @@ -102,6 +102,11 @@ InputStateMachineEngine::InputStateMachineEngine(std::unique_ptrWriteCtrlKey(key); + _encounteredWin32InputModeSequence = true; break; } default: diff --git a/src/terminal/parser/InputStateMachineEngine.hpp b/src/terminal/parser/InputStateMachineEngine.hpp index 74af20a9b39..b0687f6a0b3 100644 --- a/src/terminal/parser/InputStateMachineEngine.hpp +++ b/src/terminal/parser/InputStateMachineEngine.hpp @@ -132,6 +132,7 @@ namespace Microsoft::Console::VirtualTerminal InputStateMachineEngine(std::unique_ptr pDispatch, const bool lookingForDSR); + bool EncounteredWin32InputModeSequence() const noexcept override; void SetLookingForDSR(const bool looking) noexcept; bool ActionExecute(const wchar_t wch) override; @@ -167,6 +168,7 @@ namespace Microsoft::Console::VirtualTerminal const std::unique_ptr _pDispatch; std::function _pfnFlushToInputQueue; bool _lookingForDSR; + bool _encounteredWin32InputModeSequence = false; DWORD _mouseButtonState = 0; std::chrono::milliseconds _doubleClickTime; std::optional _lastMouseClickPos{}; diff --git a/src/terminal/parser/OutputStateMachineEngine.cpp b/src/terminal/parser/OutputStateMachineEngine.cpp index e744c95ad08..68a45916df4 100644 --- a/src/terminal/parser/OutputStateMachineEngine.cpp +++ b/src/terminal/parser/OutputStateMachineEngine.cpp @@ -23,6 +23,11 @@ OutputStateMachineEngine::OutputStateMachineEngine(std::unique_ptr pDispatch); + bool EncounteredWin32InputModeSequence() const noexcept override; + bool ActionExecute(const wchar_t wch) override; bool ActionExecuteFromEscape(const wchar_t wch) override; diff --git a/src/terminal/parser/stateMachine.cpp b/src/terminal/parser/stateMachine.cpp index 643409afda5..88727ad6ec2 100644 --- a/src/terminal/parser/stateMachine.cpp +++ b/src/terminal/parser/stateMachine.cpp @@ -2144,9 +2144,15 @@ void StateMachine::ProcessString(const std::wstring_view string) // which breaks up many of our longer sequences, like our Win32InputMode ones. // // As a heuristic, this code specifically checks for a trailing Esc or Alt+key. + // If we encountered a win32-input-mode sequence before, we know that our \x1b[?9001h + // request to enable them was successful. While a client may still send \x1b{some char} + // intentionally, it's far more likely now that we're looking at a broken up sequence. + // The most common win32-input-mode is ConPTY itself after all, and we never emit + // \x1b{some char} once it's enabled. if (_isEngineForInput) { - if (run.size() <= 2 && run.front() == L'\x1b') + const auto win32 = _engine->EncounteredWin32InputModeSequence(); + if (!win32 && run.size() <= 2 && run.front() == L'\x1b') { _EnterGround(); if (run.size() == 1) diff --git a/src/terminal/parser/ut_parser/StateMachineTest.cpp b/src/terminal/parser/ut_parser/StateMachineTest.cpp index 4893964c249..d7e49537207 100644 --- a/src/terminal/parser/ut_parser/StateMachineTest.cpp +++ b/src/terminal/parser/ut_parser/StateMachineTest.cpp @@ -40,6 +40,11 @@ class Microsoft::Console::VirtualTerminal::TestStateMachineEngine : public IStat dcsDataString.clear(); } + bool EncounteredWin32InputModeSequence() const noexcept override + { + return false; + } + bool ActionExecute(const wchar_t wch) override { executed += wch;