Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Impl
  • Loading branch information
dkwingsmt committed Aug 17, 2021
commit 5a6838112519741d4faa6cd122a726ee0b1b29da
13 changes: 12 additions & 1 deletion shell/platform/windows/keyboard_key_channel_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,17 @@ int GetModsForKeyState() {
#endif
}

// Revert the "character" for a dead key to its normal value, or the argument
// unchanged otherwise.
//
// When a dead key is pressed, the WM_KEYDOWN's lParam is mapped to a special
// value: the "normal character" | 0x80000000. For example, when pressing
// "dead key caret" (one that makes the following e into ê), its mapped
// character is 0x8000005E. "Reverting" it gives 0x5E, which is character '^'.
uint32_t _UndeadChar(uint32_t ch) {
return ch & ~0x80000000;
}

} // namespace

KeyboardKeyChannelHandler::KeyboardKeyChannelHandler(
Expand Down Expand Up @@ -130,7 +141,7 @@ void KeyboardKeyChannelHandler::KeyboardHook(
event.AddMember(kKeyCodeKey, key, allocator);
event.AddMember(kScanCodeKey, scancode | (extended ? kScancodeExtended : 0),
allocator);
event.AddMember(kCharacterCodePointKey, character, allocator);
event.AddMember(kCharacterCodePointKey, _UndeadChar(character), allocator);
event.AddMember(kKeyMapKey, kWindowsKeyMap, allocator);
event.AddMember(kModifiersKey, GetModsForKeyState(), allocator);

Expand Down
13 changes: 12 additions & 1 deletion shell/platform/windows/keyboard_key_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ namespace {
// emitting a warning on the console about unhandled events.
static constexpr int kMaxPendingEvents = 1000;

// Returns if a character sent by Win32 is a dead key.
bool _IsDeadKey(uint32_t ch) {
return (ch & 0x80000000) != 0;
}

// Returns true if this key is a key down event of ShiftRight.
//
// This is a temporary solution to
Expand Down Expand Up @@ -261,7 +266,13 @@ void KeyboardKeyHandler::ResolvePendingEvent(uint64_t sequence_id,
if (event.unreplied == 0) {
std::unique_ptr<PendingEvent> event_ptr = std::move(*iter);
pending_responds_.erase(iter);
if (!event_ptr->any_handled) {
// Don't dispatch handled events or dead key events.
//
// Redispatching dead keys events makes Win32 ignore the dead key state
// and redispatches a normal character without combining it with the
// next letter key.
const bool should_redispatch = !event_ptr->any_handled && !_IsDeadKey(event_ptr->character);
if (should_redispatch) {
RedispatchEvent(std::move(event_ptr));
}
}
Expand Down
12 changes: 8 additions & 4 deletions shell/platform/windows/keyboard_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,10 @@ class TestFlutterWindowsView : public FlutterWindowsView {

uint32_t redispatch_char;

void InjectPendingEvents(MockFlutterWindowWin32* win32window,
int InjectPendingEvents(MockFlutterWindowWin32* win32window,
uint32_t redispatch_char) {
std::vector<Win32Message> messages;
int num_pending_responds = pending_responds_.size();
for (const SendInputInfo& input : pending_responds_) {
const KEYBDINPUT kbdinput = input.kbdinput;
const UINT message =
Expand All @@ -200,6 +201,7 @@ class TestFlutterWindowsView : public FlutterWindowsView {

win32window->InjectMessageList(messages.size(), messages.data());
pending_responds_.clear();
return num_pending_responds;
}

void SetKeyState(uint32_t key, bool pressed, bool toggled_on) {
Expand Down Expand Up @@ -294,10 +296,12 @@ class KeyboardTester {
// Inject all events called with |SendInput| to the event queue,
// then process the event queue.
//
// Returns the number of events injected.
//
// If |redispatch_char| is not 0, then WM_KEYDOWN events will
// also redispatch a WM_CHAR event with that value as lparam.
void InjectPendingEvents(uint32_t redispatch_char = 0) {
view_->InjectPendingEvents(window_.get(), redispatch_char);
int InjectPendingEvents(uint32_t redispatch_char = 0) {
return view_->InjectPendingEvents(window_.get(), redispatch_char);
}

static bool test_response;
Expand Down Expand Up @@ -802,7 +806,7 @@ TEST(KeyboardTest, DeadKeyThatCombines) {
kNotSynthesized);
clear_key_calls();

tester.InjectPendingEvents(0); // No WM_DEADCHAR messages sent here.
EXPECT_EQ(tester.InjectPendingEvents(), 0);
EXPECT_EQ(key_calls.size(), 0);
clear_key_calls();

Expand Down