Flutter Engine
 
Loading...
Searching...
No Matches
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
6#include <Foundation/Foundation.h>
7
12
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;
21 std::optional<flutter::Isolate> _isolate;
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:(FlutterWindowSize)contentSize;
37- (void)flutterSetConstraints:(FlutterWindowConstraints)constraints;
38
39@end
40
41@implementation NSWindow (FlutterWindowSizing)
42- (void)flutterSetContentSize:(FlutterWindowSize)contentSize {
43 [self setContentSize:NSMakeSize(contentSize.width, contentSize.height)];
44}
45
46- (void)flutterSetConstraints:(FlutterWindowConstraints)constraints {
47 NSSize size = [self frameRectForContentRect:self.frame].size;
48 NSSize originalSize = size;
49 [self setContentMinSize:NSMakeSize(constraints.min_width, constraints.min_height)];
50 size.width = std::max(size.width, constraints.min_width);
51 size.height = std::max(size.height, constraints.min_height);
52 if (constraints.max_width > 0 && constraints.max_height > 0) {
53 [self setContentMaxSize:NSMakeSize(constraints.max_width, constraints.max_height)];
54 size.width = std::min(size.width, constraints.max_width);
55 size.height = std::min(size.height, constraints.max_height);
56 } else {
57 [self setContentMaxSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX)];
58 }
59 if (!NSEqualSizes(originalSize, size)) {
60 [self setContentSize:size];
61 }
62}
63
64@end
65
66@implementation FlutterWindowOwner
67
68@synthesize window = _window;
69@synthesize flutterViewController = _flutterViewController;
70
71- (instancetype)initWithWindow:(NSWindow*)window
72 flutterViewController:(FlutterViewController*)viewController
73 creationRequest:(const FlutterWindowCreationRequest&)creationRequest {
74 if (self = [super init]) {
75 _window = window;
77 _creationRequest = creationRequest;
78 _isolate = flutter::Isolate::Current();
79 }
80 return self;
81}
82
83- (void)windowDidBecomeKey:(NSNotification*)notification {
84 [_flutterViewController.engine windowDidBecomeKey:_flutterViewController.viewIdentifier];
85}
86
87- (void)windowDidResignKey:(NSNotification*)notification {
88 [_flutterViewController.engine windowDidResignKey:_flutterViewController.viewIdentifier];
89}
90
91- (BOOL)windowShouldClose:(NSWindow*)sender {
92 flutter::IsolateScope isolate_scope(*_isolate);
93 _creationRequest.on_close();
94 return NO;
95}
96
97- (void)windowDidResize:(NSNotification*)notification {
98 flutter::IsolateScope isolate_scope(*_isolate);
99 _creationRequest.notify_listeners();
100}
101
102// Miniaturize does not trigger resize event, but for now there
103// is no other way to get notification about the state change.
104- (void)windowDidMiniaturize:(NSNotification*)notification {
105 flutter::IsolateScope isolate_scope(*_isolate);
106 _creationRequest.notify_listeners();
107}
108
109// Deminiaturize does not trigger resize event, but for now there
110// is no other way to get notification about the state change.
111- (void)windowDidDeminiaturize:(NSNotification*)notification {
112 flutter::IsolateScope isolate_scope(*_isolate);
113 _creationRequest.notify_listeners();
114}
115
116- (void)windowWillEnterFullScreen:(NSNotification*)notification {
117 flutter::IsolateScope isolate_scope(*_isolate);
118 _creationRequest.notify_listeners();
119}
120
121- (void)windowWillExitFullScreen:(NSNotification*)notification {
122 flutter::IsolateScope isolate_scope(*_isolate);
123 _creationRequest.notify_listeners();
124}
125
126@end
127
129 NSMutableArray<FlutterWindowOwner*>* _windows;
130}
131
132@end
133
134@implementation FlutterWindowController
135
136- (instancetype)init {
137 self = [super init];
138 if (self != nil) {
139 _windows = [NSMutableArray array];
140 }
141 return self;
142}
143
144- (FlutterViewIdentifier)createRegularWindow:(const FlutterWindowCreationRequest*)request {
145 FlutterViewController* c = [[FlutterViewController alloc] initWithEngine:_engine
146 nibName:nil
147 bundle:nil];
148
149 NSWindow* window = [[NSWindow alloc] init];
150 // If this is not set there will be double free on window close when
151 // using ARC.
152 [window setReleasedWhenClosed:NO];
153
154 window.contentViewController = c;
155 window.styleMask = NSWindowStyleMaskResizable | NSWindowStyleMaskTitled |
156 NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
157 if (request->has_size) {
158 [window flutterSetContentSize:request->size];
159 }
160 if (request->has_constraints) {
161 [window flutterSetConstraints:request->constraints];
162 }
163 [window setIsVisible:YES];
164 [window makeKeyAndOrderFront:nil];
165
166 FlutterWindowOwner* w = [[FlutterWindowOwner alloc] initWithWindow:window
167 flutterViewController:c
168 creationRequest:*request];
169 window.delegate = w;
170 [_windows addObject:w];
171
172 return c.viewIdentifier;
173}
174
175- (void)destroyWindow:(NSWindow*)window {
176 FlutterWindowOwner* owner = nil;
177 for (FlutterWindowOwner* o in _windows) {
178 if (o.window == window) {
179 owner = o;
180 break;
181 }
182 }
183 if (owner != nil) {
184 [_windows removeObject:owner];
185 // Make sure to unregister the controller from the engine and remove the FlutterView
186 // before destroying the window and Flutter NSView.
187 [owner.flutterViewController dispose];
188 owner.window.delegate = nil;
189 [owner.window close];
190 }
191}
192
193- (void)closeAllWindows {
194 for (FlutterWindowOwner* owner in _windows) {
195 [owner.flutterViewController dispose];
196 [owner.window close];
197 }
198 [_windows removeAllObjects];
199}
200
201@end
202
203// NOLINTBEGIN(google-objc-function-naming)
204
206 int64_t engine_id,
207 const FlutterWindowCreationRequest* request) {
208 FlutterEngine* engine = [FlutterEngine engineForIdentifier:engine_id];
209 [engine enableMultiView];
210 return [engine.windowController createRegularWindow:request];
211}
212
213void InternalFlutter_Window_Destroy(int64_t engine_id, void* window) {
214 NSWindow* w = (__bridge NSWindow*)window;
215 FlutterEngine* engine = [FlutterEngine engineForIdentifier:engine_id];
216 [engine.windowController destroyWindow:w];
217}
218
220 FlutterEngine* engine = [FlutterEngine engineForIdentifier:engine_id];
221 FlutterViewController* controller = [engine viewControllerForIdentifier:view_id];
222 return (__bridge void*)controller.view.window;
223}
224
226 NSWindow* w = (__bridge NSWindow*)window;
227 NSRect contentRect = [w contentRectForFrameRect:w.frame];
228 return {
229 .width = contentRect.size.width,
230 .height = contentRect.size.height,
231 };
232}
233
235 NSWindow* w = (__bridge NSWindow*)window;
236 [w flutterSetContentSize:*size];
237}
238
241 const FlutterWindowConstraints* constraints) {
242 NSWindow* w = (__bridge NSWindow*)window;
243 [w flutterSetConstraints:*constraints];
244}
245
246void InternalFlutter_Window_SetTitle(void* window, const char* title) {
247 NSWindow* w = (__bridge NSWindow*)window;
248 w.title = [NSString stringWithUTF8String:title];
249}
250
251void InternalFlutter_Window_SetMaximized(void* window, bool maximized) {
252 NSWindow* w = (__bridge NSWindow*)window;
253 if (maximized & !w.isZoomed) {
254 [w zoom:nil];
255 } else if (!maximized && w.isZoomed) {
256 [w zoom:nil];
257 }
258}
259
261 NSWindow* w = (__bridge NSWindow*)window;
262 return w.isZoomed;
263}
264
266 NSWindow* w = (__bridge NSWindow*)window;
267 [w miniaturize:nil];
268}
269
271 NSWindow* w = (__bridge NSWindow*)window;
272 [w deminiaturize:nil];
273}
274
276 NSWindow* w = (__bridge NSWindow*)window;
277 return w.isMiniaturized;
278}
279
280void InternalFlutter_Window_SetFullScreen(void* window, bool fullScreen) {
281 NSWindow* w = (__bridge NSWindow*)window;
282 bool isFullScreen = (w.styleMask & NSWindowStyleMaskFullScreen) != 0;
283 if (fullScreen && !isFullScreen) {
284 [w toggleFullScreen:nil];
285 } else if (!fullScreen && isFullScreen) {
286 [w toggleFullScreen:nil];
287 }
288}
289
291 NSWindow* w = (__bridge NSWindow*)window;
292 return (w.styleMask & NSWindowStyleMaskFullScreen) != 0;
293}
294
296 NSWindow* w = (__bridge NSWindow*)window;
297 [NSApplication.sharedApplication activateIgnoringOtherApps:YES];
298 [w makeKeyAndOrderFront:nil];
299}
300
302 NSWindow* w = (__bridge NSWindow*)window;
303 return strdup(w.title.UTF8String);
304}
305
307 NSWindow* w = (__bridge NSWindow*)window;
308 return w.isKeyWindow;
309}
310
311// NOLINTEND(google-objc-function-naming)
#define FLUTTER_DARWIN_EXPORT
UIViewController< FlutterViewResponder > * _flutterViewController
void InternalFlutter_Window_Activate(void *window)
bool InternalFlutter_Window_IsMaximized(void *window)
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_SetConstraints(void *window, const FlutterWindowConstraints *constraints)
bool InternalFlutter_Window_IsActivated(void *window)
int64_t InternalFlutter_WindowController_CreateRegularWindow(int64_t engine_id, const FlutterWindowCreationRequest *request)
void InternalFlutter_Window_SetFullScreen(void *window, bool fullScreen)
bool InternalFlutter_Window_IsFullScreen(void *window)
void InternalFlutter_Window_SetContentSize(void *window, const FlutterWindowSize *size)
void InternalFlutter_Window_Minimize(void *window)
void * InternalFlutter_Window_GetHandle(int64_t engine_id, FlutterViewIdentifier view_id)
void InternalFlutter_Window_SetTitle(void *window, const char *title)
bool InternalFlutter_Window_IsMinimized(void *window)
void InternalFlutter_Window_Destroy(int64_t engine_id, void *window)
void InternalFlutter_Window_SetMaximized(void *window, bool maximized)
char * InternalFlutter_Window_GetTitle(void *window)
FlutterWindowSize InternalFlutter_Window_GetContentSize(void *window)
void InternalFlutter_Window_Unminimize(void *window)
NSMutableArray< FlutterWindowOwner * > * _windows
static Isolate Current()
GLFWwindow * window
Definition main.cc:60
FlutterEngine engine
Definition main.cc:84
G_BEGIN_DECLS FlutterViewId view_id
FlutterViewIdentifier viewIdentifier
FlutterViewController * _flutterViewController
std::optional< flutter::Isolate > _isolate
FlutterWindowCreationRequest _creationRequest
FlutterViewController * viewController
int64_t FlutterViewIdentifier
int BOOL