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
102@property(nonatomic, readonly) NSMutableDictionary<NSString*, FlutterEngineRegistrar*>*
registrars;
108#pragma mark - Embedder API properties
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) {
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];
436 self.flutterViewControllerWillDeallocObserver =
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 {
750 return self.shell.Screenshot(
type, 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 {
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 {
795 flutter::ThreadHost::Type::kIo;
798 threadHostType = threadHostType | flutter::ThreadHost::Type::kProfiler;
804 host_config.ui_config =
806 flutter::ThreadHost::Type::kUi, threadLabel.UTF8String),
809 host_config.raster_config =
814 host_config.io_config =
816 flutter::ThreadHost::Type::kIo, threadLabel.UTF8String),
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>(
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];
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.");
1256 : fml::MakeRefCounted<flutter::PlatformMessageResponseDarwin>(
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));
1276 binaryMessageHandler:
1278 return [
self setMessageHandlerOnChannel:channel binaryMessageHandler:handler taskQueue:nil];
1282 setMessageHandlerOnChannel:(NSString*)channel
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
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>(
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 {
1492 return self.project.isImpellerEnabled;
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];
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];
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 void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
static SkScalar center(float pos0, float pos1)
FlutterEngineProcTable & embedderAPI
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)
FlutterEngineResult FlutterEngineGetProcAddresses(FlutterEngineProcTable *table)
Gets the table of engine function pointers.
@ kRaster
Suitable for thread which raster data.
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
NSMutableDictionary< NSString *, FlutterEngineRegistrar * > * registrars
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)
fml::Thread::ThreadConfig ThreadConfig
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 policy
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)
@ kAvailable
Indicates that GPU operations should be permitted.
def timeout(deadline, cmd)
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.