From 86ba1fc6c36653988bd1328a85f455c2e488a2e5 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Wed, 22 Sep 2021 21:39:34 +0200 Subject: [PATCH] Fix KeyChord constructor assertion failure during tab dragging (#11306) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some weird reason we sometimes receive a WM_KEYDOWN message without vkey or scanCode if a user drags a tab. The KeyChord constructor has a debug assertion ensuring that all KeyChord either have a valid vkey/scanCode. This is important, because this prevents accidential insertion of invalid KeyChords into classes like ActionMap. ## PR Checklist * [x] Closes #11076 * [x] I work here * [x] Tests added/passed ## Validation Steps Performed * Tab dragging doesn't produce assertion failures anymore ✔️ --- src/cascadia/TerminalControl/TermControl.cpp | 33 +++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index fc74dd0a9..f90190a5d 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -848,6 +848,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation return; } + const auto keyStatus = e.KeyStatus(); + const auto vkey = gsl::narrow_cast(e.OriginalKey()); + const auto scanCode = gsl::narrow_cast(keyStatus.ScanCode); + auto modifiers = _GetPressedModifierKeys(); + + // GH#11076: + // For some weird reason we sometimes receive a WM_KEYDOWN + // message without vkey or scanCode if a user drags a tab. + // The KeyChord constructor has a debug assertion ensuring that all KeyChord + // either have a valid vkey/scanCode. This is important, because this prevents + // accidential insertion of invalid KeyChords into classes like ActionMap. + if (!vkey && !scanCode) + { + e.Handled(true); + return; + } + // Mark the event as handled and do nothing if we're closing, or the key // was the Windows key. // @@ -856,19 +873,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation // win32-input-mode, then we'll send all these keystrokes to the // terminal - it's smart enough to ignore the keys it doesn't care // about. - if (_IsClosing() || - e.OriginalKey() == VirtualKey::LeftWindows || - e.OriginalKey() == VirtualKey::RightWindows) - + if (_IsClosing() || vkey == VK_LWIN || vkey == VK_RWIN) { e.Handled(true); return; } - auto modifiers = _GetPressedModifierKeys(); - const auto vkey = gsl::narrow_cast(e.OriginalKey()); - const auto scanCode = gsl::narrow_cast(e.KeyStatus().ScanCode); - // Short-circuit isReadOnly check to avoid warning dialog if (_core.IsInReadOnlyMode()) { @@ -876,7 +886,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation return; } - if (e.KeyStatus().IsExtendedKey) + if (keyStatus.IsExtendedKey) { modifiers |= ControlKeyStates::EnhancedKey; } @@ -886,8 +896,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // will be sent through the TSFInputControl. See GH#1401 for more // details if (modifiers.IsAltPressed() && - (e.OriginalKey() >= VirtualKey::NumberPad0 && e.OriginalKey() <= VirtualKey::NumberPad9)) - + (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9)) { e.Handled(true); return; @@ -917,7 +926,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Manually prevent keyboard navigation with tab. We want to send tab to // the terminal, and we don't want to be able to escape focus of the // control with tab. - e.Handled(e.OriginalKey() == VirtualKey::Tab); + e.Handled(vkey == VK_TAB); } // Method Description: