Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit da5fc92

Browse files
authored
[macOS] Make the default background color black. (#36906)
1 parent 10f7f05 commit da5fc92

6 files changed

Lines changed: 140 additions & 0 deletions

File tree

shell/platform/darwin/macos/framework/Headers/FlutterViewController.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,48 @@ FLUTTER_DARWIN_EXPORT
7373
*/
7474
- (void)onPreEngineRestart;
7575

76+
/**
77+
* The contentView (FlutterView)'s background color is set to black during
78+
* its instantiation.
79+
*
80+
* The containing layer's color can be set to the NSColor provided to this method.
81+
*
82+
* For example, the background may be set after the FlutterViewController
83+
* is instantiated in MainFlutterWindow.swift in the Flutter project.
84+
* ```swift
85+
* import Cocoa
86+
* import FlutterMacOS
87+
*
88+
* class MainFlutterWindow: NSWindow {
89+
* override func awakeFromNib() {
90+
* let flutterViewController = FlutterViewController.init()
91+
*
92+
* // The background color of the window and `FlutterViewController`
93+
* // are retained separately.
94+
* //
95+
* // In this example, both the MainFlutterWindow and FlutterViewController's
96+
* // FlutterView's backgroundColor are set to clear to achieve a fully
97+
* // transparent effect.
98+
* //
99+
* // If the window's background color is not set, it will use the system
100+
* // default.
101+
* //
102+
* // If the `FlutterView`'s color is not set via `FlutterViewController.setBackgroundColor`
103+
* // it's default will be black.
104+
* self.backgroundColor = NSColor.clear
105+
* flutterViewController.backgroundColor = NSColor.clear
106+
*
107+
* let windowFrame = self.frame
108+
* self.contentViewController = flutterViewController
109+
* self.setFrame(windowFrame, display: true)
110+
*
111+
* RegisterGeneratedPlugins(registry: flutterViewController)
112+
*
113+
* super.awakeFromNib()
114+
* }
115+
* }
116+
* ```
117+
*/
118+
@property(readwrite, nonatomic, nullable) NSColor* backgroundColor;
119+
76120
@end

shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,67 @@ @interface FlutterEngine (Test)
101101
EXPECT_TRUE(logs.find("Hello logging") != std::string::npos);
102102
}
103103

104+
TEST_F(FlutterEngineTest, BackgroundIsBlack) {
105+
// Launch the test entrypoint.
106+
FlutterEngine* engine = GetFlutterEngine();
107+
EXPECT_TRUE([engine runWithEntrypoint:@"backgroundTest"]);
108+
EXPECT_TRUE(engine.running);
109+
110+
NSString* fixtures = @(flutter::testing::GetFixturesPath());
111+
FlutterDartProject* project = [[FlutterDartProject alloc]
112+
initWithAssetsPath:fixtures
113+
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
114+
FlutterViewController* viewController = [[FlutterViewController alloc] initWithProject:project];
115+
[viewController loadView];
116+
viewController.flutterView.frame = CGRectMake(0, 0, 800, 600);
117+
[engine setViewController:viewController];
118+
119+
// Latch to ensure the entire layer tree has been generated and presented.
120+
fml::AutoResetWaitableEvent latch;
121+
AddNativeCallback("SignalNativeTest", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
122+
CALayer* rootLayer = engine.viewController.flutterView.layer;
123+
EXPECT_TRUE(rootLayer.backgroundColor != nil);
124+
if (rootLayer.backgroundColor != nil) {
125+
NSColor* actualBackgroundColor =
126+
[NSColor colorWithCGColor:rootLayer.backgroundColor];
127+
EXPECT_EQ(actualBackgroundColor, [NSColor blackColor]);
128+
}
129+
latch.Signal();
130+
}));
131+
latch.Wait();
132+
}
133+
134+
TEST_F(FlutterEngineTest, CanOverrideBackgroundColor) {
135+
// Launch the test entrypoint.
136+
FlutterEngine* engine = GetFlutterEngine();
137+
EXPECT_TRUE([engine runWithEntrypoint:@"backgroundTest"]);
138+
EXPECT_TRUE(engine.running);
139+
140+
NSString* fixtures = @(flutter::testing::GetFixturesPath());
141+
FlutterDartProject* project = [[FlutterDartProject alloc]
142+
initWithAssetsPath:fixtures
143+
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
144+
FlutterViewController* viewController = [[FlutterViewController alloc] initWithProject:project];
145+
[viewController loadView];
146+
viewController.flutterView.frame = CGRectMake(0, 0, 800, 600);
147+
[engine setViewController:viewController];
148+
viewController.flutterView.backgroundColor = [NSColor whiteColor];
149+
150+
// Latch to ensure the entire layer tree has been generated and presented.
151+
fml::AutoResetWaitableEvent latch;
152+
AddNativeCallback("SignalNativeTest", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
153+
CALayer* rootLayer = engine.viewController.flutterView.layer;
154+
EXPECT_TRUE(rootLayer.backgroundColor != nil);
155+
if (rootLayer.backgroundColor != nil) {
156+
NSColor* actualBackgroundColor =
157+
[NSColor colorWithCGColor:rootLayer.backgroundColor];
158+
EXPECT_EQ(actualBackgroundColor, [NSColor whiteColor]);
159+
}
160+
latch.Signal();
161+
}));
162+
latch.Wait();
163+
}
164+
104165
TEST_F(FlutterEngineTest, CanToggleAccessibility) {
105166
FlutterEngine* engine = GetFlutterEngine();
106167
// Capture the update callbacks before the embedder API initializes.

shell/platform/darwin/macos/framework/Source/FlutterView.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,13 @@
6868
*/
6969
- (void)shutdown;
7070

71+
/**
72+
* By default, the `FlutterSurfaceManager` creates two layers to manage Flutter
73+
* content, the content layer and containing layer. To set the native background
74+
* color, onto which the Flutter content is drawn, call this method with the
75+
* NSColor which you would like to override the default, black background color
76+
* with.
77+
*/
78+
- (void)setBackgroundColor:(nonnull NSColor*)color;
79+
7180
@end

shell/platform/darwin/macos/framework/Source/FlutterView.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ - (instancetype)initWithMTLDevice:(id<MTLDevice>)device
2828
self = [super initWithFrame:NSZeroRect];
2929
if (self) {
3030
[self setWantsLayer:YES];
31+
[self setBackgroundColor:[NSColor blackColor]];
3132
[self setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawDuringViewResize];
3233
_reshapeListener = reshapeListener;
3334
_resizableBackingStoreProvider =
@@ -51,6 +52,7 @@ - (instancetype)initWithFrame:(NSRect)frame
5152
self = [super initWithFrame:frame];
5253
if (self) {
5354
[self setWantsLayer:YES];
55+
[self setBackgroundColor:[NSColor blackColor]];
5456
_reshapeListener = reshapeListener;
5557
_resizableBackingStoreProvider =
5658
[[FlutterOpenGLResizableBackingStoreProvider alloc] initWithMainContext:mainContext
@@ -84,6 +86,10 @@ - (void)reshaped {
8486
}];
8587
}
8688

89+
- (void)setBackgroundColor:(NSColor*)color {
90+
self.layer.backgroundColor = color.CGColor;
91+
}
92+
8793
#pragma mark - NSView overrides
8894

8995
- (void)setFrameSize:(NSSize)newSize {

shell/platform/darwin/macos/framework/Source/FlutterViewController.mm

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ void Reset() {
159159
*/
160160
@interface FlutterViewWrapper : NSView
161161

162+
- (void)setBackgroundColor:(NSColor*)color;
163+
162164
@end
163165

164166
/**
@@ -266,6 +268,10 @@ - (instancetype)initWithFlutterView:(FlutterView*)view {
266268
return self;
267269
}
268270

271+
- (void)setBackgroundColor:(NSColor*)color {
272+
[_flutterView setBackgroundColor:color];
273+
}
274+
269275
- (NSArray*)accessibilityChildren {
270276
return @[ _flutterView ];
271277
}
@@ -376,6 +382,9 @@ - (void)loadView {
376382
}
377383
flutterView = [[FlutterView alloc] initWithMainContext:mainContext reshapeListener:self];
378384
}
385+
if (_backgroundColor != nil) {
386+
[flutterView setBackgroundColor:_backgroundColor];
387+
}
379388
FlutterViewWrapper* wrapperView = [[FlutterViewWrapper alloc] initWithFlutterView:flutterView];
380389
self.view = wrapperView;
381390
_flutterView = flutterView;
@@ -418,6 +427,11 @@ - (void)setMouseTrackingMode:(FlutterMouseTrackingMode)mode {
418427
[self configureTrackingArea];
419428
}
420429

430+
- (void)setBackgroundColor:(NSColor*)color {
431+
_backgroundColor = color;
432+
[_flutterView setBackgroundColor:_backgroundColor];
433+
}
434+
421435
- (void)onPreEngineRestart {
422436
[self initializeKeyboard];
423437
}

shell/platform/darwin/macos/framework/Source/fixtures/flutter_desktop_test.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,9 @@ Picture _createSimplePicture() {
5757
void nativeCallback() {
5858
signalNativeTest();
5959
}
60+
61+
@pragma('vm:entry-point')
62+
void backgroundTest() {
63+
PlatformDispatcher.instance.views.first.render(SceneBuilder().build());
64+
signalNativeTest(); // should look black
65+
}

0 commit comments

Comments
 (0)