summaryrefslogtreecommitdiffstats
path: root/remoting/ios/key_input.mm
blob: 0e51efa7ac61ae166b76312a933a4a33b9c47ffc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// 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