Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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> {
14 __weak id<FlutterViewDelegate> _viewDelegate;
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
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
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 NSView* hitTestView = [self hitTest:[self convertPoint:event.locationInWindow fromView:nil]];
111 if (hitTestView != self) {
112 return;
113 }
114 [_lastCursor set];
115 // It is possible that there is a platform view with NSTrackingArea below flutter content.
116 // This could override the mouse cursor as a result of mouse move event. There is no good way
117 // to prevent that short of swizzling [NSCursor set], so as a workaround force flutter cursor
118 // in next runloop turn. This is not ideal, as it may cause the cursor flicker a bit.
119 [[NSRunLoop currentRunLoop] performBlock:^{
120 [_lastCursor set];
121 }];
122}
123
125 [super viewDidChangeBackingProperties];
126 // Force redraw
127 [_viewDelegate viewDidReshape:self];
128}
129
130- (BOOL)layer:(CALayer*)layer
131 shouldInheritContentsScale:(CGFloat)newScale
132 fromWindow:(NSWindow*)window {
133 return YES;
134}
135
136#pragma mark - NSAccessibility overrides
137
139 return YES;
140}
141
142- (NSAccessibilityRole)accessibilityRole {
143 return NSAccessibilityGroupRole;
144}
145
146- (NSString*)accessibilityLabel {
147 // TODO(chunhtai): Provides a way to let developer customize the accessibility
148 // label.
149 // https://github.com/flutter/flutter/issues/75446
150 NSString* applicationName =
151 [NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"];
152 if (!applicationName) {
153 applicationName = [NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleName"];
154 }
155 return applicationName;
156}
157
158@end
SkColor4f color
BOOL acceptsFirstResponder()
BOOL isAccessibilityElement()
__weak id< FlutterViewDelegate > _viewDelegate
FlutterSurfaceManager * surfaceManager
Definition FlutterView.h:57
NSString * accessibilityLabel()
NSAccessibilityRole accessibilityRole()
void viewDidChangeBackingProperties()
NSCursor * _lastCursor
FlutterSurfaceManager * _surfaceManager
FlutterThreadSynchronizer * _threadSynchronizer
FlutterViewIdentifier _viewIdentifier
int64_t FlutterViewIdentifier
FlutterThreadSynchronizer * _threadSynchronizer
int BOOL