Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
021480d
Resolving merge conflicts.
emilyabest Jun 10, 2022
5027753
Removed trailing whitespace
emilyabest Jul 15, 2022
24731fa
Removed conflict code. Initial attempt with backdrop filter case.
emilyabest Jul 15, 2022
83b6607
Removed duplicate test
emilyabest Jul 18, 2022
fb0684c
Reverted code to pass the unit tests. Prepared method calls for mergi…
emilyabest Jul 19, 2022
31567f4
Ran whitespace check
emilyabest Jul 19, 2022
2bca987
Bringing back old checks.
emilyabest Jul 19, 2022
e830e4a
Updated code to plug into Javon's PR. Started unit tests for integrat…
emilyabest Jul 19, 2022
c881e11
Saving applyBackdropFilterWithRadius method for reference.
emilyabest Jul 20, 2022
81d2d71
Removed applyBackdropFilterWithRadius method. This is the new startin…
emilyabest Jul 20, 2022
bc2e1b1
Updated unit tests to use applyBackdropFilter method
emilyabest Jul 21, 2022
ff81803
Ran clang checks
emilyabest Jul 21, 2022
359a10d
First implementation to allow multiple backdrop filters. Also reorgan…
emilyabest Jul 21, 2022
cfd473d
Fixed BAD ACCESS error with private instance variable. Prepped for gi…
emilyabest Jul 22, 2022
ac3d4cf
Ran formatting checks
emilyabest Jul 22, 2022
c501a80
Condensed applyBackdropFilter method
emilyabest Jul 25, 2022
b4c64b6
Updated spacing.
emilyabest Jul 25, 2022
0f147e9
Formatted code
emilyabest Jul 25, 2022
604113e
Quick fix for failing applyBackdropFilters unit test. Started PR comm…
emilyabest Jul 27, 2022
ade2908
Added unit tests for non-DlImageBlurFilters. Made activeGaussianFilte…
emilyabest Jul 27, 2022
6a1e014
Formatting checks
emilyabest Jul 27, 2022
e07cb72
Minor formatting changes
emilyabest Jul 28, 2022
d9bcea9
Minor changes for visual testing.
emilyabest Jul 28, 2022
4ae563b
Ran formatting checks
emilyabest Jul 28, 2022
8e48100
Merge branch 'main' into BackdropView
emilyabest Jul 28, 2022
b18c2ad
Updated code to work with Chris' PR
emilyabest Aug 1, 2022
732c94d
Formatted code
emilyabest Aug 1, 2022
d6066ec
Resolved memory leak failure. Commented pass by reference alternative.
emilyabest Aug 2, 2022
2450016
Reorganized extraction method to use a for loop
emilyabest Aug 2, 2022
995fd57
Formatted code. Previous commit also updates API checks
emilyabest Aug 2, 2022
20a7d8f
Added unit test for invalid UIVEV API
emilyabest Aug 3, 2022
d81676f
Formatting check
emilyabest Aug 3, 2022
4e9da14
Implemented Chris' last comments, reverted back to original check to …
emilyabest Aug 4, 2022
2bdaec3
Formatting checks
emilyabest Aug 4, 2022
dc064ed
Removed typo
emilyabest Aug 4, 2022
beb4090
Formatting checks
emilyabest Aug 4, 2022
5599649
Moved blurEffectView release. Working on GitHub error.
emilyabest Aug 9, 2022
def8905
Formatting checks
emilyabest Aug 9, 2022
d010037
Adding gaussianFilter copies
emilyabest Aug 9, 2022
029d7cc
Formatting checks
emilyabest Aug 9, 2022
673b641
Simplified applyBackdropBlurFilter method
emilyabest Aug 10, 2022
aeef63e
Formatting checks
emilyabest Aug 10, 2022
b434756
Moved blurEffectView release to dealloc. Simplified while loops to cl…
emilyabest Aug 10, 2022
9429015
Simplified applyBackdropBlurFilters method
emilyabest Aug 10, 2022
cfea8e9
Trying a different init method for newGaussianFilters.
emilyabest Aug 10, 2022
3ed695d
Added autorelease after copying _gaussianFilter
emilyabest Aug 11, 2022
c4ab9cb
Merge branch 'main' into BackdropViewPreRebase
emilyabest Aug 12, 2022
a1ca917
review feedbacks
Aug 13, 2022
ee25e17
remove TODOs
Aug 18, 2022
92cc72b
fixes
Aug 18, 2022
1dca0dd
update golden
Aug 18, 2022
0702129
Merge branch 'main' into BackdropView
Aug 22, 2022
c810c40
Revert "Revert "Pushing BackdropFilter Mutator (#34355)" (#35543)"
Aug 22, 2022
a043cca
merge main
Aug 29, 2022
fd24904
update golden
Aug 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
if (flutter_view_ == nullptr) {
return;
}

Comment thread
emilyabest marked this conversation as resolved.
Outdated
FML_DCHECK(CATransform3DEqualToTransform(embedded_view.layer.transform, CATransform3DIdentity));
ResetAnchor(embedded_view.layer);
ChildClippingView* clipView = (ChildClippingView*)embedded_view.superview;
Expand Down Expand Up @@ -423,6 +424,7 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
embedded_view.alpha = (*iter)->GetAlphaFloat() * embedded_view.alpha;
break;
case kBackdropFilter:
[clipView applyBackdropFilterWithRadius:@(5)];
break;
}
++iter;
Expand Down
124 changes: 124 additions & 0 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

#import <OCMock/OCMock.h>
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>

#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
Expand Down Expand Up @@ -242,6 +243,129 @@ - (void)testChildClippingViewHitTests {
XCTAssertTrue([childClippingView pointInside:CGPointMake(199, 199) withEvent:nil]);
}

- (void)testChildClippingViewApplyBackdropFilter {
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
/*platform=*/thread_task_runner,
/*raster=*/thread_task_runner,
/*ui=*/thread_task_runner,
/*io=*/thread_task_runner);
auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
/*delegate=*/mock_delegate,
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*platform_views_controller=*/flutterPlatformViewsController,
/*task_runners=*/runners);

FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
[[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease];
flutterPlatformViewsController->RegisterViewFactory(
factory, @"MockFlutterPlatformView",
FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
FlutterResult result = ^(id result) {
};
flutterPlatformViewsController->OnMethodCall(
[FlutterMethodCall
methodCallWithMethodName:@"create"
arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
result); // TODO EMILY: should viewType be backdropFilter?

XCTAssertNotNil(gMockPlatformView);

UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)] autorelease];
flutterPlatformViewsController->SetFlutterView(mockFlutterView);
// Create embedded view params
flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack
SkMatrix screenScaleMatrix =
SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
stack.PushTransform(screenScaleMatrix); // TODO EMILY: change this to PushBackdropFilter

auto embeddedViewParams =
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack);

flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
flutterPlatformViewsController->CompositeEmbeddedView(2);
XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]);
ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview;
[mockFlutterView addSubview:childClippingView];

[mockFlutterView setNeedsLayout];
[mockFlutterView layoutIfNeeded];

// childClippingView has the CAFilter
XCTAssertEqual(1, (int)[childClippingView.layer.filters count]);
Comment thread
cyanglaz marked this conversation as resolved.

NSObject* gaussianFilter = [childClippingView.layer.filters firstObject];
XCTAssertEqual(@(5), [gaussianFilter valueForKey:@"inputRadius"]);

// No new views were added
XCTAssertEqual(0, (int)[gMockPlatformView.subviews count]);
}

- (void)testChildClippingViewApplyDuplicateBackdropFilter {
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
/*platform=*/thread_task_runner,
/*raster=*/thread_task_runner,
/*ui=*/thread_task_runner,
/*io=*/thread_task_runner);
auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
/*delegate=*/mock_delegate,
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*platform_views_controller=*/flutterPlatformViewsController,
/*task_runners=*/runners);

FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
[[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease];
flutterPlatformViewsController->RegisterViewFactory(
factory, @"MockFlutterPlatformView",
FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
FlutterResult result = ^(id result) {
};
flutterPlatformViewsController->OnMethodCall(
[FlutterMethodCall
methodCallWithMethodName:@"create"
arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
result); // TODO EMILY: should viewType be backdropFilter?

XCTAssertNotNil(gMockPlatformView);

UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)] autorelease];
flutterPlatformViewsController->SetFlutterView(mockFlutterView);
// Create embedded view params
flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack
SkMatrix screenScaleMatrix =
SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
stack.PushTransform(screenScaleMatrix); // TODO EMILY: change this to PushBackdropFilter
stack.PushTransform(screenScaleMatrix);

auto embeddedViewParams =
std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make(10, 10), stack);

flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
flutterPlatformViewsController->CompositeEmbeddedView(2);
XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:[ChildClippingView class]]);
ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview;
[mockFlutterView addSubview:childClippingView];

[mockFlutterView setNeedsLayout];
[mockFlutterView layoutIfNeeded];

// childClippingView has the CAFilter, no additional filters were added
XCTAssertEqual(1, (int)[childClippingView.layer.filters count]);

NSObject* gaussianFilter = [childClippingView.layer.filters firstObject];
XCTAssertEqual(@(5), [gaussianFilter valueForKey:@"inputRadius"]);

// No new views were added
XCTAssertEqual(0, (int)[gMockPlatformView.subviews count]);
}

- (void)testCompositePlatformView {
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
// The parent view handles clipping to its subviews.
@interface ChildClippingView : UIView

// Adds a blur filter to its layers.
- (void)applyBackdropFilterWithRadius:
Comment thread
emilyabest marked this conversation as resolved.
Outdated
(NSNumber*)blurRadius; // TODO EMILY: is it better to pass an int?

@end

namespace flutter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ void ResetAnchor(CALayer* layer) {

} // namespace flutter

@implementation ChildClippingView
@implementation ChildClippingView {
NSObject* _gaussianFilter;
}

// The ChildClippingView's frame is the bounding rect of the platform view. we only want touches to
// be hit tested and consumed by this view if they are inside the embedded platform view which could
Expand All @@ -70,6 +72,45 @@ - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
return NO;
}

- (void)applyBackdropFilterWithRadius:(NSNumber*)blurRadius {
if (!_gaussianFilter) {
UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];

UIView* view = [visualEffectView.subviews firstObject];
if (!view) {
FML_DLOG(ERROR) << "Apple's API for UIVisualEffectView changed. Update the implementation to "
"access the Gaussian blur filter.";
return;
}

_gaussianFilter = [[view.layer.filters firstObject] retain];
if (!_gaussianFilter)
return;

FML_DCHECK([[_gaussianFilter valueForKey:@"name"] isEqual:@"gaussianBlur"]);
[visualEffectView release];
}

if (![[_gaussianFilter valueForKey:@"inputRadius"] isKindOfClass:[NSNumber class]]) {
FML_DLOG(ERROR) << "Apple's API for UIVisualEffectView changed. Update the implementation to "
"access the Gaussian blur filter's properties.";
return;
}

if ([[_gaussianFilter valueForKey:@"inputRadius"] isEqual:blurRadius])
return;

[_gaussianFilter setValue:blurRadius forKey:@"inputRadius"];
self.layer.filters = @[ _gaussianFilter ];
}

- (void)dealloc {
[_gaussianFilter release];
_gaussianFilter = nil;
[super dealloc];
}

@end

@interface FlutterClippingMaskView ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
Comment thread
emilyabest marked this conversation as resolved.
Outdated
INFOPLIST_FILE = App/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -466,6 +467,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
Comment thread
emilyabest marked this conversation as resolved.
Outdated
INFOPLIST_FILE = App/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down