@@ -19,7 +19,9 @@ constexpr gboolean kPress = TRUE;
1919constexpr gboolean kIsModifier = TRUE ;
2020constexpr gboolean kIsNotModifier = FALSE ;
2121
22+ constexpr guint16 kKeyCodeDigit1 = 0x0au ;
2223constexpr guint16 kKeyCodeKeyA = 0x26u ;
24+ constexpr guint16 kKeyCodeShiftLeft = 0x32u ;
2325constexpr guint16 kKeyCodeShiftRight = 0x3Eu ;
2426constexpr guint16 kKeyCodeNumpad1 = 0x57u ;
2527constexpr guint16 kKeyCodeNumLock = 0x4Du ;
@@ -527,6 +529,103 @@ TEST(FlKeyEmbedderResponderTest, TapNumPadKeysBetweenNumLockEvents) {
527529 g_object_unref (responder);
528530}
529531
532+ // Press or release digit 1 between presses/releases of Shift.
533+ //
534+ // GTK will change the virtual key during a key tap, and the embedder
535+ // should regularize it.
536+ TEST (FlKeyEmbedderResponderTest, ReleaseShiftKeyBetweenDigitKeyEvents) {
537+ EXPECT_EQ (g_call_records, nullptr );
538+ g_call_records = g_ptr_array_new_with_free_func (g_object_unref);
539+ FlEngine* engine = make_mock_engine_with_records ();
540+ FlKeyResponder* responder =
541+ FL_KEY_RESPONDER (fl_key_embedder_responder_new (engine));
542+ int user_data = 123 ; // Arbitrary user data
543+
544+ FlKeyEmbedderCallRecord* record;
545+
546+ guint state = 0 ;
547+
548+ // Press shift left
549+ fl_key_responder_handle_event (
550+ responder,
551+ fl_key_event_new_by_mock (101 , kPress , GDK_KEY_Shift_L, kKeyCodeShiftLeft ,
552+ state, kIsModifier ),
553+ verify_response_handled, &user_data);
554+
555+ EXPECT_EQ (g_call_records->len , 1u );
556+ record = FL_KEY_EMBEDDER_CALL_RECORD (g_ptr_array_index (g_call_records, 0 ));
557+ EXPECT_EQ (record->event ->type , kFlutterKeyEventTypeDown );
558+ EXPECT_EQ (record->event ->physical , kPhysicalShiftLeft );
559+ EXPECT_EQ (record->event ->logical , kLogicalShiftLeft );
560+ EXPECT_STREQ (record->event ->character , nullptr );
561+ EXPECT_EQ (record->event ->synthesized , false );
562+
563+ invoke_record_callback_and_verify (record, TRUE , &user_data);
564+ g_ptr_array_clear (g_call_records);
565+
566+ state = GDK_SHIFT_MASK;
567+
568+ // Press digit 1, which is '!' on a US keyboard
569+ fl_key_responder_handle_event (
570+ responder,
571+ fl_key_event_new_by_mock (102 , kPress , GDK_KEY_exclam, kKeyCodeDigit1 ,
572+ state, kIsNotModifier ),
573+ verify_response_handled, &user_data);
574+
575+ EXPECT_EQ (g_call_records->len , 1u );
576+ record = FL_KEY_EMBEDDER_CALL_RECORD (g_ptr_array_index (g_call_records, 0 ));
577+ EXPECT_EQ (record->event ->type , kFlutterKeyEventTypeDown );
578+ EXPECT_EQ (record->event ->physical , kPhysicalDigit1 );
579+ EXPECT_EQ (record->event ->logical , kLogicalExclamation );
580+ EXPECT_STREQ (record->event ->character , " !" );
581+ EXPECT_EQ (record->event ->synthesized , false );
582+
583+ invoke_record_callback_and_verify (record, TRUE , &user_data);
584+ g_ptr_array_clear (g_call_records);
585+
586+ // Release shift
587+ fl_key_responder_handle_event (
588+ responder,
589+ fl_key_event_new_by_mock (103 , kRelease , GDK_KEY_Shift_L,
590+ kKeyCodeShiftLeft , state, kIsModifier ),
591+ verify_response_handled, &user_data);
592+
593+ EXPECT_EQ (g_call_records->len , 1u );
594+ record = FL_KEY_EMBEDDER_CALL_RECORD (g_ptr_array_index (g_call_records, 0 ));
595+ EXPECT_EQ (record->event ->type , kFlutterKeyEventTypeUp );
596+ EXPECT_EQ (record->event ->physical , kPhysicalShiftLeft );
597+ EXPECT_EQ (record->event ->logical , kLogicalShiftLeft );
598+ EXPECT_STREQ (record->event ->character , nullptr );
599+ EXPECT_EQ (record->event ->synthesized , false );
600+
601+ invoke_record_callback_and_verify (record, TRUE , &user_data);
602+ g_ptr_array_clear (g_call_records);
603+
604+ state = 0 ;
605+
606+ // Release digit 1, which is "1" because shift has been released.
607+ fl_key_responder_handle_event (
608+ responder,
609+ fl_key_event_new_by_mock (104 , kRelease , GDK_KEY_1, kKeyCodeDigit1 , state,
610+ kIsNotModifier ),
611+ verify_response_handled, &user_data);
612+
613+ EXPECT_EQ (g_call_records->len , 1u );
614+ record = FL_KEY_EMBEDDER_CALL_RECORD (g_ptr_array_index (g_call_records, 0 ));
615+ EXPECT_EQ (record->event ->type , kFlutterKeyEventTypeUp );
616+ EXPECT_EQ (record->event ->physical , kPhysicalDigit1 );
617+ EXPECT_EQ (record->event ->logical , kLogicalExclamation ); // Important
618+ EXPECT_STREQ (record->event ->character , nullptr );
619+ EXPECT_EQ (record->event ->synthesized , false );
620+
621+ invoke_record_callback_and_verify (record, TRUE , &user_data);
622+ g_ptr_array_clear (g_call_records);
623+
624+ clear_g_call_records ();
625+ g_object_unref (engine);
626+ g_object_unref (responder);
627+ }
628+
530629// Press or release letter key between presses/releases of CapsLock.
531630//
532631// This tests interaction between lock keys and non-lock keys in cases that do
0 commit comments