| Index: remoting/android/java/src/org/chromium/chromoting/Desktop.java
|
| diff --git a/remoting/android/java/src/org/chromium/chromoting/Desktop.java b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
|
| index 5ba3f013e16f49b117df19707bc794c946d21f7a..f7fad3fa502d0443c3fe328dad713027dd55f94d 100644
|
| --- a/remoting/android/java/src/org/chromium/chromoting/Desktop.java
|
| +++ b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
|
| @@ -9,6 +9,7 @@ import android.app.Activity;
|
| import android.content.res.Configuration;
|
| import android.os.Build;
|
| import android.os.Bundle;
|
| +import android.view.KeyCharacterMap;
|
| import android.view.KeyEvent;
|
| import android.view.Menu;
|
| import android.view.MenuItem;
|
| @@ -18,6 +19,9 @@ import android.widget.ImageButton;
|
|
|
| import org.chromium.chromoting.jni.JniInterface;
|
|
|
| +import java.util.Set;
|
| +import java.util.TreeSet;
|
| +
|
| /**
|
| * A simple screen that does nothing except display a DesktopView and notify it of rotations.
|
| */
|
| @@ -32,6 +36,9 @@ public class Desktop extends Activity implements View.OnSystemUiVisibilityChange
|
| /** The button used to show the action bar. */
|
| private ImageButton mOverlayButton;
|
|
|
| + /** Set of pressed keys for which we've sent TextEvent. */
|
| + private Set<Integer> mPressedTextKeys = new TreeSet<Integer>();
|
| +
|
| /** Called when the activity is first created. */
|
| @Override
|
| public void onCreate(Bundle savedInstanceState) {
|
| @@ -176,48 +183,65 @@ public class Desktop extends Activity implements View.OnSystemUiVisibilityChange
|
| */
|
| @Override
|
| public boolean dispatchKeyEvent(KeyEvent event) {
|
| - // Send ACTION_MULTIPLE event as TextEvent.
|
| - //
|
| - // TODO(sergeyu): For all keys on English keyboard Android generates
|
| - // ACTION_DOWN/ACTION_UP events, so they are sent as KeyEvent instead of
|
| - // TextEvent. As result the host may handle them as non-English chars
|
| - // when it has non-English layout selected, which might be confusing for
|
| - // the user. This code should be fixed to send all text input events as
|
| - // TextEvent, but it cannot be done now because not all hosts support
|
| - // TextEvent. Also, to handle keyboard shortcuts properly this code will
|
| - // need to track the state of modifier keys (such as Ctrl or Alt) and
|
| - // send KeyEvents in the case any of the modifier keys are pressed.
|
| + // Send TextEvent in two cases:
|
| + // 1. This is an ACTION_MULTIPLE event.
|
| + // 2. The event was generated by on-screen keyboard and Ctrl, Alt and
|
| + // Meta are not pressed.
|
| + // This ensures that on-screen keyboard always injects input that
|
| + // correspond to what user sees on the screen, while physical keyboard
|
| + // acts as if it is connected to the remote host.
|
| if (event.getAction() == KeyEvent.ACTION_MULTIPLE) {
|
| JniInterface.sendTextEvent(event.getCharacters());
|
| return super.dispatchKeyEvent(event);
|
| }
|
|
|
| - boolean depressed = event.getAction() == KeyEvent.ACTION_DOWN;
|
| + int keyCode = event.getKeyCode();
|
| + boolean pressed = event.getAction() == KeyEvent.ACTION_DOWN;
|
| +
|
| + // For Enter getUnicodeChar() returns 10 (line feed), but we still
|
| + // want to send it as KeyEvent.
|
| + int unicode = keyCode != KeyEvent.KEYCODE_ENTER ? event.getUnicodeChar() : 0;
|
| +
|
| + boolean no_modifiers = !event.isAltPressed() &&
|
| + !event.isCtrlPressed() && !event.isMetaPressed();
|
| +
|
| + if (event.getDeviceId() == KeyCharacterMap.VIRTUAL_KEYBOARD &&
|
| + pressed && unicode != 0 && no_modifiers) {
|
| + mPressedTextKeys.add(keyCode);
|
| + int[] codePoints = { unicode };
|
| + JniInterface.sendTextEvent(new String(codePoints, 0, 1));
|
| + return super.dispatchKeyEvent(event);
|
| + }
|
| +
|
| + if (!pressed && mPressedTextKeys.contains(keyCode)) {
|
| + mPressedTextKeys.remove(keyCode);
|
| + return super.dispatchKeyEvent(event);
|
| + }
|
|
|
| - switch (event.getKeyCode()) {
|
| + switch (keyCode) {
|
| case KeyEvent.KEYCODE_AT:
|
| - JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
|
| - JniInterface.sendKeyEvent(KeyEvent.KEYCODE_2, depressed);
|
| + JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, pressed);
|
| + JniInterface.sendKeyEvent(KeyEvent.KEYCODE_2, pressed);
|
| break;
|
|
|
| case KeyEvent.KEYCODE_POUND:
|
| - JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
|
| - JniInterface.sendKeyEvent(KeyEvent.KEYCODE_3, depressed);
|
| + JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, pressed);
|
| + JniInterface.sendKeyEvent(KeyEvent.KEYCODE_3, pressed);
|
| break;
|
|
|
| case KeyEvent.KEYCODE_STAR:
|
| - JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
|
| - JniInterface.sendKeyEvent(KeyEvent.KEYCODE_8, depressed);
|
| + JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, pressed);
|
| + JniInterface.sendKeyEvent(KeyEvent.KEYCODE_8, pressed);
|
| break;
|
|
|
| case KeyEvent.KEYCODE_PLUS:
|
| - JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
|
| - JniInterface.sendKeyEvent(KeyEvent.KEYCODE_EQUALS, depressed);
|
| + JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, pressed);
|
| + JniInterface.sendKeyEvent(KeyEvent.KEYCODE_EQUALS, pressed);
|
| break;
|
|
|
| default:
|
| // We try to send all other key codes to the host directly.
|
| - JniInterface.sendKeyEvent(event.getKeyCode(), depressed);
|
| + JniInterface.sendKeyEvent(keyCode, pressed);
|
| }
|
|
|
| return super.dispatchKeyEvent(event);
|
|
|