Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 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. | |
| 4 | |
| 5 package org.chromium.chromoting; | |
| 6 | |
| 7 import android.graphics.Point; | |
| 8 import android.view.KeyEvent; | |
| 9 import android.view.MotionEvent; | |
| 10 | |
| 11 import org.chromium.chromoting.jni.TouchEventData; | |
| 12 | |
| 13 import java.util.ArrayList; | |
| 14 import java.util.List; | |
| 15 import java.util.Set; | |
| 16 import java.util.TreeSet; | |
| 17 | |
| 18 /** | |
| 19 * A set of functions to send users' activities, which are represented by Androi d classes, to | |
| 20 * remove host machine. This class uses a {@link InputInjector} to do the real i njections. | |
| 21 */ | |
| 22 public final class InputInjectorWrapper { | |
|
Sergey Ulanov
2016/06/22 06:39:01
I don't think this is the best name for this class
Hzj_jie
2016/06/22 23:18:54
Done.
| |
| 23 private static final int[] CTRL_ALT_DEL = { | |
| 24 KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYC ODE_FORWARD_DEL, | |
| 25 }; | |
| 26 | |
| 27 private final InputInjector mInjector; | |
| 28 | |
| 29 /** Set of pressed keys for which we've sent TextEvent. */ | |
| 30 private final Set<Integer> mPressedTextKeys; | |
| 31 | |
| 32 public InputInjectorWrapper(InputInjector injector) { | |
| 33 Preconditions.notNull(injector); | |
| 34 mInjector = injector; | |
| 35 mPressedTextKeys = new TreeSet<>(); | |
| 36 } | |
| 37 | |
| 38 public void sendMouseEvent(Point pos, int button, boolean down) { | |
| 39 Preconditions.isTrue(button == TouchInputHandler.BUTTON_UNDEFINED | |
| 40 || button == TouchInputHandler.BUTTON_LEFT | |
| 41 || button == TouchInputHandler.BUTTON_MIDDLE | |
| 42 || button == TouchInputHandler.BUTTON_RIGHT); | |
| 43 mInjector.sendMouseEvent(pos.x, pos.y, button, down); | |
| 44 } | |
| 45 | |
| 46 public void sendMouseDown(Point pos, int button) { | |
| 47 sendMouseEvent(pos, button, true); | |
| 48 } | |
| 49 | |
| 50 public void sendMouseUp(Point pos, int button) { | |
| 51 sendMouseEvent(pos, button, false); | |
| 52 } | |
| 53 | |
| 54 public void sendMouseClick(Point pos, int button) { | |
| 55 sendMouseDown(pos, button); | |
| 56 sendMouseUp(pos, button); | |
| 57 } | |
| 58 | |
| 59 public void sendCursorMove(Point pos) { | |
| 60 sendMouseUp(pos, TouchInputHandler.BUTTON_UNDEFINED); | |
| 61 } | |
| 62 | |
| 63 // TODO (zijiehe): This function will be eventually removed after {@link Inp utStrategyInterface} | |
|
Lambros
2016/06/22 01:43:14
No space between TODO and (.
Hzj_jie
2016/06/22 23:18:54
Done.
| |
| 64 // has been deprecated. | |
| 65 public void sendCursorMove(int x, int y) { | |
| 66 sendCursorMove(new Point(x, y)); | |
| 67 } | |
| 68 | |
| 69 public void sendMouseWheelEvent(float distanceX, float distanceY) { | |
| 70 mInjector.sendMouseWheelEvent((int) distanceX, (int) distanceY); | |
| 71 } | |
| 72 | |
| 73 public void sendReverseMouseWheelEvent(float distanceX, float distanceY) { | |
| 74 sendMouseWheelEvent(-distanceX, -distanceY); | |
| 75 } | |
| 76 | |
| 77 /** | |
| 78 * Extracts the touch point data from a MotionEvent, converts each point int o a marshallable | |
| 79 * object and passes the set of points to the JNI layer to be transmitted to the remote host. | |
| 80 * | |
| 81 * @param event The event to send to the remote host for injection. NOTE: T his object must be | |
| 82 * updated to represent the remote machine's coordinate system before calling this | |
| 83 * function. | |
| 84 */ | |
| 85 public void sendTouchEvent(MotionEvent event) { | |
| 86 int action = event.getActionMasked(); | |
| 87 TouchEventData.EventType touchEventType = TouchEventData.EventType.fromM askedAction(action); | |
| 88 List<TouchEventData> touchEventList = new ArrayList<TouchEventData>(); | |
| 89 | |
| 90 if (action == MotionEvent.ACTION_MOVE) { | |
| 91 // In order to process all of the events associated with an ACTION_M OVE event, we need | |
| 92 // to walk the list of historical events in order and add each event to our list, then | |
| 93 // retrieve the current move event data. | |
| 94 int pointerCount = event.getPointerCount(); | |
| 95 int historySize = event.getHistorySize(); | |
| 96 for (int h = 0; h < historySize; ++h) { | |
| 97 for (int p = 0; p < pointerCount; ++p) { | |
| 98 touchEventList.add(new TouchEventData(event.getPointerId(p), | |
| 99 event.getHistoricalX(p, h), event.getHistoricalY(p, h), | |
| 100 event.getHistoricalSize(p, h), event.getHistoricalSi ze(p, h), | |
| 101 event.getHistoricalOrientation(p, h), | |
| 102 event.getHistoricalPressure(p, h))); | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 for (int p = 0; p < pointerCount; p++) { | |
| 107 touchEventList.add(new TouchEventData(event.getPointerId(p), eve nt.getX(p), | |
| 108 event.getY(p), event.getSize(p), event.getSize(p), event .getOrientation(p), | |
| 109 event.getPressure(p))); | |
| 110 } | |
| 111 } else { | |
| 112 // For all other events, we only want to grab the current/active poi nter. The event | |
| 113 // contains a list of every active pointer but passing all of of the se to the host can | |
| 114 // cause confusion on the remote OS side and result in broken touch gestures. | |
| 115 int activePointerIndex = event.getActionIndex(); | |
| 116 touchEventList.add(new TouchEventData(event.getPointerId(activePoint erIndex), | |
| 117 event.getX(activePointerIndex), event.getY(activePointerInde x), | |
| 118 event.getSize(activePointerIndex), event.getSize(activePoint erIndex), | |
| 119 event.getOrientation(activePointerIndex), | |
| 120 event.getPressure(activePointerIndex))); | |
| 121 } | |
| 122 | |
| 123 if (!touchEventList.isEmpty()) { | |
| 124 mInjector.sendTouchEvent(touchEventType, touchEventList.toArray(new TouchEventData[0])); | |
| 125 } | |
| 126 } | |
| 127 | |
| 128 /** | |
| 129 * Converts the {@link KeyEvent} into low-level events and sends them to the host as either | |
| 130 * key-events or text-events. This contains some logic for handling some spe cial keys, and | |
| 131 * avoids sending a key-up event for a key that was previously injected as a text-event. | |
| 132 */ | |
| 133 public boolean sendKeyEvent(KeyEvent event) { | |
| 134 int keyCode = event.getKeyCode(); | |
| 135 boolean pressed = event.getAction() == KeyEvent.ACTION_DOWN; | |
| 136 | |
| 137 // Events received from software keyboards generate TextEvent in two | |
| 138 // cases: | |
| 139 // 1. This is an ACTION_MULTIPLE event. | |
| 140 // 2. Ctrl, Alt and Meta are not pressed. | |
| 141 // This ensures that on-screen keyboard always injects input that | |
| 142 // correspond to what user sees on the screen, while physical keyboard | |
| 143 // acts as if it is connected to the remote host. | |
| 144 if (event.getAction() == KeyEvent.ACTION_MULTIPLE) { | |
| 145 mInjector.sendTextEvent(event.getCharacters()); | |
| 146 return true; | |
| 147 } | |
| 148 | |
| 149 // For Enter getUnicodeChar() returns 10 (line feed), but we still | |
| 150 // want to send it as KeyEvent. | |
| 151 int unicode = keyCode != KeyEvent.KEYCODE_ENTER ? event.getUnicodeChar() : 0; | |
| 152 | |
| 153 boolean no_modifiers = | |
| 154 !event.isAltPressed() && !event.isCtrlPressed() && !event.isMeta Pressed(); | |
| 155 | |
| 156 if (pressed && unicode != 0 && no_modifiers) { | |
| 157 mPressedTextKeys.add(keyCode); | |
| 158 int[] codePoints = {unicode}; | |
| 159 mInjector.sendTextEvent(new String(codePoints, 0, 1)); | |
| 160 return true; | |
| 161 } | |
| 162 | |
| 163 if (!pressed && mPressedTextKeys.contains(keyCode)) { | |
| 164 mPressedTextKeys.remove(keyCode); | |
| 165 return true; | |
| 166 } | |
| 167 | |
| 168 switch (keyCode) { | |
| 169 // KEYCODE_AT, KEYCODE_POUND, KEYCODE_STAR and KEYCODE_PLUS are | |
| 170 // deprecated, but they still need to be here for older devices and | |
| 171 // third-party keyboards that may still generate these events. See | |
| 172 // https://source.android.com/devices/input/keyboard-devices.html#le gacy-unsupported-keys | |
| 173 case KeyEvent.KEYCODE_AT: | |
| 174 mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, pressed); | |
| 175 mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_2, pressed); | |
| 176 return true; | |
| 177 | |
| 178 case KeyEvent.KEYCODE_POUND: | |
| 179 mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, pressed); | |
| 180 mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_3, pressed); | |
| 181 return true; | |
| 182 | |
| 183 case KeyEvent.KEYCODE_STAR: | |
| 184 mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, pressed); | |
| 185 mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_8, pressed); | |
| 186 return true; | |
| 187 | |
| 188 case KeyEvent.KEYCODE_PLUS: | |
| 189 mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, pressed); | |
| 190 mInjector.sendKeyEvent(0, KeyEvent.KEYCODE_EQUALS, pressed); | |
| 191 return true; | |
| 192 | |
| 193 default: | |
| 194 // We try to send all other key codes to the host directly. | |
| 195 return mInjector.sendKeyEvent(0, keyCode, pressed); | |
| 196 } | |
| 197 } | |
| 198 | |
| 199 public void sendKeyDown(int keyCode) { | |
| 200 mInjector.sendKeyEvent(0, keyCode, true); | |
| 201 } | |
| 202 | |
| 203 public void sendKeyUp(int keyCode) { | |
| 204 mInjector.sendKeyEvent(0, keyCode, false); | |
| 205 } | |
| 206 | |
| 207 /** | |
| 208 * Sends key combinations such as Ctrl-Alt-Del. This injects a key-down even t for every key in | |
| 209 * the list, and then injects the corresponding key-up events. | |
| 210 */ | |
| 211 public void sendKeysPress(int[] keyCodes) { | |
| 212 if (keyCodes != null && keyCodes.length > 0) { | |
|
Lambros
2016/06/22 01:43:14
I don't think you need a null check, and the lengt
Hzj_jie
2016/06/22 23:18:54
I believe Java allows an array to be null. And for
Lambros
2016/06/23 01:40:09
Arguably, it can be better to crash than to silent
Hzj_jie
2016/06/23 18:03:23
Done.
| |
| 213 for (int keyCode : keyCodes) { | |
| 214 sendKeyDown(keyCode); | |
| 215 } | |
| 216 for (int keyCode : keyCodes) { | |
| 217 sendKeyUp(keyCode); | |
| 218 } | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 public void sendCtrlAltDel() { | |
| 223 sendKeysPress(CTRL_ALT_DEL); | |
| 224 } | |
| 225 } | |
| OLD | NEW |