diff --git a/engine/src/flutter/shell/platform/windows/keyboard_key_embedder_handler.cc b/engine/src/flutter/shell/platform/windows/keyboard_key_embedder_handler.cc index e9617464ccb..bc4632877e9 100644 --- a/engine/src/flutter/shell/platform/windows/keyboard_key_embedder_handler.cc +++ b/engine/src/flutter/shell/platform/windows/keyboard_key_embedder_handler.cc @@ -126,6 +126,10 @@ uint64_t KeyboardKeyEmbedderHandler::GetPhysicalKey(int scancode, uint64_t KeyboardKeyEmbedderHandler::GetLogicalKey(int key, bool extended, int scancode) { + if (key == VK_PROCESSKEY) { + return VK_PROCESSKEY; + } + // Normally logical keys should only be derived from key codes, but since some // key codes are either 0 or ambiguous (multiple keys using the same key // code), these keys are resolved by scan codes. @@ -220,6 +224,15 @@ void KeyboardKeyEmbedderHandler::KeyboardHookImpl( } } + if (result_logical_key == VK_PROCESSKEY) { + // VK_PROCESSKEY means that the key press is used by an IME. These key + // presses are considered handled and not sent to Flutter. These events must + // be filtered by result_logical_key because the key up event of such + // presses uses the "original" logical key. + callback(true); + return; + } + UpdateLastSeenCritialKey(key, physical_key, result_logical_key); // Synchronize the toggled states of critical keys (such as whether CapsLocks // is enabled). Toggled states can only be changed upon a down event, so if @@ -248,15 +261,6 @@ void KeyboardKeyEmbedderHandler::KeyboardHookImpl( pressingRecords_.erase(record_iter); } - if (result_logical_key == VK_PROCESSKEY) { - // VK_PROCESSKEY means that the key press is used by an IME. These key - // presses are considered handled and not sent to Flutter. These events must - // be filtered by result_logical_key because the key up event of such - // presses uses the "original" logical key. - callback(true); - return; - } - FlutterKeyEvent key_data{ .struct_size = sizeof(FlutterKeyEvent), .timestamp = static_cast( diff --git a/engine/src/flutter/shell/platform/windows/keyboard_win32_unittests.cc b/engine/src/flutter/shell/platform/windows/keyboard_win32_unittests.cc index bfdda3da091..7d488864204 100644 --- a/engine/src/flutter/shell/platform/windows/keyboard_win32_unittests.cc +++ b/engine/src/flutter/shell/platform/windows/keyboard_win32_unittests.cc @@ -1545,7 +1545,7 @@ TEST(KeyboardTest, MultibyteCharacter) { tester.Responding(false); // Gothic Keyboard layout. (We need a layout that yields non-BMP characters - // without IME, which that is actually very rare.) + // without IME, which is actually very rare.) // Press key W of a US keyboard, which should yield character '𐍅'. tester.InjectMessages( @@ -1617,6 +1617,33 @@ TEST(KeyboardTest, NeverRedispatchShiftRightKeyDown) { EXPECT_EQ(key_calls.size(), 0); } +// Pressing modifiers during IME events should work properly by not sending any +// events. +// +// Regression test for https://github.com/flutter/flutter/issues/95888 . +TEST(KeyboardTest, ImeModifierEventsAreIgnored) { + KeyboardTester tester; + tester.Responding(false); + + // US Keyboard layout. + + // To make the keyboard into IME mode, there should have been events like + // letter key down with VK_PROCESSKEY. Omit them in this test since they don't + // seem significant. + + // Press CtrlRight in IME mode. + tester.SetKeyState(VK_RCONTROL, true, false); + tester.InjectMessages( + 1, + WmKeyDownInfo{VK_PROCESSKEY, kScanCodeControl, kExtended, kWasUp}.Build( + kWmResultZero)); + + EXPECT_EQ(key_calls.size(), 1); + EXPECT_CALL_IS_EVENT(key_calls[0], kFlutterKeyEventTypeDown, 0, 0, "", + kNotSynthesized); + clear_key_calls(); +} + TEST(KeyboardTest, DisorderlyRespondedEvents) { KeyboardTester tester;