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