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 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 
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);
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 =
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,
143 
144  EXPECT_EQ(call_records->len, 1u);
145  FlKeyEmbedderCallRecord* record =
146  FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
147  EXPECT_EQ(record->event->struct_size, sizeof(FlutterKeyEvent));
148  EXPECT_EQ(record->event->timestamp, 12345000);
149  EXPECT_EQ(record->event->type, kFlutterKeyEventTypeDown);
150  EXPECT_EQ(record->event->physical, kPhysicalKeyA);
151  EXPECT_EQ(record->event->logical, kLogicalKeyA);
152  EXPECT_STREQ(record->event->character, "a");
153  EXPECT_EQ(record->event->synthesized, false);
154 
156  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,
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 
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,
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 
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,
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 
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 =
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,
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 
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 =
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,
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 
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,
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 
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,
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 
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,
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 
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 =
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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 =
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,
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 
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,
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 
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,
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 
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,
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 
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 =
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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 =
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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,
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 
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 =
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,
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));
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,
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 
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,
914 
915  EXPECT_EQ(call_records->len, 1u);
916  record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
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 =
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,
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 =
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,
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 
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,
995  EXPECT_EQ(call_records->len, 1u);
996  record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
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,
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 
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,
1035  EXPECT_EQ(call_records->len, 1u);
1036  record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(call_records, 0));
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,
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 =
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,
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 
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,
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 
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,
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 
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,
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 
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 =
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,
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 
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,
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 
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 =
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,
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 
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,
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 
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,
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 =
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,
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 
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,
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 
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 =
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,
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 =
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,
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 =
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,
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