OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chromoting; | 5 package org.chromium.chromoting; |
6 | 6 |
7 import android.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
8 import android.content.Intent; | 8 import android.content.Intent; |
9 import android.content.pm.ApplicationInfo; | 9 import android.content.pm.ApplicationInfo; |
10 import android.content.pm.PackageManager; | 10 import android.content.pm.PackageManager; |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 JniInterface.disconnectFromHost(); | 221 JniInterface.disconnectFromHost(); |
222 return true; | 222 return true; |
223 } | 223 } |
224 if (id == R.id.actionbar_send_ctrl_alt_del) { | 224 if (id == R.id.actionbar_send_ctrl_alt_del) { |
225 int[] keys = { | 225 int[] keys = { |
226 KeyEvent.KEYCODE_CTRL_LEFT, | 226 KeyEvent.KEYCODE_CTRL_LEFT, |
227 KeyEvent.KEYCODE_ALT_LEFT, | 227 KeyEvent.KEYCODE_ALT_LEFT, |
228 KeyEvent.KEYCODE_FORWARD_DEL, | 228 KeyEvent.KEYCODE_FORWARD_DEL, |
229 }; | 229 }; |
230 for (int key : keys) { | 230 for (int key : keys) { |
231 JniInterface.sendKeyEvent(key, true); | 231 JniInterface.sendKeyEvent(0, key, true); |
232 } | 232 } |
233 for (int key : keys) { | 233 for (int key : keys) { |
234 JniInterface.sendKeyEvent(key, false); | 234 JniInterface.sendKeyEvent(0, key, false); |
235 } | 235 } |
236 return true; | 236 return true; |
237 } | 237 } |
238 if (id == R.id.actionbar_help) { | 238 if (id == R.id.actionbar_help) { |
239 HelpActivity.launch(this, HELP_URL); | 239 HelpActivity.launch(this, HELP_URL); |
240 return true; | 240 return true; |
241 } | 241 } |
242 return super.onOptionsItemSelected(item); | 242 return super.onOptionsItemSelected(item); |
243 } | 243 } |
244 | 244 |
245 /** | 245 /** |
246 * Called once when a keyboard key is pressed, then again when that same key
is released. This | 246 * Called once when a keyboard key is pressed, then again when that same key
is released. This |
247 * is not guaranteed to be notified of all soft keyboard events: certian key
boards might not | 247 * is not guaranteed to be notified of all soft keyboard events: certian key
boards might not |
248 * call it at all, while others might skip it in certain situations (e.g. sw
ipe input). | 248 * call it at all, while others might skip it in certain situations (e.g. sw
ipe input). |
249 */ | 249 */ |
250 @Override | 250 @Override |
251 public boolean dispatchKeyEvent(KeyEvent event) { | 251 public boolean dispatchKeyEvent(KeyEvent event) { |
252 int keyCode = event.getKeyCode(); | 252 int keyCode = event.getKeyCode(); |
253 | 253 |
254 // Dispatch the back button to the system to handle navigation | 254 // Dispatch the back button to the system to handle navigation |
255 if (keyCode == KeyEvent.KEYCODE_BACK) { | 255 if (keyCode == KeyEvent.KEYCODE_BACK) { |
256 return super.dispatchKeyEvent(event); | 256 return super.dispatchKeyEvent(event); |
257 } | 257 } |
258 | 258 |
259 // Send TextEvent in two cases: | 259 boolean pressed = event.getAction() == KeyEvent.ACTION_DOWN; |
| 260 |
| 261 // Physical keyboard must work as if it is connected to the remote host |
| 262 // and so events coming from physical keyboard never generate text |
| 263 // events. Also scan codes must be used instead of key code, so that |
| 264 // the keyboard layout selected on the client doesn't affect the key |
| 265 // codes sent to the host. |
| 266 if (event.getDeviceId() != KeyCharacterMap.VIRTUAL_KEYBOARD) { |
| 267 return JniInterface.sendKeyEvent(event.getScanCode(), 0, pressed); |
| 268 } |
| 269 |
| 270 // Events received from software keyboards generate TextEvent in two |
| 271 // cases: |
260 // 1. This is an ACTION_MULTIPLE event. | 272 // 1. This is an ACTION_MULTIPLE event. |
261 // 2. The event was generated by on-screen keyboard and Ctrl, Alt and | 273 // 2. Ctrl, Alt and Meta are not pressed. |
262 // Meta are not pressed. | |
263 // This ensures that on-screen keyboard always injects input that | 274 // This ensures that on-screen keyboard always injects input that |
264 // correspond to what user sees on the screen, while physical keyboard | 275 // correspond to what user sees on the screen, while physical keyboard |
265 // acts as if it is connected to the remote host. | 276 // acts as if it is connected to the remote host. |
266 if (event.getAction() == KeyEvent.ACTION_MULTIPLE) { | 277 if (event.getAction() == KeyEvent.ACTION_MULTIPLE) { |
267 JniInterface.sendTextEvent(event.getCharacters()); | 278 JniInterface.sendTextEvent(event.getCharacters()); |
268 return true; | 279 return true; |
269 } | 280 } |
270 | 281 |
271 boolean pressed = event.getAction() == KeyEvent.ACTION_DOWN; | |
272 | |
273 // For Enter getUnicodeChar() returns 10 (line feed), but we still | 282 // For Enter getUnicodeChar() returns 10 (line feed), but we still |
274 // want to send it as KeyEvent. | 283 // want to send it as KeyEvent. |
275 int unicode = keyCode != KeyEvent.KEYCODE_ENTER ? event.getUnicodeChar()
: 0; | 284 int unicode = keyCode != KeyEvent.KEYCODE_ENTER ? event.getUnicodeChar()
: 0; |
276 | 285 |
277 boolean no_modifiers = !event.isAltPressed() | 286 boolean no_modifiers = !event.isAltPressed() |
278 && !event.isCtrlPressed() && !event.isMetaPressed(); | 287 && !event.isCtrlPressed() && !event.isMetaPressed(); |
279 | 288 |
280 if (event.getDeviceId() == KeyCharacterMap.VIRTUAL_KEYBOARD | 289 if (pressed && unicode != 0 && no_modifiers) { |
281 && pressed && unicode != 0 && no_modifiers) { | |
282 mPressedTextKeys.add(keyCode); | 290 mPressedTextKeys.add(keyCode); |
283 int[] codePoints = { unicode }; | 291 int[] codePoints = { unicode }; |
284 JniInterface.sendTextEvent(new String(codePoints, 0, 1)); | 292 JniInterface.sendTextEvent(new String(codePoints, 0, 1)); |
285 return true; | 293 return true; |
286 } | 294 } |
287 | 295 |
288 if (!pressed && mPressedTextKeys.contains(keyCode)) { | 296 if (!pressed && mPressedTextKeys.contains(keyCode)) { |
289 mPressedTextKeys.remove(keyCode); | 297 mPressedTextKeys.remove(keyCode); |
290 return true; | 298 return true; |
291 } | 299 } |
292 | 300 |
293 switch (keyCode) { | 301 switch (keyCode) { |
| 302 // KEYCODE_AT, KEYCODE_POUND, KEYCODE_STAR and KEYCODE_PLUS are |
| 303 // deprecated, but they still need to be here for older devices and |
| 304 // third-party keyboards that may still generate these events. See |
| 305 // https://source.android.com/devices/input/keyboard-devices.html#le
gacy-unsupported-keys |
294 case KeyEvent.KEYCODE_AT: | 306 case KeyEvent.KEYCODE_AT: |
295 JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, pressed); | 307 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, presse
d); |
296 JniInterface.sendKeyEvent(KeyEvent.KEYCODE_2, pressed); | 308 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_2, pressed); |
297 return true; | 309 return true; |
298 | 310 |
299 case KeyEvent.KEYCODE_POUND: | 311 case KeyEvent.KEYCODE_POUND: |
300 JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, pressed); | 312 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, presse
d); |
301 JniInterface.sendKeyEvent(KeyEvent.KEYCODE_3, pressed); | 313 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_3, pressed); |
302 return true; | 314 return true; |
303 | 315 |
304 case KeyEvent.KEYCODE_STAR: | 316 case KeyEvent.KEYCODE_STAR: |
305 JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, pressed); | 317 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, presse
d); |
306 JniInterface.sendKeyEvent(KeyEvent.KEYCODE_8, pressed); | 318 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_8, pressed); |
307 return true; | 319 return true; |
308 | 320 |
309 case KeyEvent.KEYCODE_PLUS: | 321 case KeyEvent.KEYCODE_PLUS: |
310 JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, pressed); | 322 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, presse
d); |
311 JniInterface.sendKeyEvent(KeyEvent.KEYCODE_EQUALS, pressed); | 323 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_EQUALS, pressed); |
312 return true; | 324 return true; |
313 | 325 |
314 default: | 326 default: |
315 // We try to send all other key codes to the host directly. | 327 // We try to send all other key codes to the host directly. |
316 return JniInterface.sendKeyEvent(keyCode, pressed); | 328 return JniInterface.sendKeyEvent(0, keyCode, pressed); |
317 } | 329 } |
318 } | 330 } |
319 } | 331 } |
OLD | NEW |