diff --git a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp index 79bebbe1705..e4d22a3bed1 100644 --- a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp +++ b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp @@ -559,7 +559,7 @@ void HwndTerminal::_SendKeyEvent(WORD vkey, WORD scanCode) noexcept try { const auto flags = getControlKeyState(); - _terminal->SendKeyEvent(vkey, scanCode, flags); + _terminal->SendKeyEvent(vkey, scanCode, flags, true); } CATCH_LOG(); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 62be8967f74..ccd096f29e7 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -712,7 +712,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (!handled) { // _TrySendKeyEvent pretends it didn't handle F7 for some unknown reason. - (void)_TrySendKeyEvent(VK_F7, 0, modifiers); + (void)_TrySendKeyEvent(VK_F7, 0, modifiers, true); handled = true; } @@ -721,6 +721,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void TermControl::_KeyDownHandler(winrt::Windows::Foundation::IInspectable const& /*sender*/, Input::KeyRoutedEventArgs const& e) + { + _KeyHandler(e, true); + } + + void TermControl::_KeyUpHandler(winrt::Windows::Foundation::IInspectable const& /*sender*/, + Input::KeyRoutedEventArgs const& e) + { + _KeyHandler(e, false); + } + + void TermControl::_KeyHandler(Input::KeyRoutedEventArgs const& e, const bool keyDown) { // If the current focused element is a child element of searchbox, // we do not send this event up to terminal @@ -734,9 +745,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - key modifier is pressed // NOTE: for key combos like CTRL + C, two events are fired (one for CTRL, one for 'C'). We care about the 'C' event and then check for key modifiers below. if (_closing || - e.OriginalKey() == VirtualKey::Control || - e.OriginalKey() == VirtualKey::Shift || - e.OriginalKey() == VirtualKey::Menu || + // e.OriginalKey() == VirtualKey::Control || + // e.OriginalKey() == VirtualKey::Shift || + // e.OriginalKey() == VirtualKey::Menu || e.OriginalKey() == VirtualKey::LeftWindows || e.OriginalKey() == VirtualKey::RightWindows) @@ -778,7 +789,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (!handled) { - handled = _TrySendKeyEvent(vkey, scanCode, modifiers); + handled = _TrySendKeyEvent(vkey, scanCode, modifiers, keyDown); } // Manually prevent keyboard navigation with tab. We want to send tab to @@ -800,7 +811,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // Arguments: // - vkey: The vkey of the key pressed. // - states: The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states. - bool TermControl::_TrySendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates modifiers) + bool TermControl::_TrySendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates modifiers, const bool keyDown) { // When there is a selection active, escape should clear it and NOT flow through // to the terminal. With any other keypress, it should clear the selection AND @@ -825,7 +836,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // If the terminal translated the key, mark the event as handled. // This will prevent the system from trying to get the character out // of it and sending us a CharacterReceived event. - const auto handled = vkey ? _terminal->SendKeyEvent(vkey, scanCode, modifiers) : true; + const auto handled = vkey ? _terminal->SendKeyEvent(vkey, scanCode, modifiers, keyDown) : true; if (_cursorTimer.has_value()) { diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index c42f2246abe..cb678d9ba83 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -180,6 +180,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _SetFontSize(int fontSize); void _TappedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs const& e); void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e); + void _KeyUpHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e); void _CharacterHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::CharacterReceivedRoutedEventArgs const& e); void _PointerPressedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); void _PointerMovedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); @@ -218,8 +219,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _ScrollbarUpdater(Windows::UI::Xaml::Controls::Primitives::ScrollBar scrollbar, const int viewTop, const int viewHeight, const int bufferSize); static Windows::UI::Xaml::Thickness _ParseThicknessFromPadding(const hstring padding); + void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown); ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const; - bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers); + bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown); bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point); bool _CanSendVTMouseInput(); diff --git a/src/cascadia/TerminalControl/TermControl.xaml b/src/cascadia/TerminalControl/TermControl.xaml index 32609b73926..f39e4b1e9b8 100644 --- a/src/cascadia/TerminalControl/TermControl.xaml +++ b/src/cascadia/TerminalControl/TermControl.xaml @@ -19,6 +19,7 @@ Tapped="_TappedHandler" PointerWheelChanged="_MouseWheelHandler" PreviewKeyDown="_KeyDownHandler" + KeyUp="_KeyUpHandler" CharacterReceived="_CharacterHandler" GotFocus="_GotFocusHandler" LostFocus="_LostFocusHandler"> diff --git a/src/cascadia/TerminalCore/ITerminalApi.hpp b/src/cascadia/TerminalCore/ITerminalApi.hpp index b521f4ecea2..1e94e522e7c 100644 --- a/src/cascadia/TerminalCore/ITerminalApi.hpp +++ b/src/cascadia/TerminalCore/ITerminalApi.hpp @@ -47,6 +47,7 @@ namespace Microsoft::Terminal::Core virtual bool SetDefaultForeground(const DWORD color) noexcept = 0; virtual bool SetDefaultBackground(const DWORD color) noexcept = 0; + virtual bool EnableWin32InputMode(const bool win32InputMode) noexcept = 0; virtual bool SetCursorKeysMode(const bool applicationMode) noexcept = 0; virtual bool SetKeypadMode(const bool applicationMode) noexcept = 0; virtual bool EnableVT200MouseMode(const bool enabled) noexcept = 0; diff --git a/src/cascadia/TerminalCore/ITerminalInput.hpp b/src/cascadia/TerminalCore/ITerminalInput.hpp index 5df7a0845d3..1d9785e4ee6 100644 --- a/src/cascadia/TerminalCore/ITerminalInput.hpp +++ b/src/cascadia/TerminalCore/ITerminalInput.hpp @@ -16,7 +16,7 @@ namespace Microsoft::Terminal::Core ITerminalInput& operator=(const ITerminalInput&) = default; ITerminalInput& operator=(ITerminalInput&&) = default; - virtual bool SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states) = 0; + virtual bool SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states, const bool keyDown) = 0; virtual bool SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta) = 0; virtual bool SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) = 0; diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 025d2abc7be..e9f81b64566 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -413,7 +413,7 @@ bool Terminal::IsTrackingMouseInput() const noexcept // Return Value: // - true if we translated the key event, and it should not be processed any further. // - false if we did not translate the key, and it should be processed into a character. -bool Terminal::SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states) +bool Terminal::SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states, const bool keyDown) { TrySnapOnInput(); _StoreKeyEvent(vkey, scanCode); @@ -443,7 +443,7 @@ bool Terminal::SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlK return false; } - KeyEvent keyEv{ true, 0, vkey, scanCode, ch, states.Value() }; + KeyEvent keyEv{ keyDown, 1, vkey, scanCode, ch, states.Value() }; return _terminalInput->HandleKey(&keyEv); } diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 8655987ae33..6f941a5527e 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -101,6 +101,7 @@ class Microsoft::Terminal::Core::Terminal final : bool SetDefaultForeground(const COLORREF color) noexcept override; bool SetDefaultBackground(const COLORREF color) noexcept override; + bool EnableWin32InputMode(const bool win32InputMode) noexcept override; bool SetCursorKeysMode(const bool applicationMode) noexcept override; bool SetKeypadMode(const bool applicationMode) noexcept override; bool EnableVT200MouseMode(const bool enabled) noexcept override; @@ -115,7 +116,7 @@ class Microsoft::Terminal::Core::Terminal final : #pragma region ITerminalInput // These methods are defined in Terminal.cpp - bool SendKeyEvent(const WORD vkey, const WORD scanCode, const Microsoft::Terminal::Core::ControlKeyStates states) override; + bool SendKeyEvent(const WORD vkey, const WORD scanCode, const Microsoft::Terminal::Core::ControlKeyStates states, const bool keyDown) override; bool SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta) override; bool SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) override; diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index 4189e07b1d0..453d9c711cc 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -505,6 +505,12 @@ try } CATCH_LOG_RETURN_FALSE() +bool Terminal::EnableWin32InputMode(const bool win32InputMode) noexcept +{ + _terminalInput->ChangeWin32InputMode(win32InputMode); + return true; +} + bool Terminal::SetCursorKeysMode(const bool applicationMode) noexcept { _terminalInput->ChangeCursorKeysMode(applicationMode); diff --git a/src/cascadia/TerminalCore/TerminalDispatch.cpp b/src/cascadia/TerminalCore/TerminalDispatch.cpp index c209e810d25..def069cbd2e 100644 --- a/src/cascadia/TerminalCore/TerminalDispatch.cpp +++ b/src/cascadia/TerminalCore/TerminalDispatch.cpp @@ -246,6 +246,18 @@ bool TerminalDispatch::SetCursorKeysMode(const bool applicationMode) noexcept return true; } +// Method Description +// - TODO +// Arguments: +// - applicationMode - set to true to enable Application Mode Input, false for Numeric Mode Input. +// Return Value: +// - True if handled successfully. False otherwise. +bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) noexcept +{ + _terminalApi.EnableWin32InputMode(win32Mode); + return true; +} + //Routine Description: // Enable VT200 Mouse Mode - Enables/disables the mouse input handler in default tracking mode. //Arguments: diff --git a/src/cascadia/TerminalCore/TerminalDispatch.hpp b/src/cascadia/TerminalCore/TerminalDispatch.hpp index e3be6ecbe92..4defa9f4cfb 100644 --- a/src/cascadia/TerminalCore/TerminalDispatch.hpp +++ b/src/cascadia/TerminalCore/TerminalDispatch.hpp @@ -18,6 +18,8 @@ class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatc bool CursorPosition(const size_t line, const size_t column) noexcept override; // CUP + bool EnableWin32InputMode(const bool win32InputMode) noexcept override; // win32-input-mode + bool CursorVisibility(const bool isVisible) noexcept override; // DECTCEM bool EnableCursorBlinking(const bool enable) noexcept override; // ATT610