5#import <Foundation/Foundation.h>
7#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderKeyResponder.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"
19 userData:(nullable
void*)userData;
21- (void)respond:(
BOOL)handled;
27 userData:(nullable
void*)userData {
30 if (
event->character !=
nullptr) {
31 size_t len = strlen(
event->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;
63constexpr uint64_t kKeyCodeKeyA = 0x00;
64constexpr uint64_t kKeyCodeKeyW = 0x0d;
66constexpr uint64_t kKeyCodeShiftRight = 0x3c;
67constexpr uint64_t kKeyCodeCapsLock = 0x39;
68constexpr uint64_t kKeyCodeNumpad1 = 0x53;
69constexpr uint64_t kKeyCodeF1 = 0x7a;
70constexpr uint64_t kKeyCodeAltRight = 0x3d;
74typedef void (^ResponseCallback)(
bool handled);
76NSEvent* keyEvent(NSEventType
type,
77 NSEventModifierFlags modifierFlags,
79 NSString* charactersIgnoringModifiers,
81 unsigned short keyCode) {
82 return [NSEvent keyEventWithType:type
84 modifierFlags:modifierFlags
89 charactersIgnoringModifiers:charactersIgnoringModifiers
94NSEvent* 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
118TEST(FlutterEmbedderKeyResponderUnittests, BasicKeyEvent) {
119 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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);
141 EXPECT_EQ(
event->timestamp, 123000000.0f);
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);
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);
186 EXPECT_EQ(
event->timestamp, 124000000.0f);
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];
200TEST(FlutterEmbedderKeyResponderUnittests, NonAsciiCharacters) {
201 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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);
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);
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);
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);
268 EXPECT_STREQ(
event->character,
nullptr);
269 EXPECT_EQ(
event->synthesized,
false);
271 [events removeAllObjects];
274TEST(FlutterEmbedderKeyResponderUnittests, MultipleCharacters) {
275 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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);
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);
310 EXPECT_EQ(
event->logical, 0x1400000000ull);
311 EXPECT_STREQ(
event->character,
nullptr);
312 EXPECT_EQ(
event->synthesized,
false);
314 [events removeAllObjects];
317TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeForDuplicateDownEvent) {
318 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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);
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);
363 EXPECT_STREQ(
event->character, NULL);
364 EXPECT_EQ(
event->synthesized,
true);
366 event = [events lastObject].data;
367 ASSERT_NE(
event,
nullptr);
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];
379TEST(FlutterEmbedderKeyResponderUnittests, IgnoreDuplicateUpEvent) {
380 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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];
410TEST(FlutterEmbedderKeyResponderUnittests, ConvertAbruptRepeatEventsToDown) {
411 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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);
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];
448TEST(FlutterEmbedderKeyResponderUnittests, ToggleModifiersDuringKeyTap) {
449 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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);
469 EXPECT_EQ(
event->timestamp, 123000000.0f);
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);
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);
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);
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);
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);
552 EXPECT_STREQ(
event->character,
nullptr);
553 EXPECT_EQ(
event->synthesized,
false);
554 [[events lastObject] respond:TRUE];
556 [events removeAllObjects];
564TEST(FlutterEmbedderKeyResponderUnittests, SpecialModiferFlags) {
565 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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);
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);
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);
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);
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);
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);
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);
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);
713 EXPECT_STREQ(
event->character,
nullptr);
714 EXPECT_EQ(
event->synthesized,
false);
715 [[events lastObject] respond:TRUE];
717 [events removeAllObjects];
720TEST(FlutterEmbedderKeyResponderUnittests, IdentifyLeftAndRightModifiers) {
721 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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);
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);
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);
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);
794 EXPECT_STREQ(
event->character,
nullptr);
795 EXPECT_EQ(
event->synthesized,
false);
796 [[events lastObject] respond:TRUE];
798 [events removeAllObjects];
806TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeMissedModifierEvents) {
807 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
809 id keyEventCallback = ^(
BOOL handled) {
810 last_handled = handled;
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);
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);
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);
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);
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);
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);
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);
1001 EXPECT_STREQ(
event->character,
nullptr);
1002 EXPECT_EQ(
event->synthesized,
true);
1006 event = [events lastObject].data;
1007 ASSERT_NE(
event,
nullptr);
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];
1022TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeMissedModifierEventsInNormalEvents) {
1023 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1025 id keyEventCallback = ^(
BOOL handled) {
1026 last_handled = handled;
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);
1051 EXPECT_STREQ(
event->character,
nullptr);
1052 EXPECT_EQ(
event->synthesized,
true);
1055 event = [events lastObject].data;
1056 ASSERT_NE(
event,
nullptr);
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);
1080 EXPECT_STREQ(
event->character,
nullptr);
1081 EXPECT_EQ(
event->synthesized,
true);
1084 event = [events lastObject].data;
1085 ASSERT_NE(
event,
nullptr);
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];
1100TEST(FlutterEmbedderKeyResponderUnittests, ConvertCapsLockEvents) {
1101 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1103 id keyEventCallback = ^(
BOOL handled) {
1104 last_handled = handled;
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);
1130 EXPECT_STREQ(
event->character,
nullptr);
1131 EXPECT_EQ(
event->synthesized,
false);
1134 event = [events lastObject].data;
1135 ASSERT_NE(
event,
nullptr);
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);
1162 EXPECT_STREQ(
event->character,
nullptr);
1163 EXPECT_EQ(
event->synthesized,
false);
1166 event = [events lastObject].data;
1167 ASSERT_NE(
event,
nullptr);
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];
1183TEST(FlutterEmbedderKeyResponderUnittests, SynchronizeCapsLockStateOnCapsLock) {
1184 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
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];
1218TEST(FlutterEmbedderKeyResponderUnittests, SynchronizeCapsLockStateOnNormalKey) {
1219 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1221 id keyEventCallback = ^(
BOOL handled) {
1222 last_handled = handled;
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);
1245 EXPECT_STREQ(
event->character,
nullptr);
1246 EXPECT_EQ(
event->synthesized,
true);
1249 event = events[1].data;
1250 ASSERT_NE(
event,
nullptr);
1254 EXPECT_STREQ(
event->character,
nullptr);
1255 EXPECT_EQ(
event->synthesized,
true);
1258 event = events[2].data;
1259 ASSERT_NE(
event,
nullptr);
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];
void(* FlutterKeyEventCallback)(bool, void *)
@ kFlutterKeyEventTypeDown
@ kFlutterKeyEventTypeRepeat
void handleEvent:callback:(NSEvent *event, [callback] FlutterAsyncKeyCallback callback)
FlutterKeyEventCallback callback
constexpr uint64_t kPhysicalAltRight
constexpr uint64_t kPhysicalKeyW
constexpr uint64_t kLogicalF1
constexpr uint64_t kLogicalShiftRight
constexpr uint64_t kLogicalNumpad1
constexpr uint64_t kPhysicalShiftLeft
constexpr uint64_t kPhysicalKeyA
constexpr uint64_t kPhysicalCapsLock
constexpr uint64_t kLogicalKeyW
constexpr uint64_t kLogicalKeyA
constexpr uint64_t kLogicalAltRight
constexpr uint64_t kPhysicalF1
constexpr uint64_t kPhysicalNumpad1
constexpr uint64_t kLogicalCapsLock
constexpr uint64_t kLogicalShiftLeft
constexpr uint64_t kPhysicalShiftRight
TEST(FlutterEmbedderKeyResponderUnittests, SynchronizeCapsLockStateOnNormalKey)
constexpr int kKeyCodeShiftLeft
#define EXPECT_TRUE(handle)