blob: 0e51efa7ac61ae166b76312a933a4a33b9c47ffc [file] [log] [blame]
// 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