| Flutter Linux Embedder |

fl_key_embedder_responder_test.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/shell/platform/linux/fl_key_embedder_responder.h"
6
7 #include "gtest/gtest.h"
8
9 #include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
10 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
11 #include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
12 #include "flutter/shell/platform/linux/fl_engine_private.h"
13 #include "flutter/shell/platform/linux/testing/fl_test.h"
14
15 namespace {
16 constexpr gboolean kRelease = FALSE;
17 constexpr gboolean kPress = TRUE;
18
19 constexpr gboolean kIsModifier = TRUE;
20 constexpr gboolean kIsNotModifier = FALSE;
21
22 constexpr guint16 kKeyCodeDigit1 = 0x0au;
23 constexpr guint16 kKeyCodeKeyA = 0x26u;
24 constexpr guint16 kKeyCodeShiftLeft = 0x32u;
25 constexpr guint16 kKeyCodeShiftRight = 0x3Eu;
26 constexpr guint16 kKeyCodeAltLeft = 0x40u;
27 constexpr guint16 kKeyCodeAltRight = 0x6Cu;
28 constexpr guint16 kKeyCodeNumpad1 = 0x57u;
29 constexpr guint16 kKeyCodeNumLock = 0x4Du;
30 constexpr guint16 kKeyCodeCapsLock = 0x42u;
31 constexpr guint16 kKeyCodeControlLeft = 0x25u;
32 constexpr guint16 kKeyCodeControlRight = 0x69u;
33
34 using namespace ::flutter::testing::keycodes;
35 } // namespace
36
37 static void g_ptr_array_clear(GPtrArray* array) {
38 g_ptr_array_remove_range(array, 0, array->len);
39 }
40
41 G_DECLARE_FINAL_TYPE(FlKeyEmbedderCallRecord,
42 fl_key_embedder_call_record,
43 FL,
44 KEY_EMBEDDER_CALL_RECORD,
45 GObject);
46
47 struct _FlKeyEmbedderCallRecord {
48 GObject parent_instance;
49
50 FlutterKeyEvent* event;
51 FlutterKeyEventCallback callback;
52 gpointer user_data;
53 };
54
55 G_DEFINE_TYPE(FlKeyEmbedderCallRecord,
56 fl_key_embedder_call_record,
57 G_TYPE_OBJECT)
58
59 static void fl_key_embedder_call_record_init(FlKeyEmbedderCallRecord* self) {}
60
61 // Dispose method for FlKeyEmbedderCallRecord.
62 static void fl_key_embedder_call_record_dispose(GObject* object) {
63 g_return_if_fail(FL_IS_KEY_EMBEDDER_CALL_RECORD(object));
64
65 FlKeyEmbedderCallRecord* self = FL_KEY_EMBEDDER_CALL_RECORD(object);
66 if (self->event != nullptr) {
67 g_free(const_cast<char*>(self->event->character));
68 g_free(self->event);
69 }
70 G_OBJECT_CLASS(fl_key_embedder_call_record_parent_class)->dispose(object);
71 }
72
73 // Class Initialization method for FlKeyEmbedderCallRecord class.
74 static void fl_key_embedder_call_record_class_init(
75 FlKeyEmbedderCallRecordClass* klass) {
76 G_OBJECT_CLASS(klass)->dispose = fl_key_embedder_call_record_dispose;
77 }
78
79 static FlKeyEmbedderCallRecord* fl_key_embedder_call_record_new(
80 const FlutterKeyEvent* event,
81 FlutterKeyEventCallback callback,
82 gpointer user_data) {
83 g_return_val_if_fail(event != nullptr, nullptr);
84
85 FlKeyEmbedderCallRecord* self = FL_KEY_EMBEDDER_CALL_RECORD(
86 g_object_new(fl_key_embedder_call_record_get_type(), nullptr));
87
88 FlutterKeyEvent* clone_event = g_new(FlutterKeyEvent, 1);
89 *clone_event = *event;
90 if (event->character != nullptr) {
91 size_t character_length = strlen(event->character);
92 char* clone_character = g_new(char, character_length + 1);
93 strncpy(clone_character, event->character, character_length + 1);
94 clone_event->character = clone_character;
95 }
96 self->event = clone_event;
97 self->callback = callback;
98 self->user_data = user_data;
99
100 return self;
101 }
102
103 namespace {
104 // A global variable to store new event. It is a global variable so that it can
105 // be returned by #fl_key_event_new_by_mock for easy use.
106 FlKeyEvent _g_key_event;
107 } // namespace
108
109 // Create a new #FlKeyEvent with the given information.
110 //
111 // This event is passed to #fl_key_responder_handle_event,
112 // which assumes that the event is managed by callee.
113 // Therefore #fl_key_event_new_by_mock doesn't need to
114 // dynamically allocate, but reuses the same global object.
115 static FlKeyEvent* fl_key_event_new_by_mock(guint32 time_in_milliseconds,
116 bool is_press,
117 guint keyval,
118 guint16 keycode,
119 GdkModifierType state,
120 gboolean is_modifier) {
121 _g_key_event.is_press = is_press;
122 _g_key_event.time = time_in_milliseconds;
123 _g_key_event.state = state;
124 _g_key_event.keyval = keyval;
125 _g_key_event.keycode = keycode;
126 _g_key_event.origin = nullptr;
127 return &_g_key_event;
128 }
129
130 static gboolean g_expected_handled;
131 static gpointer g_expected_user_data;
132
133 static void verify_response_handled(bool handled, gpointer user_data) {
134 EXPECT_EQ(handled, g_expected_handled);
135 }
136
137 static void invoke_record_callback_and_verify(FlKeyEmbedderCallRecord* record,
138 bool expected_handled,
139 void* expected_user_data) {
140 g_return_if_fail(record->callback != nullptr);
141 g_expected_handled = expected_handled;
142 g_expected_user_data = expected_user_data;
143 record->callback(expected_handled, record->user_data);
144 }
145
146 namespace {
147 GPtrArray* g_call_records;
148 }
149
150 static void record_calls(const FlutterKeyEvent* event,
151 FlutterKeyEventCallback callback,
152 void* callback_user_data,
153 void* send_key_event_user_data) {
154 GPtrArray* records_array =
155 reinterpret_cast<GPtrArray*>(send_key_event_user_data);
156 if (records_array != nullptr) {
157 g_ptr_array_add(records_array, fl_key_embedder_call_record_new(
158 event, callback, callback_user_data));
159 }
160 }
161
162 static void clear_g_call_records() {
163 g_ptr_array_free(g_call_records, TRUE);
164 g_call_records = nullptr;
165 }
166
167 // Basic key presses
168 TEST(FlKeyEmbedderResponderTest, SendKeyEvent) {
169 EXPECT_EQ(g_call_records, nullptr);
170 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
171 FlKeyResponder* responder = FL_KEY_RESPONDER(
172 fl_key_embedder_responder_new(record_calls, g_call_records));
173 int user_data = 123; // Arbitrary user data
174
175 FlKeyEmbedderCallRecord* record;
176
177 // On a QWERTY keyboard, press key Q (physically key A), and release.
178 // Key down
179 fl_key_responder_handle_event(
180 responder,
181 fl_key_event_new_by_mock(12345, kPress, GDK_KEY_a, kKeyCodeKeyA,
182 static_cast<GdkModifierType>(0), kIsNotModifier),
183 verify_response_handled, &user_data);
184
185 EXPECT_EQ(g_call_records->len, 1u);
186 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
187 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
188 EXPECT_EQ(record->event->timestamp, 12345000);
189 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
190 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
191 EXPECT_EQ(record->event->logical, kLogicalKeyA);
192 EXPECT_STREQ(record->event->character, "a");
193 EXPECT_EQ(record->event->synthesized, false);
194
195 invoke_record_callback_and_verify(record, TRUE, &user_data);
196 g_ptr_array_clear(g_call_records);
197
198 // Key up
199 fl_key_responder_handle_event(
200 responder,
201 fl_key_event_new_by_mock(12346, kRelease, GDK_KEY_a, kKeyCodeKeyA,
202 static_cast<GdkModifierType>(0), kIsNotModifier),
203 verify_response_handled, &user_data);
204
205 EXPECT_EQ(g_call_records->len, 1u);
206 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
207 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
208 EXPECT_EQ(record->event->timestamp, 12346000);
209 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
210 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
211 EXPECT_EQ(record->event->logical, kLogicalKeyA);
212 EXPECT_STREQ(record->event->character, nullptr);
213 EXPECT_EQ(record->event->synthesized, false);
214
215 invoke_record_callback_and_verify(record, FALSE, &user_data);
216 g_ptr_array_clear(g_call_records);
217
218 // On an AZERTY keyboard, press key Q (physically key A), and release.
219 // Key down
220 fl_key_responder_handle_event(
221 responder,
222 fl_key_event_new_by_mock(12347, kPress, GDK_KEY_q, kKeyCodeKeyA,
223 static_cast<GdkModifierType>(0), kIsNotModifier),
224 verify_response_handled, &user_data);
225
226 EXPECT_EQ(g_call_records->len, 1u);
227 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
228 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
229 EXPECT_EQ(record->event->timestamp, 12347000);
230 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
231 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
232 EXPECT_EQ(record->event->logical, kLogicalKeyQ);
233 EXPECT_STREQ(record->event->character, "q");
234 EXPECT_EQ(record->event->synthesized, false);
235
236 invoke_record_callback_and_verify(record, TRUE, &user_data);
237 g_ptr_array_clear(g_call_records);
238
239 // Key up
240 fl_key_responder_handle_event(
241 responder,
242 fl_key_event_new_by_mock(12348, kRelease, GDK_KEY_q, kKeyCodeKeyA,
243 static_cast<GdkModifierType>(0), kIsNotModifier),
244 verify_response_handled, &user_data);
245
246 EXPECT_EQ(g_call_records->len, 1u);
247 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
248 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
249 EXPECT_EQ(record->event->timestamp, 12348000);
250 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
251 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
252 EXPECT_EQ(record->event->logical, kLogicalKeyQ);
253 EXPECT_STREQ(record->event->character, nullptr);
254 EXPECT_EQ(record->event->synthesized, false);
255
256 invoke_record_callback_and_verify(record, FALSE, &user_data);
257 g_ptr_array_clear(g_call_records);
258
259 clear_g_call_records();
260 g_object_unref(responder);
261 }
262
263 // Basic key presses, but uses the specified logical key if it is not 0.
264 TEST(FlKeyEmbedderResponderTest, UsesSpecifiedLogicalKey) {
265 EXPECT_EQ(g_call_records, nullptr);
266 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
267 FlKeyResponder* responder = FL_KEY_RESPONDER(
268 fl_key_embedder_responder_new(record_calls, g_call_records));
269 int user_data = 123; // Arbitrary user data
270
271 FlKeyEmbedderCallRecord* record;
272
273 // On an AZERTY keyboard, press physical key 1, and release.
274 // Key down
275 fl_key_responder_handle_event(
276 responder,
277 fl_key_event_new_by_mock(12345, kPress, GDK_KEY_ampersand, kKeyCodeDigit1,
278 static_cast<GdkModifierType>(0), kIsNotModifier),
279 verify_response_handled, &user_data, kLogicalDigit1);
280
281 EXPECT_EQ(g_call_records->len, 1u);
282 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
283 EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
284 EXPECT_EQ(record->event->timestamp, 12345000);
285 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
286 EXPECT_EQ(record->event->physical, kPhysicalDigit1);
287 EXPECT_EQ(record->event->logical, kLogicalDigit1);
288 EXPECT_STREQ(record->event->character, "&");
289 EXPECT_EQ(record->event->synthesized, false);
290
291 invoke_record_callback_and_verify(record, TRUE, &user_data);
292 g_ptr_array_clear(g_call_records);
293
294 clear_g_call_records();
295 g_object_unref(responder);
296 }
297
298 // Press Shift, key A, then release Shift, key A.
299 TEST(FlKeyEmbedderResponderTest, PressShiftDuringLetterKeyTap) {
300 EXPECT_EQ(g_call_records, nullptr);
301 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
302 FlKeyResponder* responder = FL_KEY_RESPONDER(
303 fl_key_embedder_responder_new(record_calls, g_call_records));
304 int user_data = 123; // Arbitrary user data
305
306 FlKeyEmbedderCallRecord* record;
307
308 // Press shift right
309 fl_key_responder_handle_event(
310 responder,
311 fl_key_event_new_by_mock(101, kPress, GDK_KEY_Shift_R, kKeyCodeShiftRight,
312 static_cast<GdkModifierType>(0), kIsModifier),
313 verify_response_handled, &user_data);
314
315 EXPECT_EQ(g_call_records->len, 1u);
316 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
317 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
318 EXPECT_EQ(record->event->physical, kPhysicalShiftRight);
319 EXPECT_EQ(record->event->logical, kLogicalShiftRight);
320 EXPECT_STREQ(record->event->character, nullptr);
321 EXPECT_EQ(record->event->synthesized, false);
322
323 invoke_record_callback_and_verify(record, TRUE, &user_data);
324 g_ptr_array_clear(g_call_records);
325
326 // Press key A
327 fl_key_responder_handle_event(
328 responder,
329 fl_key_event_new_by_mock(102, kPress, GDK_KEY_A, kKeyCodeKeyA,
330 GDK_SHIFT_MASK, kIsNotModifier),
331 verify_response_handled, &user_data);
332
333 EXPECT_EQ(g_call_records->len, 1u);
334 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
335 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
336 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
337 EXPECT_EQ(record->event->logical, kLogicalKeyA);
338 EXPECT_STREQ(record->event->character, "A");
339 EXPECT_EQ(record->event->synthesized, false);
340
341 invoke_record_callback_and_verify(record, TRUE, &user_data);
342 g_ptr_array_clear(g_call_records);
343
344 // Release shift right
345 fl_key_responder_handle_event(
346 responder,
347 fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Shift_R,
348 kKeyCodeShiftRight, GDK_SHIFT_MASK, kIsModifier),
349 verify_response_handled, &user_data);
350
351 EXPECT_EQ(g_call_records->len, 1u);
352 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
353 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
354 EXPECT_EQ(record->event->physical, kPhysicalShiftRight);
355 EXPECT_EQ(record->event->logical, kLogicalShiftRight);
356 EXPECT_STREQ(record->event->character, nullptr);
357 EXPECT_EQ(record->event->synthesized, false);
358
359 invoke_record_callback_and_verify(record, TRUE, &user_data);
360 g_ptr_array_clear(g_call_records);
361
362 // Release key A
363 fl_key_responder_handle_event(
364 responder,
365 fl_key_event_new_by_mock(104, kRelease, GDK_KEY_A, kKeyCodeKeyA,
366 static_cast<GdkModifierType>(0), kIsNotModifier),
367 verify_response_handled, &user_data);
368
369 EXPECT_EQ(g_call_records->len, 1u);
370 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
371 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
372 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
373 EXPECT_EQ(record->event->logical, kLogicalKeyA);
374 EXPECT_STREQ(record->event->character, nullptr);
375 EXPECT_EQ(record->event->synthesized, false);
376
377 invoke_record_callback_and_verify(record, TRUE, &user_data);
378 g_ptr_array_clear(g_call_records);
379
380 clear_g_call_records();
381 g_object_unref(responder);
382 }
383
384 // Press or release Numpad 1 between presses/releases of NumLock.
385 //
386 // This tests interaction between lock keys and non-lock keys in cases that do
387 // not have events missed.
388 //
389 // This also tests the result of Numpad keys across NumLock taps, which is
390 // test-worthy because the keyval for the numpad key will change before and
391 // after the NumLock tap, which should not alter the resulting logical key.
392 TEST(FlKeyEmbedderResponderTest, TapNumPadKeysBetweenNumLockEvents) {
393 EXPECT_EQ(g_call_records, nullptr);
394 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
395 FlKeyResponder* responder = FL_KEY_RESPONDER(
396 fl_key_embedder_responder_new(record_calls, g_call_records));
397 int user_data = 123; // Arbitrary user data
398
399 FlKeyEmbedderCallRecord* record;
400
401 // Press Numpad 1 (stage 0)
402 fl_key_responder_handle_event(
403 responder,
404 fl_key_event_new_by_mock(101, kPress, GDK_KEY_KP_End, kKeyCodeNumpad1,
405 static_cast<GdkModifierType>(0), kIsNotModifier),
406 verify_response_handled, &user_data);
407
408 EXPECT_EQ(g_call_records->len, 1u);
409 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
410 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
411 EXPECT_EQ(record->event->physical, kPhysicalNumpad1);
412 EXPECT_EQ(record->event->logical, kLogicalNumpad1);
413 EXPECT_STREQ(record->event->character, nullptr); // TODO(chrome-bot):
414 EXPECT_EQ(record->event->synthesized, false);
415
416 invoke_record_callback_and_verify(record, TRUE, &user_data);
417 g_ptr_array_clear(g_call_records);
418
419 // Press NumLock (stage 0 -> 1)
420 fl_key_responder_handle_event(
421 responder,
422 fl_key_event_new_by_mock(102, kPress, GDK_KEY_Num_Lock, kKeyCodeNumLock,
423 static_cast<GdkModifierType>(0), kIsNotModifier),
424 verify_response_handled, &user_data);
425
426 EXPECT_EQ(g_call_records->len, 1u);
427 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
428 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
429 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
430 EXPECT_EQ(record->event->logical, kLogicalNumLock);
431 EXPECT_STREQ(record->event->character, nullptr);
432 EXPECT_EQ(record->event->synthesized, false);
433
434 invoke_record_callback_and_verify(record, TRUE, &user_data);
435 g_ptr_array_clear(g_call_records);
436
437 // Release numpad 1 (stage 1)
438 fl_key_responder_handle_event(
439 responder,
440 fl_key_event_new_by_mock(104, kRelease, GDK_KEY_KP_1, kKeyCodeNumpad1,
441 GDK_MOD2_MASK, kIsNotModifier),
442 verify_response_handled, &user_data);
443
444 EXPECT_EQ(g_call_records->len, 1u);
445 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
446 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
447 EXPECT_EQ(record->event->physical, kPhysicalNumpad1);
448 EXPECT_EQ(record->event->logical, kLogicalNumpad1);
449 EXPECT_STREQ(record->event->character, nullptr);
450 EXPECT_EQ(record->event->synthesized, false);
451
452 invoke_record_callback_and_verify(record, TRUE, &user_data);
453 g_ptr_array_clear(g_call_records);
454
455 // Release NumLock (stage 1 -> 2)
456 fl_key_responder_handle_event(
457 responder,
458 fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Num_Lock, kKeyCodeNumLock,
459 GDK_MOD2_MASK, kIsModifier),
460 verify_response_handled, &user_data);
461
462 EXPECT_EQ(g_call_records->len, 1u);
463 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
464 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
465 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
466 EXPECT_EQ(record->event->logical, kLogicalNumLock);
467 EXPECT_STREQ(record->event->character, nullptr);
468 EXPECT_EQ(record->event->synthesized, false);
469
470 invoke_record_callback_and_verify(record, TRUE, &user_data);
471 g_ptr_array_clear(g_call_records);
472
473 // Press Numpad 1 (stage 2)
474 fl_key_responder_handle_event(
475 responder,
476 fl_key_event_new_by_mock(101, kPress, GDK_KEY_KP_End, kKeyCodeNumpad1,
477 GDK_MOD2_MASK, kIsNotModifier),
478 verify_response_handled, &user_data);
479
480 EXPECT_EQ(g_call_records->len, 1u);
481 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_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
488 invoke_record_callback_and_verify(record, TRUE, &user_data);
489 g_ptr_array_clear(g_call_records);
490
491 // Press NumLock (stage 2 -> 3)
492 fl_key_responder_handle_event(
493 responder,
494 fl_key_event_new_by_mock(102, kPress, GDK_KEY_Num_Lock, kKeyCodeNumLock,
495 GDK_MOD2_MASK, kIsNotModifier),
496 verify_response_handled, &user_data);
497
498 EXPECT_EQ(g_call_records->len, 1u);
499 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
500 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
501 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
502 EXPECT_EQ(record->event->logical, kLogicalNumLock);
503 EXPECT_STREQ(record->event->character, nullptr);
504 EXPECT_EQ(record->event->synthesized, false);
505
506 invoke_record_callback_and_verify(record, TRUE, &user_data);
507 g_ptr_array_clear(g_call_records);
508
509 // Release numpad 1 (stage 3)
510 fl_key_responder_handle_event(
511 responder,
512 fl_key_event_new_by_mock(104, kRelease, GDK_KEY_KP_1, kKeyCodeNumpad1,
513 GDK_MOD2_MASK, kIsNotModifier),
514 verify_response_handled, &user_data);
515
516 EXPECT_EQ(g_call_records->len, 1u);
517 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
518 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
519 EXPECT_EQ(record->event->physical, kPhysicalNumpad1);
520 EXPECT_EQ(record->event->logical, kLogicalNumpad1);
521 EXPECT_STREQ(record->event->character, nullptr);
522 EXPECT_EQ(record->event->synthesized, false);
523
524 invoke_record_callback_and_verify(record, TRUE, &user_data);
525 g_ptr_array_clear(g_call_records);
526
527 // Release NumLock (stage 3 -> 0)
528 fl_key_responder_handle_event(
529 responder,
530 fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Num_Lock, kKeyCodeNumLock,
531 GDK_MOD2_MASK, kIsModifier),
532 verify_response_handled, &user_data);
533
534 EXPECT_EQ(g_call_records->len, 1u);
535 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
536 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
537 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
538 EXPECT_EQ(record->event->logical, kLogicalNumLock);
539 EXPECT_STREQ(record->event->character, nullptr);
540 EXPECT_EQ(record->event->synthesized, false);
541
542 invoke_record_callback_and_verify(record, TRUE, &user_data);
543 g_ptr_array_clear(g_call_records);
544
545 clear_g_call_records();
546 g_object_unref(responder);
547 }
548
549 // Press or release digit 1 between presses/releases of Shift.
550 //
551 // GTK will change the virtual key during a key tap, and the embedder
552 // should regularize it.
553 TEST(FlKeyEmbedderResponderTest, ReleaseShiftKeyBetweenDigitKeyEvents) {
554 EXPECT_EQ(g_call_records, nullptr);
555 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
556 FlKeyResponder* responder = FL_KEY_RESPONDER(
557 fl_key_embedder_responder_new(record_calls, g_call_records));
558 int user_data = 123; // Arbitrary user data
559
560 FlKeyEmbedderCallRecord* record;
561
562 GdkModifierType state = static_cast<GdkModifierType>(0);
563
564 // Press shift left
565 fl_key_responder_handle_event(
566 responder,
567 fl_key_event_new_by_mock(101, kPress, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
568 state, kIsModifier),
569 verify_response_handled, &user_data);
570
571 EXPECT_EQ(g_call_records->len, 1u);
572 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
573 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
574 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
575 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
576 EXPECT_STREQ(record->event->character, nullptr);
577 EXPECT_EQ(record->event->synthesized, false);
578
579 invoke_record_callback_and_verify(record, TRUE, &user_data);
580 g_ptr_array_clear(g_call_records);
581
582 state = GDK_SHIFT_MASK;
583
584 // Press digit 1, which is '!' on a US keyboard
585 fl_key_responder_handle_event(
586 responder,
587 fl_key_event_new_by_mock(102, kPress, GDK_KEY_exclam, kKeyCodeDigit1,
588 state, kIsNotModifier),
589 verify_response_handled, &user_data);
590
591 EXPECT_EQ(g_call_records->len, 1u);
592 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
593 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
594 EXPECT_EQ(record->event->physical, kPhysicalDigit1);
595 EXPECT_EQ(record->event->logical, kLogicalExclamation);
596 EXPECT_STREQ(record->event->character, "!");
597 EXPECT_EQ(record->event->synthesized, false);
598
599 invoke_record_callback_and_verify(record, TRUE, &user_data);
600 g_ptr_array_clear(g_call_records);
601
602 // Release shift
603 fl_key_responder_handle_event(
604 responder,
605 fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Shift_L,
606 kKeyCodeShiftLeft, state, kIsModifier),
607 verify_response_handled, &user_data);
608
609 EXPECT_EQ(g_call_records->len, 1u);
610 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
611 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
612 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
613 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
614 EXPECT_STREQ(record->event->character, nullptr);
615 EXPECT_EQ(record->event->synthesized, false);
616
617 invoke_record_callback_and_verify(record, TRUE, &user_data);
618 g_ptr_array_clear(g_call_records);
619
620 state = static_cast<GdkModifierType>(0);
621
622 // Release digit 1, which is "1" because shift has been released.
623 fl_key_responder_handle_event(
624 responder,
625 fl_key_event_new_by_mock(104, kRelease, GDK_KEY_1, kKeyCodeDigit1, state,
626 kIsNotModifier),
627 verify_response_handled, &user_data);
628
629 EXPECT_EQ(g_call_records->len, 1u);
630 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
631 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
632 EXPECT_EQ(record->event->physical, kPhysicalDigit1);
633 EXPECT_EQ(record->event->logical, kLogicalExclamation); // Important
634 EXPECT_STREQ(record->event->character, nullptr);
635 EXPECT_EQ(record->event->synthesized, false);
636
637 invoke_record_callback_and_verify(record, TRUE, &user_data);
638 g_ptr_array_clear(g_call_records);
639
640 clear_g_call_records();
641 g_object_unref(responder);
642 }
643
644 // Press or release letter key between presses/releases of CapsLock.
645 //
646 // This tests interaction between lock keys and non-lock keys in cases that do
647 // not have events missed.
648 TEST(FlKeyEmbedderResponderTest, TapLetterKeysBetweenCapsLockEvents) {
649 EXPECT_EQ(g_call_records, nullptr);
650 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
651 FlKeyResponder* responder = FL_KEY_RESPONDER(
652 fl_key_embedder_responder_new(record_calls, g_call_records));
653 int user_data = 123; // Arbitrary user data
654
655 FlKeyEmbedderCallRecord* record;
656
657 // Press CapsLock (stage 0 -> 1)
658 fl_key_responder_handle_event(
659 responder,
660 fl_key_event_new_by_mock(101, kPress, GDK_KEY_Caps_Lock, kKeyCodeCapsLock,
661 static_cast<GdkModifierType>(0), kIsModifier),
662 verify_response_handled, &user_data);
663
664 EXPECT_EQ(g_call_records->len, 1u);
665 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
666 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
667 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
668 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
669 EXPECT_STREQ(record->event->character, nullptr);
670 EXPECT_EQ(record->event->synthesized, false);
671
672 invoke_record_callback_and_verify(record, TRUE, &user_data);
673 g_ptr_array_clear(g_call_records);
674
675 // Press key A (stage 1)
676 fl_key_responder_handle_event(
677 responder,
678 fl_key_event_new_by_mock(102, kPress, GDK_KEY_A, kKeyCodeKeyA,
679 GDK_LOCK_MASK, kIsNotModifier),
680 verify_response_handled, &user_data);
681
682 EXPECT_EQ(g_call_records->len, 1u);
683 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
684 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
685 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
686 EXPECT_EQ(record->event->logical, kLogicalKeyA);
687 EXPECT_STREQ(record->event->character, "A");
688 EXPECT_EQ(record->event->synthesized, false);
689
690 invoke_record_callback_and_verify(record, TRUE, &user_data);
691 g_ptr_array_clear(g_call_records);
692
693 // Release CapsLock (stage 1 -> 2)
694 fl_key_responder_handle_event(
695 responder,
696 fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Caps_Lock,
697 kKeyCodeCapsLock, GDK_LOCK_MASK, kIsModifier),
698 verify_response_handled, &user_data);
699
700 EXPECT_EQ(g_call_records->len, 1u);
701 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
702 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
703 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
704 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
705 EXPECT_STREQ(record->event->character, nullptr);
706 EXPECT_EQ(record->event->synthesized, false);
707
708 invoke_record_callback_and_verify(record, TRUE, &user_data);
709 g_ptr_array_clear(g_call_records);
710
711 // Release key A (stage 2)
712 fl_key_responder_handle_event(
713 responder,
714 fl_key_event_new_by_mock(104, kRelease, GDK_KEY_A, kKeyCodeKeyA,
715 GDK_LOCK_MASK, kIsNotModifier),
716 verify_response_handled, &user_data);
717
718 EXPECT_EQ(g_call_records->len, 1u);
719 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
720 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
721 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
722 EXPECT_EQ(record->event->logical, kLogicalKeyA);
723 EXPECT_STREQ(record->event->character, nullptr);
724 EXPECT_EQ(record->event->synthesized, false);
725
726 invoke_record_callback_and_verify(record, TRUE, &user_data);
727 g_ptr_array_clear(g_call_records);
728
729 // Press CapsLock (stage 2 -> 3)
730 fl_key_responder_handle_event(
731 responder,
732 fl_key_event_new_by_mock(105, kPress, GDK_KEY_Caps_Lock, kKeyCodeCapsLock,
733 GDK_LOCK_MASK, kIsModifier),
734 verify_response_handled, &user_data);
735
736 EXPECT_EQ(g_call_records->len, 1u);
737 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
738 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
739 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
740 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
741 EXPECT_STREQ(record->event->character, nullptr);
742 EXPECT_EQ(record->event->synthesized, false);
743
744 invoke_record_callback_and_verify(record, TRUE, &user_data);
745 g_ptr_array_clear(g_call_records);
746
747 // Press key A (stage 3)
748 fl_key_responder_handle_event(
749 responder,
750 fl_key_event_new_by_mock(106, kPress, GDK_KEY_A, kKeyCodeKeyA,
751 GDK_LOCK_MASK, kIsNotModifier),
752 verify_response_handled, &user_data);
753
754 EXPECT_EQ(g_call_records->len, 1u);
755 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
756 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
757 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
758 EXPECT_EQ(record->event->logical, kLogicalKeyA);
759 EXPECT_STREQ(record->event->character, "A");
760 EXPECT_EQ(record->event->synthesized, false);
761
762 invoke_record_callback_and_verify(record, TRUE, &user_data);
763 g_ptr_array_clear(g_call_records);
764
765 // Release CapsLock (stage 3 -> 0)
766 fl_key_responder_handle_event(
767 responder,
768 fl_key_event_new_by_mock(107, kRelease, GDK_KEY_Caps_Lock,
769 kKeyCodeCapsLock, GDK_LOCK_MASK, kIsModifier),
770 verify_response_handled, &user_data);
771
772 EXPECT_EQ(g_call_records->len, 1u);
773 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
774 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
775 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
776 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
777 EXPECT_STREQ(record->event->character, nullptr);
778 EXPECT_EQ(record->event->synthesized, false);
779
780 invoke_record_callback_and_verify(record, TRUE, &user_data);
781 g_ptr_array_clear(g_call_records);
782
783 // Release key A (stage 0)
784 fl_key_responder_handle_event(
785 responder,
786 fl_key_event_new_by_mock(108, kRelease, GDK_KEY_a, kKeyCodeKeyA,
787 static_cast<GdkModifierType>(0), kIsNotModifier),
788 verify_response_handled, &user_data);
789
790 EXPECT_EQ(g_call_records->len, 1u);
791 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
792 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
793 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
794 EXPECT_EQ(record->event->logical, kLogicalKeyA);
795 EXPECT_STREQ(record->event->character, nullptr);
796 EXPECT_EQ(record->event->synthesized, false);
797
798 invoke_record_callback_and_verify(record, TRUE, &user_data);
799 g_ptr_array_clear(g_call_records);
800
801 clear_g_call_records();
802 g_object_unref(responder);
803 }
804
805 // Press or release letter key between presses/releases of CapsLock, on
806 // a platform with reversed logic.
807 //
808 // This happens when using a Chrome remote desktop on MacOS.
809 TEST(FlKeyEmbedderResponderTest, TapLetterKeysBetweenCapsLockEventsReversed) {
810 EXPECT_EQ(g_call_records, nullptr);
811 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
812 FlKeyResponder* responder = FL_KEY_RESPONDER(
813 fl_key_embedder_responder_new(record_calls, g_call_records));
814 int user_data = 123; // Arbitrary user data
815
816 FlKeyEmbedderCallRecord* record;
817
818 // Press key A (stage 0)
819 fl_key_responder_handle_event(
820 responder,
821 fl_key_event_new_by_mock(101, kPress, GDK_KEY_a, kKeyCodeKeyA,
822 static_cast<GdkModifierType>(0), kIsNotModifier),
823 verify_response_handled, &user_data);
824
825 EXPECT_EQ(g_call_records->len, 1u);
826 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
827 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
828 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
829 EXPECT_EQ(record->event->logical, kLogicalKeyA);
830 EXPECT_STREQ(record->event->character, "a");
831 EXPECT_EQ(record->event->synthesized, false);
832
833 invoke_record_callback_and_verify(record, TRUE, &user_data);
834 g_ptr_array_clear(g_call_records);
835
836 // Press CapsLock (stage 0 -> 1)
837 fl_key_responder_handle_event(
838 responder,
839 fl_key_event_new_by_mock(102, kPress, GDK_KEY_Caps_Lock, kKeyCodeCapsLock,
840 GDK_LOCK_MASK, kIsModifier),
841 verify_response_handled, &user_data);
842
843 EXPECT_EQ(g_call_records->len, 1u);
844 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
845 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
846 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
847 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
848 EXPECT_STREQ(record->event->character, nullptr);
849 EXPECT_EQ(record->event->synthesized, false);
850
851 invoke_record_callback_and_verify(record, TRUE, &user_data);
852 g_ptr_array_clear(g_call_records);
853
854 // Release CapsLock (stage 1 -> 2)
855 fl_key_responder_handle_event(
856 responder,
857 fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Caps_Lock,
858 kKeyCodeCapsLock, GDK_LOCK_MASK, kIsModifier),
859 verify_response_handled, &user_data);
860
861 EXPECT_EQ(g_call_records->len, 1u);
862 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
863 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
864 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
865 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
866 EXPECT_STREQ(record->event->character, nullptr);
867 EXPECT_EQ(record->event->synthesized, false);
868
869 invoke_record_callback_and_verify(record, TRUE, &user_data);
870 g_ptr_array_clear(g_call_records);
871
872 // Release key A (stage 2)
873 fl_key_responder_handle_event(
874 responder,
875 fl_key_event_new_by_mock(104, kRelease, GDK_KEY_A, kKeyCodeKeyA,
876 GDK_LOCK_MASK, kIsNotModifier),
877 verify_response_handled, &user_data);
878
879 EXPECT_EQ(g_call_records->len, 1u);
880 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
881 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
882 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
883 EXPECT_EQ(record->event->logical, kLogicalKeyA);
884 EXPECT_STREQ(record->event->character, nullptr);
885 EXPECT_EQ(record->event->synthesized, false);
886
887 invoke_record_callback_and_verify(record, TRUE, &user_data);
888 g_ptr_array_clear(g_call_records);
889
890 // Press key A (stage 2)
891 fl_key_responder_handle_event(
892 responder,
893 fl_key_event_new_by_mock(105, kPress, GDK_KEY_A, kKeyCodeKeyA,
894 GDK_LOCK_MASK, kIsNotModifier),
895 verify_response_handled, &user_data);
896
897 EXPECT_EQ(g_call_records->len, 1u);
898 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
899 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
900 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
901 EXPECT_EQ(record->event->logical, kLogicalKeyA);
902 EXPECT_STREQ(record->event->character, "A");
903 EXPECT_EQ(record->event->synthesized, false);
904
905 invoke_record_callback_and_verify(record, TRUE, &user_data);
906 g_ptr_array_clear(g_call_records);
907
908 // Press CapsLock (stage 2 -> 3)
909 fl_key_responder_handle_event(
910 responder,
911 fl_key_event_new_by_mock(106, kPress, GDK_KEY_Caps_Lock, kKeyCodeCapsLock,
912 static_cast<GdkModifierType>(0), kIsModifier),
913 verify_response_handled, &user_data);
914
915 EXPECT_EQ(g_call_records->len, 1u);
916 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
917 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
918 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
919 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
920 EXPECT_STREQ(record->event->character, nullptr);
921 EXPECT_EQ(record->event->synthesized, false);
922
923 invoke_record_callback_and_verify(record, TRUE, &user_data);
924 g_ptr_array_clear(g_call_records);
925
926 // Release CapsLock (stage 3 -> 0)
927 fl_key_responder_handle_event(
928 responder,
929 fl_key_event_new_by_mock(107, kRelease, GDK_KEY_Caps_Lock,
930 kKeyCodeCapsLock, GDK_LOCK_MASK, kIsModifier),
931 verify_response_handled, &user_data);
932
933 EXPECT_EQ(g_call_records->len, 1u);
934 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
935 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
936 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
937 EXPECT_EQ(record->event->logical, kLogicalCapsLock);
938 EXPECT_STREQ(record->event->character, nullptr);
939 EXPECT_EQ(record->event->synthesized, false);
940
941 invoke_record_callback_and_verify(record, TRUE, &user_data);
942 g_ptr_array_clear(g_call_records);
943
944 // Release key A (stage 0)
945 fl_key_responder_handle_event(
946 responder,
947 fl_key_event_new_by_mock(108, kRelease, GDK_KEY_a, kKeyCodeKeyA,
948 static_cast<GdkModifierType>(0), kIsNotModifier),
949 verify_response_handled, &user_data);
950
951 EXPECT_EQ(g_call_records->len, 1u);
952 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
953 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
954 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
955 EXPECT_EQ(record->event->logical, kLogicalKeyA);
956 EXPECT_STREQ(record->event->character, nullptr);
957 EXPECT_EQ(record->event->synthesized, false);
958
959 invoke_record_callback_and_verify(record, TRUE, &user_data);
960 g_ptr_array_clear(g_call_records);
961
962 clear_g_call_records();
963 g_object_unref(responder);
964 }
965
966 TEST(FlKeyEmbedderResponderTest, TurnDuplicateDownEventsToRepeats) {
967 EXPECT_EQ(g_call_records, nullptr);
968 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
969 FlKeyResponder* responder = FL_KEY_RESPONDER(
970 fl_key_embedder_responder_new(record_calls, g_call_records));
971 int user_data = 123; // Arbitrary user data
972
973 FlKeyEmbedderCallRecord* record;
974
975 // Press KeyA
976 fl_key_responder_handle_event(
977 responder,
978 fl_key_event_new_by_mock(101, kPress, GDK_KEY_a, kKeyCodeKeyA,
979 static_cast<GdkModifierType>(0), kIsNotModifier),
980 verify_response_handled, &user_data);
981
982 EXPECT_EQ(g_call_records->len, 1u);
983
984 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
985 invoke_record_callback_and_verify(record, TRUE, &user_data);
986 g_ptr_array_clear(g_call_records);
987
988 // Another KeyA down events, which usually means a repeated event.
989 g_expected_handled = false;
990 fl_key_responder_handle_event(
991 responder,
992 fl_key_event_new_by_mock(102, kPress, GDK_KEY_a, kKeyCodeKeyA,
993 static_cast<GdkModifierType>(0), kIsNotModifier),
994 verify_response_handled, &user_data);
995
996 EXPECT_EQ(g_call_records->len, 1u);
997
998 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
999 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeRepeat);
1000 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1001 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1002 EXPECT_STREQ(record->event->character, "a");
1003 EXPECT_EQ(record->event->synthesized, false);
1004 EXPECT_NE(record->callback, nullptr);
1005
1006 invoke_record_callback_and_verify(record, TRUE, &user_data);
1007 g_ptr_array_clear(g_call_records);
1008
1009 // Release KeyA
1010 fl_key_responder_handle_event(
1011 responder,
1012 fl_key_event_new_by_mock(103, kRelease, GDK_KEY_q, kKeyCodeKeyA,
1013 static_cast<GdkModifierType>(0), kIsNotModifier),
1014 verify_response_handled, &user_data);
1015
1016 EXPECT_EQ(g_call_records->len, 1u);
1017 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1018 invoke_record_callback_and_verify(record, TRUE, &user_data);
1019 g_ptr_array_clear(g_call_records);
1020
1021 clear_g_call_records();
1022 g_object_unref(responder);
1023 }
1024
1025 TEST(FlKeyEmbedderResponderTest, IgnoreAbruptUpEvent) {
1026 FlKeyEmbedderCallRecord* record;
1027
1028 EXPECT_EQ(g_call_records, nullptr);
1029 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
1030 FlKeyResponder* responder = FL_KEY_RESPONDER(
1031 fl_key_embedder_responder_new(record_calls, g_call_records));
1032 int user_data = 123; // Arbitrary user data
1033
1034 // Release KeyA before it was even pressed.
1035 g_expected_handled = true; // The empty event is always handled.
1036 fl_key_responder_handle_event(
1037 responder,
1038 fl_key_event_new_by_mock(103, kRelease, GDK_KEY_q, kKeyCodeKeyA,
1039 static_cast<GdkModifierType>(0), kIsNotModifier),
1040 verify_response_handled, &user_data);
1041
1042 EXPECT_EQ(g_call_records->len, 1u);
1043
1044 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1045 EXPECT_EQ(record->event->physical, 0ull);
1046 EXPECT_EQ(record->event->logical, 0ull);
1047 EXPECT_STREQ(record->event->character, nullptr);
1048 EXPECT_EQ(record->event->synthesized, false);
1049 EXPECT_EQ(record->callback, nullptr);
1050
1051 clear_g_call_records();
1052 g_object_unref(responder);
1053 }
1054
1055 // Test if missed modifier keys can be detected and synthesized with state
1056 // information upon events that are for this modifier key.
1057 TEST(FlKeyEmbedderResponderTest, SynthesizeForDesyncPressingStateOnSelfEvents) {
1058 EXPECT_EQ(g_call_records, nullptr);
1059 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
1060 FlKeyResponder* responder = FL_KEY_RESPONDER(
1061 fl_key_embedder_responder_new(record_calls, g_call_records));
1062 int user_data = 123; // Arbitrary user data
1063
1064 FlKeyEmbedderCallRecord* record;
1065
1066 // Test 1: synthesize key down.
1067
1068 // A key down of control left is missed.
1069 GdkModifierType state = GDK_CONTROL_MASK;
1070
1071 // Send a ControlLeft up
1072 fl_key_responder_handle_event(
1073 responder,
1074 fl_key_event_new_by_mock(101, kRelease, GDK_KEY_Control_L,
1075 kKeyCodeControlLeft, state, kIsModifier),
1076 verify_response_handled, &user_data);
1077
1078 EXPECT_EQ(g_call_records->len, 2u);
1079 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1080 EXPECT_EQ(record->event->timestamp, 101000);
1081 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1082 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1083 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1084 EXPECT_STREQ(record->event->character, nullptr);
1085 EXPECT_EQ(record->event->synthesized, true);
1086
1087 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1088 EXPECT_EQ(record->event->timestamp, 101000);
1089 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1090 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1091 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1092 EXPECT_STREQ(record->event->character, nullptr);
1093 EXPECT_EQ(record->event->synthesized, false);
1094
1095 invoke_record_callback_and_verify(record, TRUE, &user_data);
1096 g_ptr_array_clear(g_call_records);
1097
1098 // Test 2: synthesize key up.
1099
1100 // Send a ControlLeft down.
1101 state = static_cast<GdkModifierType>(0);
1102 fl_key_responder_handle_event(
1103 responder,
1104 fl_key_event_new_by_mock(102, kPress, GDK_KEY_Control_L,
1105 kKeyCodeControlLeft, state, kIsModifier),
1106 verify_response_handled, &user_data);
1107 EXPECT_EQ(g_call_records->len, 1u);
1108 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1109 invoke_record_callback_and_verify(record, TRUE, &user_data);
1110 g_ptr_array_clear(g_call_records);
1111
1112 // A key up of control left is missed.
1113 state = static_cast<GdkModifierType>(0);
1114
1115 // Send another ControlLeft down
1116 fl_key_responder_handle_event(
1117 responder,
1118 fl_key_event_new_by_mock(103, kPress, GDK_KEY_Control_L,
1119 kKeyCodeControlLeft, state, kIsModifier),
1120 verify_response_handled, &user_data);
1121
1122 EXPECT_EQ(g_call_records->len, 2u);
1123 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1124 EXPECT_EQ(record->event->timestamp, 103000);
1125 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1126 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1127 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1128 EXPECT_STREQ(record->event->character, nullptr);
1129 EXPECT_EQ(record->event->synthesized, true);
1130
1131 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1132 EXPECT_EQ(record->event->timestamp, 103000);
1133 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1134 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1135 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1136 EXPECT_STREQ(record->event->character, nullptr);
1137 EXPECT_EQ(record->event->synthesized, false);
1138
1139 invoke_record_callback_and_verify(record, TRUE, &user_data);
1140 g_ptr_array_clear(g_call_records);
1141
1142 // Send a ControlLeft up to clear up state.
1143 state = GDK_CONTROL_MASK;
1144 fl_key_responder_handle_event(
1145 responder,
1146 fl_key_event_new_by_mock(104, kRelease, GDK_KEY_Control_L,
1147 kKeyCodeControlLeft, state, kIsModifier),
1148 verify_response_handled, &user_data);
1149 EXPECT_EQ(g_call_records->len, 1u);
1150 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1151 invoke_record_callback_and_verify(record, TRUE, &user_data);
1152 g_ptr_array_clear(g_call_records);
1153
1154 // Test 3: synthesize by right modifier.
1155
1156 // A key down of control right is missed.
1157 state = GDK_CONTROL_MASK;
1158
1159 // Send a ControlRight up.
1160 fl_key_responder_handle_event(
1161 responder,
1162 fl_key_event_new_by_mock(105, kRelease, GDK_KEY_Control_R,
1163 kKeyCodeControlRight, state, kIsModifier),
1164 verify_response_handled, &user_data);
1165
1166 // A ControlLeft down is synthesized, with an empty event.
1167 // Reason: The ControlLeft down is synthesized to synchronize the state
1168 // showing Control as pressed. The ControlRight event is ignored because
1169 // the event is considered a duplicate up event.
1170 EXPECT_EQ(g_call_records->len, 1u);
1171 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1172 EXPECT_EQ(record->event->timestamp, 105000);
1173 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1174 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1175 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1176 EXPECT_STREQ(record->event->character, nullptr);
1177 EXPECT_EQ(record->event->synthesized, true);
1178
1179 g_ptr_array_clear(g_call_records);
1180
1181 clear_g_call_records();
1182 g_object_unref(responder);
1183 }
1184
1185 // Test if missed modifier keys can be detected and synthesized with state
1186 // information upon events that are not for this modifier key.
1187 TEST(FlKeyEmbedderResponderTest,
1188 SynthesizeForDesyncPressingStateOnNonSelfEvents) {
1189 EXPECT_EQ(g_call_records, nullptr);
1190 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
1191 FlKeyResponder* responder = FL_KEY_RESPONDER(
1192 fl_key_embedder_responder_new(record_calls, g_call_records));
1193 int user_data = 123; // Arbitrary user data
1194
1195 FlKeyEmbedderCallRecord* record;
1196
1197 // A key down of control left is missed.
1198 GdkModifierType state = GDK_CONTROL_MASK;
1199
1200 // Send a normal event (KeyA down)
1201 fl_key_responder_handle_event(
1202 responder,
1203 fl_key_event_new_by_mock(101, kPress, GDK_KEY_a, kKeyCodeKeyA, state,
1204 kIsNotModifier),
1205 verify_response_handled, &user_data);
1206
1207 EXPECT_EQ(g_call_records->len, 2u);
1208 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1209 EXPECT_EQ(record->event->timestamp, 101000);
1210 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1211 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1212 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1213 EXPECT_STREQ(record->event->character, nullptr);
1214 EXPECT_EQ(record->event->synthesized, true);
1215
1216 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1217 EXPECT_EQ(record->event->timestamp, 101000);
1218 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1219 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1220 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1221 EXPECT_STREQ(record->event->character, "a");
1222 EXPECT_EQ(record->event->synthesized, false);
1223
1224 invoke_record_callback_and_verify(record, TRUE, &user_data);
1225 g_ptr_array_clear(g_call_records);
1226
1227 // A key up of control left is missed.
1228 state = static_cast<GdkModifierType>(0);
1229
1230 // Send a normal event (KeyA up)
1231 fl_key_responder_handle_event(
1232 responder,
1233 fl_key_event_new_by_mock(102, kRelease, GDK_KEY_A, kKeyCodeKeyA, state,
1234 kIsNotModifier),
1235 verify_response_handled, &user_data);
1236
1237 EXPECT_EQ(g_call_records->len, 2u);
1238 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1239 EXPECT_EQ(record->event->timestamp, 102000);
1240 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1241 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1242 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1243 EXPECT_STREQ(record->event->character, nullptr);
1244 EXPECT_EQ(record->event->synthesized, true);
1245
1246 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1247 EXPECT_EQ(record->event->timestamp, 102000);
1248 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1249 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1250 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1251 EXPECT_STREQ(record->event->character, nullptr);
1252 EXPECT_EQ(record->event->synthesized, false);
1253
1254 invoke_record_callback_and_verify(record, TRUE, &user_data);
1255 g_ptr_array_clear(g_call_records);
1256
1257 // Test non-default key mapping.
1258
1259 // Press a key with physical CapsLock and logical ControlLeft.
1260 state = static_cast<GdkModifierType>(0);
1261
1262 fl_key_responder_handle_event(
1263 responder,
1264 fl_key_event_new_by_mock(101, kPress, GDK_KEY_Control_L, kKeyCodeCapsLock,
1265 state, kIsModifier),
1266 verify_response_handled, &user_data);
1267
1268 EXPECT_EQ(g_call_records->len, 1u);
1269 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1270 EXPECT_EQ(record->event->timestamp, 101000);
1271 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1272 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1273 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1274 EXPECT_STREQ(record->event->character, nullptr);
1275 EXPECT_EQ(record->event->synthesized, false);
1276
1277 invoke_record_callback_and_verify(record, TRUE, &user_data);
1278 g_ptr_array_clear(g_call_records);
1279
1280 // The key up of the control left press is missed.
1281 state = static_cast<GdkModifierType>(0);
1282
1283 // Send a normal event (KeyA down).
1284 fl_key_responder_handle_event(
1285 responder,
1286 fl_key_event_new_by_mock(102, kPress, GDK_KEY_A, kKeyCodeKeyA, state,
1287 kIsNotModifier),
1288 verify_response_handled, &user_data);
1289
1290 // The synthesized event should have physical CapsLock and logical
1291 // ControlLeft.
1292 EXPECT_EQ(g_call_records->len, 2u);
1293 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1294 EXPECT_EQ(record->event->timestamp, 102000);
1295 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1296 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1297 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1298 EXPECT_STREQ(record->event->character, nullptr);
1299 EXPECT_EQ(record->event->synthesized, true);
1300
1301 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1302 EXPECT_EQ(record->event->timestamp, 102000);
1303 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1304 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1305 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1306 EXPECT_STREQ(record->event->character, "A");
1307 EXPECT_EQ(record->event->synthesized, false);
1308
1309 invoke_record_callback_and_verify(record, TRUE, &user_data);
1310 g_ptr_array_clear(g_call_records);
1311
1312 clear_g_call_records();
1313 g_object_unref(responder);
1314 }
1315
1316 // Test if missed modifier keys can be detected and synthesized with state
1317 // information upon events that do not have the standard key mapping.
1318 TEST(FlKeyEmbedderResponderTest,
1319 SynthesizeForDesyncPressingStateOnRemappedEvents) {
1320 EXPECT_EQ(g_call_records, nullptr);
1321 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
1322 FlKeyResponder* responder = FL_KEY_RESPONDER(
1323 fl_key_embedder_responder_new(record_calls, g_call_records));
1324 int user_data = 123; // Arbitrary user data
1325
1326 FlKeyEmbedderCallRecord* record;
1327
1328 // Press a key with physical CapsLock and logical ControlLeft.
1329 GdkModifierType state = static_cast<GdkModifierType>(0);
1330
1331 fl_key_responder_handle_event(
1332 responder,
1333 fl_key_event_new_by_mock(101, kPress, GDK_KEY_Control_L, kKeyCodeCapsLock,
1334 state, kIsModifier),
1335 verify_response_handled, &user_data);
1336
1337 EXPECT_EQ(g_call_records->len, 1u);
1338 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1339 EXPECT_EQ(record->event->timestamp, 101000);
1340 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1341 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1342 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1343 EXPECT_STREQ(record->event->character, nullptr);
1344 EXPECT_EQ(record->event->synthesized, false);
1345
1346 invoke_record_callback_and_verify(record, TRUE, &user_data);
1347 g_ptr_array_clear(g_call_records);
1348
1349 // The key up of the control left press is missed.
1350 state = static_cast<GdkModifierType>(0);
1351
1352 // Send a normal event (KeyA down).
1353 fl_key_responder_handle_event(
1354 responder,
1355 fl_key_event_new_by_mock(102, kPress, GDK_KEY_A, kKeyCodeKeyA, state,
1356 kIsNotModifier),
1357 verify_response_handled, &user_data);
1358
1359 // The synthesized event should have physical CapsLock and logical
1360 // ControlLeft.
1361 EXPECT_EQ(g_call_records->len, 2u);
1362 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1363 EXPECT_EQ(record->event->timestamp, 102000);
1364 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1365 EXPECT_EQ(record->event->physical, kPhysicalCapsLock);
1366 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1367 EXPECT_STREQ(record->event->character, nullptr);
1368 EXPECT_EQ(record->event->synthesized, true);
1369
1370 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1371 EXPECT_EQ(record->event->timestamp, 102000);
1372 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1373 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1374 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1375 EXPECT_STREQ(record->event->character, "A");
1376 EXPECT_EQ(record->event->synthesized, false);
1377
1378 invoke_record_callback_and_verify(record, TRUE, &user_data);
1379 g_ptr_array_clear(g_call_records);
1380
1381 clear_g_call_records();
1382 g_object_unref(responder);
1383 }
1384
1385 // Test if missed lock keys can be detected and synthesized with state
1386 // information upon events that are not for this modifier key.
1387 TEST(FlKeyEmbedderResponderTest, SynthesizeForDesyncLockModeOnNonSelfEvents) {
1388 EXPECT_EQ(g_call_records, nullptr);
1389 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
1390 FlKeyResponder* responder = FL_KEY_RESPONDER(
1391 fl_key_embedder_responder_new(record_calls, g_call_records));
1392 int user_data = 123; // Arbitrary user data
1393
1394 FlKeyEmbedderCallRecord* record;
1395
1396 // The NumLock is desynchronized by being enabled.
1397 GdkModifierType state = GDK_MOD2_MASK;
1398
1399 // Send a normal event
1400 fl_key_responder_handle_event(
1401 responder,
1402 fl_key_event_new_by_mock(101, kPress, GDK_KEY_a, kKeyCodeKeyA, state,
1403 kIsNotModifier),
1404 verify_response_handled, &user_data);
1405
1406 EXPECT_EQ(g_call_records->len, 2u);
1407 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1408 EXPECT_EQ(record->event->timestamp, 101000);
1409 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1410 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1411 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1412 EXPECT_STREQ(record->event->character, nullptr);
1413 EXPECT_EQ(record->event->synthesized, true);
1414
1415 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1416 EXPECT_EQ(record->event->timestamp, 101000);
1417 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1418 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1419 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1420 EXPECT_STREQ(record->event->character, "a");
1421 EXPECT_EQ(record->event->synthesized, false);
1422
1423 invoke_record_callback_and_verify(record, TRUE, &user_data);
1424 g_ptr_array_clear(g_call_records);
1425
1426 // The NumLock is desynchronized by being disabled.
1427 state = static_cast<GdkModifierType>(0);
1428
1429 // Release key A
1430 fl_key_responder_handle_event(
1431 responder,
1432 fl_key_event_new_by_mock(102, kRelease, GDK_KEY_A, kKeyCodeKeyA, state,
1433 kIsNotModifier),
1434 verify_response_handled, &user_data);
1435
1436 EXPECT_EQ(g_call_records->len, 4u);
1437 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1438 EXPECT_EQ(record->event->timestamp, 102000);
1439 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1440 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1441 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1442 EXPECT_STREQ(record->event->character, nullptr);
1443 EXPECT_EQ(record->event->synthesized, true);
1444
1445 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1446 EXPECT_EQ(record->event->timestamp, 102000);
1447 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1448 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1449 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1450 EXPECT_STREQ(record->event->character, nullptr);
1451 EXPECT_EQ(record->event->synthesized, true);
1452
1453 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 2));
1454 EXPECT_EQ(record->event->timestamp, 102000);
1455 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1456 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1457 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1458 EXPECT_STREQ(record->event->character, nullptr);
1459 EXPECT_EQ(record->event->synthesized, true);
1460
1461 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 3));
1462 EXPECT_EQ(record->event->timestamp, 102000);
1463 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1464 EXPECT_EQ(record->event->physical, kPhysicalKeyA);
1465 EXPECT_EQ(record->event->logical, kLogicalKeyA);
1466 EXPECT_STREQ(record->event->character, nullptr);
1467 EXPECT_EQ(record->event->synthesized, false);
1468
1469 invoke_record_callback_and_verify(record, TRUE, &user_data);
1470 g_ptr_array_clear(g_call_records);
1471
1472 // Release NumLock. Since the previous event should have synthesized NumLock
1473 // to be released, this should result in only an empty event.
1474 g_expected_handled = true;
1475 fl_key_responder_handle_event(
1476 responder,
1477 fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Num_Lock, kKeyCodeNumLock,
1478 state, kIsModifier),
1479 verify_response_handled, &user_data);
1480
1481 EXPECT_EQ(g_call_records->len, 1u);
1482 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1483 EXPECT_EQ(record->event->physical, 0ull);
1484 EXPECT_EQ(record->event->logical, 0ull);
1485 EXPECT_STREQ(record->event->character, nullptr);
1486 EXPECT_EQ(record->event->synthesized, false);
1487 EXPECT_EQ(record->callback, nullptr);
1488
1489 clear_g_call_records();
1490 g_object_unref(responder);
1491 }
1492
1493 // Test if missed lock keys can be detected and synthesized with state
1494 // information upon events that are for this modifier key.
1495 TEST(FlKeyEmbedderResponderTest, SynthesizeForDesyncLockModeOnSelfEvents) {
1496 EXPECT_EQ(g_call_records, nullptr);
1497 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
1498 FlKeyResponder* responder = FL_KEY_RESPONDER(
1499 fl_key_embedder_responder_new(record_calls, g_call_records));
1500 int user_data = 123; // Arbitrary user data
1501
1502 FlKeyEmbedderCallRecord* record;
1503
1504 // The NumLock is desynchronized by being enabled.
1505 GdkModifierType state = GDK_MOD2_MASK;
1506
1507 // NumLock down
1508 fl_key_responder_handle_event(
1509 responder,
1510 fl_key_event_new_by_mock(101, kPress, GDK_KEY_Num_Lock, kKeyCodeNumLock,
1511 state, kIsModifier),
1512 verify_response_handled, &user_data);
1513
1514 EXPECT_EQ(g_call_records->len, 3u);
1515 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1516 EXPECT_EQ(record->event->timestamp, 101000);
1517 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1518 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1519 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1520 EXPECT_STREQ(record->event->character, nullptr);
1521 EXPECT_EQ(record->event->synthesized, true);
1522
1523 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1524 EXPECT_EQ(record->event->timestamp, 101000);
1525 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1526 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1527 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1528 EXPECT_STREQ(record->event->character, nullptr);
1529 EXPECT_EQ(record->event->synthesized, true);
1530
1531 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 2));
1532 EXPECT_EQ(record->event->timestamp, 101000);
1533 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1534 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1535 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1536 EXPECT_STREQ(record->event->character, nullptr);
1537 EXPECT_EQ(record->event->synthesized, false);
1538
1539 invoke_record_callback_and_verify(record, TRUE, &user_data);
1540 g_ptr_array_clear(g_call_records);
1541
1542 // The NumLock is desynchronized by being enabled in a press event.
1543 state = GDK_MOD2_MASK;
1544
1545 // NumLock up
1546 fl_key_responder_handle_event(
1547 responder,
1548 fl_key_event_new_by_mock(102, kPress, GDK_KEY_Num_Lock, kKeyCodeNumLock,
1549 state, kIsModifier),
1550 verify_response_handled, &user_data);
1551
1552 EXPECT_EQ(g_call_records->len, 4u);
1553 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1554 EXPECT_EQ(record->event->timestamp, 102000);
1555 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1556 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1557 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1558 EXPECT_STREQ(record->event->character, nullptr);
1559 EXPECT_EQ(record->event->synthesized, true);
1560
1561 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1562 EXPECT_EQ(record->event->timestamp, 102000);
1563 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1564 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1565 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1566 EXPECT_STREQ(record->event->character, nullptr);
1567 EXPECT_EQ(record->event->synthesized, true);
1568
1569 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 2));
1570 EXPECT_EQ(record->event->timestamp, 102000);
1571 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1572 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1573 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1574 EXPECT_STREQ(record->event->character, nullptr);
1575 EXPECT_EQ(record->event->synthesized, true);
1576
1577 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 3));
1578 EXPECT_EQ(record->event->timestamp, 102000);
1579 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1580 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1581 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1582 EXPECT_STREQ(record->event->character, nullptr);
1583 EXPECT_EQ(record->event->synthesized, false);
1584
1585 invoke_record_callback_and_verify(record, TRUE, &user_data);
1586 g_ptr_array_clear(g_call_records);
1587
1588 clear_g_call_records();
1589 g_object_unref(responder);
1590 }
1591
1592 // Ensures that even if the primary event is ignored (due to duplicate
1593 // key up or down events), key synthesization is still performed.
1594 TEST(FlKeyEmbedderResponderTest, SynthesizationOccursOnIgnoredEvents) {
1595 EXPECT_EQ(g_call_records, nullptr);
1596 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
1597 FlKeyResponder* responder = FL_KEY_RESPONDER(
1598 fl_key_embedder_responder_new(record_calls, g_call_records));
1599 int user_data = 123; // Arbitrary user data
1600
1601 FlKeyEmbedderCallRecord* record;
1602
1603 // The NumLock is desynchronized by being enabled, and Control is pressed.
1604 GdkModifierType state =
1605 static_cast<GdkModifierType>(GDK_MOD2_MASK | GDK_CONTROL_MASK);
1606
1607 // Send a KeyA up event, which will be ignored.
1608 g_expected_handled = true; // The ignored event is always handled.
1609 fl_key_responder_handle_event(
1610 responder,
1611 fl_key_event_new_by_mock(101, kRelease, GDK_KEY_a, kKeyCodeKeyA, state,
1612 kIsNotModifier),
1613 verify_response_handled, &user_data);
1614
1615 EXPECT_EQ(g_call_records->len, 2u);
1616 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1617 EXPECT_EQ(record->event->timestamp, 101000);
1618 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1619 EXPECT_EQ(record->event->physical, kPhysicalNumLock);
1620 EXPECT_EQ(record->event->logical, kLogicalNumLock);
1621 EXPECT_STREQ(record->event->character, nullptr);
1622 EXPECT_EQ(record->event->synthesized, true);
1623
1624 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1625 EXPECT_EQ(record->event->timestamp, 101000);
1626 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1627 EXPECT_EQ(record->event->physical, kPhysicalControlLeft);
1628 EXPECT_EQ(record->event->logical, kLogicalControlLeft);
1629 EXPECT_STREQ(record->event->character, nullptr);
1630 EXPECT_EQ(record->event->synthesized, true);
1631
1632 g_ptr_array_clear(g_call_records);
1633
1634 clear_g_call_records();
1635 g_object_unref(responder);
1636 }
1637
1638 // This test case occurs when the following two cases collide:
1639 //
1640 // 1. When holding shift, AltRight key gives logical GDK_KEY_Meta_R with the
1641 // state bitmask still MOD3 (Alt).
1642 // 2. When holding AltRight, ShiftLeft key gives logical GDK_KEY_ISO_Next_Group
1643 // with the state bitmask RESERVED_14.
1644 //
1645 // The resulting event sequence is not perfectly ideal: it had to synthesize
1646 // AltLeft down because the physical AltRight key corresponds to logical
1647 // MetaRight at the moment.
1648 TEST(FlKeyEmbedderResponderTest, HandlesShiftAltVersusGroupNext) {
1649 EXPECT_EQ(g_call_records, nullptr);
1650 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
1651 FlKeyResponder* responder = FL_KEY_RESPONDER(
1652 fl_key_embedder_responder_new(record_calls, g_call_records));
1653
1654 g_expected_handled = true;
1655 guint32 now_time = 1;
1656 // A convenient shorthand to simulate events.
1657 auto send_key_event = [responder, &now_time](bool is_press, guint keyval,
1658 guint16 keycode,
1659 GdkModifierType state) {
1660 now_time += 1;
1661 int user_data = 123; // Arbitrary user data
1662 fl_key_responder_handle_event(
1663 responder,
1664 fl_key_event_new_by_mock(now_time, is_press, keyval, keycode, state,
1665 kIsModifier),
1666 verify_response_handled, &user_data);
1667 };
1668
1669 FlKeyEmbedderCallRecord* record;
1670
1671 send_key_event(kPress, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
1672 GDK_MODIFIER_RESERVED_25_MASK);
1673 EXPECT_EQ(g_call_records->len, 1u);
1674 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1675 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1676 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
1677 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
1678 EXPECT_EQ(record->event->synthesized, false);
1679
1680 send_key_event(kPress, GDK_KEY_Meta_R, kKeyCodeAltRight,
1681 static_cast<GdkModifierType>(GDK_SHIFT_MASK |
1682 GDK_MODIFIER_RESERVED_25_MASK));
1683 EXPECT_EQ(g_call_records->len, 2u);
1684 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1685 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1686 EXPECT_EQ(record->event->physical, kPhysicalAltRight);
1687 EXPECT_EQ(record->event->logical, kLogicalMetaRight);
1688 EXPECT_EQ(record->event->synthesized, false);
1689
1690 send_key_event(kRelease, GDK_KEY_ISO_Next_Group, kKeyCodeShiftLeft,
1691 static_cast<GdkModifierType>(GDK_SHIFT_MASK | GDK_MOD1_MASK |
1692 GDK_MODIFIER_RESERVED_25_MASK));
1693 EXPECT_EQ(g_call_records->len, 5u);
1694 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 2));
1695 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1696 EXPECT_EQ(record->event->physical, kPhysicalAltLeft);
1697 EXPECT_EQ(record->event->logical, kLogicalAltLeft);
1698 EXPECT_EQ(record->event->synthesized, true);
1699
1700 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 3));
1701 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1702 EXPECT_EQ(record->event->physical, kPhysicalAltRight);
1703 EXPECT_EQ(record->event->logical, kLogicalMetaRight);
1704 EXPECT_EQ(record->event->synthesized, true);
1705
1706 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 4));
1707 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1708 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
1709 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
1710 EXPECT_EQ(record->event->synthesized, false);
1711
1712 send_key_event(kPress, GDK_KEY_ISO_Next_Group, kKeyCodeShiftLeft,
1713 static_cast<GdkModifierType>(GDK_MOD1_MASK |
1714 GDK_MODIFIER_RESERVED_25_MASK));
1715 EXPECT_EQ(g_call_records->len, 6u);
1716 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 5));
1717 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1718 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
1719 EXPECT_EQ(record->event->logical, kLogicalGroupNext);
1720 EXPECT_EQ(record->event->synthesized, false);
1721
1722 send_key_event(kRelease, GDK_KEY_ISO_Level3_Shift, kKeyCodeAltRight,
1723 static_cast<GdkModifierType>(GDK_MOD1_MASK |
1724 GDK_MODIFIER_RESERVED_13_MASK |
1725 GDK_MODIFIER_RESERVED_25_MASK));
1726 EXPECT_EQ(g_call_records->len, 7u);
1727 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 6));
1728 EXPECT_EQ(record->event->physical, 0u);
1729 EXPECT_EQ(record->event->logical, 0u);
1730
1731 send_key_event(kRelease, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
1732 static_cast<GdkModifierType>(GDK_MODIFIER_RESERVED_13_MASK |
1733 GDK_MODIFIER_RESERVED_25_MASK));
1734 EXPECT_EQ(g_call_records->len, 9u);
1735 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 7));
1736 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1737 EXPECT_EQ(record->event->physical, kPhysicalAltLeft);
1738 EXPECT_EQ(record->event->logical, kLogicalAltLeft);
1739 EXPECT_EQ(record->event->synthesized, true);
1740
1741 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 8));
1742 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeUp);
1743 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
1744 EXPECT_EQ(record->event->logical, kLogicalGroupNext);
1745 EXPECT_EQ(record->event->synthesized, false);
1746
1747 clear_g_call_records();
1748 g_object_unref(responder);
1749 }
1750
1751 // Shift + AltLeft results in GDK event whose keyval is MetaLeft but whose
1752 // keycode is either AltLeft or Shift keycode (depending on which one was
1753 // released last). The physical key is usually deduced from the keycode, but in
1754 // this case (Shift + AltLeft) a correction is needed otherwise the physical
1755 // key won't be the MetaLeft one.
1756 // Regression test for https://github.com/flutter/flutter/issues/96082
1757 TEST(FlKeyEmbedderResponderTest, HandlesShiftAltLeftIsMetaLeft) {
1758 EXPECT_EQ(g_call_records, nullptr);
1759 g_call_records = g_ptr_array_new_with_free_func(g_object_unref);
1760 FlKeyResponder* responder = FL_KEY_RESPONDER(
1761 fl_key_embedder_responder_new(record_calls, g_call_records));
1762
1763 g_expected_handled = true;
1764 guint32 now_time = 1;
1765 // A convenient shorthand to simulate events.
1766 auto send_key_event = [responder, &now_time](bool is_press, guint keyval,
1767 guint16 keycode,
1768 GdkModifierType state) {
1769 now_time += 1;
1770 int user_data = 123; // Arbitrary user data
1771 fl_key_responder_handle_event(
1772 responder,
1773 fl_key_event_new_by_mock(now_time, is_press, keyval, keycode, state,
1774 kIsModifier),
1775 verify_response_handled, &user_data);
1776 };
1777
1778 FlKeyEmbedderCallRecord* record;
1779
1780 // ShiftLeft + AltLeft
1781 send_key_event(kPress, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
1782 GDK_MODIFIER_RESERVED_25_MASK);
1783 EXPECT_EQ(g_call_records->len, 1u);
1784 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1785 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1786 EXPECT_EQ(record->event->physical, kPhysicalShiftLeft);
1787 EXPECT_EQ(record->event->logical, kLogicalShiftLeft);
1788 EXPECT_EQ(record->event->synthesized, false);
1789
1790 send_key_event(kPress, GDK_KEY_Meta_L, kKeyCodeAltLeft,
1791 static_cast<GdkModifierType>(GDK_SHIFT_MASK |
1792 GDK_MODIFIER_RESERVED_25_MASK));
1793 EXPECT_EQ(g_call_records->len, 2u);
1794 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1795 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1796 EXPECT_EQ(record->event->physical, kPhysicalMetaLeft);
1797 EXPECT_EQ(record->event->logical, kLogicalMetaLeft);
1798 EXPECT_EQ(record->event->synthesized, false);
1799
1800 send_key_event(kRelease, GDK_KEY_Meta_L, kKeyCodeAltLeft,
1801 static_cast<GdkModifierType>(GDK_MODIFIER_RESERVED_13_MASK |
1802 GDK_MODIFIER_RESERVED_25_MASK));
1803 send_key_event(kRelease, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
1804 GDK_MODIFIER_RESERVED_25_MASK);
1805 g_ptr_array_clear(g_call_records);
1806
1807 // ShiftRight + AltLeft
1808 send_key_event(kPress, GDK_KEY_Shift_R, kKeyCodeShiftRight,
1809 GDK_MODIFIER_RESERVED_25_MASK);
1810 EXPECT_EQ(g_call_records->len, 1u);
1811 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
1812 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1813 EXPECT_EQ(record->event->physical, kPhysicalShiftRight);
1814 EXPECT_EQ(record->event->logical, kLogicalShiftRight);
1815 EXPECT_EQ(record->event->synthesized, false);
1816
1817 send_key_event(kPress, GDK_KEY_Meta_L, kKeyCodeAltLeft,
1818 static_cast<GdkModifierType>(GDK_SHIFT_MASK |
1819 GDK_MODIFIER_RESERVED_25_MASK));
1820 EXPECT_EQ(g_call_records->len, 2u);
1821 record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 1));
1822 EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
1823 EXPECT_EQ(record->event->physical, kPhysicalMetaLeft);
1824 EXPECT_EQ(record->event->logical, kLogicalMetaLeft);
1825 EXPECT_EQ(record->event->synthesized, false);
1826
1827 clear_g_call_records();
1828 g_object_unref(responder);
1829 }
event
FlKeyEvent * event
Definition: fl_key_channel_responder.cc:118
fl_key_embedder_responder.h
clear_g_call_records
static void clear_g_call_records()
Definition: fl_key_embedder_responder_test.cc:162
user_data
FlKeyEvent uint64_t FlKeyResponderAsyncCallback gpointer user_data
Definition: fl_key_channel_responder.cc:121
fl_key_embedder_call_record_class_init
static void fl_key_embedder_call_record_class_init(FlKeyEmbedderCallRecordClass *klass)
Definition: fl_key_embedder_responder_test.cc:74
_FlKeyEvent
Definition: fl_key_event.h:22
state
AtkStateType state
Definition: fl_accessible_node.cc:10
_FlKeyEmbedderCallRecord::event
FlutterKeyEvent * event
Definition: fl_key_embedder_responder_test.cc:50
record_calls
static void record_calls(const FlutterKeyEvent *event, FlutterKeyEventCallback callback, void *callback_user_data, void *send_key_event_user_data)
Definition: fl_key_embedder_responder_test.cc:150
fl_key_embedder_responder_new
FlKeyEmbedderResponder * fl_key_embedder_responder_new(EmbedderSendKeyEvent send_key_event, void *send_key_event_user_data)
Definition: fl_key_embedder_responder.cc:263
fl_key_event_new_by_mock
static FlKeyEvent * fl_key_event_new_by_mock(guint32 time_in_milliseconds, bool is_press, guint keyval, guint16 keycode, GdkModifierType state, gboolean is_modifier)
Definition: fl_key_embedder_responder_test.cc:115
fl_key_responder_handle_event
void fl_key_responder_handle_event(FlKeyResponder *self, FlKeyEvent *event, FlKeyResponderAsyncCallback callback, gpointer user_data, uint64_t specified_logical_key)
Definition: fl_key_responder.cc:11
_FlKeyEmbedderCallRecord::callback
FlutterKeyEventCallback callback
Definition: fl_key_embedder_responder_test.cc:51
_FlKeyEmbedderCallRecord::parent_instance
GObject parent_instance
Definition: fl_key_embedder_responder_test.cc:48
fl_engine_private.h
_FlKeyEvent::is_press
bool is_press
Definition: fl_key_event.h:26
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
_FlKeyEmbedderCallRecord
Definition: fl_key_embedder_responder_test.cc:47
fl_key_embedder_call_record_dispose
static void fl_key_embedder_call_record_dispose(GObject *object)
Definition: fl_key_embedder_responder_test.cc:62
G_DEFINE_TYPE
G_DEFINE_TYPE(FlKeyEmbedderCallRecord, fl_key_embedder_call_record, G_TYPE_OBJECT) static void fl_key_embedder_call_record_init(FlKeyEmbedderCallRecord *self)
Definition: fl_key_embedder_responder_test.cc:55
FL
FL
Definition: fl_binary_messenger.cc:27
fl_key_embedder_call_record_new
static FlKeyEmbedderCallRecord * fl_key_embedder_call_record_new(const FlutterKeyEvent *event, FlutterKeyEventCallback callback, gpointer user_data)
Definition: fl_key_embedder_responder_test.cc:79
fl_binary_messenger_private.h
_FlKeyEmbedderCallRecord::user_data
gpointer user_data
Definition: fl_key_embedder_responder_test.cc:52
g_expected_handled
static gboolean g_expected_handled
Definition: fl_key_embedder_responder_test.cc:130
invoke_record_callback_and_verify
static void invoke_record_callback_and_verify(FlKeyEmbedderCallRecord *record, bool expected_handled, void *expected_user_data)
Definition: fl_key_embedder_responder_test.cc:137
g_ptr_array_clear
static void g_ptr_array_clear(GPtrArray *array)
Definition: fl_key_embedder_responder_test.cc:37
g_expected_user_data
static gpointer g_expected_user_data
Definition: fl_key_embedder_responder_test.cc:131
verify_response_handled
static void verify_response_handled(bool handled, gpointer user_data)
Definition: fl_key_embedder_responder_test.cc:133
G_DECLARE_FINAL_TYPE
G_DECLARE_FINAL_TYPE(FlKeyEmbedderCallRecord, fl_key_embedder_call_record, FL, KEY_EMBEDDER_CALL_RECORD, GObject)
send_key_event
static void send_key_event(FlTextInputPlugin *plugin, gint keyval, gint state=0)
Definition: fl_text_input_plugin_test.cc:181
callback
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Definition: fl_key_channel_responder.cc:120
TEST
TEST(FlKeyEmbedderResponderTest, SendKeyEvent)
Definition: fl_key_embedder_responder_test.cc:168
expected_handled
static gboolean expected_handled
Definition: fl_key_channel_responder_test.cc:14