Skip to content

Commit 25b09e8

Browse files
authored
[macOS] Handle reparenting platform views (flutter#52152)
Fixes flutter#146810 This handles situation where the platform view reparents and replaces itself with a placeholder view. This commonly happens with WKWebView entering full screen. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making or feature I am adding, or the PR is [test-exempt]. See [testing the engine] for instructions on writing and running engine tests. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I signed the [CLA]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
1 parent 0e9e2f4 commit 25b09e8

2 files changed

Lines changed: 34 additions & 3 deletions

File tree

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,9 +602,18 @@ - (void)updatePlatformViewWithBounds:(CGRect)untransformedBounds
602602
[containerSuperview addSubview:_platformViewContainer];
603603
_platformViewContainer.frame = self.bounds;
604604

605-
// Nest the platform view in the PlatformViewContainer.
606-
[_platformViewContainer addSubview:_platformView];
607-
_platformView.frame = untransformedBounds;
605+
// Nest the platform view in the PlatformViewContainer, but only if the view doesn't have a
606+
// superview yet. Sometimes the platform view reparents itself (WKWebView entering FullScreen)
607+
// in which case do not forcefully move it back.
608+
if (_platformView.superview == nil) {
609+
[_platformViewContainer addSubview:_platformView];
610+
}
611+
612+
// Originally first subview would be the _platformView. However during WKWebView full screen
613+
// the platform view gets replaced with a placeholder. Given that _platformViewContainer does
614+
// not contain any other views it is safe to assume that any subview found can be treated
615+
// as the platform view.
616+
_platformViewContainer.subviews.firstObject.frame = untransformedBounds;
608617

609618
// Transform for the platform view is finalTransform adjusted for bounding rect origin.
610619
CATransform3D translation =

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,28 @@ void ExpectTransform3DEqual(const CATransform3D& t, const CATransform3D& u) {
562562
EXPECT_EQ([mutatorView hitTest:NSMakePoint(10, 50)], platformView);
563563
}
564564

565+
TEST(FlutterMutatorViewTest, ReparentingPlatformView) {
566+
NSView* platformView = [[NSView alloc] init];
567+
FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
568+
ApplyFlutterLayer(mutatorView, FlutterSize{100, 100}, {});
569+
EXPECT_TRUE(platformView.superview == mutatorView.platformViewContainer);
570+
EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 100, 100)));
571+
572+
// Reparent platform view and replace it with placeholder (mimicking WKWebKit going full screen)
573+
NSView* newParent = [[NSView alloc] init];
574+
[newParent addSubview:platformView];
575+
platformView.frame = CGRectMake(10, 10, 200, 200);
576+
577+
NSView* placeholderView = [[NSView alloc] init];
578+
[mutatorView.platformViewContainer addSubview:placeholderView];
579+
ApplyFlutterLayer(mutatorView, FlutterSize{100, 100}, {});
580+
581+
// Platform view should not be touched but the replacement view should be properly positioned.
582+
EXPECT_TRUE(platformView.superview == newParent);
583+
EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(10, 10, 200, 200)));
584+
EXPECT_TRUE(CGRectEqualToRect(placeholderView.frame, CGRectMake(0, 0, 100, 100)));
585+
}
586+
565587
@interface FlutterCursorCoordinatorTest : NSObject
566588

567589
@end

0 commit comments

Comments
 (0)