Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion shell/platform/linux/fl_key_embedder_responder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,8 @@ static void fl_key_embedder_responder_handle_event_impl(
out_event.struct_size = sizeof(out_event);
out_event.timestamp = timestamp;
out_event.physical = physical_key;
out_event.logical = logical_key;
out_event.logical =
last_logical_record != 0 ? last_logical_record : logical_key;
out_event.character = nullptr;
out_event.synthesized = false;

Expand Down
99 changes: 99 additions & 0 deletions shell/platform/linux/fl_key_embedder_responder_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ constexpr gboolean kPress = TRUE;
constexpr gboolean kIsModifier = TRUE;
constexpr gboolean kIsNotModifier = FALSE;

constexpr guint16 kKeyCodeDigit1 = 0x0au;
constexpr guint16 kKeyCodeKeyA = 0x26u;
constexpr guint16 kKeyCodeShiftLeft = 0x32u;
constexpr guint16 kKeyCodeShiftRight = 0x3Eu;
constexpr guint16 kKeyCodeNumpad1 = 0x57u;
constexpr guint16 kKeyCodeNumLock = 0x4Du;
Expand Down Expand Up @@ -527,6 +529,103 @@ TEST(FlKeyEmbedderResponderTest, TapNumPadKeysBetweenNumLockEvents) {
g_object_unref(responder);
}

// Press or release digit 1 between presses/releases of Shift.
//
// GTK will change the virtual key during a key tap, and the embedder
// should regularize it.
TEST(FlKeyEmbedderResponderTest, ReleaseShiftKeyBetweenDigitKeyEvents) {
EXPECT_EQ(g_call_records, nullptr);
g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
FlEngine* engine = make_mock_engine_with_records();
FlKeyResponder* responder =
FL_KEY_RESPONDER(fl_key_embedder_responder_new(engine));
int user_data = 123; // Arbitrary user data

FlKeyEmbedderCallRecord* record;

guint state = 0;

// Press shift left
fl_key_responder_handle_event(
responder,
fl_key_event_new_by_mock(101, kPress, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
state, kIsModifier),
verify_response_handled, &user_data);

EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
EXPECT_STREQ(record->event->character, nullptr);
EXPECT_EQ(record->event->synthesized, false);

invoke_record_callback_and_verify(record, TRUE, &user_data);
g_ptr_array_clear(g_call_records);

state = GDK_SHIFT_MASK;

// Press digit 1, which is '!' on a US keyboard
fl_key_responder_handle_event(
responder,
fl_key_event_new_by_mock(102, kPress, GDK_KEY_exclam, kKeyCodeDigit1,
state, kIsNotModifier),
verify_response_handled, &user_data);

EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
EXPECT_EQ(record->event->physical, kPhysicalDigit1);
EXPECT_EQ(record->event->logical, kLogicalExclamation);
EXPECT_STREQ(record->event->character, "!");
EXPECT_EQ(record->event->synthesized, false);

invoke_record_callback_and_verify(record, TRUE, &user_data);
g_ptr_array_clear(g_call_records);

// Release shift
fl_key_responder_handle_event(
responder,
fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Shift_L,
kKeyCodeShiftLeft, state, kIsModifier),
verify_response_handled, &user_data);

EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
EXPECT_STREQ(record->event->character, nullptr);
EXPECT_EQ(record->event->synthesized, false);

invoke_record_callback_and_verify(record, TRUE, &user_data);
g_ptr_array_clear(g_call_records);

state = 0;

// Release digit 1, which is "1" because shift has been released.
fl_key_responder_handle_event(
responder,
fl_key_event_new_by_mock(104, kRelease, GDK_KEY_1, kKeyCodeDigit1, state,
kIsNotModifier),
verify_response_handled, &user_data);

EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
EXPECT_EQ(record->event->physical, kPhysicalDigit1);
EXPECT_EQ(record->event->logical, kLogicalExclamation); // Important
EXPECT_STREQ(record->event->character, nullptr);
EXPECT_EQ(record->event->synthesized, false);

invoke_record_callback_and_verify(record, TRUE, &user_data);
g_ptr_array_clear(g_call_records);

clear_g_call_records();
g_object_unref(engine);
g_object_unref(responder);
}

// Press or release letter key between presses/releases of CapsLock.
//
// This tests interaction between lock keys and non-lock keys in cases that do
Expand Down