blob: eaff4235db04c76d6c83bacda01da2b3cccef9c5 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// 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"
#include <memory>
#include "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"
#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 {
_keyboardDisabler =
std::make_unique<ScopedFullscreenDisabler>(self.controller);
}
- (void)keyboardDidHide {
_keyboardDisabler = nullptr;
}
- (void)applicationWillEnterForeground {
self.mediator->ExitFullscreen();
}
@end