@@ -187,7 +187,7 @@ void KeyboardKeyEmbedderHandler::KeyboardHookImpl(
187187 const bool is_event_down = action == WM_KEYDOWN || action == WM_SYSKEYDOWN;
188188
189189 bool event_key_can_be_repeat = true ;
190- UpdateLastSeenCritialKey (key, physical_key, sequence_logical_key);
190+ UpdateLastSeenCriticalKey (key, physical_key, sequence_logical_key);
191191 // Synchronize the toggled states of critical keys (such as whether CapsLocks
192192 // is enabled). Toggled states can only be changed upon a down event, so if
193193 // the recorded toggled state does not match the true state, this function
@@ -197,16 +197,17 @@ void KeyboardKeyEmbedderHandler::KeyboardHookImpl(
197197 // After this function, all critical keys will have their toggled state
198198 // updated to the true state, while the critical keys whose toggled state have
199199 // been changed will be pressed regardless of their true pressed state.
200- // Updating the pressed state will be done by SynchronizeCritialPressedStates.
201- SynchronizeCritialToggledStates (key, is_event_down, &event_key_can_be_repeat);
200+ // Updating the pressed state will be done by SynchronizeCriticalPressedStates.
201+ SynchronizeCriticalToggledStates (key, is_event_down,
202+ &event_key_can_be_repeat);
202203 // Synchronize the pressed states of critical keys (such as whether CapsLocks
203204 // is pressed).
204205 //
205206 // After this function, all critical keys except for the target key will have
206207 // their toggled state and pressed state matched with their true states. The
207208 // target key's pressed state will be updated immediately after this.
208- SynchronizeCritialPressedStates (key, physical_key, is_event_down,
209- event_key_can_be_repeat);
209+ SynchronizeCriticalPressedStates (key, physical_key, is_event_down,
210+ event_key_can_be_repeat);
210211
211212 // Reassess the last logical record in case pressingRecords_ was modified
212213 // by the above synchronization methods.
@@ -317,8 +318,8 @@ void KeyboardKeyEmbedderHandler::KeyboardHookImpl(
317318 // received despite that GetKeyState says that CapsLock is not pressed. In
318319 // such case, post-event synchronization will synthesize a CapsLock up event
319320 // after the main event.
320- SynchronizeCritialPressedStates (key, physical_key, is_event_down,
321- event_key_can_be_repeat);
321+ SynchronizeCriticalPressedStates (key, physical_key, is_event_down,
322+ event_key_can_be_repeat);
322323}
323324
324325void KeyboardKeyEmbedderHandler::KeyboardHook (
@@ -349,7 +350,7 @@ void KeyboardKeyEmbedderHandler::KeyboardHook(
349350 }
350351}
351352
352- void KeyboardKeyEmbedderHandler::UpdateLastSeenCritialKey (
353+ void KeyboardKeyEmbedderHandler::UpdateLastSeenCriticalKey (
353354 int virtual_key,
354355 uint64_t physical_key,
355356 uint64_t logical_key) {
@@ -360,7 +361,7 @@ void KeyboardKeyEmbedderHandler::UpdateLastSeenCritialKey(
360361 }
361362}
362363
363- void KeyboardKeyEmbedderHandler::SynchronizeCritialToggledStates (
364+ void KeyboardKeyEmbedderHandler::SynchronizeCriticalToggledStates (
364365 int event_virtual_key,
365366 bool is_event_down,
366367 bool * event_key_can_be_repeat) {
@@ -415,7 +416,7 @@ void KeyboardKeyEmbedderHandler::SynchronizeCritialToggledStates(
415416 }
416417}
417418
418- void KeyboardKeyEmbedderHandler::SynchronizeCritialPressedStates (
419+ void KeyboardKeyEmbedderHandler::SynchronizeCriticalPressedStates (
419420 int event_virtual_key,
420421 int event_physical_key,
421422 bool is_event_down,
@@ -492,6 +493,72 @@ void KeyboardKeyEmbedderHandler::SynchronizeCritialPressedStates(
492493 }
493494}
494495
496+ void KeyboardKeyEmbedderHandler::SyncModifiersIfNeeded (int modifiers_state) {
497+ // TODO(bleroux): consider exposing these constants in flutter_key_map.g.cc?
498+ const uint64_t physical_shift_left =
499+ windowsToPhysicalMap_.at (kScanCodeShiftLeft );
500+ const uint64_t physical_shift_right =
501+ windowsToPhysicalMap_.at (kScanCodeShiftRight );
502+ const uint64_t logical_shift_left =
503+ windowsToLogicalMap_.at (kKeyCodeShiftLeft );
504+ const uint64_t physical_control_left =
505+ windowsToPhysicalMap_.at (kScanCodeControlLeft );
506+ const uint64_t physical_control_right =
507+ windowsToPhysicalMap_.at (kScanCodeControlRight );
508+ const uint64_t logical_control_left =
509+ windowsToLogicalMap_.at (kKeyCodeControlLeft );
510+
511+ bool shift_pressed = (modifiers_state & kShift ) != 0 ;
512+ SynthesizeIfNeeded (physical_shift_left, physical_shift_right,
513+ logical_shift_left, shift_pressed);
514+ bool control_pressed = (modifiers_state & kControl ) != 0 ;
515+ SynthesizeIfNeeded (physical_control_left, physical_control_right,
516+ logical_control_left, control_pressed);
517+ }
518+
519+ void KeyboardKeyEmbedderHandler::SynthesizeIfNeeded (uint64_t physical_left,
520+ uint64_t physical_right,
521+ uint64_t logical_left,
522+ bool is_pressed) {
523+ auto pressing_record_iter_left = pressingRecords_.find (physical_left);
524+ bool left_pressed = pressing_record_iter_left != pressingRecords_.end ();
525+ auto pressing_record_iter_right = pressingRecords_.find (physical_right);
526+ bool right_pressed = pressing_record_iter_right != pressingRecords_.end ();
527+ bool already_pressed = left_pressed || right_pressed;
528+ bool synthesize_down = is_pressed && !already_pressed;
529+ bool synthesize_up = !is_pressed && already_pressed;
530+
531+ if (synthesize_down) {
532+ SendSynthesizeDownEvent (physical_left, logical_left);
533+ }
534+
535+ if (synthesize_up && left_pressed) {
536+ uint64_t known_logical = pressing_record_iter_left->second ;
537+ SendSynthesizeUpEvent (physical_left, known_logical);
538+ }
539+
540+ if (synthesize_up && right_pressed) {
541+ uint64_t known_logical = pressing_record_iter_right->second ;
542+ SendSynthesizeUpEvent (physical_right, known_logical);
543+ }
544+ }
545+
546+ void KeyboardKeyEmbedderHandler::SendSynthesizeDownEvent (uint64_t physical,
547+ uint64_t logical) {
548+ SendEvent (
549+ SynthesizeSimpleEvent (kFlutterKeyEventTypeDown , physical, logical, " " ),
550+ nullptr , nullptr );
551+ pressingRecords_[physical] = logical;
552+ };
553+
554+ void KeyboardKeyEmbedderHandler::SendSynthesizeUpEvent (uint64_t physical,
555+ uint64_t logical) {
556+ SendEvent (
557+ SynthesizeSimpleEvent (kFlutterKeyEventTypeUp , physical, logical, " " ),
558+ nullptr , nullptr );
559+ pressingRecords_.erase (physical);
560+ };
561+
495562void KeyboardKeyEmbedderHandler::HandleResponse (bool handled, void * user_data) {
496563 PendingResponse* pending = reinterpret_cast <PendingResponse*>(user_data);
497564 auto callback = std::move (pending->callback );
@@ -516,8 +583,6 @@ void KeyboardKeyEmbedderHandler::InitCriticalKeys(
516583 };
517584 };
518585
519- // TODO(dkwingsmt): Consider adding more critical keys here.
520- // https://github.com/flutter/flutter/issues/76736
521586 critical_keys_.emplace (VK_LSHIFT,
522587 createCheckedKey (VK_LSHIFT, false , true , false ));
523588 critical_keys_.emplace (VK_RSHIFT,
@@ -532,7 +597,6 @@ void KeyboardKeyEmbedderHandler::InitCriticalKeys(
532597 createCheckedKey (VK_RMENU, true , true , false ));
533598 critical_keys_.emplace (VK_LWIN, createCheckedKey (VK_LWIN, true , true , false ));
534599 critical_keys_.emplace (VK_RWIN, createCheckedKey (VK_RWIN, true , true , false ));
535-
536600 critical_keys_.emplace (VK_CAPITAL,
537601 createCheckedKey (VK_CAPITAL, false , true , true ));
538602 critical_keys_.emplace (VK_SCROLL,
0 commit comments