5#define FML_USED_ON_EMBEDDER
7#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
11#include "flutter/common/constants.h"
12#include "flutter/fml/message_loop.h"
13#include "flutter/fml/platform/darwin/platform_version.h"
14#include "flutter/fml/platform/darwin/weak_nsobject.h"
15#include "flutter/fml/trace_event.h"
16#include "flutter/runtime/ptrace_check.h"
17#include "flutter/shell/common/engine.h"
18#include "flutter/shell/common/platform_view.h"
19#include "flutter/shell/common/shell.h"
20#include "flutter/shell/common/switches.h"
21#include "flutter/shell/common/thread_host.h"
22#include "flutter/shell/common/variable_refresh_rate_display.h"
23#import "flutter/shell/platform/darwin/common/command_line.h"
24#import "flutter/shell/platform/darwin/common/framework/Source/FlutterBinaryMessengerRelay.h"
25#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
26#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.h"
27#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterIndirectScribbleDelegate.h"
28#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h"
29#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h"
30#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h"
31#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.h"
32#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerDelegate.h"
33#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerPlugin.h"
34#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
35#import "flutter/shell/platform/darwin/ios/framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.h"
36#import "flutter/shell/platform/darwin/ios/framework/Source/connection_collection.h"
37#import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h"
38#import "flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.h"
39#import "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h"
40#import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
41#import "flutter/shell/platform/darwin/ios/rendering_api_selection.h"
42#include "flutter/shell/profiling/sampling_profiler.h"
53 pthread_set_qos_class_self_np(QOS_CLASS_BACKGROUND, 0);
54 [[NSThread currentThread] setThreadPriority:0];
58 pthread_set_qos_class_self_np(QOS_CLASS_DEFAULT, 0);
59 [[NSThread currentThread] setThreadPriority:0.5];
64 pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0);
65 [[NSThread currentThread] setThreadPriority:1.0];
68 pthread_t thread = pthread_self();
69 if (!pthread_getschedparam(thread, &policy, ¶m)) {
70 param.sched_priority = 50;
71 pthread_setschedparam(thread, policy, ¶m);
78#pragma mark - Public exported constants
83#pragma mark - Internal constants
95 FlutterUndoManagerDelegate,
96 FlutterTextInputDelegate,
97 FlutterBinaryMessenger,
98 FlutterTextureRegistry>
101@property(nonatomic, readonly) NSMutableDictionary* pluginPublications;
102@property(nonatomic, readonly) NSMutableDictionary<NSString*, FlutterEngineRegistrar*>* registrars;
104@property(nonatomic, readwrite,
copy) NSString* isolateId;
105@property(nonatomic,
copy) NSString* initialRoute;
106@property(nonatomic, retain) id<NSObject> flutterViewControllerWillDeallocObserver;
108#pragma mark - Embedder API properties
110@property(nonatomic, assign)
BOOL enableEmbedderAPI;
160- (instancetype)init {
161 return [
self initWithName:@"FlutterEngine" project:nil allowHeadlessExecution:YES];
164- (instancetype)initWithName:(NSString*)labelPrefix {
165 return [
self initWithName:labelPrefix project:nil allowHeadlessExecution:YES];
168- (instancetype)initWithName:(NSString*)labelPrefix project:(
FlutterDartProject*)project {
169 return [
self initWithName:labelPrefix project:project allowHeadlessExecution:YES];
172- (instancetype)initWithName:(NSString*)labelPrefix
174 allowHeadlessExecution:(
BOOL)allowHeadlessExecution {
175 return [
self initWithName:labelPrefix
177 allowHeadlessExecution:allowHeadlessExecution
178 restorationEnabled:NO];
181- (instancetype)initWithName:(NSString*)labelPrefix
183 allowHeadlessExecution:(
BOOL)allowHeadlessExecution
184 restorationEnabled:(
BOOL)restorationEnabled {
186 NSAssert(
self,
@"Super init cannot be nil");
187 NSAssert(labelPrefix,
@"labelPrefix is required");
193 _weakFactory = std::make_unique<fml::WeakNSObjectFactory<FlutterEngine>>(
self);
195 if (project == nil) {
198 _dartProject.reset([project retain]);
201 _enableEmbedderAPI = _dartProject.get().settings.enable_embedder_api;
202 if (_enableEmbedderAPI) {
203 NSLog(
@"============== iOS: enable_embedder_api is on ==============");
210 @"Cannot create a FlutterEngine instance in debug mode without Flutter tooling or "
211 @"Xcode.\n\nTo launch in debug mode in iOS 14+, run flutter run from Flutter tools, run "
212 @"from an IDE with a Flutter IDE plugin or run the iOS project from Xcode.\nAlternatively "
213 @"profile and release mode apps can be launched from the home screen.");
218 _pluginPublications = [[NSMutableDictionary alloc] init];
219 _registrars = [[NSMutableDictionary alloc] init];
220 [
self recreatePlatformViewController];
226 NSNotificationCenter*
center = [NSNotificationCenter defaultCenter];
227 [center addObserver:self
228 selector:@selector(onMemoryWarning:)
229 name:UIApplicationDidReceiveMemoryWarningNotification
232#if APPLICATION_EXTENSION_API_ONLY
233 if (@available(iOS 13.0, *)) {
234 [
self setUpSceneLifecycleNotifications:center];
236 [
self setUpApplicationLifecycleNotifications:center];
239 [
self setUpApplicationLifecycleNotifications:center];
242 [center addObserver:self
243 selector:@selector(onLocaleUpdated:)
244 name:NSCurrentLocaleDidChangeNotification
250- (void)setUpSceneLifecycleNotifications:(NSNotificationCenter*)center API_AVAILABLE(
ios(13.0)) {
251 [center addObserver:self
252 selector:@selector(sceneWillEnterForeground:)
253 name:UISceneWillEnterForegroundNotification
255 [center addObserver:self
256 selector:@selector(sceneDidEnterBackground:)
257 name:UISceneDidEnterBackgroundNotification
261- (void)setUpApplicationLifecycleNotifications:(NSNotificationCenter*)center {
262 [center addObserver:self
263 selector:@selector(applicationWillEnterForeground:)
264 name:UIApplicationWillEnterForegroundNotification
266 [center addObserver:self
267 selector:@selector(applicationDidEnterBackground:)
268 name:UIApplicationDidEnterBackgroundNotification
272- (void)recreatePlatformViewController {
277- (
flutter::IOSRenderingAPI)platformViewsRenderingAPI {
284 [_pluginPublications enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL* stop) {
285 if ([object respondsToSelector:@selector(detachFromEngineForRegistrar:)]) {
286 NSObject<FlutterPluginRegistrar>* registrar = self.registrars[key];
287 [object detachFromEngineForRegistrar:registrar];
291 [[NSNotificationCenter defaultCenter] postNotificationName:kFlutterEngineWillDealloc
301 enumerateKeysAndObjectsUsingBlock:^(id key, FlutterEngineRegistrar* registrar, BOOL* stop) {
302 registrar.flutterEngine = nil;
305 [_labelPrefix release];
306 [_initialRoute release];
307 [_pluginPublications release];
308 [_registrars release];
311 [_binaryMessenger release];
312 [_textureRegistry release];
314 [_isolateId release];
316 NSNotificationCenter*
center = [NSNotificationCenter defaultCenter];
317 if (_flutterViewControllerWillDeallocObserver) {
318 [center removeObserver:_flutterViewControllerWillDeallocObserver];
319 [_flutterViewControllerWillDeallocObserver release];
321 [center removeObserver:self];
331- (
fml::WeakNSObject<FlutterEngine>)getWeakNSObject {
335- (void)updateViewportMetrics:(
flutter::ViewportMetrics)viewportMetrics {
336 if (!
self.platformView) {
342- (void)dispatchPointerDataPacket:(
std::unique_ptr<
flutter::PointerDataPacket>)packet {
343 if (!
self.platformView) {
346 self.platformView->DispatchPointerDataPacket(std::move(packet));
349- (
fml::WeakPtr<flutter::PlatformView>)platformView {
351 return _shell->GetPlatformView();
354- (
flutter::PlatformViewIOS*)iosPlatformView {
359- (
fml::RefPtr<fml::TaskRunner>)platformTaskRunner {
361 return _shell->GetTaskRunners().GetPlatformTaskRunner();
364- (
fml::RefPtr<fml::TaskRunner>)uiTaskRunner {
366 return _shell->GetTaskRunners().GetUITaskRunner();
369- (
fml::RefPtr<fml::TaskRunner>)rasterTaskRunner {
371 return _shell->GetTaskRunners().GetRasterTaskRunner();
376 userData:(
void*)userData API_AVAILABLE(
ios(13.4)) {
377 if (@available(iOS 13.4, *)) {
381 if (!
self.platformView) {
389 switch (
event.type) {
401 key_data.
logical =
event.logical;
404 auto packet = std::make_unique<flutter::KeyDataPacket>(key_data,
character);
405 NSData*
message = [NSData dataWithBytes:packet->data().data() length:packet->data().size()];
407 auto response = ^(NSData* reply) {
412 if (reply.length == 1 && *
reinterpret_cast<const uint8_t*
>(reply.bytes) == 1) {
418 [
self sendOnChannel:kFlutterKeyDataChannel message:message binaryReply:response];
421- (void)ensureSemanticsEnabled {
422 self.iosPlatformView->SetSemanticsEnabled(
true);
430 [
self maybeSetupPlatformViewChannels];
431 [
self updateDisplays];
437 [[NSNotificationCenter defaultCenter] addObserverForName:FlutterViewControllerWillDealloc
438 object:viewController
439 queue:[NSOperationQueue mainQueue]
440 usingBlock:^(NSNotification* note) {
441 [blockSelf notifyViewControllerDeallocated];
444 self.flutterViewControllerWillDeallocObserver = nil;
445 [
self notifyLowMemory];
450 self.iosPlatformView->attachView();
453- (void)setFlutterViewControllerWillDeallocObserver:(
id<NSObject>)observer {
454 if (observer != _flutterViewControllerWillDeallocObserver) {
455 if (_flutterViewControllerWillDeallocObserver) {
456 [[NSNotificationCenter defaultCenter]
457 removeObserver:_flutterViewControllerWillDeallocObserver];
458 [_flutterViewControllerWillDeallocObserver release];
460 _flutterViewControllerWillDeallocObserver = [observer retain];
464- (void)notifyViewControllerDeallocated {
465 [[
self lifecycleChannel] sendMessage:@"AppLifecycleState.detached"];
468 [
self destroyContext];
475 [_textInputPlugin.get() resetViewResponder];
479- (void)destroyContext {
480 [
self resetChannels];
481 self.isolateId = nil;
498- (
std::shared_ptr<flutter::FlutterPlatformViewsController>&)platformViewsController {
547- (NSURL*)observatoryUrl {
548 return [_publisher.get() url];
551- (NSURL*)vmServiceUrl {
552 return [_publisher.get() url];
555- (void)resetChannels {
571- (void)startProfiler {
574 _profiler = std::make_shared<flutter::SamplingProfiler>(
583- (void)setUpChannels {
587 [_binaryMessenger setMessageHandlerOnChannel:@"flutter/isolate"
588 binaryMessageHandler:^(NSData* message, FlutterBinaryReply reply) {
590 weakSelf.get().isolateId =
596 initWithName:
@"flutter/localization"
597 binaryMessenger:
self.binaryMessenger
601 initWithName:
@"flutter/navigation"
602 binaryMessenger:
self.binaryMessenger
605 if ([_initialRoute
length] > 0) {
607 [_navigationChannel invokeMethod:@"setInitialRoute" arguments:_initialRoute];
608 [_initialRoute release];
613 initWithName:
@"flutter/restoration"
614 binaryMessenger:
self.binaryMessenger
618 initWithName:
@"flutter/platform"
619 binaryMessenger:
self.binaryMessenger
623 initWithName:
@"flutter/platform_views"
624 binaryMessenger:
self.binaryMessenger
628 initWithName:
@"flutter/textinput"
629 binaryMessenger:
self.binaryMessenger
633 initWithName:
@"flutter/undomanager"
634 binaryMessenger:
self.binaryMessenger
638 initWithName:
@"flutter/scribble"
639 binaryMessenger:
self.binaryMessenger
643 initWithName:
@"flutter/spellcheck"
644 binaryMessenger:
self.binaryMessenger
648 initWithName:
@"flutter/lifecycle"
649 binaryMessenger:
self.binaryMessenger
653 initWithName:
@"flutter/system"
654 binaryMessenger:
self.binaryMessenger
658 initWithName:
@"flutter/settings"
659 binaryMessenger:
self.binaryMessenger
663 initWithName:
@"flutter/keyevent"
664 binaryMessenger:
self.binaryMessenger
684 initWithName:
@"flutter/screenshot"
685 binaryMessenger:
self.binaryMessenger
688 [_screenshotChannel.get()
689 setMethodCallHandler:^(FlutterMethodCall* _Nonnull call, FlutterResult _Nonnull result) {
690 if (!(weakSelf.get() && weakSelf.get()->_shell && weakSelf.get()->_shell->IsSetup())) {
693 message:@"Requesting screenshot while engine is not running."
696 flutter::Rasterizer::Screenshot screenshot =
697 [weakSelf.get() screenshot:flutter::Rasterizer::ScreenshotType::SurfaceData
699 if (!screenshot.data) {
701 message:@"Unable to get screenshot."
705 NSData* data = [NSData dataWithBytes:screenshot.data->writable_data()
706 length:screenshot.data->size()];
707 NSString* format = [NSString stringWithUTF8String:screenshot.format.c_str()];
708 NSNumber* width = @(screenshot.frame_size.fWidth);
709 NSNumber* height = @(screenshot.frame_size.fHeight);
710 return result(@[ width, height, format ?: [NSNull null], data ]);
714- (void)maybeSetupPlatformViewChannels {
717 [_platformChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
722 [_platformViewsChannel.get()
723 setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
725 weakSelf.get().platformViewsController->OnMethodCall(call, result);
730 [_textInputChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
735 [_undoManagerChannel.get()
736 setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
741 [_spellCheckChannel.get()
742 setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
748- (
flutter::Rasterizer::Screenshot)screenshot:(
flutter::Rasterizer::ScreenshotType)type
749 base64Encode:(
bool)base64Encode {
753- (void)launchEngine:(NSString*)entrypoint
754 libraryURI:(NSString*)libraryOrNil
755 entrypointArgs:(NSArray<NSString*>*)entrypointArgs {
757 self.shell.RunEngine([_dartProject.get() runConfigurationForEntrypoint:entrypoint
758 libraryOrNil:libraryOrNil
759 entrypointArgs:entrypointArgs]);
762- (void)setUpShell:(
std::unique_ptr<
flutter::Shell>)shell
763 withVMServicePublication:(
BOOL)doesVMServicePublication {
764 _shell = std::move(shell);
765 [
self setUpChannels];
766 [
self onLocaleUpdated:nil];
767 [
self updateDisplays];
769 initWithEnableVMServicePublication:doesVMServicePublication]);
770 [
self maybeSetupPlatformViewChannels];
775+ (
BOOL)isProfilerEnabled {
776 bool profilerEnabled =
false;
777#if (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG) || \
778 (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE)
779 profilerEnabled =
true;
781 return profilerEnabled;
784+ (NSString*)generateThreadLabel:(NSString*)labelPrefix {
785 static size_t s_shellCount = 0;
786 return [NSString stringWithFormat:@"%@.%zu", labelPrefix, ++s_shellCount];
789+ (
flutter::ThreadHost)makeThreadHost:(NSString*)threadLabel {
804 host_config.ui_config =
809 host_config.raster_config =
814 host_config.io_config =
822static void SetEntryPoint(
flutter::Settings* settings, NSString* entrypoint, NSString* libraryURI) {
824 FML_DCHECK(entrypoint) <<
"Must specify entrypoint if specifying library";
825 settings->advisory_script_entrypoint = entrypoint.UTF8String;
826 settings->advisory_script_uri = libraryURI.UTF8String;
827 }
else if (entrypoint) {
828 settings->advisory_script_entrypoint = entrypoint.UTF8String;
829 settings->advisory_script_uri = std::string(
"main.dart");
831 settings->advisory_script_entrypoint = std::string(
"main");
832 settings->advisory_script_uri = std::string(
"main.dart");
836- (
BOOL)createShell:(NSString*)entrypoint
837 libraryURI:(NSString*)libraryURI
838 initialRoute:(NSString*)initialRoute {
840 FML_LOG(WARNING) <<
"This FlutterEngine was already invoked.";
844 self.initialRoute = initialRoute;
846 auto settings = [_dartProject.get() settings];
847 if (initialRoute != nil) {
848 self.initialRoute = initialRoute;
849 }
else if (
settings.route.empty() ==
false) {
850 self.initialRoute = [NSString stringWithUTF8String:settings.route.c_str()];
855 auto platformData = [_dartProject.get() defaultPlatformData];
857 SetEntryPoint(&settings, entrypoint, libraryURI);
860 _threadHost = std::make_shared<flutter::ThreadHost>();
867 [
self recreatePlatformViewController];
868 return std::make_unique<flutter::PlatformViewIOS>(
869 shell,
self->_renderingApi,
self->_platformViewsController,
shell.GetTaskRunners(),
870 shell.GetConcurrentWorkerTaskRunner(),
shell.GetIsGpuDisabledSyncSwitch());
883#if APPLICATION_EXTENSION_API_ONLY
884 if (@available(iOS 13.0, *)) {
885 _isGpuDisabled =
self.viewController.flutterWindowSceneIfViewLoaded.activationState ==
886 UISceneActivationStateBackground;
894 [UIApplication sharedApplication].applicationState == UIApplicationStateBackground;
902 on_create_platform_view,
903 on_create_rasterizer,
906 if (shell ==
nullptr) {
907 FML_LOG(
ERROR) <<
"Could not start a shell FlutterEngine with entrypoint: "
908 << entrypoint.UTF8String;
911 FML_LOG(INFO) <<
"Enabled VM Service Publication: " <<
settings.enable_vm_service_publication;
912 [
self setUpShell:std::move(shell)
913 withVMServicePublication:settings.enable_vm_service_publication];
915 [
self startProfiler];
922- (void)updateDisplays {
927 auto vsync_waiter =
_shell->GetVsyncWaiter().lock();
928 auto vsync_waiter_ios = std::static_pointer_cast<flutter::VsyncWaiterIOS>(vsync_waiter);
929 std::vector<std::unique_ptr<flutter::Display>> displays;
930 auto screen_size = UIScreen.mainScreen.nativeBounds.size;
931 auto scale = UIScreen.mainScreen.scale;
932 displays.push_back(std::make_unique<flutter::VariableRefreshRateDisplay>(
933 0, vsync_waiter_ios, screen_size.width, screen_size.height,
scale));
934 _shell->OnDisplayUpdates(std::move(displays));
938 return [
self runWithEntrypoint:FlutterDefaultDartEntrypoint
940 initialRoute:FlutterDefaultInitialRoute];
943- (
BOOL)runWithEntrypoint:(NSString*)entrypoint libraryURI:(NSString*)libraryURI {
944 return [
self runWithEntrypoint:entrypoint
945 libraryURI:libraryURI
946 initialRoute:FlutterDefaultInitialRoute];
949- (
BOOL)runWithEntrypoint:(NSString*)entrypoint {
950 return [
self runWithEntrypoint:entrypoint libraryURI:nil initialRoute:FlutterDefaultInitialRoute];
953- (
BOOL)runWithEntrypoint:(NSString*)entrypoint initialRoute:(NSString*)initialRoute {
954 return [
self runWithEntrypoint:entrypoint libraryURI:nil initialRoute:initialRoute];
957- (
BOOL)runWithEntrypoint:(NSString*)entrypoint
958 libraryURI:(NSString*)libraryURI
959 initialRoute:(NSString*)initialRoute {
960 return [
self runWithEntrypoint:entrypoint
961 libraryURI:libraryURI
962 initialRoute:initialRoute
966- (
BOOL)runWithEntrypoint:(NSString*)entrypoint
967 libraryURI:(NSString*)libraryURI
968 initialRoute:(NSString*)initialRoute
969 entrypointArgs:(NSArray<NSString*>*)entrypointArgs {
970 if ([
self createShell:entrypoint libraryURI:libraryURI initialRoute:initialRoute]) {
971 [
self launchEngine:entrypoint libraryURI:libraryURI entrypointArgs:entrypointArgs];
977- (void)notifyLowMemory {
979 _shell->NotifyLowMemoryWarning();
981 [_systemChannel sendMessage:@{@"type" : @"memoryPressure"}];
984#pragma mark - Text input delegate
987 updateEditingClient:(
int)client
988 withState:(NSDictionary*)state {
989 [_textInputChannel.get() invokeMethod:@"TextInputClient.updateEditingState"
990 arguments:@[ @(client), state ]];
994 updateEditingClient:(
int)client
995 withState:(NSDictionary*)state
996 withTag:(NSString*)tag {
997 [_textInputChannel.get() invokeMethod:@"TextInputClient.updateEditingStateWithTag"
998 arguments:@[ @(client), @{tag : state} ]];
1002 updateEditingClient:(
int)client
1003 withDelta:(NSDictionary*)delta {
1004 [_textInputChannel.get() invokeMethod:@"TextInputClient.updateEditingStateWithDeltas"
1005 arguments:@[ @(client), delta ]];
1009 updateFloatingCursor:(FlutterFloatingCursorDragState)state
1010 withClient:(
int)client
1011 withPosition:(NSDictionary*)position {
1012 NSString* stateString;
1014 case FlutterFloatingCursorDragStateStart:
1015 stateString =
@"FloatingCursorDragState.start";
1017 case FlutterFloatingCursorDragStateUpdate:
1018 stateString =
@"FloatingCursorDragState.update";
1020 case FlutterFloatingCursorDragStateEnd:
1021 stateString =
@"FloatingCursorDragState.end";
1024 [_textInputChannel.get() invokeMethod:@"TextInputClient.updateFloatingCursor"
1025 arguments:@[ @(client), stateString, position ]];
1029 performAction:(FlutterTextInputAction)action
1030 withClient:(
int)client {
1031 NSString* actionString;
1033 case FlutterTextInputActionUnspecified:
1038 actionString =
@"TextInputAction.unspecified";
1040 case FlutterTextInputActionDone:
1041 actionString =
@"TextInputAction.done";
1043 case FlutterTextInputActionGo:
1044 actionString =
@"TextInputAction.go";
1046 case FlutterTextInputActionSend:
1047 actionString =
@"TextInputAction.send";
1049 case FlutterTextInputActionSearch:
1050 actionString =
@"TextInputAction.search";
1052 case FlutterTextInputActionNext:
1053 actionString =
@"TextInputAction.next";
1055 case FlutterTextInputActionContinue:
1056 actionString =
@"TextInputAction.continueAction";
1058 case FlutterTextInputActionJoin:
1059 actionString =
@"TextInputAction.join";
1061 case FlutterTextInputActionRoute:
1062 actionString =
@"TextInputAction.route";
1064 case FlutterTextInputActionEmergencyCall:
1065 actionString =
@"TextInputAction.emergencyCall";
1067 case FlutterTextInputActionNewline:
1068 actionString =
@"TextInputAction.newline";
1071 [_textInputChannel.get() invokeMethod:@"TextInputClient.performAction"
1072 arguments:@[ @(client), actionString ]];
1076 showAutocorrectionPromptRectForStart:(NSUInteger)start
1078 withClient:(
int)client {
1079 [_textInputChannel.get() invokeMethod:@"TextInputClient.showAutocorrectionPromptRect"
1080 arguments:@[ @(client), @(start), @(end) ]];
1084 willDismissEditMenuWithTextInputClient:(
int)client {
1085 [_platformChannel.get() invokeMethod:@"ContextMenu.onDismissSystemContextMenu"
1086 arguments:@[ @(client) ]];
1089#pragma mark - FlutterViewEngineDelegate
1095 [_textInputChannel.get() invokeMethod:@"TextInputClient.showToolbar" arguments:@[ @(client) ]];
1099 focusElement:(UIScribbleElementIdentifier)elementIdentifier
1100 atPoint:(CGPoint)referencePoint
1105 [_textInputChannel.get()
1106 invokeMethod:@"TextInputClient.focusElement"
1107 arguments:@[ elementIdentifier, @(referencePoint.x), @(referencePoint.y) ]
1112 requestElementsInRect:(CGRect)rect
1117 [_textInputChannel.get()
1118 invokeMethod:@"TextInputClient.requestElementsInRect"
1119 arguments:@[ @(rect.origin.x), @(rect.origin.y), @(rect.size.width), @(rect.size.height) ]
1127 [_textInputChannel.get() invokeMethod:@"TextInputClient.scribbleInteractionBegan" arguments:nil];
1134 [_textInputChannel.get() invokeMethod:@"TextInputClient.scribbleInteractionFinished"
1139 insertTextPlaceholderWithSize:(CGSize)size
1140 withClient:(
int)client {
1144 [_textInputChannel.get() invokeMethod:@"TextInputClient.insertTextPlaceholder"
1145 arguments:@[ @(client), @(size.width), @(size.height) ]];
1149 removeTextPlaceholder:(
int)client {
1153 [_textInputChannel.get() invokeMethod:@"TextInputClient.removeTextPlaceholder"
1154 arguments:@[ @(client) ]];
1158 didResignFirstResponderWithTextInputClient:(
int)client {
1162 [_textInputChannel.get() invokeMethod:@"TextInputClient.onConnectionClosed"
1163 arguments:@[ @(client) ]];
1184 dispatch_async(dispatch_get_main_queue(), ^(
void) {
1185 long platform_view_id =
self.platformViewsController->FindFirstResponderPlatformViewId();
1186 if (platform_view_id == -1) {
1190 [_platformViewsChannel.get() invokeMethod:@"viewFocused" arguments:@(platform_view_id)];
1194#pragma mark - Undo Manager Delegate
1196- (void)handleUndoWithDirection:(FlutterUndoRedoDirection)direction {
1197 NSString*
action = (direction == FlutterUndoRedoDirectionUndo) ?
@"undo" :
@"redo";
1198 [_undoManagerChannel.get() invokeMethod:@"UndoManagerClient.handleUndo" arguments:@[ action ]];
1201- (UIView<UITextInput>*)activeTextInputView {
1202 return [[
self textInputPlugin] textInputView];
1205- (NSUndoManager*)undoManager {
1206 return self.viewController.undoManager;
1209#pragma mark - Screenshot Delegate
1211- (
flutter::Rasterizer::Screenshot)takeScreenshot:(
flutter::Rasterizer::ScreenshotType)type
1212 asBase64Encoded:(
BOOL)base64Encode {
1214 return _shell->Screenshot(
type, base64Encode);
1217- (void)flutterViewAccessibilityDidCall {
1218 if (
self.viewController.view.accessibilityElements == nil) {
1219 [
self ensureSemanticsEnabled];
1223- (NSObject<FlutterBinaryMessenger>*)binaryMessenger {
1227- (NSObject<FlutterTextureRegistry>*)textureRegistry {
1237 [_binaryMessenger release];
1242#pragma mark - FlutterBinaryMessenger
1244- (void)sendOnChannel:(NSString*)channel message:(NSData*)message {
1245 [
self sendOnChannel:channel message:message binaryReply:nil];
1248- (void)sendOnChannel:(NSString*)channel
1249 message:(NSData*)message
1251 NSParameterAssert(channel);
1253 @"Sending a message before the FlutterEngine has been run.");
1260 _shell->GetTaskRunners().GetPlatformTaskRunner());
1261 std::unique_ptr<flutter::PlatformMessage> platformMessage =
1262 (
message == nil) ? std::make_unique<flutter::PlatformMessage>(channel.UTF8String, response)
1263 : std::make_unique<flutter::PlatformMessage>(
1266 _shell->GetPlatformView()->DispatchPlatformMessage(std::move(platformMessage));
1271- (NSObject<FlutterTaskQueue>*)makeBackgroundTaskQueue {
1276 binaryMessageHandler:
1278 return [
self setMessageHandlerOnChannel:channel binaryMessageHandler:handler taskQueue:nil];
1282 setMessageHandlerOnChannel:(NSString*)channel
1284 taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue {
1285 NSParameterAssert(channel);
1287 self.iosPlatformView->GetPlatformMessageHandlerIos()->SetMessageHandler(channel.UTF8String,
1288 handler, taskQueue);
1289 return _connections->AquireConnection(channel.UTF8String);
1291 NSAssert(!handler,
@"Setting a message handler before the FlutterEngine has been run.");
1299 std::string channel =
_connections->CleanupConnection(connection);
1300 if (!channel.empty()) {
1301 self.iosPlatformView->GetPlatformMessageHandlerIos()->SetMessageHandler(channel.c_str(), nil,
1307#pragma mark - FlutterTextureRegistry
1311 self.iosPlatformView->RegisterExternalTexture(textureId,
texture);
1315- (void)unregisterTexture:(int64_t)textureId {
1316 _shell->GetPlatformView()->UnregisterTexture(textureId);
1319- (void)textureFrameAvailable:(int64_t)textureId {
1320 _shell->GetPlatformView()->MarkTextureFrameAvailable(textureId);
1323- (NSString*)lookupKeyForAsset:(NSString*)asset {
1327- (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package {
1331- (
id<FlutterPluginRegistry>)pluginRegistry {
1335#pragma mark - FlutterPluginRegistry
1337- (NSObject<FlutterPluginRegistrar>*)registrarForPlugin:(NSString*)pluginKey {
1338 NSAssert(
self.pluginPublications[pluginKey] == nil,
@"Duplicate plugin key: %@", pluginKey);
1339 self.pluginPublications[pluginKey] = [NSNull null];
1341 flutterEngine:self];
1343 return [result autorelease];
1346- (
BOOL)hasPlugin:(NSString*)pluginKey {
1347 return _pluginPublications[pluginKey] != nil;
1350- (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey {
1351 return _pluginPublications[pluginKey];
1354#pragma mark - Notifications
1356#if APPLICATION_EXTENSION_API_ONLY
1357- (void)sceneWillEnterForeground:(NSNotification*)notification API_AVAILABLE(
ios(13.0)) {
1358 [
self flutterWillEnterForeground:notification];
1361- (void)sceneDidEnterBackground:(NSNotification*)notification API_AVAILABLE(
ios(13.0)) {
1362 [
self flutterDidEnterBackground:notification];
1365- (void)applicationWillEnterForeground:(NSNotification*)notification {
1366 [
self flutterWillEnterForeground:notification];
1369- (void)applicationDidEnterBackground:(NSNotification*)notification {
1370 [
self flutterDidEnterBackground:notification];
1374- (void)flutterWillEnterForeground:(NSNotification*)notification {
1375 [
self setIsGpuDisabled:NO];
1378- (void)flutterDidEnterBackground:(NSNotification*)notification {
1379 [
self setIsGpuDisabled:YES];
1380 [
self notifyLowMemory];
1383- (void)onMemoryWarning:(NSNotification*)notification {
1384 [
self notifyLowMemory];
1387- (void)setIsGpuDisabled:(
BOOL)value {
1392 _isGpuDisabled =
value;
1395#pragma mark - Locale updates
1397- (void)onLocaleUpdated:(NSNotification*)notification {
1399 NSMutableArray<NSString*>* localeData = [[[NSMutableArray alloc] init] autorelease];
1400 NSArray<NSString*>* preferredLocales = [NSLocale preferredLanguages];
1401 for (NSString* localeID in preferredLocales) {
1402 NSLocale* locale = [[[NSLocale alloc] initWithLocaleIdentifier:localeID] autorelease];
1403 NSString* languageCode = [locale objectForKey:NSLocaleLanguageCode];
1404 NSString* countryCode = [locale objectForKey:NSLocaleCountryCode];
1405 NSString* scriptCode = [locale objectForKey:NSLocaleScriptCode];
1406 NSString* variantCode = [locale objectForKey:NSLocaleVariantCode];
1407 if (!languageCode) {
1410 [localeData addObject:languageCode];
1411 [localeData addObject:(countryCode ? countryCode : @"")];
1412 [localeData addObject:(scriptCode ? scriptCode : @"")];
1413 [localeData addObject:(variantCode ? variantCode : @"")];
1415 if (localeData.count == 0) {
1418 [
self.localizationChannel invokeMethod:@"setLocale" arguments:localeData];
1421- (void)waitForFirstFrame:(NSTimeInterval)timeout
1422 callback:(
void (^_Nonnull)(
BOOL didTimeout))callback {
1423 dispatch_queue_t
queue = dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0);
1424 dispatch_async(queue, ^{
1428 dispatch_async(dispatch_get_main_queue(), ^{
1435 libraryURI:( NSString*)libraryURI
1436 initialRoute:( NSString*)initialRoute
1437 entrypointArgs:( NSArray<NSString*>*)entrypointArgs {
1438 NSAssert(
_shell,
@"Spawning from an engine without a shell (possibly not run).");
1440 project:_dartProject.get()
1441 allowHeadlessExecution:_allowHeadlessExecution];
1443 [_dartProject.get() runConfigurationForEntrypoint:entrypoint
1444 libraryOrNil:libraryURI
1445 entrypointArgs:entrypointArgs];
1452 std::shared_ptr<flutter::IOSContext> context = ios_platform_view->
GetIosContext();
1460 return std::make_unique<flutter::PlatformViewIOS>(
1461 shell, context,
result->_platformViewsController,
shell.GetTaskRunners());
1467 std::string cppInitialRoute;
1469 cppInitialRoute = [initialRoute UTF8String];
1472 std::unique_ptr<flutter::Shell>
shell =
_shell->Spawn(
1473 std::move(configuration), cppInitialRoute, on_create_platform_view, on_create_rasterizer);
1478 result->_isGpuDisabled = _isGpuDisabled;
1479 [result setUpShell:std::move(shell) withVMServicePublication:NO];
1480 return [result autorelease];
1483- (const
flutter::ThreadHost&)threadHost {
1488 return _dartProject.get();
1491- (
BOOL)isUsingImpeller {
1498 NSString* _pluginKey;
1501- (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(
FlutterEngine*)flutterEngine {
1502 self = [
super init];
1503 NSAssert(
self,
@"Super init cannot be nil");
1504 _pluginKey = [pluginKey copy];
1510 [_pluginKey release];
1514- (NSObject<FlutterBinaryMessenger>*)messenger {
1518- (NSObject<FlutterTextureRegistry>*)
textures {
1522- (void)publish:(NSObject*)value {
1526- (void)addMethodCallDelegate:(NSObject<FlutterPlugin>*)delegate
1529 [delegate handleMethodCall:call result:result];
1533- (void)addApplicationDelegate:(NSObject<FlutterPlugin>*)delegate
1534 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in plugins used in
app extensions") {
1535 id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
1536 if ([appDelegate conformsToProtocol:@protocol(FlutterAppLifeCycleProvider)]) {
1537 id<FlutterAppLifeCycleProvider> lifeCycleProvider =
1538 (id<FlutterAppLifeCycleProvider>)appDelegate;
1539 [lifeCycleProvider addApplicationLifeCycleDelegate:delegate];
1543- (NSString*)lookupKeyForAsset:(NSString*)asset {
1544 return [_flutterEngine lookupKeyForAsset:asset];
1547- (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package {
1548 return [_flutterEngine lookupKeyForAsset:asset fromPackage:package];
1552 withId:(NSString*)factoryId {
1553 [
self registerViewFactory:factory
1555 gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager];
1559 withId:(NSString*)factoryId
1560 gestureRecognizersBlockingPolicy:
1562 [_flutterEngine platformViewsController]->RegisterViewFactory(factory, factoryId,
1563 gestureRecognizersBlockingPolicy);
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterBinaryReply)(NSData *_Nullable reply)
void(^ FlutterBinaryMessageHandler)(NSData *_Nullable message, FlutterBinaryReply reply)
int64_t FlutterBinaryMessengerConnection
void(^ FlutterResult)(id _Nullable result)
FlutterPlatformViewGestureRecognizersBlockingPolicy
static SkScalar center(float pos0, float pos1)
Maintains a current integer assigned to a name (connections).
static Connection MakeErrorConnection(int errCode)
Specifies all the configuration required by the runtime library to launch the root isolate....
static std::unique_ptr< Shell > Create(const PlatformData &platform_data, const TaskRunners &task_runners, Settings settings, const CreateCallback< PlatformView > &on_create_platform_view, const CreateCallback< Rasterizer > &on_create_rasterizer, bool is_gpu_disabled=false)
Creates a shell instance using the provided settings. The callbacks to create the various shell subco...
std::function< std::unique_ptr< T >(Shell &)> CreateCallback
static void EnsureInitializedForCurrentThread()
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
T get() const __attribute((ns_returns_not_retained))
@ kNormal
Default priority level.
@ kRaster
Suitable for thread which raster data.
@ kBackground
Suitable for threads that shouldn't disrupt high priority work.
@ kDisplay
Suitable for threads which generate data for the display.
static void SetCurrentThreadName(const ThreadConfig &config)
static constexpr TimeDelta FromMilliseconds(int64_t millis)
void reset(NST *object=Traits::InvalidValue(), scoped_policy::OwnershipPolicy policy=scoped_policy::OwnershipPolicy::kAssume)
std::vector< std::shared_ptr< FakeTexture > > textures
FlutterEngineResult FlutterEngineGetProcAddresses(FlutterEngineProcTable *table)
Gets the table of engine function pointers.
void(* FlutterKeyEventCallback)(bool, void *)
@ kFlutterKeyEventTypeDown
@ kFlutterKeyEventTypeRepeat
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
HWND(* FlutterPlatformViewFactory)(const FlutterPlatformViewCreationParameters *)
#define FML_LOG(severity)
#define FML_DCHECK(condition)
NSObject< FlutterBinaryMessenger > * parent
NSString * lookupKeyForAsset:fromPackage:(NSString *asset,[fromPackage] NSString *package)
NSString * lookupKeyForAsset:(NSString *asset)
FlutterEngine * flutterEngine
NSObject< FlutterBinaryMessenger > * binaryMessenger
NSObject< FlutterTextureRegistry > * textureRegistry
void recreatePlatformViewController()
NSString * generateThreadLabel:(NSString *labelPrefix)
NSMutableDictionary * pluginPublications
id< NSObject > flutterViewControllerWillDeallocObserver
flutter::ThreadHost makeThreadHost:(NSString *threadLabel)
instancetype errorWithCode:message:details:(NSString *code,[message] NSString *_Nullable message,[details] id _Nullable details)
void setMethodCallHandler:(FlutterMethodCallHandler _Nullable handler)
void handleMethodCall:result:(FlutterMethodCall *call,[result] FlutterResult result)
instancetype sharedInstance()
void setUpIndirectScribbleInteraction:(id< FlutterViewResponder > viewResponder)
void handleMethodCall:result:(FlutterMethodCall *call,[result] FlutterResult result)
id< FlutterIndirectScribbleDelegate > indirectScribbleDelegate
NSObject< FlutterTextureRegistry > * parent
void handleMethodCall:result:(FlutterMethodCall *call,[result] FlutterResult result)
fml::WeakNSObject< FlutterViewController > getWeakNSObject()
BOOL forceSoftwareRendering
fml::scoped_nsobject< FlutterMethodChannel > _undoManagerChannel
fml::scoped_nsobject< FlutterSpellCheckPlugin > _spellCheckPlugin
fml::scoped_nsobject< FlutterBasicMessageChannel > _lifecycleChannel
NSString *const FlutterDefaultDartEntrypoint
fml::WeakNSObject< FlutterViewController > _viewController
NSString *const kFlutterEngineWillDealloc
fml::scoped_nsobject< FlutterMethodChannel > _localizationChannel
fml::scoped_nsobject< FlutterMethodChannel > _navigationChannel
std::shared_ptr< flutter::ProfilerMetricsIOS > _profiler_metrics
std::shared_ptr< flutter::SamplingProfiler > _profiler
fml::scoped_nsobject< FlutterMethodChannel > _spellCheckChannel
fml::scoped_nsobject< FlutterPlatformPlugin > _platformPlugin
std::unique_ptr< flutter::Shell > _shell
fml::scoped_nsobject< FlutterMethodChannel > _screenshotChannel
fml::scoped_nsobject< FlutterMethodChannel > _platformViewsChannel
fml::scoped_nsobject< FlutterMethodChannel > _scribbleChannel
fml::scoped_nsobject< FlutterBasicMessageChannel > _keyEventChannel
fml::scoped_nsobject< FlutterDartVMServicePublisher > _publisher
BOOL _allowHeadlessExecution
fml::scoped_nsobject< FlutterBasicMessageChannel > _systemChannel
std::shared_ptr< flutter::FlutterPlatformViewsController > _platformViewsController
fml::scoped_nsobject< FlutterUndoManagerPlugin > _undoManagerPlugin
static void IOSPlatformThreadConfigSetter(const fml::Thread::ThreadConfig &config)
NSString *const kFlutterKeyDataChannel
std::unique_ptr< fml::WeakNSObjectFactory< FlutterEngine > > _weakFactory
fml::scoped_nsobject< FlutterBasicMessageChannel > _settingsChannel
fml::scoped_nsobject< FlutterMethodChannel > _platformChannel
std::unique_ptr< flutter::ConnectionCollection > _connections
NSString *const FlutterDefaultInitialRoute
fml::scoped_nsobject< FlutterRestorationPlugin > _restorationPlugin
flutter::IOSRenderingAPI _renderingApi
FlutterTextureRegistryRelay * _textureRegistry
fml::scoped_nsobject< FlutterTextInputPlugin > _textInputPlugin
static constexpr int kNumProfilerSamplesPerSec
std::shared_ptr< flutter::ThreadHost > _threadHost
fml::scoped_nsobject< FlutterMethodChannel > _restorationChannel
fml::scoped_nsobject< FlutterMethodChannel > _textInputChannel
FlutterBinaryMessengerRelay * _binaryMessenger
FlutterViewController * viewController
FlutterTextInputPlugin * textInputPlugin
__weak FlutterEngine * _flutterEngine
SK_API sk_sp< SkSurface > ios(9.0)
constexpr int64_t kFlutterImplicitViewId
fml::MallocMapping CopyNSDataToMapping(NSData *data)
bool EnableTracingIfNecessary(const Settings &vm_settings)
Enables tracing in the process so that JIT mode VMs may be launched. Explicitly enabling tracing is n...
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software)
GpuAvailability
Values for |Shell::SetGpuAvailability|.
@ kAvailable
Indicates that GPU operations should be permitted.
RefPtr< T > MakeRefCounted(Args &&... args)
const myers::Point & get(const myers::Segment &)
Function-pointer-based versions of the APIs above.
static std::string MakeThreadName(Type type, const std::string &prefix)
Use the prefix and thread type to generator a thread name.
The collection of all the threads used by the engine.
The ThreadConfig is the thread info include thread name, thread priority.