1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.terminal;
18 
19 import android.util.Log;
20 import android.view.KeyCharacterMap;
21 import android.view.KeyEvent;
22 import android.view.View;
23 
24 public class TerminalKeys {
25     private static final String TAG = "TerminalKeys";
26     private static final boolean DEBUG = true;
27     // Taken from vterm_input.h
28     // TODO: Consider setting these via jni
29     public static final int VTERM_KEY_NONE      = 0;
30     public static final int VTERM_KEY_ENTER     = 1;
31     public static final int VTERM_KEY_TAB       = 2;
32     public static final int VTERM_KEY_BACKSPACE = 3;
33     public static final int VTERM_KEY_ESCAPE    = 4;
34     public static final int VTERM_KEY_UP        = 5;
35     public static final int VTERM_KEY_DOWN      = 6;
36     public static final int VTERM_KEY_LEFT      = 7;
37     public static final int VTERM_KEY_RIGHT     = 8;
38     public static final int VTERM_KEY_INS       = 9;
39     public static final int VTERM_KEY_DEL       = 10;
40     public static final int VTERM_KEY_HOME      = 11;
41     public static final int VTERM_KEY_END       = 12;
42     public static final int VTERM_KEY_PAGEUP    = 13;
43     public static final int VTERM_KEY_PAGEDOWN  = 14;
44 
45     public static final int VTERM_KEY_FUNCTION_0   = 256;
46     public static final int VTERM_KEY_FUNCTION_MAX = VTERM_KEY_FUNCTION_0 + 255;
47 
48     public static final int VTERM_KEY_KP_0 = 512;
49     public static final int VTERM_KEY_KP_1 = 513;
50     public static final int VTERM_KEY_KP_2 = 514;
51     public static final int VTERM_KEY_KP_3 = 515;
52     public static final int VTERM_KEY_KP_4 = 516;
53     public static final int VTERM_KEY_KP_5 = 517;
54     public static final int VTERM_KEY_KP_6 = 518;
55     public static final int VTERM_KEY_KP_7 = 519;
56     public static final int VTERM_KEY_KP_8 = 520;
57     public static final int VTERM_KEY_KP_9 = 521;
58     public static final int VTERM_KEY_KP_MULT = 522;
59     public static final int VTERM_KEY_KP_PLUS = 523;
60     public static final int VTERM_KEY_KP_COMMA = 524;
61     public static final int VTERM_KEY_KP_MINUS = 525;
62     public static final int VTERM_KEY_KP_PERIOD = 526;
63     public static final int VTERM_KEY_KP_DIVIDE = 527;
64     public static final int VTERM_KEY_KP_ENTER = 528;
65     public static final int VTERM_KEY_KP_EQUAL = 529;
66 
67     public static final int VTERM_MOD_NONE = 0x00;
68     public static final int VTERM_MOD_SHIFT = 0x01;
69     public static final int VTERM_MOD_ALT = 0x02;
70     public static final int VTERM_MOD_CTRL = 0x04;
71 
72     private Terminal mTerm;
73 
getModifiers(KeyEvent event)74     public static int getModifiers(KeyEvent event) {
75         int mod = 0;
76         if (event.isCtrlPressed()) {
77             mod |= VTERM_MOD_CTRL;
78         }
79         if (event.isAltPressed()) {
80             mod |= VTERM_MOD_ALT;
81         }
82         if (event.isShiftPressed()) {
83             mod |= VTERM_MOD_SHIFT;
84         }
85         return mod;
86     }
87 
getKey(KeyEvent event)88     public static int getKey(KeyEvent event) {
89         switch(event.getKeyCode()) {
90             case KeyEvent.KEYCODE_ENTER:
91                 return VTERM_KEY_ENTER;
92             case KeyEvent.KEYCODE_TAB:
93                 return VTERM_KEY_TAB;
94             case KeyEvent.KEYCODE_DEL:
95                 return VTERM_KEY_BACKSPACE;
96             case KeyEvent.KEYCODE_ESCAPE:
97                 return VTERM_KEY_ESCAPE;
98             case KeyEvent.KEYCODE_DPAD_UP:
99                 return VTERM_KEY_UP;
100             case KeyEvent.KEYCODE_DPAD_DOWN:
101                 return VTERM_KEY_DOWN;
102             case KeyEvent.KEYCODE_DPAD_LEFT:
103                 return VTERM_KEY_LEFT;
104             case KeyEvent.KEYCODE_DPAD_RIGHT:
105                 return VTERM_KEY_RIGHT;
106             case KeyEvent.KEYCODE_INSERT:
107                 return VTERM_KEY_INS;
108             case KeyEvent.KEYCODE_FORWARD_DEL:
109                 return VTERM_KEY_DEL;
110             case KeyEvent.KEYCODE_MOVE_HOME:
111                 return VTERM_KEY_HOME;
112             case KeyEvent.KEYCODE_MOVE_END:
113                 return VTERM_KEY_END;
114             case KeyEvent.KEYCODE_PAGE_UP:
115                 return VTERM_KEY_PAGEUP;
116             case KeyEvent.KEYCODE_PAGE_DOWN:
117                 return VTERM_KEY_PAGEDOWN;
118             default:
119                 return 0;
120         }
121     }
122 
getKeyName(int key)123     public static String getKeyName(int key) {
124         switch(key) {
125             case VTERM_KEY_ENTER:
126                 return "VTERM_KEY_ENTER";
127             case VTERM_KEY_TAB:
128                 return "VTERM_KEY_TAB";
129             case VTERM_KEY_BACKSPACE:
130                 return "VTERM_KEY_BACKSPACE";
131             case VTERM_KEY_ESCAPE:
132                 return "VTERM_KEY_ESCAPE";
133             case VTERM_KEY_UP:
134                 return "VTERM_KEY_UP";
135             case VTERM_KEY_DOWN:
136                 return "VTERM_KEY_DOWN";
137             case VTERM_KEY_LEFT:
138                 return "VTERM_KEY_LEFT";
139             case VTERM_KEY_RIGHT:
140                 return "VTERM_KEY_RIGHT";
141             case VTERM_KEY_INS:
142                 return "VTERM_KEY_INS";
143             case VTERM_KEY_DEL:
144                 return "VTERM_KEY_DEL";
145             case VTERM_KEY_HOME:
146                 return "VTERM_KEY_HOME";
147             case VTERM_KEY_END:
148                 return "VTERM_KEY_END";
149             case VTERM_KEY_PAGEUP:
150                 return "VTERM_KEY_PAGEUP";
151             case VTERM_KEY_PAGEDOWN:
152                 return "VTERM_KEY_PAGEDOWN";
153             case VTERM_KEY_NONE:
154                 return "VTERM_KEY_NONE";
155             default:
156                 return "UNKNOWN KEY";
157         }
158     }
159 
getCharacter(KeyEvent event)160     public int getCharacter(KeyEvent event) {
161         int c = event.getUnicodeChar();
162         // TODO: Actually support dead keys
163         if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
164             Log.w(TAG, "Received dead key, ignoring");
165             return 0;
166         }
167         return c;
168     }
169 
onKey(View v, int keyCode, KeyEvent event)170     public boolean onKey(View v, int keyCode, KeyEvent event) {
171         if (mTerm == null || event.getAction() == KeyEvent.ACTION_UP) return false;
172 
173         int modifiers = getModifiers(event);
174 
175         int c = getKey(event);
176         if (c != 0) {
177             if (DEBUG) {
178                 Log.d(TAG, "dispatched key event: " +
179                         "mod=" + modifiers + ", " +
180                         "keys=" + getKeyName(c));
181             }
182             return mTerm.dispatchKey(modifiers, c);
183         }
184 
185         c = getCharacter(event);
186         if (c != 0) {
187             if (DEBUG) {
188                 Log.d(TAG, "dispatched key event: " +
189                         "mod=" + modifiers + ", " +
190                         "character='" + new String(Character.toChars(c)) + "'");
191             }
192             return mTerm.dispatchCharacter(modifiers, c);
193         }
194 
195         return false;
196     }
197 
setTerminal(Terminal term)198     public void setTerminal(Terminal term) {
199         mTerm = term;
200     }
201 }
202