| Flutter macOS Embedder |

FlutterView.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/FlutterView.h"
6
7 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.h"
8 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h"
9
10 #import <QuartzCore/QuartzCore.h>
11
12 @interface FlutterView () <FlutterSurfaceManagerDelegate> {
13 FlutterViewIdentifier _viewIdentifier;
14 __weak id<FlutterViewDelegate> _viewDelegate;
15 FlutterResizeSynchronizer* _resizeSynchronizer;
16 FlutterSurfaceManager* _surfaceManager;
17 NSCursor* _lastCursor;
18 }
19
20 @end
21
22 @implementation FlutterView
23
24 - (instancetype)initWithMTLDevice:(id<MTLDevice>)device
25 commandQueue:(id<MTLCommandQueue>)commandQueue
26 delegate:(id<FlutterViewDelegate>)delegate
27 viewIdentifier:(FlutterViewIdentifier)viewIdentifier {
28 self = [super initWithFrame:NSZeroRect];
29 if (self) {
30 [self setWantsLayer:YES];
31 [self setBackgroundColor:[NSColor blackColor]];
32 [self setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawDuringViewResize];
33 _viewIdentifier = viewIdentifier;
34 _viewDelegate = delegate;
35 _surfaceManager = [[FlutterSurfaceManager alloc] initWithDevice:device
36 commandQueue:commandQueue
37 layer:self.layer
38 delegate:self];
39 _resizeSynchronizer = [[FlutterResizeSynchronizer alloc] init];
40 }
41 return self;
42 }
43
44 - (void)onPresent:(CGSize)frameSize withBlock:(dispatch_block_t)block delay:(NSTimeInterval)delay {
45 [_resizeSynchronizer performCommitForSize:frameSize notify:block delay:delay];
46 }
47
48 - (FlutterSurfaceManager*)surfaceManager {
49 return _surfaceManager;
50 }
51
52 - (void)shutDown {
53 [_resizeSynchronizer shutDown];
54 }
55
56 - (void)setBackgroundColor:(NSColor*)color {
57 self.layer.backgroundColor = color.CGColor;
58 }
59
60 #pragma mark - NSView overrides
61
62 - (void)setFrameSize:(NSSize)newSize {
63 [super setFrameSize:newSize];
64 CGSize scaledSize = [self convertSizeToBacking:self.bounds.size];
65 [_resizeSynchronizer beginResizeForSize:scaledSize
66 notify:^{
67 [_viewDelegate viewDidReshape:self];
68 }];
69 }
70
71 /**
72 * Declares that the view uses a flipped coordinate system, consistent with Flutter conventions.
73 */
74 - (BOOL)isFlipped {
75 return YES;
76 }
77
78 - (BOOL)isOpaque {
79 return YES;
80 }
81
82 /**
83 * Declares that the initial mouse-down when the view is not in focus will send an event to the
84 * view.
85 */
86 - (BOOL)acceptsFirstMouse:(NSEvent*)event {
87 return YES;
88 }
89
90 - (BOOL)acceptsFirstResponder {
91 // This is to ensure that FlutterView does not take first responder status from TextInputPlugin
92 // on mouse clicks.
93 return [_viewDelegate viewShouldAcceptFirstResponder:self];
94 }
95
96 - (void)didUpdateMouseCursor:(NSCursor*)cursor {
97 _lastCursor = cursor;
98 }
99
100 // Restores mouse cursor. There are few cases when this is needed and framework will not handle
101 // this automatically:
102 // - When mouse cursor leaves subview of FlutterView (technically still within bound of
103 // FlutterView tracking area so the framework won't be notified)
104 // - When context menu above FlutterView is closed. Context menu will change current cursor to
105 // arrow and will not restore it back.
106 - (void)cursorUpdate:(NSEvent*)event {
107 // Make sure to not override cursor when over a platform view.
108 NSPoint mouseLocation = [[self superview] convertPoint:event.locationInWindow fromView:nil];
109 NSView* hitTestView = [self hitTest:mouseLocation];
110 if (hitTestView != self) {
111 return;
112 }
113 [_lastCursor set];
114 // It is possible that there is a platform view with NSTrackingArea below flutter content.
115 // This could override the mouse cursor as a result of mouse move event. There is no good way
116 // to prevent that short of swizzling [NSCursor set], so as a workaround force flutter cursor
117 // in next runloop turn. This is not ideal, as it may cause the cursor flicker a bit.
118 [[NSRunLoop currentRunLoop] performBlock:^{
119 [_lastCursor set];
120 }];
121 }
122
123 - (void)viewDidChangeBackingProperties {
124 [super viewDidChangeBackingProperties];
125 // Force redraw
126 [_viewDelegate viewDidReshape:self];
127 }
128
129 - (BOOL)layer:(CALayer*)layer
130 shouldInheritContentsScale:(CGFloat)newScale
131 fromWindow:(NSWindow*)window {
132 return YES;
133 }
134
135 #pragma mark - NSAccessibility overrides
136
137 - (BOOL)isAccessibilityElement {
138 return YES;
139 }
140
141 - (NSAccessibilityRole)accessibilityRole {
142 return NSAccessibilityGroupRole;
143 }
144
145 - (NSString*)accessibilityLabel {
146 // TODO(chunhtai): Provides a way to let developer customize the accessibility
147 // label.
148 // https://github.com/flutter/flutter/issues/75446
149 NSString* applicationName =
150 [NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"];
151 if (!applicationName) {
152 applicationName = [NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleName"];
153 }
154 return applicationName;
155 }
156
157 @end
FlutterResizeSynchronizer.h
FlutterSurfaceManager.h
FlutterView.h
FlutterViewIdentifier
int64_t FlutterViewIdentifier
Definition: FlutterViewController.h:21
FlutterView()::_viewDelegate
__weak id< FlutterViewDelegate > _viewDelegate
Definition: FlutterView.mm:14
FlutterView()::_lastCursor
NSCursor * _lastCursor
Definition: FlutterView.mm:17
FlutterView()::_surfaceManager
FlutterSurfaceManager * _surfaceManager
Definition: FlutterView.mm:16
FlutterView()::_viewIdentifier
FlutterViewIdentifier _viewIdentifier
Definition: FlutterView.mm:13
FlutterView()::_resizeSynchronizer
FlutterResizeSynchronizer * _resizeSynchronizer
Definition: FlutterView.mm:15
FlutterResizeSynchronizer
Definition: FlutterResizeSynchronizer.h:17
FlutterSurfaceManager
Definition: FlutterSurfaceManager.h:47
FlutterView
Definition: FlutterView.h:36
-[FlutterView shutDown]
void shutDown()
Definition: FlutterView.mm:52
FlutterView::surfaceManager
FlutterSurfaceManager * surfaceManager
Definition: FlutterView.h:56
FlutterSurfaceManagerDelegate-p
Definition: FlutterSurfaceManager.h:27
FlutterViewDelegate-p
Definition: FlutterView.h:18