12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- // Copyright 2017 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.
- #if !defined(__has_feature) || !__has_feature(objc_arc)
- #error "This file requires ARC support."
- #endif
- #import "remoting/ios/app/physical_keyboard_detector.h"
- // A view to do measurement to figure out whether a physical keyboard is
- // presented.
- //
- // The logic is hacky since iOS doesn't provide any API that tells you whether
- // a physical keyboard is being used. We infer that in these steps:
- //
- // 1. Add a hidden text field (this view) to the view to be detected and
- // register the keyboardWillShow notification.
- // 2. Make the text field first responder.
- // 3. keyboardWillShow will get called. The keyboard's end frame will go
- // offscreen if the physical keyboard is presented.
- // 4. Pass that information to the callback and remove the hidden text field.
- // The view will not flicker as long as we immediately remove the text field
- // in keyboardWillShow.
- //
- // Unfortunately there is no easy way to know immediately when the user connects
- // or disconnects the keyboard.
- @interface PhysicalKeyboardDetectorView : UITextField {
- void (^_callback)(BOOL);
- }
- - (void)detectOnView:(UIView*)view callback:(void (^)(BOOL))callback;
- @end
- @implementation PhysicalKeyboardDetectorView
- - (instancetype)initWithFrame:(CGRect)frame {
- if (self = [super initWithFrame:frame]) {
- self.hidden = YES;
- // This is to force keyboardWillShow to always be called.
- self.inputAccessoryView = [[UIView alloc] initWithFrame:CGRectZero];
- }
- return self;
- }
- - (void)dealloc {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- }
- - (void)detectOnView:(UIView*)view callback:(void (^)(BOOL))callback {
- _callback = callback;
- [view addSubview:self];
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(keyboardWillShow:)
- name:UIKeyboardWillShowNotification
- object:nil];
- [self becomeFirstResponder];
- }
- #pragma mark - Private
- - (void)keyboardWillShow:(NSNotification*)notification {
- if (!self.isFirstResponder) {
- // Don't handle the notification if it is not for the detector view.
- return;
- }
- CGRect keyboardFrame = [(NSValue*)[notification.userInfo
- objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
- // iPad will still show the toolbar at the top of the soft keyboard even if
- // the physical keyboard is presented, so the safer check is to see if the
- // bottom of the keyboard goes under the screen.
- int keyboardBottom = keyboardFrame.origin.y + keyboardFrame.size.height;
- BOOL isKeyboardOffScreen =
- keyboardBottom > UIScreen.mainScreen.bounds.size.height;
- [self resignFirstResponder];
- [self removeFromSuperview];
- _callback(isKeyboardOffScreen);
- }
- @end
- #pragma mark - PhysicalKeyboardDetector
- @implementation PhysicalKeyboardDetector
- + (void)detectOnView:(UIView*)view callback:(void (^)(BOOL))callback {
- PhysicalKeyboardDetectorView* detectorView =
- [[PhysicalKeyboardDetectorView alloc] initWithFrame:CGRectZero];
- [detectorView detectOnView:view callback:callback];
- }
- @end
|