@@ -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,18 @@ 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
201+ // SynchronizeCriticalPressedStates.
202+ SynchronizeCriticalToggledStates (key, is_event_down,
203+ &event_key_can_be_repeat);
202204 // Synchronize the pressed states of critical keys (such as whether CapsLocks
203205 // is pressed).
204206 //
205207 // After this function, all critical keys except for the target key will have
206208 // their toggled state and pressed state matched with their true states. The
207209 // 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);
210+ SynchronizeCriticalPressedStates (key, physical_key, is_event_down,
211+ event_key_can_be_repeat);
210212
211213 // Reassess the last logical record in case pressingRecords_ was modified
212214 // by the above synchronization methods.
@@ -317,8 +319,8 @@ void KeyboardKeyEmbedderHandler::KeyboardHookImpl(
317319 // received despite that GetKeyState says that CapsLock is not pressed. In
318320 // such case, post-event synchronization will synthesize a CapsLock up event
319321 // after the main event.
320- SynchronizeCritialPressedStates (key, physical_key, is_event_down,
321- event_key_can_be_repeat);
322+ SynchronizeCriticalPressedStates (key, physical_key, is_event_down,
323+ event_key_can_be_repeat);
322324}
323325
324326void KeyboardKeyEmbedderHandler::KeyboardHook (
@@ -349,7 +351,7 @@ void KeyboardKeyEmbedderHandler::KeyboardHook(
349351 }
350352}
351353
352- void KeyboardKeyEmbedderHandler::UpdateLastSeenCritialKey (
354+ void KeyboardKeyEmbedderHandler::UpdateLastSeenCriticalKey (
353355 int virtual_key,
354356 uint64_t physical_key,
355357 uint64_t logical_key) {
@@ -360,7 +362,7 @@ void KeyboardKeyEmbedderHandler::UpdateLastSeenCritialKey(
360362 }
361363}
362364
363- void KeyboardKeyEmbedderHandler::SynchronizeCritialToggledStates (
365+ void KeyboardKeyEmbedderHandler::SynchronizeCriticalToggledStates (
364366 int event_virtual_key,
365367 bool is_event_down,
366368 bool * event_key_can_be_repeat) {
@@ -415,7 +417,7 @@ void KeyboardKeyEmbedderHandler::SynchronizeCritialToggledStates(
415417 }
416418}
417419
418- void KeyboardKeyEmbedderHandler::SynchronizeCritialPressedStates (
420+ void KeyboardKeyEmbedderHandler::SynchronizeCriticalPressedStates (
419421 int event_virtual_key,
420422 int event_physical_key,
421423 bool is_event_down,
@@ -492,6 +494,72 @@ void KeyboardKeyEmbedderHandler::SynchronizeCritialPressedStates(
492494 }
493495}
494496
497+ void KeyboardKeyEmbedderHandler::SyncModifiersIfNeeded (int modifiers_state) {
498+ // TODO(bleroux): consider exposing these constants in flutter_key_map.g.cc?
499+ const uint64_t physical_shift_left =
500+ windowsToPhysicalMap_.at (kScanCodeShiftLeft );
501+ const uint64_t physical_shift_right =
502+ windowsToPhysicalMap_.at (kScanCodeShiftRight );
503+ const uint64_t logical_shift_left =
504+ windowsToLogicalMap_.at (kKeyCodeShiftLeft );
505+ const uint64_t physical_control_left =
506+ windowsToPhysicalMap_.at (kScanCodeControlLeft );
507+ const uint64_t physical_control_right =
508+ windowsToPhysicalMap_.at (kScanCodeControlRight );
509+ const uint64_t logical_control_left =
510+ windowsToLogicalMap_.at (kKeyCodeControlLeft );
511+
512+ bool shift_pressed = (modifiers_state & kShift ) != 0 ;
513+ SynthesizeIfNeeded (physical_shift_left, physical_shift_right,
514+ logical_shift_left, shift_pressed);
515+ bool control_pressed = (modifiers_state & kControl ) != 0 ;
516+ SynthesizeIfNeeded (physical_control_left, physical_control_right,
517+ logical_control_left, control_pressed);
518+ }
519+
520+ void KeyboardKeyEmbedderHandler::SynthesizeIfNeeded (uint64_t physical_left,
521+ uint64_t physical_right,
522+ uint64_t logical_left,
523+ bool is_pressed) {
524+ auto pressing_record_iter_left = pressingRecords_.find (physical_left);
525+ bool left_pressed = pressing_record_iter_left != pressingRecords_.end ();
526+ auto pressing_record_iter_right = pressingRecords_.find (physical_right);
527+ bool right_pressed = pressing_record_iter_right != pressingRecords_.end ();
528+ bool already_pressed = left_pressed || right_pressed;
529+ bool synthesize_down = is_pressed && !already_pressed;
530+ bool synthesize_up = !is_pressed && already_pressed;
531+
532+ if (synthesize_down) {
533+ SendSynthesizeDownEvent (physical_left, logical_left);
534+ }
535+
536+ if (synthesize_up && left_pressed) {
537+ uint64_t known_logical = pressing_record_iter_left->second ;
538+ SendSynthesizeUpEvent (physical_left, known_logical);
539+ }
540+
541+ if (synthesize_up && right_pressed) {
542+ uint64_t known_logical = pressing_record_iter_right->second ;
543+ SendSynthesizeUpEvent (physical_right, known_logical);
544+ }
545+ }
546+
547+ void KeyboardKeyEmbedderHandler::SendSynthesizeDownEvent (uint64_t physical,
548+ uint64_t logical) {
549+ SendEvent (
550+ SynthesizeSimpleEvent (kFlutterKeyEventTypeDown , physical, logical, " " ),
551+ nullptr , nullptr );
552+ pressingRecords_[physical] = logical;
553+ };
554+
555+ void KeyboardKeyEmbedderHandler::SendSynthesizeUpEvent (uint64_t physical,
556+ uint64_t logical) {
557+ SendEvent (
558+ SynthesizeSimpleEvent (kFlutterKeyEventTypeUp , physical, logical, " " ),
559+ nullptr , nullptr );
560+ pressingRecords_.erase (physical);
561+ };
562+
495563void KeyboardKeyEmbedderHandler::HandleResponse (bool handled, void * user_data) {
496564 PendingResponse* pending = reinterpret_cast <PendingResponse*>(user_data);
497565 auto callback = std::move (pending->callback );
@@ -516,8 +584,6 @@ void KeyboardKeyEmbedderHandler::InitCriticalKeys(
516584 };
517585 };
518586
519- // TODO(dkwingsmt): Consider adding more critical keys here.
520- // https://github.com/flutter/flutter/issues/76736
521587 critical_keys_.emplace (VK_LSHIFT,
522588 createCheckedKey (VK_LSHIFT, false , true , false ));
523589 critical_keys_.emplace (VK_RSHIFT,
@@ -532,7 +598,6 @@ void KeyboardKeyEmbedderHandler::InitCriticalKeys(
532598 createCheckedKey (VK_RMENU, true , true , false ));
533599 critical_keys_.emplace (VK_LWIN, createCheckedKey (VK_LWIN, true , true , false ));
534600 critical_keys_.emplace (VK_RWIN, createCheckedKey (VK_RWIN, true , true , false ));
535-
536601 critical_keys_.emplace (VK_CAPITAL,
537602 createCheckedKey (VK_CAPITAL, false , true , true ));
538603 critical_keys_.emplace (VK_SCROLL,
0 commit comments