@@ -186,6 +186,7 @@ void KeyboardKeyEmbedderHandler::KeyboardHookImpl(
186186
187187 const bool is_event_down = action == WM_KEYDOWN || action == WM_SYSKEYDOWN;
188188
189+ bool event_key_can_be_repeat = true ;
189190 UpdateLastSeenCritialKey (key, physical_key, sequence_logical_key);
190191 // Synchronize the toggled states of critical keys (such as whether CapsLocks
191192 // is enabled). Toggled states can only be changed upon a down event, so if
@@ -197,14 +198,15 @@ void KeyboardKeyEmbedderHandler::KeyboardHookImpl(
197198 // updated to the true state, while the critical keys whose toggled state have
198199 // been changed will be pressed regardless of their true pressed state.
199200 // Updating the pressed state will be done by SynchronizeCritialPressedStates.
200- SynchronizeCritialToggledStates (key, is_event_down);
201+ SynchronizeCritialToggledStates (key, is_event_down, &event_key_can_be_repeat );
201202 // Synchronize the pressed states of critical keys (such as whether CapsLocks
202203 // is pressed).
203204 //
204205 // After this function, all critical keys except for the target key will have
205206 // their toggled state and pressed state matched with their true states. The
206207 // target key's pressed state will be updated immediately after this.
207- SynchronizeCritialPressedStates (key, physical_key, is_event_down);
208+ SynchronizeCritialPressedStates (key, physical_key, is_event_down,
209+ event_key_can_be_repeat);
208210
209211 // The resulting event's `type`.
210212 FlutterKeyEventType type;
@@ -340,7 +342,8 @@ void KeyboardKeyEmbedderHandler::UpdateLastSeenCritialKey(
340342
341343void KeyboardKeyEmbedderHandler::SynchronizeCritialToggledStates (
342344 int event_virtual_key,
343- bool is_event_down) {
345+ bool is_event_down,
346+ bool * event_key_can_be_repeat) {
344347 // NowState ----------------> PreEventState --------------> TrueState
345348 // Synchronization Event
346349 for (auto & kv : critical_keys_) {
@@ -385,6 +388,7 @@ void KeyboardKeyEmbedderHandler::SynchronizeCritialToggledStates(
385388 key_info.physical_key ,
386389 key_info.logical_key , empty_character),
387390 nullptr , nullptr );
391+ *event_key_can_be_repeat = false ;
388392 }
389393 key_info.toggled_on = true_toggled;
390394 }
@@ -394,7 +398,8 @@ void KeyboardKeyEmbedderHandler::SynchronizeCritialToggledStates(
394398void KeyboardKeyEmbedderHandler::SynchronizeCritialPressedStates (
395399 int event_virtual_key,
396400 int event_physical_key,
397- bool is_event_down) {
401+ bool is_event_down,
402+ bool event_key_can_be_repeat) {
398403 // During an incoming event, there might be a synthesized Flutter event for
399404 // each key of each pressing goal, followed by an eventual main Flutter
400405 // event.
@@ -424,8 +429,18 @@ void KeyboardKeyEmbedderHandler::SynchronizeCritialPressedStates(
424429 if (is_event_down) {
425430 // For down events, this key is the event key if they have the same
426431 // virtual key, because virtual key represents "functionality."
432+ //
433+ // In that case, normally Flutter should synthesize nothing since the
434+ // resulting event can adapt to the current state by dispatching either
435+ // a down or a repeat event. However, in certain cases (when Flutter has
436+ // just synchronized the key's toggling state) the event must not be a
437+ // repeat event.
427438 if (virtual_key == event_virtual_key) {
428- pre_event_pressed = false ;
439+ if (event_key_can_be_repeat) {
440+ continue ;
441+ } else {
442+ pre_event_pressed = false ;
443+ }
429444 }
430445 } else {
431446 // For up events, this key is the event key if they have the same
0 commit comments