Flutter macOS Embedder
FlutterViewControllerTestObjC Class Reference
Inheritance diagram for FlutterViewControllerTestObjC:

Instance Methods

(bool) - testKeyEventsAreSentToFramework:
 
(bool) - testKeyEventsArePropagatedIfNotHandled:
 
(bool) - testKeyEventsAreNotPropagatedIfHandled:
 
(bool) - testCtrlTabKeyEventIsPropagated:
 
(bool) - testKeyEquivalentIsPassedToTextInputPlugin:
 
(bool) - testFlagsChangedEventsArePropagatedIfNotHandled:
 
(bool) - testKeyboardIsRestartedOnEngineRestart:
 
(bool) - testTrackpadGesturesAreSentToFramework:
 
(bool) - testMouseDownUpEventsSentToNextResponder:
 
(bool) - testModifierKeysAreSynthesizedOnMouseMove:
 
(bool) - testViewWillAppearCalledMultipleTimes:
 
(bool) - testFlutterViewIsConfigured:
 
(bool) - testLookupKeyAssets
 
(bool) - testLookupKeyAssetsWithPackage
 
(bool) - testViewControllerIsReleased
 

Class Methods

(void) + respondFalseForSendEvent:callback:userData:
 

Detailed Description

Definition at line 95 of file FlutterViewControllerTest.mm.

Method Documentation

◆ respondFalseForSendEvent:callback:userData:

+ (void) respondFalseForSendEvent: (const FlutterKeyEvent&)  event
callback: (nullable FlutterKeyEventCallback)  callback
userData: (nullable void*)  userData 

Definition at line 698 of file FlutterViewControllerTest.mm.

698  :(const FlutterKeyEvent&)event
699  callback:(nullable FlutterKeyEventCallback)callback
700  userData:(nullable void*)userData {
701  if (callback != nullptr) {
702  callback(false, userData);
703  }
704 }

◆ testCtrlTabKeyEventIsPropagated:

- (bool) testCtrlTabKeyEventIsPropagated: (id)  mockEngine

Definition at line 369 of file FlutterViewControllerTest.mm.

369  :(id)engineMock {
370  __block bool called = false;
371  __block FlutterKeyEvent last_event;
372  OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
373  callback:nil
374  userData:nil])
375  .andDo((^(NSInvocation* invocation) {
376  FlutterKeyEvent* event;
377  [invocation getArgument:&event atIndex:2];
378  called = true;
379  last_event = *event;
380  }));
381  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
382  nibName:@""
383  bundle:nil];
384  // Ctrl+tab
385  NSEvent* event = [NSEvent keyEventWithType:NSEventTypeKeyDown
386  location:NSZeroPoint
387  modifierFlags:0x40101
388  timestamp:0
389  windowNumber:0
390  context:nil
391  characters:@""
392  charactersIgnoringModifiers:@""
393  isARepeat:NO
394  keyCode:48];
395  const uint64_t kPhysicalKeyTab = 0x7002b;
396 
397  [viewController viewWillAppear]; // Initializes the event channel.
398  // Creates a NSWindow so that FlutterView view can be first responder.
399  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
400  styleMask:NSBorderlessWindowMask
401  backing:NSBackingStoreBuffered
402  defer:NO];
403  window.contentView = viewController.view;
404  [window makeFirstResponder:viewController.flutterView];
405  [viewController.view performKeyEquivalent:event];
406 
407  EXPECT_TRUE(called);
408  EXPECT_EQ(last_event.type, kFlutterKeyEventTypeDown);
409  EXPECT_EQ(last_event.physical, kPhysicalKeyTab);
410  return true;
411 }

◆ testFlagsChangedEventsArePropagatedIfNotHandled:

- (bool) testFlagsChangedEventsArePropagatedIfNotHandled: (id)  mockEngine

Definition at line 537 of file FlutterViewControllerTest.mm.

537  :(id)engineMock {
538  id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
539  OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
540  [engineMock binaryMessenger])
541  .andReturn(binaryMessengerMock);
542  OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
543  callback:nil
544  userData:nil])
545  .andCall([FlutterViewControllerTestObjC class],
546  @selector(respondFalseForSendEvent:callback:userData:));
547  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
548  nibName:@""
549  bundle:nil];
550  id responderMock = flutter::testing::mockResponder();
551  id responderWrapper = [[FlutterResponderWrapper alloc] initWithResponder:responderMock];
552  viewController.nextResponder = responderWrapper;
553  NSDictionary* expectedEvent = @{
554  @"keymap" : @"macos",
555  @"type" : @"keydown",
556  @"keyCode" : @(56), // SHIFT key
557  @"modifiers" : @(537001986),
558  };
559  NSData* encodedKeyEvent = [[FlutterJSONMessageCodec sharedInstance] encode:expectedEvent];
560  CGEventRef cgEvent = CGEventCreateKeyboardEvent(NULL, 56, TRUE); // SHIFT key
561  CGEventSetType(cgEvent, kCGEventFlagsChanged);
562  NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
563  OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
564  [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
565  message:encodedKeyEvent
566  binaryReply:[OCMArg any]])
567  .andDo((^(NSInvocation* invocation) {
568  FlutterBinaryReply handler;
569  [invocation getArgument:&handler atIndex:4];
570  NSDictionary* reply = @{
571  @"handled" : @(false),
572  };
573  NSData* encodedReply = [[FlutterJSONMessageCodec sharedInstance] encode:reply];
574  handler(encodedReply);
575  }));
576  [viewController viewWillAppear]; // Initializes the event channel.
577  [viewController flagsChanged:event];
578  @try {
579  OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
580  [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
581  message:encodedKeyEvent
582  binaryReply:[OCMArg any]]);
583  } @catch (NSException* e) {
584  NSLog(@"%@", e.reason);
585  return false;
586  }
587  return true;
588 }

References FlutterBinaryReply, and <FlutterMessageCodec>::sharedInstance.

◆ testFlutterViewIsConfigured:

- (bool) testFlutterViewIsConfigured: (id)  mockEngine

Definition at line 518 of file FlutterViewControllerTest.mm.

518  :(id)engineMock {
519  FlutterRenderer* renderer_ = [[FlutterRenderer alloc] initWithFlutterEngine:engineMock];
520  OCMStub([engineMock renderer]).andReturn(renderer_);
521 
522  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
523  nibName:@""
524  bundle:nil];
525  [viewController loadView];
526 
527  @try {
528  // Make sure "renderer" was called during "loadView", which means "flutterView" is created
529  OCMVerify([engineMock renderer]);
530  } @catch (...) {
531  return false;
532  }
533 
534  return true;
535 }

◆ testKeyboardIsRestartedOnEngineRestart:

- (bool) testKeyboardIsRestartedOnEngineRestart: (id)  mockEngine

Definition at line 645 of file FlutterViewControllerTest.mm.

645  :(id)engineMock {
646  id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
647  OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
648  [engineMock binaryMessenger])
649  .andReturn(binaryMessengerMock);
650  __block bool called = false;
651  __block FlutterKeyEvent last_event;
652  OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
653  callback:nil
654  userData:nil])
655  .andDo((^(NSInvocation* invocation) {
656  FlutterKeyEvent* event;
657  [invocation getArgument:&event atIndex:2];
658  called = true;
659  last_event = *event;
660  }));
661 
662  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
663  nibName:@""
664  bundle:nil];
665  [viewController viewWillAppear];
666  NSEvent* keyADown = [NSEvent keyEventWithType:NSEventTypeKeyDown
667  location:NSZeroPoint
668  modifierFlags:0x100
669  timestamp:0
670  windowNumber:0
671  context:nil
672  characters:@"a"
673  charactersIgnoringModifiers:@"a"
674  isARepeat:FALSE
675  keyCode:0];
676  const uint64_t kPhysicalKeyA = 0x70004;
677 
678  // Send KeyA key down event twice. Without restarting the keyboard during
679  // onPreEngineRestart, the second event received will be an empty event with
680  // physical key 0x0 because duplicate key down events are ignored.
681 
682  called = false;
683  [viewController keyDown:keyADown];
684  EXPECT_TRUE(called);
685  EXPECT_EQ(last_event.type, kFlutterKeyEventTypeDown);
686  EXPECT_EQ(last_event.physical, kPhysicalKeyA);
687 
688  [viewController onPreEngineRestart];
689 
690  called = false;
691  [viewController keyDown:keyADown];
692  EXPECT_TRUE(called);
693  EXPECT_EQ(last_event.type, kFlutterKeyEventTypeDown);
694  EXPECT_EQ(last_event.physical, kPhysicalKeyA);
695  return true;
696 }

References FlutterViewController::onPreEngineRestart.

◆ testKeyEquivalentIsPassedToTextInputPlugin:

- (bool) testKeyEquivalentIsPassedToTextInputPlugin: (id)  mockEngine

Definition at line 413 of file FlutterViewControllerTest.mm.

413  :(id)engineMock {
414  __block bool called = false;
415  __block FlutterKeyEvent last_event;
416  OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
417  callback:nil
418  userData:nil])
419  .andDo((^(NSInvocation* invocation) {
420  FlutterKeyEvent* event;
421  [invocation getArgument:&event atIndex:2];
422  called = true;
423  last_event = *event;
424  }));
425  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
426  nibName:@""
427  bundle:nil];
428  // Ctrl+tab
429  NSEvent* event = [NSEvent keyEventWithType:NSEventTypeKeyDown
430  location:NSZeroPoint
431  modifierFlags:0x40101
432  timestamp:0
433  windowNumber:0
434  context:nil
435  characters:@""
436  charactersIgnoringModifiers:@""
437  isARepeat:NO
438  keyCode:48];
439  const uint64_t kPhysicalKeyTab = 0x7002b;
440 
441  [viewController viewWillAppear]; // Initializes the event channel.
442 
443  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
444  styleMask:NSBorderlessWindowMask
445  backing:NSBackingStoreBuffered
446  defer:NO];
447  window.contentView = viewController.view;
448 
449  [viewController.view addSubview:viewController.textInputPlugin];
450 
451  // Make the textInputPlugin first responder. This should still result in
452  // view controller reporting the key event.
453  [window makeFirstResponder:viewController.textInputPlugin];
454 
455  [viewController.view performKeyEquivalent:event];
456 
457  EXPECT_TRUE(called);
458  EXPECT_EQ(last_event.type, kFlutterKeyEventTypeDown);
459  EXPECT_EQ(last_event.physical, kPhysicalKeyTab);
460  return true;
461 }

◆ testKeyEventsAreNotPropagatedIfHandled:

- (bool) testKeyEventsAreNotPropagatedIfHandled: (id)  mockEngine

Definition at line 590 of file FlutterViewControllerTest.mm.

590  :(id)engineMock {
591  id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
592  OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
593  [engineMock binaryMessenger])
594  .andReturn(binaryMessengerMock);
595  OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
596  callback:nil
597  userData:nil])
598  .andCall([FlutterViewControllerTestObjC class],
599  @selector(respondFalseForSendEvent:callback:userData:));
600  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
601  nibName:@""
602  bundle:nil];
603  id responderMock = flutter::testing::mockResponder();
604  id responderWrapper = [[FlutterResponderWrapper alloc] initWithResponder:responderMock];
605  viewController.nextResponder = responderWrapper;
606  NSDictionary* expectedEvent = @{
607  @"keymap" : @"macos",
608  @"type" : @"keydown",
609  @"keyCode" : @(65),
610  @"modifiers" : @(538968064),
611  @"characters" : @".",
612  @"charactersIgnoringModifiers" : @".",
613  };
614  NSData* encodedKeyEvent = [[FlutterJSONMessageCodec sharedInstance] encode:expectedEvent];
615  CGEventRef cgEvent = CGEventCreateKeyboardEvent(NULL, 65, TRUE);
616  NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
617  OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
618  [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
619  message:encodedKeyEvent
620  binaryReply:[OCMArg any]])
621  .andDo((^(NSInvocation* invocation) {
622  FlutterBinaryReply handler;
623  [invocation getArgument:&handler atIndex:4];
624  NSDictionary* reply = @{
625  @"handled" : @(true),
626  };
627  NSData* encodedReply = [[FlutterJSONMessageCodec sharedInstance] encode:reply];
628  handler(encodedReply);
629  }));
630  [viewController viewWillAppear]; // Initializes the event channel.
631  [viewController keyDown:event];
632  @try {
633  OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
634  never(), [responderMock keyDown:[OCMArg any]]);
635  OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
636  [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
637  message:encodedKeyEvent
638  binaryReply:[OCMArg any]]);
639  } @catch (...) {
640  return false;
641  }
642  return true;
643 }

References FlutterBinaryReply, and <FlutterMessageCodec>::sharedInstance.

◆ testKeyEventsArePropagatedIfNotHandled:

- (bool) testKeyEventsArePropagatedIfNotHandled: (id)  mockEngine

Definition at line 463 of file FlutterViewControllerTest.mm.

463  :(id)engineMock {
464  id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
465  OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
466  [engineMock binaryMessenger])
467  .andReturn(binaryMessengerMock);
468  OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
469  callback:nil
470  userData:nil])
471  .andCall([FlutterViewControllerTestObjC class],
472  @selector(respondFalseForSendEvent:callback:userData:));
473  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
474  nibName:@""
475  bundle:nil];
476  id responderMock = flutter::testing::mockResponder();
477  id responderWrapper = [[FlutterResponderWrapper alloc] initWithResponder:responderMock];
478  viewController.nextResponder = responderWrapper;
479  NSDictionary* expectedEvent = @{
480  @"keymap" : @"macos",
481  @"type" : @"keydown",
482  @"keyCode" : @(65),
483  @"modifiers" : @(538968064),
484  @"characters" : @".",
485  @"charactersIgnoringModifiers" : @".",
486  };
487  NSData* encodedKeyEvent = [[FlutterJSONMessageCodec sharedInstance] encode:expectedEvent];
488  CGEventRef cgEvent = CGEventCreateKeyboardEvent(NULL, 65, TRUE);
489  NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
490  OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
491  [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
492  message:encodedKeyEvent
493  binaryReply:[OCMArg any]])
494  .andDo((^(NSInvocation* invocation) {
495  FlutterBinaryReply handler;
496  [invocation getArgument:&handler atIndex:4];
497  NSDictionary* reply = @{
498  @"handled" : @(false),
499  };
500  NSData* encodedReply = [[FlutterJSONMessageCodec sharedInstance] encode:reply];
501  handler(encodedReply);
502  }));
503  [viewController viewWillAppear]; // Initializes the event channel.
504  [viewController keyDown:event];
505  @try {
506  OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
507  [responderMock keyDown:[OCMArg any]]);
508  OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
509  [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
510  message:encodedKeyEvent
511  binaryReply:[OCMArg any]]);
512  } @catch (...) {
513  return false;
514  }
515  return true;
516 }

References FlutterBinaryReply, and <FlutterMessageCodec>::sharedInstance.

◆ testKeyEventsAreSentToFramework:

- (bool) testKeyEventsAreSentToFramework: (id)  mockEngine

Definition at line 331 of file FlutterViewControllerTest.mm.

331  :(id)engineMock {
332  id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
333  OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
334  [engineMock binaryMessenger])
335  .andReturn(binaryMessengerMock);
336  OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
337  callback:nil
338  userData:nil])
339  .andCall([FlutterViewControllerTestObjC class],
340  @selector(respondFalseForSendEvent:callback:userData:));
341  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
342  nibName:@""
343  bundle:nil];
344  NSDictionary* expectedEvent = @{
345  @"keymap" : @"macos",
346  @"type" : @"keydown",
347  @"keyCode" : @(65),
348  @"modifiers" : @(538968064),
349  @"characters" : @".",
350  @"charactersIgnoringModifiers" : @".",
351  };
352  NSData* encodedKeyEvent = [[FlutterJSONMessageCodec sharedInstance] encode:expectedEvent];
353  CGEventRef cgEvent = CGEventCreateKeyboardEvent(NULL, 65, TRUE);
354  NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
355  [viewController viewWillAppear]; // Initializes the event channel.
356  [viewController keyDown:event];
357  @try {
358  OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
359  [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
360  message:encodedKeyEvent
361  binaryReply:[OCMArg any]]);
362  } @catch (...) {
363  return false;
364  }
365  return true;
366 }

References <FlutterMessageCodec>::sharedInstance.

◆ testLookupKeyAssets

- (bool) testLookupKeyAssets

Definition at line 1016 of file FlutterViewControllerTest.mm.

1016  {
1017  FlutterViewController* viewController = [[FlutterViewController alloc] initWithProject:nil];
1018  NSString* key = [viewController lookupKeyForAsset:@"test.png"];
1019  EXPECT_TRUE(
1020  [key isEqualToString:@"Contents/Frameworks/App.framework/Resources/flutter_assets/test.png"]);
1021  return true;
1022 }

References FlutterViewController::lookupKeyForAsset:.

◆ testLookupKeyAssetsWithPackage

- (bool) testLookupKeyAssetsWithPackage

Definition at line 1024 of file FlutterViewControllerTest.mm.

1024  {
1025  FlutterViewController* viewController = [[FlutterViewController alloc] initWithProject:nil];
1026 
1027  NSString* packageKey = [viewController lookupKeyForAsset:@"test.png" fromPackage:@"test"];
1028  EXPECT_TRUE([packageKey
1029  isEqualToString:
1030  @"Contents/Frameworks/App.framework/Resources/flutter_assets/packages/test/test.png"]);
1031  return true;
1032 }

References FlutterViewController::lookupKeyForAsset:fromPackage:.

◆ testModifierKeysAreSynthesizedOnMouseMove:

- (bool) testModifierKeysAreSynthesizedOnMouseMove: (id)  mockEngine

Definition at line 1079 of file FlutterViewControllerTest.mm.

1079  :(id)engineMock {
1080  id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1081  OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1082  [engineMock binaryMessenger])
1083  .andReturn(binaryMessengerMock);
1084 
1085  // Need to return a real renderer to allow view controller to load.
1086  FlutterRenderer* renderer_ = [[FlutterRenderer alloc] initWithFlutterEngine:engineMock];
1087  OCMStub([engineMock renderer]).andReturn(renderer_);
1088 
1089  // Capture calls to sendKeyEvent
1090  __block NSMutableArray<KeyEventWrapper*>* events = [NSMutableArray array];
1091  OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
1092  callback:nil
1093  userData:nil])
1094  .andDo((^(NSInvocation* invocation) {
1095  FlutterKeyEvent* event;
1096  [invocation getArgument:&event atIndex:2];
1097  [events addObject:[[KeyEventWrapper alloc] initWithEvent:event]];
1098  }));
1099 
1100  __block NSMutableArray<NSDictionary*>* channelEvents = [NSMutableArray array];
1101  OCMStub([binaryMessengerMock sendOnChannel:@"flutter/keyevent"
1102  message:[OCMArg any]
1103  binaryReply:[OCMArg any]])
1104  .andDo((^(NSInvocation* invocation) {
1105  NSData* data;
1106  [invocation getArgument:&data atIndex:3];
1107  id event = [[FlutterJSONMessageCodec sharedInstance] decode:data];
1108  [channelEvents addObject:event];
1109  }));
1110 
1111  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1112  nibName:@""
1113  bundle:nil];
1114  [viewController loadView];
1115  [viewController viewWillAppear];
1116 
1117  // Zeroed modifier flag should not synthesize events.
1118  NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(0x00);
1119  [viewController mouseMoved:mouseEvent];
1120  EXPECT_EQ([events count], 0u);
1121 
1122  // For each modifier key, check that key events are synthesized.
1123  for (NSNumber* keyCode in flutter::keyCodeToModifierFlag) {
1124  FlutterKeyEvent* event;
1125  NSDictionary* channelEvent;
1126  NSNumber* logicalKey;
1127  NSNumber* physicalKey;
1128  NSEventModifierFlags flag = [flutter::keyCodeToModifierFlag[keyCode] unsignedLongValue];
1129 
1130  // Cocoa event always contain combined flags.
1132  flag |= NSEventModifierFlagShift;
1133  }
1135  flag |= NSEventModifierFlagControl;
1136  }
1138  flag |= NSEventModifierFlagOption;
1139  }
1141  flag |= NSEventModifierFlagCommand;
1142  }
1143 
1144  // Should synthesize down event.
1145  NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(flag);
1146  [viewController mouseMoved:mouseEvent];
1147  EXPECT_EQ([events count], 1u);
1148  event = events[0].data;
1149  logicalKey = [flutter::keyCodeToLogicalKey objectForKey:keyCode];
1150  physicalKey = [flutter::keyCodeToPhysicalKey objectForKey:keyCode];
1151  EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1152  EXPECT_EQ(event->logical, logicalKey.unsignedLongLongValue);
1153  EXPECT_EQ(event->physical, physicalKey.unsignedLongLongValue);
1154  EXPECT_EQ(event->synthesized, true);
1155 
1156  channelEvent = channelEvents[0];
1157  EXPECT_TRUE([channelEvent[@"type"] isEqual:@"keydown"]);
1158  EXPECT_TRUE([channelEvent[@"keyCode"] isEqual:keyCode]);
1159  EXPECT_TRUE([channelEvent[@"modifiers"] isEqual:@(flag)]);
1160 
1161  // Should synthesize up event.
1162  mouseEvent = flutter::testing::CreateMouseEvent(0x00);
1163  [viewController mouseMoved:mouseEvent];
1164  EXPECT_EQ([events count], 2u);
1165  event = events[1].data;
1166  logicalKey = [flutter::keyCodeToLogicalKey objectForKey:keyCode];
1167  physicalKey = [flutter::keyCodeToPhysicalKey objectForKey:keyCode];
1168  EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1169  EXPECT_EQ(event->logical, logicalKey.unsignedLongLongValue);
1170  EXPECT_EQ(event->physical, physicalKey.unsignedLongLongValue);
1171  EXPECT_EQ(event->synthesized, true);
1172 
1173  channelEvent = channelEvents[1];
1174  EXPECT_TRUE([channelEvent[@"type"] isEqual:@"keyup"]);
1175  EXPECT_TRUE([channelEvent[@"keyCode"] isEqual:keyCode]);
1176  EXPECT_TRUE([channelEvent[@"modifiers"] isEqual:@(0)]);
1177 
1178  [events removeAllObjects];
1179  [channelEvents removeAllObjects];
1180  };
1181 
1182  return true;
1183 }

References KeyEventWrapper::data, flutter::keyCodeToModifierFlag, flutter::kModifierFlagAltLeft, flutter::kModifierFlagAltRight, flutter::kModifierFlagControlLeft, flutter::kModifierFlagControlRight, flutter::kModifierFlagMetaLeft, flutter::kModifierFlagMetaRight, flutter::kModifierFlagShiftLeft, flutter::kModifierFlagShiftRight, and <FlutterMessageCodec>::sharedInstance.

◆ testMouseDownUpEventsSentToNextResponder:

- (bool) testMouseDownUpEventsSentToNextResponder: (id)  mockEngine

Definition at line 1043 of file FlutterViewControllerTest.mm.

1043  :(id)engineMock {
1044  // The root cause of the above bug is NSResponder mouseDown/mouseUp methods that don't correctly
1045  // walk the responder chain calling the appropriate method on the next responder under certain
1046  // conditions. Simulate this by swizzling out the default implementations and replacing them with
1047  // no-ops.
1048  Method mouseDown = class_getInstanceMethod([NSResponder class], @selector(mouseDown:));
1049  Method mouseUp = class_getInstanceMethod([NSResponder class], @selector(mouseUp:));
1050  IMP noopImp = (IMP)SwizzledNoop;
1051  IMP origMouseDown = method_setImplementation(mouseDown, noopImp);
1052  IMP origMouseUp = method_setImplementation(mouseUp, noopImp);
1053 
1054  // Verify that mouseDown/mouseUp trigger mouseDown/mouseUp calls on FlutterViewController.
1055  MouseEventFlutterViewController* viewController =
1056  [[MouseEventFlutterViewController alloc] initWithEngine:engineMock nibName:@"" bundle:nil];
1057  FlutterView* view = (FlutterView*)[viewController view];
1058 
1059  EXPECT_FALSE(viewController.mouseDownCalled);
1060  EXPECT_FALSE(viewController.mouseUpCalled);
1061 
1062  NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(0x00);
1063  [view mouseDown:mouseEvent];
1064  EXPECT_TRUE(viewController.mouseDownCalled);
1065  EXPECT_FALSE(viewController.mouseUpCalled);
1066 
1067  viewController.mouseDownCalled = NO;
1068  [view mouseUp:mouseEvent];
1069  EXPECT_FALSE(viewController.mouseDownCalled);
1070  EXPECT_TRUE(viewController.mouseUpCalled);
1071 
1072  // Restore the original NSResponder mouseDown/mouseUp implementations.
1073  method_setImplementation(mouseDown, origMouseDown);
1074  method_setImplementation(mouseUp, origMouseUp);
1075 
1076  return true;
1077 }

References MouseEventFlutterViewController::mouseDownCalled, and MouseEventFlutterViewController::mouseUpCalled.

◆ testTrackpadGesturesAreSentToFramework:

- (bool) testTrackpadGesturesAreSentToFramework: (id)  mockEngine

Definition at line 706 of file FlutterViewControllerTest.mm.

706  :(id)engineMock {
707  // Need to return a real renderer to allow view controller to load.
708  FlutterRenderer* renderer_ = [[FlutterRenderer alloc] initWithFlutterEngine:engineMock];
709  OCMStub([engineMock renderer]).andReturn(renderer_);
710  __block bool called = false;
711  __block FlutterPointerEvent last_event;
712  OCMStub([[engineMock ignoringNonObjectArgs] sendPointerEvent:FlutterPointerEvent{}])
713  .andDo((^(NSInvocation* invocation) {
714  FlutterPointerEvent* event;
715  [invocation getArgument:&event atIndex:2];
716  called = true;
717  last_event = *event;
718  }));
719 
720  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
721  nibName:@""
722  bundle:nil];
723  [viewController loadView];
724 
725  // Test for pan events.
726  // Start gesture.
727  CGEventRef cgEventStart = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 1, 0);
728  CGEventSetType(cgEventStart, kCGEventScrollWheel);
729  CGEventSetIntegerValueField(cgEventStart, kCGScrollWheelEventScrollPhase, kCGScrollPhaseBegan);
730  CGEventSetIntegerValueField(cgEventStart, kCGScrollWheelEventIsContinuous, 1);
731 
732  called = false;
733  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventStart]];
734  EXPECT_TRUE(called);
735  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
736  EXPECT_EQ(last_event.phase, kPanZoomStart);
737  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
738  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
739 
740  // Update gesture.
741  CGEventRef cgEventUpdate = CGEventCreateCopy(cgEventStart);
742  CGEventSetIntegerValueField(cgEventUpdate, kCGScrollWheelEventScrollPhase, kCGScrollPhaseChanged);
743  CGEventSetIntegerValueField(cgEventUpdate, kCGScrollWheelEventDeltaAxis2, 1); // pan_x
744  CGEventSetIntegerValueField(cgEventUpdate, kCGScrollWheelEventDeltaAxis1, 2); // pan_y
745 
746  called = false;
747  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventUpdate]];
748  EXPECT_TRUE(called);
749  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
750  EXPECT_EQ(last_event.phase, kPanZoomUpdate);
751  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
752  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
753  EXPECT_EQ(last_event.pan_x, 8 * viewController.flutterView.layer.contentsScale);
754  EXPECT_EQ(last_event.pan_y, 16 * viewController.flutterView.layer.contentsScale);
755 
756  // Make sure the pan values accumulate.
757  called = false;
758  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventUpdate]];
759  EXPECT_TRUE(called);
760  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
761  EXPECT_EQ(last_event.phase, kPanZoomUpdate);
762  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
763  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
764  EXPECT_EQ(last_event.pan_x, 16 * viewController.flutterView.layer.contentsScale);
765  EXPECT_EQ(last_event.pan_y, 32 * viewController.flutterView.layer.contentsScale);
766 
767  // End gesture.
768  CGEventRef cgEventEnd = CGEventCreateCopy(cgEventStart);
769  CGEventSetIntegerValueField(cgEventEnd, kCGScrollWheelEventScrollPhase, kCGScrollPhaseEnded);
770 
771  called = false;
772  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventEnd]];
773  EXPECT_TRUE(called);
774  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
775  EXPECT_EQ(last_event.phase, kPanZoomEnd);
776  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
777  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
778 
779  // Start system momentum.
780  CGEventRef cgEventMomentumStart = CGEventCreateCopy(cgEventStart);
781  CGEventSetIntegerValueField(cgEventMomentumStart, kCGScrollWheelEventScrollPhase, 0);
782  CGEventSetIntegerValueField(cgEventMomentumStart, kCGScrollWheelEventMomentumPhase,
783  kCGMomentumScrollPhaseBegin);
784 
785  called = false;
786  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventMomentumStart]];
787  EXPECT_FALSE(called);
788 
789  // Advance system momentum.
790  CGEventRef cgEventMomentumUpdate = CGEventCreateCopy(cgEventStart);
791  CGEventSetIntegerValueField(cgEventMomentumUpdate, kCGScrollWheelEventScrollPhase, 0);
792  CGEventSetIntegerValueField(cgEventMomentumUpdate, kCGScrollWheelEventMomentumPhase,
793  kCGMomentumScrollPhaseContinue);
794 
795  called = false;
796  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventMomentumUpdate]];
797  EXPECT_FALSE(called);
798 
799  // Mock a touch on the trackpad.
800  id touchMock = OCMClassMock([NSTouch class]);
801  NSSet* touchSet = [NSSet setWithObject:touchMock];
802  id touchEventMock1 = OCMClassMock([NSEvent class]);
803  OCMStub([touchEventMock1 allTouches]).andReturn(touchSet);
804  CGPoint touchLocation = {0, 0};
805  OCMStub([touchEventMock1 locationInWindow]).andReturn(touchLocation);
806  OCMStub([(NSEvent*)touchEventMock1 timestamp]).andReturn(0.150); // 150 milliseconds.
807 
808  // Scroll inertia cancel event should not be issued (timestamp too far in the future).
809  called = false;
810  [viewController touchesBeganWithEvent:touchEventMock1];
811  EXPECT_FALSE(called);
812 
813  // Mock another touch on the trackpad.
814  id touchEventMock2 = OCMClassMock([NSEvent class]);
815  OCMStub([touchEventMock2 allTouches]).andReturn(touchSet);
816  OCMStub([touchEventMock2 locationInWindow]).andReturn(touchLocation);
817  OCMStub([(NSEvent*)touchEventMock2 timestamp]).andReturn(0.005); // 5 milliseconds.
818 
819  // Scroll inertia cancel event should be issued.
820  called = false;
821  [viewController touchesBeganWithEvent:touchEventMock2];
822  EXPECT_TRUE(called);
823  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindScrollInertiaCancel);
824  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
825 
826  // End system momentum.
827  CGEventRef cgEventMomentumEnd = CGEventCreateCopy(cgEventStart);
828  CGEventSetIntegerValueField(cgEventMomentumEnd, kCGScrollWheelEventScrollPhase, 0);
829  CGEventSetIntegerValueField(cgEventMomentumEnd, kCGScrollWheelEventMomentumPhase,
830  kCGMomentumScrollPhaseEnd);
831 
832  called = false;
833  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventMomentumEnd]];
834  EXPECT_FALSE(called);
835 
836  // May-begin and cancel are used while macOS determines which type of gesture to choose.
837  CGEventRef cgEventMayBegin = CGEventCreateCopy(cgEventStart);
838  CGEventSetIntegerValueField(cgEventMayBegin, kCGScrollWheelEventScrollPhase,
839  kCGScrollPhaseMayBegin);
840 
841  called = false;
842  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventMayBegin]];
843  EXPECT_TRUE(called);
844  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
845  EXPECT_EQ(last_event.phase, kPanZoomStart);
846  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
847  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
848 
849  // Cancel gesture.
850  CGEventRef cgEventCancel = CGEventCreateCopy(cgEventStart);
851  CGEventSetIntegerValueField(cgEventCancel, kCGScrollWheelEventScrollPhase,
852  kCGScrollPhaseCancelled);
853 
854  called = false;
855  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventCancel]];
856  EXPECT_TRUE(called);
857  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
858  EXPECT_EQ(last_event.phase, kPanZoomEnd);
859  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
860  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
861 
862  // A discrete scroll event should use the PointerSignal system.
863  CGEventRef cgEventDiscrete = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 1, 0);
864  CGEventSetType(cgEventDiscrete, kCGEventScrollWheel);
865  CGEventSetIntegerValueField(cgEventDiscrete, kCGScrollWheelEventIsContinuous, 0);
866  CGEventSetIntegerValueField(cgEventDiscrete, kCGScrollWheelEventDeltaAxis2, 1); // scroll_delta_x
867  CGEventSetIntegerValueField(cgEventDiscrete, kCGScrollWheelEventDeltaAxis1, 2); // scroll_delta_y
868 
869  called = false;
870  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventDiscrete]];
871  EXPECT_TRUE(called);
872  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindScroll);
873  // pixelsPerLine is 40.0 and direction is reversed.
874  EXPECT_EQ(last_event.scroll_delta_x, -40 * viewController.flutterView.layer.contentsScale);
875  EXPECT_EQ(last_event.scroll_delta_y, -80 * viewController.flutterView.layer.contentsScale);
876 
877  // A discrete scroll event should use the PointerSignal system, and flip the
878  // direction when shift is pressed.
879  CGEventRef cgEventDiscreteShift =
880  CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 1, 0);
881  CGEventSetType(cgEventDiscreteShift, kCGEventScrollWheel);
882  CGEventSetFlags(cgEventDiscreteShift, kCGEventFlagMaskShift | flutter::kModifierFlagShiftLeft);
883  CGEventSetIntegerValueField(cgEventDiscreteShift, kCGScrollWheelEventIsContinuous, 0);
884  CGEventSetIntegerValueField(cgEventDiscreteShift, kCGScrollWheelEventDeltaAxis2,
885  0); // scroll_delta_x
886  CGEventSetIntegerValueField(cgEventDiscreteShift, kCGScrollWheelEventDeltaAxis1,
887  2); // scroll_delta_y
888 
889  called = false;
890  [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventDiscreteShift]];
891  EXPECT_TRUE(called);
892  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindScroll);
893  // pixelsPerLine is 40.0, direction is reversed and axes have been flipped back.
894  EXPECT_FLOAT_EQ(last_event.scroll_delta_x, 0.0 * viewController.flutterView.layer.contentsScale);
895  EXPECT_FLOAT_EQ(last_event.scroll_delta_y,
896  -80.0 * viewController.flutterView.layer.contentsScale);
897 
898  // Test for scale events.
899  // Start gesture.
900  called = false;
901  [viewController magnifyWithEvent:flutter::testing::MockGestureEvent(NSEventTypeMagnify,
902  NSEventPhaseBegan, 1, 0)];
903  EXPECT_TRUE(called);
904  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
905  EXPECT_EQ(last_event.phase, kPanZoomStart);
906  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
907  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
908 
909  // Update gesture.
910  called = false;
911  [viewController magnifyWithEvent:flutter::testing::MockGestureEvent(NSEventTypeMagnify,
912  NSEventPhaseChanged, 1, 0)];
913  EXPECT_TRUE(called);
914  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
915  EXPECT_EQ(last_event.phase, kPanZoomUpdate);
916  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
917  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
918  EXPECT_EQ(last_event.pan_x, 0);
919  EXPECT_EQ(last_event.pan_y, 0);
920  EXPECT_EQ(last_event.scale, 2); // macOS uses logarithmic scaling values, the linear value for
921  // flutter here should be 2^1 = 2.
922  EXPECT_EQ(last_event.rotation, 0);
923 
924  // Make sure the scale values accumulate.
925  called = false;
926  [viewController magnifyWithEvent:flutter::testing::MockGestureEvent(NSEventTypeMagnify,
927  NSEventPhaseChanged, 1, 0)];
928  EXPECT_TRUE(called);
929  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
930  EXPECT_EQ(last_event.phase, kPanZoomUpdate);
931  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
932  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
933  EXPECT_EQ(last_event.pan_x, 0);
934  EXPECT_EQ(last_event.pan_y, 0);
935  EXPECT_EQ(last_event.scale, 4); // macOS uses logarithmic scaling values, the linear value for
936  // flutter here should be 2^(1+1) = 2.
937  EXPECT_EQ(last_event.rotation, 0);
938 
939  // End gesture.
940  called = false;
941  [viewController magnifyWithEvent:flutter::testing::MockGestureEvent(NSEventTypeMagnify,
942  NSEventPhaseEnded, 0, 0)];
943  EXPECT_TRUE(called);
944  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
945  EXPECT_EQ(last_event.phase, kPanZoomEnd);
946  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
947  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
948 
949  // Test for rotation events.
950  // Start gesture.
951  called = false;
952  [viewController rotateWithEvent:flutter::testing::MockGestureEvent(NSEventTypeRotate,
953  NSEventPhaseBegan, 1, 0)];
954  EXPECT_TRUE(called);
955  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
956  EXPECT_EQ(last_event.phase, kPanZoomStart);
957  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
958  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
959 
960  // Update gesture.
961  called = false;
962  [viewController rotateWithEvent:flutter::testing::MockGestureEvent(
963  NSEventTypeRotate, NSEventPhaseChanged, 0, -180)]; // degrees
964  EXPECT_TRUE(called);
965  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
966  EXPECT_EQ(last_event.phase, kPanZoomUpdate);
967  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
968  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
969  EXPECT_EQ(last_event.pan_x, 0);
970  EXPECT_EQ(last_event.pan_y, 0);
971  EXPECT_EQ(last_event.scale, 1);
972  EXPECT_EQ(last_event.rotation, M_PI); // radians
973 
974  // Make sure the rotation values accumulate.
975  called = false;
976  [viewController rotateWithEvent:flutter::testing::MockGestureEvent(
977  NSEventTypeRotate, NSEventPhaseChanged, 0, -360)]; // degrees
978  EXPECT_TRUE(called);
979  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
980  EXPECT_EQ(last_event.phase, kPanZoomUpdate);
981  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
982  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
983  EXPECT_EQ(last_event.pan_x, 0);
984  EXPECT_EQ(last_event.pan_y, 0);
985  EXPECT_EQ(last_event.scale, 1);
986  EXPECT_EQ(last_event.rotation, 3 * M_PI); // radians
987 
988  // End gesture.
989  called = false;
990  [viewController rotateWithEvent:flutter::testing::MockGestureEvent(NSEventTypeRotate,
991  NSEventPhaseEnded, 0, 0)];
992  EXPECT_TRUE(called);
993  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
994  EXPECT_EQ(last_event.phase, kPanZoomEnd);
995  EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
996  EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
997 
998  // Test that stray NSEventPhaseCancelled event does not crash
999  called = false;
1000  [viewController rotateWithEvent:flutter::testing::MockGestureEvent(NSEventTypeRotate,
1001  NSEventPhaseCancelled, 0, 0)];
1002  EXPECT_FALSE(called);
1003 
1004  return true;
1005 }

References flutter::kModifierFlagShiftLeft.

◆ testViewControllerIsReleased

- (bool) testViewControllerIsReleased

Definition at line 1185 of file FlutterViewControllerTest.mm.

1185  {
1186  __weak FlutterViewController* weakController;
1187  @autoreleasepool {
1188  id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1189 
1190  FlutterRenderer* renderer_ = [[FlutterRenderer alloc] initWithFlutterEngine:engineMock];
1191  OCMStub([engineMock renderer]).andReturn(renderer_);
1192 
1193  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1194  nibName:@""
1195  bundle:nil];
1196  [viewController loadView];
1197  weakController = viewController;
1198 
1199  [engineMock shutDownEngine];
1200  }
1201 
1202  EXPECT_EQ(weakController, nil);
1203  return true;
1204 }

References flutter::testing::CreateMockFlutterEngine().

◆ testViewWillAppearCalledMultipleTimes:

- (bool) testViewWillAppearCalledMultipleTimes: (id)  mockEngine

Definition at line 1007 of file FlutterViewControllerTest.mm.

1007  :(id)engineMock {
1008  FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1009  nibName:@""
1010  bundle:nil];
1011  [viewController viewWillAppear];
1012  [viewController viewWillAppear];
1013  return true;
1014 }

The documentation for this class was generated from the following file:
FlutterViewControllerTestObjC
Definition: FlutterViewControllerTest.mm:95
FlutterViewController
Definition: FlutterViewController.h:65
FlutterResponderWrapper
Definition: FlutterViewControllerTest.mm:46
MouseEventFlutterViewController
Definition: FlutterViewControllerTest.mm:80
flutter::testing::CreateMockFlutterEngine
id CreateMockFlutterEngine(NSString *pasteboardString)
Definition: FlutterEngineTestUtils.mm:76
flutter::kModifierFlagMetaLeft
@ kModifierFlagMetaLeft
Definition: KeyCodeMap_Internal.h:83
flutter::kModifierFlagAltRight
@ kModifierFlagAltRight
Definition: KeyCodeMap_Internal.h:86
flutter::kModifierFlagMetaRight
@ kModifierFlagMetaRight
Definition: KeyCodeMap_Internal.h:84
-[FlutterViewController lookupKeyForAsset:]
nonnull NSString * lookupKeyForAsset:(nonnull NSString *asset)
MouseEventFlutterViewController::mouseDownCalled
BOOL mouseDownCalled
Definition: FlutterViewControllerTest.mm:81
KeyEventWrapper
Definition: FlutterViewControllerTest.mm:25
FlutterRenderer
Definition: FlutterRenderer.h:18
flutter::kModifierFlagControlLeft
@ kModifierFlagControlLeft
Definition: KeyCodeMap_Internal.h:80
-[FlutterViewController onPreEngineRestart]
void onPreEngineRestart()
Definition: FlutterViewController.mm:477
flutter::kModifierFlagAltLeft
@ kModifierFlagAltLeft
Definition: KeyCodeMap_Internal.h:85
-[FlutterViewController lookupKeyForAsset:fromPackage:]
nonnull NSString * lookupKeyForAsset:fromPackage:(nonnull NSString *asset,[fromPackage] nonnull NSString *package)
flutter::keyCodeToModifierFlag
const NSDictionary * keyCodeToModifierFlag
Definition: KeyCodeMap.g.mm:223
flutter::kModifierFlagShiftRight
@ kModifierFlagShiftRight
Definition: KeyCodeMap_Internal.h:82
MouseEventFlutterViewController::mouseUpCalled
BOOL mouseUpCalled
Definition: FlutterViewControllerTest.mm:82
FlutterView
Definition: FlutterView.h:48
flutter::kModifierFlagShiftLeft
@ kModifierFlagShiftLeft
Definition: KeyCodeMap_Internal.h:81
FlutterBinaryMessenger-p
Definition: FlutterBinaryMessenger.h:49
flutter::kModifierFlagControlRight
@ kModifierFlagControlRight
Definition: KeyCodeMap_Internal.h:87
FlutterBinaryReply
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterBinaryReply)(NSData *_Nullable reply)
+[FlutterMessageCodec-p sharedInstance]
instancetype sharedInstance()
FlutterJSONMessageCodec
Definition: FlutterCodecs.h:81