Skip to content

Commit

Permalink
Force orientation change when current orientation not allowed on iOS (f…
Browse files Browse the repository at this point in the history
  • Loading branch information
josh-ksr authored and GaryQian committed Oct 31, 2019
1 parent 7fe505c commit 3a32d9f
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 17 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ Simon Lightfoot <[email protected]>
Dwayne Slater <[email protected]>
Tetsuhiro Ueda <[email protected]>
shoryukenn <[email protected]>
SOTEC GmbH & Co. KG <[email protected]>
Original file line number Diff line number Diff line change
Expand Up @@ -828,14 +828,36 @@ - (void)onOrientationPreferencesUpdated:(NSNotification*)notification {
if (update == nil) {
return;
}
[self performOrientationUpdate:update.unsignedIntegerValue];
});
}

NSUInteger new_preferences = update.unsignedIntegerValue;

if (new_preferences != _orientationPreferences) {
_orientationPreferences = new_preferences;
[UIViewController attemptRotationToDeviceOrientation];
- (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences {
if (new_preferences != _orientationPreferences) {
_orientationPreferences = new_preferences;
[UIViewController attemptRotationToDeviceOrientation];

UIInterfaceOrientationMask currentInterfaceOrientation =
1 << [[UIApplication sharedApplication] statusBarOrientation];
if (!(_orientationPreferences & currentInterfaceOrientation)) {
// Force orientation switch if the current orientation is not allowed
if (_orientationPreferences & UIInterfaceOrientationMaskPortrait) {
// This is no official API but more like a workaround / hack (using
// key-value coding on a read-only property). This might break in
// the future, but currently it´s the only way to force an orientation change
[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
} else if (_orientationPreferences & UIInterfaceOrientationMaskPortraitUpsideDown) {
[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationPortraitUpsideDown)
forKey:@"orientation"];
} else if (_orientationPreferences & UIInterfaceOrientationMaskLandscapeLeft) {
[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft)
forKey:@"orientation"];
} else if (_orientationPreferences & UIInterfaceOrientationMaskLandscapeRight) {
[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeRight)
forKey:@"orientation"];
}
}
});
}
}

- (BOOL)shouldAutorotate {
Expand Down
201 changes: 190 additions & 11 deletions shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ - (UIAccessibilityContrast)accessibilityContrast;
@end
#endif

@interface FlutterViewController (Tests)
- (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences;
@end

@implementation FlutterViewControllerTest

- (void)testBinaryMessenger {
Expand Down Expand Up @@ -252,6 +256,179 @@ - (void)testItReportsHighContrastWhenTraitCollectionRequestsIt {
[mockTraitCollection stopMocking];
}

- (void)testPerformOrientationUpdateForcesOrientationChange {
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortrait
currentOrientation:UIInterfaceOrientationLandscapeLeft
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationPortrait];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortrait
currentOrientation:UIInterfaceOrientationLandscapeRight
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationPortrait];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortrait
currentOrientation:UIInterfaceOrientationPortraitUpsideDown
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationPortrait];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortraitUpsideDown
currentOrientation:UIInterfaceOrientationLandscapeLeft
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationPortraitUpsideDown];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortraitUpsideDown
currentOrientation:UIInterfaceOrientationLandscapeRight
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationPortraitUpsideDown];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortraitUpsideDown
currentOrientation:UIInterfaceOrientationPortrait
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationPortraitUpsideDown];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscape
currentOrientation:UIInterfaceOrientationPortrait
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationLandscapeLeft];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscape
currentOrientation:UIInterfaceOrientationPortraitUpsideDown
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationLandscapeLeft];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeLeft
currentOrientation:UIInterfaceOrientationPortrait
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationLandscapeLeft];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeLeft
currentOrientation:UIInterfaceOrientationLandscapeRight
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationLandscapeLeft];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeLeft
currentOrientation:UIInterfaceOrientationPortraitUpsideDown
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationLandscapeLeft];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeRight
currentOrientation:UIInterfaceOrientationPortrait
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationLandscapeRight];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeRight
currentOrientation:UIInterfaceOrientationLandscapeLeft
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationLandscapeRight];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeRight
currentOrientation:UIInterfaceOrientationPortraitUpsideDown
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationLandscapeRight];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown
currentOrientation:UIInterfaceOrientationPortraitUpsideDown
didChangeOrientation:YES
resultingOrientation:UIInterfaceOrientationPortrait];
}

- (void)testPerformOrientationUpdateDoesNotForceOrientationChange {
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll
currentOrientation:UIInterfaceOrientationPortrait
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll
currentOrientation:UIInterfaceOrientationPortraitUpsideDown
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll
currentOrientation:UIInterfaceOrientationLandscapeLeft
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAll
currentOrientation:UIInterfaceOrientationLandscapeRight
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown
currentOrientation:UIInterfaceOrientationPortrait
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown
currentOrientation:UIInterfaceOrientationLandscapeLeft
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskAllButUpsideDown
currentOrientation:UIInterfaceOrientationLandscapeRight
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortrait
currentOrientation:UIInterfaceOrientationPortrait
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortraitUpsideDown
currentOrientation:UIInterfaceOrientationPortraitUpsideDown
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscape
currentOrientation:UIInterfaceOrientationLandscapeLeft
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscape
currentOrientation:UIInterfaceOrientationLandscapeRight
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeLeft
currentOrientation:UIInterfaceOrientationLandscapeLeft
didChangeOrientation:NO
resultingOrientation:0];

[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskLandscapeRight
currentOrientation:UIInterfaceOrientationLandscapeRight
didChangeOrientation:NO
resultingOrientation:0];
}

// Perform an orientation update test that fails when the expected outcome
// for an orientation update is not met
- (void)orientationTestWithOrientationUpdate:(UIInterfaceOrientationMask)mask
currentOrientation:(UIInterfaceOrientation)currentOrientation
didChangeOrientation:(BOOL)didChange
resultingOrientation:(UIInterfaceOrientation)resultingOrientation {
id engine = OCMClassMock([FlutterEngine class]);

id deviceMock = OCMPartialMock([UIDevice currentDevice]);
if (!didChange) {
OCMReject([deviceMock setValue:[OCMArg any] forKey:@"orientation"]);
} else {
OCMExpect([deviceMock setValue:@(resultingOrientation) forKey:@"orientation"]);
}

FlutterViewController* realVC = [[FlutterViewController alloc] initWithEngine:engine
nibName:nil
bundle:nil];
id mockApplication = OCMClassMock([UIApplication class]);
OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
OCMStub([mockApplication statusBarOrientation]).andReturn(currentOrientation);

[realVC performOrientationUpdate:mask];
OCMVerifyAll(deviceMock);
[engine stopMocking];
[deviceMock stopMocking];
[mockApplication stopMocking];
}

// Creates a mocked UITraitCollection with nil values for everything except accessibilityContrast,
// which is set to the given "contrast".
- (UITraitCollection*)fakeTraitCollectionWithContrast:(UIAccessibilityContrast)contrast {
Expand All @@ -264,17 +441,19 @@ - (void)testWillDeallocNotification {
XCTestExpectation* expectation =
[[XCTestExpectation alloc] initWithDescription:@"notification called"];
id engine = [[MockEngine alloc] init];
FlutterViewController* realVC = [[FlutterViewController alloc] initWithEngine:engine
nibName:nil
bundle:nil];
id observer =
[[NSNotificationCenter defaultCenter] addObserverForName:FlutterViewControllerWillDealloc
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification* _Nonnull note) {
[expectation fulfill];
}];
realVC = nil;
@autoreleasepool {
FlutterViewController* realVC = [[FlutterViewController alloc] initWithEngine:engine
nibName:nil
bundle:nil];
id observer =
[[NSNotificationCenter defaultCenter] addObserverForName:FlutterViewControllerWillDealloc
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification* _Nonnull note) {
[expectation fulfill];
}];
realVC = nil;
}
[self waitForExpectations:@[ expectation ] timeout:1.0];
}

Expand Down

0 comments on commit 3a32d9f

Please sign in to comment.