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 
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"
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 
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.
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);
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(
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);
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 
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);
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 
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);
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 
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);
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 
227  g_ptr_array_clear(g_call_records);
228 
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(
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);
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 
262  g_ptr_array_clear(g_call_records);
263 
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(
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);
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 
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);
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 
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);
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 
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);
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 
346  g_ptr_array_clear(g_call_records);
347 
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(
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
505  g_ptr_array_clear(g_call_records);
506 
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(
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);
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 
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);
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 
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);
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 
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);
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 
596  g_ptr_array_clear(g_call_records);
597 
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(
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
751  g_ptr_array_clear(g_call_records);
752 
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(
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
906  g_ptr_array_clear(g_call_records);
907 
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(
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);
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));
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);
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 
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);
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));
963  g_ptr_array_clear(g_call_records);
964 
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(
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);
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 
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);
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 
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);
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));
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);
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 
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);
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));
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
1245  g_ptr_array_clear(g_call_records);
1246 
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);
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 
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);
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 
1312  g_ptr_array_clear(g_call_records);
1313 
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);
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 
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);
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 
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);
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 
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);
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 
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);
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 
1514  g_ptr_array_clear(g_call_records);
1515 
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);
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 
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);
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 
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);
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 
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