Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
fl_key_embedder_responder_test.cc File Reference

Go to the source code of this file.

Classes

struct  _FlKeyEmbedderCallRecord
 
class  FlKeyEmbedderResponderTest
 

Functions

static void clear_records (GPtrArray *array)
 
 G_DECLARE_FINAL_TYPE (FlKeyEmbedderCallRecord, fl_key_embedder_call_record, FL, KEY_EMBEDDER_CALL_RECORD, GObject)
 
 G_DEFINE_TYPE (FlKeyEmbedderCallRecord, fl_key_embedder_call_record, G_TYPE_OBJECT) static void fl_key_embedder_call_record_init(FlKeyEmbedderCallRecord *self)
 
static void fl_key_embedder_call_record_dispose (GObject *object)
 
static void fl_key_embedder_call_record_class_init (FlKeyEmbedderCallRecordClass *klass)
 
static FlKeyEmbedderCallRecord * fl_key_embedder_call_record_new (const FlutterKeyEvent *event, FlutterKeyEventCallback callback, gpointer user_data)
 
static void invoke_record_callback (FlKeyEmbedderCallRecord *record, bool expected_handled)
 
 TEST_F (FlKeyEmbedderResponderTest, SendKeyEvent)
 
 TEST_F (FlKeyEmbedderResponderTest, UsesSpecifiedLogicalKey)
 
 TEST_F (FlKeyEmbedderResponderTest, PressShiftDuringLetterKeyTap)
 
 TEST_F (FlKeyEmbedderResponderTest, TapNumPadKeysBetweenNumLockEvents)
 
 TEST_F (FlKeyEmbedderResponderTest, ReleaseShiftKeyBetweenDigitKeyEvents)
 
 TEST_F (FlKeyEmbedderResponderTest, TapLetterKeysBetweenCapsLockEvents)
 
 TEST_F (FlKeyEmbedderResponderTest, TapLetterKeysBetweenCapsLockEventsReversed)
 
 TEST_F (FlKeyEmbedderResponderTest, TurnDuplicateDownEventsToRepeats)
 
 TEST_F (FlKeyEmbedderResponderTest, IgnoreAbruptUpEvent)
 
 TEST_F (FlKeyEmbedderResponderTest, SynthesizeForDesyncPressingStateOnSelfEvents)
 
 TEST_F (FlKeyEmbedderResponderTest, SynthesizeForDesyncPressingStateOnNonSelfEvents)
 
 TEST_F (FlKeyEmbedderResponderTest, SynthesizeForDesyncPressingStateOnRemappedEvents)
 
 TEST_F (FlKeyEmbedderResponderTest, SynthesizeForDesyncLockModeOnNonSelfEvents)
 
 TEST_F (FlKeyEmbedderResponderTest, SynthesizeForDesyncLockModeOnSelfEvents)
 
 TEST_F (FlKeyEmbedderResponderTest, SynthesizationOccursOnIgnoredEvents)
 
 TEST_F (FlKeyEmbedderResponderTest, HandlesShiftAltVersusGroupNext)
 
 TEST_F (FlKeyEmbedderResponderTest, HandlesShiftAltLeftIsMetaLeft)
 

Function Documentation

◆ clear_records()

static void clear_records ( GPtrArray *  array)
static

Definition at line 34 of file fl_key_embedder_responder_test.cc.

34 {
35 g_ptr_array_remove_range(array, 0, array->len);
36}

Referenced by TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), and TEST_F().

◆ fl_key_embedder_call_record_class_init()

static void fl_key_embedder_call_record_class_init ( FlKeyEmbedderCallRecordClass *  klass)
static

Definition at line 71 of file fl_key_embedder_responder_test.cc.

72 {
73 G_OBJECT_CLASS(klass)->dispose = fl_key_embedder_call_record_dispose;
74}
static void fl_key_embedder_call_record_dispose(GObject *object)

References fl_key_embedder_call_record_dispose().

◆ fl_key_embedder_call_record_dispose()

static void fl_key_embedder_call_record_dispose ( GObject *  object)
static

Definition at line 59 of file fl_key_embedder_responder_test.cc.

59 {
60 g_return_if_fail(FL_IS_KEY_EMBEDDER_CALL_RECORD(object));
61
62 FlKeyEmbedderCallRecord* self = FL_KEY_EMBEDDER_CALL_RECORD(object);
63 if (self->event != nullptr) {
64 g_free(const_cast<char*>(self->event->character));
65 g_free(self->event);
66 }
67 G_OBJECT_CLASS(fl_key_embedder_call_record_parent_class)->dispose(object);
68}

References self.

Referenced by fl_key_embedder_call_record_class_init().

◆ fl_key_embedder_call_record_new()

static FlKeyEmbedderCallRecord * fl_key_embedder_call_record_new ( const FlutterKeyEvent event,
FlutterKeyEventCallback  callback,
gpointer  user_data 
)
static

Definition at line 76 of file fl_key_embedder_responder_test.cc.

79 {
80 g_return_val_if_fail(event != nullptr, nullptr);
81
82 FlKeyEmbedderCallRecord* self = FL_KEY_EMBEDDER_CALL_RECORD(
83 g_object_new(fl_key_embedder_call_record_get_type(), nullptr));
84
85 FlutterKeyEvent* clone_event = g_new(FlutterKeyEvent, 1);
86 *clone_event = *event;
87 if (event->character != nullptr) {
88 size_t character_length = strlen(event->character);
89 char* clone_character = g_new(char, character_length + 1);
90 strncpy(clone_character, event->character, character_length + 1);
91 clone_event->character = clone_character;
92 }
93 self->event = clone_event;
94 self->callback = callback;
95 self->user_data = user_data;
96
97 return self;
98}
FlutterDesktopBinaryReply callback
const char * character
Definition embedder.h:1464

References callback, FlutterKeyEvent::character, self, and user_data.

Referenced by TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), and TEST_F().

◆ G_DECLARE_FINAL_TYPE()

G_DECLARE_FINAL_TYPE ( FlKeyEmbedderCallRecord  ,
fl_key_embedder_call_record  ,
FL  ,
KEY_EMBEDDER_CALL_RECORD  ,
GObject   
)

◆ G_DEFINE_TYPE()

G_DEFINE_TYPE ( FlKeyEmbedderCallRecord  ,
fl_key_embedder_call_record  ,
G_TYPE_OBJECT   
)

Definition at line 52 of file fl_key_embedder_responder_test.cc.

56 {}

◆ invoke_record_callback()

static void invoke_record_callback ( FlKeyEmbedderCallRecord *  record,
bool  expected_handled 
)
static

Definition at line 100 of file fl_key_embedder_responder_test.cc.

101 {
102 g_return_if_fail(record->callback != nullptr);
103 record->callback(expected_handled, record->user_data);
104}

Referenced by TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), and TEST_F().

◆ TEST_F() [1/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
HandlesShiftAltLeftIsMetaLeft   
)

Definition at line 2385 of file fl_key_embedder_responder_test.cc.

2385 {
2386 StartEngine();
2387
2388 g_autoptr(FlKeyEmbedderResponder) responder =
2390
2391 g_autoptr(GPtrArray) call_records =
2392 g_ptr_array_new_with_free_func(g_object_unref);
2394 SendKeyEvent,
2395 ([&call_records](auto engine, const FlutterKeyEvent* event,
2397 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
2398 event, callback, user_data));
2399 callback(true, user_data);
2400 return kSuccess;
2401 }));
2402
2403 guint32 now_time = 1;
2404 // A convenient shorthand to simulate events.
2405 auto send_key_event = [responder, &now_time](bool is_press, guint keyval,
2406 guint16 keycode,
2407 GdkModifierType state) {
2408 now_time += 1;
2409 g_autoptr(FlKeyEvent) event =
2410 fl_key_event_new(now_time, is_press, keycode, keyval, state, 0);
2411 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
2413 responder, event, 0, nullptr,
2414 [](GObject* object, GAsyncResult* result, gpointer user_data) {
2415 gboolean handled;
2417 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
2418 EXPECT_EQ(handled, TRUE);
2419
2420 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
2421 },
2422 loop);
2423 g_main_loop_run(loop);
2424 };
2425
2426 // ShiftLeft + AltLeft
2427 send_key_event(kPress, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
2428 GDK_MODIFIER_RESERVED_25_MASK);
2429 EXPECT_EQ(call_records->len, 1u);
2430 FlKeyEmbedderCallRecord* record =
2431 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
2432 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2433 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
2434 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
2435 EXPECT_EQ(record->event->synthesized, false);
2436
2437 send_key_event(kPress, GDK_KEY_Meta_L, kKeyCodeAltLeft,
2438 static_cast<GdkModifierType>(GDK_SHIFT_MASK |
2439 GDK_MODIFIER_RESERVED_25_MASK));
2440 EXPECT_EQ(call_records->len, 2u);
2441 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
2442 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2443 EXPECT_EQ(record->event->physical, kPhysicalMetaLeft);
2444 EXPECT_EQ(record->event->logical, kLogicalMetaLeft);
2445 EXPECT_EQ(record->event->synthesized, false);
2446
2447 send_key_event(kRelease, GDK_KEY_Meta_L, kKeyCodeAltLeft,
2448 static_cast<GdkModifierType>(GDK_MODIFIER_RESERVED_13_MASK |
2449 GDK_MODIFIER_RESERVED_25_MASK));
2450 send_key_event(kRelease, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
2451 GDK_MODIFIER_RESERVED_25_MASK);
2452 clear_records(call_records);
2453
2454 // ShiftRight + AltLeft
2455 send_key_event(kPress, GDK_KEY_Shift_R, kKeyCodeShiftRight,
2456 GDK_MODIFIER_RESERVED_25_MASK);
2457 EXPECT_EQ(call_records->len, 1u);
2458 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
2459 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2460 EXPECT_EQ(record->event->physical, kPhysicalShiftRight);
2461 EXPECT_EQ(record->event->logical, kLogicalShiftRight);
2462 EXPECT_EQ(record->event->synthesized, false);
2463
2464 send_key_event(kPress, GDK_KEY_Meta_L, kKeyCodeAltLeft,
2465 static_cast<GdkModifierType>(GDK_SHIFT_MASK |
2466 GDK_MODIFIER_RESERVED_25_MASK));
2467 EXPECT_EQ(call_records->len, 2u);
2468 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
2469 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2470 EXPECT_EQ(record->event->physical, kPhysicalMetaLeft);
2471 EXPECT_EQ(record->event->logical, kLogicalMetaLeft);
2472 EXPECT_EQ(record->event->synthesized, false);
2473}
@ kSuccess
Definition embedder.h:73
void(* FlutterKeyEventCallback)(bool, void *)
Definition embedder.h:1482
@ kFlutterKeyEventTypeDown
Definition embedder.h:1403
FlutterEngine engine
Definition main.cc:84
g_autoptr(FlEngine) engine
return TRUE
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition fl_engine.cc:920
FlKeyEmbedderResponder * fl_key_embedder_responder_new(FlEngine *engine)
void fl_key_embedder_responder_handle_event(FlKeyEmbedderResponder *self, FlKeyEvent *event, uint64_t specified_logical_key, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
gboolean fl_key_embedder_responder_handle_event_finish(FlKeyEmbedderResponder *self, GAsyncResult *result, gboolean *handled, GError **error)
static void clear_records(GPtrArray *array)
static FlKeyEmbedderCallRecord * fl_key_embedder_call_record_new(const FlutterKeyEvent *event, FlutterKeyEventCallback callback, gpointer user_data)
FlKeyEvent * fl_key_event_new(guint32 time, gboolean is_press, guint16 keycode, guint keyval, GdkModifierType state, guint8 group)
static void send_key_event(FlTextInputHandler *handler, gint keyval, gint state=0)
#define MOCK_ENGINE_PROC(proc, mock_impl)
FlutterEngineSendKeyEventFnPtr SendKeyEvent
Definition embedder.h:3776

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), kFlutterKeyEventTypeDown, kSuccess, MOCK_ENGINE_PROC, send_key_event(), FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [2/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
HandlesShiftAltVersusGroupNext   
)

Definition at line 2260 of file fl_key_embedder_responder_test.cc.

2260 {
2261 StartEngine();
2262
2263 g_autoptr(FlKeyEmbedderResponder) responder =
2265
2266 g_autoptr(GPtrArray) call_records =
2267 g_ptr_array_new_with_free_func(g_object_unref);
2269 SendKeyEvent,
2270 ([&call_records](auto engine, const FlutterKeyEvent* event,
2272 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
2273 event, callback, user_data));
2274 callback(true, user_data);
2275 return kSuccess;
2276 }));
2277
2278 guint32 now_time = 1;
2279 // A convenient shorthand to simulate events.
2280 auto send_key_event = [responder, &now_time](bool is_press, guint keyval,
2281 guint16 keycode,
2282 GdkModifierType state) {
2283 now_time += 1;
2284 g_autoptr(FlKeyEvent) event =
2285 fl_key_event_new(now_time, is_press, keycode, keyval, state, 0);
2286 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
2288 responder, event, 0, nullptr,
2289 [](GObject* object, GAsyncResult* result, gpointer user_data) {
2290 gboolean handled;
2292 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
2293 EXPECT_EQ(handled, TRUE);
2294
2295 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
2296 },
2297 loop);
2298 g_main_loop_run(loop);
2299 };
2300
2301 send_key_event(kPress, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
2302 GDK_MODIFIER_RESERVED_25_MASK);
2303 EXPECT_EQ(call_records->len, 1u);
2304 FlKeyEmbedderCallRecord* record =
2305 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
2306 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2307 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
2308 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
2309 EXPECT_EQ(record->event->synthesized, false);
2310
2311 send_key_event(kPress, GDK_KEY_Meta_R, kKeyCodeAltRight,
2312 static_cast<GdkModifierType>(GDK_SHIFT_MASK |
2313 GDK_MODIFIER_RESERVED_25_MASK));
2314 EXPECT_EQ(call_records->len, 2u);
2315 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
2316 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2317 EXPECT_EQ(record->event->physical, kPhysicalAltRight);
2318 EXPECT_EQ(record->event->logical, kLogicalMetaRight);
2319 EXPECT_EQ(record->event->synthesized, false);
2320
2321 send_key_event(kRelease, GDK_KEY_ISO_Next_Group, kKeyCodeShiftLeft,
2322 static_cast<GdkModifierType>(GDK_SHIFT_MASK | GDK_MOD1_MASK |
2323 GDK_MODIFIER_RESERVED_25_MASK));
2324 EXPECT_EQ(call_records->len, 5u);
2325 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 2));
2326 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2327 EXPECT_EQ(record->event->physical, kPhysicalAltLeft);
2328 EXPECT_EQ(record->event->logical, kLogicalAltLeft);
2329 EXPECT_EQ(record->event->synthesized, true);
2330
2331 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 3));
2332 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2333 EXPECT_EQ(record->event->physical, kPhysicalAltRight);
2334 EXPECT_EQ(record->event->logical, kLogicalMetaRight);
2335 EXPECT_EQ(record->event->synthesized, true);
2336
2337 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 4));
2338 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2339 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
2340 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
2341 EXPECT_EQ(record->event->synthesized, false);
2342
2343 send_key_event(kPress, GDK_KEY_ISO_Next_Group, kKeyCodeShiftLeft,
2344 static_cast<GdkModifierType>(GDK_MOD1_MASK |
2345 GDK_MODIFIER_RESERVED_25_MASK));
2346 EXPECT_EQ(call_records->len, 6u);
2347 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 5));
2348 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2349 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
2350 EXPECT_EQ(record->event->logical, kLogicalGroupNext);
2351 EXPECT_EQ(record->event->synthesized, false);
2352
2353 send_key_event(kRelease, GDK_KEY_ISO_Level3_Shift, kKeyCodeAltRight,
2354 static_cast<GdkModifierType>(GDK_MOD1_MASK |
2355 GDK_MODIFIER_RESERVED_13_MASK |
2356 GDK_MODIFIER_RESERVED_25_MASK));
2357 EXPECT_EQ(call_records->len, 7u);
2358 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 6));
2359 EXPECT_EQ(record->event->physical, 0u);
2360 EXPECT_EQ(record->event->logical, 0u);
2361
2362 send_key_event(kRelease, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
2363 static_cast<GdkModifierType>(GDK_MODIFIER_RESERVED_13_MASK |
2364 GDK_MODIFIER_RESERVED_25_MASK));
2365 EXPECT_EQ(call_records->len, 9u);
2366 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 7));
2367 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2368 EXPECT_EQ(record->event->physical, kPhysicalAltLeft);
2369 EXPECT_EQ(record->event->logical, kLogicalAltLeft);
2370 EXPECT_EQ(record->event->synthesized, true);
2371
2372 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 8));
2373 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2374 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
2375 EXPECT_EQ(record->event->logical, kLogicalGroupNext);
2376 EXPECT_EQ(record->event->synthesized, false);
2377}
@ kFlutterKeyEventTypeUp
Definition embedder.h:1402

References callback, engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kSuccess, MOCK_ENGINE_PROC, send_key_event(), FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [3/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
IgnoreAbruptUpEvent   
)

Definition at line 1419 of file fl_key_embedder_responder_test.cc.

1419 {
1420 StartEngine();
1421
1422 g_autoptr(FlKeyEmbedderResponder) responder =
1424
1425 g_autoptr(GPtrArray) call_records =
1426 g_ptr_array_new_with_free_func(g_object_unref);
1428 SendKeyEvent,
1429 ([&call_records](auto engine, const FlutterKeyEvent* event,
1431 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
1432 event, callback, user_data));
1433 return kSuccess;
1434 }));
1435
1436 // Release KeyA before it was even pressed.
1437 g_autoptr(FlKeyEvent) event =
1438 fl_key_event_new(103, kRelease, kKeyCodeKeyA, GDK_KEY_q,
1439 static_cast<GdkModifierType>(0), 0);
1440 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
1442 responder, event, 0, nullptr,
1443 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1444 gboolean handled;
1446 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1447 EXPECT_EQ(handled, TRUE);
1448
1449 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1450 },
1451 loop);
1452
1453 EXPECT_EQ(call_records->len, 1u);
1454
1455 FlKeyEmbedderCallRecord* record =
1456 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1457 EXPECT_EQ(record->event->physical, 0ull);
1458 EXPECT_EQ(record->event->logical, 0ull);
1459 EXPECT_STREQ(record->event->character, nullptr);
1460 EXPECT_EQ(record->event->synthesized, false);
1461
1463 g_main_loop_run(loop);
1464}
static void invoke_record_callback(FlKeyEmbedderCallRecord *record, bool expected_handled)
constexpr guint16 kKeyCodeKeyA

References callback, engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [4/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
PressShiftDuringLetterKeyTap   
)

Definition at line 305 of file fl_key_embedder_responder_test.cc.

305 {
306 StartEngine();
307
308 g_autoptr(FlKeyEmbedderResponder) responder =
310
311 g_autoptr(GPtrArray) call_records =
312 g_ptr_array_new_with_free_func(g_object_unref);
314 SendKeyEvent,
315 ([&call_records](auto engine, const FlutterKeyEvent* event,
317 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
318 event, callback, user_data));
319 return kSuccess;
320 }));
321
322 // Press shift right
323 g_autoptr(FlKeyEvent) event1 =
324 fl_key_event_new(101, kPress, kKeyCodeShiftRight, GDK_KEY_Shift_R,
325 static_cast<GdkModifierType>(0), 0);
326 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
328 responder, event1, 0, nullptr,
329 [](GObject* object, GAsyncResult* result, gpointer user_data) {
330 gboolean handled;
332 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
333 EXPECT_EQ(handled, TRUE);
334
335 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
336 },
337 loop1);
338
339 EXPECT_EQ(call_records->len, 1u);
340 FlKeyEmbedderCallRecord* record =
341 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
342 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
343 EXPECT_EQ(record->event->physical, kPhysicalShiftRight);
344 EXPECT_EQ(record->event->logical, kLogicalShiftRight);
345 EXPECT_STREQ(record->event->character, nullptr);
346 EXPECT_EQ(record->event->synthesized, false);
347
349 g_main_loop_run(loop1);
350 clear_records(call_records);
351
352 // Press key A
353 g_autoptr(FlKeyEvent) event2 =
354 fl_key_event_new(102, kPress, kKeyCodeKeyA, GDK_KEY_A, GDK_SHIFT_MASK, 0);
355 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
357 responder, event2, 0, nullptr,
358 [](GObject* object, GAsyncResult* result, gpointer user_data) {
359 gboolean handled;
361 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
362 EXPECT_EQ(handled, TRUE);
363
364 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
365 },
366 loop2);
367
368 EXPECT_EQ(call_records->len, 1u);
369 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
370 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
371 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
372 EXPECT_EQ(record->event->logical, kLogicalKeyA);
373 EXPECT_STREQ(record->event->character, "A");
374 EXPECT_EQ(record->event->synthesized, false);
375
377 g_main_loop_run(loop2);
378 clear_records(call_records);
379
380 // Release shift right
381 g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
382 103, kRelease, kKeyCodeShiftRight, GDK_KEY_Shift_R, GDK_SHIFT_MASK, 0);
383 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
385 responder, event3, 0, nullptr,
386 [](GObject* object, GAsyncResult* result, gpointer user_data) {
387 gboolean handled;
389 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
390 EXPECT_EQ(handled, TRUE);
391
392 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
393 },
394 loop3);
395
396 EXPECT_EQ(call_records->len, 1u);
397 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
398 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
399 EXPECT_EQ(record->event->physical, kPhysicalShiftRight);
400 EXPECT_EQ(record->event->logical, kLogicalShiftRight);
401 EXPECT_STREQ(record->event->character, nullptr);
402 EXPECT_EQ(record->event->synthesized, false);
403
405 g_main_loop_run(loop3);
406 clear_records(call_records);
407
408 // Release key A
409 g_autoptr(FlKeyEvent) event4 =
410 fl_key_event_new(104, kRelease, kKeyCodeKeyA, GDK_KEY_A,
411 static_cast<GdkModifierType>(0), 0);
412 g_autoptr(GMainLoop) loop4 = g_main_loop_new(nullptr, 0);
414 responder, event4, 0, nullptr,
415 [](GObject* object, GAsyncResult* result, gpointer user_data) {
416 gboolean handled;
418 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
419 EXPECT_EQ(handled, TRUE);
420
421 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
422 },
423 loop4);
424
425 EXPECT_EQ(call_records->len, 1u);
426 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
427 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
428 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
429 EXPECT_EQ(record->event->logical, kLogicalKeyA);
430 EXPECT_STREQ(record->event->character, nullptr);
431 EXPECT_EQ(record->event->synthesized, false);
432
434 g_main_loop_run(loop4);
435}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [5/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
ReleaseShiftKeyBetweenDigitKeyEvents   
)

Definition at line 693 of file fl_key_embedder_responder_test.cc.

693 {
694 StartEngine();
695
696 g_autoptr(FlKeyEmbedderResponder) responder =
698
699 g_autoptr(GPtrArray) call_records =
700 g_ptr_array_new_with_free_func(g_object_unref);
702 SendKeyEvent,
703 ([&call_records](auto engine, const FlutterKeyEvent* event,
705 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
706 event, callback, user_data));
707 return kSuccess;
708 }));
709
710 GdkModifierType state = static_cast<GdkModifierType>(0);
711
712 // Press shift left
713 g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
714 101, kPress, kKeyCodeShiftLeft, GDK_KEY_Shift_L, state, 0);
715 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
717 responder, event1, 0, nullptr,
718 [](GObject* object, GAsyncResult* result, gpointer user_data) {
719 gboolean handled;
721 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
722 EXPECT_EQ(handled, TRUE);
723
724 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
725 },
726 loop1);
727
728 EXPECT_EQ(call_records->len, 1u);
729 FlKeyEmbedderCallRecord* record =
730 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
731 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
732 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
733 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
734 EXPECT_STREQ(record->event->character, nullptr);
735 EXPECT_EQ(record->event->synthesized, false);
736
738 g_main_loop_run(loop1);
739 clear_records(call_records);
740
741 state = GDK_SHIFT_MASK;
742
743 // Press digit 1, which is '!' on a US keyboard
744 g_autoptr(FlKeyEvent) event2 =
745 fl_key_event_new(102, kPress, kKeyCodeDigit1, GDK_KEY_exclam, state, 0);
746 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
748 responder, event2, 0, nullptr,
749 [](GObject* object, GAsyncResult* result, gpointer user_data) {
750 gboolean handled;
752 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
753 EXPECT_EQ(handled, TRUE);
754
755 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
756 },
757 loop2);
758
759 EXPECT_EQ(call_records->len, 1u);
760 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
761 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
762 EXPECT_EQ(record->event->physical, kPhysicalDigit1);
763 EXPECT_EQ(record->event->logical, kLogicalExclamation);
764 EXPECT_STREQ(record->event->character, "!");
765 EXPECT_EQ(record->event->synthesized, false);
766
768 g_main_loop_run(loop2);
769 clear_records(call_records);
770
771 // Release shift
772 g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
773 103, kRelease, kKeyCodeShiftLeft, GDK_KEY_Shift_L, state, 0);
774 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
776 responder, event3, 0, nullptr,
777 [](GObject* object, GAsyncResult* result, gpointer user_data) {
778 gboolean handled;
780 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
781 EXPECT_EQ(handled, TRUE);
782
783 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
784 },
785 loop3);
786
787 EXPECT_EQ(call_records->len, 1u);
788 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
789 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
790 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
791 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
792 EXPECT_STREQ(record->event->character, nullptr);
793 EXPECT_EQ(record->event->synthesized, false);
794
796 g_main_loop_run(loop3);
797 clear_records(call_records);
798
799 state = static_cast<GdkModifierType>(0);
800
801 // Release digit 1, which is "1" because shift has been released.
802 g_autoptr(FlKeyEvent) event4 =
803 fl_key_event_new(104, kRelease, kKeyCodeDigit1, GDK_KEY_1, state, 0);
804 g_autoptr(GMainLoop) loop4 = g_main_loop_new(nullptr, 0);
806 responder, event4, 0, nullptr,
807 [](GObject* object, GAsyncResult* result, gpointer user_data) {
808 gboolean handled;
810 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
811 EXPECT_EQ(handled, TRUE);
812
813 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
814 },
815 loop4);
816
817 EXPECT_EQ(call_records->len, 1u);
818 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
819 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
820 EXPECT_EQ(record->event->physical, kPhysicalDigit1);
821 EXPECT_EQ(record->event->logical, kLogicalExclamation); // Important
822 EXPECT_STREQ(record->event->character, nullptr);
823 EXPECT_EQ(record->event->synthesized, false);
824
826 g_main_loop_run(loop4);
827}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [6/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
SendKeyEvent   
)

Definition at line 109 of file fl_key_embedder_responder_test.cc.

109 {
110 StartEngine();
111
112 g_autoptr(FlKeyEmbedderResponder) responder =
114
115 g_autoptr(GPtrArray) call_records =
116 g_ptr_array_new_with_free_func(g_object_unref);
118 SendKeyEvent,
119 ([&call_records](auto engine, const FlutterKeyEvent* event,
121 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
122 event, callback, user_data));
123 return kSuccess;
124 }));
125
126 // On a QWERTY keyboard, press key Q (physically key A), and release.
127 // Key down
128 g_autoptr(FlKeyEvent) event1 =
129 fl_key_event_new(12345, kPress, kKeyCodeKeyA, GDK_KEY_a,
130 static_cast<GdkModifierType>(0), 0);
131 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
133 responder, event1, 0, nullptr,
134 [](GObject* object, GAsyncResult* result, gpointer user_data) {
135 gboolean handled;
137 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
138 EXPECT_EQ(handled, TRUE);
139
140 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
141 },
142 loop1);
143
144 EXPECT_EQ(call_records->len, 1u);
145 FlKeyEmbedderCallRecord* record =
146 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
147 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
148 EXPECT_EQ(record->event->timestamp, 12345000);
149 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
150 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
151 EXPECT_EQ(record->event->logical, kLogicalKeyA);
152 EXPECT_STREQ(record->event->character, "a");
153 EXPECT_EQ(record->event->synthesized, false);
154
156 g_main_loop_run(loop1);
157 clear_records(call_records);
158
159 // Key up
160 g_autoptr(FlKeyEvent) event2 =
161 fl_key_event_new(12346, kRelease, kKeyCodeKeyA, GDK_KEY_a,
162 static_cast<GdkModifierType>(0), 0);
163 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
165 responder, event2, 0, nullptr,
166 [](GObject* object, GAsyncResult* result, gpointer user_data) {
167 gboolean handled;
169 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
170 EXPECT_EQ(handled, FALSE);
171
172 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
173 },
174 loop2);
175
176 EXPECT_EQ(call_records->len, 1u);
177 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
178 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
179 EXPECT_EQ(record->event->timestamp, 12346000);
180 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
181 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
182 EXPECT_EQ(record->event->logical, kLogicalKeyA);
183 EXPECT_STREQ(record->event->character, nullptr);
184 EXPECT_EQ(record->event->synthesized, false);
185
186 invoke_record_callback(record, FALSE);
187 g_main_loop_run(loop2);
188 clear_records(call_records);
189
190 // On an AZERTY keyboard, press key Q (physically key A), and release.
191 // Key down
192 g_autoptr(FlKeyEvent) event3 =
193 fl_key_event_new(12347, kPress, kKeyCodeKeyA, GDK_KEY_q,
194 static_cast<GdkModifierType>(0), 0);
195 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
197 responder, event3, 0, nullptr,
198 [](GObject* object, GAsyncResult* result, gpointer user_data) {
199 gboolean handled;
201 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
202 EXPECT_EQ(handled, TRUE);
203
204 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
205 },
206 loop3);
207
208 EXPECT_EQ(call_records->len, 1u);
209 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
210 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
211 EXPECT_EQ(record->event->timestamp, 12347000);
212 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
213 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
214 EXPECT_EQ(record->event->logical, kLogicalKeyQ);
215 EXPECT_STREQ(record->event->character, "q");
216 EXPECT_EQ(record->event->synthesized, false);
217
219 g_main_loop_run(loop3);
220 clear_records(call_records);
221
222 // Key up
223 g_autoptr(FlKeyEvent) event4 =
224 fl_key_event_new(12348, kRelease, kKeyCodeKeyA, GDK_KEY_q,
225 static_cast<GdkModifierType>(0), 0);
226 g_autoptr(GMainLoop) loop4 = g_main_loop_new(nullptr, 0);
228 responder, event4, 0, nullptr,
229 [](GObject* object, GAsyncResult* result, gpointer user_data) {
230 gboolean handled;
232 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
233 EXPECT_EQ(handled, FALSE);
234
235 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
236 },
237 loop4);
238
239 EXPECT_EQ(call_records->len, 1u);
240 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
241 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
242 EXPECT_EQ(record->event->timestamp, 12348000);
243 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
244 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
245 EXPECT_EQ(record->event->logical, kLogicalKeyQ);
246 EXPECT_STREQ(record->event->character, nullptr);
247 EXPECT_EQ(record->event->synthesized, false);
248
249 invoke_record_callback(record, FALSE);
250 g_main_loop_run(loop4);
251}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [7/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
SynthesizationOccursOnIgnoredEvents   
)

Definition at line 2193 of file fl_key_embedder_responder_test.cc.

2193 {
2194 StartEngine();
2195
2196 g_autoptr(FlKeyEmbedderResponder) responder =
2198
2199 g_autoptr(GPtrArray) call_records =
2200 g_ptr_array_new_with_free_func(g_object_unref);
2202 SendKeyEvent,
2203 ([&call_records](auto engine, const FlutterKeyEvent* event,
2205 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
2206 event, callback, user_data));
2207 return kSuccess;
2208 }));
2209
2210 // The NumLock is desynchronized by being enabled, and Control is pressed.
2211 GdkModifierType state =
2212 static_cast<GdkModifierType>(GDK_MOD2_MASK | GDK_CONTROL_MASK);
2213
2214 // Send a KeyA up event, which will be ignored.
2215 g_autoptr(FlKeyEvent) event =
2216 fl_key_event_new(101, kRelease, kKeyCodeKeyA, GDK_KEY_a, state, 0);
2217 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
2219 responder, event, 0, nullptr,
2220 [](GObject* object, GAsyncResult* result, gpointer user_data) {
2221 gboolean handled;
2223 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
2224 EXPECT_EQ(handled, TRUE);
2225
2226 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
2227 },
2228 loop);
2229 g_main_loop_run(loop);
2230
2231 EXPECT_EQ(call_records->len, 2u);
2232 FlKeyEmbedderCallRecord* record =
2233 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
2234 EXPECT_EQ(record->event->timestamp, 101000);
2235 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2236 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2237 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2238 EXPECT_STREQ(record->event->character, nullptr);
2239 EXPECT_EQ(record->event->synthesized, true);
2240
2241 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
2242 EXPECT_EQ(record->event->timestamp, 101000);
2243 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2244 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
2245 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
2246 EXPECT_STREQ(record->event->character, nullptr);
2247 EXPECT_EQ(record->event->synthesized, true);
2248}

References callback, engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), kFlutterKeyEventTypeDown, kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [8/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
SynthesizeForDesyncLockModeOnNonSelfEvents   
)

Definition at line 1925 of file fl_key_embedder_responder_test.cc.

1925 {
1926 StartEngine();
1927
1928 g_autoptr(FlKeyEmbedderResponder) responder =
1930
1931 g_autoptr(GPtrArray) call_records =
1932 g_ptr_array_new_with_free_func(g_object_unref);
1934 SendKeyEvent,
1935 ([&call_records](auto engine, const FlutterKeyEvent* event,
1937 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
1938 event, callback, user_data));
1939 return kSuccess;
1940 }));
1941
1942 // The NumLock is desynchronized by being enabled.
1943 GdkModifierType state = GDK_MOD2_MASK;
1944
1945 // Send a normal event
1946 g_autoptr(FlKeyEvent) event1 =
1947 fl_key_event_new(101, kPress, kKeyCodeKeyA, GDK_KEY_a, state, 0);
1948 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
1950 responder, event1, 0, nullptr,
1951 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1952 gboolean handled;
1954 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1955 EXPECT_EQ(handled, TRUE);
1956
1957 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1958 },
1959 loop1);
1960
1961 EXPECT_EQ(call_records->len, 2u);
1962 FlKeyEmbedderCallRecord* record =
1963 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1964 EXPECT_EQ(record->event->timestamp, 101000);
1965 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1966 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1967 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1968 EXPECT_STREQ(record->event->character, nullptr);
1969 EXPECT_EQ(record->event->synthesized, true);
1970
1971 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
1972 EXPECT_EQ(record->event->timestamp, 101000);
1973 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1974 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1975 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1976 EXPECT_STREQ(record->event->character, "a");
1977 EXPECT_EQ(record->event->synthesized, false);
1978
1980 g_main_loop_run(loop1);
1981 clear_records(call_records);
1982
1983 // The NumLock is desynchronized by being disabled.
1984 state = static_cast<GdkModifierType>(0);
1985
1986 // Release key A
1987 g_autoptr(FlKeyEvent) event2 =
1988 fl_key_event_new(102, kRelease, kKeyCodeKeyA, GDK_KEY_A, state, 0);
1989 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
1991 responder, event2, 0, nullptr,
1992 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1993 gboolean handled;
1995 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1996 EXPECT_EQ(handled, TRUE);
1997
1998 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1999 },
2000 loop2);
2001
2002 EXPECT_EQ(call_records->len, 4u);
2003 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
2004 EXPECT_EQ(record->event->timestamp, 102000);
2005 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2006 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2007 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2008 EXPECT_STREQ(record->event->character, nullptr);
2009 EXPECT_EQ(record->event->synthesized, true);
2010
2011 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
2012 EXPECT_EQ(record->event->timestamp, 102000);
2013 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2014 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2015 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2016 EXPECT_STREQ(record->event->character, nullptr);
2017 EXPECT_EQ(record->event->synthesized, true);
2018
2019 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 2));
2020 EXPECT_EQ(record->event->timestamp, 102000);
2021 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2022 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2023 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2024 EXPECT_STREQ(record->event->character, nullptr);
2025 EXPECT_EQ(record->event->synthesized, true);
2026
2027 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 3));
2028 EXPECT_EQ(record->event->timestamp, 102000);
2029 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2030 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
2031 EXPECT_EQ(record->event->logical, kLogicalKeyA);
2032 EXPECT_STREQ(record->event->character, nullptr);
2033 EXPECT_EQ(record->event->synthesized, false);
2034
2036 g_main_loop_run(loop2);
2037 clear_records(call_records);
2038
2039 // Release NumLock. Since the previous event should have synthesized NumLock
2040 // to be released, this should result in only an empty event.
2041 g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
2042 103, kRelease, kKeyCodeNumLock, GDK_KEY_Num_Lock, state, 0);
2043 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
2045 responder, event3, 0, nullptr,
2046 [](GObject* object, GAsyncResult* result, gpointer user_data) {
2047 gboolean handled;
2049 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
2050 EXPECT_EQ(handled, TRUE);
2051
2052 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
2053 },
2054 loop3);
2055
2056 EXPECT_EQ(call_records->len, 1u);
2057 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
2058 EXPECT_EQ(record->event->physical, 0ull);
2059 EXPECT_EQ(record->event->logical, 0ull);
2060 EXPECT_STREQ(record->event->character, nullptr);
2061 EXPECT_EQ(record->event->synthesized, false);
2062
2064 g_main_loop_run(loop3);
2065}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [9/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
SynthesizeForDesyncLockModeOnSelfEvents   
)

Definition at line 2069 of file fl_key_embedder_responder_test.cc.

2069 {
2070 StartEngine();
2071
2072 g_autoptr(FlKeyEmbedderResponder) responder =
2074
2075 g_autoptr(GPtrArray) call_records =
2076 g_ptr_array_new_with_free_func(g_object_unref);
2078 SendKeyEvent,
2079 ([&call_records](auto engine, const FlutterKeyEvent* event,
2081 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
2082 event, callback, user_data));
2083 return kSuccess;
2084 }));
2085
2086 // The NumLock is desynchronized by being enabled.
2087 GdkModifierType state = GDK_MOD2_MASK;
2088
2089 // NumLock down
2090 g_autoptr(FlKeyEvent) event1 = fl_key_event_new(101, kPress, kKeyCodeNumLock,
2091 GDK_KEY_Num_Lock, state, 0);
2092 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
2094 responder, event1, 0, nullptr,
2095 [](GObject* object, GAsyncResult* result, gpointer user_data) {
2096 gboolean handled;
2098 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
2099 EXPECT_EQ(handled, TRUE);
2100
2101 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
2102 },
2103 loop1);
2104
2105 EXPECT_EQ(call_records->len, 3u);
2106 FlKeyEmbedderCallRecord* record =
2107 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
2108 EXPECT_EQ(record->event->timestamp, 101000);
2109 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2110 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2111 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2112 EXPECT_STREQ(record->event->character, nullptr);
2113 EXPECT_EQ(record->event->synthesized, true);
2114
2115 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
2116 EXPECT_EQ(record->event->timestamp, 101000);
2117 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2118 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2119 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2120 EXPECT_STREQ(record->event->character, nullptr);
2121 EXPECT_EQ(record->event->synthesized, true);
2122
2123 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 2));
2124 EXPECT_EQ(record->event->timestamp, 101000);
2125 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2126 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2127 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2128 EXPECT_STREQ(record->event->character, nullptr);
2129 EXPECT_EQ(record->event->synthesized, false);
2130
2132 g_main_loop_run(loop1);
2133 clear_records(call_records);
2134
2135 // The NumLock is desynchronized by being enabled in a press event.
2136 state = GDK_MOD2_MASK;
2137
2138 // NumLock up
2139 g_autoptr(FlKeyEvent) event2 = fl_key_event_new(102, kPress, kKeyCodeNumLock,
2140 GDK_KEY_Num_Lock, state, 0);
2141 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
2143 responder, event2, 0, nullptr,
2144 [](GObject* object, GAsyncResult* result, gpointer user_data) {
2145 gboolean handled;
2147 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
2148 EXPECT_EQ(handled, TRUE);
2149
2150 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
2151 },
2152 loop2);
2153
2154 EXPECT_EQ(call_records->len, 4u);
2155 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
2156 EXPECT_EQ(record->event->timestamp, 102000);
2157 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2158 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2159 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2160 EXPECT_STREQ(record->event->character, nullptr);
2161 EXPECT_EQ(record->event->synthesized, true);
2162
2163 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
2164 EXPECT_EQ(record->event->timestamp, 102000);
2165 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2166 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2167 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2168 EXPECT_STREQ(record->event->character, nullptr);
2169 EXPECT_EQ(record->event->synthesized, true);
2170
2171 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 2));
2172 EXPECT_EQ(record->event->timestamp, 102000);
2173 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
2174 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2175 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2176 EXPECT_STREQ(record->event->character, nullptr);
2177 EXPECT_EQ(record->event->synthesized, true);
2178
2179 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 3));
2180 EXPECT_EQ(record->event->timestamp, 102000);
2181 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
2182 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
2183 EXPECT_EQ(record->event->logical, kLogicalNumLock);
2184 EXPECT_STREQ(record->event->character, nullptr);
2185 EXPECT_EQ(record->event->synthesized, false);
2186
2188 g_main_loop_run(loop2);
2189}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [10/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
SynthesizeForDesyncPressingStateOnNonSelfEvents   
)

Definition at line 1655 of file fl_key_embedder_responder_test.cc.

1656 {
1657 StartEngine();
1658
1659 g_autoptr(FlKeyEmbedderResponder) responder =
1661
1662 g_autoptr(GPtrArray) call_records =
1663 g_ptr_array_new_with_free_func(g_object_unref);
1665 SendKeyEvent,
1666 ([&call_records](auto engine, const FlutterKeyEvent* event,
1668 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
1669 event, callback, user_data));
1670 return kSuccess;
1671 }));
1672
1673 // A key down of control left is missed.
1674 GdkModifierType state = GDK_CONTROL_MASK;
1675
1676 // Send a normal event (KeyA down)
1677 g_autoptr(FlKeyEvent) event1 =
1678 fl_key_event_new(101, kPress, kKeyCodeKeyA, GDK_KEY_a, state, 0);
1679 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
1681 responder, event1, 0, nullptr,
1682 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1683 gboolean handled;
1685 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1686 EXPECT_EQ(handled, TRUE);
1687
1688 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1689 },
1690 loop1);
1691
1692 EXPECT_EQ(call_records->len, 2u);
1693 FlKeyEmbedderCallRecord* record =
1694 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1695 EXPECT_EQ(record->event->timestamp, 101000);
1696 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1697 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1698 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1699 EXPECT_STREQ(record->event->character, nullptr);
1700 EXPECT_EQ(record->event->synthesized, true);
1701
1702 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
1703 EXPECT_EQ(record->event->timestamp, 101000);
1704 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1705 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1706 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1707 EXPECT_STREQ(record->event->character, "a");
1708 EXPECT_EQ(record->event->synthesized, false);
1709
1711 g_main_loop_run(loop1);
1712 clear_records(call_records);
1713
1714 // A key up of control left is missed.
1715 state = static_cast<GdkModifierType>(0);
1716
1717 // Send a normal event (KeyA up)
1718 g_autoptr(FlKeyEvent) event2 =
1719 fl_key_event_new(102, kRelease, kKeyCodeKeyA, GDK_KEY_A, state, 0);
1720 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
1722 responder, event2, 0, nullptr,
1723 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1724 gboolean handled;
1726 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1727 EXPECT_EQ(handled, TRUE);
1728
1729 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1730 },
1731 loop2);
1732
1733 EXPECT_EQ(call_records->len, 2u);
1734 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1735 EXPECT_EQ(record->event->timestamp, 102000);
1736 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1737 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1738 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1739 EXPECT_STREQ(record->event->character, nullptr);
1740 EXPECT_EQ(record->event->synthesized, true);
1741
1742 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
1743 EXPECT_EQ(record->event->timestamp, 102000);
1744 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1745 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1746 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1747 EXPECT_STREQ(record->event->character, nullptr);
1748 EXPECT_EQ(record->event->synthesized, false);
1749
1751 g_main_loop_run(loop2);
1752 clear_records(call_records);
1753
1754 // Test non-default key mapping.
1755
1756 // Press a key with physical CapsLock and logical ControlLeft.
1757 state = static_cast<GdkModifierType>(0);
1758
1759 g_autoptr(FlKeyEvent) event3 = fl_key_event_new(101, kPress, kKeyCodeCapsLock,
1760 GDK_KEY_Control_L, state, 0);
1761 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
1763 responder, event3, 0, nullptr,
1764 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1765 gboolean handled;
1767 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1768 EXPECT_EQ(handled, TRUE);
1769
1770 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1771 },
1772 loop3);
1773
1774 EXPECT_EQ(call_records->len, 1u);
1775 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1776 EXPECT_EQ(record->event->timestamp, 101000);
1777 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1778 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1779 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1780 EXPECT_STREQ(record->event->character, nullptr);
1781 EXPECT_EQ(record->event->synthesized, false);
1782
1784 g_main_loop_run(loop3);
1785 clear_records(call_records);
1786
1787 // The key up of the control left press is missed.
1788 state = static_cast<GdkModifierType>(0);
1789
1790 // Send a normal event (KeyA down).
1791 g_autoptr(FlKeyEvent) event4 =
1792 fl_key_event_new(102, kPress, kKeyCodeKeyA, GDK_KEY_A, state, 0);
1793 g_autoptr(GMainLoop) loop4 = g_main_loop_new(nullptr, 0);
1795 responder, event4, 0, nullptr,
1796 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1797 gboolean handled;
1799 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1800 EXPECT_EQ(handled, TRUE);
1801
1802 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1803 },
1804 loop4);
1805
1806 // The synthesized event should have physical CapsLock and logical
1807 // ControlLeft.
1808 EXPECT_EQ(call_records->len, 2u);
1809 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1810 EXPECT_EQ(record->event->timestamp, 102000);
1811 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1812 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1813 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1814 EXPECT_STREQ(record->event->character, nullptr);
1815 EXPECT_EQ(record->event->synthesized, true);
1816
1817 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
1818 EXPECT_EQ(record->event->timestamp, 102000);
1819 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1820 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1821 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1822 EXPECT_STREQ(record->event->character, "A");
1823 EXPECT_EQ(record->event->synthesized, false);
1824
1826 g_main_loop_run(loop4);
1827}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [11/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
SynthesizeForDesyncPressingStateOnRemappedEvents   
)

Definition at line 1831 of file fl_key_embedder_responder_test.cc.

1832 {
1833 StartEngine();
1834
1835 g_autoptr(FlKeyEmbedderResponder) responder =
1837
1838 g_autoptr(GPtrArray) call_records =
1839 g_ptr_array_new_with_free_func(g_object_unref);
1841 SendKeyEvent,
1842 ([&call_records](auto engine, const FlutterKeyEvent* event,
1844 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
1845 event, callback, user_data));
1846 return kSuccess;
1847 }));
1848
1849 // Press a key with physical CapsLock and logical ControlLeft.
1850 GdkModifierType state = static_cast<GdkModifierType>(0);
1851
1852 g_autoptr(FlKeyEvent) event1 = fl_key_event_new(101, kPress, kKeyCodeCapsLock,
1853 GDK_KEY_Control_L, state, 0);
1854 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
1856 responder, event1, 0, nullptr,
1857 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1858 gboolean handled;
1860 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1861 EXPECT_EQ(handled, TRUE);
1862
1863 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1864 },
1865 loop1);
1866
1867 EXPECT_EQ(call_records->len, 1u);
1868 FlKeyEmbedderCallRecord* record =
1869 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1870 EXPECT_EQ(record->event->timestamp, 101000);
1871 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1872 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1873 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1874 EXPECT_STREQ(record->event->character, nullptr);
1875 EXPECT_EQ(record->event->synthesized, false);
1876
1878 g_main_loop_run(loop1);
1879 clear_records(call_records);
1880
1881 // The key up of the control left press is missed.
1882 state = static_cast<GdkModifierType>(0);
1883
1884 // Send a normal event (KeyA down).
1885 g_autoptr(FlKeyEvent) event2 =
1886 fl_key_event_new(102, kPress, kKeyCodeKeyA, GDK_KEY_A, state, 0);
1887 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
1889 responder, event2, 0, nullptr,
1890 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1891 gboolean handled;
1893 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1894 EXPECT_EQ(handled, TRUE);
1895
1896 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1897 },
1898 loop2);
1899
1900 // The synthesized event should have physical CapsLock and logical
1901 // ControlLeft.
1902 EXPECT_EQ(call_records->len, 2u);
1903 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1904 EXPECT_EQ(record->event->timestamp, 102000);
1905 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1906 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1907 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1908 EXPECT_STREQ(record->event->character, nullptr);
1909 EXPECT_EQ(record->event->synthesized, true);
1910
1911 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
1912 EXPECT_EQ(record->event->timestamp, 102000);
1913 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1914 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1915 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1916 EXPECT_STREQ(record->event->character, "A");
1917 EXPECT_EQ(record->event->synthesized, false);
1918
1920 g_main_loop_run(loop2);
1921}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [12/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
SynthesizeForDesyncPressingStateOnSelfEvents   
)

Definition at line 1468 of file fl_key_embedder_responder_test.cc.

1469 {
1470 StartEngine();
1471
1472 g_autoptr(FlKeyEmbedderResponder) responder =
1474
1475 g_autoptr(GPtrArray) call_records =
1476 g_ptr_array_new_with_free_func(g_object_unref);
1478 SendKeyEvent,
1479 ([&call_records](auto engine, const FlutterKeyEvent* event,
1481 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
1482 event, callback, user_data));
1483 return kSuccess;
1484 }));
1485
1486 // Test 1: synthesize key down.
1487
1488 // A key down of control left is missed.
1489 GdkModifierType state = GDK_CONTROL_MASK;
1490
1491 // Send a ControlLeft up
1492 g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
1493 101, kRelease, kKeyCodeControlLeft, GDK_KEY_Control_L, state, 0);
1494 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
1496 responder, event1, 0, nullptr,
1497 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1498 gboolean handled;
1500 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1501 EXPECT_EQ(handled, TRUE);
1502
1503 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1504 },
1505 loop1);
1506
1507 EXPECT_EQ(call_records->len, 2u);
1508 FlKeyEmbedderCallRecord* record =
1509 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1510 EXPECT_EQ(record->event->timestamp, 101000);
1511 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1512 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1513 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1514 EXPECT_STREQ(record->event->character, nullptr);
1515 EXPECT_EQ(record->event->synthesized, true);
1516
1517 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
1518 EXPECT_EQ(record->event->timestamp, 101000);
1519 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1520 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1521 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1522 EXPECT_STREQ(record->event->character, nullptr);
1523 EXPECT_EQ(record->event->synthesized, false);
1524
1526 g_main_loop_run(loop1);
1527 clear_records(call_records);
1528
1529 // Test 2: synthesize key up.
1530
1531 // Send a ControlLeft down.
1532 state = static_cast<GdkModifierType>(0);
1533 g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
1534 102, kPress, kKeyCodeControlLeft, GDK_KEY_Control_L, state, 0);
1535 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
1537 responder, event2, 0, nullptr,
1538 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1539 gboolean handled;
1541 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1542 EXPECT_EQ(handled, TRUE);
1543
1544 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1545 },
1546 loop2);
1547 EXPECT_EQ(call_records->len, 1u);
1548 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1550 g_main_loop_run(loop2);
1551 clear_records(call_records);
1552
1553 // A key up of control left is missed.
1554 state = static_cast<GdkModifierType>(0);
1555
1556 // Send another ControlLeft down
1557 g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
1558 103, kPress, kKeyCodeControlLeft, GDK_KEY_Control_L, state, 0);
1559 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
1561 responder, event3, 0, nullptr,
1562 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1563 gboolean handled;
1565 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1566 EXPECT_EQ(handled, TRUE);
1567
1568 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1569 },
1570 loop3);
1571
1572 EXPECT_EQ(call_records->len, 2u);
1573 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1574 EXPECT_EQ(record->event->timestamp, 103000);
1575 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1576 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1577 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1578 EXPECT_STREQ(record->event->character, nullptr);
1579 EXPECT_EQ(record->event->synthesized, true);
1580
1581 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 1));
1582 EXPECT_EQ(record->event->timestamp, 103000);
1583 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1584 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1585 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1586 EXPECT_STREQ(record->event->character, nullptr);
1587 EXPECT_EQ(record->event->synthesized, false);
1588
1590 g_main_loop_run(loop3);
1591 clear_records(call_records);
1592
1593 // Send a ControlLeft up to clear up state.
1594 state = GDK_CONTROL_MASK;
1595 g_autoptr(FlKeyEvent) event4 = fl_key_event_new(
1596 104, kRelease, kKeyCodeControlLeft, GDK_KEY_Control_L, state, 0);
1597 g_autoptr(GMainLoop) loop4 = g_main_loop_new(nullptr, 0);
1599 responder, event4, 0, nullptr,
1600 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1601 gboolean handled;
1603 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1604 EXPECT_EQ(handled, TRUE);
1605
1606 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1607 },
1608 loop4);
1609 EXPECT_EQ(call_records->len, 1u);
1610 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1612 g_main_loop_run(loop4);
1613 clear_records(call_records);
1614
1615 // Test 3: synthesize by right modifier.
1616
1617 // A key down of control right is missed.
1618 state = GDK_CONTROL_MASK;
1619
1620 // Send a ControlRight up.
1621 g_autoptr(FlKeyEvent) event5 = fl_key_event_new(
1622 105, kRelease, kKeyCodeControlRight, GDK_KEY_Control_R, state, 0);
1623 g_autoptr(GMainLoop) loop5 = g_main_loop_new(nullptr, 0);
1625 responder, event5, 0, nullptr,
1626 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1627 gboolean handled;
1629 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1630 EXPECT_EQ(handled, TRUE);
1631
1632 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1633 },
1634 loop5);
1635
1636 // A ControlLeft down is synthesized, with an empty event.
1637 // Reason: The ControlLeft down is synthesized to synchronize the state
1638 // showing Control as pressed. The ControlRight event is ignored because
1639 // the event is considered a duplicate up event.
1640 EXPECT_EQ(call_records->len, 1u);
1641 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1642 EXPECT_EQ(record->event->timestamp, 105000);
1643 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1644 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1645 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1646 EXPECT_STREQ(record->event->character, nullptr);
1647 EXPECT_EQ(record->event->synthesized, true);
1648
1650 g_main_loop_run(loop5);
1651}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [13/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
TapLetterKeysBetweenCapsLockEvents   
)

Definition at line 833 of file fl_key_embedder_responder_test.cc.

833 {
834 StartEngine();
835
836 g_autoptr(FlKeyEmbedderResponder) responder =
838
839 g_autoptr(GPtrArray) call_records =
840 g_ptr_array_new_with_free_func(g_object_unref);
842 SendKeyEvent,
843 ([&call_records](auto engine, const FlutterKeyEvent* event,
845 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
846 event, callback, user_data));
847 return kSuccess;
848 }));
849
850 // Press CapsLock (stage 0 -> 1)
851 g_autoptr(FlKeyEvent) event1 =
852 fl_key_event_new(101, kPress, kKeyCodeCapsLock, GDK_KEY_Caps_Lock,
853 static_cast<GdkModifierType>(0), 0);
854 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
856 responder, event1, 0, nullptr,
857 [](GObject* object, GAsyncResult* result, gpointer user_data) {
858 gboolean handled;
860 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
861 EXPECT_EQ(handled, TRUE);
862
863 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
864 },
865 loop1);
866
867 EXPECT_EQ(call_records->len, 1u);
868 FlKeyEmbedderCallRecord* record =
869 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
870 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
871 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
872 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
873 EXPECT_STREQ(record->event->character, nullptr);
874 EXPECT_EQ(record->event->synthesized, false);
875
877 g_main_loop_run(loop1);
878 clear_records(call_records);
879
880 // Press key A (stage 1)
881 g_autoptr(FlKeyEvent) event2 =
882 fl_key_event_new(102, kPress, kKeyCodeKeyA, GDK_KEY_A, GDK_LOCK_MASK, 0);
883 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
885 responder, event2, 0, nullptr,
886 [](GObject* object, GAsyncResult* result, gpointer user_data) {
887 gboolean handled;
889 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
890 EXPECT_EQ(handled, TRUE);
891
892 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
893 },
894 loop2);
895
896 EXPECT_EQ(call_records->len, 1u);
897 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
898 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
899 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
900 EXPECT_EQ(record->event->logical, kLogicalKeyA);
901 EXPECT_STREQ(record->event->character, "A");
902 EXPECT_EQ(record->event->synthesized, false);
903
905 g_main_loop_run(loop2);
906 clear_records(call_records);
907
908 // Release CapsLock (stage 1 -> 2)
909 g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
910 103, kRelease, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
911 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
913 responder, event3, 0, nullptr,
914 [](GObject* object, GAsyncResult* result, gpointer user_data) {
915 gboolean handled;
917 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
918 EXPECT_EQ(handled, TRUE);
919
920 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
921 },
922 loop3);
923
924 EXPECT_EQ(call_records->len, 1u);
925 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
926 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
927 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
928 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
929 EXPECT_STREQ(record->event->character, nullptr);
930 EXPECT_EQ(record->event->synthesized, false);
931
933 g_main_loop_run(loop3);
934 clear_records(call_records);
935
936 // Release key A (stage 2)
937 g_autoptr(FlKeyEvent) event4 = fl_key_event_new(104, kRelease, kKeyCodeKeyA,
938 GDK_KEY_A, GDK_LOCK_MASK, 0);
939 g_autoptr(GMainLoop) loop4 = g_main_loop_new(nullptr, 0);
941 responder, event4, 0, nullptr,
942 [](GObject* object, GAsyncResult* result, gpointer user_data) {
943 gboolean handled;
945 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
946 EXPECT_EQ(handled, TRUE);
947
948 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
949 },
950 loop4);
951
952 EXPECT_EQ(call_records->len, 1u);
953 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
954 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
955 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
956 EXPECT_EQ(record->event->logical, kLogicalKeyA);
957 EXPECT_STREQ(record->event->character, nullptr);
958 EXPECT_EQ(record->event->synthesized, false);
959
961 g_main_loop_run(loop4);
962 clear_records(call_records);
963
964 // Press CapsLock (stage 2 -> 3)
965 g_autoptr(FlKeyEvent) event5 = fl_key_event_new(
966 105, kPress, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
967 g_autoptr(GMainLoop) loop5 = g_main_loop_new(nullptr, 0);
969 responder, event5, 0, nullptr,
970 [](GObject* object, GAsyncResult* result, gpointer user_data) {
971 gboolean handled;
973 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
974 EXPECT_EQ(handled, TRUE);
975
976 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
977 },
978 loop5);
979
980 EXPECT_EQ(call_records->len, 1u);
981 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
982 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
983 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
984 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
985 EXPECT_STREQ(record->event->character, nullptr);
986 EXPECT_EQ(record->event->synthesized, false);
987
989 g_main_loop_run(loop5);
990 clear_records(call_records);
991
992 // Press key A (stage 3)
993 g_autoptr(FlKeyEvent) event6 =
994 fl_key_event_new(106, kPress, kKeyCodeKeyA, GDK_KEY_A, GDK_LOCK_MASK, 0);
995 g_autoptr(GMainLoop) loop6 = g_main_loop_new(nullptr, 0);
997 responder, event6, 0, nullptr,
998 [](GObject* object, GAsyncResult* result, gpointer user_data) {
999 gboolean handled;
1001 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1002 EXPECT_EQ(handled, TRUE);
1003
1004 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1005 },
1006 loop6);
1007
1008 EXPECT_EQ(call_records->len, 1u);
1009 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1010 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1011 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1012 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1013 EXPECT_STREQ(record->event->character, "A");
1014 EXPECT_EQ(record->event->synthesized, false);
1015
1017 g_main_loop_run(loop6);
1018 clear_records(call_records);
1019
1020 // Release CapsLock (stage 3 -> 0)
1021 g_autoptr(FlKeyEvent) event7 = fl_key_event_new(
1022 107, kRelease, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
1023 g_autoptr(GMainLoop) loop7 = g_main_loop_new(nullptr, 0);
1025 responder, event7, 0, nullptr,
1026 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1027 gboolean handled;
1029 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1030 EXPECT_EQ(handled, TRUE);
1031
1032 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1033 },
1034 loop7);
1035
1036 EXPECT_EQ(call_records->len, 1u);
1037 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1038 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1039 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1040 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
1041 EXPECT_STREQ(record->event->character, nullptr);
1042 EXPECT_EQ(record->event->synthesized, false);
1043
1045 g_main_loop_run(loop7);
1046 clear_records(call_records);
1047
1048 // Release key A (stage 0)
1049 g_autoptr(FlKeyEvent) event8 =
1050 fl_key_event_new(108, kRelease, kKeyCodeKeyA, GDK_KEY_a,
1051 static_cast<GdkModifierType>(0), 0);
1052 g_autoptr(GMainLoop) loop8 = g_main_loop_new(nullptr, 0);
1054 responder, event8, 0, nullptr,
1055 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1056 gboolean handled;
1058 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1059 EXPECT_EQ(handled, TRUE);
1060
1061 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1062 },
1063 loop8);
1064
1065 EXPECT_EQ(call_records->len, 1u);
1066 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1067 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1068 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1069 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1070 EXPECT_STREQ(record->event->character, nullptr);
1071 EXPECT_EQ(record->event->synthesized, false);
1072
1074 g_main_loop_run(loop8);
1075}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [14/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
TapLetterKeysBetweenCapsLockEventsReversed   
)

Definition at line 1081 of file fl_key_embedder_responder_test.cc.

1081 {
1082 StartEngine();
1083
1084 g_autoptr(FlKeyEmbedderResponder) responder =
1086
1087 g_autoptr(GPtrArray) call_records =
1088 g_ptr_array_new_with_free_func(g_object_unref);
1090 SendKeyEvent,
1091 ([&call_records](auto engine, const FlutterKeyEvent* event,
1093 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
1094 event, callback, user_data));
1095 return kSuccess;
1096 }));
1097
1098 // Press key A (stage 0)
1099 g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
1100 101, kPress, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
1101 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
1103 responder, event1, 0, nullptr,
1104 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1105 gboolean handled;
1107 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1108 EXPECT_EQ(handled, TRUE);
1109
1110 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1111 },
1112 loop1);
1113
1114 EXPECT_EQ(call_records->len, 1u);
1115 FlKeyEmbedderCallRecord* record =
1116 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1117 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1118 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1119 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1120 EXPECT_STREQ(record->event->character, "a");
1121 EXPECT_EQ(record->event->synthesized, false);
1122
1124 g_main_loop_run(loop1);
1125 clear_records(call_records);
1126
1127 // Press CapsLock (stage 0 -> 1)
1128 g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
1129 102, kPress, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
1130 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
1132 responder, event2, 0, nullptr,
1133 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1134 gboolean handled;
1136 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1137 EXPECT_EQ(handled, TRUE);
1138
1139 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1140 },
1141 loop2);
1142
1143 EXPECT_EQ(call_records->len, 1u);
1144 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1145 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1146 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1147 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
1148 EXPECT_STREQ(record->event->character, nullptr);
1149 EXPECT_EQ(record->event->synthesized, false);
1150
1152 g_main_loop_run(loop2);
1153 clear_records(call_records);
1154
1155 // Release CapsLock (stage 1 -> 2)
1156 g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
1157 103, kRelease, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
1158 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
1160 responder, event3, 0, nullptr,
1161 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1162 gboolean handled;
1164 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1165 EXPECT_EQ(handled, TRUE);
1166
1167 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1168 },
1169 loop3);
1170
1171 EXPECT_EQ(call_records->len, 1u);
1172 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1173 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1174 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1175 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
1176 EXPECT_STREQ(record->event->character, nullptr);
1177 EXPECT_EQ(record->event->synthesized, false);
1178
1180 g_main_loop_run(loop3);
1181 clear_records(call_records);
1182
1183 // Release key A (stage 2)
1184 g_autoptr(FlKeyEvent) event4 = fl_key_event_new(104, kRelease, kKeyCodeKeyA,
1185 GDK_KEY_A, GDK_LOCK_MASK, 0);
1186 g_autoptr(GMainLoop) loop4 = g_main_loop_new(nullptr, 0);
1188 responder, event4, 0, nullptr,
1189 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1190 gboolean handled;
1192 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1193 EXPECT_EQ(handled, TRUE);
1194
1195 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1196 },
1197 loop4);
1198
1199 EXPECT_EQ(call_records->len, 1u);
1200 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1201 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1202 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1203 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1204 EXPECT_STREQ(record->event->character, nullptr);
1205 EXPECT_EQ(record->event->synthesized, false);
1206
1208 g_main_loop_run(loop4);
1209 clear_records(call_records);
1210
1211 // Press key A (stage 2)
1212 g_autoptr(FlKeyEvent) event5 =
1213 fl_key_event_new(105, kPress, kKeyCodeKeyA, GDK_KEY_A, GDK_LOCK_MASK, 0);
1214 g_autoptr(GMainLoop) loop5 = g_main_loop_new(nullptr, 0);
1216 responder, event5, 0, nullptr,
1217 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1218 gboolean handled;
1220 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1221 EXPECT_EQ(handled, TRUE);
1222
1223 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1224 },
1225 loop5);
1226
1227 EXPECT_EQ(call_records->len, 1u);
1228 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1229 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1230 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1231 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1232 EXPECT_STREQ(record->event->character, "A");
1233 EXPECT_EQ(record->event->synthesized, false);
1234
1236 g_main_loop_run(loop5);
1237 clear_records(call_records);
1238
1239 // Press CapsLock (stage 2 -> 3)
1240 g_autoptr(FlKeyEvent) event6 =
1241 fl_key_event_new(106, kPress, kKeyCodeCapsLock, GDK_KEY_Caps_Lock,
1242 static_cast<GdkModifierType>(0), 0);
1243 g_autoptr(GMainLoop) loop6 = g_main_loop_new(nullptr, 0);
1245 responder, event6, 0, nullptr,
1246 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1247 gboolean handled;
1249 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1250 EXPECT_EQ(handled, TRUE);
1251
1252 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1253 },
1254 loop6);
1255
1256 EXPECT_EQ(call_records->len, 1u);
1257 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1258 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1259 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1260 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
1261 EXPECT_STREQ(record->event->character, nullptr);
1262 EXPECT_EQ(record->event->synthesized, false);
1263
1265 g_main_loop_run(loop6);
1266 clear_records(call_records);
1267
1268 // Release CapsLock (stage 3 -> 0)
1269 g_autoptr(FlKeyEvent) event7 = fl_key_event_new(
1270 107, kRelease, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
1271 g_autoptr(GMainLoop) loop7 = g_main_loop_new(nullptr, 0);
1273 responder, event7, 0, nullptr,
1274 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1275 gboolean handled;
1277 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1278 EXPECT_EQ(handled, TRUE);
1279
1280 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1281 },
1282 loop7);
1283
1284 EXPECT_EQ(call_records->len, 1u);
1285 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1286 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1287 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1288 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
1289 EXPECT_STREQ(record->event->character, nullptr);
1290 EXPECT_EQ(record->event->synthesized, false);
1291
1293 g_main_loop_run(loop7);
1294 clear_records(call_records);
1295
1296 // Release key A (stage 0)
1297 g_autoptr(FlKeyEvent) event8 =
1298 fl_key_event_new(108, kRelease, kKeyCodeKeyA, GDK_KEY_a,
1299 static_cast<GdkModifierType>(0), 0);
1300 g_autoptr(GMainLoop) loop8 = g_main_loop_new(nullptr, 0);
1302 responder, event8, 0, nullptr,
1303 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1304 gboolean handled;
1306 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1307 EXPECT_EQ(handled, TRUE);
1308
1309 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1310 },
1311 loop8);
1312
1313 EXPECT_EQ(call_records->len, 1u);
1314 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1315 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1316 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1317 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1318 EXPECT_STREQ(record->event->character, nullptr);
1319 EXPECT_EQ(record->event->synthesized, false);
1320
1322 g_main_loop_run(loop8);
1323}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [15/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
TapNumPadKeysBetweenNumLockEvents   
)

Definition at line 445 of file fl_key_embedder_responder_test.cc.

445 {
446 StartEngine();
447
448 g_autoptr(FlKeyEmbedderResponder) responder =
450
451 g_autoptr(GPtrArray) call_records =
452 g_ptr_array_new_with_free_func(g_object_unref);
454 SendKeyEvent,
455 ([&call_records](auto engine, const FlutterKeyEvent* event,
457 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
458 event, callback, user_data));
459 return kSuccess;
460 }));
461
462 // Press Numpad 1 (stage 0)
463 g_autoptr(FlKeyEvent) event1 =
464 fl_key_event_new(101, kPress, kKeyCodeNumpad1, GDK_KEY_KP_End,
465 static_cast<GdkModifierType>(0), 0);
466 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
468 responder, event1, 0, nullptr,
469 [](GObject* object, GAsyncResult* result, gpointer user_data) {
470 gboolean handled;
472 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
473 EXPECT_EQ(handled, TRUE);
474
475 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
476 },
477 loop1);
478
479 EXPECT_EQ(call_records->len, 1u);
480 FlKeyEmbedderCallRecord* record =
481 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
482 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
483 EXPECT_EQ(record->event->physical, kPhysicalNumpad1);
484 EXPECT_EQ(record->event->logical, kLogicalNumpad1);
485 EXPECT_STREQ(record->event->character, nullptr); // TODO(chrome-bot):
486 EXPECT_EQ(record->event->synthesized, false);
487
489 g_main_loop_run(loop1);
490 clear_records(call_records);
491
492 // Press NumLock (stage 0 -> 1)
493 g_autoptr(FlKeyEvent) event2 =
494 fl_key_event_new(102, kPress, kKeyCodeNumLock, GDK_KEY_Num_Lock,
495 static_cast<GdkModifierType>(0), 0);
496 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
498 responder, event2, 0, nullptr,
499 [](GObject* object, GAsyncResult* result, gpointer user_data) {
500 gboolean handled;
502 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
503 EXPECT_EQ(handled, TRUE);
504
505 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
506 },
507 loop2);
508
509 EXPECT_EQ(call_records->len, 1u);
510 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
511 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
512 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
513 EXPECT_EQ(record->event->logical, kLogicalNumLock);
514 EXPECT_STREQ(record->event->character, nullptr);
515 EXPECT_EQ(record->event->synthesized, false);
516
518 g_main_loop_run(loop2);
519 clear_records(call_records);
520
521 // Release numpad 1 (stage 1)
522 g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
523 104, kRelease, kKeyCodeNumpad1, GDK_KEY_KP_1, GDK_MOD2_MASK, 0);
524 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
526 responder, event3, 0, nullptr,
527 [](GObject* object, GAsyncResult* result, gpointer user_data) {
528 gboolean handled;
530 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
531 EXPECT_EQ(handled, TRUE);
532
533 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
534 },
535 loop3);
536
537 EXPECT_EQ(call_records->len, 1u);
538 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
539 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
540 EXPECT_EQ(record->event->physical, kPhysicalNumpad1);
541 EXPECT_EQ(record->event->logical, kLogicalNumpad1);
542 EXPECT_STREQ(record->event->character, nullptr);
543 EXPECT_EQ(record->event->synthesized, false);
544
546 g_main_loop_run(loop3);
547 clear_records(call_records);
548
549 // Release NumLock (stage 1 -> 2)
550 g_autoptr(FlKeyEvent) event4 = fl_key_event_new(
551 103, kRelease, kKeyCodeNumLock, GDK_KEY_Num_Lock, GDK_MOD2_MASK, 0);
552 g_autoptr(GMainLoop) loop4 = g_main_loop_new(nullptr, 0);
554 responder, event4, 0, nullptr,
555 [](GObject* object, GAsyncResult* result, gpointer user_data) {
556 gboolean handled;
558 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
559 EXPECT_EQ(handled, TRUE);
560
561 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
562 },
563 loop4);
564
565 EXPECT_EQ(call_records->len, 1u);
566 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
567 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
568 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
569 EXPECT_EQ(record->event->logical, kLogicalNumLock);
570 EXPECT_STREQ(record->event->character, nullptr);
571 EXPECT_EQ(record->event->synthesized, false);
572
574 g_main_loop_run(loop4);
575 clear_records(call_records);
576
577 // Press Numpad 1 (stage 2)
578 g_autoptr(FlKeyEvent) event5 = fl_key_event_new(
579 101, kPress, kKeyCodeNumpad1, GDK_KEY_KP_End, GDK_MOD2_MASK, 0);
580 g_autoptr(GMainLoop) loop5 = g_main_loop_new(nullptr, 0);
582 responder, event5, 0, nullptr,
583 [](GObject* object, GAsyncResult* result, gpointer user_data) {
584 gboolean handled;
586 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
587 EXPECT_EQ(handled, TRUE);
588
589 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
590 },
591 loop5);
592
593 EXPECT_EQ(call_records->len, 1u);
594 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
595 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
596 EXPECT_EQ(record->event->physical, kPhysicalNumpad1);
597 EXPECT_EQ(record->event->logical, kLogicalNumpad1);
598 EXPECT_STREQ(record->event->character, nullptr); // TODO(chrome-bot):
599 EXPECT_EQ(record->event->synthesized, false);
600
602 g_main_loop_run(loop5);
603 clear_records(call_records);
604
605 // Press NumLock (stage 2 -> 3)
606 g_autoptr(FlKeyEvent) event6 = fl_key_event_new(
607 102, kPress, kKeyCodeNumLock, GDK_KEY_Num_Lock, GDK_MOD2_MASK, 0);
608 g_autoptr(GMainLoop) loop6 = g_main_loop_new(nullptr, 0);
610 responder, event6, 0, nullptr,
611 [](GObject* object, GAsyncResult* result, gpointer user_data) {
612 gboolean handled;
614 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
615 EXPECT_EQ(handled, TRUE);
616
617 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
618 },
619 loop6);
620
621 EXPECT_EQ(call_records->len, 1u);
622 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
623 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
624 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
625 EXPECT_EQ(record->event->logical, kLogicalNumLock);
626 EXPECT_STREQ(record->event->character, nullptr);
627 EXPECT_EQ(record->event->synthesized, false);
628
630 g_main_loop_run(loop6);
631 clear_records(call_records);
632
633 // Release numpad 1 (stage 3)
634 g_autoptr(FlKeyEvent) event7 = fl_key_event_new(
635 104, kRelease, kKeyCodeNumpad1, GDK_KEY_KP_1, GDK_MOD2_MASK, 0);
636 g_autoptr(GMainLoop) loop7 = g_main_loop_new(nullptr, 0);
638 responder, event7, 0, nullptr,
639 [](GObject* object, GAsyncResult* result, gpointer user_data) {
640 gboolean handled;
642 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
643 EXPECT_EQ(handled, TRUE);
644
645 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
646 },
647 loop7);
648
649 EXPECT_EQ(call_records->len, 1u);
650 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
651 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
652 EXPECT_EQ(record->event->physical, kPhysicalNumpad1);
653 EXPECT_EQ(record->event->logical, kLogicalNumpad1);
654 EXPECT_STREQ(record->event->character, nullptr);
655 EXPECT_EQ(record->event->synthesized, false);
656
658 g_main_loop_run(loop7);
659 clear_records(call_records);
660
661 // Release NumLock (stage 3 -> 0)
662 g_autoptr(FlKeyEvent) event8 = fl_key_event_new(
663 103, kRelease, kKeyCodeNumLock, GDK_KEY_Num_Lock, GDK_MOD2_MASK, 0);
664 g_autoptr(GMainLoop) loop8 = g_main_loop_new(nullptr, 0);
666 responder, event8, 0, nullptr,
667 [](GObject* object, GAsyncResult* result, gpointer user_data) {
668 gboolean handled;
670 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
671 EXPECT_EQ(handled, TRUE);
672
673 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
674 },
675 loop8);
676
677 EXPECT_EQ(call_records->len, 1u);
678 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
679 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
680 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
681 EXPECT_EQ(record->event->logical, kLogicalNumLock);
682 EXPECT_STREQ(record->event->character, nullptr);
683 EXPECT_EQ(record->event->synthesized, false);
684
686 g_main_loop_run(loop8);
687}

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kFlutterKeyEventTypeUp, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [16/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
TurnDuplicateDownEventsToRepeats   
)

Definition at line 1325 of file fl_key_embedder_responder_test.cc.

1325 {
1326 StartEngine();
1327
1328 g_autoptr(FlKeyEmbedderResponder) responder =
1330
1331 g_autoptr(GPtrArray) call_records =
1332 g_ptr_array_new_with_free_func(g_object_unref);
1334 SendKeyEvent,
1335 ([&call_records](auto engine, const FlutterKeyEvent* event,
1337 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
1338 event, callback, user_data));
1339 return kSuccess;
1340 }));
1341
1342 // Press KeyA
1343 g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
1344 101, kPress, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
1345 g_autoptr(GMainLoop) loop1 = g_main_loop_new(nullptr, 0);
1347 responder, event1, 0, nullptr,
1348 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1349 gboolean handled;
1351 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1352 EXPECT_EQ(handled, TRUE);
1353
1354 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1355 },
1356 loop1);
1357
1358 EXPECT_EQ(call_records->len, 1u);
1359
1360 FlKeyEmbedderCallRecord* record =
1361 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1363 g_main_loop_run(loop1);
1364 clear_records(call_records);
1365
1366 // Another KeyA down events, which usually means a repeated event.
1367 g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
1368 102, kPress, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
1369 g_autoptr(GMainLoop) loop2 = g_main_loop_new(nullptr, 0);
1371 responder, event2, 0, nullptr,
1372 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1373 gboolean handled;
1375 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1376 EXPECT_EQ(handled, TRUE);
1377
1378 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1379 },
1380 loop2);
1381
1382 EXPECT_EQ(call_records->len, 1u);
1383
1384 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1385 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeRepeat);
1386 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1387 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1388 EXPECT_STREQ(record->event->character, "a");
1389 EXPECT_EQ(record->event->synthesized, false);
1390 EXPECT_NE(record->callback, nullptr);
1391
1393 g_main_loop_run(loop2);
1394 clear_records(call_records);
1395
1396 // Release KeyA
1397 g_autoptr(FlKeyEvent) event3 =
1398 fl_key_event_new(103, kRelease, kKeyCodeKeyA, GDK_KEY_q,
1399 static_cast<GdkModifierType>(0), 0);
1400 g_autoptr(GMainLoop) loop3 = g_main_loop_new(nullptr, 0);
1402 responder, event3, 0, nullptr,
1403 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1404 gboolean handled;
1406 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
1407 EXPECT_EQ(handled, TRUE);
1408
1409 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1410 },
1411 loop3);
1412
1413 EXPECT_EQ(call_records->len, 1u);
1414 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
1416 g_main_loop_run(loop3);
1417}
@ kFlutterKeyEventTypeRepeat
Definition embedder.h:1404

References callback, clear_records(), engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeRepeat, kKeyCodeKeyA, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.

◆ TEST_F() [17/17]

TEST_F ( FlKeyEmbedderResponderTest  ,
UsesSpecifiedLogicalKey   
)

Definition at line 254 of file fl_key_embedder_responder_test.cc.

254 {
255 StartEngine();
256
257 g_autoptr(FlKeyEmbedderResponder) responder =
259
260 g_autoptr(GPtrArray) call_records =
261 g_ptr_array_new_with_free_func(g_object_unref);
263 SendKeyEvent,
264 ([&call_records](auto engine, const FlutterKeyEvent* event,
266 g_ptr_array_add(call_records, fl_key_embedder_call_record_new(
267 event, callback, user_data));
268 return kSuccess;
269 }));
270
271 // On an AZERTY keyboard, press physical key 1, and release.
272 // Key down
273 g_autoptr(FlKeyEvent) event =
274 fl_key_event_new(12345, kPress, kKeyCodeDigit1, GDK_KEY_ampersand,
275 static_cast<GdkModifierType>(0), 0);
276 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
278 responder, event, kLogicalDigit1, nullptr,
279 [](GObject* object, GAsyncResult* result, gpointer user_data) {
280 gboolean handled;
282 FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, nullptr));
283 EXPECT_EQ(handled, TRUE);
284
285 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
286 },
287 loop);
288
289 EXPECT_EQ(call_records->len, 1u);
290 FlKeyEmbedderCallRecord* record =
291 FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
292 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
293 EXPECT_EQ(record->event->timestamp, 12345000);
294 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
295 EXPECT_EQ(record->event->physical, kPhysicalDigit1);
296 EXPECT_EQ(record->event->logical, kLogicalDigit1);
297 EXPECT_STREQ(record->event->character, "&");
298 EXPECT_EQ(record->event->synthesized, false);
299
301 g_main_loop_run(loop);
302}

References callback, engine, fl_engine_get_embedder_api(), fl_key_embedder_call_record_new(), fl_key_embedder_responder_handle_event(), fl_key_embedder_responder_handle_event_finish(), fl_key_embedder_responder_new(), fl_key_event_new(), g_autoptr(), invoke_record_callback(), kFlutterKeyEventTypeDown, kSuccess, MOCK_ENGINE_PROC, FlutterEngineProcTable::SendKeyEvent, TRUE, and user_data.