1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ios/chrome/browser/ui/keyboard/hardware_keyboard_watcher.h"
7 #import <CoreGraphics/CoreGraphics.h>
9 #include "base/logging.h"
10 #include "base/mac/scoped_nsobject.h"
11 #include "base/metrics/histogram_macros.h"
15 // Whether firstRect has a non null rect intersection with secondRect, yet does
16 // not fully include it.
17 bool IntersectsButDoesNotInclude(CGRect firstRect, CGRect secondRect) {
18 return CGRectIntersectsRect(firstRect, secondRect) &&
19 !CGRectContainsRect(firstRect, secondRect);
24 @interface HardwareKeyboardWatcher () {
25 base::scoped_nsobject<UIView> _accessoryView;
27 @property(nonatomic, assign) UIInterfaceOrientation orientation;
30 @implementation HardwareKeyboardWatcher
32 @synthesize orientation = _orientation;
34 - (instancetype)init {
39 - (instancetype)initWithAccessoryView:(UIView*)accessoryView {
40 DCHECK(accessoryView);
43 _accessoryView.reset([accessoryView retain]);
44 _orientation = [UIApplication sharedApplication].statusBarOrientation;
45 [[NSNotificationCenter defaultCenter]
47 selector:@selector(keyboardWillChangeFrame:)
48 name:UIKeyboardWillChangeFrameNotification
55 [[NSNotificationCenter defaultCenter] removeObserver:self];
59 - (void)keyboardWillChangeFrame:(NSNotification*)notification {
60 // Don't handle keyboard notifications not involving the set accessory view.
61 if ([_accessoryView window] == nil)
64 // Don't handle rotations as the reported keyboard frames are in the screen
65 // coordinates *prior* to the rotation, while the screen already has its
66 // new coordinates. http://crbug.com/511267
67 if (self.orientation !=
68 [UIApplication sharedApplication].statusBarOrientation) {
72 NSDictionary* userInfo = [notification userInfo];
73 CGRect beginKeyboardFrame =
74 [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
75 CGRect endKeyboardFrame =
76 [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
77 CGRect screenBounds = [UIScreen mainScreen].bounds;
79 // CGRectZero frames are seen when moving a split dock. Split keyboard means
81 bool hasCGRectZeroFrames =
82 CGRectEqualToRect(CGRectZero, beginKeyboardFrame) ||
83 CGRectEqualToRect(CGRectZero, endKeyboardFrame);
85 bool keyboardIsPartiallyOnScreen =
86 IntersectsButDoesNotInclude(screenBounds, beginKeyboardFrame) ||
87 IntersectsButDoesNotInclude(screenBounds, endKeyboardFrame);
89 bool isInHarwareKeyboardMode =
90 !hasCGRectZeroFrames && keyboardIsPartiallyOnScreen;
92 UMA_HISTOGRAM_BOOLEAN("Omnibox.HardwareKeyboardModeEnabled",
93 isInHarwareKeyboardMode);