diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 5c9e0ac454d9c..453b653dc57a5 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -873,7 +873,7 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUmbrell FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterView.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.m +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index 809c467a4e554..5238be44eaef1 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -4,6 +4,7 @@ #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h" #include "flutter/fml/logging.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" #include #include @@ -161,6 +162,15 @@ - (void)setSystemChromeEnabledSystemUIOverlays:(NSArray*)overlays { // UIViewControllerBasedStatusBarAppearance [UIApplication sharedApplication].statusBarHidden = ![overlays containsObject:@"SystemUiOverlay.top"]; + if ([overlays containsObject:@"SystemUiOverlay.bottom"]) { + [[NSNotificationCenter defaultCenter] + postNotificationName:FlutterViewControllerShowHomeIndicator + object:nil]; + } else { + [[NSNotificationCenter defaultCenter] + postNotificationName:FlutterViewControllerHideHomeIndicator + object:nil]; + } } - (void)restoreSystemChromeSystemUIOverlays { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 2c5f4ebb6d3b0..9c0ff5883fa95 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -27,8 +27,11 @@ static constexpr CGFloat kScrollViewContentSize = 2.0; NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemanticsUpdate"; - NSNotificationName const FlutterViewControllerWillDealloc = @"FlutterViewControllerWillDealloc"; +NSNotificationName const FlutterViewControllerHideHomeIndicator = + @"FlutterViewControllerHideHomeIndicator"; +NSNotificationName const FlutterViewControllerShowHomeIndicator = + @"FlutterViewControllerShowHomeIndicator"; /// Class to coalesce calls for a period of time. /// @@ -91,6 +94,7 @@ - (void)invalidate { // just a warning. @interface FlutterViewController () @property(nonatomic, readwrite, getter=isDisplayingFlutterUI) BOOL displayingFlutterUI; +@property(nonatomic, assign) BOOL isHomeIndicatorHidden; @end // The following conditional compilation defines an API 13 concept on earlier API targets so that @@ -318,6 +322,16 @@ - (void)setupNotificationCenterObservers { selector:@selector(onUserSettingsChanged:) name:UIContentSizeCategoryDidChangeNotification object:nil]; + + [center addObserver:self + selector:@selector(onHideHomeIndicatorNotification:) + name:FlutterViewControllerHideHomeIndicator + object:nil]; + + [center addObserver:self + selector:@selector(onShowHomeIndicatorNotification:) + name:FlutterViewControllerShowHomeIndicator + object:nil]; } - (void)setInitialRoute:(NSString*)route { @@ -1022,6 +1036,27 @@ - (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences { } } +- (void)onHideHomeIndicatorNotification:(NSNotification*)notification { + self.isHomeIndicatorHidden = YES; +} + +- (void)onShowHomeIndicatorNotification:(NSNotification*)notification { + self.isHomeIndicatorHidden = NO; +} + +- (void)setIsHomeIndicatorHidden:(BOOL)hideHomeIndicator { + if (hideHomeIndicator != _isHomeIndicatorHidden) { + _isHomeIndicatorHidden = hideHomeIndicator; + if (@available(iOS 11, *)) { + [self setNeedsUpdateOfHomeIndicatorAutoHidden]; + } + } +} + +- (BOOL)prefersHomeIndicatorAutoHidden { + return self.isHomeIndicatorHidden; +} + - (BOOL)shouldAutorotate { return YES; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.m b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm similarity index 91% rename from shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.m rename to shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index 403e4e3625311..d851616720905 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.m +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -6,6 +6,7 @@ #import #include "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" #include "FlutterBinaryMessenger.h" @@ -344,67 +345,67 @@ - (void)testPerformOrientationUpdateDoesNotForceOrientationChange { [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll currentOrientation:UIInterfaceOrientationPortrait didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll currentOrientation:UIInterfaceOrientationPortraitUpsideDown didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll currentOrientation:UIInterfaceOrientationLandscapeLeft didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll currentOrientation:UIInterfaceOrientationLandscapeRight didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown currentOrientation:UIInterfaceOrientationPortrait didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown currentOrientation:UIInterfaceOrientationLandscapeLeft didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown currentOrientation:UIInterfaceOrientationLandscapeRight didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortrait currentOrientation:UIInterfaceOrientationPortrait didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortraitUpsideDown currentOrientation:UIInterfaceOrientationPortraitUpsideDown didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscape currentOrientation:UIInterfaceOrientationLandscapeLeft didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscape currentOrientation:UIInterfaceOrientationLandscapeRight didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeLeft currentOrientation:UIInterfaceOrientationLandscapeLeft didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; [self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeRight currentOrientation:UIInterfaceOrientationLandscapeRight didChangeOrientation:NO - resultingOrientation:0]; + resultingOrientation:static_cast(0)]; } // Perform an orientation update test that fails when the expected outcome @@ -465,8 +466,6 @@ - (void)testWillDeallocNotification { } - (void)testDoesntLoadViewInInit { - XCTestExpectation* expectation = - [[XCTestExpectation alloc] initWithDescription:@"notification called"]; FlutterDartProject* project = [[FlutterDartProject alloc] init]; FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project]; [engine createShell:@"" libraryURI:@""]; @@ -476,4 +475,17 @@ - (void)testDoesntLoadViewInInit { XCTAssertFalse([realVC isViewLoaded], @"shouldn't have loaded since it hasn't been shown"); } +- (void)testHideOverlay { + FlutterDartProject* project = [[FlutterDartProject alloc] init]; + FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project]; + [engine createShell:@"" libraryURI:@""]; + FlutterViewController* realVC = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + XCTAssertFalse(realVC.prefersHomeIndicatorAutoHidden, @""); + [[NSNotificationCenter defaultCenter] postNotificationName:FlutterViewControllerHideHomeIndicator + object:nil]; + XCTAssertTrue(realVC.prefersHomeIndicatorAutoHidden, @""); +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h index afe5b8166ce4a..98f222b3254ac 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h @@ -5,16 +5,22 @@ #ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_ -#include "flutter/flow/embedded_views.h" #include "flutter/fml/memory/weak_ptr.h" -#include "flutter/fml/platform/darwin/scoped_nsobject.h" -#include "flutter/shell/common/shell.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" -#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" + +namespace flutter { +class FlutterPlatformViewsController; +} FLUTTER_EXPORT extern NSNotificationName const FlutterViewControllerWillDealloc; +FLUTTER_EXPORT +extern NSNotificationName const FlutterViewControllerHideHomeIndicator; + +FLUTTER_EXPORT +extern NSNotificationName const FlutterViewControllerShowHomeIndicator; + @interface FlutterViewController () - (fml::WeakPtr)getWeakPtr; diff --git a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj index 533ff80fd389c..1ed8dfcd26acc 100644 --- a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj +++ b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 0D17A5C022D78FCD0057279F /* FlutterViewControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + 0D17A5C022D78FCD0057279F /* FlutterViewControllerTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.mm */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; 0D1CE5D8233430F400E5D880 /* FlutterChannelsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D1CE5D7233430F400E5D880 /* FlutterChannelsTest.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; 0D4C3FB022DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D4C3FAF22DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; 0D52D3BD22C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0D52D3B622C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; @@ -76,7 +76,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FlutterViewControllerTest.m; sourceTree = ""; }; + 0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterViewControllerTest.mm; sourceTree = ""; }; 0D1CE5D7233430F400E5D880 /* FlutterChannelsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FlutterChannelsTest.m; sourceTree = ""; }; 0D4C3FAF22DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FlutterPluginAppLifeCycleDelegateTest.m; sourceTree = ""; }; 0D52D3B622C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterBinaryMessengerRelayTest.mm; sourceTree = ""; }; @@ -179,7 +179,7 @@ 0D52D3B622C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm */, 0D6AB6E722BB40CF00EEE540 /* FlutterEngineTest.mm */, 3D8AF6172384C5420033B95F /* FlutterTextInputPluginTest.m */, - 0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.m */, + 0D17A5BF22D78FCD0057279F /* FlutterViewControllerTest.mm */, 0D4C3FAF22DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m */, ); name = Source; @@ -391,7 +391,7 @@ files = ( 0D6AB6EB22BB40E700EEE540 /* FlutterEngineTest.mm in Sources */, 3D8AF6182384C5420033B95F /* FlutterTextInputPluginTest.m in Sources */, - 0D17A5C022D78FCD0057279F /* FlutterViewControllerTest.m in Sources */, + 0D17A5C022D78FCD0057279F /* FlutterViewControllerTest.mm in Sources */, 0D1CE5D8233430F400E5D880 /* FlutterChannelsTest.m in Sources */, 0D52D3BD22C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm in Sources */, 0D4C3FB022DF9F5300A67C70 /* FlutterPluginAppLifeCycleDelegateTest.m in Sources */,