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