5 #import <Foundation/Foundation.h>
6 #import <OCMock/OCMock.h>
9 #include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
10 #import "flutter/testing/testing.h"
11 #include "third_party/googletest/googletest/include/gtest/gtest.h"
15 @property(nonatomic) FlutterKeyEvent*
data;
16 @property(nonatomic) FlutterKeyEventCallback
callback;
18 - (nonnull instancetype)initWithEvent:(const FlutterKeyEvent*)event
19 callback:(nullable FlutterKeyEventCallback)callback
20 userData:(nullable _VoidPtr)userData;
22 - (void)respond:(BOOL)handled;
26 - (instancetype)initWithEvent:(const FlutterKeyEvent*)event
27 callback:(nullable FlutterKeyEventCallback)callback
28 userData:(nullable _VoidPtr)userData {
30 _data =
new FlutterKeyEvent(*event);
31 if (event->character !=
nullptr) {
32 size_t len = strlen(event->character);
33 char* character =
new char[len + 1];
34 strlcpy(character, event->character,
sizeof(character));
35 _data->character = character;
43 return _callback != nil;
46 - (void)respond:(BOOL)handled {
49 @"Improper call to `respond` that does not have a callback.");
50 _callback(handled, _userData);
54 if (_data->character !=
nullptr) {
55 delete[] _data->character;
64 constexpr uint64_t kKeyCodeKeyA = 0x00;
65 constexpr uint64_t kKeyCodeKeyW = 0x0d;
66 constexpr uint64_t kKeyCodeShiftLeft = 0x38;
67 constexpr uint64_t kKeyCodeShiftRight = 0x3c;
68 constexpr uint64_t kKeyCodeCapsLock = 0x39;
69 constexpr uint64_t kKeyCodeNumpad1 = 0x53;
70 constexpr uint64_t kKeyCodeF1 = 0x7a;
71 constexpr uint64_t kKeyCodeAltRight = 0x3d;
73 using namespace ::flutter::testing::keycodes;
75 typedef void (^ResponseCallback)(
bool handled);
77 NSEvent* keyEvent(NSEventType type,
78 NSEventModifierFlags modifierFlags,
80 NSString* charactersIgnoringModifiers,
82 unsigned short keyCode) {
83 return [NSEvent keyEventWithType:type
85 modifierFlags:modifierFlags
90 charactersIgnoringModifiers:charactersIgnoringModifiers
95 NSEvent* keyEvent(NSEventType type,
96 NSTimeInterval timestamp,
97 NSEventModifierFlags modifierFlags,
99 NSString* charactersIgnoringModifiers,
101 unsigned short keyCode) {
102 return [NSEvent keyEventWithType:type
104 modifierFlags:modifierFlags
108 characters:characters
109 charactersIgnoringModifiers:charactersIgnoringModifiers
119 TEST(FlutterEmbedderKeyResponderUnittests, BasicKeyEvent) {
120 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
121 __block BOOL last_handled = TRUE;
122 FlutterKeyEvent* event;
125 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
126 _Nullable _VoidPtr user_data) {
127 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
129 userData:user_data]];
132 last_handled = FALSE;
133 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 123.0f, 0x100, @"a", @"a", FALSE, 0)
135 last_handled = handled;
138 EXPECT_EQ([events count], 1u);
139 event = [events lastObject].data;
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 EXPECT_EQ(event->type, kFlutterKeyEventTypeRepeat);
163 EXPECT_EQ(event->physical, kPhysicalKeyA);
164 EXPECT_EQ(event->logical, kLogicalKeyA);
165 EXPECT_STREQ(event->character,
"a");
166 EXPECT_EQ(event->synthesized,
false);
168 EXPECT_EQ(last_handled, FALSE);
170 [[events lastObject] respond:TRUE];
171 EXPECT_EQ(last_handled, TRUE);
173 [events removeAllObjects];
176 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 124.0f, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
178 last_handled = handled;
181 EXPECT_EQ([events count], 1u);
182 event = [events lastObject].data;
183 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
184 EXPECT_EQ(event->timestamp, 124000000.0f);
185 EXPECT_EQ(event->physical, kPhysicalKeyA);
186 EXPECT_EQ(event->logical, kLogicalKeyA);
187 EXPECT_EQ(event->character,
nullptr);
188 EXPECT_EQ(event->synthesized,
false);
190 EXPECT_EQ(last_handled, TRUE);
192 [[events lastObject] respond:FALSE];
193 EXPECT_EQ(last_handled, FALSE);
195 [events removeAllObjects];
198 TEST(FlutterEmbedderKeyResponderUnittests, NonAsciiCharacters) {
199 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
200 FlutterKeyEvent* event;
203 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
204 _Nullable _VoidPtr user_data) {
205 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
207 userData:user_data]];
211 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x80140, @"", @"", FALSE, kKeyCodeAltRight)
215 EXPECT_EQ([events count], 1u);
216 event = [events lastObject].data;
217 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
218 EXPECT_EQ(event->physical, kPhysicalAltRight);
219 EXPECT_EQ(event->logical, kLogicalAltRight);
220 EXPECT_STREQ(event->character,
nullptr);
221 EXPECT_EQ(event->synthesized,
false);
223 [events removeAllObjects];
225 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x80140, @"â ˆ‘", @"w", FALSE, kKeyCodeKeyW)
229 EXPECT_EQ([events count], 1u);
230 event = [events lastObject].data;
231 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
232 EXPECT_EQ(event->physical, kPhysicalKeyW);
233 EXPECT_EQ(event->logical, kLogicalKeyW);
234 EXPECT_STREQ(event->character,
"∑");
235 EXPECT_EQ(event->synthesized,
false);
237 [events removeAllObjects];
239 [responder
handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeAltRight)
243 EXPECT_EQ([events count], 1u);
244 event = [events lastObject].data;
245 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
246 EXPECT_EQ(event->physical, kPhysicalAltRight);
247 EXPECT_EQ(event->logical, kLogicalAltRight);
248 EXPECT_STREQ(event->character,
nullptr);
249 EXPECT_EQ(event->synthesized,
false);
251 [events removeAllObjects];
253 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x100, @"w", @"w", FALSE, kKeyCodeKeyW)
257 EXPECT_EQ([events count], 1u);
258 event = [events lastObject].data;
259 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
260 EXPECT_EQ(event->physical, kPhysicalKeyW);
261 EXPECT_EQ(event->logical, kLogicalKeyW);
262 EXPECT_STREQ(event->character,
nullptr);
263 EXPECT_EQ(event->synthesized,
false);
265 [events removeAllObjects];
268 TEST(FlutterEmbedderKeyResponderUnittests, MultipleCharacters) {
269 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
270 FlutterKeyEvent* event;
273 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
274 _Nullable _VoidPtr user_data) {
275 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
277 userData:user_data]];
280 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0, @"Ã n", @"Ã n", FALSE, kKeyCodeKeyA)
284 EXPECT_EQ([events count], 1u);
285 event = [events lastObject].data;
286 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
287 EXPECT_EQ(event->physical, kPhysicalKeyA);
288 EXPECT_EQ(event->logical, 0x1400000000ull);
289 EXPECT_STREQ(event->character,
"Ã n");
290 EXPECT_EQ(event->synthesized,
false);
292 [events removeAllObjects];
294 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0, @"a", @"a", FALSE, kKeyCodeKeyA)
298 EXPECT_EQ([events count], 1u);
299 event = [events lastObject].data;
300 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
301 EXPECT_EQ(event->physical, kPhysicalKeyA);
302 EXPECT_EQ(event->logical, 0x1400000000ull);
303 EXPECT_STREQ(event->character,
nullptr);
304 EXPECT_EQ(event->synthesized,
false);
306 [events removeAllObjects];
309 TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeForDuplicateDownEvent) {
310 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
311 __block BOOL last_handled = TRUE;
312 FlutterKeyEvent* event;
315 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
316 _Nullable _VoidPtr user_data) {
317 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
319 userData:user_data]];
323 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
325 last_handled = handled;
328 EXPECT_EQ([events count], 1u);
329 event = [events lastObject].data;
330 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
331 EXPECT_EQ(event->physical, kPhysicalKeyA);
332 EXPECT_EQ(event->logical, kLogicalKeyA);
333 EXPECT_STREQ(event->character,
"a");
334 EXPECT_EQ(event->synthesized,
false);
335 EXPECT_EQ(last_handled, TRUE);
336 [[events lastObject] respond:FALSE];
337 EXPECT_EQ(last_handled, FALSE);
339 [events removeAllObjects];
342 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"Ã ", @"Ã ", FALSE, kKeyCodeKeyA)
344 last_handled = handled;
347 EXPECT_EQ([events count], 2u);
349 event = [events firstObject].data;
350 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
351 EXPECT_EQ(event->physical, kPhysicalKeyA);
352 EXPECT_EQ(event->logical, kLogicalKeyA);
353 EXPECT_STREQ(event->character, NULL);
354 EXPECT_EQ(event->synthesized,
true);
356 event = [events lastObject].data;
357 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
358 EXPECT_EQ(event->physical, kPhysicalKeyA);
359 EXPECT_EQ(event->logical, 0xE0ull );
360 EXPECT_STREQ(event->character,
"Ã ");
361 EXPECT_EQ(event->synthesized,
false);
362 [[events lastObject] respond:FALSE];
363 EXPECT_EQ(last_handled, FALSE);
365 [events removeAllObjects];
368 TEST(FlutterEmbedderKeyResponderUnittests, IgnoreDuplicateUpEvent) {
369 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
370 FlutterKeyEvent* event;
371 __block BOOL last_handled = TRUE;
374 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
375 _Nullable _VoidPtr user_data) {
376 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
378 userData:user_data]];
381 last_handled = FALSE;
382 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
384 last_handled = handled;
387 EXPECT_EQ([events count], 1u);
388 EXPECT_EQ(last_handled, TRUE);
389 event = [events lastObject].data;
390 EXPECT_EQ(event->physical, 0ull);
391 EXPECT_EQ(event->logical, 0ull);
393 EXPECT_EQ(last_handled, TRUE);
395 [events removeAllObjects];
398 TEST(FlutterEmbedderKeyResponderUnittests, ConvertAbruptRepeatEventsToDown) {
399 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
400 __block BOOL last_handled = TRUE;
401 FlutterKeyEvent* event;
404 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
405 _Nullable _VoidPtr user_data) {
406 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
408 userData:user_data]];
412 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", TRUE, kKeyCodeKeyA)
414 last_handled = handled;
417 EXPECT_EQ([events count], 1u);
418 event = [events lastObject].data;
419 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
420 EXPECT_EQ(event->physical, kPhysicalKeyA);
421 EXPECT_EQ(event->logical, kLogicalKeyA);
422 EXPECT_STREQ(event->character,
"a");
423 EXPECT_EQ(event->synthesized,
false);
424 EXPECT_EQ(last_handled, TRUE);
425 [[events lastObject] respond:FALSE];
426 EXPECT_EQ(last_handled, FALSE);
428 [events removeAllObjects];
435 TEST(FlutterEmbedderKeyResponderUnittests, ToggleModifiersDuringKeyTap) {
436 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
437 FlutterKeyEvent* event;
440 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
441 _Nullable _VoidPtr user_data) {
442 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
444 userData:user_data]];
447 [responder
handleEvent:keyEvent(NSEventTypeFlagsChanged, 123.0f, 0x20104, @"", @"", FALSE,
452 EXPECT_EQ([events count], 1u);
453 event = [events lastObject].data;
454 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
455 EXPECT_EQ(event->timestamp, 123000000.0f);
456 EXPECT_EQ(event->physical, kPhysicalShiftRight);
457 EXPECT_EQ(event->logical, kLogicalShiftRight);
458 EXPECT_STREQ(event->character,
nullptr);
459 EXPECT_EQ(event->synthesized,
false);
460 [[events lastObject] respond:TRUE];
462 [events removeAllObjects];
464 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x20104, @"A", @"A", FALSE, kKeyCodeKeyA)
468 EXPECT_EQ([events count], 1u);
469 event = [events lastObject].data;
470 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
471 EXPECT_EQ(event->physical, kPhysicalKeyA);
472 EXPECT_EQ(event->logical, kLogicalKeyA);
473 EXPECT_STREQ(event->character,
"A");
474 EXPECT_EQ(event->synthesized,
false);
475 [[events lastObject] respond:TRUE];
477 [events removeAllObjects];
479 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x20104, @"A", @"A", TRUE, kKeyCodeKeyA)
483 EXPECT_EQ([events count], 1u);
484 event = [events lastObject].data;
485 EXPECT_EQ(event->type, kFlutterKeyEventTypeRepeat);
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];
495 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftRight)
499 EXPECT_EQ([events count], 1u);
500 event = [events lastObject].data;
501 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
502 EXPECT_EQ(event->physical, kPhysicalShiftRight);
503 EXPECT_EQ(event->logical, kLogicalShiftRight);
504 EXPECT_STREQ(event->character,
nullptr);
505 EXPECT_EQ(event->synthesized,
false);
506 [[events lastObject] respond:TRUE];
508 [events removeAllObjects];
510 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", TRUE, kKeyCodeKeyA)
514 EXPECT_EQ([events count], 1u);
515 event = [events lastObject].data;
516 EXPECT_EQ(event->type, kFlutterKeyEventTypeRepeat);
517 EXPECT_EQ(event->physical, kPhysicalKeyA);
518 EXPECT_EQ(event->logical, kLogicalKeyA);
519 EXPECT_STREQ(event->character,
"a");
520 EXPECT_EQ(event->synthesized,
false);
522 [events removeAllObjects];
524 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
528 EXPECT_EQ([events count], 1u);
529 event = [events lastObject].data;
530 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
531 EXPECT_EQ(event->physical, kPhysicalKeyA);
532 EXPECT_EQ(event->logical, kLogicalKeyA);
533 EXPECT_STREQ(event->character,
nullptr);
534 EXPECT_EQ(event->synthesized,
false);
535 [[events lastObject] respond:TRUE];
537 [events removeAllObjects];
545 TEST(FlutterEmbedderKeyResponderUnittests, SpecialModiferFlags) {
546 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
547 FlutterKeyEvent* event;
550 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
551 _Nullable _VoidPtr user_data) {
552 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
554 userData:user_data]];
561 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x200100, @"1", @"1", FALSE, kKeyCodeNumpad1)
565 EXPECT_EQ([events count], 1u);
566 event = [events lastObject].data;
567 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
568 EXPECT_EQ(event->physical, kPhysicalNumpad1);
569 EXPECT_EQ(event->logical, kLogicalNumpad1);
570 EXPECT_STREQ(event->character,
"1");
571 EXPECT_EQ(event->synthesized,
false);
572 [[events lastObject] respond:TRUE];
574 [events removeAllObjects];
578 handleEvent:keyEvent(NSEventTypeKeyDown, 0x800100, @"\uf704", @"\uf704", FALSE, kKeyCodeF1)
582 EXPECT_EQ([events count], 1u);
583 event = [events lastObject].data;
584 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
585 EXPECT_EQ(event->physical, kPhysicalF1);
586 EXPECT_EQ(event->logical, kLogicalF1);
587 EXPECT_STREQ(event->character,
nullptr);
588 EXPECT_EQ(event->synthesized,
false);
589 [[events lastObject] respond:TRUE];
591 [events removeAllObjects];
594 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
598 EXPECT_EQ([events count], 1u);
599 event = [events lastObject].data;
600 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
601 EXPECT_EQ(event->physical, kPhysicalKeyA);
602 EXPECT_EQ(event->logical, kLogicalKeyA);
603 EXPECT_STREQ(event->character,
"a");
604 EXPECT_EQ(event->synthesized,
false);
605 [[events lastObject] respond:TRUE];
607 [events removeAllObjects];
611 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
615 EXPECT_EQ([events count], 1u);
616 event = [events lastObject].data;
617 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
618 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
619 EXPECT_EQ(event->logical, kLogicalShiftLeft);
620 EXPECT_STREQ(event->character,
nullptr);
621 EXPECT_EQ(event->synthesized,
false);
622 [[events lastObject] respond:TRUE];
624 [events removeAllObjects];
627 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x220102, @"1", @"1", FALSE, kKeyCodeNumpad1)
631 EXPECT_EQ([events count], 1u);
632 event = [events lastObject].data;
633 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
634 EXPECT_EQ(event->physical, kPhysicalNumpad1);
635 EXPECT_EQ(event->logical, kLogicalNumpad1);
636 EXPECT_STREQ(event->character,
nullptr);
637 EXPECT_EQ(event->synthesized,
false);
638 [[events lastObject] respond:TRUE];
640 [events removeAllObjects];
644 handleEvent:keyEvent(NSEventTypeKeyUp, 0x820102, @"\uF704", @"\uF704", FALSE, kKeyCodeF1)
648 EXPECT_EQ([events count], 1u);
649 event = [events lastObject].data;
650 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
651 EXPECT_EQ(event->physical, kPhysicalF1);
652 EXPECT_EQ(event->logical, kLogicalF1);
653 EXPECT_STREQ(event->character,
nullptr);
654 EXPECT_EQ(event->synthesized,
false);
655 [[events lastObject] respond:TRUE];
657 [events removeAllObjects];
660 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x20102, @"a", @"a", FALSE, kKeyCodeKeyA)
664 EXPECT_EQ([events count], 1u);
665 event = [events lastObject].data;
666 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
667 EXPECT_EQ(event->physical, kPhysicalKeyA);
668 EXPECT_EQ(event->logical, kLogicalKeyA);
669 EXPECT_STREQ(event->character,
nullptr);
670 EXPECT_EQ(event->synthesized,
false);
671 [[events lastObject] respond:TRUE];
673 [events removeAllObjects];
677 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftLeft)
681 EXPECT_EQ([events count], 1u);
682 event = [events lastObject].data;
683 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
684 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
685 EXPECT_EQ(event->logical, kLogicalShiftLeft);
686 EXPECT_STREQ(event->character,
nullptr);
687 EXPECT_EQ(event->synthesized,
false);
688 [[events lastObject] respond:TRUE];
690 [events removeAllObjects];
693 TEST(FlutterEmbedderKeyResponderUnittests, IdentifyLeftAndRightModifiers) {
694 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
695 FlutterKeyEvent* event;
698 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
699 _Nullable _VoidPtr user_data) {
700 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
702 userData:user_data]];
706 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
710 EXPECT_EQ([events count], 1u);
711 event = [events lastObject].data;
712 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
713 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
714 EXPECT_EQ(event->logical, kLogicalShiftLeft);
715 EXPECT_STREQ(event->character,
nullptr);
716 EXPECT_EQ(event->synthesized,
false);
717 [[events lastObject] respond:TRUE];
719 [events removeAllObjects];
722 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20106, @"", @"", FALSE, kKeyCodeShiftRight)
726 EXPECT_EQ([events count], 1u);
727 event = [events lastObject].data;
728 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
729 EXPECT_EQ(event->physical, kPhysicalShiftRight);
730 EXPECT_EQ(event->logical, kLogicalShiftRight);
731 EXPECT_STREQ(event->character,
nullptr);
732 EXPECT_EQ(event->synthesized,
false);
733 [[events lastObject] respond:TRUE];
735 [events removeAllObjects];
738 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20104, @"", @"", FALSE, kKeyCodeShiftLeft)
742 EXPECT_EQ([events count], 1u);
743 event = [events lastObject].data;
744 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
745 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
746 EXPECT_EQ(event->logical, kLogicalShiftLeft);
747 EXPECT_STREQ(event->character,
nullptr);
748 EXPECT_EQ(event->synthesized,
false);
749 [[events lastObject] respond:TRUE];
751 [events removeAllObjects];
754 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftRight)
758 EXPECT_EQ([events count], 1u);
759 event = [events lastObject].data;
760 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
761 EXPECT_EQ(event->physical, kPhysicalShiftRight);
762 EXPECT_EQ(event->logical, kLogicalShiftRight);
763 EXPECT_STREQ(event->character,
nullptr);
764 EXPECT_EQ(event->synthesized,
false);
765 [[events lastObject] respond:TRUE];
767 [events removeAllObjects];
775 TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeMissedModifierEvents) {
776 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
777 __block BOOL last_handled = TRUE;
778 id keyEventCallback = ^(BOOL handled) {
779 last_handled = handled;
781 FlutterKeyEvent* event;
784 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
785 _Nullable _VoidPtr user_data) {
786 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
788 userData:user_data]];
794 last_handled = FALSE;
796 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
799 EXPECT_EQ([events count], 1u);
800 event = [events lastObject].data;
801 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
802 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
803 EXPECT_EQ(event->logical, kLogicalShiftLeft);
804 EXPECT_STREQ(event->character,
nullptr);
805 EXPECT_EQ(event->synthesized,
false);
807 EXPECT_EQ(last_handled, FALSE);
809 [[events lastObject] respond:TRUE];
810 EXPECT_EQ(last_handled, TRUE);
812 [events removeAllObjects];
814 last_handled = FALSE;
816 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
819 EXPECT_EQ([events count], 1u);
820 EXPECT_EQ([events lastObject].
data->physical, 0u);
821 EXPECT_EQ([events lastObject].
data->logical, 0u);
823 EXPECT_EQ(last_handled, TRUE);
824 [events removeAllObjects];
826 last_handled = FALSE;
828 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftLeft)
831 EXPECT_EQ([events count], 1u);
832 event = [events lastObject].data;
833 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
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];
850 last_handled = FALSE;
852 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftLeft)
855 EXPECT_EQ([events count], 1u);
856 EXPECT_EQ([events lastObject].
data->physical, 0u);
857 EXPECT_EQ([events lastObject].
data->logical, 0u);
859 EXPECT_EQ(last_handled, TRUE);
860 [events removeAllObjects];
866 last_handled = FALSE;
868 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
871 EXPECT_EQ([events count], 1u);
872 event = [events lastObject].data;
873 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
874 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
875 EXPECT_EQ(event->logical, kLogicalShiftLeft);
876 EXPECT_STREQ(event->character,
nullptr);
877 EXPECT_EQ(event->synthesized,
false);
879 EXPECT_EQ(last_handled, FALSE);
881 [[events lastObject] respond:TRUE];
882 EXPECT_EQ(last_handled, TRUE);
884 [events removeAllObjects];
886 last_handled = FALSE;
888 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftRight)
891 EXPECT_EQ([events count], 1u);
892 event = [events lastObject].data;
893 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
894 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
895 EXPECT_EQ(event->logical, kLogicalShiftLeft);
896 EXPECT_STREQ(event->character,
nullptr);
897 EXPECT_EQ(event->synthesized,
true);
900 EXPECT_EQ(last_handled, TRUE);
903 [events removeAllObjects];
909 last_handled = FALSE;
911 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", FALSE, kKeyCodeShiftLeft)
914 EXPECT_EQ([events count], 1u);
915 event = [events lastObject].data;
916 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
917 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
918 EXPECT_EQ(event->logical, kLogicalShiftLeft);
919 EXPECT_STREQ(event->character,
nullptr);
920 EXPECT_EQ(event->synthesized,
false);
922 EXPECT_EQ(last_handled, FALSE);
924 [[events lastObject] respond:TRUE];
925 EXPECT_EQ(last_handled, TRUE);
927 [events removeAllObjects];
929 last_handled = FALSE;
931 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x20106, @"", @"", FALSE, kKeyCodeShiftRight)
934 EXPECT_EQ([events count], 1u);
935 event = [events lastObject].data;
936 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
937 EXPECT_EQ(event->physical, kPhysicalShiftRight);
938 EXPECT_EQ(event->logical, kLogicalShiftRight);
939 EXPECT_STREQ(event->character,
nullptr);
940 EXPECT_EQ(event->synthesized,
false);
942 EXPECT_EQ(last_handled, FALSE);
944 [[events lastObject] respond:TRUE];
945 EXPECT_EQ(last_handled, TRUE);
947 [events removeAllObjects];
949 last_handled = FALSE;
951 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeShiftRight)
954 EXPECT_EQ([events count], 2u);
955 event = [events firstObject].data;
956 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
957 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
958 EXPECT_EQ(event->logical, kLogicalShiftLeft);
959 EXPECT_STREQ(event->character,
nullptr);
960 EXPECT_EQ(event->synthesized,
true);
964 event = [events lastObject].data;
965 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
966 EXPECT_EQ(event->physical, kPhysicalShiftRight);
967 EXPECT_EQ(event->logical, kLogicalShiftRight);
968 EXPECT_STREQ(event->character,
nullptr);
969 EXPECT_EQ(event->synthesized,
false);
971 EXPECT_EQ(last_handled, FALSE);
973 [[events lastObject] respond:TRUE];
974 EXPECT_EQ(last_handled, TRUE);
976 [events removeAllObjects];
979 TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeMissedModifierEventsInNormalEvents) {
980 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
981 __block BOOL last_handled = TRUE;
982 id keyEventCallback = ^(BOOL handled) {
983 last_handled = handled;
985 FlutterKeyEvent* event;
988 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
989 _Nullable _VoidPtr user_data) {
990 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
992 userData:user_data]];
998 last_handled = FALSE;
999 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x20102, @"A", @"A", FALSE, kKeyCodeKeyA)
1002 EXPECT_EQ([events count], 2u);
1003 event = [events firstObject].data;
1004 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1005 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
1006 EXPECT_EQ(event->logical, kLogicalShiftLeft);
1007 EXPECT_STREQ(event->character,
nullptr);
1008 EXPECT_EQ(event->synthesized,
true);
1011 event = [events lastObject].data;
1012 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1013 EXPECT_EQ(event->physical, kPhysicalKeyA);
1014 EXPECT_EQ(event->logical, kLogicalKeyA);
1015 EXPECT_STREQ(event->character,
"A");
1016 EXPECT_EQ(event->synthesized,
false);
1019 EXPECT_EQ(last_handled, FALSE);
1020 [[events lastObject] respond:TRUE];
1021 EXPECT_EQ(last_handled, TRUE);
1023 [events removeAllObjects];
1025 last_handled = FALSE;
1026 [responder
handleEvent:keyEvent(NSEventTypeKeyUp, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
1029 EXPECT_EQ([events count], 2u);
1030 event = [events firstObject].data;
1031 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1032 EXPECT_EQ(event->physical, kPhysicalShiftLeft);
1033 EXPECT_EQ(event->logical, kLogicalShiftLeft);
1034 EXPECT_STREQ(event->character,
nullptr);
1035 EXPECT_EQ(event->synthesized,
true);
1038 event = [events lastObject].data;
1039 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1040 EXPECT_EQ(event->physical, kPhysicalKeyA);
1041 EXPECT_EQ(event->logical, kLogicalKeyA);
1042 EXPECT_STREQ(event->character,
nullptr);
1043 EXPECT_EQ(event->synthesized,
false);
1046 EXPECT_EQ(last_handled, FALSE);
1047 [[events lastObject] respond:TRUE];
1048 EXPECT_EQ(last_handled, TRUE);
1050 [events removeAllObjects];
1053 TEST(FlutterEmbedderKeyResponderUnittests, ConvertCapsLockEvents) {
1054 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1055 __block BOOL last_handled = TRUE;
1056 id keyEventCallback = ^(BOOL handled) {
1057 last_handled = handled;
1059 FlutterKeyEvent* event;
1062 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
1063 _Nullable _VoidPtr user_data) {
1064 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
1066 userData:user_data]];
1071 last_handled = FALSE;
1073 handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x10100, @"", @"", FALSE, kKeyCodeCapsLock)
1076 EXPECT_EQ([events count], 2u);
1078 event = [events firstObject].data;
1079 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1080 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1081 EXPECT_EQ(event->logical, kLogicalCapsLock);
1082 EXPECT_STREQ(event->character,
nullptr);
1083 EXPECT_EQ(event->synthesized,
false);
1086 event = [events lastObject].data;
1087 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1088 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1089 EXPECT_EQ(event->logical, kLogicalCapsLock);
1090 EXPECT_STREQ(event->character,
nullptr);
1091 EXPECT_EQ(event->synthesized,
true);
1094 EXPECT_EQ(last_handled, FALSE);
1095 [[events firstObject] respond:TRUE];
1096 EXPECT_EQ(last_handled, TRUE);
1098 [events removeAllObjects];
1102 last_handled = FALSE;
1103 [responder
handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeCapsLock)
1106 EXPECT_EQ([events count], 2u);
1108 event = [events firstObject].data;
1109 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1110 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1111 EXPECT_EQ(event->logical, kLogicalCapsLock);
1112 EXPECT_STREQ(event->character,
nullptr);
1113 EXPECT_EQ(event->synthesized,
false);
1116 event = [events lastObject].data;
1117 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1118 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1119 EXPECT_EQ(event->logical, kLogicalCapsLock);
1120 EXPECT_STREQ(event->character,
nullptr);
1121 EXPECT_EQ(event->synthesized,
true);
1124 EXPECT_EQ(last_handled, FALSE);
1125 [[events firstObject] respond:TRUE];
1126 EXPECT_EQ(last_handled, TRUE);
1128 [events removeAllObjects];
1132 TEST(FlutterEmbedderKeyResponderUnittests, SynchronizeCapsLockStateOnCapsLock) {
1133 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1134 FlutterKeyEvent* event;
1135 __block BOOL last_handled = TRUE;
1136 id keyEventCallback = ^(BOOL handled) {
1137 last_handled = handled;
1141 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
1142 _Nullable _VoidPtr user_data) {
1143 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
1145 userData:user_data]];
1150 last_handled = FALSE;
1151 [responder
handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, kKeyCodeCapsLock)
1154 EXPECT_EQ([events count], 1u);
1155 EXPECT_EQ(last_handled, TRUE);
1156 event = [events lastObject].data;
1157 EXPECT_EQ(event->physical, 0ull);
1158 EXPECT_EQ(event->logical, 0ull);
1160 EXPECT_EQ(last_handled, TRUE);
1162 [events removeAllObjects];
1166 TEST(FlutterEmbedderKeyResponderUnittests, SynchronizeCapsLockStateOnNormalKey) {
1167 __block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
1168 __block BOOL last_handled = TRUE;
1169 id keyEventCallback = ^(BOOL handled) {
1170 last_handled = handled;
1172 FlutterKeyEvent* event;
1175 initWithSendEvent:^(const FlutterKeyEvent& event, _Nullable FlutterKeyEventCallback callback,
1176 _Nullable _VoidPtr user_data) {
1177 [events addObject:[[
TestKeyEvent alloc] initWithEvent:&event
1179 userData:user_data]];
1182 last_handled = FALSE;
1183 [responder
handleEvent:keyEvent(NSEventTypeKeyDown, 0x10100, @"A", @"a", FALSE, kKeyCodeKeyA)
1186 EXPECT_EQ([events count], 3u);
1188 event = events[0].data;
1189 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1190 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1191 EXPECT_EQ(event->logical, kLogicalCapsLock);
1192 EXPECT_STREQ(event->character,
nullptr);
1193 EXPECT_EQ(event->synthesized,
true);
1196 event = events[1].data;
1197 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1198 EXPECT_EQ(event->physical, kPhysicalCapsLock);
1199 EXPECT_EQ(event->logical, kLogicalCapsLock);
1200 EXPECT_STREQ(event->character,
nullptr);
1201 EXPECT_EQ(event->synthesized,
true);
1204 event = events[2].data;
1205 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1206 EXPECT_EQ(event->physical, kPhysicalKeyA);
1207 EXPECT_EQ(event->logical, kLogicalKeyA);
1208 EXPECT_STREQ(event->character,
"A");
1209 EXPECT_EQ(event->synthesized,
false);
1212 EXPECT_EQ(last_handled, FALSE);
1213 [[events lastObject] respond:TRUE];
1214 EXPECT_EQ(last_handled, TRUE);
1216 [events removeAllObjects];