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