| Flutter macOS Embedder |

FlutterWindowController.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterWindowController.h"
6 #include <Foundation/Foundation.h>
7
8 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
9 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h"
10 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
11 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
12
13 #include "flutter/shell/platform/common/isolate_scope.h"
14
15 // A delegate for a Flutter managed window.
16 @interface FlutterWindowOwner : NSObject <NSWindowDelegate> {
17 // Strong reference to the window. This is the only strong reference to the
18 // window.
19 NSWindow* _window;
20 FlutterViewController* _flutterViewController;
21 std::optional<flutter::Isolate> _isolate;
22 FlutterWindowCreationRequest _creationRequest;
23 }
24
25 @property(readonly, nonatomic) NSWindow* window;
26 @property(readonly, nonatomic) FlutterViewController* flutterViewController;
27
28 - (instancetype)initWithWindow:(NSWindow*)window
29 flutterViewController:(FlutterViewController*)viewController
30 creationRequest:(const FlutterWindowCreationRequest&)creationRequest;
31
32 @end
33
34 @interface NSWindow (FlutterWindowSizing)
35
36 - (void)flutterSetContentSize:(FlutterWindowSizing)contentSize;
37
38 @end
39
40 @implementation NSWindow (FlutterWindowSizing)
41 - (void)flutterSetContentSize:(FlutterWindowSizing)contentSize {
42 if (contentSize.has_size) {
43 [self setContentSize:NSMakeSize(contentSize.width, contentSize.height)];
44 }
45 if (contentSize.has_constraints) {
46 [self setContentMinSize:NSMakeSize(contentSize.min_width, contentSize.min_height)];
47 if (contentSize.max_width > 0 && contentSize.max_height > 0) {
48 [self setContentMaxSize:NSMakeSize(contentSize.max_width, contentSize.max_height)];
49 } else {
50 [self setContentMaxSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX)];
51 }
52 }
53 }
54
55 @end
56
57 @implementation FlutterWindowOwner
58
59 @synthesize window = _window;
60 @synthesize flutterViewController = _flutterViewController;
61
62 - (instancetype)initWithWindow:(NSWindow*)window
63 flutterViewController:(FlutterViewController*)viewController
64 creationRequest:(const FlutterWindowCreationRequest&)creationRequest {
65 if (self = [super init]) {
66 _window = window;
67 _flutterViewController = viewController;
68 _creationRequest = creationRequest;
69 _isolate = flutter::Isolate::Current();
70 }
71 return self;
72 }
73
74 - (void)windowDidBecomeKey:(NSNotification*)notification {
75 [_flutterViewController.engine windowDidBecomeKey:_flutterViewController.viewIdentifier];
76 }
77
78 - (void)windowDidResignKey:(NSNotification*)notification {
79 [_flutterViewController.engine windowDidResignKey:_flutterViewController.viewIdentifier];
80 }
81
82 - (BOOL)windowShouldClose:(NSWindow*)sender {
83 flutter::IsolateScope isolate_scope(*_isolate);
84 _creationRequest.on_close();
85 return NO;
86 }
87
88 - (void)windowDidResize:(NSNotification*)notification {
89 flutter::IsolateScope isolate_scope(*_isolate);
90 _creationRequest.on_size_change();
91 }
92
93 // Miniaturize does not trigger resize event, but for now there
94 // is no other way to get notification about the state change.
95 - (void)windowDidMiniaturize:(NSNotification*)notification {
96 flutter::IsolateScope isolate_scope(*_isolate);
97 _creationRequest.on_size_change();
98 }
99
100 // Deminiaturize does not trigger resize event, but for now there
101 // is no other way to get notification about the state change.
102 - (void)windowDidDeminiaturize:(NSNotification*)notification {
103 flutter::IsolateScope isolate_scope(*_isolate);
104 _creationRequest.on_size_change();
105 }
106
107 @end
108
109 @interface FlutterWindowController () {
110 NSMutableArray<FlutterWindowOwner*>* _windows;
111 }
112
113 @end
114
115 @implementation FlutterWindowController
116
117 - (instancetype)init {
118 self = [super init];
119 if (self != nil) {
120 _windows = [NSMutableArray array];
121 }
122 return self;
123 }
124
125 - (FlutterViewIdentifier)createRegularWindow:(const FlutterWindowCreationRequest*)request {
126 FlutterViewController* c = [[FlutterViewController alloc] initWithEngine:_engine
127 nibName:nil
128 bundle:nil];
129
130 NSWindow* window = [[NSWindow alloc] init];
131 // If this is not set there will be double free on window close when
132 // using ARC.
133 [window setReleasedWhenClosed:NO];
134
135 window.contentViewController = c;
136 window.styleMask = NSWindowStyleMaskResizable | NSWindowStyleMaskTitled |
137 NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
138 [window flutterSetContentSize:request->contentSize];
139 [window setIsVisible:YES];
140 [window makeKeyAndOrderFront:nil];
141
142 FlutterWindowOwner* w = [[FlutterWindowOwner alloc] initWithWindow:window
143 flutterViewController:c
144 creationRequest:*request];
145 window.delegate = w;
146 [_windows addObject:w];
147
148 return c.viewIdentifier;
149 }
150
151 - (void)destroyWindow:(NSWindow*)window {
152 FlutterWindowOwner* owner = nil;
153 for (FlutterWindowOwner* o in _windows) {
154 if (o.window == window) {
155 owner = o;
156 break;
157 }
158 }
159 if (owner != nil) {
160 [_windows removeObject:owner];
161 // Make sure to unregister the controller from the engine and remove the FlutterView
162 // before destroying the window and Flutter NSView.
163 [owner.flutterViewController dispose];
164 owner.window.delegate = nil;
165 [owner.window close];
166 }
167 }
168
169 - (void)closeAllWindows {
170 for (FlutterWindowOwner* owner in _windows) {
171 [owner.flutterViewController dispose];
172 [owner.window close];
173 }
174 [_windows removeAllObjects];
175 }
176
177 @end
178
179 // NOLINTBEGIN(google-objc-function-naming)
180
181 int64_t InternalFlutter_WindowController_CreateRegularWindow(
182 int64_t engine_id,
183 const FlutterWindowCreationRequest* request) {
184 FlutterEngine* engine = [FlutterEngine engineForIdentifier:engine_id];
185 [engine enableMultiView];
186 return [engine.windowController createRegularWindow:request];
187 }
188
189 void InternalFlutter_Window_Destroy(int64_t engine_id, void* window) {
190 NSWindow* w = (__bridge NSWindow*)window;
191 FlutterEngine* engine = [FlutterEngine engineForIdentifier:engine_id];
192 [engine.windowController destroyWindow:w];
193 }
194
195 void* InternalFlutter_Window_GetHandle(int64_t engine_id, FlutterViewIdentifier view_id) {
196 FlutterEngine* engine = [FlutterEngine engineForIdentifier:engine_id];
197 FlutterViewController* controller = [engine viewControllerForIdentifier:view_id];
198 return (__bridge void*)controller.view.window;
199 }
200
201 FlutterWindowSize InternalFlutter_Window_GetContentSize(void* window) {
202 NSWindow* w = (__bridge NSWindow*)window;
203 return {
204 .width = w.frame.size.width,
205 .height = w.frame.size.height,
206 };
207 }
208
209 void InternalFlutter_Window_SetContentSize(void* window, const FlutterWindowSizing* size) {
210 NSWindow* w = (__bridge NSWindow*)window;
211 [w flutterSetContentSize:*size];
212 }
213
214 void InternalFlutter_Window_SetTitle(void* window, const char* title) {
215 NSWindow* w = (__bridge NSWindow*)window;
216 w.title = [NSString stringWithUTF8String:title];
217 }
218
219 void InternalFlutter_Window_SetMaximized(void* window, bool maximized) {
220 NSWindow* w = (__bridge NSWindow*)window;
221 if (maximized & !w.isZoomed) {
222 [w zoom:nil];
223 } else if (!maximized && w.isZoomed) {
224 [w zoom:nil];
225 }
226 }
227
228 bool InternalFlutter_Window_IsMaximized(void* window) {
229 NSWindow* w = (__bridge NSWindow*)window;
230 return w.isZoomed;
231 }
232
233 void InternalFlutter_Window_Minimize(void* window) {
234 NSWindow* w = (__bridge NSWindow*)window;
235 [w miniaturize:nil];
236 }
237
238 void InternalFlutter_Window_Unminimize(void* window) {
239 NSWindow* w = (__bridge NSWindow*)window;
240 [w deminiaturize:nil];
241 }
242
243 bool InternalFlutter_Window_IsMinimized(void* window) {
244 NSWindow* w = (__bridge NSWindow*)window;
245 return w.isMiniaturized;
246 }
247
248 void InternalFlutter_Window_SetFullScreen(void* window, bool fullScreen) {
249 NSWindow* w = (__bridge NSWindow*)window;
250 bool isFullScreen = (w.styleMask & NSWindowStyleMaskFullScreen) != 0;
251 if (fullScreen && !isFullScreen) {
252 [w toggleFullScreen:nil];
253 } else if (!fullScreen && isFullScreen) {
254 [w toggleFullScreen:nil];
255 }
256 }
257
258 bool InternalFlutter_Window_IsFullScreen(void* window) {
259 NSWindow* w = (__bridge NSWindow*)window;
260 return (w.styleMask & NSWindowStyleMaskFullScreen) != 0;
261 }
262
263 void InternalFlutter_Window_Activate(void* window) {
264 NSWindow* w = (__bridge NSWindow*)window;
265 [NSApplication.sharedApplication activateIgnoringOtherApps:YES];
266 [w makeKeyAndOrderFront:nil];
267 }
268
269 // NOLINTEND(google-objc-function-naming)
FlutterChannels.h
FlutterCodecs.h
FlutterEngine_Internal.h
FlutterViewIdentifier
int64_t FlutterViewIdentifier
Definition: FlutterViewController.h:21
FlutterViewController_Internal.h
FlutterWindowController.h
InternalFlutter_Window_Activate
void InternalFlutter_Window_Activate(void *window)
Definition: FlutterWindowController.mm:263
InternalFlutter_Window_GetHandle
void * InternalFlutter_Window_GetHandle(int64_t engine_id, FlutterViewIdentifier view_id)
Definition: FlutterWindowController.mm:195
InternalFlutter_Window_IsMaximized
bool InternalFlutter_Window_IsMaximized(void *window)
Definition: FlutterWindowController.mm:228
InternalFlutter_Window_SetContentSize
void InternalFlutter_Window_SetContentSize(void *window, const FlutterWindowSizing *size)
Definition: FlutterWindowController.mm:209
InternalFlutter_WindowController_CreateRegularWindow
int64_t InternalFlutter_WindowController_CreateRegularWindow(int64_t engine_id, const FlutterWindowCreationRequest *request)
Definition: FlutterWindowController.mm:181
InternalFlutter_Window_SetFullScreen
void InternalFlutter_Window_SetFullScreen(void *window, bool fullScreen)
Definition: FlutterWindowController.mm:248
InternalFlutter_Window_IsFullScreen
bool InternalFlutter_Window_IsFullScreen(void *window)
Definition: FlutterWindowController.mm:258
InternalFlutter_Window_Minimize
void InternalFlutter_Window_Minimize(void *window)
Definition: FlutterWindowController.mm:233
InternalFlutter_Window_SetTitle
void InternalFlutter_Window_SetTitle(void *window, const char *title)
Definition: FlutterWindowController.mm:214
InternalFlutter_Window_IsMinimized
bool InternalFlutter_Window_IsMinimized(void *window)
Definition: FlutterWindowController.mm:243
InternalFlutter_Window_Destroy
void InternalFlutter_Window_Destroy(int64_t engine_id, void *window)
Definition: FlutterWindowController.mm:189
InternalFlutter_Window_SetMaximized
void InternalFlutter_Window_SetMaximized(void *window, bool maximized)
Definition: FlutterWindowController.mm:219
InternalFlutter_Window_GetContentSize
FlutterWindowSize InternalFlutter_Window_GetContentSize(void *window)
Definition: FlutterWindowController.mm:201
InternalFlutter_Window_Unminimize
void InternalFlutter_Window_Unminimize(void *window)
Definition: FlutterWindowController.mm:238
FlutterWindowController()::_windows
NSMutableArray< FlutterWindowOwner * > * _windows
Definition: FlutterWindowController.mm:110
-[FlutterWindowController(Testing) closeAllWindows]
void closeAllWindows()
NSWindow(FlutterWindowSizing)
Definition: FlutterWindowController.mm:34
flutter::Isolate::Current
static Isolate Current()
Definition: isolate_scope.cc:9
flutter::IsolateScope
Definition: isolate_scope.h:33
FlutterEngine
Definition: FlutterEngine.h:32
FlutterViewController
Definition: FlutterViewController.h:73
FlutterViewController::viewIdentifier
FlutterViewIdentifier viewIdentifier
Definition: FlutterViewController.h:130
FlutterWindowController
Definition: FlutterWindowController.h:16
FlutterWindowController::engine
FlutterEngine * engine
Definition: FlutterWindowController.h:17
FlutterWindowOwner
Definition: FlutterWindowController.mm:16
FlutterWindowOwner::_window
NSWindow * _window
Definition: FlutterWindowController.mm:19
FlutterWindowOwner::_flutterViewController
FlutterViewController * _flutterViewController
Definition: FlutterWindowController.mm:20
FlutterWindowOwner::window
NSWindow * window
Definition: FlutterWindowController.mm:25
FlutterWindowOwner::flutterViewController
FlutterViewController * flutterViewController
Definition: FlutterWindowController.mm:26
FlutterWindowOwner::_isolate
std::optional< flutter::Isolate > _isolate
Definition: FlutterWindowController.mm:21
FlutterWindowOwner::_creationRequest
FlutterWindowCreationRequest _creationRequest
Definition: FlutterWindowController.mm:22
isolate_scope.h
FlutterWindowCreationRequest
Definition: FlutterWindowController.h:38
FlutterWindowCreationRequest::on_size_change
void(* on_size_change)()
Definition: FlutterWindowController.h:41
FlutterWindowCreationRequest::on_close
void(* on_close)()
Definition: FlutterWindowController.h:40
FlutterWindowSize
Definition: FlutterWindowController.h:44
FlutterWindowSizing
Definition: FlutterWindowController.h:27
FlutterWindowSizing::has_constraints
bool has_constraints
Definition: FlutterWindowController.h:31
FlutterWindowSizing::max_height
double max_height
Definition: FlutterWindowController.h:35
FlutterWindowSizing::max_width
double max_width
Definition: FlutterWindowController.h:34
FlutterWindowSizing::has_size
bool has_size
Definition: FlutterWindowController.h:28