| // Copyright 2014 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/key_input.h" |
| #import "remoting/ios/key_map_us.h" |
| |
| @interface KeyInput (Private) |
| - (void)transmitAppropriateKeyCode:(NSString*)text; |
| - (void)transmitKeyCode:(NSInteger)keyCode needShift:(bool)needShift; |
| @end |
| |
| @implementation KeyInput |
| |
| @synthesize delegate = _delegate; |
| |
| // Override UIKeyInput::UITextInputTraits property |
| - (UIKeyboardType)keyboardType { |
| return UIKeyboardTypeAlphabet; |
| } |
| |
| // Override UIView::UIResponder, when this interface is the first responder |
| // on-screen keyboard input will create events for Chromoting keyboard input |
| - (BOOL)canBecomeFirstResponder { |
| return YES; |
| } |
| |
| // Override UIView::UIResponder |
| // Keyboard was dismissed |
| - (BOOL)resignFirstResponder { |
| BOOL wasFirstResponder = self.isFirstResponder; |
| BOOL didResignFirstReponder = |
| [super resignFirstResponder]; // I'm not sure that this returns YES when |
| // first responder was resigned, but for |
| // now I don't actually need to know what |
| // the return from super means. |
| if (wasFirstResponder) { |
| [_delegate keyboardDismissed]; |
| } |
| |
| return didResignFirstReponder; |
| } |
| |
| // @protocol UIKeyInput, Send backspace |
| - (void)deleteBackward { |
| [self transmitKeyCode:kKeyCodeUS[kBackspaceIndex] needShift:false]; |
| } |
| |
| // @protocol UIKeyInput, Assume this is a text input |
| - (BOOL)hasText { |
| return YES; |
| } |
| |
| // @protocol UIKeyInput, Translate inserted text to key presses, one char at a |
| // time |
| - (void)insertText:(NSString*)text { |
| [self transmitAppropriateKeyCode:text]; |
| } |
| |
| - (void)ctrlAltDel { |
| if (_delegate) { |
| [_delegate keyboardActionKeyCode:kKeyCodeUS[kCtrlIndex] isKeyDown:YES]; |
| [_delegate keyboardActionKeyCode:kKeyCodeUS[kAltIndex] isKeyDown:YES]; |
| [_delegate keyboardActionKeyCode:kKeyCodeUS[kDelIndex] isKeyDown:YES]; |
| [_delegate keyboardActionKeyCode:kKeyCodeUS[kDelIndex] isKeyDown:NO]; |
| [_delegate keyboardActionKeyCode:kKeyCodeUS[kAltIndex] isKeyDown:NO]; |
| [_delegate keyboardActionKeyCode:kKeyCodeUS[kCtrlIndex] isKeyDown:NO]; |
| } |
| } |
| |
| // When inserting multiple characters, process them one at a time. |text| is as |
| // it was output on the device. The shift key is not naturally presented in the |
| // input stream, and must be inserted by inspecting each char and considering |
| // that if the key was input on a traditional keyboard that the character would |
| // have required a shift. Assume caps lock does not exist. |
| - (void)transmitAppropriateKeyCode:(NSString*)text { |
| for (int i = 0; i < [text length]; ++i) { |
| NSInteger charToSend = [text characterAtIndex:i]; |
| |
| if (charToSend <= kKeyboardKeyMaxUS) { |
| [self transmitKeyCode:kKeyCodeUS[charToSend] |
| needShift:kIsShiftRequiredUS[charToSend]]; |
| } |
| } |
| } |
| |
| // |charToSend| is as it was output on the device. Some call this a |
| // 'key press'. For Chromoting this must be transferred as a key down (press |
| // down with a finger), followed by a key up (finger is removed from the |
| // keyboard) |
| // |
| // The delivery may be an upper case or special character. Chromoting is just |
| // interested in the button that was pushed, so to create an upper case |
| // character, first send a shift press, then the button, then release shift |
| - (void)transmitKeyCode:(NSInteger)keyCode needShift:(bool)needShift { |
| if (keyCode > 0 && _delegate) { |
| if (needShift) { |
| [_delegate keyboardActionKeyCode:kKeyCodeUS[kShiftIndex] isKeyDown:YES]; |
| } |
| [_delegate keyboardActionKeyCode:keyCode isKeyDown:YES]; |
| [_delegate keyboardActionKeyCode:keyCode isKeyDown:NO]; |
| if (needShift) { |
| [_delegate keyboardActionKeyCode:kKeyCodeUS[kShiftIndex] isKeyDown:NO]; |
| } |
| } |
| } |
| @end |