| 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 |