From 1d6572622fd4af29119fac6eca4da4fd46e04519 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 10 Jul 2019 11:12:51 -0700 Subject: [PATCH 1/5] Move resource context into engine --- .../macos/framework/Source/FLEEngine.mm | 24 +++++++++++-- .../framework/Source/FLEEngine_Internal.h | 13 +++++++ .../framework/Source/FLEViewController.mm | 36 +++++++------------ .../Source/FLEViewController_Internal.h | 6 ---- .../macos/framework/Source/FlutterView.h | 4 ++- .../macos/framework/Source/FlutterView.mm | 14 ++++---- 6 files changed, 57 insertions(+), 40 deletions(-) diff --git a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm index 289ab47c4449e..18ea41db8592d 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm @@ -120,6 +120,9 @@ @implementation FLEEngine { // The embedding-API-level engine object. FlutterEngine _engine; + // The context provided to the Flutter engine for resource loading. + NSOpenGLContext* _resourceContext; + // A mapping of channel names to the registered handlers for those channels. NSMutableDictionary* _messageHandlers; } @@ -151,7 +154,7 @@ - (void)setProject:(FLEDartProject*)project { } - (BOOL)run { - if (_engine != NULL) { + if (self.running) { return NO; } @@ -193,6 +196,23 @@ - (BOOL)run { #pragma mark - Framework-internal methods +- (BOOL)running { + return _engine != nullptr; +} + +- (NSOpenGLContext*)resourceContext { + if (!_resourceContext) { + NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADoubleBuffer, 0, + }; + NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + _resourceContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat + shareContext:nil]; + } + return _resourceContext; +} + - (void)updateWindowMetricsWithSize:(CGSize)size pixelRatio:(double)pixelRatio { const FlutterWindowMetricsEvent event = { .struct_size = sizeof(event), @@ -237,7 +257,7 @@ - (bool)engineCallbackOnMakeResourceCurrent { if (!_viewController.flutterView) { return false; } - [_viewController makeResourceContextCurrent]; + [self.resourceContext makeCurrentContext]; return true; } diff --git a/shell/platform/darwin/macos/framework/Source/FLEEngine_Internal.h b/shell/platform/darwin/macos/framework/Source/FLEEngine_Internal.h index 80112e205c9e0..beefdf3c26f24 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEEngine_Internal.h +++ b/shell/platform/darwin/macos/framework/Source/FLEEngine_Internal.h @@ -4,10 +4,23 @@ #import "flutter/shell/platform/darwin/macos/framework/Headers/FLEEngine.h" +#import + #import "flutter/shell/platform/embedder/embedder.h" @interface FLEEngine () +/** + * True if the engine is currently running. + */ +@property(nonatomic, readonly) BOOL running; + +/** + * The resource context used by the engine for texture uploads. FlutterViews associated with this + * engine should be created to share with this context. + */ +@property(nonatomic, readonly, nullable) NSOpenGLContext* resourceContext; + /** * Informs the engine that the display region's size has changed. * diff --git a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm index 91ad156f26c8f..aa2ab4fab7abc 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm @@ -95,11 +95,6 @@ - (void)configureTrackingArea; */ - (void)addInternalPlugins; -/** - * Creates the OpenGL context used as the resource context by the engine. - */ -- (void)createResourceContext; - /** * Calls dispatchMouseEvent:phase: with a phase determined by self.mouseState. * @@ -149,9 +144,6 @@ - (void)setClipboardData:(NSDictionary*)data; #pragma mark - FLEViewController implementation. @implementation FLEViewController { - // The additional context provided to the Flutter engine for resource loading. - NSOpenGLContext* _resourceContext; - // The plugin used to handle text input. This is not an FlutterPlugin, so must be owned // separately. FLETextInputPlugin* _textInputPlugin; @@ -195,7 +187,13 @@ - (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBun } - (void)loadView { - FlutterView* flutterView = [[FlutterView alloc] initWithReshapeListener:self]; + NSOpenGLContext* resourceContext = _engine.resourceContext; + if (!resourceContext) { + NSLog(@"Unable to create FlutterView; no resource context available."); + return; + } + FlutterView* flutterView = [[FlutterView alloc] initWithShareContext:resourceContext + reshapeListener:self]; self.view = flutterView; } @@ -214,11 +212,6 @@ - (void)setMouseTrackingMode:(FlutterMouseTrackingMode)mode { } - (BOOL)launchEngineWithProject:(nullable FLEDartProject*)project { - // Set up the resource context. This is done here rather than in viewDidLoad as there's no - // guarantee that viewDidLoad will be called before the engine is started, and the context must - // be valid by that point. - [self createResourceContext]; - // Register internal plugins before starting the engine. [self addInternalPlugins]; @@ -226,6 +219,8 @@ - (BOOL)launchEngineWithProject:(nullable FLEDartProject*)project { if (![_engine run]) { return NO; } + // Send an initial window metrics event. + [self viewDidReshape:self.view]; // Send the initial user settings such as brightness and text scale factor // to the engine. [self sendInitialSettings]; @@ -246,10 +241,6 @@ - (void)removeKeyResponder:(NSResponder*)responder { [self.additionalKeyResponders removeObject:responder]; } -- (void)makeResourceContextCurrent { - [_resourceContext makeCurrentContext]; -} - #pragma mark - Private methods - (void)configureTrackingArea { @@ -301,12 +292,6 @@ - (void)addInternalPlugins { }]; } -- (void)createResourceContext { - NSOpenGLContext* viewContext = ((NSOpenGLView*)self.view).openGLContext; - _resourceContext = [[NSOpenGLContext alloc] initWithFormat:viewContext.pixelFormat - shareContext:viewContext]; -} - - (void)dispatchMouseEvent:(nonnull NSEvent*)event { FlutterPointerPhase phase = _mouseState.buttons == 0 ? (_mouseState.flutter_state_is_down ? kUp : kHover) @@ -455,6 +440,9 @@ - (void)setClipboardData:(NSDictionary*)data { * Responds to view reshape by notifying the engine of the change in dimensions. */ - (void)viewDidReshape:(NSView*)view { + if (!_engine.running) { + return; + } CGSize scaledSize = [view convertRectToBacking:view.bounds].size; double pixelRatio = view.bounds.size.width == 0 ? 1 : scaledSize.width / view.bounds.size.width; [_engine updateWindowMetricsWithSize:scaledSize pixelRatio:pixelRatio]; diff --git a/shell/platform/darwin/macos/framework/Source/FLEViewController_Internal.h b/shell/platform/darwin/macos/framework/Source/FLEViewController_Internal.h index cf5804b706468..756758d6f0a6a 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEViewController_Internal.h +++ b/shell/platform/darwin/macos/framework/Source/FLEViewController_Internal.h @@ -22,10 +22,4 @@ */ - (void)removeKeyResponder:(nonnull NSResponder*)responder; -/** - * Called when the engine wants to make the resource context current. This must be a context - * that is in the same share group as this controller's view. - */ -- (void)makeResourceContextCurrent; - @end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterView.h b/shell/platform/darwin/macos/framework/Source/FlutterView.h index 404ce2442f82b..330f3b0186412 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterView.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterView.h @@ -21,10 +21,12 @@ @interface FlutterView : NSOpenGLView - (nullable instancetype)initWithFrame:(NSRect)frame +shareContext:(nonnull NSOpenGLContext*)shareContext reshapeListener:(nonnull id)reshapeListener NS_DESIGNATED_INITIALIZER; -- (nullable instancetype)initWithReshapeListener: +- (nullable instancetype)initWithShareContext:(nonnull NSOpenGLContext*)shareContext +reshapeListener: (nonnull id)reshapeListener; - (nullable instancetype)initWithFrame:(NSRect)frameRect diff --git a/shell/platform/darwin/macos/framework/Source/FlutterView.mm b/shell/platform/darwin/macos/framework/Source/FlutterView.mm index cbb93d063ad95..91242000ff12d 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterView.mm @@ -8,18 +8,18 @@ @implementation FlutterView { __weak id _reshapeListener; } -- (instancetype)initWithReshapeListener:(id)reshapeListener { - return [self initWithFrame:NSZeroRect reshapeListener:reshapeListener]; +- (instancetype)initWithShareContext:(NSOpenGLContext*)shareContext +reshapeListener:(id)reshapeListener { + return [self initWithFrame:NSZeroRect shareContext:shareContext reshapeListener:reshapeListener]; } - (instancetype)initWithFrame:(NSRect)frame +shareContext:(NSOpenGLContext*)shareContext reshapeListener:(id)reshapeListener { - NSOpenGLPixelFormatAttribute attributes[] = { - NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, NSOpenGLPFADoubleBuffer, 0, - }; - NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - self = [super initWithFrame:frame pixelFormat:pixelFormat]; + self = [super initWithFrame:frame]; if (self) { + self.openGLContext = [[NSOpenGLContext alloc] initWithFormat:shareContext.pixelFormat + shareContext:shareContext]; _reshapeListener = reshapeListener; self.wantsBestResolutionOpenGLSurface = YES; } From d08d4cdc845657c77b267a579b27b189f10c39da Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 10 Jul 2019 12:21:11 -0700 Subject: [PATCH 2/5] Remove the need for a public VC method to launch engine --- .../framework/Headers/FLEViewController.h | 10 ++-- .../framework/Source/FLEViewController.mm | 57 +++++++++++++------ 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/shell/platform/darwin/macos/framework/Headers/FLEViewController.h b/shell/platform/darwin/macos/framework/Headers/FLEViewController.h index 2328ec5825c57..3f9b3762cf4e8 100644 --- a/shell/platform/darwin/macos/framework/Headers/FLEViewController.h +++ b/shell/platform/darwin/macos/framework/Headers/FLEViewController.h @@ -41,12 +41,14 @@ FLUTTER_EXPORT @property(nonatomic) FlutterMouseTrackingMode mouseTrackingMode; /** - * Launches the Flutter engine with the provided project. - * + * Initializes a controller that will run the given project. + * * @param project The project to run in this view controller. If nil, a default `FLEDartProject` * will be used. - * @return YES if the engine launched successfully. */ -- (BOOL)launchEngineWithProject:(nullable FLEDartProject*)project; +- (nonnull instancetype)initWithProject:(nullable FLEDartProject*)project NS_DESIGNATED_INITIALIZER; + +- (nonnull instancetype)initWithNibName:(nullable NSString*)nibNameOrNil bundle:(nullable NSBundle*)nibBundleOrNil NS_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithCoder:(nonnull NSCoder*)nibNameOrNil NS_DESIGNATED_INITIALIZER; @end diff --git a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm index aa2ab4fab7abc..7e15ffc8cc3c2 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm @@ -84,6 +84,11 @@ @interface FLEViewController () */ @property(nonatomic) MouseState mouseState; +/** + * Starts running |engine|, including any initial setup. + */ +- (BOOL)launchEngine; + /** * Updates |trackingArea| for the current tracking settings, creating it with * the correct mode if tracking is enabled, or removing it if not. @@ -144,6 +149,9 @@ - (void)setClipboardData:(NSDictionary*)data; #pragma mark - FLEViewController implementation. @implementation FLEViewController { + // The project to run in this controller's engine. + FLEDartProject* _project; + // The plugin used to handle text input. This is not an FlutterPlugin, so must be owned // separately. FLETextInputPlugin* _textInputPlugin; @@ -165,7 +173,7 @@ @implementation FLEViewController { * Performs initialization that's common between the different init paths. */ static void CommonInit(FLEViewController* controller) { - controller->_engine = [[FLEEngine alloc] initWithViewController:controller project:nil]; + controller->_engine = [[FLEEngine alloc] initWithViewController:controller project:controller->_project]; controller->_additionalKeyResponders = [[NSMutableOrderedSet alloc] init]; controller->_mouseTrackingMode = FlutterMouseTrackingModeInKeyWindow; } @@ -186,6 +194,15 @@ - (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBun return self; } +- (instancetype)initWithProject:(nullable FLEDartProject*)project { + self = [super initWithNibName:nil bundle:nil]; + if (self != nil) { + _project = project; + CommonInit(self); + } + return self; +} + - (void)loadView { NSOpenGLContext* resourceContext = _engine.resourceContext; if (!resourceContext) { @@ -201,6 +218,13 @@ - (void)viewDidLoad { [self configureTrackingArea]; } +- (void)viewWillAppear { + [super viewWillAppear]; + if (!_engine.running) { + [self launchEngine]; + } +} + #pragma mark - Public methods - (void)setMouseTrackingMode:(FlutterMouseTrackingMode)mode { @@ -211,22 +235,6 @@ - (void)setMouseTrackingMode:(FlutterMouseTrackingMode)mode { [self configureTrackingArea]; } -- (BOOL)launchEngineWithProject:(nullable FLEDartProject*)project { - // Register internal plugins before starting the engine. - [self addInternalPlugins]; - - _engine.project = project; - if (![_engine run]) { - return NO; - } - // Send an initial window metrics event. - [self viewDidReshape:self.view]; - // Send the initial user settings such as brightness and text scale factor - // to the engine. - [self sendInitialSettings]; - return YES; -} - #pragma mark - Framework-internal methods - (FlutterView*)flutterView { @@ -243,6 +251,21 @@ - (void)removeKeyResponder:(NSResponder*)responder { #pragma mark - Private methods +- (BOOL)launchEngine { + // Register internal plugins before starting the engine. + [self addInternalPlugins]; + + if (![_engine run]) { + return NO; + } + // Send an initial window metrics event. + [self viewDidReshape:self.view]; + // Send the initial user settings such as brightness and text scale factor + // to the engine. + [self sendInitialSettings]; + return YES; +} + - (void)configureTrackingArea { if (_mouseTrackingMode != FlutterMouseTrackingModeNone && self.view) { NSTrackingAreaOptions options = From a33eee6d85ffe3fc4024657cc0547dc11b4b2184 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 10 Jul 2019 13:14:04 -0700 Subject: [PATCH 3/5] Align engine creation APIs and VC-engine interaction with iOS --- .../macos/framework/Headers/FLEEngine.h | 31 ++++---- .../macos/framework/Source/FLEEngine.mm | 71 +++++++++++++++---- .../framework/Source/FLEEngine_Internal.h | 7 +- .../framework/Source/FLEViewController.mm | 38 +++++----- 4 files changed, 94 insertions(+), 53 deletions(-) diff --git a/shell/platform/darwin/macos/framework/Headers/FLEEngine.h b/shell/platform/darwin/macos/framework/Headers/FLEEngine.h index b9b302fcfc23b..ae932645cda78 100644 --- a/shell/platform/darwin/macos/framework/Headers/FLEEngine.h +++ b/shell/platform/darwin/macos/framework/Headers/FLEEngine.h @@ -26,34 +26,37 @@ FLUTTER_EXPORT /** * Initializes an engine with the given viewController. * - * @param viewController The view controller associated with this engine. If nil, the engine - * will be run headless. + * @param labelPrefix Currently unused; in the future, may be used for labelling threads + * as with the iOS FlutterEngine. * @param project The project configuration. If nil, a default FLEDartProject will be used. */ -- (nonnull instancetype)initWithViewController:(nullable FLEViewController*)viewController - project:(nullable FLEDartProject*)project - NS_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithName:(nonnull NSString*)labelPrefix + project:(nullable FLEDartProject*)project; /** - * Runs `main()` from this engine's project. + * Initializes an engine with the given viewController. * - * @return YES if the engine launched successfully. + * @param labelPrefix Currently unused; in the future, may be used for labelling threads + * as with the iOS FlutterEngine. + * @param project The project configuration. If nil, a default FLEDartProject will be used. */ -- (BOOL)run; +- (nonnull instancetype)initWithName:(nonnull NSString*)labelPrefix + project:(nullable FLEDartProject*)project + allowHeadlessExecution:(BOOL)allowHeadlessExecution NS_DESIGNATED_INITIALIZER; + +- (nonnull instancetype)init NS_UNAVAILABLE; /** - * The `FLEDartProject` associated with this engine. If nil, a default will be used for `run`. + * Runs `main()` from this engine's project. * - * TODO(stuartmorgan): Remove this once FLEViewController takes the project as an initializer - * argument. Blocked on currently needing to create it from a XIB due to the view issues - * described in https://github.com/google/flutter-desktop-embedding/issues/10. + * @return YES if the engine launched successfully. */ -@property(nonatomic, nullable) FLEDartProject* project; +- (BOOL)run; /** * The `FLEViewController` associated with this engine, if any. */ -@property(nonatomic, nullable, readonly, weak) FLEViewController* viewController; +@property(nonatomic, nullable, weak) FLEViewController* viewController; /** * The `FlutterBinaryMessenger` for communicating with this engine. diff --git a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm index 18ea41db8592d..54d9dd9b6e7b8 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm @@ -41,6 +41,11 @@ - (bool)engineCallbackOnMakeResourceCurrent; */ - (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message; +/** + * Shuts the Flutter engine if it is running. + */ + - (void)shutDownEngine; + @end #pragma mark - @@ -120,23 +125,30 @@ @implementation FLEEngine { // The embedding-API-level engine object. FlutterEngine _engine; + // The project being run by this engine. + FLEDartProject* _project; + // The context provided to the Flutter engine for resource loading. NSOpenGLContext* _resourceContext; // A mapping of channel names to the registered handlers for those channels. NSMutableDictionary* _messageHandlers; + + // Whether the engine can continue running after the view controller is removed. + BOOL _allowHeadlessExecution; } -- (instancetype)init { - return [self initWithViewController:nil project:nil]; +- (instancetype)initWithName:(NSString*)labelPrefix + project:(FLEDartProject*)project { + return [self initWithName:labelPrefix project:project allowHeadlessExecution:YES]; } -- (instancetype)initWithViewController:(FLEViewController*)viewController - project:(FLEDartProject*)project { +- (instancetype)initWithName:(NSString*)labelPrefix + project:(FLEDartProject*)project + allowHeadlessExecution:(BOOL)allowHeadlessExecution { self = [super init]; NSAssert(self, @"Super init cannot be nil"); - _viewController = viewController; _project = project ?: [[FLEDartProject alloc] init]; _messageHandlers = [[NSMutableDictionary alloc] init]; @@ -144,13 +156,7 @@ - (instancetype)initWithViewController:(FLEViewController*)viewController } - (void)dealloc { - if (FlutterEngineShutdown(_engine) == kSuccess) { - _engine = NULL; - } -} - -- (void)setProject:(FLEDartProject*)project { - _project = project ?: [[FLEDartProject alloc] init]; + [self shutDownEngine]; } - (BOOL)run { @@ -158,6 +164,11 @@ - (BOOL)run { return NO; } + if (!_allowHeadlessExecution && !_viewController) { + NSLog(@"Attempted to run an engine with no view controller without headless mode enabled."); + return NO; + } + const FlutterRendererConfig rendererConfig = { .type = kOpenGL, .open_gl.struct_size = sizeof(FlutterOpenGLRendererConfig), @@ -185,9 +196,19 @@ - (BOOL)run { NSLog(@"Failed to start Flutter engine: error %d", result); return NO; } + [self updateWindowMetrics]; return YES; } +- (void)setViewController:(FLEViewController*)controller { + _viewController = controller; + if (!controller && !_allowHeadlessExecution) { + [self shutDownEngine]; + _resourceContext = nil; + } + [self updateWindowMetrics]; +} + - (id)binaryMessenger { // TODO(stuartmorgan): Switch to FlutterBinaryMessengerRelay to avoid plugins // keeping the engine alive. @@ -213,11 +234,18 @@ - (NSOpenGLContext*)resourceContext { return _resourceContext; } -- (void)updateWindowMetricsWithSize:(CGSize)size pixelRatio:(double)pixelRatio { +- (void)updateWindowMetrics { + if (!_engine) { + return; + } + NSView* view = _viewController.view; + CGSize scaledSize = [view convertRectToBacking:view.bounds].size; + double pixelRatio = view.bounds.size.width == 0 ? 1 : scaledSize.width / view.bounds.size.width; + const FlutterWindowMetricsEvent event = { .struct_size = sizeof(event), - .width = static_cast(size.width), - .height = static_cast(size.height), + .width = static_cast(scaledSize.width), + .height = static_cast(scaledSize.height), .pixel_ratio = pixelRatio, }; FlutterEngineSendWindowMetricsEvent(_engine, &event); @@ -289,6 +317,19 @@ - (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message { } } +/** + * Note: Called from dealloc. Should not use accessors or other methods. + */ +- (void)shutDownEngine { + if (_engine) { + FlutterEngineResult result = FlutterEngineShutdown(_engine); + if (result != kSuccess) { + NSLog(@"Failed to shut down Flutter engine: error %d", result); + } + } + _engine = nullptr; +} + #pragma mark - FlutterBinaryMessenger - (void)sendOnChannel:(nonnull NSString*)channel message:(nullable NSData*)message { diff --git a/shell/platform/darwin/macos/framework/Source/FLEEngine_Internal.h b/shell/platform/darwin/macos/framework/Source/FLEEngine_Internal.h index beefdf3c26f24..18c4957d4007d 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEEngine_Internal.h +++ b/shell/platform/darwin/macos/framework/Source/FLEEngine_Internal.h @@ -22,12 +22,9 @@ @property(nonatomic, readonly, nullable) NSOpenGLContext* resourceContext; /** - * Informs the engine that the display region's size has changed. - * - * @param size The size of the display, in pixels. - * @param pixelRatio The number of pixels per screen coordinate. + * Informs the engine that the associated view controller's view size has changed. */ -- (void)updateWindowMetricsWithSize:(CGSize)size pixelRatio:(double)pixelRatio; +- (void)updateWindowMetrics; /** * Dispatches the given pointer event data to engine. diff --git a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm index 7e15ffc8cc3c2..9581c4d5f33f1 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm @@ -173,33 +173,35 @@ @implementation FLEViewController { * Performs initialization that's common between the different init paths. */ static void CommonInit(FLEViewController* controller) { - controller->_engine = [[FLEEngine alloc] initWithViewController:controller project:controller->_project]; + controller->_engine = [[FLEEngine alloc] initWithName:@"io.flutter" + project:controller->_project + allowHeadlessExecution:NO]; controller->_additionalKeyResponders = [[NSMutableOrderedSet alloc] init]; controller->_mouseTrackingMode = FlutterMouseTrackingModeInKeyWindow; } - (instancetype)initWithCoder:(NSCoder*)coder { self = [super initWithCoder:coder]; - if (self != nil) { - CommonInit(self); - } + NSAssert(self, @"Super init cannot be nil"); + + CommonInit(self); return self; } - (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; - if (self != nil) { - CommonInit(self); - } + NSAssert(self, @"Super init cannot be nil"); + + CommonInit(self); return self; } - (instancetype)initWithProject:(nullable FLEDartProject*)project { self = [super initWithNibName:nil bundle:nil]; - if (self != nil) { - _project = project; - CommonInit(self); - } + NSAssert(self, @"Super init cannot be nil"); + + _project = project; + CommonInit(self); return self; } @@ -225,6 +227,10 @@ - (void)viewWillAppear { } } +- (void)dealloc { + _engine.viewController = nil; +} + #pragma mark - Public methods - (void)setMouseTrackingMode:(FlutterMouseTrackingMode)mode { @@ -255,11 +261,10 @@ - (BOOL)launchEngine { // Register internal plugins before starting the engine. [self addInternalPlugins]; + _engine.viewController = self; if (![_engine run]) { return NO; } - // Send an initial window metrics event. - [self viewDidReshape:self.view]; // Send the initial user settings such as brightness and text scale factor // to the engine. [self sendInitialSettings]; @@ -463,12 +468,7 @@ - (void)setClipboardData:(NSDictionary*)data { * Responds to view reshape by notifying the engine of the change in dimensions. */ - (void)viewDidReshape:(NSView*)view { - if (!_engine.running) { - return; - } - CGSize scaledSize = [view convertRectToBacking:view.bounds].size; - double pixelRatio = view.bounds.size.width == 0 ? 1 : scaledSize.width / view.bounds.size.width; - [_engine updateWindowMetricsWithSize:scaledSize pixelRatio:pixelRatio]; + [_engine updateWindowMetrics]; } #pragma mark - FlutterPluginRegistry From bc1626d572a62d6d880cfbd073cb23e3dd732260 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 10 Jul 2019 13:14:43 -0700 Subject: [PATCH 4/5] Autoformat --- .../macos/framework/Headers/FLEEngine.h | 2 +- .../framework/Headers/FLEViewController.h | 6 ++++-- .../macos/framework/Source/FLEEngine.mm | 19 ++++++++----------- .../framework/Source/FLEViewController.mm | 4 ++-- .../macos/framework/Source/FlutterView.h | 6 +++--- .../macos/framework/Source/FlutterView.mm | 6 +++--- 6 files changed, 21 insertions(+), 22 deletions(-) diff --git a/shell/platform/darwin/macos/framework/Headers/FLEEngine.h b/shell/platform/darwin/macos/framework/Headers/FLEEngine.h index ae932645cda78..e4cc8f1f10725 100644 --- a/shell/platform/darwin/macos/framework/Headers/FLEEngine.h +++ b/shell/platform/darwin/macos/framework/Headers/FLEEngine.h @@ -42,7 +42,7 @@ FLUTTER_EXPORT */ - (nonnull instancetype)initWithName:(nonnull NSString*)labelPrefix project:(nullable FLEDartProject*)project - allowHeadlessExecution:(BOOL)allowHeadlessExecution NS_DESIGNATED_INITIALIZER; + allowHeadlessExecution:(BOOL)allowHeadlessExecution NS_DESIGNATED_INITIALIZER; - (nonnull instancetype)init NS_UNAVAILABLE; diff --git a/shell/platform/darwin/macos/framework/Headers/FLEViewController.h b/shell/platform/darwin/macos/framework/Headers/FLEViewController.h index 3f9b3762cf4e8..2142dce31379c 100644 --- a/shell/platform/darwin/macos/framework/Headers/FLEViewController.h +++ b/shell/platform/darwin/macos/framework/Headers/FLEViewController.h @@ -42,13 +42,15 @@ FLUTTER_EXPORT /** * Initializes a controller that will run the given project. - * + * * @param project The project to run in this view controller. If nil, a default `FLEDartProject` * will be used. */ - (nonnull instancetype)initWithProject:(nullable FLEDartProject*)project NS_DESIGNATED_INITIALIZER; -- (nonnull instancetype)initWithNibName:(nullable NSString*)nibNameOrNil bundle:(nullable NSBundle*)nibBundleOrNil NS_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(nullable NSString*)nibNameOrNil + bundle:(nullable NSBundle*)nibBundleOrNil + NS_DESIGNATED_INITIALIZER; - (nonnull instancetype)initWithCoder:(nonnull NSCoder*)nibNameOrNil NS_DESIGNATED_INITIALIZER; @end diff --git a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm index 54d9dd9b6e7b8..0bc5db65f31d4 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm @@ -44,7 +44,7 @@ - (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message; /** * Shuts the Flutter engine if it is running. */ - - (void)shutDownEngine; +- (void)shutDownEngine; @end @@ -138,13 +138,12 @@ @implementation FLEEngine { BOOL _allowHeadlessExecution; } -- (instancetype)initWithName:(NSString*)labelPrefix - project:(FLEDartProject*)project { +- (instancetype)initWithName:(NSString*)labelPrefix project:(FLEDartProject*)project { return [self initWithName:labelPrefix project:project allowHeadlessExecution:YES]; } - (instancetype)initWithName:(NSString*)labelPrefix - project:(FLEDartProject*)project + project:(FLEDartProject*)project allowHeadlessExecution:(BOOL)allowHeadlessExecution { self = [super init]; NSAssert(self, @"Super init cannot be nil"); @@ -224,12 +223,10 @@ - (BOOL)running { - (NSOpenGLContext*)resourceContext { if (!_resourceContext) { NSOpenGLPixelFormatAttribute attributes[] = { - NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADoubleBuffer, 0, - }; - NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - _resourceContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat - shareContext:nil]; + NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, NSOpenGLPFADoubleBuffer, 0, + }; + NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + _resourceContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; } return _resourceContext; } @@ -241,7 +238,7 @@ - (void)updateWindowMetrics { NSView* view = _viewController.view; CGSize scaledSize = [view convertRectToBacking:view.bounds].size; double pixelRatio = view.bounds.size.width == 0 ? 1 : scaledSize.width / view.bounds.size.width; - + const FlutterWindowMetricsEvent event = { .struct_size = sizeof(event), .width = static_cast(scaledSize.width), diff --git a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm index 9581c4d5f33f1..35007ce552c2d 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm @@ -174,8 +174,8 @@ @implementation FLEViewController { */ static void CommonInit(FLEViewController* controller) { controller->_engine = [[FLEEngine alloc] initWithName:@"io.flutter" - project:controller->_project - allowHeadlessExecution:NO]; + project:controller->_project + allowHeadlessExecution:NO]; controller->_additionalKeyResponders = [[NSMutableOrderedSet alloc] init]; controller->_mouseTrackingMode = FlutterMouseTrackingModeInKeyWindow; } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterView.h b/shell/platform/darwin/macos/framework/Source/FlutterView.h index 330f3b0186412..9342e748dc771 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterView.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterView.h @@ -21,13 +21,13 @@ @interface FlutterView : NSOpenGLView - (nullable instancetype)initWithFrame:(NSRect)frame -shareContext:(nonnull NSOpenGLContext*)shareContext + shareContext:(nonnull NSOpenGLContext*)shareContext reshapeListener:(nonnull id)reshapeListener NS_DESIGNATED_INITIALIZER; - (nullable instancetype)initWithShareContext:(nonnull NSOpenGLContext*)shareContext -reshapeListener: - (nonnull id)reshapeListener; + reshapeListener: + (nonnull id)reshapeListener; - (nullable instancetype)initWithFrame:(NSRect)frameRect pixelFormat:(nullable NSOpenGLPixelFormat*)format NS_UNAVAILABLE; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterView.mm b/shell/platform/darwin/macos/framework/Source/FlutterView.mm index 91242000ff12d..5f3b46d194960 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterView.mm @@ -9,17 +9,17 @@ @implementation FlutterView { } - (instancetype)initWithShareContext:(NSOpenGLContext*)shareContext -reshapeListener:(id)reshapeListener { + reshapeListener:(id)reshapeListener { return [self initWithFrame:NSZeroRect shareContext:shareContext reshapeListener:reshapeListener]; } - (instancetype)initWithFrame:(NSRect)frame -shareContext:(NSOpenGLContext*)shareContext + shareContext:(NSOpenGLContext*)shareContext reshapeListener:(id)reshapeListener { self = [super initWithFrame:frame]; if (self) { self.openGLContext = [[NSOpenGLContext alloc] initWithFormat:shareContext.pixelFormat - shareContext:shareContext]; + shareContext:shareContext]; _reshapeListener = reshapeListener; self.wantsBestResolutionOpenGLSurface = YES; } From 9b80fc57a64b647e8758f65d9b6c92866c7cf957 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 10 Jul 2019 13:27:45 -0700 Subject: [PATCH 5/5] Add entrypoint support to futher align APIs --- .../darwin/macos/framework/Headers/FLEEngine.h | 15 ++++++++++++--- .../darwin/macos/framework/Source/FLEEngine.mm | 3 ++- .../macos/framework/Source/FLEViewController.mm | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/shell/platform/darwin/macos/framework/Headers/FLEEngine.h b/shell/platform/darwin/macos/framework/Headers/FLEEngine.h index e4cc8f1f10725..307f085b849b2 100644 --- a/shell/platform/darwin/macos/framework/Headers/FLEEngine.h +++ b/shell/platform/darwin/macos/framework/Headers/FLEEngine.h @@ -47,11 +47,20 @@ FLUTTER_EXPORT - (nonnull instancetype)init NS_UNAVAILABLE; /** - * Runs `main()` from this engine's project. + * Runs a Dart program on an Isolate from the main Dart library (i.e. the library that + * contains `main()`). * - * @return YES if the engine launched successfully. + * The first call to this method will create a new Isolate. Subsequent calls will return + * immediately. + * + * @param entrypoint The name of a top-level function from the same Dart + * library that contains the app's main() function. If this is nil, it will + * default to `main()`. If it is not the app's main() function, that function + * must be decorated with `@pragma(vm:entry-point)` to ensure the method is not + * tree-shaken by the Dart compiler. + * @return YES if the call succeeds in creating and running a Flutter Engine instance; NO otherwise. */ -- (BOOL)run; +- (BOOL)runWithEntrypoint:(nullable NSString*)entrypoint; /** * The `FLEViewController` associated with this engine, if any. diff --git a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm index 0bc5db65f31d4..9a50499f309ea 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm @@ -158,7 +158,7 @@ - (void)dealloc { [self shutDownEngine]; } -- (BOOL)run { +- (BOOL)runWithEntrypoint:(NSString*)entrypoint { if (self.running) { return NO; } @@ -188,6 +188,7 @@ - (BOOL)run { flutterArguments.command_line_argc = static_cast(arguments.size()); flutterArguments.command_line_argv = &arguments[0]; flutterArguments.platform_message_callback = (FlutterPlatformMessageCallback)OnPlatformMessage; + flutterArguments.custom_dart_entrypoint = entrypoint.UTF8String; FlutterEngineResult result = FlutterEngineRun( FLUTTER_ENGINE_VERSION, &rendererConfig, &flutterArguments, (__bridge void*)(self), &_engine); diff --git a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm index 35007ce552c2d..7b58c81dab55b 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm @@ -262,7 +262,7 @@ - (BOOL)launchEngine { [self addInternalPlugins]; _engine.viewController = self; - if (![_engine run]) { + if (![_engine runWithEntrypoint:nil]) { return NO; } // Send the initial user settings such as brightness and text scale factor