From febde50da87d758263b6d1230ee158ca9916e08a Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Thu, 16 Apr 2020 12:32:17 -0700 Subject: [PATCH 1/3] add SS3 enc. for arrows, home, end --- src/terminal/parser/InputStateMachineEngine.cpp | 8 +++++++- src/terminal/parser/InputStateMachineEngine.hpp | 14 ++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/terminal/parser/InputStateMachineEngine.cpp b/src/terminal/parser/InputStateMachineEngine.cpp index 0178ba0c7b3..9f07d418650 100644 --- a/src/terminal/parser/InputStateMachineEngine.cpp +++ b/src/terminal/parser/InputStateMachineEngine.cpp @@ -73,7 +73,13 @@ struct Ss3ToVkey short vkey; }; -static constexpr std::array s_ss3Map = { +static constexpr std::array s_ss3Map = { + Ss3ToVkey{ Ss3ActionCodes::ArrowUp, VK_UP }, + Ss3ToVkey{ Ss3ActionCodes::ArrowDown, VK_DOWN }, + Ss3ToVkey{ Ss3ActionCodes::ArrowRight, VK_RIGHT }, + Ss3ToVkey{ Ss3ActionCodes::ArrowLeft, VK_LEFT }, + Ss3ToVkey{ Ss3ActionCodes::End, VK_END }, + Ss3ToVkey{ Ss3ActionCodes::Home, VK_HOME }, Ss3ToVkey{ Ss3ActionCodes::SS3_F1, VK_F1 }, Ss3ToVkey{ Ss3ActionCodes::SS3_F2, VK_F2 }, Ss3ToVkey{ Ss3ActionCodes::SS3_F3, VK_F3 }, diff --git a/src/terminal/parser/InputStateMachineEngine.hpp b/src/terminal/parser/InputStateMachineEngine.hpp index f6ab555c6a4..a4c1cef366b 100644 --- a/src/terminal/parser/InputStateMachineEngine.hpp +++ b/src/terminal/parser/InputStateMachineEngine.hpp @@ -116,14 +116,12 @@ namespace Microsoft::Console::VirtualTerminal enum class Ss3ActionCodes : wchar_t { - // The "Cursor Keys" are sometimes sent as a SS3 in "application mode" - // But for now we'll only accept them as Normal Mode sequences, as CSI's. - // ArrowUp = L'A', - // ArrowDown = L'B', - // ArrowRight = L'C', - // ArrowLeft = L'D', - // Home = L'H', - // End = L'F', + ArrowUp = L'A', + ArrowDown = L'B', + ArrowRight = L'C', + ArrowLeft = L'D', + Home = L'H', + End = L'F', SS3_F1 = L'P', SS3_F2 = L'Q', SS3_F3 = L'R', From 3e94cd75b2098b1affd60cd07699ccd8261838a1 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Thu, 16 Apr 2020 13:14:01 -0700 Subject: [PATCH 2/3] revert the hacky bit of #4913 --- src/terminal/adapter/adaptDispatch.cpp | 56 ++++++++------------------ 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index ffcc448f0b9..3be87be04f9 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -1056,11 +1056,8 @@ bool AdaptDispatch::SetKeypadMode(const bool fApplicationMode) bool success = true; success = _pConApi->PrivateSetKeypadMode(fApplicationMode); - // If we're a conpty, AND WE'RE IN VT INPUT MODE, always return false - // The VT Input mode check is to work around ssh.exe v7.7, which uses VT - // output, but not Input. Once the conpty supports these types of input, - // this check can be removed. See GH#4911 - if (_pConApi->IsConsolePty() && _pConApi->PrivateIsVtInputEnabled()) + // If we're a conpty, always return false + if (_pConApi->IsConsolePty()) { return false; } @@ -1078,11 +1075,8 @@ bool AdaptDispatch::SetCursorKeysMode(const bool applicationMode) bool success = true; success = _pConApi->PrivateSetCursorKeysMode(applicationMode); - // If we're a conpty, AND WE'RE IN VT INPUT MODE, always return false - // The VT Input mode check is to work around ssh.exe v7.7, which uses VT - // output, but not Input. Once the conpty supports these types of input, - // this check can be removed. See GH#4911 - if (_pConApi->IsConsolePty() && _pConApi->PrivateIsVtInputEnabled()) + // If we're a conpty, always return false + if (_pConApi->IsConsolePty()) { return false; } @@ -1878,11 +1872,8 @@ bool AdaptDispatch::EnableVT200MouseMode(const bool enabled) bool success = true; success = _pConApi->PrivateEnableVT200MouseMode(enabled); - // If we're a conpty, AND WE'RE IN VT INPUT MODE, always return false - // The VT Input mode check is to work around ssh.exe v7.7, which uses VT - // output, but not Input. Once the conpty supports these types of input, - // this check can be removed. See GH#4911 - if (_pConApi->IsConsolePty() && _pConApi->PrivateIsVtInputEnabled()) + // If we're a conpty, always return false + if (_pConApi->IsConsolePty()) { return false; } @@ -1902,11 +1893,8 @@ bool AdaptDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) bool success = true; success = _pConApi->PrivateEnableUTF8ExtendedMouseMode(enabled); - // If we're a conpty, AND WE'RE IN VT INPUT MODE, always return false - // The VT Input mode check is to work around ssh.exe v7.7, which uses VT - // output, but not Input. Once the conpty supports these types of input, - // this check can be removed. See GH#4911 - if (_pConApi->IsConsolePty() && _pConApi->PrivateIsVtInputEnabled()) + // If we're a conpty, always return false + if (_pConApi->IsConsolePty()) { return false; } @@ -1926,11 +1914,8 @@ bool AdaptDispatch::EnableSGRExtendedMouseMode(const bool enabled) bool success = true; success = _pConApi->PrivateEnableSGRExtendedMouseMode(enabled); - // If we're a conpty, AND WE'RE IN VT INPUT MODE, always return false - // The VT Input mode check is to work around ssh.exe v7.7, which uses VT - // output, but not Input. Once the conpty supports these types of input, - // this check can be removed. See GH#4911 - if (_pConApi->IsConsolePty() && _pConApi->PrivateIsVtInputEnabled()) + // If we're a conpty, always return false + if (_pConApi->IsConsolePty()) { return false; } @@ -1949,11 +1934,8 @@ bool AdaptDispatch::EnableButtonEventMouseMode(const bool enabled) bool success = true; success = _pConApi->PrivateEnableButtonEventMouseMode(enabled); - // If we're a conpty, AND WE'RE IN VT INPUT MODE, always return false - // The VT Input mode check is to work around ssh.exe v7.7, which uses VT - // output, but not Input. Once the conpty supports these types of input, - // this check can be removed. See GH#4911 - if (_pConApi->IsConsolePty() && _pConApi->PrivateIsVtInputEnabled()) + // If we're a conpty, always return false + if (_pConApi->IsConsolePty()) { return false; } @@ -1973,11 +1955,8 @@ bool AdaptDispatch::EnableAnyEventMouseMode(const bool enabled) bool success = true; success = _pConApi->PrivateEnableAnyEventMouseMode(enabled); - // If we're a conpty, AND WE'RE IN VT INPUT MODE, always return false - // The VT Input mode check is to work around ssh.exe v7.7, which uses VT - // output, but not Input. Once the conpty supports these types of input, - // this check can be removed. See GH#4911 - if (_pConApi->IsConsolePty() && _pConApi->PrivateIsVtInputEnabled()) + // If we're a conpty, always return false + if (_pConApi->IsConsolePty()) { return false; } @@ -1997,11 +1976,8 @@ bool AdaptDispatch::EnableAlternateScroll(const bool enabled) bool success = true; success = _pConApi->PrivateEnableAlternateScroll(enabled); - // If we're a conpty, AND WE'RE IN VT INPUT MODE, always return false - // The VT Input mode check is to work around ssh.exe v7.7, which uses VT - // output, but not Input. Once the conpty supports these types of input, - // this check can be removed. See GH#4911 - if (_pConApi->IsConsolePty() && _pConApi->PrivateIsVtInputEnabled()) + // If we're a conpty, always return false + if (_pConApi->IsConsolePty()) { return false; } From 3a7560e6604c9385f3034487b06fb6427c365c4c Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Thu, 16 Apr 2020 15:25:28 -0700 Subject: [PATCH 3/3] add test --- .../parser/ut_parser/InputEngineTest.cpp | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/terminal/parser/ut_parser/InputEngineTest.cpp b/src/terminal/parser/ut_parser/InputEngineTest.cpp index 8f51479e9dd..f2e32e95950 100644 --- a/src/terminal/parser/ut_parser/InputEngineTest.cpp +++ b/src/terminal/parser/ut_parser/InputEngineTest.cpp @@ -253,6 +253,7 @@ class Microsoft::Console::VirtualTerminal::InputEngineTest TEST_METHOD(CursorPositioningTest); TEST_METHOD(CSICursorBackTabTest); TEST_METHOD(EnhancedKeysTest); + TEST_METHOD(SS3CursorKeyTest); TEST_METHOD(AltBackspaceTest); TEST_METHOD(AltCtrlDTest); TEST_METHOD(AltIntermediateTest); @@ -844,6 +845,50 @@ void InputEngineTest::EnhancedKeysTest() VerifyExpectedInputDrained(); } +void InputEngineTest::SS3CursorKeyTest() +{ + auto pfn = std::bind(&TestState::TestInputCallback, &testState, std::placeholders::_1); + auto dispatch = std::make_unique(pfn, &testState); + auto inputEngine = std::make_unique(std::move(dispatch)); + auto _stateMachine = std::make_unique(std::move(inputEngine)); + VERIFY_IS_NOT_NULL(_stateMachine); + testState._stateMachine = _stateMachine.get(); + + // clang-format off + const std::map cursorKeys{ + { VK_UP, L"\x1bOA" }, + { VK_DOWN, L"\x1bOB" }, + { VK_RIGHT, L"\x1bOC" }, + { VK_LEFT, L"\x1bOD" }, + { VK_HOME, L"\x1bOH" }, + { VK_END, L"\x1bOF" }, + }; + // clang-format on + + for (const auto& [vkey, seq] : cursorKeys) + { + INPUT_RECORD inputRec; + + const wchar_t wch = (wchar_t)MapVirtualKeyW(vkey, MAPVK_VK_TO_CHAR); + const WORD scanCode = (WORD)MapVirtualKeyW(vkey, MAPVK_VK_TO_VSC); + + inputRec.EventType = KEY_EVENT; + inputRec.Event.KeyEvent.bKeyDown = TRUE; + inputRec.Event.KeyEvent.dwControlKeyState = 0; + inputRec.Event.KeyEvent.wRepeatCount = 1; + inputRec.Event.KeyEvent.wVirtualKeyCode = static_cast(vkey); + inputRec.Event.KeyEvent.wVirtualScanCode = scanCode; + inputRec.Event.KeyEvent.uChar.UnicodeChar = wch; + + testState.vExpectedInput.push_back(inputRec); + + Log::Comment(NoThrowString().Format( + L"Processing \"%s\"", seq.c_str())); + _stateMachine->ProcessString(seq); + } + VerifyExpectedInputDrained(); +} + void InputEngineTest::AltBackspaceTest() { auto pfn = std::bind(&TestState::TestInputCallback, &testState, std::placeholders::_1);