blob: a70f5c30a274400c095cafdd8bf17578ffa0669b [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/fullscreen/fullscreen_system_notification_observer.h"
#import <memory>
#import "base/check.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h"
#import "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h"
#import "ios/public/provider/chrome/browser/find_in_page/find_in_page_api.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface FullscreenSystemNotificationObserver () {
// The disabler created when VoiceOver is enabled.
std::unique_ptr<ScopedFullscreenDisabler> _voiceOverDisabler;
// The disabler created when the keyboard is visible.
std::unique_ptr<ScopedFullscreenDisabler> _keyboardDisabler;
}
// The FullscreenController being enabled/disabled for system events.
@property(nonatomic, readonly, nonnull) FullscreenController* controller;
// The FullscreenMediator through which foreground events are propagated to
// FullscreenControllerObservers.
@property(nonatomic, readonly, nonnull) FullscreenMediator* mediator;
// Creates or destroys `_voiceOverDisabler` depending on whether VoiceOver is
// enabled.
- (void)voiceOverStatusChanged;
// Called when the keyboard is shown/hidden to reset `_keyboardDisabler`.
- (void)keyboardWillShow;
- (void)keyboardDidHide;
// Called when the application is foregrounded.
- (void)applicationWillEnterForeground;
@end
@implementation FullscreenSystemNotificationObserver
@synthesize controller = _controller;
@synthesize mediator = _mediator;
- (instancetype)initWithController:(FullscreenController*)controller
mediator:(FullscreenMediator*)mediator {
if (self = [super init]) {
_controller = controller;
DCHECK(_controller);
_mediator = mediator;
DCHECK(_mediator);
// Register for VoiceOVer status change notifications. The notification
// name has been updated in iOS 11.
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter
addObserver:self
selector:@selector(voiceOverStatusChanged)
name:UIAccessibilityVoiceOverStatusDidChangeNotification
object:nil];
// Create a disabler if VoiceOver is enabled.
if (UIAccessibilityIsVoiceOverRunning()) {
_voiceOverDisabler =
std::make_unique<ScopedFullscreenDisabler>(_controller);
}
// Register for keyboard visibility notifications.
[defaultCenter addObserver:self
selector:@selector(keyboardWillShow)
name:UIKeyboardWillShowNotification
object:nil];
[defaultCenter addObserver:self
selector:@selector(keyboardDidHide)
name:UIKeyboardDidHideNotification
object:nil];
// Register for application lifecycle events.
[defaultCenter addObserver:self
selector:@selector(applicationWillEnterForeground)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
return self;
}
- (void)dealloc {
// `-disconnect` should be called before deallocation.
DCHECK(!_controller);
}
#pragma mark Public
- (void)disconnect {
[[NSNotificationCenter defaultCenter] removeObserver:self];
_controller = nullptr;
}
#pragma mark Private
- (void)voiceOverStatusChanged {
_voiceOverDisabler =
UIAccessibilityIsVoiceOverRunning()
? std::make_unique<ScopedFullscreenDisabler>(self.controller)
: nullptr;
}
- (void)keyboardWillShow {
if (ios::provider::IsNativeFindInPageWithSystemFindPanel()) {
// If Native Find in Page with system Find panel is active, then triggering
// Find in Page will show the keyboard AND make Chrome enter full screen
// mode.
return;
}
_keyboardDisabler =
std::make_unique<ScopedFullscreenDisabler>(self.controller);
}
- (void)keyboardDidHide {
_keyboardDisabler = nullptr;
}
- (void)applicationWillEnterForeground {
self.mediator->ExitFullscreen();
}
@end