OSDN Git Service

Add support for full PC keyboards.
authorJack Palevich <jackpal@google.com>
Sun, 28 Nov 2010 04:34:19 +0000 (20:34 -0800)
committerJack Palevich <jackpal@google.com>
Sun, 28 Nov 2010 04:34:19 +0000 (20:34 -0800)
Tested with a Logitech Bluetooth keyboard.

src/jackpal/androidterm/Term.java

index c23ff76..42eb810 100644 (file)
@@ -20,6 +20,7 @@ import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 
@@ -2808,8 +2809,8 @@ class EmulatorView extends View implements GestureDetector.OnGestureListener {
                 + "\000\000\000" // sym .. envelope
                 + "\015\177" // enter, del
                 + "`-=[]\\;'/@"
-                + "\000\000\000"
-                + "+";
+                + "\000\000"
+                + "\000+";
 
             @Override
             public boolean setComposingText(CharSequence text, int newCursorPosition) {
@@ -3061,19 +3062,15 @@ class EmulatorView extends View implements GestureDetector.OnGestureListener {
         } else if (isSystemKey(keyCode, event)) {
             // Don't intercept the system keys
             return super.onKeyDown(keyCode, event);
-        } else if (handleDPad(keyCode, true)) {
-            return true;
         }
 
         // Translate the keyCode into an ASCII character.
-        int letter = mKeyListener.keyDown(keyCode, event);
 
-        if (letter >= 0) {
-            try {
-                mTermOut.write(letter);
-            } catch (IOException e) {
-                // Ignore I/O exceptions
-            }
+        try {
+            mKeyListener.keyDown(keyCode, event, mTermOut,
+                    getKeypadApplicationMode());
+        } catch (IOException e) {
+            // Ignore I/O exceptions
         }
         return true;
     }
@@ -3088,8 +3085,6 @@ class EmulatorView extends View implements GestureDetector.OnGestureListener {
         } else if (isSystemKey(keyCode, event)) {
             // Don't intercept the system keys
             return super.onKeyUp(keyCode, event);
-        } else if (handleDPad(keyCode, false)) {
-            return true;
         }
 
         mKeyListener.keyUp(keyCode);
@@ -3108,54 +3103,6 @@ class EmulatorView extends View implements GestureDetector.OnGestureListener {
         return false;
     }
 
-    /**
-     * Handle dpad left-right-up-down events. Don't handle
-     * dpad-center, that's our control key.
-     * @param keyCode
-     * @param down
-     */
-    private boolean handleDPad(int keyCode, boolean down) {
-        if (keyCode < KeyEvent.KEYCODE_DPAD_UP ||
-                keyCode > KeyEvent.KEYCODE_DPAD_CENTER) {
-            return false;
-        }
-
-        if (down) {
-            try {
-                if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
-                    mTermOut.write('\r');
-                } else {
-                    char code;
-                    switch (keyCode) {
-                    case KeyEvent.KEYCODE_DPAD_UP:
-                        code = 'A';
-                        break;
-                    case KeyEvent.KEYCODE_DPAD_DOWN:
-                        code = 'B';
-                        break;
-                    case KeyEvent.KEYCODE_DPAD_LEFT:
-                        code = 'D';
-                        break;
-                    default:
-                    case KeyEvent.KEYCODE_DPAD_RIGHT:
-                        code = 'C';
-                        break;
-                    }
-                    mTermOut.write(27); // ESC
-                    if (getKeypadApplicationMode()) {
-                        mTermOut.write('O');
-                    } else {
-                        mTermOut.write('[');
-                    }
-                    mTermOut.write(code);
-                }
-            } catch (IOException e) {
-                // Ignore
-            }
-        }
-        return true;
-    }
-
     private boolean isSystemKey(int keyCode, KeyEvent event) {
         return event.isSystem();
     }
@@ -3303,6 +3250,560 @@ class EmulatorView extends View implements GestureDetector.OnGestureListener {
  */
 class TermKeyListener {
     /**
+     * Android key codes that are defined in the Android 2.3 API.
+     * We want to recognize these codes, because they will be sent to our
+     * app when we run on Android 2.3 systems.
+     * But we don't want to accidentally use 2.3-specific APIs.
+     * So we compile against the Android 1.6 APIs, and have a copy of the codes here.
+     */
+
+    /** Key code constant: Unknown key code. */
+    public static final int KEYCODE_UNKNOWN         = 0;
+    /** Key code constant: Soft Left key.
+     * Usually situated below the display on phones and used as a multi-function
+     * feature key for selecting a software defined function shown on the bottom left
+     * of the display. */
+    public static final int KEYCODE_SOFT_LEFT       = 1;
+    /** Key code constant: Soft Right key.
+     * Usually situated below the display on phones and used as a multi-function
+     * feature key for selecting a software defined function shown on the bottom right
+     * of the display. */
+    public static final int KEYCODE_SOFT_RIGHT      = 2;
+    /** Key code constant: Home key.
+     * This key is handled by the framework and is never delivered to applications. */
+    public static final int KEYCODE_HOME            = 3;
+    /** Key code constant: Back key. */
+    public static final int KEYCODE_BACK            = 4;
+    /** Key code constant: Call key. */
+    public static final int KEYCODE_CALL            = 5;
+    /** Key code constant: End Call key. */
+    public static final int KEYCODE_ENDCALL         = 6;
+    /** Key code constant: '0' key. */
+    public static final int KEYCODE_0               = 7;
+    /** Key code constant: '1' key. */
+    public static final int KEYCODE_1               = 8;
+    /** Key code constant: '2' key. */
+    public static final int KEYCODE_2               = 9;
+    /** Key code constant: '3' key. */
+    public static final int KEYCODE_3               = 10;
+    /** Key code constant: '4' key. */
+    public static final int KEYCODE_4               = 11;
+    /** Key code constant: '5' key. */
+    public static final int KEYCODE_5               = 12;
+    /** Key code constant: '6' key. */
+    public static final int KEYCODE_6               = 13;
+    /** Key code constant: '7' key. */
+    public static final int KEYCODE_7               = 14;
+    /** Key code constant: '8' key. */
+    public static final int KEYCODE_8               = 15;
+    /** Key code constant: '9' key. */
+    public static final int KEYCODE_9               = 16;
+    /** Key code constant: '*' key. */
+    public static final int KEYCODE_STAR            = 17;
+    /** Key code constant: '#' key. */
+    public static final int KEYCODE_POUND           = 18;
+    /** Key code constant: Directional Pad Up key.
+     * May also be synthesized from trackball motions. */
+    public static final int KEYCODE_DPAD_UP         = 19;
+    /** Key code constant: Directional Pad Down key.
+     * May also be synthesized from trackball motions. */
+    public static final int KEYCODE_DPAD_DOWN       = 20;
+    /** Key code constant: Directional Pad Left key.
+     * May also be synthesized from trackball motions. */
+    public static final int KEYCODE_DPAD_LEFT       = 21;
+    /** Key code constant: Directional Pad Right key.
+     * May also be synthesized from trackball motions. */
+    public static final int KEYCODE_DPAD_RIGHT      = 22;
+    /** Key code constant: Directional Pad Center key.
+     * May also be synthesized from trackball motions. */
+    public static final int KEYCODE_DPAD_CENTER     = 23;
+    /** Key code constant: Volume Up key.
+     * Adjusts the speaker volume up. */
+    public static final int KEYCODE_VOLUME_UP       = 24;
+    /** Key code constant: Volume Down key.
+     * Adjusts the speaker volume down. */
+    public static final int KEYCODE_VOLUME_DOWN     = 25;
+    /** Key code constant: Power key. */
+    public static final int KEYCODE_POWER           = 26;
+    /** Key code constant: Camera key.
+     * Used to launch a camera application or take pictures. */
+    public static final int KEYCODE_CAMERA          = 27;
+    /** Key code constant: Clear key. */
+    public static final int KEYCODE_CLEAR           = 28;
+    /** Key code constant: 'A' key. */
+    public static final int KEYCODE_A               = 29;
+    /** Key code constant: 'B' key. */
+    public static final int KEYCODE_B               = 30;
+    /** Key code constant: 'C' key. */
+    public static final int KEYCODE_C               = 31;
+    /** Key code constant: 'D' key. */
+    public static final int KEYCODE_D               = 32;
+    /** Key code constant: 'E' key. */
+    public static final int KEYCODE_E               = 33;
+    /** Key code constant: 'F' key. */
+    public static final int KEYCODE_F               = 34;
+    /** Key code constant: 'G' key. */
+    public static final int KEYCODE_G               = 35;
+    /** Key code constant: 'H' key. */
+    public static final int KEYCODE_H               = 36;
+    /** Key code constant: 'I' key. */
+    public static final int KEYCODE_I               = 37;
+    /** Key code constant: 'J' key. */
+    public static final int KEYCODE_J               = 38;
+    /** Key code constant: 'K' key. */
+    public static final int KEYCODE_K               = 39;
+    /** Key code constant: 'L' key. */
+    public static final int KEYCODE_L               = 40;
+    /** Key code constant: 'M' key. */
+    public static final int KEYCODE_M               = 41;
+    /** Key code constant: 'N' key. */
+    public static final int KEYCODE_N               = 42;
+    /** Key code constant: 'O' key. */
+    public static final int KEYCODE_O               = 43;
+    /** Key code constant: 'P' key. */
+    public static final int KEYCODE_P               = 44;
+    /** Key code constant: 'Q' key. */
+    public static final int KEYCODE_Q               = 45;
+    /** Key code constant: 'R' key. */
+    public static final int KEYCODE_R               = 46;
+    /** Key code constant: 'S' key. */
+    public static final int KEYCODE_S               = 47;
+    /** Key code constant: 'T' key. */
+    public static final int KEYCODE_T               = 48;
+    /** Key code constant: 'U' key. */
+    public static final int KEYCODE_U               = 49;
+    /** Key code constant: 'V' key. */
+    public static final int KEYCODE_V               = 50;
+    /** Key code constant: 'W' key. */
+    public static final int KEYCODE_W               = 51;
+    /** Key code constant: 'X' key. */
+    public static final int KEYCODE_X               = 52;
+    /** Key code constant: 'Y' key. */
+    public static final int KEYCODE_Y               = 53;
+    /** Key code constant: 'Z' key. */
+    public static final int KEYCODE_Z               = 54;
+    /** Key code constant: ',' key. */
+    public static final int KEYCODE_COMMA           = 55;
+    /** Key code constant: '.' key. */
+    public static final int KEYCODE_PERIOD          = 56;
+    /** Key code constant: Left Alt modifier key. */
+    public static final int KEYCODE_ALT_LEFT        = 57;
+    /** Key code constant: Right Alt modifier key. */
+    public static final int KEYCODE_ALT_RIGHT       = 58;
+    /** Key code constant: Left Shift modifier key. */
+    public static final int KEYCODE_SHIFT_LEFT      = 59;
+    /** Key code constant: Right Shift modifier key. */
+    public static final int KEYCODE_SHIFT_RIGHT     = 60;
+    /** Key code constant: Tab key. */
+    public static final int KEYCODE_TAB             = 61;
+    /** Key code constant: Space key. */
+    public static final int KEYCODE_SPACE           = 62;
+    /** Key code constant: Symbol modifier key.
+     * Used to enter alternate symbols. */
+    public static final int KEYCODE_SYM             = 63;
+    /** Key code constant: Explorer special function key.
+     * Used to launch a browser application. */
+    public static final int KEYCODE_EXPLORER        = 64;
+    /** Key code constant: Envelope special function key.
+     * Used to launch a mail application. */
+    public static final int KEYCODE_ENVELOPE        = 65;
+    /** Key code constant: Enter key. */
+    public static final int KEYCODE_ENTER           = 66;
+    /** Key code constant: Backspace key.
+     * Deletes characters before the insertion point, unlike {@link #KEYCODE_FORWARD_DEL}. */
+    public static final int KEYCODE_DEL             = 67;
+    /** Key code constant: '`' (backtick) key. */
+    public static final int KEYCODE_GRAVE           = 68;
+    /** Key code constant: '-'. */
+    public static final int KEYCODE_MINUS           = 69;
+    /** Key code constant: '=' key. */
+    public static final int KEYCODE_EQUALS          = 70;
+    /** Key code constant: '[' key. */
+    public static final int KEYCODE_LEFT_BRACKET    = 71;
+    /** Key code constant: ']' key. */
+    public static final int KEYCODE_RIGHT_BRACKET   = 72;
+    /** Key code constant: '\' key. */
+    public static final int KEYCODE_BACKSLASH       = 73;
+    /** Key code constant: ';' key. */
+    public static final int KEYCODE_SEMICOLON       = 74;
+    /** Key code constant: ''' (apostrophe) key. */
+    public static final int KEYCODE_APOSTROPHE      = 75;
+    /** Key code constant: '/' key. */
+    public static final int KEYCODE_SLASH           = 76;
+    /** Key code constant: '@' key. */
+    public static final int KEYCODE_AT              = 77;
+    /** Key code constant: Number modifier key.
+     * Used to enter numeric symbols.
+     * This key is not Num Lock; it is more like {@link #KEYCODE_ALT_LEFT} and is
+     * interpreted as an ALT key by {@link android.text.method.MetaKeyKeyListener}. */
+    public static final int KEYCODE_NUM             = 78;
+    /** Key code constant: Headset Hook key.
+     * Used to hang up calls and stop media. */
+    public static final int KEYCODE_HEADSETHOOK     = 79;
+    /** Key code constant: Camera Focus key.
+     * Used to focus the camera. */
+    public static final int KEYCODE_FOCUS           = 80;   // *Camera* focus
+    /** Key code constant: '+' key. */
+    public static final int KEYCODE_PLUS            = 81;
+    /** Key code constant: Menu key. */
+    public static final int KEYCODE_MENU            = 82;
+    /** Key code constant: Notification key. */
+    public static final int KEYCODE_NOTIFICATION    = 83;
+    /** Key code constant: Search key. */
+    public static final int KEYCODE_SEARCH          = 84;
+    /** Key code constant: Play/Pause media key. */
+    public static final int KEYCODE_MEDIA_PLAY_PAUSE= 85;
+    /** Key code constant: Stop media key. */
+    public static final int KEYCODE_MEDIA_STOP      = 86;
+    /** Key code constant: Play Next media key. */
+    public static final int KEYCODE_MEDIA_NEXT      = 87;
+    /** Key code constant: Play Previous media key. */
+    public static final int KEYCODE_MEDIA_PREVIOUS  = 88;
+    /** Key code constant: Rewind media key. */
+    public static final int KEYCODE_MEDIA_REWIND    = 89;
+    /** Key code constant: Fast Forward media key. */
+    public static final int KEYCODE_MEDIA_FAST_FORWARD = 90;
+    /** Key code constant: Mute key.
+     * Mutes the microphone, unlike {@link #KEYCODE_VOLUME_MUTE}. */
+    public static final int KEYCODE_MUTE            = 91;
+    /** Key code constant: Page Up key. */
+    public static final int KEYCODE_PAGE_UP         = 92;
+    /** Key code constant: Page Down key. */
+    public static final int KEYCODE_PAGE_DOWN       = 93;
+    /** Key code constant: Picture Symbols modifier key.
+     * Used to switch symbol sets (Emoji, Kao-moji). */
+    public static final int KEYCODE_PICTSYMBOLS     = 94;   // switch symbol-sets (Emoji,Kao-moji)
+    /** Key code constant: Switch Charset modifier key.
+     * Used to switch character sets (Kanji, Katakana). */
+    public static final int KEYCODE_SWITCH_CHARSET  = 95;   // switch char-sets (Kanji,Katakana)
+    /** Key code constant: A Button key.
+     * On a game controller, the A button should be either the button labeled A
+     * or the first button on the upper row of controller buttons. */
+    public static final int KEYCODE_BUTTON_A        = 96;
+    /** Key code constant: B Button key.
+     * On a game controller, the B button should be either the button labeled B
+     * or the second button on the upper row of controller buttons. */
+    public static final int KEYCODE_BUTTON_B        = 97;
+    /** Key code constant: C Button key.
+     * On a game controller, the C button should be either the button labeled C
+     * or the third button on the upper row of controller buttons. */
+    public static final int KEYCODE_BUTTON_C        = 98;
+    /** Key code constant: X Button key.
+     * On a game controller, the X button should be either the button labeled X
+     * or the first button on the lower row of controller buttons. */
+    public static final int KEYCODE_BUTTON_X        = 99;
+    /** Key code constant: Y Button key.
+     * On a game controller, the Y button should be either the button labeled Y
+     * or the second button on the lower row of controller buttons. */
+    public static final int KEYCODE_BUTTON_Y        = 100;
+    /** Key code constant: Z Button key.
+     * On a game controller, the Z button should be either the button labeled Z
+     * or the third button on the lower row of controller buttons. */
+    public static final int KEYCODE_BUTTON_Z        = 101;
+    /** Key code constant: L1 Button key.
+     * On a game controller, the L1 button should be either the button labeled L1 (or L)
+     * or the top left trigger button. */
+    public static final int KEYCODE_BUTTON_L1       = 102;
+    /** Key code constant: R1 Button key.
+     * On a game controller, the R1 button should be either the button labeled R1 (or R)
+     * or the top right trigger button. */
+    public static final int KEYCODE_BUTTON_R1       = 103;
+    /** Key code constant: L2 Button key.
+     * On a game controller, the L2 button should be either the button labeled L2
+     * or the bottom left trigger button. */
+    public static final int KEYCODE_BUTTON_L2       = 104;
+    /** Key code constant: R2 Button key.
+     * On a game controller, the R2 button should be either the button labeled R2
+     * or the bottom right trigger button. */
+    public static final int KEYCODE_BUTTON_R2       = 105;
+    /** Key code constant: Left Thumb Button key.
+     * On a game controller, the left thumb button indicates that the left (or only)
+     * joystick is pressed. */
+    public static final int KEYCODE_BUTTON_THUMBL   = 106;
+    /** Key code constant: Right Thumb Button key.
+     * On a game controller, the right thumb button indicates that the right
+     * joystick is pressed. */
+    public static final int KEYCODE_BUTTON_THUMBR   = 107;
+    /** Key code constant: Start Button key.
+     * On a game controller, the button labeled Start. */
+    public static final int KEYCODE_BUTTON_START    = 108;
+    /** Key code constant: Select Button key.
+     * On a game controller, the button labeled Select. */
+    public static final int KEYCODE_BUTTON_SELECT   = 109;
+    /** Key code constant: Mode Button key.
+     * On a game controller, the button labeled Mode. */
+    public static final int KEYCODE_BUTTON_MODE     = 110;
+    /** Key code constant: Escape key. */
+    public static final int KEYCODE_ESCAPE          = 111;
+    /** Key code constant: Forward Delete key.
+     * Deletes characters ahead of the insertion point, unlike {@link #KEYCODE_DEL}. */
+    public static final int KEYCODE_FORWARD_DEL     = 112;
+    /** Key code constant: Left Control modifier key. */
+    public static final int KEYCODE_CTRL_LEFT       = 113;
+    /** Key code constant: Right Control modifier key. */
+    public static final int KEYCODE_CTRL_RIGHT      = 114;
+    /** Key code constant: Caps Lock modifier key. */
+    public static final int KEYCODE_CAPS_LOCK       = 115;
+    /** Key code constant: Scroll Lock key. */
+    public static final int KEYCODE_SCROLL_LOCK     = 116;
+    /** Key code constant: Left Meta modifier key. */
+    public static final int KEYCODE_META_LEFT       = 117;
+    /** Key code constant: Right Meta modifier key. */
+    public static final int KEYCODE_META_RIGHT      = 118;
+    /** Key code constant: Function modifier key. */
+    public static final int KEYCODE_FUNCTION        = 119;
+    /** Key code constant: System Request / Print Screen key. */
+    public static final int KEYCODE_SYSRQ           = 120;
+    /** Key code constant: Break / Pause key. */
+    public static final int KEYCODE_BREAK           = 121;
+    /** Key code constant: Home Movement key.
+     * Used for scrolling or moving the cursor around to the start of a line
+     * or to the top of a list. */
+    public static final int KEYCODE_MOVE_HOME       = 122;
+    /** Key code constant: End Movement key.
+     * Used for scrolling or moving the cursor around to the end of a line
+     * or to the bottom of a list. */
+    public static final int KEYCODE_MOVE_END        = 123;
+    /** Key code constant: Insert key.
+     * Toggles insert / overwrite edit mode. */
+    public static final int KEYCODE_INSERT          = 124;
+    /** Key code constant: Forward key.
+     * Navigates forward in the history stack.  Complement of {@link #KEYCODE_BACK}. */
+    public static final int KEYCODE_FORWARD         = 125;
+    /** Key code constant: Play media key. */
+    public static final int KEYCODE_MEDIA_PLAY      = 126;
+    /** Key code constant: Pause media key. */
+    public static final int KEYCODE_MEDIA_PAUSE     = 127;
+    /** Key code constant: Close media key.
+     * May be used to close a CD tray, for example. */
+    public static final int KEYCODE_MEDIA_CLOSE     = 128;
+    /** Key code constant: Eject media key.
+     * May be used to eject a CD tray, for example. */
+    public static final int KEYCODE_MEDIA_EJECT     = 129;
+    /** Key code constant: Record media key. */
+    public static final int KEYCODE_MEDIA_RECORD    = 130;
+    /** Key code constant: F1 key. */
+    public static final int KEYCODE_F1              = 131;
+    /** Key code constant: F2 key. */
+    public static final int KEYCODE_F2              = 132;
+    /** Key code constant: F3 key. */
+    public static final int KEYCODE_F3              = 133;
+    /** Key code constant: F4 key. */
+    public static final int KEYCODE_F4              = 134;
+    /** Key code constant: F5 key. */
+    public static final int KEYCODE_F5              = 135;
+    /** Key code constant: F6 key. */
+    public static final int KEYCODE_F6              = 136;
+    /** Key code constant: F7 key. */
+    public static final int KEYCODE_F7              = 137;
+    /** Key code constant: F8 key. */
+    public static final int KEYCODE_F8              = 138;
+    /** Key code constant: F9 key. */
+    public static final int KEYCODE_F9              = 139;
+    /** Key code constant: F10 key. */
+    public static final int KEYCODE_F10             = 140;
+    /** Key code constant: F11 key. */
+    public static final int KEYCODE_F11             = 141;
+    /** Key code constant: F12 key. */
+    public static final int KEYCODE_F12             = 142;
+    /** Key code constant: Num Lock modifier key.
+     * This is the Num Lock key; it is different from {@link #KEYCODE_NUM}.
+     * This key generally modifies the behavior of other keys on the numeric keypad. */
+    public static final int KEYCODE_NUM_LOCK        = 143;
+    /** Key code constant: Numeric keypad '0' key. */
+    public static final int KEYCODE_NUMPAD_0        = 144;
+    /** Key code constant: Numeric keypad '1' key. */
+    public static final int KEYCODE_NUMPAD_1        = 145;
+    /** Key code constant: Numeric keypad '2' key. */
+    public static final int KEYCODE_NUMPAD_2        = 146;
+    /** Key code constant: Numeric keypad '3' key. */
+    public static final int KEYCODE_NUMPAD_3        = 147;
+    /** Key code constant: Numeric keypad '4' key. */
+    public static final int KEYCODE_NUMPAD_4        = 148;
+    /** Key code constant: Numeric keypad '5' key. */
+    public static final int KEYCODE_NUMPAD_5        = 149;
+    /** Key code constant: Numeric keypad '6' key. */
+    public static final int KEYCODE_NUMPAD_6        = 150;
+    /** Key code constant: Numeric keypad '7' key. */
+    public static final int KEYCODE_NUMPAD_7        = 151;
+    /** Key code constant: Numeric keypad '8' key. */
+    public static final int KEYCODE_NUMPAD_8        = 152;
+    /** Key code constant: Numeric keypad '9' key. */
+    public static final int KEYCODE_NUMPAD_9        = 153;
+    /** Key code constant: Numeric keypad '/' key (for division). */
+    public static final int KEYCODE_NUMPAD_DIVIDE   = 154;
+    /** Key code constant: Numeric keypad '*' key (for multiplication). */
+    public static final int KEYCODE_NUMPAD_MULTIPLY = 155;
+    /** Key code constant: Numeric keypad '-' key (for subtraction). */
+    public static final int KEYCODE_NUMPAD_SUBTRACT = 156;
+    /** Key code constant: Numeric keypad '+' key (for addition). */
+    public static final int KEYCODE_NUMPAD_ADD      = 157;
+    /** Key code constant: Numeric keypad '.' key (for decimals or digit grouping). */
+    public static final int KEYCODE_NUMPAD_DOT      = 158;
+    /** Key code constant: Numeric keypad ',' key (for decimals or digit grouping). */
+    public static final int KEYCODE_NUMPAD_COMMA    = 159;
+    /** Key code constant: Numeric keypad Enter key. */
+    public static final int KEYCODE_NUMPAD_ENTER    = 160;
+    /** Key code constant: Numeric keypad '=' key. */
+    public static final int KEYCODE_NUMPAD_EQUALS   = 161;
+    /** Key code constant: Numeric keypad '(' key. */
+    public static final int KEYCODE_NUMPAD_LEFT_PAREN = 162;
+    /** Key code constant: Numeric keypad ')' key. */
+    public static final int KEYCODE_NUMPAD_RIGHT_PAREN = 163;
+    /** Key code constant: Volume Mute key.
+     * Mutes the speaker, unlike {@link #KEYCODE_MUTE}.
+     * This key should normally be implemented as a toggle such that the first press
+     * mutes the speaker and the second press restores the original volume. */
+    public static final int KEYCODE_VOLUME_MUTE     = 164;
+    /** Key code constant: Info key.
+     * Common on TV remotes to show additional information related to what is
+     * currently being viewed. */
+    public static final int KEYCODE_INFO            = 165;
+    /** Key code constant: Channel up key.
+     * On TV remotes, increments the television channel. */
+    public static final int KEYCODE_CHANNEL_UP      = 166;
+    /** Key code constant: Channel down key.
+     * On TV remotes, decrements the television channel. */
+    public static final int KEYCODE_CHANNEL_DOWN    = 167;
+    /** Key code constant: Zoom in key. */
+    public static final int KEYCODE_ZOOM_IN         = 168;
+    /** Key code constant: Zoom out key. */
+    public static final int KEYCODE_ZOOM_OUT        = 169;
+    /** Key code constant: TV key.
+     * On TV remotes, switches to viewing live TV. */
+    public static final int KEYCODE_TV              = 170;
+    /** Key code constant: Window key.
+     * On TV remotes, toggles picture-in-picture mode or other windowing functions. */
+    public static final int KEYCODE_WINDOW          = 171;
+    /** Key code constant: Guide key.
+     * On TV remotes, shows a programming guide. */
+    public static final int KEYCODE_GUIDE           = 172;
+    /** Key code constant: DVR key.
+     * On some TV remotes, switches to a DVR mode for recorded shows. */
+    public static final int KEYCODE_DVR             = 173;
+    /** Key code constant: Bookmark key.
+     * On some TV remotes, bookmarks content or web pages. */
+    public static final int KEYCODE_BOOKMARK        = 174;
+    /** Key code constant: Toggle captions key.
+     * Switches the mode for closed-captioning text, for example during television shows. */
+    public static final int KEYCODE_CAPTIONS        = 175;
+    /** Key code constant: Settings key.
+     * Starts the system settings activity. */
+    public static final int KEYCODE_SETTINGS        = 176;
+    /** Key code constant: TV power key.
+     * On TV remotes, toggles the power on a television screen. */
+    public static final int KEYCODE_TV_POWER        = 177;
+    /** Key code constant: TV input key.
+     * On TV remotes, switches the input on a television screen. */
+    public static final int KEYCODE_TV_INPUT        = 178;
+    /** Key code constant: Set-top-box power key.
+     * On TV remotes, toggles the power on an external Set-top-box. */
+    public static final int KEYCODE_STB_POWER       = 179;
+    /** Key code constant: Set-top-box input key.
+     * On TV remotes, switches the input mode on an external Set-top-box. */
+    public static final int KEYCODE_STB_INPUT       = 180;
+    /** Key code constant: A/V Receiver power key.
+     * On TV remotes, toggles the power on an external A/V Receiver. */
+    public static final int KEYCODE_AVR_POWER       = 181;
+    /** Key code constant: A/V Receiver input key.
+     * On TV remotes, switches the input mode on an external A/V Receiver. */
+    public static final int KEYCODE_AVR_INPUT       = 182;
+    /** Key code constant: Red "programmable" key.
+     * On TV remotes, acts as a contextual/programmable key. */
+    public static final int KEYCODE_PROG_RED        = 183;
+    /** Key code constant: Green "programmable" key.
+     * On TV remotes, actsas a contextual/programmable key. */
+    public static final int KEYCODE_PROG_GREEN      = 184;
+    /** Key code constant: Yellow "programmable" key.
+     * On TV remotes, acts as a contextual/programmable key. */
+    public static final int KEYCODE_PROG_YELLOW     = 185;
+    /** Key code constant: Blue "programmable" key.
+     * On TV remotes, acts as a contextual/programmable key. */
+    public static final int KEYCODE_PROG_BLUE       = 186;
+
+    private static final int LAST_KEYCODE           = KEYCODE_PROG_BLUE;
+
+    private String[] mKeyCodes = new String[256];
+    private String[] mAppKeyCodes = new String[256];
+
+    private void initKeyCodes() {
+        mKeyCodes[KEYCODE_DPAD_CENTER] = "\015";
+        mKeyCodes[KEYCODE_DPAD_UP] = "\033[A";
+        mKeyCodes[KEYCODE_DPAD_DOWN] = "\033[B";
+        mKeyCodes[KEYCODE_DPAD_RIGHT] = "\033[C";
+        mKeyCodes[KEYCODE_DPAD_LEFT] = "\033[D";
+        mKeyCodes[KEYCODE_F1] = "\033[OP";
+        mKeyCodes[KEYCODE_F2] = "\033[OQ";
+        mKeyCodes[KEYCODE_F3] = "\033[OR";
+        mKeyCodes[KEYCODE_F4] = "\033[OS";
+        mKeyCodes[KEYCODE_F5] = "\033[15~";
+        mKeyCodes[KEYCODE_F6] = "\033[17~";
+        mKeyCodes[KEYCODE_F7] = "\033[18~";
+        mKeyCodes[KEYCODE_F8] = "\033[19~";
+        mKeyCodes[KEYCODE_F9] = "\033[20~";
+        mKeyCodes[KEYCODE_F10] = "\033[21~";
+        mKeyCodes[KEYCODE_F11] = "\033[23~";
+        mKeyCodes[KEYCODE_F12] = "\033[24~";
+        mKeyCodes[KEYCODE_SYSRQ] = "\033[32~"; // Sys Request / Print
+        // Is this Scroll lock? mKeyCodes[Cancel] = "\033[33~";
+        mKeyCodes[KEYCODE_BREAK] = "\033[34~"; // Pause/Break
+
+        mKeyCodes[KEYCODE_TAB] = "\011";
+        mKeyCodes[KEYCODE_ENTER] = "\015";
+        mKeyCodes[KEYCODE_ESCAPE] = "\033";
+
+        mKeyCodes[KEYCODE_INSERT] = "\033[2~";
+        mKeyCodes[KEYCODE_FORWARD_DEL] = "\033[3~";
+        mKeyCodes[KEYCODE_MOVE_HOME] = "\033[1~";
+        mKeyCodes[KEYCODE_MOVE_END] = "\033[4~";
+        mKeyCodes[KEYCODE_PAGE_UP] = "\033[5~";
+        mKeyCodes[KEYCODE_PAGE_DOWN] = "\033[6~";
+        mKeyCodes[KEYCODE_DEL]= "\177";
+        mKeyCodes[KEYCODE_NUM_LOCK] = "\033OP";
+        mKeyCodes[KEYCODE_NUMPAD_DIVIDE] = "/";
+        mKeyCodes[KEYCODE_NUMPAD_MULTIPLY] = "*";
+        mKeyCodes[KEYCODE_NUMPAD_SUBTRACT] = "-";
+        mKeyCodes[KEYCODE_NUMPAD_ADD] = "+";
+        mKeyCodes[KEYCODE_NUMPAD_ENTER] = "\015";
+        mKeyCodes[KEYCODE_NUMPAD_EQUALS] = "=";
+        mKeyCodes[KEYCODE_NUMPAD_DOT] = ".";
+        mKeyCodes[KEYCODE_NUMPAD_COMMA] = ",";
+        mKeyCodes[KEYCODE_NUMPAD_0] = "0";
+        mKeyCodes[KEYCODE_NUMPAD_1] = "1";
+        mKeyCodes[KEYCODE_NUMPAD_2] = "2";
+        mKeyCodes[KEYCODE_NUMPAD_3] = "3";
+        mKeyCodes[KEYCODE_NUMPAD_4] = "4";
+        mKeyCodes[KEYCODE_NUMPAD_5] = "5";
+        mKeyCodes[KEYCODE_NUMPAD_6] = "6";
+        mKeyCodes[KEYCODE_NUMPAD_7] = "7";
+        mKeyCodes[KEYCODE_NUMPAD_8] = "8";
+        mKeyCodes[KEYCODE_NUMPAD_9] = "9";
+
+        mAppKeyCodes[KEYCODE_DPAD_UP] = "\033OA";
+        mAppKeyCodes[KEYCODE_DPAD_DOWN] = "\033OB";
+        mAppKeyCodes[KEYCODE_DPAD_RIGHT] = "\033OC";
+        mAppKeyCodes[KEYCODE_DPAD_LEFT] = "\033OD";
+        mAppKeyCodes[KEYCODE_NUMPAD_DIVIDE] = "\033Oo";
+        mAppKeyCodes[KEYCODE_NUMPAD_MULTIPLY] = "\033Oj";
+        mAppKeyCodes[KEYCODE_NUMPAD_SUBTRACT] = "\033Om";
+        mAppKeyCodes[KEYCODE_NUMPAD_ADD] = "\033Ok";
+        mAppKeyCodes[KEYCODE_NUMPAD_ENTER] = "\033OM";
+        mAppKeyCodes[KEYCODE_NUMPAD_EQUALS] = "\033OX";
+        mAppKeyCodes[KEYCODE_NUMPAD_DOT] = "\033On";
+        mAppKeyCodes[KEYCODE_NUMPAD_COMMA] = "\033Ol";
+        mAppKeyCodes[KEYCODE_NUMPAD_0] = "\033Op";
+        mAppKeyCodes[KEYCODE_NUMPAD_1] = "\033Oq";
+        mAppKeyCodes[KEYCODE_NUMPAD_2] = "\033Or";
+        mAppKeyCodes[KEYCODE_NUMPAD_3] = "\033Os";
+        mAppKeyCodes[KEYCODE_NUMPAD_4] = "\033Ot";
+        mAppKeyCodes[KEYCODE_NUMPAD_5] = "\033Ou";
+        mAppKeyCodes[KEYCODE_NUMPAD_6] = "\033Ov";
+        mAppKeyCodes[KEYCODE_NUMPAD_7] = "\033Ow";
+        mAppKeyCodes[KEYCODE_NUMPAD_8] = "\033Ox";
+        mAppKeyCodes[KEYCODE_NUMPAD_9] = "\033Oy";
+    }
+
+    /**
      * The state engine for a modifier key. Can be pressed, released, locked,
      * and so on.
      *
@@ -3388,11 +3889,14 @@ class TermKeyListener {
 
     private ModifierKey mControlKey = new ModifierKey();
 
+    private boolean mCapsLock;
+
     /**
      * Construct a term key listener.
      *
      */
     public TermKeyListener() {
+        initKeyCodes();
     }
 
     public void handleControlKey(boolean down) {
@@ -3436,10 +3940,25 @@ class TermKeyListener {
      * Handle a keyDown event.
      *
      * @param keyCode the keycode of the keyDown event
-     * @return the ASCII byte to transmit to the pseudo-teletype, or -1 if this
-     *         event does not produce an ASCII byte.
+     *
      */
-    public int keyDown(int keyCode, KeyEvent event) {
+    public void keyDown(int keyCode, KeyEvent event, OutputStream out, boolean appMode) throws IOException {
+        if (keyCode >= 0 && keyCode < mKeyCodes.length) {
+            String code = null;
+            if (appMode) {
+                code = mAppKeyCodes[keyCode];
+            }
+            if (code == null) {
+                code = mKeyCodes[keyCode];
+            }
+            if (code != null) {
+                int length = code.length();
+                for (int i = 0; i < length; i++) {
+                    out.write(code.charAt(i));
+                }
+                return;
+            }
+        }
         int result = -1;
         switch (keyCode) {
         case KeyEvent.KEYCODE_ALT_RIGHT:
@@ -3452,21 +3971,20 @@ class TermKeyListener {
             mCapKey.onPress();
             break;
 
-        case KeyEvent.KEYCODE_ENTER:
-            // Convert newlines into returns. The vt100 sends a
-            // '\r' when the 'Return' key is pressed, but our
-            // KeyEvent translates this as a '\n'.
-            result = '\r';
+        case KEYCODE_CTRL_LEFT:
+        case KEYCODE_CTRL_RIGHT:
+            mControlKey.onPress();
             break;
 
-        case KeyEvent.KEYCODE_DEL:
-            // Convert DEL into 127 (instead of 8)
-            result = 127;
+        case KEYCODE_CAPS_LOCK:
+            if (event.getRepeatCount() == 0) {
+                mCapsLock = !mCapsLock;
+            }
             break;
 
         default: {
             result = event.getUnicodeChar(
-                   (mCapKey.isActive() ? KeyEvent.META_SHIFT_ON : 0) |
+                   (mCapKey.isActive() || mCapsLock ? KeyEvent.META_SHIFT_ON : 0) |
                    (mAltKey.isActive() ? KeyEvent.META_ALT_ON : 0));
             break;
             }
@@ -3474,7 +3992,9 @@ class TermKeyListener {
 
         result = mapControlChar(result);
 
-        return result;
+        if (result >= 0) {
+            out.write(result);
+        }
     }
 
     /**
@@ -3492,6 +4012,12 @@ class TermKeyListener {
         case KeyEvent.KEYCODE_SHIFT_RIGHT:
             mCapKey.onRelease();
             break;
+
+        case KEYCODE_CTRL_LEFT:
+        case KEYCODE_CTRL_RIGHT:
+            mControlKey.onRelease();
+            break;
+
         default:
             // Ignore other keyUps
             break;