Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c5f572a

Browse files
authored
[Linux keyboard] Fix logical keys of up events are not regularized (#29550)
This PR fixes a bug where up events from the embedder responder are not using the logical keys of the down events, breaking the regularization
1 parent 71fb575 commit c5f572a

File tree

2 files changed

+101
-1
lines changed

2 files changed

+101
-1
lines changed

shell/platform/linux/fl_key_embedder_responder.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,8 @@ static void fl_key_embedder_responder_handle_event_impl(
714714
out_event.struct_size = sizeof(out_event);
715715
out_event.timestamp = timestamp;
716716
out_event.physical = physical_key;
717-
out_event.logical = logical_key;
717+
out_event.logical =
718+
last_logical_record != 0 ? last_logical_record : logical_key;
718719
out_event.character = nullptr;
719720
out_event.synthesized = false;
720721

shell/platform/linux/fl_key_embedder_responder_test.cc

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ constexpr gboolean kPress = TRUE;
1919
constexpr gboolean kIsModifier = TRUE;
2020
constexpr gboolean kIsNotModifier = FALSE;
2121

22+
constexpr guint16 kKeyCodeDigit1 = 0x0au;
2223
constexpr guint16 kKeyCodeKeyA = 0x26u;
24+
constexpr guint16 kKeyCodeShiftLeft = 0x32u;
2325
constexpr guint16 kKeyCodeShiftRight = 0x3Eu;
2426
constexpr guint16 kKeyCodeNumpad1 = 0x57u;
2527
constexpr 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

Comments
 (0)