[Linux keyboard] Fix logical keys of up events are not regularized (flutter/engine#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
This commit is contained in:
Tong Mu 2021-11-05 13:56:23 -07:00 committed by GitHub
parent 5f9ea0a1a9
commit d4d9c2aa4d
2 changed files with 101 additions and 1 deletions

View File

@ -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;

View File

@ -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;
@ -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