blob: 05f4682dd0f83dd55e2d77c1badd67c11765c52b [file] [log] [blame]
DRCc5dc0382011-05-13 21:42:14 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
Brian Hinz776c5582013-03-03 16:53:41 +00002 * Copyright (C) 2012-2013 D. R. Commander. All Rights Reserved.
Brian Hinzaccdd952013-03-25 20:58:14 +00003 * Copyright (C) 2013 Brian P. Hinz
Brian Hinz7b7ad802013-12-29 17:33:10 +00004 * Copyright (C) 2013 Pierre Ossman <ossman@cendio.se> for Cendio AB
Brian Hinz776c5582013-03-03 16:53:41 +00005 *
DRCc5dc0382011-05-13 21:42:14 +00006 * This is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
Brian Hinz776c5582013-03-03 16:53:41 +000010 *
DRCc5dc0382011-05-13 21:42:14 +000011 * This software is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Brian Hinz776c5582013-03-03 16:53:41 +000015 *
DRCc5dc0382011-05-13 21:42:14 +000016 * You should have received a copy of the GNU General Public License
17 * along with this software; if not, write to the Free Software
Brian Hinzb213da62012-04-11 22:00:55 +000018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
DRCc5dc0382011-05-13 21:42:14 +000019 * USA.
20 */
21
22//
23// Keysyms - defines X keysyms for non-character keys. All keysyms
24// corresponding to characters should be generated by calling
Brian Hinz2e248ad2013-12-29 16:30:32 +000025// UnicodeToKeysym.ucs2keysym().
DRCc5dc0382011-05-13 21:42:14 +000026//
27
28package com.tigervnc.rfb;
29
Brian Hinz2e248ad2013-12-29 16:30:32 +000030import java.awt.event.KeyEvent;
31import com.tigervnc.vncviewer.VncViewer;
32
DRCc5dc0382011-05-13 21:42:14 +000033public class Keysyms {
34
Brian Hinz2e248ad2013-12-29 16:30:32 +000035 public static final int VoidSymbol = 0xffffff;
36 /*
37 * TTY Functions, cleverly chosen to map to ascii, for convenience of
38 * programming, but could have been arbitrary (at the cost of lookup
39 * tables in client code.
40 */
DRCc5dc0382011-05-13 21:42:14 +000041 public static final int BackSpace = 0xFF08;
42 public static final int Tab = 0xFF09;
43 public static final int Linefeed = 0xFF0A;
44 public static final int Clear = 0xFF0B;
45 public static final int Return = 0xFF0D;
46 public static final int Pause = 0xFF13;
47 public static final int Scroll_Lock = 0xFF14;
48 public static final int Sys_Req = 0xFF15;
49 public static final int Escape = 0xFF1B;
50 public static final int Delete = 0xFFFF;
51
Brian Hinz2e248ad2013-12-29 16:30:32 +000052 /* International & multi-key character composition */
Brian Hinzaccdd952013-03-25 20:58:14 +000053 public static final int Multi_key = 0xFF20; /* Multi-key character compose */
54 public static final int Codeinput = 0xFF37;
55 public static final int SingleCandidate = 0xFF3C;
56 public static final int MultipleCandidate = 0xFF3D;
57 public static final int PreviousCandidate = 0xFF3E;
58
Brian Hinz2e248ad2013-12-29 16:30:32 +000059 /* Japanese keyboard support */
Brian Hinzaccdd952013-03-25 20:58:14 +000060 public static final int Kanji = 0xFF21; /* Kanji, Kanji convert */
61 public static final int Muhenkan = 0xFF22; /* Cancel Conversion */
62 public static final int Henkan_Mode = 0xFF23; /* Start/Stop Conversion */
63 public static final int Henkan = 0xFF23; /* Alias for Henkan_Mode */
64 public static final int Romaji = 0xFF24; /* to Romaji */
65 public static final int Hiragana = 0xFF25; /* to Hiragana */
66 public static final int Katakana = 0xFF26; /* to Katakana */
67 public static final int Hiragana_Katakana = 0xFF27; /* Hiragana/Katakana toggle */
68 public static final int Zenkaku = 0xFF28; /* to Zenkaku */
69 public static final int Hankaku = 0xFF29; /* to Hankaku */
70 public static final int Zenkaku_Hankaku = 0xFF2A; /* Zenkaku/Hankaku toggle */
71 public static final int Touroku = 0xFF2B; /* Add to Dictionary */
72 public static final int Massyo = 0xFF2C; /* Delete from Dictionary */
73 public static final int Kana_Lock = 0xFF2D; /* Kana Lock */
74 public static final int Kana_Shift = 0xFF2E; /* Kana Shift */
75 public static final int Eisu_Shift = 0xFF2F; /* Alphanumeric Shift */
76 public static final int Eisu_toggle = 0xFF30; /* Alphanumeric toggle */
77 public static final int Kanji_Bangou = 0xFF37; /* Codeinput */
78 public static final int Zen_Koho = 0xFF3D; /* Multiple/All Candidate(s) */
79 public static final int Mae_Koho = 0xFF3E; /* Previous Candidate */
80
Brian Hinz2e248ad2013-12-29 16:30:32 +000081 /* Cursor control & motion */
DRCc5dc0382011-05-13 21:42:14 +000082 public static final int Home = 0xFF50;
83 public static final int Left = 0xFF51;
84 public static final int Up = 0xFF52;
85 public static final int Right = 0xFF53;
86 public static final int Down = 0xFF54;
87 public static final int Prior = 0xFF55;
88 public static final int Page_Up = 0xFF55;
89 public static final int Next = 0xFF56;
90 public static final int Page_Down = 0xFF56;
91 public static final int End = 0xFF57;
92 public static final int Begin = 0xFF58;
93
Brian Hinz2e248ad2013-12-29 16:30:32 +000094 /* Misc Functions */
DRCc5dc0382011-05-13 21:42:14 +000095 public static final int Select = 0xFF60;
96 public static final int Print = 0xFF61;
97 public static final int Execute = 0xFF62;
98 public static final int Insert = 0xFF63;
99 public static final int Undo = 0xFF65;
100 public static final int Redo = 0xFF66;
101 public static final int Menu = 0xFF67;
102 public static final int Find = 0xFF68;
103 public static final int Cancel = 0xFF69;
104 public static final int Help = 0xFF6A;
105 public static final int Break = 0xFF6B;
106 public static final int Mode_switch = 0xFF7E;
107 public static final int script_switch = 0xFF7E;
108 public static final int Num_Lock = 0xFF7F;
109
Brian Hinz2e248ad2013-12-29 16:30:32 +0000110 /* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
111 public static final int KP_Enter = 0xFF8D;
112 public static final int KP_Home = 0xFF95;
113 public static final int KP_Left = 0xFF96;
114 public static final int KP_Up = 0xFF97;
115 public static final int KP_Right = 0xFF98;
116 public static final int KP_Down = 0xFF99;
117 public static final int KP_Page_Up = 0xFF9A;
118 public static final int KP_Page_Down = 0xFF9B;
119 public static final int KP_End = 0xFF9C;
120 public static final int KP_Begin = 0xFF9D;
121 public static final int KP_Insert = 0xFF9E;
122 public static final int KP_Delete = 0xFF9F;
123 public static final int KP_Equal = 0xFFBD;
124 public static final int KP_0 = 0xFFB0;
125 public static final int KP_1 = 0xFFB1;
126 public static final int KP_2 = 0xFFB2;
127 public static final int KP_3 = 0xFFB3;
128 public static final int KP_4 = 0xFFB4;
129 public static final int KP_5 = 0xFFB5;
130 public static final int KP_6 = 0xFFB6;
131 public static final int KP_7 = 0xFFB7;
132 public static final int KP_8 = 0xFFB8;
133 public static final int KP_9 = 0xFFB9;
134 public static final int KP_Decimal = 0xFFAE;
135 public static final int KP_Add = 0xFFAB;
136 public static final int KP_Subtract = 0xFFAD;
137 public static final int KP_Multiply = 0xFFAA;
138 public static final int KP_Divide = 0xFFAF;
139
140 /*
141 * Auxilliary Functions; note the duplicate definitions for left and right
142 * function keys; Sun keyboards and a few other manufactures have such
143 * function key groups on the left and/or right sides of the keyboard.
144 * We've not found a keyboard with more than 35 function keys total.
145 */
DRCc5dc0382011-05-13 21:42:14 +0000146 public static final int F1 = 0xFFBE;
147 public static final int F2 = 0xFFBF;
148 public static final int F3 = 0xFFC0;
149 public static final int F4 = 0xFFC1;
150 public static final int F5 = 0xFFC2;
151 public static final int F6 = 0xFFC3;
152 public static final int F7 = 0xFFC4;
153 public static final int F8 = 0xFFC5;
154 public static final int F9 = 0xFFC6;
155 public static final int F10 = 0xFFC7;
156 public static final int F11 = 0xFFC8;
157 public static final int F12 = 0xFFC9;
Brian Hinz776c5582013-03-03 16:53:41 +0000158 public static final int F13 = 0xFFCA;
Brian Hinzaccdd952013-03-25 20:58:14 +0000159 public static final int F14 = 0xFFCB;
160 public static final int F15 = 0xFFCC;
161 public static final int F16 = 0xFFCD;
162 public static final int F17 = 0xFFCE;
163 public static final int F18 = 0xFFCF;
164 public static final int F19 = 0xFFD0;
165 public static final int F20 = 0xFFD1;
166 public static final int F21 = 0xFFD2;
167 public static final int F22 = 0xFFD3;
168 public static final int F23 = 0xFFD4;
169 public static final int F24 = 0xFFD5;
DRCc5dc0382011-05-13 21:42:14 +0000170
Brian Hinz2e248ad2013-12-29 16:30:32 +0000171 /* Modifiers */
DRCc5dc0382011-05-13 21:42:14 +0000172 public static final int Shift_L = 0xFFE1;
173 public static final int Shift_R = 0xFFE2;
174 public static final int Control_L = 0xFFE3;
175 public static final int Control_R = 0xFFE4;
Brian Hinz2e248ad2013-12-29 16:30:32 +0000176 public static final int Caps_Lock = 0xFFE5;
177 public static final int Shift_Lock = 0xFFE6;
178
DRCc5dc0382011-05-13 21:42:14 +0000179 public static final int Meta_L = 0xFFE7;
180 public static final int Meta_R = 0xFFE8;
181 public static final int Alt_L = 0xFFE9;
182 public static final int Alt_R = 0xFFEA;
Brian Hinz776c5582013-03-03 16:53:41 +0000183 public static final int Super_L = 0xFFEB;
Brian Hinz2e248ad2013-12-29 16:30:32 +0000184 public static final int Super_R = 0xFFEC;
185 public static final int Hyper_L = 0xFFED;
186 public static final int Hyper_R = 0xFFEE;
Brian Hinz776c5582013-03-03 16:53:41 +0000187
Brian Hinz2e248ad2013-12-29 16:30:32 +0000188 /*
189 * ISO 9995 Function and Modifier Keys
190 * Byte 3 = 0xFE
191 */
192 public static final int ISO_Level3_Shift = 0xFE03;
193
194 /*
195 * Dead Modifier Keys
196 */
197 public static final int Dead_Grave = 0xfe50; /* COMBINING GRAVE ACCENT */
198 public static final int Dead_Acute = 0xfe51; /* COMBINING ACUTE ACCENT */
199 public static final int Dead_Circumflex = 0xfe52; /* COMBINING CIRCUMFLEX ACCENT */
200 public static final int Dead_Tilde = 0xfe53; /* COMBINING TILDE */
201 public static final int Dead_Macron = 0xfe54; /* COMBINING MACRON */
202 public static final int Dead_Breve = 0xfe55; /* COMBINING BREVE */
203 public static final int Dead_AboveDot = 0xfe56; /* COMBINING DOT ABOVE */
204 public static final int Dead_Diaeresis = 0xfe57; /* COMBINING DIAERESIS */
205 public static final int Dead_AboveRing = 0xfe58; /* COMBINING RING ABOVE */
206 public static final int Dead_DoubleAcute = 0xfe59; /* COMBINING DOUBLE ACUTE ACCENT */
207 public static final int Dead_Caron = 0xfe5a; /* COMBINING CARON */
208 public static final int Dead_Cedilla = 0xfe5b; /* COMBINING CEDILLA */
209 public static final int Dead_Ogonek = 0xfe5c; /* COMBINING OGONEK */
210 public static final int Dead_Iota = 0xfe5d; /* MODIFIER LETTER SMALL IOTA */
211 public static final int Dead_Voiced_Sound = 0xfe5e; /* COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK */
212 public static final int Dead_SemiVoiced_Sound = 0xfe5f; /* COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
213 public static final int Dead_BelowDot = 0xfe60; /* COMBINING DOT BELOW */
214
215 private static class KeySymbol {
216 public KeySymbol(int keycode_, int[] keysym_) {
217 keycode = keycode_;
218 keysym = new int[5];
219 System.arraycopy(keysym_, 0, keysym, 0, 5);
220 }
221 int keycode;
222 int[] keysym;
223 }
224
225 private static KeySymbol[] keySymbols = {
226 /* KEYCODE LOCATION */
227 /* UNKNOWN STANDARD LEFT RIGHT NUMPAD */
228 new KeySymbol(KeyEvent.VK_BACK_SPACE, new int[]{VoidSymbol, BackSpace, VoidSymbol, VoidSymbol, VoidSymbol}),
229 new KeySymbol(KeyEvent.VK_TAB, new int[]{VoidSymbol, Tab, VoidSymbol, VoidSymbol, VoidSymbol}),
230 new KeySymbol(KeyEvent.VK_ENTER, new int[]{VoidSymbol, Return, VoidSymbol, VoidSymbol, KP_Enter}),
231 new KeySymbol(KeyEvent.VK_ESCAPE, new int[]{VoidSymbol, Escape, VoidSymbol, VoidSymbol, VoidSymbol}),
232 new KeySymbol(KeyEvent.VK_CONTROL, new int[]{VoidSymbol, Control_L, Control_L, Control_R, VoidSymbol}),
233 new KeySymbol(KeyEvent.VK_ALT_GRAPH, new int[]{VoidSymbol, ISO_Level3_Shift, VoidSymbol, VoidSymbol, VoidSymbol}),
234 new KeySymbol(KeyEvent.VK_ALT, new int[]{VoidSymbol, ISO_Level3_Shift, Alt_L, Alt_R, VoidSymbol}),
235 new KeySymbol(KeyEvent.VK_SHIFT, new int[]{VoidSymbol, Shift_L, Shift_L, Shift_R, VoidSymbol}),
236 new KeySymbol(KeyEvent.VK_META, new int[]{VoidSymbol, Meta_L, Meta_L, Meta_R, VoidSymbol}),
237 new KeySymbol(KeyEvent.VK_NUMPAD0, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_0}),
238 new KeySymbol(KeyEvent.VK_NUMPAD1, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_1}),
239 new KeySymbol(KeyEvent.VK_NUMPAD2, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_2}),
240 new KeySymbol(KeyEvent.VK_NUMPAD3, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_3}),
241 new KeySymbol(KeyEvent.VK_NUMPAD4, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_4}),
242 new KeySymbol(KeyEvent.VK_NUMPAD5, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_5}),
243 new KeySymbol(KeyEvent.VK_NUMPAD6, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_6}),
244 new KeySymbol(KeyEvent.VK_NUMPAD7, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_7}),
245 new KeySymbol(KeyEvent.VK_NUMPAD8, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_8}),
246 new KeySymbol(KeyEvent.VK_NUMPAD9, new int[]{VoidSymbol, VoidSymbol, VoidSymbol, VoidSymbol, KP_9}),
247 new KeySymbol(KeyEvent.VK_DECIMAL, new int[]{VoidSymbol, KP_Decimal, VoidSymbol, VoidSymbol, KP_Decimal}),
248 new KeySymbol(KeyEvent.VK_ADD, new int[]{VoidSymbol, KP_Add, VoidSymbol, VoidSymbol, KP_Add}),
249 new KeySymbol(KeyEvent.VK_SUBTRACT, new int[]{VoidSymbol, KP_Subtract, VoidSymbol, VoidSymbol, KP_Subtract}),
250 new KeySymbol(KeyEvent.VK_MULTIPLY, new int[]{VoidSymbol, KP_Multiply, VoidSymbol, VoidSymbol, KP_Multiply}),
251 new KeySymbol(KeyEvent.VK_DIVIDE, new int[]{VoidSymbol, KP_Divide, VoidSymbol, VoidSymbol, KP_Divide}),
252 new KeySymbol(KeyEvent.VK_DELETE, new int[]{VoidSymbol, Delete, VoidSymbol, VoidSymbol, KP_Delete}),
253 new KeySymbol(KeyEvent.VK_CLEAR, new int[]{VoidSymbol, Clear, VoidSymbol, VoidSymbol, KP_Begin}),
254 new KeySymbol(KeyEvent.VK_HOME, new int[]{VoidSymbol, Home, VoidSymbol, VoidSymbol, KP_Home}),
255 new KeySymbol(KeyEvent.VK_END, new int[]{VoidSymbol, End, VoidSymbol, VoidSymbol, KP_End}),
256 new KeySymbol(KeyEvent.VK_PAGE_UP, new int[]{VoidSymbol, Page_Up, VoidSymbol, VoidSymbol, KP_Page_Up}),
257 new KeySymbol(KeyEvent.VK_PAGE_DOWN, new int[]{VoidSymbol, Page_Down, VoidSymbol, VoidSymbol, KP_Page_Down}),
258 new KeySymbol(KeyEvent.VK_UP, new int[]{VoidSymbol, Up, VoidSymbol, VoidSymbol, KP_Up}),
259 new KeySymbol(KeyEvent.VK_DOWN, new int[]{VoidSymbol, Down, VoidSymbol, VoidSymbol, KP_Down}),
260 new KeySymbol(KeyEvent.VK_LEFT, new int[]{VoidSymbol, Left, VoidSymbol, VoidSymbol, KP_Left}),
261 new KeySymbol(KeyEvent.VK_RIGHT, new int[]{VoidSymbol, Right, VoidSymbol, VoidSymbol, KP_Right}),
262 new KeySymbol(KeyEvent.VK_BEGIN, new int[]{VoidSymbol, Begin, VoidSymbol, VoidSymbol, KP_Begin}),
263 new KeySymbol(KeyEvent.VK_KP_LEFT, new int[]{VoidSymbol, KP_Left, VoidSymbol, VoidSymbol, KP_Left}),
264 new KeySymbol(KeyEvent.VK_KP_UP, new int[]{VoidSymbol, KP_Up, VoidSymbol, VoidSymbol, KP_Up}),
265 new KeySymbol(KeyEvent.VK_KP_RIGHT, new int[]{VoidSymbol, KP_Right, VoidSymbol, VoidSymbol, KP_Right}),
266 new KeySymbol(KeyEvent.VK_KP_DOWN, new int[]{VoidSymbol, KP_Down, VoidSymbol, VoidSymbol, KP_Down}),
267 new KeySymbol(KeyEvent.VK_PRINTSCREEN, new int[]{VoidSymbol, Print, VoidSymbol, VoidSymbol, VoidSymbol}),
268 new KeySymbol(KeyEvent.VK_SCROLL_LOCK, new int[]{VoidSymbol, Scroll_Lock, VoidSymbol, VoidSymbol, VoidSymbol}),
269 new KeySymbol(KeyEvent.VK_CAPS_LOCK, new int[]{VoidSymbol, Caps_Lock, VoidSymbol, VoidSymbol, VoidSymbol}),
270 new KeySymbol(KeyEvent.VK_NUM_LOCK, new int[]{VoidSymbol, Num_Lock, VoidSymbol, VoidSymbol, Num_Lock}),
271 new KeySymbol(KeyEvent.VK_INSERT, new int[]{VoidSymbol, Insert, VoidSymbol, VoidSymbol, KP_Insert}),
272 new KeySymbol(KeyEvent.VK_AGAIN, new int[]{VoidSymbol, Redo, VoidSymbol, VoidSymbol, VoidSymbol}),
273 new KeySymbol(KeyEvent.VK_UNDO, new int[]{VoidSymbol, Undo, VoidSymbol, VoidSymbol, VoidSymbol}),
274 new KeySymbol(KeyEvent.VK_FIND, new int[]{VoidSymbol, Find, VoidSymbol, VoidSymbol, VoidSymbol}),
275 new KeySymbol(KeyEvent.VK_STOP, new int[]{VoidSymbol, Cancel, VoidSymbol, VoidSymbol, VoidSymbol}),
276 new KeySymbol(KeyEvent.VK_HELP, new int[]{VoidSymbol, Help, VoidSymbol, VoidSymbol, VoidSymbol}),
277 new KeySymbol(KeyEvent.VK_WINDOWS, new int[]{VoidSymbol, Super_L, Super_L, Super_R, VoidSymbol}),
278 new KeySymbol(KeyEvent.VK_CONTEXT_MENU, new int[]{VoidSymbol, Menu, VoidSymbol, VoidSymbol, VoidSymbol}),
279 new KeySymbol(KeyEvent.VK_KANJI, new int[]{VoidSymbol, Kanji, VoidSymbol, VoidSymbol, VoidSymbol}),
280 new KeySymbol(KeyEvent.VK_KATAKANA, new int[]{VoidSymbol, Katakana, VoidSymbol, VoidSymbol, VoidSymbol}),
281 new KeySymbol(KeyEvent.VK_HIRAGANA, new int[]{VoidSymbol, Hiragana, VoidSymbol, VoidSymbol, VoidSymbol}),
282 new KeySymbol(KeyEvent.VK_PREVIOUS_CANDIDATE,
283 new int[]{VoidSymbol, PreviousCandidate,VoidSymbol, VoidSymbol, VoidSymbol}),
284 new KeySymbol(KeyEvent.VK_CODE_INPUT, new int[]{VoidSymbol, Codeinput, VoidSymbol, VoidSymbol, VoidSymbol}),
285 new KeySymbol(KeyEvent.VK_JAPANESE_ROMAN,
286 new int[]{VoidSymbol, Romaji, VoidSymbol, VoidSymbol, VoidSymbol}),
287 new KeySymbol(KeyEvent.VK_KANA_LOCK, new int[]{VoidSymbol, Kana_Lock, VoidSymbol, VoidSymbol, VoidSymbol}),
288 new KeySymbol(KeyEvent.VK_DEAD_ABOVEDOT,new int[]{VoidSymbol, Dead_AboveDot, VoidSymbol, VoidSymbol, VoidSymbol}),
289 new KeySymbol(KeyEvent.VK_DEAD_ABOVERING,
290 new int[]{VoidSymbol, Dead_AboveRing, VoidSymbol, VoidSymbol, VoidSymbol}),
291 new KeySymbol(KeyEvent.VK_DEAD_ACUTE, new int[]{VoidSymbol, Dead_Acute, VoidSymbol, VoidSymbol, VoidSymbol}),
292 new KeySymbol(KeyEvent.VK_DEAD_BREVE, new int[]{VoidSymbol, Dead_Breve, VoidSymbol, VoidSymbol, VoidSymbol}),
293 new KeySymbol(KeyEvent.VK_DEAD_CARON, new int[]{VoidSymbol, Dead_Caron, VoidSymbol, VoidSymbol, VoidSymbol}),
294 new KeySymbol(KeyEvent.VK_DEAD_CIRCUMFLEX,
295 new int[]{VoidSymbol, Dead_Circumflex, VoidSymbol, VoidSymbol, VoidSymbol}),
296 new KeySymbol(KeyEvent.VK_DEAD_DIAERESIS,
297 new int[]{VoidSymbol, Dead_Diaeresis, VoidSymbol, VoidSymbol, VoidSymbol}),
298 new KeySymbol(KeyEvent.VK_DEAD_DOUBLEACUTE,
299 new int[]{VoidSymbol, Dead_DoubleAcute, VoidSymbol, VoidSymbol, VoidSymbol}),
300 new KeySymbol(KeyEvent.VK_DEAD_GRAVE, new int[]{VoidSymbol, Dead_Grave, VoidSymbol, VoidSymbol, VoidSymbol}),
301 new KeySymbol(KeyEvent.VK_DEAD_IOTA, new int[]{VoidSymbol, Dead_Iota, VoidSymbol, VoidSymbol, VoidSymbol}),
302 new KeySymbol(KeyEvent.VK_DEAD_MACRON, new int[]{VoidSymbol, Dead_Macron, VoidSymbol, VoidSymbol, VoidSymbol}),
303 new KeySymbol(KeyEvent.VK_DEAD_OGONEK, new int[]{VoidSymbol, Dead_Ogonek, VoidSymbol, VoidSymbol, VoidSymbol}),
304 new KeySymbol(KeyEvent.VK_DEAD_SEMIVOICED_SOUND,
305 new int[]{VoidSymbol, Dead_SemiVoiced_Sound,VoidSymbol, VoidSymbol, VoidSymbol}),
306 new KeySymbol(KeyEvent.VK_DEAD_TILDE, new int[]{VoidSymbol, Dead_Tilde, VoidSymbol, VoidSymbol, VoidSymbol}),
307 new KeySymbol(KeyEvent.VK_DEAD_VOICED_SOUND,
308 new int[]{VoidSymbol, Dead_Voiced_Sound, VoidSymbol, VoidSymbol, VoidSymbol}),
309 };
310
311 public static int translateKeyEvent(KeyEvent ev) {
312 int location = ev.getKeyLocation();
313 int keyCode = ev.getKeyCode();
314
315 // First check for function keys
316 if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12)
317 return Keysyms.F1 + keyCode - KeyEvent.VK_F1;
318 if (keyCode >= KeyEvent.VK_F13 && keyCode <= KeyEvent.VK_F24)
319 return Keysyms.F13 + keyCode - KeyEvent.VK_F13;
320
321 // Numpad numbers
322 if (keyCode >= KeyEvent.VK_0 && keyCode <= KeyEvent.VK_9 &&
323 location == KeyEvent.KEY_LOCATION_NUMPAD)
324 return Keysyms.KP_0 + keyCode - KeyEvent.VK_0;
325
326 if (VncViewer.os.startsWith("mac os x")) {
327 // Alt on OS X behaves more like AltGr on other systems, and to get
328 // sane behaviour we should translate things in that manner for the
329 // remote VNC server. However that means we lose the ability to use
330 // Alt as a shortcut modifier. Do what RealVNC does and hijack the
331 // left command key as an Alt replacement.
332 switch (keyCode) {
333 case KeyEvent.VK_META:
334 if (location == KeyEvent.KEY_LOCATION_LEFT)
335 return Alt_L;
336 else
337 return Super_L;
338 case KeyEvent.VK_ALT:
339 if (location == KeyEvent.KEY_LOCATION_LEFT)
340 return Alt_L;
341 else
342 return ISO_Level3_Shift;
343 }
344 }
345
346 // Then other special keys
347 if (keyCode == KeyEvent.VK_PAUSE)
348 return (ev.isControlDown() ? Break : Pause);
349 else if (keyCode == KeyEvent.VK_PRINTSCREEN)
350 return (ev.isControlDown() ? Sys_Req : Print);
351 else
352 for(int i = 0; i < keySymbols.length; i++)
353 if (keySymbols[i].keycode == keyCode)
354 return (keySymbols[i].keysym)[location];
355
356 // Unknown special key?
357 if (KeyEvent.getKeyText(keyCode).isEmpty()) {
358 vlog.error("Unknown key code:");
359 String fmt = ev.paramString().replaceAll("%","%%");
360 vlog.error(String.format(fmt.replaceAll(",","%n ")));
361 return VoidSymbol;
362 }
363
364 char keyChar = ev.getKeyChar();
365 if (!ev.isControlDown() && keyChar != KeyEvent.CHAR_UNDEFINED)
366 return UnicodeToKeysym.ucs2keysym(Character.toString(keyChar).codePointAt(0));
367
368 int key = keyChar;
369 if (ev.isControlDown()) {
370 // For CTRL-<letter>, CTRL is sent separately, so just send <letter>.
371 if ((key >= 1 && key <= 26 && !ev.isShiftDown()) ||
372 // CTRL-{, CTRL-|, CTRL-} also map to ASCII 96-127
373 (key >= 27 && key <= 29 && ev.isShiftDown()))
374 key += 96;
375 // For CTRL-SHIFT-<letter>, send capital <letter> to emulate behavior
376 // of Linux. For CTRL-@, send @. For CTRL-_, send _. For CTRL-^,
377 // send ^.
378 else if (key < 32)
379 key += 64;
380 // Windows and Mac sometimes return CHAR_UNDEFINED with CTRL-SHIFT
381 // combinations, so best we can do is send the key code if it is
382 // a valid ASCII symbol.
383 else if (ev.getKeyChar() == KeyEvent.CHAR_UNDEFINED && keyCode >= 0 &&
384 keyCode <= 127)
385 key = keyCode;
386 }
387 return UnicodeToKeysym.ucs2keysym(key);
388 }
389
390 static LogWriter vlog = new LogWriter("Keysyms");
DRCc5dc0382011-05-13 21:42:14 +0000391}