Flutter Engine
The Flutter Engine
Instance Methods | Class Methods | Properties | List of all members
FlutterViewController Class Reference

#import <FlutterViewController.h>

Inheritance diagram for FlutterViewController:
<FlutterKeyboardViewDelegate> <FlutterViewResponder> <FlutterBinaryMessenger> <FlutterPluginRegistry> <FlutterPluginRegistry> <FlutterTextureRegistry> AccessibilityBridgeTestViewController MouseEventFlutterViewController NoStatusBarFlutterViewController ShareViewController TextInputTestViewController

Instance Methods

(instancetype) - initWithEngine:nibName:bundle:
 
(instancetype) - initWithProject:nibName:bundle:
 
(instancetype) - initWithProject:initialRoute:nibName:bundle:
 
(instancetype) - initWithCoder:
 
(void) - setFlutterViewDidRenderCallback:
 
(NSString *) - lookupKeyForAsset:
 
(NSString *) - lookupKeyForAsset:fromPackage:
 
(void) - setInitialRoute:
 
(void) - popRoute
 
(void) - pushRoute:
 
(id< FlutterPluginRegistry >) - pluginRegistry
 
(BOOL- loadDefaultSplashScreenView
 
(nonnull instancetype) - initWithProject:
 
(nonnull instancetype) - initWithNibName:bundle:
 
(nonnull instancetype) - initWithCoder:
 
(nonnull instancetype) - initWithEngine:nibName:bundle:
 
(BOOL- attached
 
(void) - onPreEngineRestart
 
(nonnull NSString *) - lookupKeyForAsset:
 
(nonnull NSString *) - lookupKeyForAsset:fromPackage:
 
(instancetype) - initWithProject:nibName:bundle: [implementation]
 
(instancetype) - initWithProject:initialRoute:nibName:bundle: [implementation]
 
(instancetype) - initWithNibName:bundle: [implementation]
 
(void) - awakeFromNib [implementation]
 
(instancetype) - init [implementation]
 
(void) - sharedSetupWithProject:initialRoute: [implementation]
 
(BOOL- isViewOpaque [implementation]
 
(void) - setViewOpaque: [implementation]
 
(void) - performCommonViewControllerInitialization [implementation]
 
(fml::WeakNSObject< FlutterViewController >) - getWeakNSObject [implementation]
 
(void) - setUpNotificationCenterObservers [implementation]
 
(void) - setUpSceneLifecycleNotifications: [implementation]
 
(void) - setUpApplicationLifecycleNotifications: [implementation]
 
(void) - setInitialRoute: [implementation]
 
(void) - loadView [implementation]
 
(flutter::PointerData- generatePointerDataForFake [implementation]
 
(BOOL- scrollViewShouldScrollToTop: [implementation]
 
(void) - installSplashScreenViewIfNecessary [implementation]
 
(void) - setDisplayingFlutterUI: [implementation]
 
(void) - callViewRenderedCallback [implementation]
 
(void) - removeSplashScreenView: [implementation]
 
(void) - installFirstFrameCallback [implementation]
 
(UIView *) - keyboardAnimationView [implementation]
 
(SpringAnimation *) - keyboardSpringAnimation [implementation]
 
(UIView *) - splashScreenFromStoryboard: [implementation]
 
(UIView *) - splashScreenFromXib: [implementation]
 
(void) - setSplashScreenView: [implementation]
 
(void) - surfaceUpdated: [implementation]
 
(void) - viewDidLoad [implementation]
 
(void) - addInternalPlugins [implementation]
 
(void) - removeInternalPlugins [implementation]
 
(void) - viewWillAppear: [implementation]
 
(void) - viewDidAppear: [implementation]
 
(void) - viewWillDisappear: [implementation]
 
(void) - viewDidDisappear: [implementation]
 
(void) - viewWillTransitionToSize:withTransitionCoordinator: [implementation]
 
(void) - flushOngoingTouches [implementation]
 
(void) - deregisterNotifications [implementation]
 
(void) - dealloc [implementation]
 
(void) - applicationBecameActive: [implementation]
 
(void) - applicationWillResignActive: [implementation]
 
(void) - applicationWillTerminate: [implementation]
 
(void) - applicationDidEnterBackground: [implementation]
 
(void) - applicationWillEnterForeground: [implementation]
 
(void) - sceneBecameActive: [implementation]
 
(void) - sceneWillResignActive: [implementation]
 
(void) - sceneWillDisconnect: [implementation]
 
(void) - sceneDidEnterBackground: [implementation]
 
(void) - sceneWillEnterForeground: [implementation]
 
(void) - appOrSceneBecameActive [implementation]
 
(void) - appOrSceneWillResignActive [implementation]
 
(void) - appOrSceneWillTerminate [implementation]
 
(void) - appOrSceneDidEnterBackground [implementation]
 
(void) - appOrSceneWillEnterForeground [implementation]
 
(void) - goToApplicationLifecycle: [implementation]
 
(void) - dispatchTouches:pointerDataChangeOverride:event: [implementation]
 
(void) - touchesBegan:withEvent: [implementation]
 
(void) - touchesMoved:withEvent: [implementation]
 
(void) - touchesEnded:withEvent: [implementation]
 
(void) - touchesCancelled:withEvent: [implementation]
 
(void) - forceTouchesCancelled: [implementation]
 
(void) - createTouchRateCorrectionVSyncClientIfNeeded [implementation]
 
(void) - triggerTouchRateCorrectionIfNeeded: [implementation]
 
(void) - invalidateTouchRateCorrectionVSyncClient [implementation]
 
(void) - updateViewportMetricsIfNeeded [implementation]
 
(void) - viewDidLayoutSubviews [implementation]
 
(void) - viewSafeAreaInsetsDidChange [implementation]
 
(void) - setViewportMetricsSize [implementation]
 
(void) - setViewportMetricsPaddings [implementation]
 
(void) - keyboardWillShowNotification: [implementation]
 
(void) - keyboardWillChangeFrame: [implementation]
 
(void) - keyboardWillBeHidden: [implementation]
 
(void) - handleKeyboardNotification: [implementation]
 
(BOOL- shouldIgnoreKeyboardNotification: [implementation]
 
(BOOL- isKeyboardNotificationForDifferentView: [implementation]
 
(FlutterKeyboardMode) - calculateKeyboardAttachMode: [implementation]
 
(CGFloat) - calculateMultitaskingAdjustment:keyboardFrame: [implementation]
 
(CGFloat) - calculateKeyboardInset:keyboardMode: [implementation]
 
(void) - startKeyBoardAnimation: [implementation]
 
(void) - setUpKeyboardSpringAnimationIfNeeded: [implementation]
 
(void) - setUpKeyboardAnimationVsyncClient: [implementation]
 
(void) - invalidateKeyboardAnimationVSyncClient [implementation]
 
(void) - removeKeyboardAnimationView [implementation]
 
(void) - ensureViewportMetricsIsCorrect [implementation]
 
(void) - handlePressEvent:nextAction: [implementation]
 
(void) - pressesBegan:withEvent: [implementation]
 
(void) - pressesChanged:withEvent: [implementation]
 
(void) - pressesEnded:withEvent: [implementation]
 
(void) - pressesCancelled:withEvent: [implementation]
 
(void) - onOrientationPreferencesUpdated: [implementation]
 
(void) - requestGeometryUpdateForWindowScenes: [implementation]
 
(void) - performOrientationUpdate: [implementation]
 
(void) - onHideHomeIndicatorNotification: [implementation]
 
(void) - onShowHomeIndicatorNotification: [implementation]
 
(void) - setIsHomeIndicatorHidden: [implementation]
 
(BOOL- prefersHomeIndicatorAutoHidden [implementation]
 
(BOOL- shouldAutorotate [implementation]
 
(NSUInteger) - supportedInterfaceOrientations [implementation]
 
(void) - onAccessibilityStatusChanged: [implementation]
 
(int32_t) - accessibilityFlags [implementation]
 
(BOOL- accessibilityPerformEscape [implementation]
 
(void) - traitCollectionDidChange: [implementation]
 
(void) - onUserSettingsChanged: [implementation]
 
(CGFloat) - textScaleFactor [implementation]
 
(BOOL- supportsShowingSystemContextMenu [implementation]
 
(BOOL- isAlwaysUse24HourFormat [implementation]
 
(NSString *) - brightnessMode [implementation]
 
(NSString *) - contrastMode [implementation]
 
(UIStatusBarStyle) - preferredStatusBarStyle [implementation]
 
(void) - onPreferredStatusBarStyleUpdated: [implementation]
 
(void) - setPrefersStatusBarHidden: [implementation]
 
(BOOL- prefersStatusBarHidden [implementation]
 Whether the status bar is preferred hidden. More...
 
(std::shared_ptr< flutter::FlutterPlatformViewsController > &) - platformViewsController [implementation]
 
(void) - sendOnChannel:message: [implementation]
 
(void) - sendOnChannel:message:binaryReply: [implementation]
 
(NSObject< FlutterTaskQueue > *) - makeBackgroundTaskQueue [implementation]
 TODO(gaaclarke): Remove optional when macos supports Background Platform Channels. More...
 
(FlutterBinaryMessengerConnection- setMessageHandlerOnChannel:binaryMessageHandler: [implementation]
 
(FlutterBinaryMessengerConnection- setMessageHandlerOnChannel:binaryMessageHandler:taskQueue: [implementation]
 
(void) - cleanUpConnection: [implementation]
 
(int64_t) - registerTexture: [implementation]
 
(void) - unregisterTexture: [implementation]
 
(void) - textureFrameAvailable: [implementation]
 
(NSObject< FlutterPluginRegistrar > *) - registrarForPlugin: [implementation]
 
(BOOL- hasPlugin: [implementation]
 
(NSObject *) - valuePublishedByPlugin: [implementation]
 
(void) - presentViewController:animated:completion: [implementation]
 
(BOOL- isPresentingViewController [implementation]
 
() - ios [implementation]
 
(BOOL- gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: [implementation]
 
(BOOL- gestureRecognizer:shouldReceiveEvent: [implementation]
 
(void) - hoverEvent: [implementation]
 
(void) - discreteScrollEvent: [implementation]
 
(void) - continuousScrollEvent: [implementation]
 
(void) - pinchEvent: [implementation]
 
(void) - encodeRestorableStateWithCoder: [implementation]
 
(void) - decodeRestorableStateWithCoder: [implementation]
 
(FlutterRestorationPlugin *) - restorationPlugin [implementation]
 
(BOOL- isDispatchingKeyEvent: [implementation]
 
(void) - viewWillAppear [implementation]
 
(void) - viewWillDisappear [implementation]
 
(void) - setMouseTrackingMode: [implementation]
 
(void) - setBackgroundColor: [implementation]
 
(void) - notifySemanticsEnabledChanged [implementation]
 
(std::weak_ptr< flutter::AccessibilityBridgeMac >) - accessibilityBridge [implementation]
 
(void) - setUpWithEngine:viewIdentifier:threadSynchronizer: [implementation]
 
(void) - detachFromEngine [implementation]
 
(void) - updateSemantics: [implementation]
 
(BOOL- launchEngine [implementation]
 
(void) - listenForMetaModifiedKeyUpEvents [implementation]
 
(void) - configureTrackingArea [implementation]
 
(void) - initializeKeyboard [implementation]
 
(void) - dispatchMouseEvent: [implementation]
 
(void) - dispatchGestureEvent: [implementation]
 
(void) - dispatchMouseEvent:phase: [implementation]
 
(void) - onAccessibilityStatusChanged: [implementation]
 
(std::shared_ptr< flutter::AccessibilityBridgeMac >) - createAccessibilityBridgeWithEngine: [implementation]
 
(nonnull FlutterView *) - createFlutterViewWithMTLDevice:commandQueue: [implementation]
 
(void) - onKeyboardLayoutChanged [implementation]
 
(void) - viewDidReshape: [implementation]
 
(BOOL- viewShouldAcceptFirstResponder: [implementation]
 
(void) - sendKeyEvent:callback:userData: [implementation]
 
(id< FlutterBinaryMessenger >) - getBinaryMessenger [implementation]
 
(BOOL- onTextInputKeyEvent: [implementation]
 
(void) - subscribeToKeyboardLayoutChange: [implementation]
 
(LayoutClue) - lookUpLayoutForKeyCode:shift: [implementation]
 
(nonnull NSDictionary *) - getPressedState [implementation]
 
(BOOL- acceptsFirstResponder [implementation]
 
(void) - keyDown: [implementation]
 
(void) - keyUp: [implementation]
 
(void) - flagsChanged: [implementation]
 
(void) - mouseEntered: [implementation]
 
(void) - mouseExited: [implementation]
 
(void) - mouseDown: [implementation]
 
(void) - mouseUp: [implementation]
 
(void) - mouseDragged: [implementation]
 
(void) - rightMouseDown: [implementation]
 
(void) - rightMouseUp: [implementation]
 
(void) - rightMouseDragged: [implementation]
 
(void) - otherMouseDown: [implementation]
 
(void) - otherMouseUp: [implementation]
 
(void) - otherMouseDragged: [implementation]
 
(void) - mouseMoved: [implementation]
 
(void) - scrollWheel: [implementation]
 
(void) - magnifyWithEvent: [implementation]
 
(void) - rotateWithEvent: [implementation]
 
(void) - swipeWithEvent: [implementation]
 
(void) - touchesBeganWithEvent: [implementation]
 
(UIHoverGestureRecognizer *hoverGestureRecognizer) - API_AVAILABLE [implementation]
 
(UIPanGestureRecognizer *discreteScrollingPanGestureRecognizer) - API_AVAILABLE [implementation]
 
(UIPanGestureRecognizer *continuousScrollingPanGestureRecognizer) - API_AVAILABLE [implementation]
 
(UIPinchGestureRecognizer *pinchGestureRecognizer) - API_AVAILABLE [implementation]
 
(UIRotationGestureRecognizer *rotationGestureRecognizer) - API_AVAILABLE [implementation]
 
(int64_t) - registerTexture:
 
(void) - textureFrameAvailable:
 
(void) - unregisterTexture:
 
- Instance Methods inherited from <FlutterPluginRegistry>
(nullable NSObject< FlutterPluginRegistrar > *) - registrarForPlugin:
 
(BOOL- hasPlugin:
 
(nullable NSObject *) - valuePublishedByPlugin:
 
(nonnull id< FlutterPluginRegistrar >) - registrarForPlugin:
 
(nullable NSObject *) - valuePublishedByPlugin:
 
- Instance Methods inherited from <FlutterBinaryMessenger>
(NSObject< FlutterTaskQueue > *) - makeBackgroundTaskQueue
 TODO(gaaclarke): Remove optional when macos supports Background Platform Channels. More...
 
(FlutterBinaryMessengerConnection- setMessageHandlerOnChannel:binaryMessageHandler:taskQueue:
 
(void) - sendOnChannel:message:
 
(void) - sendOnChannel:message:binaryReply:
 
(FlutterBinaryMessengerConnection- setMessageHandlerOnChannel:binaryMessageHandler:
 
(void) - cleanUpConnection:
 
- Instance Methods inherited from <FlutterViewResponder>
(void) - touchesBegan:withEvent:
 
(void) - touchesMoved:withEvent:
 
(void) - touchesEnded:withEvent:
 
(void) - touchesCancelled:withEvent:
 
(void) - touchesEstimatedPropertiesUpdated:
 
(void) - forceTouchesCancelled:
 
- Instance Methods inherited from <FlutterKeyboardViewDelegate>
(void) - sendKeyEvent:callback:userData:
 
(nonnull id< FlutterBinaryMessenger >) - getBinaryMessenger
 
(BOOL- onTextInputKeyEvent:
 
(void) - subscribeToKeyboardLayoutChange:
 
(flutter::LayoutClue- lookUpLayoutForKeyCode:shift:
 
(nonnull NSDictionary *) - getPressedState
 

Class Methods

(BOOL+ isUIAccessibilityIsVoiceOverRunning
 
(static UIView *) + GetViewOrPlaceholder [implementation]
 
(static void) + SendFakeTouchEvent [implementation]
 
(BOOL+ automaticallyNotifiesObserversOfDisplayingFlutterUI [implementation]
 
(static flutter::PointerData::Change+ PointerDataChangeFromUITouchPhase [implementation]
 
(static flutter::PointerData::DeviceKind+ DeviceKindFromTouchType [implementation]
 
(BOOL+ accessibilityIsOnOffSwitchLabelsEnabled [implementation]
 
(static void) + CommonInit [implementation]
 
(static NSData *) + CurrentKeyboardLayoutData [implementation]
 

Properties

BOOL displayingFlutterUI
 
UIView * splashScreenView
 
BOOL viewOpaque
 
FlutterEngineengine
 
NSObject< FlutterBinaryMessenger > * binaryMessenger
 
BOOL engineAllowHeadlessExecution
 
FlutterMouseTrackingMode mouseTrackingMode
 
FlutterViewIdentifier viewIdentifier
 
NSColor * backgroundColor
 
BOOL isHomeIndicatorHidden [implementation]
 
BOOL isPresentingViewControllerAnimating [implementation]
 
BOOL shouldIgnoreViewportMetricsUpdatesDuringRotation [implementation]
 
CGFloat targetViewInsetBottom [implementation]
 
CGFloat originalViewInsetBottom [implementation]
 
VSyncClientkeyboardAnimationVSyncClient [implementation]
 
BOOL keyboardAnimationIsShowing [implementation]
 
fml::TimePoint keyboardAnimationStartTime [implementation]
 
BOOL isKeyboardInOrTransitioningFromBackground [implementation]
 
VSyncClienttouchRateCorrectionVSyncClient [implementation]
 
BOOL isVoiceOverRunning [implementation]
 
FlutterKeyboardManagerkeyboardManager [implementation]
 
NSTrackingArea * trackingArea [implementation]
 
MouseState mouseState [implementation]
 
id keyUpMonitor [implementation]
 
KeyboardLayoutNotifier keyboardLayoutNotifier [implementation]
 
NSData * keyboardLayoutData [implementation]
 
FlutterViewflutterView [implementation]
 
FlutterTextInputPlugintextInputPlugin [implementation]
 
- Properties inherited from <FlutterViewResponder>
UIView * view
 
- Properties inherited from <FlutterKeyboardViewDelegate>
NSResponder * nextResponder
 

Detailed Description

A UIViewController implementation for Flutter views.

Dart execution, channel communication, texture registration, and plugin registration are all handled by FlutterEngine. Calls on this class to those members all proxy through to the FlutterEngine attached FlutterViewController.

A FlutterViewController can be initialized either with an already-running FlutterEngine via the initWithEngine: initializer, or it can be initialized with a FlutterDartProject that will be used to implicitly spin up a new FlutterEngine. Creating a FlutterEngine before showing a FlutterViewController can be used to pre-initialize the Dart VM and to prepare the isolate in order to reduce the latency to the first rendered frame. See https://flutter.dev/docs/development/add-to-app/performance for more details on loading latency.

Holding a FlutterEngine independently of FlutterViewControllers can also be used to not to lose Dart-related state and asynchronous tasks when navigating back and forth between a FlutterViewController and other UIViewControllers.

Controls a view that displays Flutter content and manages input.

A FlutterViewController works with a FlutterEngine. Upon creation, the view controller is always added to an engine, either a given engine, or it implicitly creates an engine and add itself to that engine.

The FlutterEngine assigns each view controller attached to it a unique ID. Each view controller corresponds to a view, and the ID is used by the framework to specify which view to operate.

A FlutterViewController can also be unattached to an engine after it is manually unset from the engine, or transiently during the initialization process. An unattached view controller is invalid. Whether the view controller is attached can be queried using attached (FlutterViewController).

The FlutterViewController strongly references the FlutterEngine, while the engine weakly the view controller. When a FlutterViewController is deallocated, it automatically removes itself from its attached engine. When a FlutterEngine has no FlutterViewControllers attached, it might shut down itself or not depending on its configuration.

Definition at line 56 of file FlutterViewController.h.

Method Documentation

◆ acceptsFirstResponder

- (BOOL) acceptsFirstResponder
implementation

Definition at line 891 of file FlutterViewController.mm.

961 {
962 return YES;
963}

◆ accessibilityBridge

- (weak_ptr<) flutter:
implementation

Definition at line 338 of file FlutterViewController.mm.

496 {
497 return _bridge;
498}
std::shared_ptr< flutter::AccessibilityBridgeMac > _bridge

◆ accessibilityFlags

- (int32_t) accessibilityFlags
implementation

Definition at line 1112 of file FlutterViewController.mm.

2086 {
2087 int32_t flags = 0;
2088 if (UIAccessibilityIsInvertColorsEnabled()) {
2090 }
2091 if (UIAccessibilityIsReduceMotionEnabled()) {
2093 }
2094 if (UIAccessibilityIsBoldTextEnabled()) {
2095 flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kBoldText);
2096 }
2097 if (UIAccessibilityDarkerSystemColorsEnabled()) {
2099 }
2102 }
2103
2104 return flags;
2105}
FlutterSemanticsFlag flags

◆ accessibilityIsOnOffSwitchLabelsEnabled

+ (BOOL) accessibilityIsOnOffSwitchLabelsEnabled
implementation

Definition at line 1112 of file FlutterViewController.mm.

2116 {
2117 if (@available(iOS 13, *)) {
2118 return UIAccessibilityIsOnOffSwitchLabelsEnabled();
2119 } else {
2120 return NO;
2121 }
2122}

◆ accessibilityPerformEscape

- (BOOL) accessibilityPerformEscape
implementation

Definition at line 1112 of file FlutterViewController.mm.

2107 {
2108 FlutterMethodChannel* navigationChannel = [_engine.get() navigationChannel];
2109 if (navigationChannel) {
2110 [self popRoute];
2111 return YES;
2112 }
2113 return NO;
2114}

◆ addInternalPlugins

- (void) addInternalPlugins
implementation

Creates and registers plugins used by this view controller.

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

814 {
815 self.keyboardManager = [[[FlutterKeyboardManager alloc] init] autorelease];
816 fml::WeakNSObject<FlutterViewController> weakSelf = [self getWeakNSObject];
817 FlutterSendKeyEvent sendEvent =
818 ^(const FlutterKeyEvent& event, FlutterKeyEventCallback callback, void* userData) {
819 if (weakSelf) {
820 [weakSelf.get()->_engine.get() sendKeyEvent:event callback:callback userData:userData];
821 }
822 };
823 [self.keyboardManager addPrimaryResponder:[[[FlutterEmbedderKeyResponder alloc]
824 initWithSendEvent:sendEvent] autorelease]];
826 initWithChannel:self.engine.keyEventChannel] autorelease];
827 [self.keyboardManager addPrimaryResponder:responder];
828 FlutterTextInputPlugin* textInputPlugin = self.engine.textInputPlugin;
829 if (textInputPlugin != nil) {
830 [self.keyboardManager addSecondaryResponder:textInputPlugin];
831 }
832 if ([_engine.get() viewController] == self) {
833 [textInputPlugin setUpIndirectScribbleInteraction:self];
834 }
835}
void(* FlutterKeyEventCallback)(bool, void *)
Definition: embedder.h:1155
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
void setUpIndirectScribbleInteraction:(id< FlutterViewResponder > viewResponder)
FlutterTextInputPlugin * textInputPlugin
void(^ FlutterSendKeyEvent)(const FlutterKeyEvent &, _Nullable FlutterKeyEventCallback, void *_Nullable)
FlutterViewController * viewController
fml::scoped_nsobject< FlutterEngine > _engine

◆ API_AVAILABLE [1/5]

- (UIHoverGestureRecognizer *hoverGestureRecognizer) API_AVAILABLE (ios(13.4)) 
implementation

◆ API_AVAILABLE [2/5]

- (UIPanGestureRecognizer *discreteScrollingPanGestureRecognizer) API_AVAILABLE (ios(13.4)) 
implementation

◆ API_AVAILABLE [3/5]

- (UIPanGestureRecognizer *continuousScrollingPanGestureRecognizer) API_AVAILABLE (ios(13.4)) 
implementation

◆ API_AVAILABLE [4/5]

- (UIPinchGestureRecognizer *pinchGestureRecognizer) API_AVAILABLE (ios(13.4)) 
implementation

◆ API_AVAILABLE [5/5]

- (UIRotationGestureRecognizer *rotationGestureRecognizer) API_AVAILABLE (ios(13.4)) 
implementation

◆ applicationBecameActive:

- (void) applicationBecameActive: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

995 :(NSNotification*)notification {
996 TRACE_EVENT0("flutter", "applicationBecameActive");
997 [self appOrSceneBecameActive];
998}
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131

◆ applicationDidEnterBackground:

- (void) applicationDidEnterBackground: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1009 :(NSNotification*)notification {
1010 TRACE_EVENT0("flutter", "applicationDidEnterBackground");
1011 [self appOrSceneDidEnterBackground];
1012}

◆ applicationWillEnterForeground:

- (void) applicationWillEnterForeground: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1014 :(NSNotification*)notification {
1015 TRACE_EVENT0("flutter", "applicationWillEnterForeground");
1016 [self appOrSceneWillEnterForeground];
1017}

◆ applicationWillResignActive:

- (void) applicationWillResignActive: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1000 :(NSNotification*)notification {
1001 TRACE_EVENT0("flutter", "applicationWillResignActive");
1002 [self appOrSceneWillResignActive];
1003}

◆ applicationWillTerminate:

- (void) applicationWillTerminate: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1005 :(NSNotification*)notification {
1006 [self appOrSceneWillTerminate];
1007}

◆ appOrSceneBecameActive

- (void) appOrSceneBecameActive
implementation

Definition at line 527 of file FlutterViewController.mm.

1047 {
1048 self.isKeyboardInOrTransitioningFromBackground = NO;
1050 [self surfaceUpdated:YES];
1051 }
1052 [self performSelector:@selector(goToApplicationLifecycle:)
1053 withObject:@"AppLifecycleState.resumed"
1054 afterDelay:0.0f];
1055}
flutter::ViewportMetrics _viewportMetrics

◆ appOrSceneDidEnterBackground

- (void) appOrSceneDidEnterBackground
implementation

Definition at line 527 of file FlutterViewController.mm.

1069 {
1070 self.isKeyboardInOrTransitioningFromBackground = YES;
1071 [self surfaceUpdated:NO];
1072 [self goToApplicationLifecycle:@"AppLifecycleState.paused"];
1073}

◆ appOrSceneWillEnterForeground

- (void) appOrSceneWillEnterForeground
implementation

Definition at line 527 of file FlutterViewController.mm.

1075 {
1076 [self goToApplicationLifecycle:@"AppLifecycleState.inactive"];
1077}

◆ appOrSceneWillResignActive

- (void) appOrSceneWillResignActive
implementation

Definition at line 527 of file FlutterViewController.mm.

1057 {
1058 [NSObject cancelPreviousPerformRequestsWithTarget:self
1059 selector:@selector(goToApplicationLifecycle:)
1060 object:@"AppLifecycleState.resumed"];
1061 [self goToApplicationLifecycle:@"AppLifecycleState.inactive"];
1062}

◆ appOrSceneWillTerminate

- (void) appOrSceneWillTerminate
implementation

Definition at line 527 of file FlutterViewController.mm.

1064 {
1065 [self goToApplicationLifecycle:@"AppLifecycleState.detached"];
1066 [self.engine destroyContext];
1067}

◆ attached

- (BOOL) attached

Return YES if the view controller is attached to an engine.

Definition at line 338 of file FlutterViewController.mm.

517 {
518 return _engine != nil;
519}

◆ automaticallyNotifiesObserversOfDisplayingFlutterUI

+ (BOOL) automaticallyNotifiesObserversOfDisplayingFlutterUI
implementation

Definition at line 527 of file FlutterViewController.mm.

574 {
575 return NO;
576}

◆ awakeFromNib

- (void) awakeFromNib
implementation

Definition at line 152 of file FlutterViewController.mm.

223 {
224 [super awakeFromNib];
225 if (!_engine) {
226 [self sharedSetupWithProject:nil initialRoute:nil];
227 }
228}

◆ brightnessMode

- (NSString *) brightnessMode
implementation

Definition at line 1112 of file FlutterViewController.mm.

2229 {
2230 if (@available(iOS 13, *)) {
2231 UIUserInterfaceStyle style = self.traitCollection.userInterfaceStyle;
2232
2233 if (style == UIUserInterfaceStyleDark) {
2234 return @"dark";
2235 } else {
2236 return @"light";
2237 }
2238 } else {
2239 return @"light";
2240 }
2241}

◆ calculateKeyboardAttachMode:

- (FlutterKeyboardMode) calculateKeyboardAttachMode: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1597 :(NSNotification*)notification {
1598 // There are multiple types of keyboard: docked, undocked, split, split docked,
1599 // floating, expanded shortcuts bar, minimized shortcuts bar. This function will categorize
1600 // the keyboard as one of the following modes: docked, floating, or hidden.
1601 // Docked mode includes docked, split docked, expanded shortcuts bar (when opening via click),
1602 // and minimized shortcuts bar (when opened via click).
1603 // Floating includes undocked, split, floating, expanded shortcuts bar (when dragged and dropped),
1604 // and minimized shortcuts bar (when dragged and dropped).
1605 NSDictionary* info = notification.userInfo;
1606 CGRect keyboardFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
1607
1608 if (notification.name == UIKeyboardWillHideNotification) {
1609 return FlutterKeyboardModeHidden;
1610 }
1611
1612 // If keyboard's dimensions and position are all zeroes, that means it's a Minimized/Expanded
1613 // Shortcuts Bar that has been dropped after dragging, which we categorize as floating.
1614 if (CGRectEqualToRect(keyboardFrame, CGRectZero)) {
1615 return FlutterKeyboardModeFloating;
1616 }
1617 // If keyboard's width or height are 0, it's hidden.
1618 if (CGRectIsEmpty(keyboardFrame)) {
1619 return FlutterKeyboardModeHidden;
1620 }
1621
1622 CGRect screenRect = [self flutterScreenIfViewLoaded].bounds;
1623 CGRect adjustedKeyboardFrame = keyboardFrame;
1624 adjustedKeyboardFrame.origin.y += [self calculateMultitaskingAdjustment:screenRect
1625 keyboardFrame:keyboardFrame];
1626
1627 // If the keyboard is partially or fully showing within the screen, it's either docked or
1628 // floating. Sometimes with custom keyboard extensions, the keyboard's position may be off by a
1629 // small decimal amount (which is why CGRectIntersectRect can't be used). Round to compare.
1630 CGRect intersection = CGRectIntersection(adjustedKeyboardFrame, screenRect);
1631 CGFloat intersectionHeight = CGRectGetHeight(intersection);
1632 CGFloat intersectionWidth = CGRectGetWidth(intersection);
1633 if (round(intersectionHeight) > 0 && intersectionWidth > 0) {
1634 // If the keyboard is above the bottom of the screen, it's floating.
1635 CGFloat screenHeight = CGRectGetHeight(screenRect);
1636 CGFloat adjustedKeyboardBottom = CGRectGetMaxY(adjustedKeyboardFrame);
1637 if (round(adjustedKeyboardBottom) < screenHeight) {
1638 return FlutterKeyboardModeFloating;
1639 }
1640 return FlutterKeyboardModeDocked;
1641 }
1642 return FlutterKeyboardModeHidden;
1643}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static void round(SkPoint *p)

◆ calculateKeyboardInset:keyboardMode:

- (CGFloat) calculateKeyboardInset: (CGRect)  keyboardFrame
keyboardMode: (NSInteger)  keyboardMode 
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1672 :(CGRect)keyboardFrame keyboardMode:(NSInteger)keyboardMode {
1673 // Only docked keyboards will have an inset.
1674 if (keyboardMode == FlutterKeyboardModeDocked) {
1675 // Calculate how much of the keyboard intersects with the view.
1676 CGRect viewRectRelativeToScreen =
1677 [self.viewIfLoaded convertRect:self.viewIfLoaded.frame
1678 toCoordinateSpace:[self flutterScreenIfViewLoaded].coordinateSpace];
1679 CGRect intersection = CGRectIntersection(keyboardFrame, viewRectRelativeToScreen);
1680 CGFloat portionOfKeyboardInView = CGRectGetHeight(intersection);
1681
1682 // The keyboard is treated as an inset since we want to effectively reduce the window size by
1683 // the keyboard height. The Dart side will compute a value accounting for the keyboard-consuming
1684 // bottom padding.
1685 CGFloat scale = [self flutterScreenIfViewLoaded].scale;
1686 return portionOfKeyboardInView * scale;
1687 }
1688 return 0;
1689}
const Scalar scale

◆ calculateMultitaskingAdjustment:keyboardFrame:

- (CGFloat) calculateMultitaskingAdjustment: (CGRect)  screenRect
keyboardFrame: (CGRect)  keyboardFrame 
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1645 :(CGRect)screenRect keyboardFrame:(CGRect)keyboardFrame {
1646 // In Slide Over mode, the keyboard's frame does not include the space
1647 // below the app, even though the keyboard may be at the bottom of the screen.
1648 // To handle, shift the Y origin by the amount of space below the app.
1649 if (self.viewIfLoaded.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPad &&
1650 self.viewIfLoaded.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact &&
1651 self.viewIfLoaded.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular) {
1652 CGFloat screenHeight = CGRectGetHeight(screenRect);
1653 CGFloat keyboardBottom = CGRectGetMaxY(keyboardFrame);
1654
1655 // Stage Manager mode will also meet the above parameters, but it does not handle
1656 // the keyboard positioning the same way, so skip if keyboard is at bottom of page.
1657 if (screenHeight == keyboardBottom) {
1658 return 0;
1659 }
1660 CGRect viewRectRelativeToScreen =
1661 [self.viewIfLoaded convertRect:self.viewIfLoaded.frame
1662 toCoordinateSpace:[self flutterScreenIfViewLoaded].coordinateSpace];
1663 CGFloat viewBottom = CGRectGetMaxY(viewRectRelativeToScreen);
1664 CGFloat offset = screenHeight - viewBottom;
1665 if (offset > 0) {
1666 return offset;
1667 }
1668 }
1669 return 0;
1670}
SeparatedVector2 offset

◆ callViewRenderedCallback

- (void) callViewRenderedCallback
implementation

Definition at line 527 of file FlutterViewController.mm.

591 {
592 self.displayingFlutterUI = YES;
593 if (_flutterViewRenderedCallback != nil) {
596 }
597}
fml::ScopedBlock< void(^)(void)> _flutterViewRenderedCallback

◆ cleanUpConnection:

- (void) cleanUpConnection: (FlutterBinaryMessengerConnection connection
implementation

Clears out a channel's message handler if that handler is still the one that was created as a result of setMessageHandlerOnChannel:binaryMessageHandler:.

Parameters
connectionThe result from setMessageHandlerOnChannel:binaryMessageHandler:.

Reimplemented from <FlutterBinaryMessenger>.

Definition at line 1112 of file FlutterViewController.mm.

2341 [_engine.get().binaryMessenger cleanUpConnection:connection];
2342}
int64_t FlutterBinaryMessengerConnection

◆ CommonInit

+ (static void) CommonInit (FlutterViewController *)  controller
(FlutterEngine *)  engine 
implementation

Performs initialization that's common between the different init paths.

Definition at line 338 of file FlutterViewController.mm.

338 {
339 if (!engine) {
340 engine = [[FlutterEngine alloc] initWithName:@"io.flutter"
341 project:controller->_project
342 allowHeadlessExecution:NO];
343 }
344 NSCAssert(controller.engine == nil,
345 @"The FlutterViewController is unexpectedly attached to "
346 @"engine %@ before initialization.",
347 controller.engine);
348 [engine addViewController:controller];
349 NSCAssert(controller.engine != nil,
350 @"The FlutterViewController unexpectedly stays unattached after initialization. "
351 @"In unit tests, this is likely because either the FlutterViewController or "
352 @"the FlutterEngine is mocked. Please subclass these classes instead.",
353 controller.engine, controller.viewIdentifier);
354 controller->_mouseTrackingMode = kFlutterMouseTrackingModeInKeyWindow;
355 controller->_textInputPlugin = [[FlutterTextInputPlugin alloc] initWithViewController:controller];
356 [controller initializeKeyboard];
358 // macOS fires this message when changing IMEs.
359 CFNotificationCenterRef cfCenter = CFNotificationCenterGetDistributedCenter();
360 __weak FlutterViewController* weakSelf = controller;
361 CFNotificationCenterAddObserver(cfCenter, (__bridge void*)weakSelf, OnKeyboardLayoutChanged,
362 kTISNotifySelectedKeyboardInputSourceChanged, NULL,
363 CFNotificationSuspensionBehaviorDeliverImmediately);
364}
void addViewController:(FlutterViewController *controller)
FlutterViewIdentifier viewIdentifier
static void OnKeyboardLayoutChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)

◆ configureTrackingArea

- (void) configureTrackingArea
implementation

Updates |trackingArea| for the current tracking settings, creating it with the correct mode if tracking is enabled, or removing it if not.

Definition at line 338 of file FlutterViewController.mm.

591 {
592 if (!self.viewLoaded) {
593 // The viewDidLoad will call configureTrackingArea again when
594 // the view is actually loaded.
595 return;
596 }
597 if (_mouseTrackingMode != kFlutterMouseTrackingModeNone && self.flutterView) {
598 NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
599 NSTrackingInVisibleRect | NSTrackingEnabledDuringMouseDrag;
600 switch (_mouseTrackingMode) {
601 case kFlutterMouseTrackingModeInKeyWindow:
602 options |= NSTrackingActiveInKeyWindow;
603 break;
604 case kFlutterMouseTrackingModeInActiveApp:
605 options |= NSTrackingActiveInActiveApp;
606 break;
607 case kFlutterMouseTrackingModeAlways:
608 options |= NSTrackingActiveAlways;
609 break;
610 default:
611 NSLog(@"Error: Unrecognized mouse tracking mode: %ld", _mouseTrackingMode);
612 return;
613 }
614 _trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
615 options:options
616 owner:self
617 userInfo:nil];
618 [self.flutterView addTrackingArea:_trackingArea];
619 } else if (_trackingArea) {
620 [self.flutterView removeTrackingArea:_trackingArea];
621 _trackingArea = nil;
622 }
623}
const char * options

◆ continuousScrollEvent:

- (void) continuousScrollEvent: (ios(13.4))  API_AVAILABLE
implementation

Definition at line 1112 of file FlutterViewController.mm.

2534 :(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) {
2535 CGPoint translation = [recognizer translationInView:self.view];
2536 const CGFloat scale = [self flutterScreenIfViewLoaded].scale;
2537
2538 flutter::PointerData pointer_data = [self generatePointerDataAtLastMouseLocation];
2539 pointer_data.device = reinterpret_cast<int64_t>(recognizer);
2541 pointer_data.view_id = self.viewIdentifier;
2542 switch (recognizer.state) {
2543 case UIGestureRecognizerStateBegan:
2545 break;
2546 case UIGestureRecognizerStateChanged:
2548 pointer_data.pan_x = translation.x * scale;
2549 pointer_data.pan_y = translation.y * scale;
2550 pointer_data.pan_delta_x = 0; // Delta will be generated in pointer_data_packet_converter.cc.
2551 pointer_data.pan_delta_y = 0; // Delta will be generated in pointer_data_packet_converter.cc.
2552 pointer_data.scale = 1;
2553 break;
2554 case UIGestureRecognizerStateEnded:
2555 case UIGestureRecognizerStateCancelled:
2557 [[NSProcessInfo processInfo] systemUptime] +
2558 0.1; // Time to lift fingers off trackpad (experimentally determined)
2559 // When running an iOS app on an Apple Silicon Mac, AppKit will send an event
2560 // of type UIEventTypeScroll when trackpad scroll momentum has ended. This event
2561 // is sent whether the momentum ended normally or was cancelled by a trackpad touch.
2562 // Since Flutter scrolling inertia will likely not match the system inertia, we should
2563 // only send a PointerScrollInertiaCancel event for user-initiated cancellations.
2564 // The following (curve-fitted) calculation provides a cutoff point after which any
2565 // UIEventTypeScroll event will likely be from the system instead of the user.
2566 // See https://github.com/flutter/engine/pull/34929.
2568 [[NSProcessInfo processInfo] systemUptime] +
2569 (0.1821 * log(fmax([recognizer velocityInView:self.view].x,
2570 [recognizer velocityInView:self.view].y))) -
2571 0.4825;
2573 break;
2574 default:
2575 // continuousScrollEvent: should only ever be triggered with the above phases
2576 NSAssert(false, @"Trackpad pan event occured with unexpected phase 0x%lx",
2577 (long)recognizer.state);
2578 break;
2579 }
2580
2581 auto packet = std::make_unique<flutter::PointerDataPacket>(1);
2582 packet->SetPointerData(/*i=*/0, pointer_data);
2583 [_engine.get() dispatchPointerDataPacket:std::move(packet)];
2584}
NSTimeInterval _scrollInertiaEventStartline
NSTimeInterval _scrollInertiaEventAppKitDeadline
SK_API sk_sp< SkSurface > ios(9.0)

◆ contrastMode

- (NSString *) contrastMode
implementation

Definition at line 1112 of file FlutterViewController.mm.

2246 {
2247 if (@available(iOS 13, *)) {
2248 UIAccessibilityContrast contrast = self.traitCollection.accessibilityContrast;
2249
2250 if (contrast == UIAccessibilityContrastHigh) {
2251 return @"high";
2252 } else {
2253 return @"normal";
2254 }
2255 } else {
2256 return @"normal";
2257 }
2258}

◆ createAccessibilityBridgeWithEngine:

- (shared_ptr<) flutter: (nonnull FlutterEngine*)  engine
implementation

Reimplemented in AccessibilityBridgeTestViewController.

Provided by category FlutterViewController(TestMethods).

Definition at line 338 of file FlutterViewController.mm.

825 :
826 (nonnull FlutterEngine*)engine {
827 return std::make_shared<flutter::AccessibilityBridgeMac>(engine, self);
828}

◆ createFlutterViewWithMTLDevice:commandQueue:

- (nonnull FlutterView *) createFlutterViewWithMTLDevice: (id<MTLDevice>)  device
commandQueue: (id<MTLCommandQueue>)  commandQueue 
implementation

Reimplemented in TextInputTestViewController.

Provided by category FlutterViewController(TestMethods).

Definition at line 338 of file FlutterViewController.mm.

830 :(id<MTLDevice>)device
831 commandQueue:(id<MTLCommandQueue>)commandQueue {
832 return [[FlutterView alloc] initWithMTLDevice:device
833 commandQueue:commandQueue
834 delegate:self
835 threadSynchronizer:_threadSynchronizer
836 viewIdentifier:_viewIdentifier];
837}
VkDevice device
Definition: main.cc:53

◆ createTouchRateCorrectionVSyncClientIfNeeded

- (void) createTouchRateCorrectionVSyncClientIfNeeded
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1319 {
1320 if (_touchRateCorrectionVSyncClient != nil) {
1321 return;
1322 }
1323
1324 double displayRefreshRate = DisplayLinkManager.displayRefreshRate;
1325 const double epsilon = 0.1;
1326 if (displayRefreshRate < 60.0 + epsilon) { // displayRefreshRate <= 60.0
1327
1328 // If current device's max frame rate is not larger than 60HZ, the delivery rate of touch events
1329 // is the same with render vsync rate. So it is unnecessary to create
1330 // _touchRateCorrectionVSyncClient to correct touch callback's rate.
1331 return;
1332 }
1333
1334 flutter::Shell& shell = [_engine.get() shell];
1335 auto callback = [](std::unique_ptr<flutter::FrameTimingsRecorder> recorder) {
1336 // Do nothing in this block. Just trigger system to callback touch events with correct rate.
1337 };
1338 _touchRateCorrectionVSyncClient =
1339 [[VSyncClient alloc] initWithTaskRunner:shell.GetTaskRunners().GetPlatformTaskRunner()
1340 callback:callback];
1341 _touchRateCorrectionVSyncClient.allowPauseAfterVsync = NO;
1342}
double displayRefreshRate
The display refresh rate used for reporting purposes. The engine does not care about this for frame s...

◆ CurrentKeyboardLayoutData

+ (static NSData *) CurrentKeyboardLayoutData
implementation

Returns the current Unicode layout data (kTISPropertyUnicodeKeyLayoutData).

To use the returned data, convert it to CFDataRef first, finds its bytes with CFDataGetBytePtr, then reinterpret it into const UCKeyboardLayout*. It's returned in NSData* to enable auto reference count.

Definition at line 891 of file FlutterViewController.mm.

891 {
892 TISInputSourceRef source = TISCopyCurrentKeyboardInputSource();
893 CFTypeRef layout_data = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData);
894 if (layout_data == nil) {
895 CFRelease(source);
896 // TISGetInputSourceProperty returns null with Japanese keyboard layout.
897 // Using TISCopyCurrentKeyboardLayoutInputSource to fix NULL return.
898 // https://github.com/microsoft/node-native-keymap/blob/5f0699ded00179410a14c0e1b0e089fe4df8e130/src/keyboard_mac.mm#L91
899 source = TISCopyCurrentKeyboardLayoutInputSource();
900 layout_data = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData);
901 }
902 return (__bridge_transfer NSData*)CFRetain(layout_data);
903}
SkBitmap source
Definition: examples.cpp:28

◆ dealloc

- (void) dealloc
implementation

Definition at line 527 of file FlutterViewController.mm.

969 {
970 // It will be destroyed and invalidate its weak pointers
971 // before any other members are destroyed.
972 _weakFactory.reset();
973
974 [self removeInternalPlugins];
975 [self deregisterNotifications];
976
977 [self invalidateKeyboardAnimationVSyncClient];
978 [self invalidateTouchRateCorrectionVSyncClient];
979 _scrollView.get().delegate = nil;
980 _hoverGestureRecognizer.delegate = nil;
981 [_hoverGestureRecognizer release];
982 _discreteScrollingPanGestureRecognizer.delegate = nil;
983 [_discreteScrollingPanGestureRecognizer release];
984 _continuousScrollingPanGestureRecognizer.delegate = nil;
985 [_continuousScrollingPanGestureRecognizer release];
986 _pinchGestureRecognizer.delegate = nil;
987 [_pinchGestureRecognizer release];
988 _rotationGestureRecognizer.delegate = nil;
989 [_rotationGestureRecognizer release];
990 [super dealloc];
991}
std::unique_ptr< fml::WeakNSObjectFactory< FlutterEngine > > _weakFactory
fml::scoped_nsobject< UIScrollView > _scrollView

◆ decodeRestorableStateWithCoder:

- (void) decodeRestorableStateWithCoder: (NSCoder*)  coder
implementation

Definition at line 1112 of file FlutterViewController.mm.

2626 :(NSCoder*)coder {
2627 NSUInteger restorationDataLength;
2628 const unsigned char* restorationBytes = [coder decodeBytesForKey:kFlutterRestorationStateAppData
2629 returnedLength:&restorationDataLength];
2630 NSData* restorationData = [NSData dataWithBytes:restorationBytes length:restorationDataLength];
2631 [[_engine.get() restorationPlugin] setRestorationData:restorationData];
2632}

◆ deregisterNotifications

- (void) deregisterNotifications
implementation

Definition at line 527 of file FlutterViewController.mm.

962 {
963 [[NSNotificationCenter defaultCenter] postNotificationName:FlutterViewControllerWillDealloc
964 object:self
965 userInfo:nil];
966 [[NSNotificationCenter defaultCenter] removeObserver:self];
967}

◆ detachFromEngine

- (void) detachFromEngine
implementation

Reset the engine and id of this controller.

This method is called by FlutterEngine.

Definition at line 338 of file FlutterViewController.mm.

510 {
511 NSAssert(_engine != nil, @"Not attached to any engine.");
512 [_threadSynchronizer deregisterView:_viewIdentifier];
514 _engine = nil;
515}
FlutterThreadSynchronizer * _threadSynchronizer

◆ DeviceKindFromTouchType

+ (static) PointerData: (UITouch *)  touch
implementation

Definition at line 1112 of file FlutterViewController.mm.

1112 {
1113 switch (touch.type) {
1114 case UITouchTypeDirect:
1115 case UITouchTypeIndirect:
1117 case UITouchTypeStylus:
1119 case UITouchTypeIndirectPointer:
1121 default:
1122 FML_DLOG(INFO) << "Unhandled touch type: " << touch.type;
1123 break;
1124 }
1125
1127}
#define FML_DLOG(severity)
Definition: logging.h:102

◆ discreteScrollEvent:

- (void) discreteScrollEvent: (ios(13.4))  API_AVAILABLE
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

2504 :(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) {
2505 CGPoint translation = [recognizer translationInView:self.view];
2506 const CGFloat scale = [self flutterScreenIfViewLoaded].scale;
2507
2508 translation.x *= scale;
2509 translation.y *= scale;
2510
2511 flutter::PointerData pointer_data = [self generatePointerDataAtLastMouseLocation];
2512 pointer_data.device = reinterpret_cast<int64_t>(recognizer);
2515 pointer_data.scroll_delta_x = (translation.x - _mouseState.last_translation.x);
2516 pointer_data.scroll_delta_y = -(translation.y - _mouseState.last_translation.y);
2517 pointer_data.view_id = self.viewIdentifier;
2518
2519 // The translation reported by UIPanGestureRecognizer is the total translation
2520 // generated by the pan gesture since the gesture began. We need to be able
2521 // to keep track of the last translation value in order to generate the deltaX
2522 // and deltaY coordinates for each subsequent scroll event.
2523 if (recognizer.state != UIGestureRecognizerStateEnded) {
2524 _mouseState.last_translation = translation;
2525 } else {
2526 _mouseState.last_translation = CGPointZero;
2527 }
2528
2529 auto packet = std::make_unique<flutter::PointerDataPacket>(1);
2530 packet->SetPointerData(/*i=*/0, pointer_data);
2531 [_engine.get() dispatchPointerDataPacket:std::move(packet)];
2532}
MouseState _mouseState
double y
double x
SignalKind signal_kind
Definition: pointer_data.h:74

◆ dispatchGestureEvent:

- (void) dispatchGestureEvent: (nonnull NSEvent *)  event
implementation

Calls dispatchMouseEvent:phase: with a phase determined by event.phase.

Definition at line 338 of file FlutterViewController.mm.

638 :(nonnull NSEvent*)event {
639 if (event.phase == NSEventPhaseBegan || event.phase == NSEventPhaseMayBegin) {
640 [self dispatchMouseEvent:event phase:kPanZoomStart];
641 } else if (event.phase == NSEventPhaseChanged) {
642 [self dispatchMouseEvent:event phase:kPanZoomUpdate];
643 } else if (event.phase == NSEventPhaseEnded || event.phase == NSEventPhaseCancelled) {
644 [self dispatchMouseEvent:event phase:kPanZoomEnd];
645 } else if (event.phase == NSEventPhaseNone && event.momentumPhase == NSEventPhaseNone) {
646 [self dispatchMouseEvent:event phase:kHover];
647 } else {
648 // Waiting until the first momentum change event is a workaround for an issue where
649 // touchesBegan: is called unexpectedly while in low power mode within the interval between
650 // momentum start and the first momentum change.
651 if (event.momentumPhase == NSEventPhaseChanged) {
652 _mouseState.last_scroll_momentum_changed_time = event.timestamp;
653 }
654 // Skip momentum update events, the framework will generate scroll momentum.
655 NSAssert(event.momentumPhase != NSEventPhaseNone,
656 @"Received gesture event with unexpected phase");
657 }
658}

◆ dispatchMouseEvent:

- (void) dispatchMouseEvent: (nonnull NSEvent *)  event
implementation

Calls dispatchMouseEvent:phase: with a phase determined by self.mouseState.

mouseState.buttons should be updated before calling this method.

Definition at line 338 of file FlutterViewController.mm.

631 :(nonnull NSEvent*)event {
632 FlutterPointerPhase phase = _mouseState.buttons == 0
633 ? (_mouseState.flutter_state_is_down ? kUp : kHover)
634 : (_mouseState.flutter_state_is_down ? kMove : kDown);
635 [self dispatchMouseEvent:event phase:phase];
636}
@ kMove
SkPath::RawIter returns 1 point.
FlutterPointerPhase
The phase of the pointer event.
Definition: embedder.h:965
@ kHover
The pointer moved while up.
Definition: embedder.h:997
@ kUp
Definition: embedder.h:973
@ kDown
Definition: embedder.h:980

◆ dispatchMouseEvent:phase:

- (void) dispatchMouseEvent: (NSEvent*)  event
phase: (FlutterPointerPhase phase 
implementation

Definition at line 338 of file FlutterViewController.mm.

660 :(NSEvent*)event phase:(FlutterPointerPhase)phase {
661 NSAssert(self.viewLoaded, @"View must be loaded before it handles the mouse event");
662 // There are edge cases where the system will deliver enter out of order relative to other
663 // events (e.g., drag out and back in, release, then click; mouseDown: will be called before
664 // mouseEntered:). Discard those events, since the add will already have been synthesized.
665 if (_mouseState.flutter_state_is_added && phase == kAdd) {
666 return;
667 }
668
669 // Multiple gesture recognizers could be active at once, we can't send multiple kPanZoomStart.
670 // For example: rotation and magnification.
671 if (phase == kPanZoomStart || phase == kPanZoomEnd) {
672 if (event.type == NSEventTypeScrollWheel) {
673 _mouseState.pan_gesture_phase = event.phase;
674 } else if (event.type == NSEventTypeMagnify) {
675 _mouseState.scale_gesture_phase = event.phase;
676 } else if (event.type == NSEventTypeRotate) {
677 _mouseState.rotate_gesture_phase = event.phase;
678 }
679 }
680 if (phase == kPanZoomStart) {
681 if (event.type == NSEventTypeScrollWheel) {
682 // Ensure scroll inertia cancel event is not sent afterwards.
683 _mouseState.last_scroll_momentum_changed_time = 0;
684 }
685 if (_mouseState.flutter_state_is_pan_zoom_started) {
686 // Already started on a previous gesture type
687 return;
688 }
689 _mouseState.flutter_state_is_pan_zoom_started = true;
690 }
691 if (phase == kPanZoomEnd) {
692 if (!_mouseState.flutter_state_is_pan_zoom_started) {
693 // NSEventPhaseCancelled is sometimes received at incorrect times in the state
694 // machine, just ignore it here if it doesn't make sense
695 // (we have no active gesture to cancel).
696 NSAssert(event.phase == NSEventPhaseCancelled,
697 @"Received gesture event with unexpected phase");
698 return;
699 }
700 // NSEventPhase values are powers of two, we can use this to inspect merged phases.
701 NSEventPhase all_gestures_fields = _mouseState.pan_gesture_phase |
702 _mouseState.scale_gesture_phase |
703 _mouseState.rotate_gesture_phase;
704 NSEventPhase active_mask = NSEventPhaseBegan | NSEventPhaseChanged;
705 if ((all_gestures_fields & active_mask) != 0) {
706 // Even though this gesture type ended, a different type is still active.
707 return;
708 }
709 }
710
711 // If a pointer added event hasn't been sent, synthesize one using this event for the basic
712 // information.
713 if (!_mouseState.flutter_state_is_added && phase != kAdd) {
714 // Only the values extracted for use in flutterEvent below matter, the rest are dummy values.
715 NSEvent* addEvent = [NSEvent enterExitEventWithType:NSEventTypeMouseEntered
716 location:event.locationInWindow
717 modifierFlags:0
718 timestamp:event.timestamp
719 windowNumber:event.windowNumber
720 context:nil
721 eventNumber:0
722 trackingNumber:0
723 userData:NULL];
724 [self dispatchMouseEvent:addEvent phase:kAdd];
725 }
726
727 NSPoint locationInView = [self.flutterView convertPoint:event.locationInWindow fromView:nil];
728 NSPoint locationInBackingCoordinates = [self.flutterView convertPointToBacking:locationInView];
731 if (phase == kPanZoomStart || phase == kPanZoomUpdate || phase == kPanZoomEnd) {
734 }
735 FlutterPointerEvent flutterEvent = {
736 .struct_size = sizeof(flutterEvent),
737 .phase = phase,
738 .timestamp = static_cast<size_t>(event.timestamp * USEC_PER_SEC),
739 .x = locationInBackingCoordinates.x,
740 .y = -locationInBackingCoordinates.y, // convertPointToBacking makes this negative.
741 .device = device,
742 .device_kind = deviceKind,
743 // If a click triggered a synthesized kAdd, don't pass the buttons in that event.
744 .buttons = phase == kAdd ? 0 : _mouseState.buttons,
745 .view_id = static_cast<FlutterViewIdentifier>(_viewIdentifier),
746 };
747
748 if (phase == kPanZoomUpdate) {
749 if (event.type == NSEventTypeScrollWheel) {
750 _mouseState.delta_x += event.scrollingDeltaX * self.flutterView.layer.contentsScale;
751 _mouseState.delta_y += event.scrollingDeltaY * self.flutterView.layer.contentsScale;
752 } else if (event.type == NSEventTypeMagnify) {
753 _mouseState.scale += event.magnification;
754 } else if (event.type == NSEventTypeRotate) {
755 _mouseState.rotation += event.rotation * (-M_PI / 180.0);
756 }
757 flutterEvent.pan_x = _mouseState.delta_x;
758 flutterEvent.pan_y = _mouseState.delta_y;
759 // Scale value needs to be normalized to range 0->infinity.
760 flutterEvent.scale = pow(2.0, _mouseState.scale);
761 flutterEvent.rotation = _mouseState.rotation;
762 } else if (phase == kPanZoomEnd) {
763 _mouseState.GestureReset();
764 } else if (phase != kPanZoomStart && event.type == NSEventTypeScrollWheel) {
766
767 double pixelsPerLine = 1.0;
768 if (!event.hasPreciseScrollingDeltas) {
769 // The scrollingDelta needs to be multiplied by the line height.
770 // CGEventSourceGetPixelsPerLine() will return 10, which will result in
771 // scrolling that is noticeably slower than in other applications.
772 // Using 40.0 as the multiplier to match Chromium.
773 // See https://source.chromium.org/chromium/chromium/src/+/main:ui/events/cocoa/events_mac.mm
774 pixelsPerLine = 40.0;
775 }
776 double scaleFactor = self.flutterView.layer.contentsScale;
777 // When mouse input is received while shift is pressed (regardless of
778 // any other pressed keys), Mac automatically flips the axis. Other
779 // platforms do not do this, so we flip it back to normalize the input
780 // received by the framework. The keyboard+mouse-scroll mechanism is exposed
781 // in the ScrollBehavior of the framework so developers can customize the
782 // behavior.
783 // At time of change, Apple does not expose any other type of API or signal
784 // that the X/Y axes have been flipped.
785 double scaledDeltaX = -event.scrollingDeltaX * pixelsPerLine * scaleFactor;
786 double scaledDeltaY = -event.scrollingDeltaY * pixelsPerLine * scaleFactor;
787 if (event.modifierFlags & NSShiftKeyMask) {
788 flutterEvent.scroll_delta_x = scaledDeltaY;
789 flutterEvent.scroll_delta_y = scaledDeltaX;
790 } else {
791 flutterEvent.scroll_delta_x = scaledDeltaX;
792 flutterEvent.scroll_delta_y = scaledDeltaY;
793 }
794 }
795
796 [_keyboardManager syncModifiersIfNeeded:event.modifierFlags timestamp:event.timestamp];
797 [_engine sendPointerEvent:flutterEvent];
798
799 // Update tracking of state as reported to Flutter.
800 if (phase == kDown) {
801 _mouseState.flutter_state_is_down = true;
802 } else if (phase == kUp) {
803 _mouseState.flutter_state_is_down = false;
804 if (_mouseState.has_pending_exit) {
805 [self dispatchMouseEvent:event phase:kRemove];
806 _mouseState.has_pending_exit = false;
807 }
808 } else if (phase == kAdd) {
809 _mouseState.flutter_state_is_added = true;
810 } else if (phase == kRemove) {
811 _mouseState.Reset();
812 }
813}
#define M_PI
@ kPanZoomUpdate
The pan/zoom updated.
Definition: embedder.h:1001
@ kPanZoomStart
A pan/zoom started on this pointer.
Definition: embedder.h:999
@ kRemove
Definition: embedder.h:995
@ kAdd
Definition: embedder.h:990
@ kPanZoomEnd
The pan/zoom ended.
Definition: embedder.h:1003
@ kFlutterPointerSignalKindScroll
Definition: embedder.h:1029
FlutterPointerDeviceKind
The device type that created a pointer event.
Definition: embedder.h:1007
@ kFlutterPointerDeviceKindTrackpad
Definition: embedder.h:1011
@ kFlutterPointerDeviceKindMouse
Definition: embedder.h:1008
static constexpr int32_t kPointerPanZoomDeviceId
Definition: fl_engine.cc:36
static constexpr int32_t kMousePointerDeviceId
Definition: fl_engine.cc:35
double scroll_delta_y
The y offset of the scroll in physical pixels.
Definition: embedder.h:1053
size_t struct_size
The size of this struct. Must be sizeof(FlutterPointerEvent).
Definition: embedder.h:1036
double scale
The scale of the pan/zoom, where 1.0 is the initial scale.
Definition: embedder.h:1067
FlutterPointerSignalKind signal_kind
Definition: embedder.h:1049
double rotation
The rotation of the pan/zoom in radians, where 0.0 is the initial angle.
Definition: embedder.h:1069
double scroll_delta_x
The x offset of the scroll in physical pixels.
Definition: embedder.h:1051
double pan_x
The x offset of the pan/zoom in physical pixels.
Definition: embedder.h:1063
double pan_y
The y offset of the pan/zoom in physical pixels.
Definition: embedder.h:1065

◆ dispatchTouches:pointerDataChangeOverride:event:

- (void) dispatchTouches: (NSSet*)  touches
pointerDataChangeOverride: (flutter::PointerData::Change*)  overridden_change
event: (UIEvent*)  event 
implementation

Definition at line 1112 of file FlutterViewController.mm.

1133 :(NSSet*)touches
1134 pointerDataChangeOverride:(flutter::PointerData::Change*)overridden_change
1135 event:(UIEvent*)event {
1136 if (!_engine) {
1137 return;
1138 }
1139
1140 // If the UIApplicationSupportsIndirectInputEvents in Info.plist returns YES, then the platform
1141 // dispatches indirect pointer touches (trackpad clicks) as UITouch with a type of
1142 // UITouchTypeIndirectPointer and different identifiers for each click. They are translated into
1143 // Flutter pointer events with type of kMouse and different device IDs. These devices must be
1144 // terminated with kRemove events when the touches end, otherwise they will keep triggering hover
1145 // events.
1146 //
1147 // If the UIApplicationSupportsIndirectInputEvents in Info.plist returns NO, then the platform
1148 // dispatches indirect pointer touches (trackpad clicks) as UITouch with a type of
1149 // UITouchTypeIndirectPointer and different identifiers for each click. They are translated into
1150 // Flutter pointer events with type of kTouch and different device IDs. Removing these devices is
1151 // neither necessary nor harmful.
1152 //
1153 // Therefore Flutter always removes these devices. The touches_to_remove_count tracks how many
1154 // remove events are needed in this group of touches to properly allocate space for the packet.
1155 // The remove event of a touch is synthesized immediately after its normal event.
1156 //
1157 // See also:
1158 // https://developer.apple.com/documentation/uikit/pointer_interactions?language=objc
1159 // https://developer.apple.com/documentation/bundleresources/information_property_list/uiapplicationsupportsindirectinputevents?language=objc
1160 NSUInteger touches_to_remove_count = 0;
1161 for (UITouch* touch in touches) {
1162 if (touch.phase == UITouchPhaseEnded || touch.phase == UITouchPhaseCancelled) {
1163 touches_to_remove_count++;
1164 }
1165 }
1166
1167 // Activate or pause the correction of delivery frame rate of touch events.
1168 [self triggerTouchRateCorrectionIfNeeded:touches];
1169
1170 const CGFloat scale = [self flutterScreenIfViewLoaded].scale;
1171 auto packet =
1172 std::make_unique<flutter::PointerDataPacket>(touches.count + touches_to_remove_count);
1173
1174 size_t pointer_index = 0;
1175
1176 for (UITouch* touch in touches) {
1177 CGPoint windowCoordinates = [touch locationInView:self.view];
1178
1179 flutter::PointerData pointer_data;
1180 pointer_data.Clear();
1181
1182 constexpr int kMicrosecondsPerSecond = 1000 * 1000;
1183 pointer_data.time_stamp = touch.timestamp * kMicrosecondsPerSecond;
1184
1185 pointer_data.change = overridden_change != nullptr
1186 ? *overridden_change
1187 : PointerDataChangeFromUITouchPhase(touch.phase);
1188
1189 pointer_data.kind = DeviceKindFromTouchType(touch);
1190
1191 pointer_data.device = reinterpret_cast<int64_t>(touch);
1192
1193 pointer_data.view_id = self.viewIdentifier;
1194
1195 // Pointer will be generated in pointer_data_packet_converter.cc.
1196 pointer_data.pointer_identifier = 0;
1197
1198 pointer_data.physical_x = windowCoordinates.x * scale;
1199 pointer_data.physical_y = windowCoordinates.y * scale;
1200
1201 // Delta will be generated in pointer_data_packet_converter.cc.
1202 pointer_data.physical_delta_x = 0.0;
1203 pointer_data.physical_delta_y = 0.0;
1204
1205 NSNumber* deviceKey = [NSNumber numberWithLongLong:pointer_data.device];
1206 // Track touches that began and not yet stopped so we can flush them
1207 // if the view controller goes away.
1208 switch (pointer_data.change) {
1210 [_ongoingTouches addObject:deviceKey];
1211 break;
1214 [_ongoingTouches removeObject:deviceKey];
1215 break;
1218 // We're only tracking starts and stops.
1219 break;
1222 // We don't use kAdd/kRemove.
1223 break;
1227 // We don't send pan/zoom events here
1228 break;
1229 }
1230
1231 // pressure_min is always 0.0
1232 pointer_data.pressure = touch.force;
1233 pointer_data.pressure_max = touch.maximumPossibleForce;
1234 pointer_data.radius_major = touch.majorRadius;
1235 pointer_data.radius_min = touch.majorRadius - touch.majorRadiusTolerance;
1236 pointer_data.radius_max = touch.majorRadius + touch.majorRadiusTolerance;
1237
1238 // iOS Documentation: altitudeAngle
1239 // A value of 0 radians indicates that the stylus is parallel to the surface. The value of
1240 // this property is Pi/2 when the stylus is perpendicular to the surface.
1241 //
1242 // PointerData Documentation: tilt
1243 // The angle of the stylus, in radians in the range:
1244 // 0 <= tilt <= pi/2
1245 // giving the angle of the axis of the stylus, relative to the axis perpendicular to the input
1246 // surface (thus 0.0 indicates the stylus is orthogonal to the plane of the input surface,
1247 // while pi/2 indicates that the stylus is flat on that surface).
1248 //
1249 // Discussion:
1250 // The ranges are the same. Origins are swapped.
1251 pointer_data.tilt = M_PI_2 - touch.altitudeAngle;
1252
1253 // iOS Documentation: azimuthAngleInView:
1254 // With the tip of the stylus touching the screen, the value of this property is 0 radians
1255 // when the cap end of the stylus (that is, the end opposite of the tip) points along the
1256 // positive x axis of the device's screen. The azimuth angle increases as the user swings the
1257 // cap end of the stylus in a clockwise direction around the tip.
1258 //
1259 // PointerData Documentation: orientation
1260 // The angle of the stylus, in radians in the range:
1261 // -pi < orientation <= pi
1262 // giving the angle of the axis of the stylus projected onto the input surface, relative to
1263 // the positive y-axis of that surface (thus 0.0 indicates the stylus, if projected onto that
1264 // surface, would go from the contact point vertically up in the positive y-axis direction, pi
1265 // would indicate that the stylus would go down in the negative y-axis direction; pi/4 would
1266 // indicate that the stylus goes up and to the right, -pi/2 would indicate that the stylus
1267 // goes to the left, etc).
1268 //
1269 // Discussion:
1270 // Sweep direction is the same. Phase of M_PI_2.
1271 pointer_data.orientation = [touch azimuthAngleInView:nil] - M_PI_2;
1272
1273 if (@available(iOS 13.4, *)) {
1274 if (event != nullptr) {
1275 pointer_data.buttons = (((event.buttonMask & UIEventButtonMaskPrimary) > 0)
1277 : 0) |
1278 (((event.buttonMask & UIEventButtonMaskSecondary) > 0)
1280 : 0);
1281 }
1282 }
1283
1284 packet->SetPointerData(pointer_index++, pointer_data);
1285
1286 if (touch.phase == UITouchPhaseEnded || touch.phase == UITouchPhaseCancelled) {
1287 flutter::PointerData remove_pointer_data = pointer_data;
1288 remove_pointer_data.change = flutter::PointerData::Change::kRemove;
1289 packet->SetPointerData(pointer_index++, remove_pointer_data);
1290 }
1291 }
1292
1293 [_engine.get() dispatchPointerDataPacket:std::move(packet)];
1294}
static flutter::PointerData::DeviceKind DeviceKindFromTouchType(UITouch *touch)
static flutter::PointerData::Change PointerDataChangeFromUITouchPhase(UITouchPhase phase)
static constexpr int kMicrosecondsPerSecond
@ kPointerButtonMouseSecondary
Definition: pointer_data.h:15
@ kPointerButtonMousePrimary
Definition: pointer_data.h:14
int64_t pointer_identifier
Definition: pointer_data.h:76

◆ encodeRestorableStateWithCoder:

- (void) encodeRestorableStateWithCoder: (NSCoder*)  coder
implementation

Definition at line 1112 of file FlutterViewController.mm.

2618 :(NSCoder*)coder {
2619 NSData* restorationData = [[_engine.get() restorationPlugin] restorationData];
2620 [coder encodeBytes:(const unsigned char*)restorationData.bytes
2621 length:restorationData.length
2622 forKey:kFlutterRestorationStateAppData];
2623 [super encodeRestorableStateWithCoder:coder];
2624}

◆ ensureViewportMetricsIsCorrect

- (void) ensureViewportMetricsIsCorrect
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1848 {
1849 if (_viewportMetrics.physical_view_inset_bottom != self.targetViewInsetBottom) {
1850 // Make sure the `physical_view_inset_bottom` is the target value.
1851 _viewportMetrics.physical_view_inset_bottom = self.targetViewInsetBottom;
1852 [self updateViewportMetricsIfNeeded];
1853 }
1854}

◆ flagsChanged:

- (void) flagsChanged: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

973 :(NSEvent*)event {
974 [_keyboardManager handleEvent:event];
975}

◆ flushOngoingTouches

- (void) flushOngoingTouches
implementation

Definition at line 527 of file FlutterViewController.mm.

931 {
932 if (_engine && _ongoingTouches.get().count > 0) {
933 auto packet = std::make_unique<flutter::PointerDataPacket>(_ongoingTouches.get().count);
934 size_t pointer_index = 0;
935 // If the view controller is going away, we want to flush cancel all the ongoing
936 // touches to the framework so nothing gets orphaned.
937 for (NSNumber* device in _ongoingTouches.get()) {
938 // Create fake PointerData to balance out each previously started one for the framework.
939 flutter::PointerData pointer_data = [self generatePointerDataForFake];
940
942 pointer_data.device = device.longLongValue;
943 pointer_data.pointer_identifier = 0;
944 pointer_data.view_id = self.viewIdentifier;
945
946 // Anything we put here will be arbitrary since there are no touches.
947 pointer_data.physical_x = 0;
948 pointer_data.physical_y = 0;
949 pointer_data.physical_delta_x = 0.0;
950 pointer_data.physical_delta_y = 0.0;
951 pointer_data.pressure = 1.0;
952 pointer_data.pressure_max = 1.0;
953
954 packet->SetPointerData(pointer_index++, pointer_data);
955 }
956
957 [_ongoingTouches removeAllObjects];
958 [_engine.get() dispatchPointerDataPacket:std::move(packet)];
959 }
960}
fml::scoped_nsobject< NSMutableSet< NSNumber * > > _ongoingTouches

◆ forceTouchesCancelled:

- (void) forceTouchesCancelled: (NSSet *)  touches
implementation

Send touches to the Flutter Engine while forcing the change type to be cancelled. The phases in touches are ignored.

Reimplemented from <FlutterViewResponder>.

Definition at line 1112 of file FlutterViewController.mm.

1312 :(NSSet*)touches {
1314 [self dispatchTouches:touches pointerDataChangeOverride:&cancel event:nullptr];
1315}

◆ generatePointerDataForFake

- (PointerData) FlutterViewController:
implementation

Provided by category FlutterViewController(Tests).

Definition at line 463 of file FlutterViewController.mm.

516 {
517 flutter::PointerData pointer_data;
518 pointer_data.Clear();
520 // `UITouch.timestamp` is defined as seconds since system startup. Synthesized events can get this
521 // time with `NSProcessInfo.systemUptime`. See
522 // https://developer.apple.com/documentation/uikit/uitouch/1618144-timestamp?language=objc
523 pointer_data.time_stamp = [[NSProcessInfo processInfo] systemUptime] * kMicrosecondsPerSecond;
524 return pointer_data;
525}

◆ gestureRecognizer:shouldReceiveEvent:

- (BOOL) gestureRecognizer: (UIGestureRecognizer*)  gestureRecognizer
shouldReceiveEvent: (ios(13.4))  API_AVAILABLE 
implementation

Definition at line 1112 of file FlutterViewController.mm.

2421 :(UIGestureRecognizer*)gestureRecognizer
2422 shouldReceiveEvent:(UIEvent*)event API_AVAILABLE(ios(13.4)) {
2423 if (gestureRecognizer == _continuousScrollingPanGestureRecognizer &&
2424 event.type == UIEventTypeScroll) {
2425 // Events with type UIEventTypeScroll are only received when running on macOS under emulation.
2426 flutter::PointerData pointer_data = [self generatePointerDataAtLastMouseLocation];
2427 pointer_data.device = reinterpret_cast<int64_t>(_continuousScrollingPanGestureRecognizer);
2430 pointer_data.view_id = self.viewIdentifier;
2431
2432 if (event.timestamp < _scrollInertiaEventAppKitDeadline) {
2433 // Only send the event if it occured before the expected natural end of gesture momentum.
2434 // If received after the deadline, it's not likely the event is from a user-initiated cancel.
2435 auto packet = std::make_unique<flutter::PointerDataPacket>(1);
2436 packet->SetPointerData(/*i=*/0, pointer_data);
2437 [_engine.get() dispatchPointerDataPacket:std::move(packet)];
2439 }
2440 }
2441 // This method is also called for UITouches, should return YES to process all touches.
2442 return YES;
2443}

◆ gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:

- (BOOL) gestureRecognizer: (UIGestureRecognizer*)  gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer: (ios(13.4))  API_AVAILABLE 
implementation

Definition at line 1112 of file FlutterViewController.mm.

2415 :(UIGestureRecognizer*)gestureRecognizer
2416 shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
2417 API_AVAILABLE(ios(13.4)) {
2418 return YES;
2419}

◆ getBinaryMessenger

- (id< FlutterBinaryMessenger >) getBinaryMessenger
implementation

Get a binary messenger to send channel messages with.

This method is used to create the key data channel and typically forwards to |FlutterEngine.binaryMessenger|.

Reimplemented from <FlutterKeyboardViewDelegate>.

Definition at line 891 of file FlutterViewController.mm.

911 {
912 return _engine.binaryMessenger;
913}

◆ getPressedState

- (nonnull NSDictionary *) getPressedState
implementation

Returns the keyboard pressed state.

Returns the keyboard pressed state. The dictionary contains one entry per pressed keys, mapping from the logical key to the physical key.

Reimplemented from <FlutterKeyboardViewDelegate>.

Definition at line 891 of file FlutterViewController.mm.

955 {
956 return [_keyboardManager getPressedState];
957}

◆ GetViewOrPlaceholder

+ (static UIView *) GetViewOrPlaceholder (UIView *)  existing_view
implementation

Definition at line 463 of file FlutterViewController.mm.

463 {
464 if (existing_view) {
465 return existing_view;
466 }
467
468 auto placeholder = [[[UIView alloc] init] autorelease];
469
470 placeholder.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
471 if (@available(iOS 13.0, *)) {
472 placeholder.backgroundColor = UIColor.systemBackgroundColor;
473 } else {
474 placeholder.backgroundColor = UIColor.whiteColor;
475 }
476 placeholder.autoresizesSubviews = YES;
477
478 // Only add the label when we know we have failed to enable tracing (and it was necessary).
479 // Otherwise, a spurious warning will be shown in cases where an engine cannot be initialized for
480 // other reasons.
482 auto messageLabel = [[[UILabel alloc] init] autorelease];
483 messageLabel.numberOfLines = 0u;
484 messageLabel.textAlignment = NSTextAlignmentCenter;
485 messageLabel.autoresizingMask =
486 UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
487 messageLabel.text =
488 @"In iOS 14+, debug mode Flutter apps can only be launched from Flutter tooling, "
489 @"IDEs with Flutter plugins or from Xcode.\n\nAlternatively, build in profile or release "
490 @"modes to enable launching from the home screen.";
491 [placeholder addSubview:messageLabel];
492 }
493
494 return placeholder;
495}
TracingResult GetTracingResult()
Returns if a tracing check has been performed and its result. To enable tracing, the Settings object ...
Definition: ptrace_check.h:62

◆ getWeakNSObject

- (WeakNSObject< FlutterViewController >) FlutterViewController:
implementation

Definition at line 152 of file FlutterViewController.mm.

296 {
297 return _weakFactory->GetWeakNSObject();
298}

◆ goToApplicationLifecycle:

- (void) goToApplicationLifecycle: (nonnull NSString*)  state
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1080 :(nonnull NSString*)state {
1081 // Accessing self.view will create the view. Instead use viewIfLoaded
1082 // to check whether the view is attached to window.
1083 if (self.viewIfLoaded.window) {
1084 [[_engine.get() lifecycleChannel] sendMessage:state];
1085 }
1086}
AtkStateType state

◆ handleKeyboardNotification:

- (void) handleKeyboardNotification: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1493 :(NSNotification*)notification {
1494 // See https://flutter.dev/go/ios-keyboard-calculating-inset for more details
1495 // on why notifications are used and how things are calculated.
1496 if ([self shouldIgnoreKeyboardNotification:notification]) {
1497 return;
1498 }
1499
1500 NSDictionary* info = notification.userInfo;
1501 CGRect beginKeyboardFrame = [info[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
1502 CGRect keyboardFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
1503 FlutterKeyboardMode keyboardMode = [self calculateKeyboardAttachMode:notification];
1504 CGFloat calculatedInset = [self calculateKeyboardInset:keyboardFrame keyboardMode:keyboardMode];
1505
1506 // Avoid double triggering startKeyBoardAnimation.
1507 if (self.targetViewInsetBottom == calculatedInset) {
1508 return;
1509 }
1510
1511 self.targetViewInsetBottom = calculatedInset;
1512 NSTimeInterval duration = [info[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
1513
1514 // Flag for simultaneous compounding animation calls.
1515 // This captures animation calls made while the keyboard animation is currently animating. If the
1516 // new animation is in the same direction as the current animation, this flag lets the current
1517 // animation continue with an updated targetViewInsetBottom instead of starting a new keyboard
1518 // animation. This allows for smoother keyboard animation interpolation.
1519 BOOL keyboardWillShow = beginKeyboardFrame.origin.y > keyboardFrame.origin.y;
1520 BOOL keyboardAnimationIsCompounding =
1521 self.keyboardAnimationIsShowing == keyboardWillShow && _keyboardAnimationVSyncClient != nil;
1522
1523 // Mark keyboard as showing or hiding.
1524 self.keyboardAnimationIsShowing = keyboardWillShow;
1525
1526 if (!keyboardAnimationIsCompounding) {
1527 [self startKeyBoardAnimation:duration];
1528 } else if ([self keyboardSpringAnimation]) {
1529 [self keyboardSpringAnimation].toValue = self.targetViewInsetBottom;
1530 }
1531}
double duration
Definition: examples.cpp:30
int BOOL
Definition: windows_types.h:37

◆ handlePressEvent:nextAction:

- (void) handlePressEvent: (FlutterUIPressProxy*)  press
nextAction: (ios(13.4))  API_AVAILABLE 
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1856 :(FlutterUIPressProxy*)press
1857 nextAction:(void (^)())next API_AVAILABLE(ios(13.4)) {
1858 if (@available(iOS 13.4, *)) {
1859 } else {
1860 next();
1861 return;
1862 }
1863 [self.keyboardManager handlePress:press nextAction:next];
1864}
static float next(float f)

◆ hasPlugin:

- (BOOL) hasPlugin: (NSString *)  pluginKey
implementation

Returns whether the specified plugin has been registered.

Parameters
pluginKeyThe unique key identifying the plugin.
Returns
YES if registrarForPlugin has been called with pluginKey.

Reimplemented from <FlutterPluginRegistry>.

Definition at line 1112 of file FlutterViewController.mm.

2380 :(NSString*)pluginKey {
2381 return [_engine.get() hasPlugin:pluginKey];
2382}

◆ hoverEvent:

- (void) hoverEvent: (ios(13.4))  API_AVAILABLE
implementation

Definition at line 1112 of file FlutterViewController.mm.

2445 :(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) {
2446 CGPoint location = [recognizer locationInView:self.view];
2447 CGFloat scale = [self flutterScreenIfViewLoaded].scale;
2448 CGPoint oldLocation = _mouseState.location;
2449 _mouseState.location = {location.x * scale, location.y * scale};
2450
2451 flutter::PointerData pointer_data = [self generatePointerDataAtLastMouseLocation];
2452 pointer_data.device = reinterpret_cast<int64_t>(recognizer);
2454 pointer_data.view_id = self.viewIdentifier;
2455
2456 switch (_hoverGestureRecognizer.state) {
2457 case UIGestureRecognizerStateBegan:
2459 break;
2460 case UIGestureRecognizerStateChanged:
2462 break;
2463 case UIGestureRecognizerStateEnded:
2464 case UIGestureRecognizerStateCancelled:
2466 break;
2467 default:
2468 // Sending kHover is the least harmful thing to do here
2469 // But this state is not expected to ever be reached.
2471 break;
2472 }
2473
2474 NSTimeInterval time = [NSProcessInfo processInfo].systemUptime;
2475 BOOL isRunningOnMac = NO;
2476 if (@available(iOS 14.0, *)) {
2477 // This "stationary pointer" heuristic is not reliable when running within macOS.
2478 // We instead receive a scroll cancel event directly from AppKit.
2479 // See gestureRecognizer:shouldReceiveEvent:
2480 isRunningOnMac = [NSProcessInfo processInfo].iOSAppOnMac;
2481 }
2482 if (!isRunningOnMac && CGPointEqualToPoint(oldLocation, _mouseState.location) &&
2484 // iPadOS reports trackpad movements events with high (sub-pixel) precision. When an event
2485 // is received with the same position as the previous one, it can only be from a finger
2486 // making or breaking contact with the trackpad surface.
2487 auto packet = std::make_unique<flutter::PointerDataPacket>(2);
2488 packet->SetPointerData(/*i=*/0, pointer_data);
2489 flutter::PointerData inertia_cancel = pointer_data;
2490 inertia_cancel.device = reinterpret_cast<int64_t>(_continuousScrollingPanGestureRecognizer);
2493 inertia_cancel.view_id = self.viewIdentifier;
2494 packet->SetPointerData(/*i=*/1, inertia_cancel);
2495 [_engine.get() dispatchPointerDataPacket:std::move(packet)];
2497 } else {
2498 auto packet = std::make_unique<flutter::PointerDataPacket>(1);
2499 packet->SetPointerData(/*i=*/0, pointer_data);
2500 [_engine.get() dispatchPointerDataPacket:std::move(packet)];
2501 }
2502}
static double time(int loops, Benchmark *bench, Target *target)
Definition: nanobench.cpp:394

◆ init

- (instancetype) init
implementation

Reimplemented in ShareViewController.

Definition at line 152 of file FlutterViewController.mm.

230 {
231 return [self initWithProject:nil nibName:nil bundle:nil];
232}

◆ initializeKeyboard

- (void) initializeKeyboard
implementation

Creates and registers keyboard related components.

Definition at line 338 of file FlutterViewController.mm.

625 {
626 // TODO(goderbauer): Seperate keyboard/textinput stuff into ViewController specific and Engine
627 // global parts. Move the global parts to FlutterEngine.
628 _keyboardManager = [[FlutterKeyboardManager alloc] initWithViewDelegate:self];
629}

◆ initWithCoder: [1/2]

- (nonnull instancetype) initWithCoder: (nonnull NSCoder *)  NS_DESIGNATED_INITIALIZER

◆ initWithCoder: [2/2]

- (instancetype) initWithCoder: (NSCoder*)  NS_DESIGNATED_INITIALIZER

Initializer that is called from loading a FlutterViewController from a XIB.

See also: https://developer.apple.com/documentation/foundation/nscoding/1416145-initwithcoder?language=objc

Definition at line 152 of file FlutterViewController.mm.

218 :(NSCoder*)aDecoder {
219 self = [super initWithCoder:aDecoder];
220 return self;
221}

◆ initWithEngine:nibName:bundle: [1/2]

- (instancetype) initWithEngine: (FlutterEngine*)  engine
nibName: (nullable NSString*)  nibName
bundle: (nullable NSBundle*)  NS_DESIGNATED_INITIALIZER 

Initializes this FlutterViewController with the specified FlutterEngine.

The initialized viewcontroller will attach itself to the engine as part of this process.

Parameters
engineThe FlutterEngine instance to attach to. Cannot be nil.
nibNameThe NIB name to initialize this UIViewController with.
nibBundleThe NIB bundle.

Definition at line 152 of file FlutterViewController.mm.

162 nibName:(nullable NSString*)nibName
163 bundle:(nullable NSBundle*)nibBundle {
164 NSAssert(engine != nil, @"Engine is required");
165 self = [super initWithNibName:nibName bundle:nibBundle];
166 if (self) {
167 _viewOpaque = YES;
169 FML_LOG(ERROR) << "The supplied FlutterEngine " << [[engine description] UTF8String]
170 << " is already used with FlutterViewController instance "
171 << [[engine.viewController description] UTF8String]
172 << ". One instance of the FlutterEngine can only be attached to one "
173 "FlutterViewController at a time. Set FlutterEngine.viewController "
174 "to nil before attaching it to another FlutterViewController.";
175 }
176 _engine.reset([engine retain]);
178 _flutterView.reset([[FlutterView alloc] initWithDelegate:_engine
179 opaque:self.isViewOpaque
180 enableWideGamut:engine.project.isWideGamutEnabled]);
181 _weakFactory = std::make_unique<fml::WeakNSObjectFactory<FlutterViewController>>(self);
182 _ongoingTouches.reset([[NSMutableSet alloc] init]);
183
184 [self performCommonViewControllerInitialization];
185 [engine setViewController:self];
186 }
187
188 return self;
189}
#define FML_LOG(severity)
Definition: logging.h:82
FlutterDartProject * project()
void setViewController:(FlutterViewController *viewController)
FlutterViewController * viewController
fml::scoped_nsobject< FlutterView > _flutterView
BOOL _viewOpaque
BOOL _engineNeedsLaunch
#define ERROR(message)
Definition: elf_loader.cc:260

◆ initWithEngine:nibName:bundle: [2/2]

- (instancetype) initWithEngine: (nonnull FlutterEngine*)  engine
nibName: (nullable NSString*)  nibName
bundle: (nullable NSBundle*)  NS_DESIGNATED_INITIALIZER 

Initializes this FlutterViewController with an existing FlutterEngine.

The initialized view controller will add itself to the engine as part of this process.

This initializer is suitable for both the first Flutter view controller and the following ones of the app.

Parameters
engineThe FlutterEngine instance to attach to. Cannot be nil.
nibNameThe NIB name to initialize this controller with.
nibBundleThe NIB bundle.

Definition at line 338 of file FlutterViewController.mm.

391 :(nonnull FlutterEngine*)engine
392 nibName:(nullable NSString*)nibName
393 bundle:(nullable NSBundle*)nibBundle {
394 NSAssert(engine != nil, @"Engine is required");
395
396 self = [super initWithNibName:nibName bundle:nibBundle];
397 if (self) {
398 CommonInit(self, engine);
399 }
400
401 return self;
402}
static void CommonInit(FlutterViewController *controller, FlutterEngine *engine)

◆ initWithNibName:bundle: [1/2]

- (instancetype) initWithNibName: (NSString*)  nibNameOrNil
bundle: (NSBundle*)  nibBundleOrNil 
implementation

Definition at line 152 of file FlutterViewController.mm.

214 :(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil {
215 return [self initWithProject:nil nibName:nil bundle:nil];
216}

◆ initWithNibName:bundle: [2/2]

- (nonnull instancetype) initWithNibName: (nullable NSString *)  nibNameOrNil
bundle: (nullable NSBundle *)  NS_DESIGNATED_INITIALIZER 

◆ initWithProject:

- (instancetype) initWithProject: (nullable FlutterDartProject*)  NS_DESIGNATED_INITIALIZER

Initializes a controller that will run the given project.

In this initializer, this controller creates an engine, and is attached to that engine as the default controller. In this way, this controller can not be set to other engines. This initializer is suitable for the first Flutter view controller of the app. To use the controller with an existing engine, use initWithEngine:nibName:bundle: instead.

Parameters
projectThe project to run in this view controller. If nil, a default FlutterDartProject will be used.

Definition at line 338 of file FlutterViewController.mm.

382 :(nullable FlutterDartProject*)project {
383 self = [super initWithNibName:nil bundle:nil];
384 NSAssert(self, @"Super init cannot be nil");
385
386 _project = project;
387 CommonInit(self, nil);
388 return self;
389}
FlutterDartProject * _project

◆ initWithProject:initialRoute:nibName:bundle: [1/2]

- (instancetype) initWithProject: (FlutterDartProject*)  project
initialRoute: (NSString*)  initialRoute
nibName: (NSString*)  nibName
bundle: (NSBundle*)  nibBundle 
implementation

Definition at line 152 of file FlutterViewController.mm.

202 :(FlutterDartProject*)project
203 initialRoute:(NSString*)initialRoute
204 nibName:(NSString*)nibName
205 bundle:(NSBundle*)nibBundle {
206 self = [super initWithNibName:nibName bundle:nibBundle];
207 if (self) {
208 [self sharedSetupWithProject:project initialRoute:initialRoute];
209 }
210
211 return self;
212}

◆ initWithProject:initialRoute:nibName:bundle: [2/2]

- (instancetype) initWithProject: (nullable FlutterDartProject *)  project
initialRoute: (nullable NSString *)  initialRoute
nibName: (nullable NSString *)  nibName
bundle: (nullable NSBundle *)  NS_DESIGNATED_INITIALIZER 

Initializes a new FlutterViewController and FlutterEngine with the specified FlutterDartProject and initialRoute.

This will implicitly create a new FlutterEngine which is retrievable via the engine property after initialization.

Parameters
projectThe FlutterDartProject to initialize the FlutterEngine with.
initialRouteThe initial Navigator route to load.
nibNameThe NIB name to initialize this UIViewController with.
nibBundleThe NIB bundle.

◆ initWithProject:nibName:bundle: [1/2]

- (instancetype) initWithProject: (FlutterDartProject*)  project
nibName: (NSString*)  nibName
bundle: (NSBundle*)  nibBundle 
implementation

Definition at line 152 of file FlutterViewController.mm.

191 :(FlutterDartProject*)project
192 nibName:(NSString*)nibName
193 bundle:(NSBundle*)nibBundle {
194 self = [super initWithNibName:nibName bundle:nibBundle];
195 if (self) {
196 [self sharedSetupWithProject:project initialRoute:nil];
197 }
198
199 return self;
200}

◆ initWithProject:nibName:bundle: [2/2]

- (instancetype) initWithProject: (nullable FlutterDartProject *)  project
nibName: (nullable NSString *)  nibName
bundle: (nullable NSBundle *)  NS_DESIGNATED_INITIALIZER 

Initializes a new FlutterViewController and FlutterEngine with the specified FlutterDartProject.

This will implicitly create a new FlutterEngine which is retrievable via the engine property after initialization.

Parameters
projectThe FlutterDartProject to initialize the FlutterEngine with.
nibNameThe NIB name to initialize this UIViewController with.
nibBundleThe NIB bundle.

◆ installFirstFrameCallback

- (void) installFirstFrameCallback
implementation

Definition at line 527 of file FlutterViewController.mm.

616 {
617 if (!_engine) {
618 return;
619 }
620
621 fml::WeakPtr<flutter::PlatformViewIOS> weakPlatformView = [_engine.get() platformView];
622 if (!weakPlatformView) {
623 return;
624 }
625
626 // Start on the platform thread.
627 weakPlatformView->SetNextFrameCallback([weakSelf = [self getWeakNSObject],
628 platformTaskRunner = [_engine.get() platformTaskRunner],
629 rasterTaskRunner = [_engine.get() rasterTaskRunner]]() {
630 FML_DCHECK(rasterTaskRunner->RunsTasksOnCurrentThread());
631 // Get callback on raster thread and jump back to platform thread.
632 platformTaskRunner->PostTask([weakSelf]() {
633 if (weakSelf) {
634 fml::scoped_nsobject<FlutterViewController> flutterViewController(
635 [(FlutterViewController*)weakSelf.get() retain]);
636 if (flutterViewController) {
637 if (flutterViewController.get()->_splashScreenView) {
638 [flutterViewController removeSplashScreenView:^{
639 [flutterViewController callViewRenderedCallback];
640 }];
641 } else {
642 [flutterViewController callViewRenderedCallback];
643 }
644 }
645 }
646 });
647 });
648}
fml::WeakNSObject< FlutterViewController > getWeakNSObject()

◆ installSplashScreenViewIfNecessary

- (void) installSplashScreenViewIfNecessary
implementation

Definition at line 527 of file FlutterViewController.mm.

556 {
557 // Show the launch screen view again on top of the FlutterView if available.
558 // This launch screen view will be removed once the first Flutter frame is rendered.
559 if (_splashScreenView && (self.isBeingPresented || self.isMovingToParentViewController)) {
560 [_splashScreenView.get() removeFromSuperview];
562 return;
563 }
564
565 // Use the property getter to initialize the default value.
566 UIView* splashScreenView = self.splashScreenView;
567 if (splashScreenView == nil) {
568 return;
569 }
570 splashScreenView.frame = self.view.bounds;
571 [self.view addSubview:splashScreenView];
572}
void reset(NST *object=Traits::InvalidValue(), scoped_policy::OwnershipPolicy policy=scoped_policy::OwnershipPolicy::kAssume)
fml::scoped_nsobject< UIView > _splashScreenView

◆ invalidateKeyboardAnimationVSyncClient

- (void) invalidateKeyboardAnimationVSyncClient
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1836 {
1837 [_keyboardAnimationVSyncClient invalidate];
1838 [_keyboardAnimationVSyncClient release];
1839 _keyboardAnimationVSyncClient = nil;
1840}

◆ invalidateTouchRateCorrectionVSyncClient

- (void) invalidateTouchRateCorrectionVSyncClient
implementation

Definition at line 1112 of file FlutterViewController.mm.

1368 {
1369 [_touchRateCorrectionVSyncClient invalidate];
1370 [_touchRateCorrectionVSyncClient release];
1371 _touchRateCorrectionVSyncClient = nil;
1372}

◆ ios

- ios
implementation

Definition at line 1112 of file FlutterViewController.mm.

2406 {
2407 flutter::PointerData pointer_data;
2408 pointer_data.Clear();
2409 pointer_data.time_stamp = [[NSProcessInfo processInfo] systemUptime] * kMicrosecondsPerSecond;
2410 pointer_data.physical_x = _mouseState.location.x;
2411 pointer_data.physical_y = _mouseState.location.y;
2412 return pointer_data;
2413}

◆ isAlwaysUse24HourFormat

- (BOOL) isAlwaysUse24HourFormat
implementation

Definition at line 1112 of file FlutterViewController.mm.

2208 {
2209 // iOS does not report its "24-Hour Time" user setting in the API. Instead, it applies
2210 // it automatically to NSDateFormatter when used with [NSLocale currentLocale]. It is
2211 // essential that [NSLocale currentLocale] is used. Any custom locale, even the one
2212 // that's the same as [NSLocale currentLocale] will ignore the 24-hour option (there
2213 // must be some internal field that's not exposed to developers).
2214 //
2215 // Therefore this option behaves differently across Android and iOS. On Android this
2216 // setting is exposed standalone, and can therefore be applied to all locales, whether
2217 // the "current system locale" or a custom one. On iOS it only applies to the current
2218 // system locale. Widget implementors must take this into account in order to provide
2219 // platform-idiomatic behavior in their widgets.
2220 NSString* dateFormat = [NSDateFormatter dateFormatFromTemplate:@"j"
2221 options:0
2222 locale:[NSLocale currentLocale]];
2223 return [dateFormat rangeOfString:@"a"].location == NSNotFound;
2224}

◆ isDispatchingKeyEvent:

- (BOOL) isDispatchingKeyEvent: (NSEvent*)  event
implementation

Definition at line 338 of file FlutterViewController.mm.

404 :(NSEvent*)event {
405 return [_keyboardManager isDispatchingKeyEvent:event];
406}

◆ isKeyboardNotificationForDifferentView:

- (BOOL) isKeyboardNotificationForDifferentView: (NSNotification*)  notification
implementation

Definition at line 1112 of file FlutterViewController.mm.

1581 :(NSNotification*)notification {
1582 NSDictionary* info = notification.userInfo;
1583 // Keyboard notifications related to other apps.
1584 // If the UIKeyboardIsLocalUserInfoKey key doesn't exist (this should not happen after iOS 8),
1585 // proceed as if it was local so that the notification is not ignored.
1586 id isLocal = info[UIKeyboardIsLocalUserInfoKey];
1587 if (isLocal && ![isLocal boolValue]) {
1588 return YES;
1589 }
1590 // Engine’s viewController is not current viewController.
1591 if ([_engine.get() viewController] != self) {
1592 return YES;
1593 }
1594 return NO;
1595}

◆ isPresentingViewController

- (BOOL) isPresentingViewController
implementation

Definition at line 1112 of file FlutterViewController.mm.

2402 {
2403 return self.presentedViewController != nil || self.isPresentingViewControllerAnimating;
2404}

◆ isUIAccessibilityIsVoiceOverRunning

+ (BOOL) isUIAccessibilityIsVoiceOverRunning

A wrapper around UIAccessibilityIsVoiceOverRunning().

As a C function, UIAccessibilityIsVoiceOverRunning() cannot be mocked in testing. Mock this class method to testing features depends on UIAccessibilityIsVoiceOverRunning().

Definition at line 1112 of file FlutterViewController.mm.

2370 {
2371 return UIAccessibilityIsVoiceOverRunning();
2372}

◆ isViewOpaque

- (BOOL) isViewOpaque
implementation

Definition at line 152 of file FlutterViewController.mm.

265 {
266 return _viewOpaque;
267}

◆ keyboardAnimationView

- (UIView *) keyboardAnimationView
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

665 {
667}
T get() const __attribute((ns_returns_not_retained))
fml::scoped_nsobject< UIView > _keyboardAnimationView

◆ keyboardSpringAnimation

- (SpringAnimation *) keyboardSpringAnimation
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

669 {
670 return _keyboardSpringAnimation.get();
671}
fml::scoped_nsobject< SpringAnimation > _keyboardSpringAnimation

◆ keyboardWillBeHidden:

- (void) keyboardWillBeHidden: (NSNotification*)  notification
implementation

Definition at line 1112 of file FlutterViewController.mm.

1486 :(NSNotification*)notification {
1487 // When keyboard is hidden or undocked, this notification will be triggered.
1488 // This notification might not occur when the keyboard is changed from docked to floating, which
1489 // is why we also use UIKeyboardWillChangeFrameNotification.
1490 [self handleKeyboardNotification:notification];
1491}

◆ keyboardWillChangeFrame:

- (void) keyboardWillChangeFrame: (NSNotification*)  notification
implementation

Definition at line 1112 of file FlutterViewController.mm.

1478 :(NSNotification*)notification {
1479 // Immediately prior to a change in keyboard frame, this notification is triggered.
1480 // Sometimes when the keyboard is being hidden or undocked, this notification's keyboard's end
1481 // frame is not yet entirely out of screen, which is why we also use
1482 // UIKeyboardWillHideNotification.
1483 [self handleKeyboardNotification:notification];
1484}

◆ keyboardWillShowNotification:

- (void) keyboardWillShowNotification: (NSNotification*)  notification
implementation

Definition at line 1112 of file FlutterViewController.mm.

1470 :(NSNotification*)notification {
1471 // Immediately prior to a docked keyboard being shown or when a keyboard goes from
1472 // undocked/floating to docked, this notification is triggered. This notification also happens
1473 // when Minimized/Expanded Shortcuts bar is dropped after dragging (the keyboard's end frame will
1474 // be CGRectZero).
1475 [self handleKeyboardNotification:notification];
1476}

◆ keyDown:

- (void) keyDown: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

965 :(NSEvent*)event {
966 [_keyboardManager handleEvent:event];
967}

◆ keyUp:

- (void) keyUp: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

969 :(NSEvent*)event {
970 [_keyboardManager handleEvent:event];
971}

◆ launchEngine

- (BOOL) launchEngine
implementation

Starts running |engine|, including any initial setup.

Definition at line 338 of file FlutterViewController.mm.

556 {
557 if (![_engine runWithEntrypoint:nil]) {
558 return NO;
559 }
560 return YES;
561}

◆ listenForMetaModifiedKeyUpEvents

- (void) listenForMetaModifiedKeyUpEvents
implementation

Definition at line 338 of file FlutterViewController.mm.

567 {
568 if (_keyUpMonitor != nil) {
569 // It is possible for [NSViewController viewWillAppear] to be invoked multiple times
570 // in a row. https://github.com/flutter/flutter/issues/105963
571 return;
572 }
573 FlutterViewController* __weak weakSelf = self;
574 _keyUpMonitor = [NSEvent
575 addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
576 handler:^NSEvent*(NSEvent* event) {
577 // Intercept keyUp only for events triggered on the current
578 // view or textInputPlugin.
579 NSResponder* firstResponder = [[event window] firstResponder];
580 if (weakSelf.viewLoaded && weakSelf.flutterView &&
581 (firstResponder == weakSelf.flutterView ||
582 firstResponder == weakSelf.textInputPlugin) &&
583 ([event modifierFlags] & NSEventModifierFlagCommand) &&
584 ([event type] == NSEventTypeKeyUp)) {
585 [weakSelf keyUp:event];
586 }
587 return event;
588 }];
589}

◆ loadDefaultSplashScreenView

- (BOOL) loadDefaultSplashScreenView

Attempts to set the splashScreenView property from the UILaunchStoryboardName from the main bundle's Info.plist file. This method will not change the value of splashScreenView if it cannot find a default one from a storyboard or nib.

Returns
YES if successful, NO otherwise.

Definition at line 527 of file FlutterViewController.mm.

673 {
674 NSString* launchscreenName =
675 [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UILaunchStoryboardName"];
676 if (launchscreenName == nil) {
677 return NO;
678 }
679 UIView* splashView = [self splashScreenFromStoryboard:launchscreenName];
680 if (!splashView) {
681 splashView = [self splashScreenFromXib:launchscreenName];
682 }
683 if (!splashView) {
684 return NO;
685 }
686 self.splashScreenView = splashView;
687 return YES;
688}

◆ loadView

- (void) loadView
implementation

Definition at line 463 of file FlutterViewController.mm.

497 {
498 self.view = GetViewOrPlaceholder(_flutterView.get());
499 self.view.multipleTouchEnabled = YES;
500 self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
501
502 [self installSplashScreenViewIfNecessary];
503 UIScrollView* scrollView = [[UIScrollView alloc] init];
504 scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
505 // The color shouldn't matter since it is offscreen.
506 scrollView.backgroundColor = UIColor.whiteColor;
507 scrollView.delegate = self;
508 // This is an arbitrary small size.
509 scrollView.contentSize = CGSizeMake(kScrollViewContentSize, kScrollViewContentSize);
510 // This is an arbitrary offset that is not CGPointZero.
511 scrollView.contentOffset = CGPointMake(kScrollViewContentSize, kScrollViewContentSize);
512 [self.view addSubview:scrollView];
513 _scrollView.reset(scrollView);
514}
static UIView * GetViewOrPlaceholder(UIView *existing_view)
static constexpr CGFloat kScrollViewContentSize

◆ lookupKeyForAsset: [1/2]

- (nonnull NSString *) lookupKeyForAsset: (nonnull NSString *)  asset

Returns the file name for the given asset. The returned file name can be used to access the asset in the application's main bundle.

Parameters
assetThe name of the asset. The name can be hierarchical.
Returns
The file name to be used for lookup in the main bundle.

◆ lookupKeyForAsset: [2/2]

- (NSString *) lookupKeyForAsset: (NSString*)  asset

Returns the file name for the given asset. The returned file name can be used to access the asset in the application's main bundle.

Parameters
assetThe name of the asset. The name can be hierarchical.
Returns
The file name to be used for lookup in the main bundle.

Definition at line 1112 of file FlutterViewController.mm.

2358 :(NSString*)asset {
2360}
NSString * lookupKeyForAsset:(NSString *asset)

◆ lookupKeyForAsset:fromPackage: [1/2]

- (nonnull NSString *) lookupKeyForAsset: (nonnull NSString *)  asset
fromPackage: (nonnull NSString *)  package 

Returns the file name for the given asset which originates from the specified package. The returned file name can be used to access the asset in the application's main bundle.

Parameters
assetThe name of the asset. The name can be hierarchical.
packageThe name of the package from which the asset originates.
Returns
The file name to be used for lookup in the main bundle.

◆ lookupKeyForAsset:fromPackage: [2/2]

- (NSString *) lookupKeyForAsset: (NSString*)  asset
fromPackage: (NSString*)  package 

Returns the file name for the given asset which originates from the specified package. The returned file name can be used to access the asset in the application's main bundle.

Parameters
assetThe name of the asset. The name can be hierarchical.
packageThe name of the package from which the asset originates.
Returns
The file name to be used for lookup in the main bundle.

Definition at line 1112 of file FlutterViewController.mm.

2362 :(NSString*)asset fromPackage:(NSString*)package {
2363 return [FlutterDartProject lookupKeyForAsset:asset fromPackage:package];
2364}

◆ lookUpLayoutForKeyCode:shift:

- (LayoutClue) lookUpLayoutForKeyCode: (uint16_t)  keyCode
shift: (BOOL shift 
implementation

Querying the printable result of a key under the given modifier state.

Reimplemented from <FlutterKeyboardViewDelegate>.

Definition at line 891 of file FlutterViewController.mm.

923 :(uint16_t)keyCode shift:(BOOL)shift {
924 if (_keyboardLayoutData == nil) {
925 _keyboardLayoutData = CurrentKeyboardLayoutData();
926 }
927 const UCKeyboardLayout* layout = reinterpret_cast<const UCKeyboardLayout*>(
928 CFDataGetBytePtr((__bridge CFDataRef)_keyboardLayoutData));
929
930 UInt32 deadKeyState = 0;
931 UniCharCount stringLength = 0;
932 UniChar resultChar;
933
934 UInt32 modifierState = ((shift ? shiftKey : 0) >> 8) & 0xFF;
935 UInt32 keyboardType = LMGetKbdLast();
936
937 bool isDeadKey = false;
938 OSStatus status =
939 UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierState, keyboardType,
940 kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &stringLength, &resultChar);
941 // For dead keys, press the same key again to get the printable representation of the key.
942 if (status == noErr && stringLength == 0 && deadKeyState != 0) {
943 isDeadKey = true;
944 status =
945 UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierState, keyboardType,
946 kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &stringLength, &resultChar);
947 }
948
949 if (status == noErr && stringLength == 1 && !std::iscntrl(resultChar)) {
950 return LayoutClue{resultChar, isDeadKey};
951 }
952 return LayoutClue{0, false};
953}
static NSData * CurrentKeyboardLayoutData()
UIKeyboardType keyboardType

◆ magnifyWithEvent:

- (void) magnifyWithEvent: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1043 :(NSEvent*)event {
1044 [self dispatchGestureEvent:event];
1045}

◆ makeBackgroundTaskQueue

- (NSObject< FlutterTaskQueue > *) makeBackgroundTaskQueue
implementation

TODO(gaaclarke): Remove optional when macos supports Background Platform Channels.

Reimplemented from <FlutterBinaryMessenger>.

Definition at line 1112 of file FlutterViewController.mm.

2320 {
2321 return [_engine.get().binaryMessenger makeBackgroundTaskQueue];
2322}

◆ mouseDown:

- (void) mouseDown: (NSEvent*)  event
implementation

Reimplemented in MouseEventFlutterViewController.

Definition at line 891 of file FlutterViewController.mm.

993 :(NSEvent*)event {
995 [self dispatchMouseEvent:event];
996}
@ kFlutterPointerButtonMousePrimary
Definition: embedder.h:1017

◆ mouseDragged:

- (void) mouseDragged: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1003 :(NSEvent*)event {
1004 [self dispatchMouseEvent:event];
1005}

◆ mouseEntered:

- (void) mouseEntered: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

977 :(NSEvent*)event {
978 if (_mouseState.has_pending_exit) {
979 _mouseState.has_pending_exit = false;
980 } else {
981 [self dispatchMouseEvent:event phase:kAdd];
982 }
983}

◆ mouseExited:

- (void) mouseExited: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

985 :(NSEvent*)event {
986 if (_mouseState.buttons != 0) {
987 _mouseState.has_pending_exit = true;
988 return;
989 }
990 [self dispatchMouseEvent:event phase:kRemove];
991}

◆ mouseMoved:

- (void) mouseMoved: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1035 :(NSEvent*)event {
1036 [self dispatchMouseEvent:event];
1037}

◆ mouseUp:

- (void) mouseUp: (NSEvent*)  event
implementation

Reimplemented in MouseEventFlutterViewController.

Definition at line 891 of file FlutterViewController.mm.

998 :(NSEvent*)event {
999 _mouseState.buttons &= ~static_cast<uint64_t>(kFlutterPointerButtonMousePrimary);
1000 [self dispatchMouseEvent:event];
1001}

◆ notifySemanticsEnabledChanged

- (void) notifySemanticsEnabledChanged
implementation

Called by the associated FlutterEngine when FlutterEngine::semanticsEnabled has changed.

Definition at line 338 of file FlutterViewController.mm.

480 {
481 BOOL mySemanticsEnabled = !!_bridge;
482 BOOL newSemanticsEnabled = _engine.semanticsEnabled;
483 if (newSemanticsEnabled == mySemanticsEnabled) {
484 return;
485 }
486 if (newSemanticsEnabled) {
487 _bridge = [self createAccessibilityBridgeWithEngine:_engine];
488 } else {
489 // Remove the accessibility children from flutter view before resetting the bridge.
490 _flutterView.accessibilityChildren = nil;
491 _bridge.reset();
492 }
493 NSAssert(newSemanticsEnabled == !!_bridge, @"Failed to update semantics for the view.");
494}

◆ onAccessibilityStatusChanged: [1/2]

- (void) onAccessibilityStatusChanged: (BOOL enabled
implementation

Definition at line 338 of file FlutterViewController.mm.

815 :(BOOL)enabled {
816 if (!enabled && self.viewLoaded && [_textInputPlugin isFirstResponder]) {
817 // Normally TextInputPlugin, when editing, is child of FlutterViewWrapper.
818 // When accessiblity is enabled the TextInputPlugin gets added as an indirect
819 // child to FlutterTextField. When disabling the plugin needs to be reparented
820 // back.
821 [self.view addSubview:_textInputPlugin];
822 }
823}
fml::scoped_nsobject< FlutterTextInputPlugin > _textInputPlugin

◆ onAccessibilityStatusChanged: [2/2]

- (void) onAccessibilityStatusChanged: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(TestMethods).

Definition at line 1112 of file FlutterViewController.mm.

2063 :(NSNotification*)notification {
2064 if (!_engine) {
2065 return;
2066 }
2067 auto platformView = [_engine.get() platformView];
2068 int32_t flags = [self accessibilityFlags];
2069#if TARGET_OS_SIMULATOR
2070 // There doesn't appear to be any way to determine whether the accessibility
2071 // inspector is enabled on the simulator. We conservatively always turn on the
2072 // accessibility bridge in the simulator, but never assistive technology.
2073 platformView->SetSemanticsEnabled(true);
2074 platformView->SetAccessibilityFeatures(flags);
2075#else
2076 _isVoiceOverRunning = UIAccessibilityIsVoiceOverRunning();
2077 bool enabled = _isVoiceOverRunning || UIAccessibilityIsSwitchControlRunning();
2078 if (enabled) {
2080 }
2081 platformView->SetSemanticsEnabled(enabled || UIAccessibilityIsSpeakScreenEnabled());
2082 platformView->SetAccessibilityFeatures(flags);
2083#endif
2084}

◆ onHideHomeIndicatorNotification:

- (void) onHideHomeIndicatorNotification: (NSNotification*)  notification
implementation

Definition at line 1112 of file FlutterViewController.mm.

2034 :(NSNotification*)notification {
2035 self.isHomeIndicatorHidden = YES;
2036}

◆ onKeyboardLayoutChanged

- (void) onKeyboardLayoutChanged
implementation

Called when the active keyboard input source changes.

Input sources may be simple keyboard layouts, or more complex input methods involving an IME, such as Chinese, Japanese, and Korean.

Definition at line 338 of file FlutterViewController.mm.

839 {
840 _keyboardLayoutData = nil;
841 if (_keyboardLayoutNotifier != nil) {
843 }
844}
flutter::KeyboardLayoutNotifier _keyboardLayoutNotifier

◆ onOrientationPreferencesUpdated:

- (void) onOrientationPreferencesUpdated: (NSNotification*)  notification
implementation

Definition at line 1112 of file FlutterViewController.mm.

1943 :(NSNotification*)notification {
1944 // Notifications may not be on the iOS UI thread
1945 dispatch_async(dispatch_get_main_queue(), ^{
1946 NSDictionary* info = notification.userInfo;
1947
1948 NSNumber* update = info[@(flutter::kOrientationUpdateNotificationKey)];
1949
1950 if (update == nil) {
1951 return;
1952 }
1953 [self performOrientationUpdate:update.unsignedIntegerValue];
1954 });
1955}
Definition: update.py:1

◆ onPreEngineRestart

- (void) onPreEngineRestart

Invoked by the engine right before the engine is restarted.

This should reset states to as if the application has just started. It usually indicates a hot restart (Shift-R in Flutter CLI.)

Definition at line 338 of file FlutterViewController.mm.

476 {
477 [self initializeKeyboard];
478}

◆ onPreferredStatusBarStyleUpdated:

- (void) onPreferredStatusBarStyleUpdated: (NSNotification*)  notification
implementation

Definition at line 1112 of file FlutterViewController.mm.

2266 :(NSNotification*)notification {
2267 // Notifications may not be on the iOS UI thread
2268 dispatch_async(dispatch_get_main_queue(), ^{
2269 NSDictionary* info = notification.userInfo;
2270
2271 NSNumber* update = info[@(flutter::kOverlayStyleUpdateNotificationKey)];
2272
2273 if (update == nil) {
2274 return;
2275 }
2276
2277 NSInteger style = update.integerValue;
2278
2279 if (style != _statusBarStyle) {
2280 _statusBarStyle = static_cast<UIStatusBarStyle>(style);
2281 [self setNeedsStatusBarAppearanceUpdate];
2282 }
2283 });
2284}
UIStatusBarStyle _statusBarStyle

◆ onShowHomeIndicatorNotification:

- (void) onShowHomeIndicatorNotification: (NSNotification*)  notification
implementation

Definition at line 1112 of file FlutterViewController.mm.

2038 :(NSNotification*)notification {
2039 self.isHomeIndicatorHidden = NO;
2040}

◆ onTextInputKeyEvent:

- (BOOL) onTextInputKeyEvent: (nonnull NSEvent *)  event
implementation

Dispatch events that are not handled by the keyboard event handlers to the text input handler.

This method typically forwards events to |TextInputPlugin.handleKeyEvent|.

Reimplemented from <FlutterKeyboardViewDelegate>.

Definition at line 891 of file FlutterViewController.mm.

915 :(nonnull NSEvent*)event {
916 return [_textInputPlugin handleKeyEvent:event];
917}

◆ onUserSettingsChanged:

- (void) onUserSettingsChanged: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

2131 :(NSNotification*)notification {
2132 [[_engine.get() settingsChannel] sendMessage:@{
2133 @"textScaleFactor" : @([self textScaleFactor]),
2134 @"alwaysUse24HourFormat" : @([self isAlwaysUse24HourFormat]),
2135 @"platformBrightness" : [self brightnessMode],
2136 @"platformContrast" : [self contrastMode],
2137 @"nativeSpellCheckServiceDefined" : @true,
2138 @"supportsShowingSystemContextMenu" : @([self supportsShowingSystemContextMenu])
2139 }];
2140}

◆ otherMouseDown:

- (void) otherMouseDown: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1021 :(NSEvent*)event {
1022 _mouseState.buttons |= (1 << event.buttonNumber);
1023 [self dispatchMouseEvent:event];
1024}

◆ otherMouseDragged:

- (void) otherMouseDragged: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1031 :(NSEvent*)event {
1032 [self dispatchMouseEvent:event];
1033}

◆ otherMouseUp:

- (void) otherMouseUp: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1026 :(NSEvent*)event {
1027 _mouseState.buttons &= ~static_cast<uint64_t>(1 << event.buttonNumber);
1028 [self dispatchMouseEvent:event];
1029}

◆ performCommonViewControllerInitialization

- (void) performCommonViewControllerInitialization
implementation

Definition at line 152 of file FlutterViewController.mm.

279 {
280 if (_initialized) {
281 return;
282 }
283
284 _initialized = YES;
285
286 _orientationPreferences = UIInterfaceOrientationMaskAll;
287 _statusBarStyle = UIStatusBarStyleDefault;
288
289 [self setUpNotificationCenterObservers];
290}
BOOL _initialized
UIInterfaceOrientationMask _orientationPreferences

◆ performOrientationUpdate:

- (void) performOrientationUpdate: (UIInterfaceOrientationMask)  new_preferences
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1973 :(UIInterfaceOrientationMask)new_preferences {
1974 if (new_preferences != _orientationPreferences) {
1975 _orientationPreferences = new_preferences;
1976
1977 if (@available(iOS 16.0, *)) {
1978 NSSet<UIScene*>* scenes =
1979#if APPLICATION_EXTENSION_API_ONLY
1980 self.flutterWindowSceneIfViewLoaded
1981 ? [NSSet setWithObject:self.flutterWindowSceneIfViewLoaded]
1982 : [NSSet set];
1983#else
1984 [UIApplication.sharedApplication.connectedScenes
1985 filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(
1986 id scene, NSDictionary* bindings) {
1987 return [scene isKindOfClass:[UIWindowScene class]];
1988 }]];
1989#endif
1990 [self requestGeometryUpdateForWindowScenes:scenes];
1991 } else {
1992 UIInterfaceOrientationMask currentInterfaceOrientation = 0;
1993 if (@available(iOS 13.0, *)) {
1994 UIWindowScene* windowScene = [self flutterWindowSceneIfViewLoaded];
1995 if (!windowScene) {
1996 FML_LOG(WARNING)
1997 << "Accessing the interface orientation when the window scene is unavailable.";
1998 return;
1999 }
2000 currentInterfaceOrientation = 1 << windowScene.interfaceOrientation;
2001 } else {
2002#if APPLICATION_EXTENSION_API_ONLY
2003 FML_LOG(ERROR) << "Application based status bar orentiation update is not supported in "
2004 "app extension. Orientation: "
2005 << currentInterfaceOrientation;
2006#else
2007 currentInterfaceOrientation = 1 << [[UIApplication sharedApplication] statusBarOrientation];
2008#endif
2009 }
2010 if (!(_orientationPreferences & currentInterfaceOrientation)) {
2011 [UIViewController attemptRotationToDeviceOrientation];
2012 // Force orientation switch if the current orientation is not allowed
2013 if (_orientationPreferences & UIInterfaceOrientationMaskPortrait) {
2014 // This is no official API but more like a workaround / hack (using
2015 // key-value coding on a read-only property). This might break in
2016 // the future, but currently it´s the only way to force an orientation change
2017 [[UIDevice currentDevice] setValue:@(UIInterfaceOrientationPortrait)
2018 forKey:@"orientation"];
2019 } else if (_orientationPreferences & UIInterfaceOrientationMaskPortraitUpsideDown) {
2020 [[UIDevice currentDevice] setValue:@(UIInterfaceOrientationPortraitUpsideDown)
2021 forKey:@"orientation"];
2022 } else if (_orientationPreferences & UIInterfaceOrientationMaskLandscapeLeft) {
2023 [[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft)
2024 forKey:@"orientation"];
2025 } else if (_orientationPreferences & UIInterfaceOrientationMaskLandscapeRight) {
2026 [[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeRight)
2027 forKey:@"orientation"];
2028 }
2029 }
2030 }
2031 }
2032}

◆ pinchEvent:

- (void) pinchEvent: (ios(13.4))  API_AVAILABLE
implementation

Definition at line 1112 of file FlutterViewController.mm.

2586 :(UIPinchGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) {
2587 flutter::PointerData pointer_data = [self generatePointerDataAtLastMouseLocation];
2588 pointer_data.device = reinterpret_cast<int64_t>(recognizer);
2590 pointer_data.view_id = self.viewIdentifier;
2591 switch (recognizer.state) {
2592 case UIGestureRecognizerStateBegan:
2594 break;
2595 case UIGestureRecognizerStateChanged:
2597 pointer_data.scale = recognizer.scale;
2598 pointer_data.rotation = _rotationGestureRecognizer.rotation;
2599 break;
2600 case UIGestureRecognizerStateEnded:
2601 case UIGestureRecognizerStateCancelled:
2603 break;
2604 default:
2605 // pinchEvent: should only ever be triggered with the above phases
2606 NSAssert(false, @"Trackpad pinch event occured with unexpected phase 0x%lx",
2607 (long)recognizer.state);
2608 break;
2609 }
2610
2611 auto packet = std::make_unique<flutter::PointerDataPacket>(1);
2612 packet->SetPointerData(/*i=*/0, pointer_data);
2613 [_engine.get() dispatchPointerDataPacket:std::move(packet)];
2614}

◆ platformViewsController

- (shared_ptr<) flutter:
implementation

Definition at line 1112 of file FlutterViewController.mm.

2299 {
2300 return [_engine.get() platformViewsController];
2301}

◆ pluginRegistry

- (id< FlutterPluginRegistry >) pluginRegistry

The FlutterPluginRegistry used by this FlutterViewController.

Definition at line 1112 of file FlutterViewController.mm.

2366 {
2367 return _engine;
2368}

◆ PointerDataChangeFromUITouchPhase

+ (static) PointerData: (UITouchPhase)  phase
implementation

Definition at line 1090 of file FlutterViewController.mm.

1090 {
1091 switch (phase) {
1092 case UITouchPhaseBegan:
1094 case UITouchPhaseMoved:
1095 case UITouchPhaseStationary:
1096 // There is no EVENT_TYPE_POINTER_STATIONARY. So we just pass a move type
1097 // with the same coordinates
1099 case UITouchPhaseEnded:
1101 case UITouchPhaseCancelled:
1103 default:
1104 // TODO(53695): Handle the `UITouchPhaseRegion`... enum values.
1105 FML_DLOG(INFO) << "Unhandled touch phase: " << phase;
1106 break;
1107 }
1108
1110}

◆ popRoute

- (void) popRoute

Instructs the Flutter Navigator (if any) to go back.

Definition at line 152 of file FlutterViewController.mm.

453 {
454 [[_engine.get() navigationChannel] invokeMethod:@"popRoute" arguments:nil];
455}

◆ preferredStatusBarStyle

- (UIStatusBarStyle) preferredStatusBarStyle
implementation

Definition at line 1112 of file FlutterViewController.mm.

2262 {
2263 return _statusBarStyle;
2264}

◆ prefersHomeIndicatorAutoHidden

- (BOOL) prefersHomeIndicatorAutoHidden
implementation

Definition at line 1112 of file FlutterViewController.mm.

2049 {
2050 return self.isHomeIndicatorHidden;
2051}

◆ prefersStatusBarHidden

- (BOOL) prefersStatusBarHidden
implementation

Whether the status bar is preferred hidden.

   This overrides the |UIViewController:prefersStatusBarHidden|.
   This is ignored when `UIViewControllerBasedStatusBarAppearance` in info.plist
   of the app project is `false`.

Reimplemented in NoStatusBarFlutterViewController.

Definition at line 1112 of file FlutterViewController.mm.

2293 {
2294 return _flutterPrefersStatusBarHidden;
2295}

◆ presentViewController:animated:completion:

- (void) presentViewController: (UIViewController*)  viewControllerToPresent
animated: (BOOL flag
completion: (void(^)(void))  completion 
implementation

Definition at line 1112 of file FlutterViewController.mm.

2388 :(UIViewController*)viewControllerToPresent
2389 animated:(BOOL)flag
2390 completion:(void (^)(void))completion {
2391 self.isPresentingViewControllerAnimating = YES;
2392 [super presentViewController:viewControllerToPresent
2393 animated:flag
2394 completion:^{
2395 self.isPresentingViewControllerAnimating = NO;
2396 if (completion) {
2397 completion();
2398 }
2399 }];
2400}
FlutterSemanticsFlag flag

◆ pressesBegan:withEvent:

- (void) pressesBegan: (NSSet<UIPress*>*)  presses
withEvent: (ios(9.0))  API_AVAILABLE 
implementation

Definition at line 1112 of file FlutterViewController.mm.

1881 :(NSSet<UIPress*>*)presses
1882 withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
1883 if (@available(iOS 13.4, *)) {
1884 for (UIPress* press in presses) {
1885 [self handlePressEvent:[[[FlutterUIPressProxy alloc] initWithPress:press
1886 withEvent:event] autorelease]
1887 nextAction:^() {
1888 [super pressesBegan:[NSSet setWithObject:press] withEvent:event];
1889 }];
1890 }
1891 } else {
1892 [super pressesBegan:presses withEvent:event];
1893 }
1894}

◆ pressesCancelled:withEvent:

- (void) pressesCancelled: (NSSet<UIPress*>*)  presses
withEvent: (ios(9.0))  API_AVAILABLE 
implementation

Definition at line 1112 of file FlutterViewController.mm.

1926 :(NSSet<UIPress*>*)presses
1927 withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
1928 if (@available(iOS 13.4, *)) {
1929 for (UIPress* press in presses) {
1930 [self handlePressEvent:[[[FlutterUIPressProxy alloc] initWithPress:press
1931 withEvent:event] autorelease]
1932 nextAction:^() {
1933 [super pressesCancelled:[NSSet setWithObject:press] withEvent:event];
1934 }];
1935 }
1936 } else {
1937 [super pressesCancelled:presses withEvent:event];
1938 }
1939}

◆ pressesChanged:withEvent:

- (void) pressesChanged: (NSSet<UIPress*>*)  presses
withEvent: (ios(9.0))  API_AVAILABLE 
implementation

Definition at line 1112 of file FlutterViewController.mm.

1896 :(NSSet<UIPress*>*)presses
1897 withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
1898 if (@available(iOS 13.4, *)) {
1899 for (UIPress* press in presses) {
1900 [self handlePressEvent:[[[FlutterUIPressProxy alloc] initWithPress:press
1901 withEvent:event] autorelease]
1902 nextAction:^() {
1903 [super pressesChanged:[NSSet setWithObject:press] withEvent:event];
1904 }];
1905 }
1906 } else {
1907 [super pressesChanged:presses withEvent:event];
1908 }
1909}

◆ pressesEnded:withEvent:

- (void) pressesEnded: (NSSet<UIPress*>*)  presses
withEvent: (ios(9.0))  API_AVAILABLE 
implementation

Definition at line 1112 of file FlutterViewController.mm.

1911 :(NSSet<UIPress*>*)presses
1912 withEvent:(UIPressesEvent*)event API_AVAILABLE(ios(9.0)) {
1913 if (@available(iOS 13.4, *)) {
1914 for (UIPress* press in presses) {
1915 [self handlePressEvent:[[[FlutterUIPressProxy alloc] initWithPress:press
1916 withEvent:event] autorelease]
1917 nextAction:^() {
1918 [super pressesEnded:[NSSet setWithObject:press] withEvent:event];
1919 }];
1920 }
1921 } else {
1922 [super pressesEnded:presses withEvent:event];
1923 }
1924}

◆ pushRoute:

- (void) pushRoute: (NSString*)  route

Instructs the Flutter Navigator (if any) to push a route on to the navigation stack.

Parameters
routeThe name of the route to push to the navigation stack.

Definition at line 152 of file FlutterViewController.mm.

457 :(NSString*)route {
458 [[_engine.get() navigationChannel] invokeMethod:@"pushRoute" arguments:route];
459}
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however route
Definition: switches.h:137

◆ registerTexture:

- (int64_t) registerTexture: (NSObject< FlutterTexture > *)  texture
implementation

Registers a FlutterTexture for usage in Flutter and returns an id that can be used to reference that texture when calling into Flutter with channels. Textures must be registered on the platform thread. On success returns the pointer to the registered texture, else returns 0.

Reimplemented from <FlutterTextureRegistry>.

Definition at line 1112 of file FlutterViewController.mm.

2346 :(NSObject<FlutterTexture>*)texture {
2347 return [_engine.get().textureRegistry registerTexture:texture];
2348}
FlTexture * texture

◆ registrarForPlugin:

- (id< FlutterPluginRegistrar >) registrarForPlugin: (NSString *)  pluginKey
implementation

Returns a registrar for registering a plugin.

Parameters
pluginKeyThe unique key identifying the plugin.

Reimplemented from <FlutterPluginRegistry>.

Definition at line 1112 of file FlutterViewController.mm.

2376 :(NSString*)pluginKey {
2377 return [_engine.get() registrarForPlugin:pluginKey];
2378}

◆ removeInternalPlugins

- (void) removeInternalPlugins
implementation

Definition at line 527 of file FlutterViewController.mm.

837 {
838 self.keyboardManager = nil;
839}

◆ removeKeyboardAnimationView

- (void) removeKeyboardAnimationView
implementation

Definition at line 1112 of file FlutterViewController.mm.

1842 {
1843 if ([self keyboardAnimationView].superview != nil) {
1844 [[self keyboardAnimationView] removeFromSuperview];
1845 }
1846}

◆ removeSplashScreenView:

- (void) removeSplashScreenView: (dispatch_block_t _Nullable)  onComplete
implementation

Definition at line 527 of file FlutterViewController.mm.

599 :(dispatch_block_t _Nullable)onComplete {
600 NSAssert(_splashScreenView, @"The splash screen view must not be null");
601 UIView* splashScreen = [_splashScreenView.get() retain];
603 [UIView animateWithDuration:0.2
604 animations:^{
605 splashScreen.alpha = 0;
606 }
607 completion:^(BOOL finished) {
608 [splashScreen removeFromSuperview];
609 [splashScreen release];
610 if (onComplete) {
611 onComplete();
612 }
613 }];
614}

◆ requestGeometryUpdateForWindowScenes:

- (void) requestGeometryUpdateForWindowScenes: (ios(16.0))  API_AVAILABLE
implementation

Definition at line 1112 of file FlutterViewController.mm.

1957 :(NSSet<UIScene*>*)windowScenes
1958 API_AVAILABLE(ios(16.0)) {
1959 for (UIScene* windowScene in windowScenes) {
1960 FML_DCHECK([windowScene isKindOfClass:[UIWindowScene class]]);
1961 UIWindowSceneGeometryPreferencesIOS* preference = [[[UIWindowSceneGeometryPreferencesIOS alloc]
1962 initWithInterfaceOrientations:_orientationPreferences] autorelease];
1963 [(UIWindowScene*)windowScene
1964 requestGeometryUpdateWithPreferences:preference
1965 errorHandler:^(NSError* error) {
1966 os_log_error(OS_LOG_DEFAULT,
1967 "Failed to change device orientation: %@", error);
1968 }];
1969 [self setNeedsUpdateOfSupportedInterfaceOrientations];
1970 }
1971}
#define FML_DCHECK(condition)
Definition: logging.h:103

◆ restorationPlugin

- (FlutterRestorationPlugin *) restorationPlugin
implementation

Definition at line 1112 of file FlutterViewController.mm.

2634 {
2635 return [_engine.get() restorationPlugin];
2636}

◆ rightMouseDown:

- (void) rightMouseDown: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1007 :(NSEvent*)event {
1009 [self dispatchMouseEvent:event];
1010}
@ kFlutterPointerButtonMouseSecondary
Definition: embedder.h:1018

◆ rightMouseDragged:

- (void) rightMouseDragged: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1017 :(NSEvent*)event {
1018 [self dispatchMouseEvent:event];
1019}

◆ rightMouseUp:

- (void) rightMouseUp: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1012 :(NSEvent*)event {
1013 _mouseState.buttons &= ~static_cast<uint64_t>(kFlutterPointerButtonMouseSecondary);
1014 [self dispatchMouseEvent:event];
1015}

◆ rotateWithEvent:

- (void) rotateWithEvent: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1047 :(NSEvent*)event {
1048 [self dispatchGestureEvent:event];
1049}

◆ sceneBecameActive:

- (void) sceneBecameActive: (ios(13.0))  API_AVAILABLE
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1021 :(NSNotification*)notification API_AVAILABLE(ios(13.0)) {
1022 TRACE_EVENT0("flutter", "sceneBecameActive");
1023 [self appOrSceneBecameActive];
1024}

◆ sceneDidEnterBackground:

- (void) sceneDidEnterBackground: (ios(13.0))  API_AVAILABLE
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1035 :(NSNotification*)notification API_AVAILABLE(ios(13.0)) {
1036 TRACE_EVENT0("flutter", "sceneDidEnterBackground");
1037 [self appOrSceneDidEnterBackground];
1038}

◆ sceneWillDisconnect:

- (void) sceneWillDisconnect: (ios(13.0))  API_AVAILABLE
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1031 :(NSNotification*)notification API_AVAILABLE(ios(13.0)) {
1032 [self appOrSceneWillTerminate];
1033}

◆ sceneWillEnterForeground:

- (void) sceneWillEnterForeground: (ios(13.0))  API_AVAILABLE
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1040 :(NSNotification*)notification API_AVAILABLE(ios(13.0)) {
1041 TRACE_EVENT0("flutter", "sceneWillEnterForeground");
1042 [self appOrSceneWillEnterForeground];
1043}

◆ sceneWillResignActive:

- (void) sceneWillResignActive: (ios(13.0))  API_AVAILABLE
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

1026 :(NSNotification*)notification API_AVAILABLE(ios(13.0)) {
1027 TRACE_EVENT0("flutter", "sceneWillResignActive");
1028 [self appOrSceneWillResignActive];
1029}

◆ scrollViewShouldScrollToTop:

- (BOOL) scrollViewShouldScrollToTop: (UIScrollView*)  scrollView
implementation

Definition at line 527 of file FlutterViewController.mm.

541 :(UIScrollView*)scrollView {
542 if (!_engine) {
543 return NO;
544 }
545 CGPoint statusBarPoint = CGPointZero;
546 UIScreen* screen = [self flutterScreenIfViewLoaded];
547 if (screen) {
548 SendFakeTouchEvent(screen, _engine.get(), statusBarPoint, flutter::PointerData::Change::kDown);
549 SendFakeTouchEvent(screen, _engine.get(), statusBarPoint, flutter::PointerData::Change::kUp);
550 }
551 return NO;
552}
static void SendFakeTouchEvent(UIScreen *screen, FlutterEngine *engine, CGPoint location, flutter::PointerData::Change change)

◆ scrollWheel:

- (void) scrollWheel: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1039 :(NSEvent*)event {
1040 [self dispatchGestureEvent:event];
1041}

◆ SendFakeTouchEvent

+ (static void) SendFakeTouchEvent (UIScreen *)  screen
(FlutterEngine *)  engine
(CGPoint)  location
(flutter::PointerData::Change change 
implementation

Definition at line 527 of file FlutterViewController.mm.

530 {
531 const CGFloat scale = screen.scale;
533 pointer_data.physical_x = location.x * scale;
534 pointer_data.physical_y = location.y * scale;
535 auto packet = std::make_unique<flutter::PointerDataPacket>(/*count=*/1);
536 pointer_data.change = change;
537 packet->SetPointerData(0, pointer_data);
538 [engine dispatchPointerDataPacket:std::move(packet)];
539}
flutter::PointerData generatePointerDataForFake()

◆ sendKeyEvent:callback:userData:

- (void) sendKeyEvent: (const FlutterKeyEvent &)  event
callback: (nullable FlutterKeyEventCallback callback
userData: (nullable void *)  userData 
implementation

Dispatch events to the framework to be processed by |HardwareKeyboard|.

This method typically forwards events to |FlutterEngine.sendKeyEvent:callback:userData:|.

Reimplemented from <FlutterKeyboardViewDelegate>.

Definition at line 891 of file FlutterViewController.mm.

905 :(const FlutterKeyEvent&)event
907 userData:(nullable void*)userData {
908 [_engine sendKeyEvent:event callback:callback userData:userData];
909}

◆ sendOnChannel:message:

- (void) sendOnChannel: (NSString*)  channel
message: (NSData*)  message 
implementation

Definition at line 1112 of file FlutterViewController.mm.

2309 :(NSString*)channel message:(NSData*)message {
2310 [_engine.get().binaryMessenger sendOnChannel:channel message:message];
2311}
Win32Message message

◆ sendOnChannel:message:binaryReply:

- (void) sendOnChannel: (NSString*)  channel
message: (NSData*)  message
binaryReply: (FlutterBinaryReply callback 
implementation

Definition at line 1112 of file FlutterViewController.mm.

2313 :(NSString*)channel
2314 message:(NSData*)message
2315 binaryReply:(FlutterBinaryReply)callback {
2316 NSAssert(channel, @"The channel must not be null");
2317 [_engine.get().binaryMessenger sendOnChannel:channel message:message binaryReply:callback];
2318}
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterBinaryReply)(NSData *_Nullable reply)

◆ setBackgroundColor:

- (void) setBackgroundColor: (NSColor*)  color
implementation

Definition at line 338 of file FlutterViewController.mm.

466 :(NSColor*)color {
467 _backgroundColor = color;
468 [_flutterView setBackgroundColor:_backgroundColor];
469}
DlColor color

◆ setDisplayingFlutterUI:

- (void) setDisplayingFlutterUI: (BOOL displayingFlutterUI
implementation

Definition at line 527 of file FlutterViewController.mm.

579 if (_displayingFlutterUI != displayingFlutterUI) {
580 if (displayingFlutterUI == YES) {
581 if (!self.viewIfLoaded.window) {
582 return;
583 }
584 }
585 [self willChangeValueForKey:@"displayingFlutterUI"];
586 _displayingFlutterUI = displayingFlutterUI;
587 [self didChangeValueForKey:@"displayingFlutterUI"];
588 }
589}

◆ setFlutterViewDidRenderCallback:

- (void) setFlutterViewDidRenderCallback: (void(^)(void))  callback

Registers a callback that will be invoked when the Flutter view has been rendered. The callback will be fired only once.

Replaces an existing callback. Use a nil callback to unregister the existing one.

Definition at line 527 of file FlutterViewController.mm.

◆ setInitialRoute: [1/2]

- (void) setInitialRoute: ("Use FlutterViewController initializer to specify initial route")  FLUTTER_DEPRECATED

Deprecated API to set initial route.

Attempts to set the first route that the Flutter app shows if the Flutter runtime hasn't yet started. The default is "/".

This method must be called immediately after initWithProject and has no effect when using initWithEngine if the FlutterEngine has already been run.

Setting this after the Flutter started running has no effect. See pushRoute and popRoute to change the route after Flutter started running.

This is deprecated because it needs to be called at the time of initialization and thus should just be in the initWithProject initializer. If using initWithEngine, the initial route should be set on the engine's initializer.

Parameters
routeThe name of the first route to show.

◆ setInitialRoute: [2/2]

- (void) setInitialRoute: (NSString*)  route
implementation

Definition at line 152 of file FlutterViewController.mm.

449 :(NSString*)route {
450 [[_engine.get() navigationChannel] invokeMethod:@"setInitialRoute" arguments:route];
451}

◆ setIsHomeIndicatorHidden:

- (void) setIsHomeIndicatorHidden: (BOOL hideHomeIndicator
implementation

Definition at line 1112 of file FlutterViewController.mm.

2042 :(BOOL)hideHomeIndicator {
2043 if (hideHomeIndicator != _isHomeIndicatorHidden) {
2044 _isHomeIndicatorHidden = hideHomeIndicator;
2045 [self setNeedsUpdateOfHomeIndicatorAutoHidden];
2046 }
2047}

◆ setMessageHandlerOnChannel:binaryMessageHandler:

- (FlutterBinaryMessengerConnection) setMessageHandlerOnChannel: (NSString*)  channel
binaryMessageHandler: (FlutterBinaryMessageHandler handler 
implementation

Definition at line 1112 of file FlutterViewController.mm.

2324 :(NSString*)channel
2325 binaryMessageHandler:
2327 return [self setMessageHandlerOnChannel:channel binaryMessageHandler:handler taskQueue:nil];
2328}
void(^ FlutterBinaryMessageHandler)(NSData *_Nullable message, FlutterBinaryReply reply)

◆ setMessageHandlerOnChannel:binaryMessageHandler:taskQueue:

- (FlutterBinaryMessengerConnection) setMessageHandlerOnChannel: (NSString*)  channel
binaryMessageHandler: (FlutterBinaryMessageHandler _Nullable)  handler
taskQueue: (NSObject<FlutterTaskQueue>* _Nullable)  taskQueue 
implementation

Reimplemented from <FlutterBinaryMessenger>.

Definition at line 1112 of file FlutterViewController.mm.

2331 :(NSString*)channel
2332 binaryMessageHandler:(FlutterBinaryMessageHandler _Nullable)handler
2333 taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue {
2334 NSAssert(channel, @"The channel must not be null");
2335 return [_engine.get().binaryMessenger setMessageHandlerOnChannel:channel
2336 binaryMessageHandler:handler
2337 taskQueue:taskQueue];
2338}

◆ setMouseTrackingMode:

- (void) setMouseTrackingMode: (FlutterMouseTrackingMode)  mode
implementation

Definition at line 338 of file FlutterViewController.mm.

458 :(FlutterMouseTrackingMode)mode {
459 if (_mouseTrackingMode == mode) {
460 return;
461 }
462 _mouseTrackingMode = mode;
463 [self configureTrackingArea];
464}
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228

◆ setPrefersStatusBarHidden:

- (void) setPrefersStatusBarHidden: (BOOL hidden
implementation

Definition at line 1112 of file FlutterViewController.mm.

2286 :(BOOL)hidden {
2287 if (hidden != _flutterPrefersStatusBarHidden) {
2288 _flutterPrefersStatusBarHidden = hidden;
2289 [self setNeedsStatusBarAppearanceUpdate];
2290 }
2291}

◆ setSplashScreenView:

- (void) setSplashScreenView: (UIView*)  view
implementation

Definition at line 527 of file FlutterViewController.mm.

718 :(UIView*)view {
719 if (!view) {
720 // Special case: user wants to remove the splash screen view.
721 if (_splashScreenView) {
722 [self removeSplashScreenView:nil];
723 }
724 return;
725 }
726
727 _splashScreenView.reset([view retain]);
728 _splashScreenView.get().autoresizingMask =
729 UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
730}

◆ setUpApplicationLifecycleNotifications:

- (void) setUpApplicationLifecycleNotifications: (NSNotificationCenter*)  center
implementation

Definition at line 152 of file FlutterViewController.mm.

422 :(NSNotificationCenter*)center {
423 [center addObserver:self
424 selector:@selector(applicationBecameActive:)
425 name:UIApplicationDidBecomeActiveNotification
426 object:nil];
427
428 [center addObserver:self
429 selector:@selector(applicationWillResignActive:)
430 name:UIApplicationWillResignActiveNotification
431 object:nil];
432
433 [center addObserver:self
434 selector:@selector(applicationWillTerminate:)
435 name:UIApplicationWillTerminateNotification
436 object:nil];
437
438 [center addObserver:self
439 selector:@selector(applicationDidEnterBackground:)
440 name:UIApplicationDidEnterBackgroundNotification
441 object:nil];
442
443 [center addObserver:self
444 selector:@selector(applicationWillEnterForeground:)
445 name:UIApplicationWillEnterForegroundNotification
446 object:nil];
447}
static SkScalar center(float pos0, float pos1)

◆ setUpKeyboardAnimationVsyncClient:

- (void) setUpKeyboardAnimationVsyncClient: (FlutterKeyboardAnimationCallback keyboardAnimationCallback
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1811 :
1812 (FlutterKeyboardAnimationCallback)keyboardAnimationCallback {
1813 if (!keyboardAnimationCallback) {
1814 return;
1815 }
1816 NSAssert(_keyboardAnimationVSyncClient == nil,
1817 @"_keyboardAnimationVSyncClient must be nil when setting up.");
1818
1819 // Make sure the new viewport metrics get sent after the begin frame event has processed.
1821 [keyboardAnimationCallback copy]);
1822 auto uiCallback = [animationCallback](std::unique_ptr<flutter::FrameTimingsRecorder> recorder) {
1823 fml::TimeDelta frameInterval = recorder->GetVsyncTargetTime() - recorder->GetVsyncStartTime();
1824 fml::TimePoint keyboardAnimationTargetTime = recorder->GetVsyncTargetTime() + frameInterval;
1825 dispatch_async(dispatch_get_main_queue(), ^(void) {
1826 animationCallback.get()(keyboardAnimationTargetTime);
1827 });
1828 };
1829
1830 _keyboardAnimationVSyncClient = [[VSyncClient alloc] initWithTaskRunner:[_engine uiTaskRunner]
1831 callback:uiCallback];
1832 _keyboardAnimationVSyncClient.allowPauseAfterVsync = NO;
1833 [_keyboardAnimationVSyncClient await];
1834}
void(^ FlutterKeyboardAnimationCallback)(fml::TimePoint)
Definition: copy.py:1

◆ setUpKeyboardSpringAnimationIfNeeded:

- (void) setUpKeyboardSpringAnimationIfNeeded: (CAAnimation*)  keyboardAnimation
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1793 :(CAAnimation*)keyboardAnimation {
1794 // If keyboard animation is null or not a spring animation, fallback to DisplayLink tracking.
1795 if (keyboardAnimation == nil || ![keyboardAnimation isKindOfClass:[CASpringAnimation class]]) {
1797 return;
1798 }
1799
1800 // Setup keyboard spring animation details for spring curve animation calculation.
1801 CASpringAnimation* keyboardCASpringAnimation = (CASpringAnimation*)keyboardAnimation;
1803 initWithStiffness:keyboardCASpringAnimation.stiffness
1804 damping:keyboardCASpringAnimation.damping
1805 mass:keyboardCASpringAnimation.mass
1806 initialVelocity:keyboardCASpringAnimation.initialVelocity
1807 fromValue:self.originalViewInsetBottom
1808 toValue:self.targetViewInsetBottom]);
1809}

◆ setUpNotificationCenterObservers

- (void) setUpNotificationCenterObservers
implementation

Definition at line 152 of file FlutterViewController.mm.

300 {
301 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
302 [center addObserver:self
303 selector:@selector(onOrientationPreferencesUpdated:)
304 name:@(flutter::kOrientationUpdateNotificationName)
305 object:nil];
306
307 [center addObserver:self
308 selector:@selector(onPreferredStatusBarStyleUpdated:)
309 name:@(flutter::kOverlayStyleUpdateNotificationName)
310 object:nil];
311
312#if APPLICATION_EXTENSION_API_ONLY
313 if (@available(iOS 13.0, *)) {
314 [self setUpSceneLifecycleNotifications:center];
315 } else {
316 [self setUpApplicationLifecycleNotifications:center];
317 }
318#else
319 [self setUpApplicationLifecycleNotifications:center];
320#endif
321
322 [center addObserver:self
323 selector:@selector(keyboardWillChangeFrame:)
324 name:UIKeyboardWillChangeFrameNotification
325 object:nil];
326
327 [center addObserver:self
328 selector:@selector(keyboardWillShowNotification:)
329 name:UIKeyboardWillShowNotification
330 object:nil];
331
332 [center addObserver:self
333 selector:@selector(keyboardWillBeHidden:)
334 name:UIKeyboardWillHideNotification
335 object:nil];
336
337 [center addObserver:self
338 selector:@selector(onAccessibilityStatusChanged:)
339 name:UIAccessibilityVoiceOverStatusDidChangeNotification
340 object:nil];
341
342 [center addObserver:self
343 selector:@selector(onAccessibilityStatusChanged:)
344 name:UIAccessibilitySwitchControlStatusDidChangeNotification
345 object:nil];
346
347 [center addObserver:self
348 selector:@selector(onAccessibilityStatusChanged:)
349 name:UIAccessibilitySpeakScreenStatusDidChangeNotification
350 object:nil];
351
352 [center addObserver:self
353 selector:@selector(onAccessibilityStatusChanged:)
354 name:UIAccessibilityInvertColorsStatusDidChangeNotification
355 object:nil];
356
357 [center addObserver:self
358 selector:@selector(onAccessibilityStatusChanged:)
359 name:UIAccessibilityReduceMotionStatusDidChangeNotification
360 object:nil];
361
362 [center addObserver:self
363 selector:@selector(onAccessibilityStatusChanged:)
364 name:UIAccessibilityBoldTextStatusDidChangeNotification
365 object:nil];
366
367 [center addObserver:self
368 selector:@selector(onAccessibilityStatusChanged:)
369 name:UIAccessibilityDarkerSystemColorsStatusDidChangeNotification
370 object:nil];
371
372 if (@available(iOS 13.0, *)) {
373 [center addObserver:self
374 selector:@selector(onAccessibilityStatusChanged:)
375 name:UIAccessibilityOnOffSwitchLabelsDidChangeNotification
376 object:nil];
377 }
378
379 [center addObserver:self
380 selector:@selector(onUserSettingsChanged:)
381 name:UIContentSizeCategoryDidChangeNotification
382 object:nil];
383
384 [center addObserver:self
385 selector:@selector(onHideHomeIndicatorNotification:)
386 name:FlutterViewControllerHideHomeIndicator
387 object:nil];
388
389 [center addObserver:self
390 selector:@selector(onShowHomeIndicatorNotification:)
391 name:FlutterViewControllerShowHomeIndicator
392 object:nil];
393}

◆ setUpSceneLifecycleNotifications:

- (void) setUpSceneLifecycleNotifications: (ios(13.0))  API_AVAILABLE
implementation

Definition at line 152 of file FlutterViewController.mm.

395 :(NSNotificationCenter*)center API_AVAILABLE(ios(13.0)) {
396 [center addObserver:self
397 selector:@selector(sceneBecameActive:)
398 name:UISceneDidActivateNotification
399 object:nil];
400
401 [center addObserver:self
402 selector:@selector(sceneWillResignActive:)
403 name:UISceneWillDeactivateNotification
404 object:nil];
405
406 [center addObserver:self
407 selector:@selector(sceneWillDisconnect:)
408 name:UISceneDidDisconnectNotification
409 object:nil];
410
411 [center addObserver:self
412 selector:@selector(sceneDidEnterBackground:)
413 name:UISceneDidEnterBackgroundNotification
414 object:nil];
415
416 [center addObserver:self
417 selector:@selector(sceneWillEnterForeground:)
418 name:UISceneWillEnterForegroundNotification
419 object:nil];
420}

◆ setUpWithEngine:viewIdentifier:threadSynchronizer:

- (void) setUpWithEngine: (FlutterEngine*)  engine
viewIdentifier: (FlutterViewIdentifier viewIdentifier
threadSynchronizer: (FlutterThreadSynchronizer*)  threadSynchronizer 
implementation

Definition at line 338 of file FlutterViewController.mm.

502 threadSynchronizer:(FlutterThreadSynchronizer*)threadSynchronizer {
503 NSAssert(_engine == nil, @"Already attached to an engine %@.", _engine);
504 _engine = engine;
505 _viewIdentifier = viewIdentifier;
506 _threadSynchronizer = threadSynchronizer;
507 [_threadSynchronizer registerView:_viewIdentifier];
508}
int64_t FlutterViewIdentifier

◆ setViewOpaque:

- (void) setViewOpaque: (BOOL value
implementation

Definition at line 152 of file FlutterViewController.mm.

269 :(BOOL)value {
271 if (_flutterView.get().layer.opaque != value) {
272 _flutterView.get().layer.opaque = value;
273 [_flutterView.get().layer setNeedsLayout];
274 }
275}
uint8_t value

◆ setViewportMetricsPaddings

- (void) setViewportMetricsPaddings
implementation

Definition at line 1112 of file FlutterViewController.mm.

1455 {
1456 UIScreen* screen = [self flutterScreenIfViewLoaded];
1457 if (!screen) {
1458 return;
1459 }
1460
1461 CGFloat scale = screen.scale;
1462 _viewportMetrics.physical_padding_top = self.view.safeAreaInsets.top * scale;
1463 _viewportMetrics.physical_padding_left = self.view.safeAreaInsets.left * scale;
1464 _viewportMetrics.physical_padding_right = self.view.safeAreaInsets.right * scale;
1465 _viewportMetrics.physical_padding_bottom = self.view.safeAreaInsets.bottom * scale;
1466}

◆ setViewportMetricsSize

- (void) setViewportMetricsSize
implementation

Definition at line 1112 of file FlutterViewController.mm.

1441 {
1442 UIScreen* screen = [self flutterScreenIfViewLoaded];
1443 if (!screen) {
1444 return;
1445 }
1446
1447 CGFloat scale = screen.scale;
1448 _viewportMetrics.physical_width = self.view.bounds.size.width * scale;
1449 _viewportMetrics.physical_height = self.view.bounds.size.height * scale;
1450}

◆ sharedSetupWithProject:initialRoute:

- (void) sharedSetupWithProject: (nullable FlutterDartProject*)  project
initialRoute: (nullable NSString*)  initialRoute 
implementation

Provided by category FlutterViewController(Tests).

Definition at line 152 of file FlutterViewController.mm.

234 :(nullable FlutterDartProject*)project
235 initialRoute:(nullable NSString*)initialRoute {
236 // Need the project to get settings for the view. Initializing it here means
237 // the Engine class won't initialize it later.
238 if (!project) {
239 project = [[[FlutterDartProject alloc] init] autorelease];
240 }
241 FlutterView.forceSoftwareRendering = project.settings.enable_software_rendering;
242 _weakFactory = std::make_unique<fml::WeakNSObjectFactory<FlutterViewController>>(self);
244 initWithName:@"io.flutter"
245 project:project
246 allowHeadlessExecution:self.engineAllowHeadlessExecution
247 restorationEnabled:[self restorationIdentifier] != nil]};
248
249 if (!engine) {
250 return;
251 }
252
253 _viewOpaque = YES;
254 _engine = engine;
255 _flutterView.reset([[FlutterView alloc] initWithDelegate:_engine
256 opaque:self.isViewOpaque
257 enableWideGamut:project.isWideGamutEnabled]);
258 [_engine.get() createShell:nil libraryURI:nil initialRoute:initialRoute];
259 _engineNeedsLaunch = YES;
260 _ongoingTouches.reset([[NSMutableSet alloc] init]);
261 [self loadDefaultSplashScreenView];
262 [self performCommonViewControllerInitialization];
263}
BOOL forceSoftwareRendering
Definition: FlutterView.h:49

◆ shouldAutorotate

- (BOOL) shouldAutorotate
implementation

Definition at line 1112 of file FlutterViewController.mm.

2053 {
2054 return YES;
2055}

◆ shouldIgnoreKeyboardNotification:

- (BOOL) shouldIgnoreKeyboardNotification: (NSNotification*)  notification
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1533 :(NSNotification*)notification {
1534 // Don't ignore UIKeyboardWillHideNotification notifications.
1535 // Even if the notification is triggered in the background or by a different app/view controller,
1536 // we want to always handle this notification to avoid inaccurate inset when in a mulitasking mode
1537 // or when switching between apps.
1538 if (notification.name == UIKeyboardWillHideNotification) {
1539 return NO;
1540 }
1541
1542 // Ignore notification when keyboard's dimensions and position are all zeroes for
1543 // UIKeyboardWillChangeFrameNotification. This happens when keyboard is dragged. Do not ignore if
1544 // the notification is UIKeyboardWillShowNotification, as CGRectZero for that notfication only
1545 // occurs when Minimized/Expanded Shortcuts Bar is dropped after dragging, which we later use to
1546 // categorize it as floating.
1547 NSDictionary* info = notification.userInfo;
1548 CGRect keyboardFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
1549 if (notification.name == UIKeyboardWillChangeFrameNotification &&
1550 CGRectEqualToRect(keyboardFrame, CGRectZero)) {
1551 return YES;
1552 }
1553
1554 // When keyboard's height or width is set to 0, don't ignore. This does not happen
1555 // often but can happen sometimes when switching between multitasking modes.
1556 if (CGRectIsEmpty(keyboardFrame)) {
1557 return NO;
1558 }
1559
1560 // Ignore keyboard notifications related to other apps or view controllers.
1561 if ([self isKeyboardNotificationForDifferentView:notification]) {
1562 return YES;
1563 }
1564
1565 if (@available(iOS 13.0, *)) {
1566 // noop
1567 } else {
1568 // If OS version is less than 13, ignore notification if the app is in the background
1569 // or is transitioning from the background. In older versions, when switching between
1570 // apps with the keyboard open in the secondary app, notifications are sent when
1571 // the app is in the background/transitioning from background as if they belong
1572 // to the app and as if the keyboard is showing even though it is not.
1574 return YES;
1575 }
1576 }
1577
1578 return NO;
1579}

◆ splashScreenFromStoryboard:

- (UIView *) splashScreenFromStoryboard: (NSString*)  name
implementation

Definition at line 527 of file FlutterViewController.mm.

690 :(NSString*)name {
691 UIStoryboard* storyboard = nil;
692 @try {
693 storyboard = [UIStoryboard storyboardWithName:name bundle:nil];
694 } @catch (NSException* exception) {
695 return nil;
696 }
697 if (storyboard) {
698 UIViewController* splashScreenViewController = [storyboard instantiateInitialViewController];
699 return splashScreenViewController.view;
700 }
701 return nil;
702}
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32

◆ splashScreenFromXib:

- (UIView *) splashScreenFromXib: (NSString*)  name
implementation

Definition at line 527 of file FlutterViewController.mm.

704 :(NSString*)name {
705 NSArray* objects = nil;
706 @try {
707 objects = [[NSBundle mainBundle] loadNibNamed:name owner:self options:nil];
708 } @catch (NSException* exception) {
709 return nil;
710 }
711 if ([objects count] != 0) {
712 UIView* view = [objects objectAtIndex:0];
713 return view;
714 }
715 return nil;
716}
int count
Definition: FontMgrTest.cpp:50

◆ startKeyBoardAnimation:

- (void) startKeyBoardAnimation: (NSTimeInterval)  duration
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1691 :(NSTimeInterval)duration {
1692 // If current physical_view_inset_bottom == targetViewInsetBottom, do nothing.
1693 if (_viewportMetrics.physical_view_inset_bottom == self.targetViewInsetBottom) {
1694 return;
1695 }
1696
1697 // When this method is called for the first time,
1698 // initialize the keyboardAnimationView to get animation interpolation during animation.
1699 if ([self keyboardAnimationView] == nil) {
1700 UIView* keyboardAnimationView = [[UIView alloc] init];
1701 [keyboardAnimationView setHidden:YES];
1703 }
1704
1705 if ([self keyboardAnimationView].superview == nil) {
1706 [self.view addSubview:[self keyboardAnimationView]];
1707 }
1708
1709 // Remove running animation when start another animation.
1710 [[self keyboardAnimationView].layer removeAllAnimations];
1711
1712 // Set animation begin value and DisplayLink tracking values.
1713 [self keyboardAnimationView].frame =
1714 CGRectMake(0, _viewportMetrics.physical_view_inset_bottom, 0, 0);
1715 self.keyboardAnimationStartTime = fml::TimePoint().Now();
1716 self.originalViewInsetBottom = _viewportMetrics.physical_view_inset_bottom;
1717
1718 // Invalidate old vsync client if old animation is not completed.
1719 [self invalidateKeyboardAnimationVSyncClient];
1720
1721 fml::WeakNSObject<FlutterViewController> weakSelf = [self getWeakNSObject];
1722 FlutterKeyboardAnimationCallback keyboardAnimationCallback = ^(
1723 fml::TimePoint keyboardAnimationTargetTime) {
1724 if (!weakSelf) {
1725 return;
1726 }
1727 fml::scoped_nsobject<FlutterViewController> flutterViewController(
1728 [(FlutterViewController*)weakSelf.get() retain]);
1729 if (!flutterViewController) {
1730 return;
1731 }
1732
1733 // If the view controller's view is not loaded, bail out.
1734 if (!flutterViewController.get().isViewLoaded) {
1735 return;
1736 }
1737 // If the view for tracking keyboard animation is nil, means it is not
1738 // created, bail out.
1739 if ([flutterViewController keyboardAnimationView] == nil) {
1740 return;
1741 }
1742 // If keyboardAnimationVSyncClient is nil, means the animation ends.
1743 // And should bail out.
1744 if (flutterViewController.get().keyboardAnimationVSyncClient == nil) {
1745 return;
1746 }
1747
1748 if ([flutterViewController keyboardAnimationView].superview == nil) {
1749 // Ensure the keyboardAnimationView is in view hierarchy when animation running.
1750 [flutterViewController.get().view addSubview:[flutterViewController keyboardAnimationView]];
1751 }
1752
1753 if ([flutterViewController keyboardSpringAnimation] == nil) {
1754 if (flutterViewController.get().keyboardAnimationView.layer.presentationLayer) {
1755 flutterViewController.get()->_viewportMetrics.physical_view_inset_bottom =
1756 flutterViewController.get()
1757 .keyboardAnimationView.layer.presentationLayer.frame.origin.y;
1758 [flutterViewController updateViewportMetricsIfNeeded];
1759 }
1760 } else {
1761 fml::TimeDelta timeElapsed =
1762 keyboardAnimationTargetTime - flutterViewController.get().keyboardAnimationStartTime;
1763 flutterViewController.get()->_viewportMetrics.physical_view_inset_bottom =
1764 [[flutterViewController keyboardSpringAnimation] curveFunction:timeElapsed.ToSecondsF()];
1765 [flutterViewController updateViewportMetricsIfNeeded];
1766 }
1767 };
1768 [self setUpKeyboardAnimationVsyncClient:keyboardAnimationCallback];
1769 VSyncClient* currentVsyncClient = _keyboardAnimationVSyncClient;
1770
1771 [UIView animateWithDuration:duration
1772 animations:^{
1773 // Set end value.
1774 [self keyboardAnimationView].frame = CGRectMake(0, self.targetViewInsetBottom, 0, 0);
1775
1776 // Setup keyboard animation interpolation.
1777 CAAnimation* keyboardAnimation =
1778 [[self keyboardAnimationView].layer animationForKey:@"position"];
1779 [self setUpKeyboardSpringAnimationIfNeeded:keyboardAnimation];
1780 }
1781 completion:^(BOOL finished) {
1782 if (_keyboardAnimationVSyncClient == currentVsyncClient) {
1783 // Indicates the vsync client captured by this block is the original one, which also
1784 // indicates the animation has not been interrupted from its beginning. Moreover,
1785 // indicates the animation is over and there is no more to execute.
1786 [self invalidateKeyboardAnimationVSyncClient];
1787 [self removeKeyboardAnimationView];
1788 [self ensureViewportMetricsIsCorrect];
1789 }
1790 }];
1791}
fml::TimePoint keyboardAnimationStartTime
std::chrono::time_point< std::chrono::high_resolution_clock > TimePoint
Definition: timing.h:15
const myers::Point & get(const myers::Segment &)

◆ subscribeToKeyboardLayoutChange:

- (void) subscribeToKeyboardLayoutChange: (nullable KeyboardLayoutNotifier callback
implementation

Definition at line 891 of file FlutterViewController.mm.

921}
std::function< void()> KeyboardLayoutNotifier

◆ supportedInterfaceOrientations

- (NSUInteger) supportedInterfaceOrientations
implementation

Definition at line 1112 of file FlutterViewController.mm.

2057 {
2059}

◆ supportsShowingSystemContextMenu

- (BOOL) supportsShowingSystemContextMenu
implementation

Definition at line 1112 of file FlutterViewController.mm.

2200 {
2201 if (@available(iOS 16.0, *)) {
2202 return YES;
2203 } else {
2204 return NO;
2205 }
2206}

◆ surfaceUpdated:

- (void) surfaceUpdated: (BOOL appeared
implementation

Provided by category FlutterViewController(Tests).

Definition at line 527 of file FlutterViewController.mm.

738 :(BOOL)appeared {
739 if (!_engine) {
740 return;
741 }
742
743 // NotifyCreated/NotifyDestroyed are synchronous and require hops between the UI and raster
744 // thread.
745 if (appeared) {
746 [self installFirstFrameCallback];
747 [_engine.get() platformViewsController]->SetFlutterView(_flutterView.get());
748 [_engine.get() platformViewsController]->SetFlutterViewController(self);
749 [_engine.get() iosPlatformView]->NotifyCreated();
750 } else {
751 self.displayingFlutterUI = NO;
752 [_engine.get() iosPlatformView]->NotifyDestroyed();
753 [_engine.get() platformViewsController]->SetFlutterView(nullptr);
754 [_engine.get() platformViewsController]->SetFlutterViewController(nullptr);
755 }
756}

◆ swipeWithEvent:

- (void) swipeWithEvent: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1051 :(NSEvent*)event {
1052 // Not needed, it's handled by scrollWheel.
1053}

◆ textScaleFactor

- (CGFloat) textScaleFactor
implementation

Definition at line 1112 of file FlutterViewController.mm.

2142 {
2143#if APPLICATION_EXTENSION_API_ONLY
2144 FML_LOG(WARNING) << "Dynamic content size update is not supported in app extension.";
2145 return 1.0;
2146#else
2147 UIContentSizeCategory category = [UIApplication sharedApplication].preferredContentSizeCategory;
2148 // The delta is computed by approximating Apple's typography guidelines:
2149 // https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/
2150 //
2151 // Specifically:
2152 // Non-accessibility sizes for "body" text are:
2153 const CGFloat xs = 14;
2154 const CGFloat s = 15;
2155 const CGFloat m = 16;
2156 const CGFloat l = 17;
2157 const CGFloat xl = 19;
2158 const CGFloat xxl = 21;
2159 const CGFloat xxxl = 23;
2160
2161 // Accessibility sizes for "body" text are:
2162 const CGFloat ax1 = 28;
2163 const CGFloat ax2 = 33;
2164 const CGFloat ax3 = 40;
2165 const CGFloat ax4 = 47;
2166 const CGFloat ax5 = 53;
2167
2168 // We compute the scale as relative difference from size L (large, the default size), where
2169 // L is assumed to have scale 1.0.
2170 if ([category isEqualToString:UIContentSizeCategoryExtraSmall]) {
2171 return xs / l;
2172 } else if ([category isEqualToString:UIContentSizeCategorySmall]) {
2173 return s / l;
2174 } else if ([category isEqualToString:UIContentSizeCategoryMedium]) {
2175 return m / l;
2176 } else if ([category isEqualToString:UIContentSizeCategoryLarge]) {
2177 return 1.0;
2178 } else if ([category isEqualToString:UIContentSizeCategoryExtraLarge]) {
2179 return xl / l;
2180 } else if ([category isEqualToString:UIContentSizeCategoryExtraExtraLarge]) {
2181 return xxl / l;
2182 } else if ([category isEqualToString:UIContentSizeCategoryExtraExtraExtraLarge]) {
2183 return xxxl / l;
2184 } else if ([category isEqualToString:UIContentSizeCategoryAccessibilityMedium]) {
2185 return ax1 / l;
2186 } else if ([category isEqualToString:UIContentSizeCategoryAccessibilityLarge]) {
2187 return ax2 / l;
2188 } else if ([category isEqualToString:UIContentSizeCategoryAccessibilityExtraLarge]) {
2189 return ax3 / l;
2190 } else if ([category isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraLarge]) {
2191 return ax4 / l;
2192 } else if ([category isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraExtraLarge]) {
2193 return ax5 / l;
2194 } else {
2195 return 1.0;
2196 }
2197#endif
2198}
struct MyStruct s

◆ textureFrameAvailable:

- (void) textureFrameAvailable: (int64_t)  textureId
implementation

Notifies Flutter that the content of the previously registered texture has been updated.

This will trigger a call to -[FlutterTexture copyPixelBuffer] on the raster thread.

Reimplemented from <FlutterTextureRegistry>.

Definition at line 1112 of file FlutterViewController.mm.

2354 :(int64_t)textureId {
2355 [_engine.get().textureRegistry textureFrameAvailable:textureId];
2356}

◆ touchesBegan:withEvent:

- (void) touchesBegan: (NSSet *)  touches
withEvent: (UIEvent *)  event 
implementation

See -[UIResponder touchesBegan:withEvent:]

Reimplemented from <FlutterViewResponder>.

Definition at line 1112 of file FlutterViewController.mm.

1296 :(NSSet*)touches withEvent:(UIEvent*)event {
1297 [self dispatchTouches:touches pointerDataChangeOverride:nullptr event:event];
1298}

◆ touchesBeganWithEvent:

- (void) touchesBeganWithEvent: (NSEvent*)  event
implementation

Definition at line 891 of file FlutterViewController.mm.

1055 :(NSEvent*)event {
1056 NSTouch* touch = event.allTouches.anyObject;
1057 if (touch != nil) {
1058 if ((event.timestamp - _mouseState.last_scroll_momentum_changed_time) <
1059 kTrackpadTouchInertiaCancelWindowMs) {
1060 // The trackpad has been touched following a scroll momentum event.
1061 // A scroll inertia cancel message should be sent to the framework.
1062 NSPoint locationInView = [self.flutterView convertPoint:event.locationInWindow fromView:nil];
1063 NSPoint locationInBackingCoordinates =
1064 [self.flutterView convertPointToBacking:locationInView];
1065 FlutterPointerEvent flutterEvent = {
1066 .struct_size = sizeof(flutterEvent),
1067 .timestamp = static_cast<size_t>(event.timestamp * USEC_PER_SEC),
1068 .x = locationInBackingCoordinates.x,
1069 .y = -locationInBackingCoordinates.y, // convertPointToBacking makes this negative.
1072 .device_kind = kFlutterPointerDeviceKindTrackpad,
1073 .view_id = static_cast<FlutterViewIdentifier>(_viewIdentifier),
1074 };
1075
1076 [_engine sendPointerEvent:flutterEvent];
1077 // Ensure no further scroll inertia cancel event will be sent.
1078 _mouseState.last_scroll_momentum_changed_time = 0;
1079 }
1080 }
1081}
@ kFlutterPointerSignalKindScrollInertiaCancel
Definition: embedder.h:1030

◆ touchesCancelled:withEvent:

- (void) touchesCancelled: (NSSet *)  touches
withEvent: (UIEvent *)  event 
implementation

See -[UIResponder touchesCancelled:withEvent:]

Reimplemented from <FlutterViewResponder>.

Definition at line 1112 of file FlutterViewController.mm.

1308 :(NSSet*)touches withEvent:(UIEvent*)event {
1309 [self dispatchTouches:touches pointerDataChangeOverride:nullptr event:event];
1310}

◆ touchesEnded:withEvent:

- (void) touchesEnded: (NSSet *)  touches
withEvent: (UIEvent *)  event 
implementation

See -[UIResponder touchesEnded:withEvent:]

Reimplemented from <FlutterViewResponder>.

Definition at line 1112 of file FlutterViewController.mm.

1304 :(NSSet*)touches withEvent:(UIEvent*)event {
1305 [self dispatchTouches:touches pointerDataChangeOverride:nullptr event:event];
1306}

◆ touchesMoved:withEvent:

- (void) touchesMoved: (NSSet *)  touches
withEvent: (UIEvent *)  event 
implementation

See -[UIResponder touchesMoved:withEvent:]

Reimplemented from <FlutterViewResponder>.

Definition at line 1112 of file FlutterViewController.mm.

1300 :(NSSet*)touches withEvent:(UIEvent*)event {
1301 [self dispatchTouches:touches pointerDataChangeOverride:nullptr event:event];
1302}

◆ traitCollectionDidChange:

- (void) traitCollectionDidChange: (UITraitCollection*)  previousTraitCollection
implementation

Definition at line 1112 of file FlutterViewController.mm.

2126 :(UITraitCollection*)previousTraitCollection {
2127 [super traitCollectionDidChange:previousTraitCollection];
2128 [self onUserSettingsChanged:nil];
2129}

◆ triggerTouchRateCorrectionIfNeeded:

- (void) triggerTouchRateCorrectionIfNeeded: (NSSet*)  touches
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1344 :(NSSet*)touches {
1345 if (_touchRateCorrectionVSyncClient == nil) {
1346 // If the _touchRateCorrectionVSyncClient is not created, means current devices doesn't
1347 // need to correct the touch rate. So just return.
1348 return;
1349 }
1350
1351 // As long as there is a touch's phase is UITouchPhaseBegan or UITouchPhaseMoved,
1352 // activate the correction. Otherwise pause the correction.
1353 BOOL isUserInteracting = NO;
1354 for (UITouch* touch in touches) {
1355 if (touch.phase == UITouchPhaseBegan || touch.phase == UITouchPhaseMoved) {
1356 isUserInteracting = YES;
1357 break;
1358 }
1359 }
1360
1361 if (isUserInteracting && [_engine.get() viewController] == self) {
1362 [_touchRateCorrectionVSyncClient await];
1363 } else {
1364 [_touchRateCorrectionVSyncClient pause];
1365 }
1366}

◆ unregisterTexture:

- (void) unregisterTexture: (int64_t)  textureId
implementation

Unregisters a FlutterTexture that has previously regeistered with registerTexture:. Textures must be unregistered on the platform thread.

Parameters
textureIdThe result that was previously returned from registerTexture:.

Reimplemented from <FlutterTextureRegistry>.

Definition at line 1112 of file FlutterViewController.mm.

2350 :(int64_t)textureId {
2351 [_engine.get().textureRegistry unregisterTexture:textureId];
2352}

◆ updateSemantics:

- (void) updateSemantics: (const FlutterSemanticsUpdate2*)  update
implementation

Definition at line 338 of file FlutterViewController.mm.

522 NSAssert(_engine.semanticsEnabled, @"Semantics must be enabled.");
523 if (!_engine.semanticsEnabled) {
524 return;
525 }
526 for (size_t i = 0; i < update->node_count; i++) {
527 const FlutterSemanticsNode2* node = update->nodes[i];
528 _bridge->AddFlutterSemanticsNodeUpdate(*node);
529 }
530
531 for (size_t i = 0; i < update->custom_action_count; i++) {
532 const FlutterSemanticsCustomAction2* action = update->custom_actions[i];
533 _bridge->AddFlutterSemanticsCustomActionUpdate(*action);
534 }
535
536 _bridge->CommitUpdates();
537
538 // Accessibility tree can only be used when the view is loaded.
539 if (!self.viewLoaded) {
540 return;
541 }
542 // Attaches the accessibility root to the flutter view.
543 auto root = _bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
544 if (root) {
545 if ([self.flutterView.accessibilityChildren count] == 0) {
546 NSAccessibilityElement* native_root = root->GetNativeViewAccessible();
547 self.flutterView.accessibilityChildren = @[ native_root ];
548 }
549 } else {
550 self.flutterView.accessibilityChildren = nil;
551 }
552}
string root
Definition: scale_cpu.py:20
A batch of updates to semantics nodes and custom actions.
Definition: embedder.h:1504

◆ updateViewportMetricsIfNeeded

- (void) updateViewportMetricsIfNeeded
implementation

Provided by category FlutterViewController(Tests).

Definition at line 1112 of file FlutterViewController.mm.

1376 {
1377 if (_shouldIgnoreViewportMetricsUpdatesDuringRotation) {
1378 return;
1379 }
1380 if ([_engine.get() viewController] == self) {
1381 [_engine.get() updateViewportMetrics:_viewportMetrics];
1382 }
1383}

◆ valuePublishedByPlugin:

- (NSObject *) valuePublishedByPlugin: (NSString *)  pluginKey
implementation

Returns a value published by the specified plugin.

Parameters
pluginKeyThe unique key identifying the plugin.
Returns
An object published by the plugin, if any. Will be NSNull if nothing has been published. Will be nil if the plugin has not been registered.

Reimplemented from <FlutterPluginRegistry>.

Definition at line 1112 of file FlutterViewController.mm.

2384 :(NSString*)pluginKey {
2385 return [_engine.get() valuePublishedByPlugin:pluginKey];
2386}

◆ viewDidAppear:

- (void) viewDidAppear: (BOOL animated
implementation

Definition at line 527 of file FlutterViewController.mm.

859 :(BOOL)animated {
860 TRACE_EVENT0("flutter", "viewDidAppear");
861 if ([_engine.get() viewController] == self) {
862 [self onUserSettingsChanged:nil];
863 [self onAccessibilityStatusChanged:nil];
864 BOOL stateIsActive = YES;
865#if APPLICATION_EXTENSION_API_ONLY
866 if (@available(iOS 13.0, *)) {
867 stateIsActive = self.flutterWindowSceneIfViewLoaded.activationState ==
868 UISceneActivationStateForegroundActive;
869 }
870#else
871 stateIsActive = UIApplication.sharedApplication.applicationState == UIApplicationStateActive;
872#endif
873 if (stateIsActive) {
874 [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.resumed"];
875 }
876 }
877 [super viewDidAppear:animated];
878}

◆ viewDidDisappear:

- (void) viewDidDisappear: (BOOL animated
implementation

Definition at line 527 of file FlutterViewController.mm.

888 :(BOOL)animated {
889 TRACE_EVENT0("flutter", "viewDidDisappear");
890 if ([_engine.get() viewController] == self) {
891 [self invalidateKeyboardAnimationVSyncClient];
892 [self ensureViewportMetricsIsCorrect];
893 [self surfaceUpdated:NO];
894 [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"];
895 [self flushOngoingTouches];
896 [_engine.get() notifyLowMemory];
897 }
898
899 [super viewDidDisappear:animated];
900}

◆ viewDidLayoutSubviews

- (void) viewDidLayoutSubviews
implementation

Definition at line 1112 of file FlutterViewController.mm.

1385 {
1386 CGRect viewBounds = self.view.bounds;
1387 CGFloat scale = [self flutterScreenIfViewLoaded].scale;
1388
1389 // Purposefully place this not visible.
1390 _scrollView.get().frame = CGRectMake(0.0, 0.0, viewBounds.size.width, 0.0);
1391 _scrollView.get().contentOffset = CGPointMake(kScrollViewContentSize, kScrollViewContentSize);
1392
1393 // First time since creation that the dimensions of its view is known.
1394 bool firstViewBoundsUpdate = !_viewportMetrics.physical_width;
1396 [self setViewportMetricsSize];
1397 [self setViewportMetricsPaddings];
1398 [self updateViewportMetricsIfNeeded];
1399
1400 // There is no guarantee that UIKit will layout subviews when the application/scene is active.
1401 // Creating the surface when inactive will cause GPU accesses from the background. Only wait for
1402 // the first frame to render when the application/scene is actually active.
1403 bool applicationOrSceneIsActive = YES;
1404#if APPLICATION_EXTENSION_API_ONLY
1405 if (@available(iOS 13.0, *)) {
1406 applicationOrSceneIsActive = self.flutterWindowSceneIfViewLoaded.activationState ==
1407 UISceneActivationStateForegroundActive;
1408 }
1409#else
1410 applicationOrSceneIsActive =
1411 [UIApplication sharedApplication].applicationState == UIApplicationStateActive;
1412#endif
1413
1414 // This must run after updateViewportMetrics so that the surface creation tasks are queued after
1415 // the viewport metrics update tasks.
1416 if (firstViewBoundsUpdate && applicationOrSceneIsActive && _engine) {
1417 [self surfaceUpdated:YES];
1418
1419 flutter::Shell& shell = [_engine.get() shell];
1420 fml::TimeDelta waitTime =
1421#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
1423#else
1425#endif
1426 if (shell.WaitForFirstFrame(waitTime).code() == fml::StatusCode::kDeadlineExceeded) {
1427 FML_LOG(INFO) << "Timeout waiting for the first frame to render. This may happen in "
1428 << "unoptimized builds. If this is a release build, you should load a less "
1429 << "complex frame to avoid the timeout.";
1430 }
1431 }
1432}
static constexpr TimeDelta FromMilliseconds(int64_t millis)
Definition: time_delta.h:46

◆ viewDidLoad

- (void) viewDidLoad
implementation

Definition at line 527 of file FlutterViewController.mm.

760 {
761 TRACE_EVENT0("flutter", "viewDidLoad");
762
764 [_engine.get() launchEngine:nil libraryURI:nil entrypointArgs:nil];
765 [_engine.get() setViewController:self];
767 } else if ([_engine.get() viewController] == self) {
768 [_engine.get() attachView];
769 }
770
771 // Register internal plugins.
772 [self addInternalPlugins];
773
774 // Create a vsync client to correct delivery frame rate of touch events if needed.
775 [self createTouchRateCorrectionVSyncClientIfNeeded];
776
777 if (@available(iOS 13.4, *)) {
778 _hoverGestureRecognizer =
779 [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(hoverEvent:)];
780 _hoverGestureRecognizer.delegate = self;
781 [_flutterView.get() addGestureRecognizer:_hoverGestureRecognizer];
782
783 _discreteScrollingPanGestureRecognizer =
784 [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(discreteScrollEvent:)];
785 _discreteScrollingPanGestureRecognizer.allowedScrollTypesMask = UIScrollTypeMaskDiscrete;
786 // Disallowing all touch types. If touch events are allowed here, touches to the screen will be
787 // consumed by the UIGestureRecognizer instead of being passed through to flutter via
788 // touchesBegan. Trackpad and mouse scrolls are sent by the platform as scroll events rather
789 // than touch events, so they will still be received.
790 _discreteScrollingPanGestureRecognizer.allowedTouchTypes = @[];
791 _discreteScrollingPanGestureRecognizer.delegate = self;
792 [_flutterView.get() addGestureRecognizer:_discreteScrollingPanGestureRecognizer];
793 _continuousScrollingPanGestureRecognizer =
794 [[UIPanGestureRecognizer alloc] initWithTarget:self
795 action:@selector(continuousScrollEvent:)];
796 _continuousScrollingPanGestureRecognizer.allowedScrollTypesMask = UIScrollTypeMaskContinuous;
797 _continuousScrollingPanGestureRecognizer.allowedTouchTypes = @[];
798 _continuousScrollingPanGestureRecognizer.delegate = self;
799 [_flutterView.get() addGestureRecognizer:_continuousScrollingPanGestureRecognizer];
800 _pinchGestureRecognizer =
801 [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchEvent:)];
802 _pinchGestureRecognizer.allowedTouchTypes = @[];
803 _pinchGestureRecognizer.delegate = self;
804 [_flutterView.get() addGestureRecognizer:_pinchGestureRecognizer];
805 _rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] init];
806 _rotationGestureRecognizer.allowedTouchTypes = @[];
807 _rotationGestureRecognizer.delegate = self;
808 [_flutterView.get() addGestureRecognizer:_rotationGestureRecognizer];
809 }
810
811 [super viewDidLoad];
812}

◆ viewDidReshape:

- (void) viewDidReshape: (NSView*)  view
implementation

Responds to view reshape by notifying the engine of the change in dimensions.

Definition at line 338 of file FlutterViewController.mm.

859 :(NSView*)view {
861 [_engine updateWindowMetricsForViewController:self];
862}

◆ viewSafeAreaInsetsDidChange

- (void) viewSafeAreaInsetsDidChange
implementation

Definition at line 1112 of file FlutterViewController.mm.

1434 {
1435 [self setViewportMetricsPaddings];
1436 [self updateViewportMetricsIfNeeded];
1437 [super viewSafeAreaInsetsDidChange];
1438}

◆ viewShouldAcceptFirstResponder:

- (BOOL) viewShouldAcceptFirstResponder: (NSView*)  view
implementation

Definition at line 338 of file FlutterViewController.mm.

864 :(NSView*)view {
866 // Only allow FlutterView to become first responder if TextInputPlugin is
867 // not active. Otherwise a mouse event inside FlutterView would cause the
868 // TextInputPlugin to lose first responder status.
869 return !_textInputPlugin.isFirstResponder;
870}

◆ viewWillAppear

- (void) viewWillAppear
implementation

Definition at line 338 of file FlutterViewController.mm.

433 {
434 [super viewWillAppear];
435 if (!_engine.running) {
436 [self launchEngine];
437 }
438 [self listenForMetaModifiedKeyUpEvents];
439}

◆ viewWillAppear:

- (void) viewWillAppear: (BOOL animated
implementation

Definition at line 527 of file FlutterViewController.mm.

841 :(BOOL)animated {
842 TRACE_EVENT0("flutter", "viewWillAppear");
843 if ([_engine.get() viewController] == self) {
844 // Send platform settings to Flutter, e.g., platform brightness.
845 [self onUserSettingsChanged:nil];
846
847 // Only recreate surface on subsequent appearances when viewport metrics are known.
848 // First time surface creation is done on viewDidLayoutSubviews.
850 [self surfaceUpdated:YES];
851 }
852 [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"];
853 [[_engine.get() restorationPlugin] markRestorationComplete];
854 }
855
856 [super viewWillAppear:animated];
857}

◆ viewWillDisappear

- (void) viewWillDisappear
implementation

Definition at line 338 of file FlutterViewController.mm.

441 {
442 // Per Apple's documentation, it is discouraged to call removeMonitor: in dealloc, and it's
443 // recommended to be called earlier in the lifecycle.
444 [NSEvent removeMonitor:_keyUpMonitor];
445 _keyUpMonitor = nil;
446}

◆ viewWillDisappear:

- (void) viewWillDisappear: (BOOL animated
implementation

Definition at line 527 of file FlutterViewController.mm.

880 :(BOOL)animated {
881 TRACE_EVENT0("flutter", "viewWillDisappear");
882 if ([_engine.get() viewController] == self) {
883 [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"];
884 }
885 [super viewWillDisappear:animated];
886}

◆ viewWillTransitionToSize:withTransitionCoordinator:

- (void) viewWillTransitionToSize: (CGSize)  size
withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>)  coordinator 
implementation

Definition at line 527 of file FlutterViewController.mm.

902 :(CGSize)size
903 withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
904 [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
905
906 // We delay the viewport metrics update for half of rotation transition duration, to address
907 // a bug with distorted aspect ratio.
908 // See: https://github.com/flutter/flutter/issues/16322
909 //
910 // This approach does not fully resolve all distortion problem. But instead, it reduces the
911 // rotation distortion roughly from 4x to 2x. The most distorted frames occur in the middle
912 // of the transition when it is rotating the fastest, making it hard to notice.
913
914 NSTimeInterval transitionDuration = coordinator.transitionDuration;
915 // Do not delay viewport metrics update if zero transition duration.
916 if (transitionDuration == 0) {
917 return;
918 }
919
920 _shouldIgnoreViewportMetricsUpdatesDuringRotation = YES;
921 dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
922 static_cast<int64_t>(transitionDuration / 2.0 * NSEC_PER_SEC)),
923 dispatch_get_main_queue(), ^{
924 // `viewWillTransitionToSize` is only called after the previous rotation is
925 // complete. So there won't be race condition for this flag.
926 _shouldIgnoreViewportMetricsUpdatesDuringRotation = NO;
927 [self updateViewportMetricsIfNeeded];
928 });
929}
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
#define NSEC_PER_SEC
Definition: timerfd.cc:35

Property Documentation

◆ backgroundColor

- (NSColor*) backgroundColor
readwritenonatomiccopy

The contentView (FlutterView)'s background color is set to black during its instantiation.

The containing layer's color can be set to the NSColor provided to this method.

For example, the background may be set after the FlutterViewController is instantiated in MainFlutterWindow.swift in the Flutter project.

import Cocoa
import FlutterMacOS
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
let flutterViewController = FlutterViewController()
// The background color of the window and `FlutterViewController`
// are retained separately.
//
// In this example, both the MainFlutterWindow and FlutterViewController's
// FlutterView's backgroundColor are set to clear to achieve a fully
// transparent effect.
//
// If the window's background color is not set, it will use the system
// default.
//
// If the `FlutterView`'s color is not set via `FlutterViewController.setBackgroundColor`
// it's default will be black.
self.backgroundColor = NSColor.clear
flutterViewController.backgroundColor = NSColor.clear
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)
RegisterGeneratedPlugins(registry: flutterViewController)
super.awakeFromNib()
}
}

Definition at line 210 of file FlutterViewController.h.

◆ binaryMessenger

- (NSObject< FlutterBinaryMessenger > *) binaryMessenger
readnonatomicassign

The FlutterBinaryMessenger associated with this FlutterViewController (used for communicating with channels).

This is just a convenient way to get the |FlutterEngine|'s binary messenger.

Definition at line 243 of file FlutterViewController.h.

◆ displayingFlutterUI

- (BOOL) displayingFlutterUI
readnonatomicassign

True if at least one frame has rendered and the ViewController has appeared.

This property is reset to false when the ViewController disappears. It is guaranteed to only alternate between true and false for observers.

Definition at line 197 of file FlutterViewController.h.

◆ engine

- (FlutterEngine *) engine
readnonatomicassign

The FlutterEngine instance for this view controller. This could be the engine this FlutterViewController is initialized with or a new FlutterEngine implicitly created if no engine was supplied during initialization.

The Flutter engine associated with this view controller.

Definition at line 235 of file FlutterViewController.h.

◆ engineAllowHeadlessExecution

- (BOOL) engineAllowHeadlessExecution
readnonatomicassign

If the FlutterViewController creates a FlutterEngine, this property determines if that FlutterEngine has allowHeadlessExecution set.

The intention is that this is used with the XIB. Otherwise, a FlutterEngine can just be sent to the init methods.

See also: -[FlutterEngine initWithName:project:allowHeadlessExecution:]

Definition at line 254 of file FlutterViewController.h.

◆ flutterView

- (FlutterView*) flutterView
readnonatomicassignimplementation

Definition at line 20 of file FlutterViewController_Internal.h.

◆ isHomeIndicatorHidden

- (BOOL) isHomeIndicatorHidden
readwritenonatomicassignimplementation

Definition at line 68 of file FlutterViewController.mm.

◆ isKeyboardInOrTransitioningFromBackground

- (BOOL) isKeyboardInOrTransitioningFromBackground
readwritenonatomicassignimplementation

Provided by category FlutterViewController(Tests).

Definition at line 84 of file FlutterViewController.mm.

◆ isPresentingViewControllerAnimating

- (BOOL) isPresentingViewControllerAnimating
readwritenonatomicassignimplementation

Definition at line 69 of file FlutterViewController.mm.

◆ isVoiceOverRunning

- (BOOL) isVoiceOverRunning
readnonatomicassignimplementation

Definition at line 48 of file FlutterViewController_Internal.h.

◆ keyboardAnimationIsShowing

- (BOOL) keyboardAnimationIsShowing
readwritenonatomicassignimplementation

Provided by category FlutterViewController(Tests).

Definition at line 82 of file FlutterViewController.mm.

◆ keyboardAnimationStartTime

- (TimePoint FlutterViewController()):
readwritenonatomicassignimplementation

Definition at line 83 of file FlutterViewController.mm.

◆ keyboardAnimationVSyncClient

- (VSyncClient*) keyboardAnimationVSyncClient
readwritenonatomicretainimplementation

Provided by category FlutterViewController(Tests).

Definition at line 81 of file FlutterViewController.mm.

◆ keyboardLayoutData

- (NSData*) keyboardLayoutData
readwritenonatomicassignimplementation

Definition at line 189 of file FlutterViewController.mm.

◆ keyboardLayoutNotifier

- (KeyboardLayoutNotifier) keyboardLayoutNotifier
readwritenonatomicassignimplementation

Definition at line 187 of file FlutterViewController.mm.

◆ keyboardManager

- (FlutterKeyboardManager*) keyboardManager
readwritenonatomicassignimplementation

Pointer to a keyboard manager, a hub that manages how key events are dispatched to various Flutter key responders, and whether the event is propagated to the next NSResponder.

Definition at line 49 of file FlutterViewController_Internal.h.

◆ keyUpMonitor

- (id) keyUpMonitor
readwritenonatomicassignimplementation

Event monitor for keyUp events.

Definition at line 178 of file FlutterViewController.mm.

◆ mouseState

- (MouseState) mouseState
readwritenonatomicassignimplementation

The current state of the mouse and the sent mouse events.

Definition at line 173 of file FlutterViewController.mm.

◆ mouseTrackingMode

- (FlutterMouseTrackingMode) mouseTrackingMode
readwritenonatomicassign

The style of mouse tracking to use for the view. Defaults to FlutterMouseTrackingModeInKeyWindow.

Definition at line 84 of file FlutterViewController.h.

◆ originalViewInsetBottom

- (CGFloat) originalViewInsetBottom
readwritenonatomicassignimplementation

Definition at line 80 of file FlutterViewController.mm.

◆ shouldIgnoreViewportMetricsUpdatesDuringRotation

- (BOOL) shouldIgnoreViewportMetricsUpdatesDuringRotation
readwritenonatomicassignimplementation

Whether we should ignore viewport metrics updates during rotation transition.

Definition at line 74 of file FlutterViewController.mm.

◆ splashScreenView

- (UIView *) splashScreenView
readwritenonatomicstrong

Specifies the view to use as a splash screen. Flutter's rendering is asynchronous, so the first frame rendered by the Flutter application might not immediately appear when the Flutter view is initially placed in the view hierarchy. The splash screen view will be used as a replacement until the first frame is rendered.

The view used should be appropriate for multiple sizes; an autoresizing mask to have a flexible width and height will be applied automatically.

Set to nil to remove the splash screen view.

Definition at line 210 of file FlutterViewController.h.

◆ targetViewInsetBottom

- (CGFloat) targetViewInsetBottom
readwritenonatomicassignimplementation

Keyboard animation properties

Provided by category FlutterViewController(Tests).

Definition at line 79 of file FlutterViewController.mm.

◆ textInputPlugin

- (FlutterTextInputPlugin*) textInputPlugin
readnonatomicassignimplementation

The text input plugin that handles text editing state for text fields.

Definition at line 25 of file FlutterViewController_Internal.h.

◆ touchRateCorrectionVSyncClient

- (VSyncClient*) touchRateCorrectionVSyncClient
readwritenonatomicretainimplementation

VSyncClient for touch events delivery frame rate correction.

On promotion devices(eg: iPhone13 Pro), the delivery frame rate of touch events is 60HZ but the frame rate of rendering is 120HZ, which is different and will leads jitter and laggy. With this VSyncClient, it can correct the delivery frame rate of touch events to let it keep the same with frame rate of rendering.

Provided by category FlutterViewController(Tests).

Definition at line 92 of file FlutterViewController.mm.

◆ trackingArea

- (NSTrackingArea*) trackingArea
readwritenonatomicassignimplementation

The tracking area used to generate hover events, if enabled.

Definition at line 168 of file FlutterViewController.mm.

◆ viewIdentifier

- (FlutterViewIdentifier) viewIdentifier
readnonatomicassign

The identifier for this view controller, if it is attached.

The identifier is assigned when the view controller is attached to a FlutterEngine.

If the view controller is detached (see FlutterViewController#attached), reading this property throws an assertion.

Definition at line 130 of file FlutterViewController.h.

◆ viewOpaque

- (BOOL) viewOpaque
readwritenonatomicassign

Controls whether the created view will be opaque or not.

Default is YES. Note that setting this to NO may negatively impact performance when using hardware acceleration, and toggling this will trigger a re-layout of the view.

Definition at line 228 of file FlutterViewController.h.


The documentation for this class was generated from the following files: