From a0cd9e97850f8f8dfbdbca66c013021687f3cb82 Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Wed, 7 Jul 2021 17:46:02 +0200 Subject: [PATCH] Do not expect WM_CHAR if control or windows key is pressed (flutter/engine#27064) --- .../shell/platform/windows/window_win32.cc | 11 ++++++++-- .../windows/window_win32_unittests.cc | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/engine/src/flutter/shell/platform/windows/window_win32.cc b/engine/src/flutter/shell/platform/windows/window_win32.cc index 7b1e007afc9..4449915cde9 100644 --- a/engine/src/flutter/shell/platform/windows/window_win32.cc +++ b/engine/src/flutter/shell/platform/windows/window_win32.cc @@ -371,11 +371,18 @@ WindowWin32::HandleMessage(UINT const message, // Check if this key produces a character. If so, the key press should // be sent with the character produced at WM_CHAR. Store the produced // keycode (it's not accessible from WM_CHAR) to be used in WM_CHAR. - const unsigned int character = MapVirtualKey(wparam, MAPVK_VK_TO_CHAR); - if (character > 0 && is_keydown_message) { + // + // Messages with Control or Win modifiers down are never considered as + // character messages. This allows key combinations such as "CTRL + Digit" + // to properly produce key down events even though `MapVirtualKey` returns + // a valid character. See https://github.com/flutter/flutter/issues/85587. + unsigned int character = MapVirtualKey(wparam, MAPVK_VK_TO_CHAR); + if (character > 0 && is_keydown_message && GetKeyState(VK_CONTROL) == 0 && + GetKeyState(VK_LWIN) == 0 && GetKeyState(VK_RWIN) == 0) { keycode_for_char_message_ = wparam; break; } + character = 0; unsigned int keyCode(wparam); const unsigned int scancode = (lparam >> 16) & 0xff; const bool extended = ((lparam >> 24) & 0x01) == 0x01; diff --git a/engine/src/flutter/shell/platform/windows/window_win32_unittests.cc b/engine/src/flutter/shell/platform/windows/window_win32_unittests.cc index 9680a0488bc..846c1217796 100644 --- a/engine/src/flutter/shell/platform/windows/window_win32_unittests.cc +++ b/engine/src/flutter/shell/platform/windows/window_win32_unittests.cc @@ -84,5 +84,27 @@ TEST(MockWin32Window, KeyDownPrintable) { window.InjectWindowMessage(WM_CHAR, 65, lparam); } +TEST(MockWin32Window, KeyDownWithCtrl) { + MockWin32Window window; + + // Simulate CONTROL pressed + BYTE keyboard_state[256]; + memset(keyboard_state, 0, 256); + keyboard_state[VK_CONTROL] = -1; + SetKeyboardState(keyboard_state); + + LPARAM lparam = CreateKeyEventLparam(30); + + // Expect OnKey, but not OnText, because Control + Key is not followed by + // WM_CHAR + EXPECT_CALL(window, OnKey(65, 30, WM_KEYDOWN, 0, false, true)).Times(1); + EXPECT_CALL(window, OnText(_)).Times(0); + + window.InjectWindowMessage(WM_KEYDOWN, 65, lparam); + + memset(keyboard_state, 0, 256); + SetKeyboardState(keyboard_state); +} + } // namespace testing } // namespace flutter