5 #import <Foundation/Foundation.h>
8 #include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
9 #import "flutter/testing/testing.h"
10 #include "third_party/googletest/googletest/include/gtest/gtest.h"
14 @property(nonatomic) FlutterKeyEvent*
data;
15 @property(nonatomic) FlutterKeyEventCallback
callback;
17 - (nonnull instancetype)initWithEvent:(const FlutterKeyEvent*)event
18 callback:(nullable FlutterKeyEventCallback)callback
19 userData:(nullable
void*)userData;
21 - (void)respond:(BOOL)handled;
25 - (instancetype)initWithEvent:(const FlutterKeyEvent*)event
26 callback:(nullable FlutterKeyEventCallback)callback
27 userData:(nullable
void*)userData {
29 _data =
new FlutterKeyEvent(*event);
30 if (event->character !=
nullptr) {
31 size_t len = strlen(event->character);
32 char* character =
new char[len + 1];
33 strlcpy(character, event->character,
sizeof(character));
34 _data->character = character;
42 return _callback != nil;
45 - (void)respond:(BOOL)handled {
48 @"Improper call to `respond` that does not have a callback.");
49 _callback(handled, _userData);
53 if (_data->character !=
nullptr) {
54 delete[] _data->character;
63 constexpr uint64_t kKeyCodeKeyA = 0x00;
64 constexpr uint64_t kKeyCodeKeyW = 0x0d;
65 constexpr uint64_t kKeyCodeShiftLeft = 0x38;
66 constexpr uint64_t kKeyCodeShiftRight = 0x3c;
67 constexpr uint64_t kKeyCodeCapsLock = 0x39;
68 constexpr uint64_t kKeyCodeNumpad1 = 0x53;
69 constexpr uint64_t kKeyCodeF1 = 0x7a;
70 constexpr uint64_t kKeyCodeAltRight = 0x3d;
72 using namespace ::flutter::testing::keycodes;
74 typedef void (^ResponseCallback)(
bool handled);
76 NSEvent* keyEvent(NSEventType type,
77 NSEventModifierFlags modifierFlags,
79 NSString* charactersIgnoringModifiers,
81 unsigned short keyCode) {
82 return [NSEvent keyEventWithType:type
84 modifierFlags:modifierFlags
89 charactersIgnoringModifiers:charactersIgnoringModifiers
94 NSEvent* keyEvent(NSEventType type,
95 NSTimeInterval timestamp,
96 NSEventModifierFlags modifierFlags,
98 NSString* charactersIgnoringModifiers,
100 unsigned short keyCode) {
101 return [NSEvent keyEventWithType:type
103 modifierFlags:modifierFlags
107 characters:characters
108 charactersIgnoringModifiers:charactersIgnoringModifiers
118 TEST(FlutterEmbedderKeyResponderUnittests, BasicKeyEvent) {
119 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
120 __block BOOL last_handled = TRUE;
121 FlutterKeyEvent* event;
124 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
125 void* _Nullable user_data) {
126 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
128 userData:user_data]];
131 last_handled = FALSE;
132 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 123.0f, 0x100, @"a", @"a", FALSE, 0)
134 last_handled = handled;
137 EXPECT_EQ([events count], 1u);
138 event = [events lastObject].data;
139 ASSERT_NE(event,
nullptr);
140 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
141 EXPECT_EQ(event->timestamp, 123000000.0f);
142 EXPECT_EQ(event->physical, kPhysicalKeyA);
143 EXPECT_EQ(event->logical, kLogicalKeyA);
144 EXPECT_STREQ(event->character,
"a");
145 EXPECT_EQ(event->synthesized,
false);
147 EXPECT_EQ(last_handled, FALSE);
149 [[events lastObject] respond:TRUE];
150 EXPECT_EQ(last_handled, TRUE);
152 [events removeAllObjects];
154 last_handled = FALSE;
155 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", TRUE, kKeyCodeKeyA)
157 last_handled = handled;
160 EXPECT_EQ([events count], 1u);
161 event = [events lastObject].data;
162 ASSERT_NE(event,
nullptr);
163 EXPECT_EQ(event->type, kFlutterKeyEventTypeRepeat);
164 EXPECT_EQ(event->physical, kPhysicalKeyA);
165 EXPECT_EQ(event->logical, kLogicalKeyA);
166 EXPECT_STREQ(event->character,
"a");
167 EXPECT_EQ(event->synthesized,
false);
169 EXPECT_EQ(last_handled, FALSE);
171 [[events lastObject] respond:TRUE];
172 EXPECT_EQ(last_handled, TRUE);
174 [events removeAllObjects];
177 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 124.0f, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
179 last_handled = handled;
182 EXPECT_EQ([events count], 1u);
183 event = [events lastObject].data;
184 ASSERT_NE(event,
nullptr);
185 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
186 EXPECT_EQ(event->timestamp, 124000000.0f);
187 EXPECT_EQ(event->physical, kPhysicalKeyA);
188 EXPECT_EQ(event->logical, kLogicalKeyA);
189 EXPECT_EQ(event->character,
nullptr);
190 EXPECT_EQ(event->synthesized,
false);
192 EXPECT_EQ(last_handled, TRUE);
194 [[events lastObject] respond:FALSE];
195 EXPECT_EQ(last_handled, FALSE);
197 [events removeAllObjects];
200 TEST(FlutterEmbedderKeyResponderUnittests, NonAsciiCharacters) {
201 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
202 FlutterKeyEvent* event;
205 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
206 void* _Nullable user_data) {
207 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
209 userData:user_data]];
213 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x80140, @"", @"", FALSE, kKeyCodeAltRight)
217 EXPECT_EQ([events count], 1u);
218 event = [events lastObject].data;
219 ASSERT_NE(event,
nullptr);
220 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
221 EXPECT_EQ(event->physical, kPhysicalAltRight);
222 EXPECT_EQ(event->logical, kLogicalAltRight);
223 EXPECT_STREQ(event->character,
nullptr);
224 EXPECT_EQ(event->synthesized,
false);
226 [events removeAllObjects];
228 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x80140, @"â ˆ‘", @"w", FALSE, kKeyCodeKeyW)
232 EXPECT_EQ([events count], 1u);
233 event = [events lastObject].data;
234 ASSERT_NE(event,
nullptr);
235 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
236 EXPECT_EQ(event->physical, kPhysicalKeyW);
237 EXPECT_EQ(event->logical, kLogicalKeyW);
238 EXPECT_STREQ(event->character,
"∑");
239 EXPECT_EQ(event->synthesized,
false);
241 [events removeAllObjects];
243 [responder
handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeAltRight)
247 EXPECT_EQ([events count], 1u);
248 event = [events lastObject].data;
249 ASSERT_NE(event,
nullptr);
250 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
251 EXPECT_EQ(event->physical, kPhysicalAltRight);
252 EXPECT_EQ(event->logical, kLogicalAltRight);
253 EXPECT_STREQ(event->character,
nullptr);
254 EXPECT_EQ(event->synthesized,
false);
256 [events removeAllObjects];
258 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x100, @"w", @"w", FALSE, kKeyCodeKeyW)
262 EXPECT_EQ([events count], 1u);
263 event = [events lastObject].data;
264 ASSERT_NE(event,
nullptr);
265 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
266 EXPECT_EQ(event->physical, kPhysicalKeyW);
267 EXPECT_EQ(event->logical, kLogicalKeyW);
268 EXPECT_STREQ(event->character,
nullptr);
269 EXPECT_EQ(event->synthesized,
false);
271 [events removeAllObjects];
274 TEST(FlutterEmbedderKeyResponderUnittests, MultipleCharacters) {
275 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
276 FlutterKeyEvent* event;
279 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
280 void* _Nullable user_data) {
281 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
283 userData:user_data]];
286 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0, @"Ã n", @"Ã n", FALSE, kKeyCodeKeyA)
290 EXPECT_EQ([events count], 1u);
291 event = [events lastObject].data;
292 ASSERT_NE(event,
nullptr);
293 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
294 EXPECT_EQ(event->physical, kPhysicalKeyA);
295 EXPECT_EQ(event->logical, 0x1400000000ull);
296 EXPECT_STREQ(event->character,
"Ã n");
297 EXPECT_EQ(event->synthesized,
false);
299 [events removeAllObjects];
301 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0, @"a", @"a", FALSE, kKeyCodeKeyA)
305 EXPECT_EQ([events count], 1u);
306 event = [events lastObject].data;
307 ASSERT_NE(event,
nullptr);
308 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
309 EXPECT_EQ(event->physical, kPhysicalKeyA);
310 EXPECT_EQ(event->logical, 0x1400000000ull);
311 EXPECT_STREQ(event->character,
nullptr);
312 EXPECT_EQ(event->synthesized,
false);
314 [events removeAllObjects];
317 TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeForDuplicateDownEvent) {
318 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
319 __block BOOL last_handled = TRUE;
320 FlutterKeyEvent* event;
323 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
324 void* _Nullable user_data) {
325 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
327 userData:user_data]];
331 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
333 last_handled = handled;
336 EXPECT_EQ([events count], 1u);
337 event = [events lastObject].data;
338 ASSERT_NE(event,
nullptr);
339 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
340 EXPECT_EQ(event->physical, kPhysicalKeyA);
341 EXPECT_EQ(event->logical, kLogicalKeyA);
342 EXPECT_STREQ(event->character,
"a");
343 EXPECT_EQ(event->synthesized,
false);
344 EXPECT_EQ(last_handled, TRUE);
345 [[events lastObject] respond:FALSE];
346 EXPECT_EQ(last_handled, FALSE);
348 [events removeAllObjects];
351 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"Ã ", @"Ã ", FALSE, kKeyCodeKeyA)
353 last_handled = handled;
356 EXPECT_EQ([events count], 2u);
358 event = [events firstObject].data;
359 ASSERT_NE(event,
nullptr);
360 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
361 EXPECT_EQ(event->physical, kPhysicalKeyA);
362 EXPECT_EQ(event->logical, kLogicalKeyA);
363 EXPECT_STREQ(event->character, NULL);
364 EXPECT_EQ(event->synthesized,
true);
366 event = [events lastObject].data;
367 ASSERT_NE(event,
nullptr);
368 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
369 EXPECT_EQ(event->physical, kPhysicalKeyA);
370 EXPECT_EQ(event->logical, 0xE0ull );
371 EXPECT_STREQ(event->character,
"Ã ");
372 EXPECT_EQ(event->synthesized,
false);
373 [[events lastObject] respond:FALSE];
374 EXPECT_EQ(last_handled, FALSE);
376 [events removeAllObjects];
379 TEST(FlutterEmbedderKeyResponderUnittests, IgnoreDuplicateUpEvent) {
380 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
381 FlutterKeyEvent* event;
382 __block BOOL last_handled = TRUE;
385 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
386 void* _Nullable user_data) {
387 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
389 userData:user_data]];
392 last_handled = FALSE;
393 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
395 last_handled = handled;
398 EXPECT_EQ([events count], 1u);
399 EXPECT_EQ(last_handled, TRUE);
400 event = [events lastObject].data;
401 ASSERT_NE(event,
nullptr);
402 EXPECT_EQ(event->physical, 0ull);
403 EXPECT_EQ(event->logical, 0ull);
405 EXPECT_EQ(last_handled, TRUE);
407 [events removeAllObjects];
410 TEST(FlutterEmbedderKeyResponderUnittests, ConvertAbruptRepeatEventsToDown) {
411 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
412 __block BOOL last_handled = TRUE;
413 FlutterKeyEvent* event;
416 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
417 void* _Nullable user_data) {
418 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
420 userData:user_data]];
424 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", TRUE, kKeyCodeKeyA)
426 last_handled = handled;
429 EXPECT_EQ([events count], 1u);
430 event = [events lastObject].data;
431 ASSERT_NE(event,
nullptr);
432 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
433 EXPECT_EQ(event->physical, kPhysicalKeyA);
434 EXPECT_EQ(event->logical, kLogicalKeyA);
435 EXPECT_STREQ(event->character,
"a");
436 EXPECT_EQ(event->synthesized,
false);
437 EXPECT_EQ(last_handled, TRUE);
438 [[events lastObject] respond:FALSE];
439 EXPECT_EQ(last_handled, FALSE);
441 [events removeAllObjects];
448 TEST(FlutterEmbedderKeyResponderUnittests, ToggleModifiersDuringKeyTap) {
449 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
450 FlutterKeyEvent* event;
453 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
454 void* _Nullable user_data) {
455 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
457 userData:user_data]];
460 [responder
handleEvent:keyEvent(NSEventTypeFlagsChanged, 123.0f, 0x20104, @"", @"", FALSE,
465 EXPECT_EQ([events count], 1u);
466 event = [events lastObject].data;
467 ASSERT_NE(event,
nullptr);
468 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
469 EXPECT_EQ(event->timestamp, 123000000.0f);
470 EXPECT_EQ(event->physical, kPhysicalShiftRight);
471 EXPECT_EQ(event->logical, kLogicalShiftRight);
472 EXPECT_STREQ(event->character,
nullptr);
473 EXPECT_EQ(event->synthesized,
false);
474 [[events lastObject] respond:TRUE];
476 [events removeAllObjects];
478 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x20104, @"A", @"A", FALSE, kKeyCodeKeyA)
482 EXPECT_EQ([events count], 1u);
483 event = [events lastObject].data;
484 ASSERT_NE(event,
nullptr);
485 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
486 EXPECT_EQ(event->physical, kPhysicalKeyA);
487 EXPECT_EQ(event->logical, kLogicalKeyA);
488 EXPECT_STREQ(event->character,
"A");
489 EXPECT_EQ(event->synthesized,
false);
490 [[events lastObject] respond:TRUE];
492 [events removeAllObjects];
494 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x20104, @"A", @"A", TRUE, kKeyCodeKeyA)
498 EXPECT_EQ([events count], 1u);
499 event = [events lastObject].data;
500 ASSERT_NE(event,
nullptr);
501 EXPECT_EQ(event->type, kFlutterKeyEventTypeRepeat);
502 EXPECT_EQ(event->physical, kPhysicalKeyA);
503 EXPECT_EQ(event->logical, kLogicalKeyA);
504 EXPECT_STREQ(event->character,
"A");
505 EXPECT_EQ(event->synthesized,
false);
506 [[events lastObject] respond:TRUE];
508 [events removeAllObjects];
511 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftRight)
515 EXPECT_EQ([events count], 1u);
516 event = [events lastObject].data;
517 ASSERT_NE(event,
nullptr);
518 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
519 EXPECT_EQ(event->physical, kPhysicalShiftRight);
520 EXPECT_EQ(event->logical, kLogicalShiftRight);
521 EXPECT_STREQ(event->character,
nullptr);
522 EXPECT_EQ(event->synthesized,
false);
523 [[events lastObject] respond:TRUE];
525 [events removeAllObjects];
527 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", TRUE, kKeyCodeKeyA)
531 EXPECT_EQ([events count], 1u);
532 event = [events lastObject].data;
533 ASSERT_NE(event,
nullptr);
534 EXPECT_EQ(event->type, kFlutterKeyEventTypeRepeat);
535 EXPECT_EQ(event->physical, kPhysicalKeyA);
536 EXPECT_EQ(event->logical, kLogicalKeyA);
537 EXPECT_STREQ(event->character,
"a");
538 EXPECT_EQ(event->synthesized,
false);
540 [events removeAllObjects];
542 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
546 EXPECT_EQ([events count], 1u);
547 event = [events lastObject].data;
548 ASSERT_NE(event,
nullptr);
549 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
550 EXPECT_EQ(event->physical, kPhysicalKeyA);
551 EXPECT_EQ(event->logical, kLogicalKeyA);
552 EXPECT_STREQ(event->character,
nullptr);
553 EXPECT_EQ(event->synthesized,
false);
554 [[events lastObject] respond:TRUE];
556 [events removeAllObjects];
564 TEST(FlutterEmbedderKeyResponderUnittests, SpecialModiferFlags) {
565 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
566 FlutterKeyEvent* event;
569 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
570 void* _Nullable user_data) {
571 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
573 userData:user_data]];
580 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x200100, @"1", @"1", FALSE, kKeyCodeNumpad1)
584 EXPECT_EQ([events count], 1u);
585 event = [events lastObject].data;
586 ASSERT_NE(event,
nullptr);
587 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
588 EXPECT_EQ(event->physical, kPhysicalNumpad1);
589 EXPECT_EQ(event->logical, kLogicalNumpad1);
590 EXPECT_STREQ(event->character,
"1");
591 EXPECT_EQ(event->synthesized,
false);
592 [[events lastObject] respond:TRUE];
594 [events removeAllObjects];
598 handleEvent:keyEvent(NSEventTypeKeyDown, 0x800100, @"\uf704", @"\uf704", FALSE, kKeyCodeF1)
602 EXPECT_EQ([events count], 1u);
603 event = [events lastObject].data;
604 ASSERT_NE(event,
nullptr);
605 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
606 EXPECT_EQ(event->physical, kPhysicalF1);
607 EXPECT_EQ(event->logical, kLogicalF1);
608 EXPECT_STREQ(event->character,
nullptr);
609 EXPECT_EQ(event->synthesized,
false);
610 [[events lastObject] respond:TRUE];
612 [events removeAllObjects];
615 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
619 EXPECT_EQ([events count], 1u);
620 event = [events lastObject].data;
621 ASSERT_NE(event,
nullptr);
622 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
623 EXPECT_EQ(event->physical, kPhysicalKeyA);
624 EXPECT_EQ(event->logical, kLogicalKeyA);
625 EXPECT_STREQ(event->character,
"a");
626 EXPECT_EQ(event->synthesized,
false);
627 [[events lastObject] respond:TRUE];
629 [events removeAllObjects];
633 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
637 EXPECT_EQ([events count], 1u);
638 event = [events lastObject].data;
639 ASSERT_NE(event,
nullptr);
640 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
641 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
642 EXPECT_EQ(event->logical, kLogicalShiftLeft);
643 EXPECT_STREQ(event->character,
nullptr);
644 EXPECT_EQ(event->synthesized,
false);
645 [[events lastObject] respond:TRUE];
647 [events removeAllObjects];
650 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x220102, @"1", @"1", FALSE, kKeyCodeNumpad1)
654 EXPECT_EQ([events count], 1u);
655 event = [events lastObject].data;
656 ASSERT_NE(event,
nullptr);
657 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
658 EXPECT_EQ(event->physical, kPhysicalNumpad1);
659 EXPECT_EQ(event->logical, kLogicalNumpad1);
660 EXPECT_STREQ(event->character,
nullptr);
661 EXPECT_EQ(event->synthesized,
false);
662 [[events lastObject] respond:TRUE];
664 [events removeAllObjects];
668 handleEvent:keyEvent(NSEventTypeKeyUp, 0x820102, @"\uF704", @"\uF704", FALSE, kKeyCodeF1)
672 EXPECT_EQ([events count], 1u);
673 event = [events lastObject].data;
674 ASSERT_NE(event,
nullptr);
675 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
676 EXPECT_EQ(event->physical, kPhysicalF1);
677 EXPECT_EQ(event->logical, kLogicalF1);
678 EXPECT_STREQ(event->character,
nullptr);
679 EXPECT_EQ(event->synthesized,
false);
680 [[events lastObject] respond:TRUE];
682 [events removeAllObjects];
685 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x20102, @"a", @"a", FALSE, kKeyCodeKeyA)
689 EXPECT_EQ([events count], 1u);
690 event = [events lastObject].data;
691 ASSERT_NE(event,
nullptr);
692 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
693 EXPECT_EQ(event->physical, kPhysicalKeyA);
694 EXPECT_EQ(event->logical, kLogicalKeyA);
695 EXPECT_STREQ(event->character,
nullptr);
696 EXPECT_EQ(event->synthesized,
false);
697 [[events lastObject] respond:TRUE];
699 [events removeAllObjects];
703 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftLeft)
707 EXPECT_EQ([events count], 1u);
708 event = [events lastObject].data;
709 ASSERT_NE(event,
nullptr);
710 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
711 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
712 EXPECT_EQ(event->logical, kLogicalShiftLeft);
713 EXPECT_STREQ(event->character,
nullptr);
714 EXPECT_EQ(event->synthesized,
false);
715 [[events lastObject] respond:TRUE];
717 [events removeAllObjects];
720 TEST(FlutterEmbedderKeyResponderUnittests, IdentifyLeftAndRightModifiers) {
721 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
722 FlutterKeyEvent* event;
725 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
726 void* _Nullable user_data) {
727 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
729 userData:user_data]];
733 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
737 EXPECT_EQ([events count], 1u);
738 event = [events lastObject].data;
739 ASSERT_NE(event,
nullptr);
740 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
741 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
742 EXPECT_EQ(event->logical, kLogicalShiftLeft);
743 EXPECT_STREQ(event->character,
nullptr);
744 EXPECT_EQ(event->synthesized,
false);
745 [[events lastObject] respond:TRUE];
747 [events removeAllObjects];
750 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20106, @"", @"", FALSE, kKeyCodeShiftRight)
754 EXPECT_EQ([events count], 1u);
755 event = [events lastObject].data;
756 ASSERT_NE(event,
nullptr);
757 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
758 EXPECT_EQ(event->physical, kPhysicalShiftRight);
759 EXPECT_EQ(event->logical, kLogicalShiftRight);
760 EXPECT_STREQ(event->character,
nullptr);
761 EXPECT_EQ(event->synthesized,
false);
762 [[events lastObject] respond:TRUE];
764 [events removeAllObjects];
767 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20104, @"", @"", FALSE, kKeyCodeShiftLeft)
771 EXPECT_EQ([events count], 1u);
772 event = [events lastObject].data;
773 ASSERT_NE(event,
nullptr);
774 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
775 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
776 EXPECT_EQ(event->logical, kLogicalShiftLeft);
777 EXPECT_STREQ(event->character,
nullptr);
778 EXPECT_EQ(event->synthesized,
false);
779 [[events lastObject] respond:TRUE];
781 [events removeAllObjects];
784 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftRight)
788 EXPECT_EQ([events count], 1u);
789 event = [events lastObject].data;
790 ASSERT_NE(event,
nullptr);
791 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
792 EXPECT_EQ(event->physical, kPhysicalShiftRight);
793 EXPECT_EQ(event->logical, kLogicalShiftRight);
794 EXPECT_STREQ(event->character,
nullptr);
795 EXPECT_EQ(event->synthesized,
false);
796 [[events lastObject] respond:TRUE];
798 [events removeAllObjects];
806 TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeMissedModifierEvents) {
807 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
808 __block BOOL last_handled = TRUE;
809 id keyEventCallback = ^(BOOL handled) {
810 last_handled = handled;
812 FlutterKeyEvent* event;
815 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
816 void* _Nullable user_data) {
817 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
819 userData:user_data]];
825 last_handled = FALSE;
827 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
830 EXPECT_EQ([events count], 1u);
831 event = [events lastObject].data;
832 ASSERT_NE(event,
nullptr);
833 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
834 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
835 EXPECT_EQ(event->logical, kLogicalShiftLeft);
836 EXPECT_STREQ(event->character,
nullptr);
837 EXPECT_EQ(event->synthesized,
false);
839 EXPECT_EQ(last_handled, FALSE);
841 [[events lastObject] respond:TRUE];
842 EXPECT_EQ(last_handled, TRUE);
844 [events removeAllObjects];
846 last_handled = FALSE;
848 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
851 EXPECT_EQ([events count], 1u);
852 event = [events lastObject].data;
853 ASSERT_NE(event,
nullptr);
854 EXPECT_EQ(event->physical, 0u);
855 EXPECT_EQ(event->logical, 0u);
857 EXPECT_EQ(last_handled, TRUE);
858 [events removeAllObjects];
860 last_handled = FALSE;
862 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftLeft)
865 EXPECT_EQ([events count], 1u);
866 event = [events lastObject].data;
867 ASSERT_NE(event,
nullptr);
868 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
869 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
870 EXPECT_EQ(event->logical, kLogicalShiftLeft);
871 EXPECT_STREQ(event->character,
nullptr);
872 EXPECT_EQ(event->synthesized,
false);
874 EXPECT_EQ(last_handled, FALSE);
876 [[events lastObject] respond:TRUE];
877 EXPECT_EQ(last_handled, TRUE);
879 [events removeAllObjects];
885 last_handled = FALSE;
887 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftLeft)
890 EXPECT_EQ([events count], 1u);
891 event = [events lastObject].data;
892 ASSERT_NE(event,
nullptr);
893 EXPECT_EQ(event->physical, 0u);
894 EXPECT_EQ(event->logical, 0u);
896 EXPECT_EQ(last_handled, TRUE);
897 [events removeAllObjects];
903 last_handled = FALSE;
905 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
908 EXPECT_EQ([events count], 1u);
909 event = [events lastObject].data;
910 ASSERT_NE(event,
nullptr);
911 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
912 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
913 EXPECT_EQ(event->logical, kLogicalShiftLeft);
914 EXPECT_STREQ(event->character,
nullptr);
915 EXPECT_EQ(event->synthesized,
false);
917 EXPECT_EQ(last_handled, FALSE);
919 [[events lastObject] respond:TRUE];
920 EXPECT_EQ(last_handled, TRUE);
922 [events removeAllObjects];
924 last_handled = FALSE;
926 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftRight)
929 EXPECT_EQ([events count], 1u);
930 event = [events lastObject].data;
931 ASSERT_NE(event,
nullptr);
932 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
933 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
934 EXPECT_EQ(event->logical, kLogicalShiftLeft);
935 EXPECT_STREQ(event->character,
nullptr);
936 EXPECT_EQ(event->synthesized,
true);
939 EXPECT_EQ(last_handled, TRUE);
942 [events removeAllObjects];
948 last_handled = FALSE;
950 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
953 EXPECT_EQ([events count], 1u);
954 event = [events lastObject].data;
955 ASSERT_NE(event,
nullptr);
956 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
957 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
958 EXPECT_EQ(event->logical, kLogicalShiftLeft);
959 EXPECT_STREQ(event->character,
nullptr);
960 EXPECT_EQ(event->synthesized,
false);
962 EXPECT_EQ(last_handled, FALSE);
964 [[events lastObject] respond:TRUE];
965 EXPECT_EQ(last_handled, TRUE);
967 [events removeAllObjects];
969 last_handled = FALSE;
971 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20106, @"", @"", FALSE, kKeyCodeShiftRight)
974 EXPECT_EQ([events count], 1u);
975 event = [events lastObject].data;
976 ASSERT_NE(event,
nullptr);
977 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
978 EXPECT_EQ(event->physical, kPhysicalShiftRight);
979 EXPECT_EQ(event->logical, kLogicalShiftRight);
980 EXPECT_STREQ(event->character,
nullptr);
981 EXPECT_EQ(event->synthesized,
false);
983 EXPECT_EQ(last_handled, FALSE);
985 [[events lastObject] respond:TRUE];
986 EXPECT_EQ(last_handled, TRUE);
988 [events removeAllObjects];
990 last_handled = FALSE;
992 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftRight)
995 EXPECT_EQ([events count], 2u);
996 event = [events firstObject].data;
997 ASSERT_NE(event,
nullptr);
998 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
999 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
1000 EXPECT_EQ(event->logical, kLogicalShiftLeft);
1001 EXPECT_STREQ(event->character,
nullptr);
1002 EXPECT_EQ(event->synthesized,
true);
1006 event = [events lastObject].data;
1007 ASSERT_NE(event,
nullptr);
1008 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1009 EXPECT_EQ(event->physical, kPhysicalShiftRight);
1010 EXPECT_EQ(event->logical, kLogicalShiftRight);
1011 EXPECT_STREQ(event->character,
nullptr);
1012 EXPECT_EQ(event->synthesized,
false);
1014 EXPECT_EQ(last_handled, FALSE);
1016 [[events lastObject] respond:TRUE];
1017 EXPECT_EQ(last_handled, TRUE);
1019 [events removeAllObjects];
1022 TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeMissedModifierEventsInNormalEvents) {
1023 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1024 __block BOOL last_handled = TRUE;
1025 id keyEventCallback = ^(BOOL handled) {
1026 last_handled = handled;
1028 FlutterKeyEvent* event;
1031 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
1032 void* _Nullable user_data) {
1033 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
1035 userData:user_data]];
1041 last_handled = FALSE;
1042 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x20102, @"A", @"A", FALSE, kKeyCodeKeyA)
1045 EXPECT_EQ([events count], 2u);
1046 event = [events firstObject].data;
1047 ASSERT_NE(event,
nullptr);
1048 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1049 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
1050 EXPECT_EQ(event->logical, kLogicalShiftLeft);
1051 EXPECT_STREQ(event->character,
nullptr);
1052 EXPECT_EQ(event->synthesized,
true);
1055 event = [events lastObject].data;
1056 ASSERT_NE(event,
nullptr);
1057 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1058 EXPECT_EQ(event->physical, kPhysicalKeyA);
1059 EXPECT_EQ(event->logical, kLogicalKeyA);
1060 EXPECT_STREQ(event->character,
"A");
1061 EXPECT_EQ(event->synthesized,
false);
1064 EXPECT_EQ(last_handled, FALSE);
1065 [[events lastObject] respond:TRUE];
1066 EXPECT_EQ(last_handled, TRUE);
1068 [events removeAllObjects];
1070 last_handled = FALSE;
1071 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
1074 EXPECT_EQ([events count], 2u);
1075 event = [events firstObject].data;
1076 ASSERT_NE(event,
nullptr);
1077 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1078 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
1079 EXPECT_EQ(event->logical, kLogicalShiftLeft);
1080 EXPECT_STREQ(event->character,
nullptr);
1081 EXPECT_EQ(event->synthesized,
true);
1084 event = [events lastObject].data;
1085 ASSERT_NE(event,
nullptr);
1086 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1087 EXPECT_EQ(event->physical, kPhysicalKeyA);
1088 EXPECT_EQ(event->logical, kLogicalKeyA);
1089 EXPECT_STREQ(event->character,
nullptr);
1090 EXPECT_EQ(event->synthesized,
false);
1093 EXPECT_EQ(last_handled, FALSE);
1094 [[events lastObject] respond:TRUE];
1095 EXPECT_EQ(last_handled, TRUE);
1097 [events removeAllObjects];
1100 TEST(FlutterEmbedderKeyResponderUnittests, ConvertCapsLockEvents) {
1101 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1102 __block BOOL last_handled = TRUE;
1103 id keyEventCallback = ^(BOOL handled) {
1104 last_handled = handled;
1106 FlutterKeyEvent* event;
1109 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
1110 void* _Nullable user_data) {
1111 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
1113 userData:user_data]];
1118 last_handled = FALSE;
1120 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x10100, @"", @"", FALSE, kKeyCodeCapsLock)
1123 EXPECT_EQ([events count], 2u);
1125 event = [events firstObject].data;
1126 ASSERT_NE(event,
nullptr);
1127 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1128 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1129 EXPECT_EQ(event->logical, kLogicalCapsLock);
1130 EXPECT_STREQ(event->character,
nullptr);
1131 EXPECT_EQ(event->synthesized,
false);
1134 event = [events lastObject].data;
1135 ASSERT_NE(event,
nullptr);
1136 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1137 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1138 EXPECT_EQ(event->logical, kLogicalCapsLock);
1139 EXPECT_STREQ(event->character,
nullptr);
1140 EXPECT_EQ(event->synthesized,
true);
1143 EXPECT_EQ(last_handled, FALSE);
1144 [[events firstObject] respond:TRUE];
1145 EXPECT_EQ(last_handled, TRUE);
1147 [events removeAllObjects];
1151 last_handled = FALSE;
1152 [responder
handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeCapsLock)
1155 EXPECT_EQ([events count], 2u);
1157 event = [events firstObject].data;
1158 ASSERT_NE(event,
nullptr);
1159 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1160 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1161 EXPECT_EQ(event->logical, kLogicalCapsLock);
1162 EXPECT_STREQ(event->character,
nullptr);
1163 EXPECT_EQ(event->synthesized,
false);
1166 event = [events lastObject].data;
1167 ASSERT_NE(event,
nullptr);
1168 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1169 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1170 EXPECT_EQ(event->logical, kLogicalCapsLock);
1171 EXPECT_STREQ(event->character,
nullptr);
1172 EXPECT_EQ(event->synthesized,
true);
1175 EXPECT_EQ(last_handled, FALSE);
1176 [[events firstObject] respond:TRUE];
1177 EXPECT_EQ(last_handled, TRUE);
1179 [events removeAllObjects];
1183 TEST(FlutterEmbedderKeyResponderUnittests, SynchronizeCapsLockStateOnCapsLock) {
1184 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1185 FlutterKeyEvent* event;
1186 __block BOOL last_handled = TRUE;
1187 id keyEventCallback = ^(BOOL handled) {
1188 last_handled = handled;
1192 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
1193 void* _Nullable user_data) {
1194 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
1196 userData:user_data]];
1201 last_handled = FALSE;
1202 [responder
handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeCapsLock)
1205 EXPECT_EQ([events count], 1u);
1206 EXPECT_EQ(last_handled, TRUE);
1207 event = [events lastObject].data;
1208 ASSERT_NE(event,
nullptr);
1209 EXPECT_EQ(event->physical, 0ull);
1210 EXPECT_EQ(event->logical, 0ull);
1212 EXPECT_EQ(last_handled, TRUE);
1214 [events removeAllObjects];
1218 TEST(FlutterEmbedderKeyResponderUnittests, SynchronizeCapsLockStateOnNormalKey) {
1219 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1220 __block BOOL last_handled = TRUE;
1221 id keyEventCallback = ^(BOOL handled) {
1222 last_handled = handled;
1224 FlutterKeyEvent* event;
1227 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
1228 void* _Nullable user_data) {
1229 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
1231 userData:user_data]];
1234 last_handled = FALSE;
1235 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x10100, @"A", @"a", FALSE, kKeyCodeKeyA)
1238 EXPECT_EQ([events count], 3u);
1240 event = events[0].data;
1241 ASSERT_NE(event,
nullptr);
1242 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1243 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1244 EXPECT_EQ(event->logical, kLogicalCapsLock);
1245 EXPECT_STREQ(event->character,
nullptr);
1246 EXPECT_EQ(event->synthesized,
true);
1249 event = events[1].data;
1250 ASSERT_NE(event,
nullptr);
1251 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1252 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1253 EXPECT_EQ(event->logical, kLogicalCapsLock);
1254 EXPECT_STREQ(event->character,
nullptr);
1255 EXPECT_EQ(event->synthesized,
true);
1258 event = events[2].data;
1259 ASSERT_NE(event,
nullptr);
1260 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1261 EXPECT_EQ(event->physical, kPhysicalKeyA);
1262 EXPECT_EQ(event->logical, kLogicalKeyA);
1263 EXPECT_STREQ(event->character,
"A");
1264 EXPECT_EQ(event->synthesized,
false);
1267 EXPECT_EQ(last_handled, FALSE);
1268 [[events lastObject] respond:TRUE];
1269 EXPECT_EQ(last_handled, TRUE);
1271 [events removeAllObjects];