Skip to content

Commit

Permalink
[macOS] Extract PlatformView mutator clip updating (flutter#42164)
Browse files Browse the repository at this point in the history
Extracts `updatePathClipViewsWithPaths:origin:` which updates the stack of AppKit clip views hosting the platform view.

This change is a cleanup change for readability and makes no semantic changes to how mutator views are applied. Existing unit tests in [FlutterMutatorViewTest.mm](https://github.com/flutter/engine/blob/main/shell/platform/darwin/macos/framework/Source/FlutterMutatorViewTest.mm) are expected to pass without changes.

This is refactoring prior to applying a fix for rotation handling.

Issue: flutter/flutter#124490

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
  • Loading branch information
cbracken authored May 19, 2023
1 parent 4f3f7bb commit 3a93bd7
Showing 1 changed file with 26 additions and 24 deletions.
50 changes: 26 additions & 24 deletions shell/platform/darwin/macos/framework/Source/FlutterMutatorView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,30 @@ - (CGFloat)contentsScale {
return self.superview != nil ? self.superview.layer.contentsScale : 1.0;
}

/// Updates the nested stack of clip views that host the platform view.
- (void)updatePathClipViewsWithPaths:(NSArray*)paths {
// Remove path clip views depending on the number of paths.
while (_pathClipViews.count > paths.count) {
NSView* view = _pathClipViews.lastObject;
[view removeFromSuperview];
[_pathClipViews removeLastObject];
}
// Otherwise, add path clip views to the end.
for (size_t i = _pathClipViews.count; i < paths.count; ++i) {
NSView* superView = _pathClipViews.count == 0 ? self : _pathClipViews.lastObject;
FlutterPathClipView* pathClipView = [[FlutterPathClipView alloc] initWithFrame:self.bounds];
[_pathClipViews addObject:pathClipView];
[superView addSubview:pathClipView];
}
// Update bounds and apply clip paths.
for (size_t i = 0; i < _pathClipViews.count; ++i) {
FlutterPathClipView* pathClipView = _pathClipViews[i];
pathClipView.frame = self.bounds;
[pathClipView maskToPath:(__bridge CGPathRef)[paths objectAtIndex:i]
withOrigin:self.frame.origin];
}
}

/// Whenever possible view will be clipped using layer bounds.
/// If clipping to path is needed, CAShapeLayer(s) will be used as mask.
/// Clipping to round rect only clips to path if round corners are intersected.
Expand Down Expand Up @@ -397,37 +421,15 @@ - (void)applyFlutterLayer:(const FlutterLayer*)layer {

/// Paths in global logical coordinates that need to be clipped to.
NSMutableArray* paths = RoundedRectClipsFromMutations(masterClip, mutations);

// Add / remove path clip views depending on the number of paths.
while (_pathClipViews.count > paths.count) {
NSView* view = _pathClipViews.lastObject;
[view removeFromSuperview];
[_pathClipViews removeLastObject];
}

NSView* lastView = self;

for (size_t i = 0; i < paths.count; ++i) {
FlutterPathClipView* pathClipView = nil;
if (i < _pathClipViews.count) {
pathClipView = _pathClipViews[i];
} else {
pathClipView = [[FlutterPathClipView alloc] initWithFrame:self.bounds];
[_pathClipViews addObject:pathClipView];
[lastView addSubview:pathClipView];
}
pathClipView.frame = self.bounds;
[pathClipView maskToPath:(__bridge CGPathRef)[paths objectAtIndex:i]
withOrigin:finalBoundingRect.origin];
lastView = pathClipView;
}
[self updatePathClipViewsWithPaths:paths];

// Used to apply sublayer transform.
if (_platformViewContainer == nil) {
_platformViewContainer = [[NSView alloc] initWithFrame:self.bounds];
_platformViewContainer.wantsLayer = YES;
}

NSView* lastView = _pathClipViews.count == 0 ? self : _pathClipViews.lastObject;
[lastView addSubview:_platformViewContainer];
_platformViewContainer.frame = self.bounds;

Expand Down

0 comments on commit 3a93bd7

Please sign in to comment.