1 | /* |
2 | * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. Oracle designates this |
8 | * particular file as subject to the "Classpath" exception as provided |
9 | * by Oracle in the LICENSE file that accompanied this code. |
10 | * |
11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | * version 2 for more details (a copy is included in the LICENSE file that |
15 | * accompanied this code). |
16 | * |
17 | * You should have received a copy of the GNU General Public License version |
18 | * 2 along with this work; if not, write to the Free Software Foundation, |
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
20 | * |
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 | * or visit www.oracle.com if you need additional information or have any |
23 | * questions. |
24 | */ |
25 | |
26 | /* Note that the contents of this file were taken from canvas.c |
27 | * in the old motif-based AWT. |
28 | */ |
29 | |
30 | #ifdef HEADLESS |
31 | #error This file should not be included in headless library |
32 | #endif |
33 | |
34 | #include <X11/Xlib.h> |
35 | #include <X11/Xutil.h> |
36 | #include <X11/Xos.h> |
37 | #include <X11/Xatom.h> |
38 | #include <ctype.h> |
39 | |
40 | #include <jvm.h> |
41 | #include <jni.h> |
42 | #include <jlong.h> |
43 | #include <jni_util.h> |
44 | |
45 | #include "sun_awt_X11_XWindow.h" |
46 | |
47 | #include "awt_p.h" |
48 | #include "awt_GraphicsEnv.h" |
49 | |
50 | #define XK_KATAKANA |
51 | #include <X11/keysym.h> /* standard X keysyms */ |
52 | #include <X11/DECkeysym.h> /* DEC vendor-specific */ |
53 | #include <X11/Sunkeysym.h> /* Sun vendor-specific */ |
54 | #include <X11/ap_keysym.h> /* Apollo (HP) vendor-specific */ |
55 | /* |
56 | * HPKeysym.h is used not only for the hp keysyms, but also to |
57 | * give us the osf keysyms that are also defined in HPkeysym.h. |
58 | * However, HPkeysym.h is missing a couple of osf keysyms, |
59 | * so I have #defined them below. |
60 | */ |
61 | #include <X11/HPkeysym.h> /* HP vendor-specific */ |
62 | |
63 | #include "java_awt_event_KeyEvent.h" |
64 | #include "java_awt_event_InputEvent.h" |
65 | #include "java_awt_event_MouseEvent.h" |
66 | #include "java_awt_event_MouseWheelEvent.h" |
67 | #include "java_awt_AWTEvent.h" |
68 | |
69 | /* |
70 | * Two osf keys are not defined in standard keysym.h, |
71 | * /Xm/VirtKeys.h, or HPkeysym.h, so I added them below. |
72 | * I found them in /usr/openwin/lib/X11/XKeysymDB |
73 | */ |
74 | #ifndef osfXK_Prior |
75 | #define osfXK_Prior 0x1004FF55 |
76 | #endif |
77 | #ifndef osfXK_Next |
78 | #define osfXK_Next 0x1004FF56 |
79 | #endif |
80 | |
81 | jfieldID windowID; |
82 | jfieldID drawStateID; |
83 | jfieldID targetID; |
84 | jfieldID graphicsConfigID; |
85 | |
86 | extern jobject currentX11InputMethodInstance; |
87 | extern Boolean awt_x11inputmethod_lookupString(XKeyPressedEvent *, KeySym *); |
88 | Boolean awt_UseType4Patch = False; |
89 | /* how about HEADLESS */ |
90 | Boolean awt_ServerDetected = False; |
91 | Boolean awt_XKBDetected = False; |
92 | Boolean awt_IsXsun = False; |
93 | Boolean awt_UseXKB = False; |
94 | |
95 | typedef struct KEYMAP_ENTRY { |
96 | jint awtKey; |
97 | KeySym x11Key; |
98 | Boolean mapsToUnicodeChar; |
99 | jint keyLocation; |
100 | } KeymapEntry; |
101 | |
102 | /* NB: XK_R? keysyms are for Type 4 keyboards. |
103 | * The corresponding XK_F? keysyms are for Type 5 |
104 | * |
105 | * Note: this table must be kept in sorted order, since it is traversed |
106 | * according to both Java keycode and X keysym. There are a number of |
107 | * keycodes that map to more than one corresponding keysym, and we need |
108 | * to choose the right one. Unfortunately, there are some keysyms that |
109 | * can map to more than one keycode, depending on what kind of keyboard |
110 | * is in use (e.g. F11 and F12). |
111 | */ |
112 | |
113 | KeymapEntry keymapTable[] = |
114 | { |
115 | {java_awt_event_KeyEvent_VK_A, XK_a, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
116 | {java_awt_event_KeyEvent_VK_B, XK_b, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
117 | {java_awt_event_KeyEvent_VK_C, XK_c, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
118 | {java_awt_event_KeyEvent_VK_D, XK_d, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
119 | {java_awt_event_KeyEvent_VK_E, XK_e, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
120 | {java_awt_event_KeyEvent_VK_F, XK_f, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
121 | {java_awt_event_KeyEvent_VK_G, XK_g, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
122 | {java_awt_event_KeyEvent_VK_H, XK_h, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
123 | {java_awt_event_KeyEvent_VK_I, XK_i, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
124 | {java_awt_event_KeyEvent_VK_J, XK_j, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
125 | {java_awt_event_KeyEvent_VK_K, XK_k, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
126 | {java_awt_event_KeyEvent_VK_L, XK_l, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
127 | {java_awt_event_KeyEvent_VK_M, XK_m, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
128 | {java_awt_event_KeyEvent_VK_N, XK_n, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
129 | {java_awt_event_KeyEvent_VK_O, XK_o, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
130 | {java_awt_event_KeyEvent_VK_P, XK_p, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
131 | {java_awt_event_KeyEvent_VK_Q, XK_q, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
132 | {java_awt_event_KeyEvent_VK_R, XK_r, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
133 | {java_awt_event_KeyEvent_VK_S, XK_s, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
134 | {java_awt_event_KeyEvent_VK_T, XK_t, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
135 | {java_awt_event_KeyEvent_VK_U, XK_u, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
136 | {java_awt_event_KeyEvent_VK_V, XK_v, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
137 | {java_awt_event_KeyEvent_VK_W, XK_w, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
138 | {java_awt_event_KeyEvent_VK_X, XK_x, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
139 | {java_awt_event_KeyEvent_VK_Y, XK_y, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
140 | {java_awt_event_KeyEvent_VK_Z, XK_z, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
141 | |
142 | /* TTY Function keys */ |
143 | {java_awt_event_KeyEvent_VK_BACK_SPACE, XK_BackSpace, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
144 | {java_awt_event_KeyEvent_VK_TAB, XK_Tab, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
145 | {java_awt_event_KeyEvent_VK_TAB, XK_ISO_Left_Tab, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
146 | {java_awt_event_KeyEvent_VK_CLEAR, XK_Clear, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
147 | {java_awt_event_KeyEvent_VK_ENTER, XK_Return, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
148 | {java_awt_event_KeyEvent_VK_ENTER, XK_Linefeed, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
149 | {java_awt_event_KeyEvent_VK_PAUSE, XK_Pause, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
150 | {java_awt_event_KeyEvent_VK_PAUSE, XK_F21, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
151 | {java_awt_event_KeyEvent_VK_PAUSE, XK_R1, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
152 | {java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_Scroll_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
153 | {java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_F23, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
154 | {java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_R3, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
155 | {java_awt_event_KeyEvent_VK_ESCAPE, XK_Escape, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
156 | |
157 | /* Other vendor-specific versions of TTY Function keys */ |
158 | {java_awt_event_KeyEvent_VK_BACK_SPACE, osfXK_BackSpace, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
159 | {java_awt_event_KeyEvent_VK_CLEAR, osfXK_Clear, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
160 | {java_awt_event_KeyEvent_VK_ESCAPE, osfXK_Escape, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
161 | |
162 | /* Modifier keys */ |
163 | {java_awt_event_KeyEvent_VK_SHIFT, XK_Shift_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT}, |
164 | {java_awt_event_KeyEvent_VK_SHIFT, XK_Shift_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT}, |
165 | {java_awt_event_KeyEvent_VK_CONTROL, XK_Control_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT}, |
166 | {java_awt_event_KeyEvent_VK_CONTROL, XK_Control_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT}, |
167 | {java_awt_event_KeyEvent_VK_ALT, XK_Alt_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT}, |
168 | {java_awt_event_KeyEvent_VK_ALT, XK_Alt_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT}, |
169 | {java_awt_event_KeyEvent_VK_META, XK_Meta_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT}, |
170 | {java_awt_event_KeyEvent_VK_META, XK_Meta_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT}, |
171 | {java_awt_event_KeyEvent_VK_CAPS_LOCK, XK_Caps_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
172 | {java_awt_event_KeyEvent_VK_CAPS_LOCK, XK_Shift_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
173 | |
174 | /* Misc Functions */ |
175 | {java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_Print, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
176 | {java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_F22, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
177 | {java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_R2, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
178 | {java_awt_event_KeyEvent_VK_CANCEL, XK_Cancel, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
179 | {java_awt_event_KeyEvent_VK_HELP, XK_Help, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
180 | {java_awt_event_KeyEvent_VK_NUM_LOCK, XK_Num_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
181 | |
182 | /* Other vendor-specific versions of Misc Functions */ |
183 | {java_awt_event_KeyEvent_VK_CANCEL, osfXK_Cancel, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
184 | {java_awt_event_KeyEvent_VK_HELP, osfXK_Help, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
185 | |
186 | /* Rectangular Navigation Block */ |
187 | {java_awt_event_KeyEvent_VK_HOME, XK_Home, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
188 | {java_awt_event_KeyEvent_VK_HOME, XK_R7, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
189 | {java_awt_event_KeyEvent_VK_PAGE_UP, XK_Page_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
190 | {java_awt_event_KeyEvent_VK_PAGE_UP, XK_Prior, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
191 | {java_awt_event_KeyEvent_VK_PAGE_UP, XK_R9, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
192 | {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_Page_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
193 | {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_Next, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
194 | {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_R15, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
195 | {java_awt_event_KeyEvent_VK_END, XK_End, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
196 | {java_awt_event_KeyEvent_VK_END, XK_R13, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
197 | {java_awt_event_KeyEvent_VK_INSERT, XK_Insert, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
198 | {java_awt_event_KeyEvent_VK_DELETE, XK_Delete, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
199 | |
200 | /* Keypad equivalents of Rectangular Navigation Block */ |
201 | {java_awt_event_KeyEvent_VK_HOME, XK_KP_Home, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
202 | {java_awt_event_KeyEvent_VK_PAGE_UP, XK_KP_Page_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
203 | {java_awt_event_KeyEvent_VK_PAGE_UP, XK_KP_Prior, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
204 | {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_KP_Page_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
205 | {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_KP_Next, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
206 | {java_awt_event_KeyEvent_VK_END, XK_KP_End, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
207 | {java_awt_event_KeyEvent_VK_INSERT, XK_KP_Insert, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
208 | {java_awt_event_KeyEvent_VK_DELETE, XK_KP_Delete, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
209 | |
210 | /* Other vendor-specific Rectangular Navigation Block */ |
211 | {java_awt_event_KeyEvent_VK_PAGE_UP, osfXK_PageUp, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
212 | {java_awt_event_KeyEvent_VK_PAGE_UP, osfXK_Prior, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
213 | {java_awt_event_KeyEvent_VK_PAGE_DOWN, osfXK_PageDown, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
214 | {java_awt_event_KeyEvent_VK_PAGE_DOWN, osfXK_Next, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
215 | {java_awt_event_KeyEvent_VK_END, osfXK_EndLine, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
216 | {java_awt_event_KeyEvent_VK_INSERT, osfXK_Insert, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
217 | {java_awt_event_KeyEvent_VK_DELETE, osfXK_Delete, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
218 | |
219 | /* Triangular Navigation Block */ |
220 | {java_awt_event_KeyEvent_VK_LEFT, XK_Left, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
221 | {java_awt_event_KeyEvent_VK_UP, XK_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
222 | {java_awt_event_KeyEvent_VK_RIGHT, XK_Right, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
223 | {java_awt_event_KeyEvent_VK_DOWN, XK_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
224 | |
225 | /* Keypad equivalents of Triangular Navigation Block */ |
226 | {java_awt_event_KeyEvent_VK_KP_LEFT, XK_KP_Left, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
227 | {java_awt_event_KeyEvent_VK_KP_UP, XK_KP_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
228 | {java_awt_event_KeyEvent_VK_KP_RIGHT, XK_KP_Right, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
229 | {java_awt_event_KeyEvent_VK_KP_DOWN, XK_KP_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
230 | |
231 | /* Other vendor-specific Triangular Navigation Block */ |
232 | {java_awt_event_KeyEvent_VK_LEFT, osfXK_Left, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
233 | {java_awt_event_KeyEvent_VK_UP, osfXK_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
234 | {java_awt_event_KeyEvent_VK_RIGHT, osfXK_Right, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
235 | {java_awt_event_KeyEvent_VK_DOWN, osfXK_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
236 | |
237 | /* Remaining Cursor control & motion */ |
238 | {java_awt_event_KeyEvent_VK_BEGIN, XK_Begin, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
239 | {java_awt_event_KeyEvent_VK_BEGIN, XK_KP_Begin, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
240 | |
241 | {java_awt_event_KeyEvent_VK_0, XK_0, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
242 | {java_awt_event_KeyEvent_VK_1, XK_1, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
243 | {java_awt_event_KeyEvent_VK_2, XK_2, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
244 | {java_awt_event_KeyEvent_VK_3, XK_3, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
245 | {java_awt_event_KeyEvent_VK_4, XK_4, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
246 | {java_awt_event_KeyEvent_VK_5, XK_5, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
247 | {java_awt_event_KeyEvent_VK_6, XK_6, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
248 | {java_awt_event_KeyEvent_VK_7, XK_7, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
249 | {java_awt_event_KeyEvent_VK_8, XK_8, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
250 | {java_awt_event_KeyEvent_VK_9, XK_9, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
251 | |
252 | {java_awt_event_KeyEvent_VK_SPACE, XK_space, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
253 | {java_awt_event_KeyEvent_VK_EXCLAMATION_MARK, XK_exclam, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
254 | {java_awt_event_KeyEvent_VK_QUOTEDBL, XK_quotedbl, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
255 | {java_awt_event_KeyEvent_VK_NUMBER_SIGN, XK_numbersign, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
256 | {java_awt_event_KeyEvent_VK_DOLLAR, XK_dollar, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
257 | {java_awt_event_KeyEvent_VK_AMPERSAND, XK_ampersand, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
258 | {java_awt_event_KeyEvent_VK_QUOTE, XK_apostrophe, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
259 | {java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS, XK_parenleft, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
260 | {java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS, XK_parenright, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
261 | {java_awt_event_KeyEvent_VK_ASTERISK, XK_asterisk, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
262 | {java_awt_event_KeyEvent_VK_PLUS, XK_plus, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
263 | {java_awt_event_KeyEvent_VK_COMMA, XK_comma, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
264 | {java_awt_event_KeyEvent_VK_MINUS, XK_minus, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
265 | {java_awt_event_KeyEvent_VK_PERIOD, XK_period, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
266 | {java_awt_event_KeyEvent_VK_SLASH, XK_slash, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
267 | |
268 | {java_awt_event_KeyEvent_VK_COLON, XK_colon, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
269 | {java_awt_event_KeyEvent_VK_SEMICOLON, XK_semicolon, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
270 | {java_awt_event_KeyEvent_VK_LESS, XK_less, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
271 | {java_awt_event_KeyEvent_VK_EQUALS, XK_equal, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
272 | {java_awt_event_KeyEvent_VK_GREATER, XK_greater, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
273 | |
274 | {java_awt_event_KeyEvent_VK_AT, XK_at, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
275 | |
276 | {java_awt_event_KeyEvent_VK_OPEN_BRACKET, XK_bracketleft, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
277 | {java_awt_event_KeyEvent_VK_BACK_SLASH, XK_backslash, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
278 | {java_awt_event_KeyEvent_VK_CLOSE_BRACKET, XK_bracketright, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
279 | {java_awt_event_KeyEvent_VK_CIRCUMFLEX, XK_asciicircum, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
280 | {java_awt_event_KeyEvent_VK_UNDERSCORE, XK_underscore, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
281 | {java_awt_event_KeyEvent_VK_BACK_QUOTE, XK_grave, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
282 | |
283 | {java_awt_event_KeyEvent_VK_BRACELEFT, XK_braceleft, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
284 | {java_awt_event_KeyEvent_VK_BRACERIGHT, XK_braceright, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
285 | |
286 | {java_awt_event_KeyEvent_VK_INVERTED_EXCLAMATION_MARK, XK_exclamdown, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
287 | |
288 | /* Remaining Numeric Keypad Keys */ |
289 | {java_awt_event_KeyEvent_VK_NUMPAD0, XK_KP_0, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
290 | {java_awt_event_KeyEvent_VK_NUMPAD1, XK_KP_1, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
291 | {java_awt_event_KeyEvent_VK_NUMPAD2, XK_KP_2, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
292 | {java_awt_event_KeyEvent_VK_NUMPAD3, XK_KP_3, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
293 | {java_awt_event_KeyEvent_VK_NUMPAD4, XK_KP_4, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
294 | {java_awt_event_KeyEvent_VK_NUMPAD5, XK_KP_5, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
295 | {java_awt_event_KeyEvent_VK_NUMPAD6, XK_KP_6, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
296 | {java_awt_event_KeyEvent_VK_NUMPAD7, XK_KP_7, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
297 | {java_awt_event_KeyEvent_VK_NUMPAD8, XK_KP_8, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
298 | {java_awt_event_KeyEvent_VK_NUMPAD9, XK_KP_9, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
299 | {java_awt_event_KeyEvent_VK_SPACE, XK_KP_Space, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
300 | {java_awt_event_KeyEvent_VK_TAB, XK_KP_Tab, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
301 | {java_awt_event_KeyEvent_VK_ENTER, XK_KP_Enter, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
302 | {java_awt_event_KeyEvent_VK_EQUALS, XK_KP_Equal, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
303 | {java_awt_event_KeyEvent_VK_EQUALS, XK_R4, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
304 | {java_awt_event_KeyEvent_VK_MULTIPLY, XK_KP_Multiply, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
305 | {java_awt_event_KeyEvent_VK_MULTIPLY, XK_F26, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
306 | {java_awt_event_KeyEvent_VK_MULTIPLY, XK_R6, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
307 | {java_awt_event_KeyEvent_VK_ADD, XK_KP_Add, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
308 | {java_awt_event_KeyEvent_VK_SEPARATOR, XK_KP_Separator, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
309 | {java_awt_event_KeyEvent_VK_SUBTRACT, XK_KP_Subtract, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
310 | {java_awt_event_KeyEvent_VK_SUBTRACT, XK_F24, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
311 | {java_awt_event_KeyEvent_VK_DECIMAL, XK_KP_Decimal, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
312 | {java_awt_event_KeyEvent_VK_DIVIDE, XK_KP_Divide, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
313 | {java_awt_event_KeyEvent_VK_DIVIDE, XK_F25, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
314 | {java_awt_event_KeyEvent_VK_DIVIDE, XK_R5, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD}, |
315 | |
316 | /* Function Keys */ |
317 | {java_awt_event_KeyEvent_VK_F1, XK_F1, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
318 | {java_awt_event_KeyEvent_VK_F2, XK_F2, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
319 | {java_awt_event_KeyEvent_VK_F3, XK_F3, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
320 | {java_awt_event_KeyEvent_VK_F4, XK_F4, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
321 | {java_awt_event_KeyEvent_VK_F5, XK_F5, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
322 | {java_awt_event_KeyEvent_VK_F6, XK_F6, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
323 | {java_awt_event_KeyEvent_VK_F7, XK_F7, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
324 | {java_awt_event_KeyEvent_VK_F8, XK_F8, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
325 | {java_awt_event_KeyEvent_VK_F9, XK_F9, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
326 | {java_awt_event_KeyEvent_VK_F10, XK_F10, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
327 | {java_awt_event_KeyEvent_VK_F11, XK_F11, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
328 | {java_awt_event_KeyEvent_VK_F12, XK_F12, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
329 | |
330 | /* Sun vendor-specific version of F11 and F12 */ |
331 | {java_awt_event_KeyEvent_VK_F11, SunXK_F36, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
332 | {java_awt_event_KeyEvent_VK_F12, SunXK_F37, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
333 | |
334 | /* X11 keysym names for input method related keys don't always |
335 | * match keytop engravings or Java virtual key names, so here we |
336 | * only map constants that we've found on real keyboards. |
337 | */ |
338 | /* Type 5c Japanese keyboard: kakutei */ |
339 | {java_awt_event_KeyEvent_VK_ACCEPT, XK_Execute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
340 | /* Type 5c Japanese keyboard: henkan */ |
341 | {java_awt_event_KeyEvent_VK_CONVERT, XK_Kanji, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
342 | /* Type 5c Japanese keyboard: nihongo */ |
343 | {java_awt_event_KeyEvent_VK_INPUT_METHOD_ON_OFF, XK_Henkan_Mode, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
344 | /* VK_KANA_LOCK is handled separately because it generates the |
345 | * same keysym as ALT_GRAPH in spite of its different behavior. |
346 | */ |
347 | |
348 | {java_awt_event_KeyEvent_VK_ALL_CANDIDATES, XK_Zen_Koho, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
349 | {java_awt_event_KeyEvent_VK_ALPHANUMERIC, XK_Eisu_Shift, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
350 | {java_awt_event_KeyEvent_VK_ALPHANUMERIC, XK_Eisu_toggle, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
351 | {java_awt_event_KeyEvent_VK_CODE_INPUT, XK_Kanji_Bangou, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
352 | {java_awt_event_KeyEvent_VK_FULL_WIDTH, XK_Zenkaku, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
353 | {java_awt_event_KeyEvent_VK_HALF_WIDTH, XK_Hankaku, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
354 | {java_awt_event_KeyEvent_VK_HIRAGANA, XK_Hiragana, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
355 | {java_awt_event_KeyEvent_VK_JAPANESE_HIRAGANA, XK_Hiragana, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
356 | {java_awt_event_KeyEvent_VK_KATAKANA, XK_Katakana, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
357 | {java_awt_event_KeyEvent_VK_JAPANESE_KATAKANA, XK_Katakana, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
358 | {java_awt_event_KeyEvent_VK_JAPANESE_ROMAN, XK_Romaji, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
359 | {java_awt_event_KeyEvent_VK_KANA, XK_Kana_Shift, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
360 | {java_awt_event_KeyEvent_VK_KANA_LOCK, XK_Kana_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
361 | {java_awt_event_KeyEvent_VK_KANJI, XK_Kanji, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
362 | {java_awt_event_KeyEvent_VK_NONCONVERT, XK_Muhenkan, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
363 | {java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE, XK_Mae_Koho, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
364 | {java_awt_event_KeyEvent_VK_ROMAN_CHARACTERS, XK_Romaji, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
365 | |
366 | {java_awt_event_KeyEvent_VK_COMPOSE, XK_Multi_key, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
367 | {java_awt_event_KeyEvent_VK_ALT_GRAPH, XK_ISO_Level3_Shift, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
368 | |
369 | /* Editing block */ |
370 | {java_awt_event_KeyEvent_VK_AGAIN, XK_Redo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
371 | {java_awt_event_KeyEvent_VK_AGAIN, XK_L2, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
372 | {java_awt_event_KeyEvent_VK_UNDO, XK_Undo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
373 | {java_awt_event_KeyEvent_VK_UNDO, XK_L4, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
374 | {java_awt_event_KeyEvent_VK_COPY, XK_L6, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
375 | {java_awt_event_KeyEvent_VK_PASTE, XK_L8, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
376 | {java_awt_event_KeyEvent_VK_CUT, XK_L10, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
377 | {java_awt_event_KeyEvent_VK_FIND, XK_Find, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
378 | {java_awt_event_KeyEvent_VK_FIND, XK_L9, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
379 | {java_awt_event_KeyEvent_VK_PROPS, XK_L3, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
380 | {java_awt_event_KeyEvent_VK_STOP, XK_L1, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
381 | |
382 | /* Sun vendor-specific versions for editing block */ |
383 | {java_awt_event_KeyEvent_VK_AGAIN, SunXK_Again, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
384 | {java_awt_event_KeyEvent_VK_UNDO, SunXK_Undo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
385 | {java_awt_event_KeyEvent_VK_COPY, SunXK_Copy, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
386 | {java_awt_event_KeyEvent_VK_PASTE, SunXK_Paste, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
387 | {java_awt_event_KeyEvent_VK_CUT, SunXK_Cut, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
388 | {java_awt_event_KeyEvent_VK_FIND, SunXK_Find, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
389 | {java_awt_event_KeyEvent_VK_PROPS, SunXK_Props, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
390 | {java_awt_event_KeyEvent_VK_STOP, SunXK_Stop, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
391 | |
392 | /* Apollo (HP) vendor-specific versions for editing block */ |
393 | {java_awt_event_KeyEvent_VK_COPY, apXK_Copy, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
394 | {java_awt_event_KeyEvent_VK_CUT, apXK_Cut, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
395 | {java_awt_event_KeyEvent_VK_PASTE, apXK_Paste, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
396 | |
397 | /* Other vendor-specific versions for editing block */ |
398 | {java_awt_event_KeyEvent_VK_COPY, osfXK_Copy, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
399 | {java_awt_event_KeyEvent_VK_CUT, osfXK_Cut, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
400 | {java_awt_event_KeyEvent_VK_PASTE, osfXK_Paste, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
401 | {java_awt_event_KeyEvent_VK_UNDO, osfXK_Undo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
402 | |
403 | /* Dead key mappings (for European keyboards) */ |
404 | {java_awt_event_KeyEvent_VK_DEAD_GRAVE, XK_dead_grave, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
405 | {java_awt_event_KeyEvent_VK_DEAD_ACUTE, XK_dead_acute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
406 | {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, XK_dead_circumflex, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
407 | {java_awt_event_KeyEvent_VK_DEAD_TILDE, XK_dead_tilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
408 | {java_awt_event_KeyEvent_VK_DEAD_MACRON, XK_dead_macron, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
409 | {java_awt_event_KeyEvent_VK_DEAD_BREVE, XK_dead_breve, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
410 | {java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT, XK_dead_abovedot, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
411 | {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, XK_dead_diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
412 | {java_awt_event_KeyEvent_VK_DEAD_ABOVERING, XK_dead_abovering, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
413 | {java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE, XK_dead_doubleacute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
414 | {java_awt_event_KeyEvent_VK_DEAD_CARON, XK_dead_caron, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
415 | {java_awt_event_KeyEvent_VK_DEAD_CEDILLA, XK_dead_cedilla, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
416 | {java_awt_event_KeyEvent_VK_DEAD_OGONEK, XK_dead_ogonek, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
417 | {java_awt_event_KeyEvent_VK_DEAD_IOTA, XK_dead_iota, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
418 | {java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND, XK_dead_voiced_sound, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
419 | {java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND, XK_dead_semivoiced_sound, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
420 | |
421 | /* Sun vendor-specific dead key mappings (for European keyboards) */ |
422 | {java_awt_event_KeyEvent_VK_DEAD_GRAVE, SunXK_FA_Grave, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
423 | {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, SunXK_FA_Circum, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
424 | {java_awt_event_KeyEvent_VK_DEAD_TILDE, SunXK_FA_Tilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
425 | {java_awt_event_KeyEvent_VK_DEAD_ACUTE, SunXK_FA_Acute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
426 | {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, SunXK_FA_Diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
427 | {java_awt_event_KeyEvent_VK_DEAD_CEDILLA, SunXK_FA_Cedilla, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
428 | |
429 | /* DEC vendor-specific dead key mappings (for European keyboards) */ |
430 | {java_awt_event_KeyEvent_VK_DEAD_ABOVERING, DXK_ring_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
431 | {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, DXK_circumflex_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
432 | {java_awt_event_KeyEvent_VK_DEAD_CEDILLA, DXK_cedilla_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
433 | {java_awt_event_KeyEvent_VK_DEAD_ACUTE, DXK_acute_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
434 | {java_awt_event_KeyEvent_VK_DEAD_GRAVE, DXK_grave_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
435 | {java_awt_event_KeyEvent_VK_DEAD_TILDE, DXK_tilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
436 | {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, DXK_diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
437 | |
438 | /* Other vendor-specific dead key mappings (for European keyboards) */ |
439 | {java_awt_event_KeyEvent_VK_DEAD_ACUTE, hpXK_mute_acute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
440 | {java_awt_event_KeyEvent_VK_DEAD_GRAVE, hpXK_mute_grave, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
441 | {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, hpXK_mute_asciicircum, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
442 | {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, hpXK_mute_diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
443 | {java_awt_event_KeyEvent_VK_DEAD_TILDE, hpXK_mute_asciitilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD}, |
444 | |
445 | {java_awt_event_KeyEvent_VK_UNDEFINED, NoSymbol, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN} |
446 | }; |
447 | |
448 | static Boolean |
449 | keyboardHasKanaLockKey() |
450 | { |
451 | static Boolean haveResult = FALSE; |
452 | static Boolean result = FALSE; |
453 | |
454 | int32_t minKeyCode, maxKeyCode, keySymsPerKeyCode; |
455 | KeySym *keySyms, *keySymsStart, keySym; |
456 | int32_t i; |
457 | int32_t kanaCount = 0; |
458 | |
459 | // Solaris doesn't let you swap keyboards without rebooting, |
460 | // so there's no need to check for the kana lock key more than once. |
461 | if (haveResult) { |
462 | return result; |
463 | } |
464 | |
465 | // There's no direct way to determine whether the keyboard has |
466 | // a kana lock key. From available keyboard mapping tables, it looks |
467 | // like only keyboards with the kana lock key can produce keysyms |
468 | // for kana characters. So, as an indirect test, we check for those. |
469 | XDisplayKeycodes(awt_display, &minKeyCode, &maxKeyCode); |
470 | keySyms = XGetKeyboardMapping(awt_display, minKeyCode, maxKeyCode - minKeyCode + 1, &keySymsPerKeyCode); |
471 | keySymsStart = keySyms; |
472 | for (i = 0; i < (maxKeyCode - minKeyCode + 1) * keySymsPerKeyCode; i++) { |
473 | keySym = *keySyms++; |
474 | if ((keySym & 0xff00) == 0x0400) { |
475 | kanaCount++; |
476 | } |
477 | } |
478 | XFree(keySymsStart); |
479 | |
480 | // use a (somewhat arbitrary) minimum so we don't get confused by a stray function key |
481 | result = kanaCount > 10; |
482 | haveResult = TRUE; |
483 | return result; |
484 | } |
485 | |
486 | static void |
487 | keysymToAWTKeyCode(KeySym x11Key, jint *keycode, Boolean *mapsToUnicodeChar, |
488 | jint *keyLocation) |
489 | { |
490 | int32_t i; |
491 | |
492 | // Solaris uses XK_Mode_switch for both the non-locking AltGraph |
493 | // and the locking Kana key, but we want to keep them separate for |
494 | // KeyEvent. |
495 | if (x11Key == XK_Mode_switch && keyboardHasKanaLockKey()) { |
496 | *keycode = java_awt_event_KeyEvent_VK_KANA_LOCK; |
497 | *mapsToUnicodeChar = FALSE; |
498 | *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; |
499 | return; |
500 | } |
501 | |
502 | for (i = 0; |
503 | keymapTable[i].awtKey != java_awt_event_KeyEvent_VK_UNDEFINED; |
504 | i++) |
505 | { |
506 | if (keymapTable[i].x11Key == x11Key) { |
507 | *keycode = keymapTable[i].awtKey; |
508 | *mapsToUnicodeChar = keymapTable[i].mapsToUnicodeChar; |
509 | *keyLocation = keymapTable[i].keyLocation; |
510 | return; |
511 | } |
512 | } |
513 | |
514 | *keycode = java_awt_event_KeyEvent_VK_UNDEFINED; |
515 | *mapsToUnicodeChar = FALSE; |
516 | *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; |
517 | |
518 | DTRACE_PRINTLN1("keysymToAWTKeyCode: no key mapping found: keysym = 0x%x" , x11Key); |
519 | } |
520 | |
521 | KeySym |
522 | awt_getX11KeySym(jint awtKey) |
523 | { |
524 | int32_t i; |
525 | |
526 | if (awtKey == java_awt_event_KeyEvent_VK_KANA_LOCK && keyboardHasKanaLockKey()) { |
527 | return XK_Mode_switch; |
528 | } |
529 | |
530 | for (i = 0; keymapTable[i].awtKey != 0; i++) { |
531 | if (keymapTable[i].awtKey == awtKey) { |
532 | return keymapTable[i].x11Key; |
533 | } |
534 | } |
535 | |
536 | DTRACE_PRINTLN1("awt_getX11KeySym: no key mapping found: awtKey = 0x%x" , awtKey); |
537 | return NoSymbol; |
538 | } |
539 | |
540 | /* Called from handleKeyEvent. The purpose of this function is |
541 | * to check for a list of vendor-specific keysyms, most of which |
542 | * have values greater than 0xFFFF. Most of these keys don't map |
543 | * to unicode characters, but some do. |
544 | * |
545 | * For keys that don't map to unicode characters, the keysym |
546 | * is irrelevant at this point. We set the keysym to zero |
547 | * to ensure that the switch statement immediately below |
548 | * this function call (in adjustKeySym) won't incorrectly act |
549 | * on them after the high bits are stripped off. |
550 | * |
551 | * For keys that do map to unicode characters, we change the keysym |
552 | * to the equivalent that is < 0xFFFF |
553 | */ |
554 | static void |
555 | handleVendorKeySyms(XEvent *event, KeySym *keysym) |
556 | { |
557 | KeySym originalKeysym = *keysym; |
558 | |
559 | switch (*keysym) { |
560 | /* Apollo (HP) vendor-specific from <X11/ap_keysym.h> */ |
561 | case apXK_Copy: |
562 | case apXK_Cut: |
563 | case apXK_Paste: |
564 | /* DEC vendor-specific from <X11/DECkeysym.h> */ |
565 | case DXK_ring_accent: /* syn usldead_ring */ |
566 | case DXK_circumflex_accent: |
567 | case DXK_cedilla_accent: /* syn usldead_cedilla */ |
568 | case DXK_acute_accent: |
569 | case DXK_grave_accent: |
570 | case DXK_tilde: |
571 | case DXK_diaeresis: |
572 | /* Sun vendor-specific from <X11/Sunkeysym.h> */ |
573 | case SunXK_FA_Grave: |
574 | case SunXK_FA_Circum: |
575 | case SunXK_FA_Tilde: |
576 | case SunXK_FA_Acute: |
577 | case SunXK_FA_Diaeresis: |
578 | case SunXK_FA_Cedilla: |
579 | case SunXK_F36: /* Labeled F11 */ |
580 | case SunXK_F37: /* Labeled F12 */ |
581 | case SunXK_Props: |
582 | case SunXK_Copy: |
583 | case SunXK_Open: |
584 | case SunXK_Paste: |
585 | case SunXK_Cut: |
586 | /* Other vendor-specific from HPkeysym.h */ |
587 | case hpXK_mute_acute: /* syn usldead_acute */ |
588 | case hpXK_mute_grave: /* syn usldead_grave */ |
589 | case hpXK_mute_asciicircum: /* syn usldead_asciicircum */ |
590 | case hpXK_mute_diaeresis: /* syn usldead_diaeresis */ |
591 | case hpXK_mute_asciitilde: /* syn usldead_asciitilde */ |
592 | case osfXK_Copy: |
593 | case osfXK_Cut: |
594 | case osfXK_Paste: |
595 | case osfXK_PageUp: |
596 | case osfXK_PageDown: |
597 | case osfXK_EndLine: |
598 | case osfXK_Clear: |
599 | case osfXK_Left: |
600 | case osfXK_Up: |
601 | case osfXK_Right: |
602 | case osfXK_Down: |
603 | case osfXK_Prior: |
604 | case osfXK_Next: |
605 | case osfXK_Insert: |
606 | case osfXK_Undo: |
607 | case osfXK_Help: |
608 | *keysym = 0; |
609 | break; |
610 | /* |
611 | * The rest DO map to unicode characters, so translate them |
612 | */ |
613 | case osfXK_BackSpace: |
614 | *keysym = XK_BackSpace; |
615 | break; |
616 | case osfXK_Escape: |
617 | *keysym = XK_Escape; |
618 | break; |
619 | case osfXK_Cancel: |
620 | *keysym = XK_Cancel; |
621 | break; |
622 | case osfXK_Delete: |
623 | *keysym = XK_Delete; |
624 | break; |
625 | default: |
626 | break; |
627 | } |
628 | |
629 | if (originalKeysym != *keysym) { |
630 | DTRACE_PRINTLN3("%s originalKeysym=0x%x, keysym=0x%x" , |
631 | "In handleVendorKeySyms:" , originalKeysym, *keysym); |
632 | } |
633 | } |
634 | |
635 | /* Called from handleKeyEvent. |
636 | * The purpose of this function is to adjust the keysym and XEvent |
637 | * keycode for a key event. This is basically a conglomeration of |
638 | * bugfixes that require these adjustments. |
639 | * Note that none of the keysyms in this function are less than 256. |
640 | */ |
641 | static void |
642 | adjustKeySym(XEvent *event, KeySym *keysym) |
643 | { |
644 | KeySym originalKeysym = *keysym; |
645 | KeyCode originalKeycode = event->xkey.keycode; |
646 | |
647 | /* We have seen bits set in the high two bytes on Linux, |
648 | * which prevents this switch statement from executing |
649 | * correctly. Strip off the high order bits. |
650 | */ |
651 | *keysym &= 0x0000FFFF; |
652 | |
653 | switch (*keysym) { |
654 | case XK_ISO_Left_Tab: /* shift-tab on Linux */ |
655 | *keysym = XK_Tab; |
656 | break; |
657 | case XK_KP_Decimal: |
658 | *keysym = '.'; |
659 | break; |
660 | case XK_KP_Add: |
661 | *keysym = '+'; |
662 | break; |
663 | case XK_F24: /* NumLock off */ |
664 | case XK_KP_Subtract: /* NumLock on */ |
665 | *keysym = '-'; |
666 | break; |
667 | case XK_F25: /* NumLock off */ |
668 | case XK_KP_Divide: /* NumLock on */ |
669 | *keysym = '/'; |
670 | break; |
671 | case XK_F26: /* NumLock off */ |
672 | case XK_KP_Multiply: /* NumLock on */ |
673 | *keysym = '*'; |
674 | break; |
675 | case XK_KP_Equal: |
676 | *keysym = '='; |
677 | break; |
678 | case XK_KP_0: |
679 | *keysym = '0'; |
680 | break; |
681 | case XK_KP_1: |
682 | *keysym = '1'; |
683 | break; |
684 | case XK_KP_2: |
685 | *keysym = '2'; |
686 | break; |
687 | case XK_KP_3: |
688 | *keysym = '3'; |
689 | break; |
690 | case XK_KP_4: |
691 | *keysym = '4'; |
692 | break; |
693 | case XK_KP_5: |
694 | *keysym = '5'; |
695 | break; |
696 | case XK_KP_6: |
697 | *keysym = '6'; |
698 | break; |
699 | case XK_KP_7: |
700 | *keysym = '7'; |
701 | break; |
702 | case XK_KP_8: |
703 | *keysym = '8'; |
704 | break; |
705 | case XK_KP_9: |
706 | *keysym = '9'; |
707 | break; |
708 | case XK_KP_Left: /* Bug 4350175 */ |
709 | *keysym = XK_Left; |
710 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
711 | break; |
712 | case XK_KP_Up: |
713 | *keysym = XK_Up; |
714 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
715 | break; |
716 | case XK_KP_Right: |
717 | *keysym = XK_Right; |
718 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
719 | break; |
720 | case XK_KP_Down: |
721 | *keysym = XK_Down; |
722 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
723 | break; |
724 | case XK_KP_Home: |
725 | *keysym = XK_Home; |
726 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
727 | break; |
728 | case XK_KP_End: |
729 | *keysym = XK_End; |
730 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
731 | break; |
732 | case XK_KP_Page_Up: |
733 | *keysym = XK_Page_Up; |
734 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
735 | break; |
736 | case XK_KP_Page_Down: |
737 | *keysym = XK_Page_Down; |
738 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
739 | break; |
740 | case XK_KP_Begin: |
741 | *keysym = XK_Begin; |
742 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
743 | break; |
744 | case XK_KP_Insert: |
745 | *keysym = XK_Insert; |
746 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
747 | break; |
748 | case XK_KP_Delete: |
749 | *keysym = XK_Delete; |
750 | event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym); |
751 | break; |
752 | case XK_KP_Enter: |
753 | *keysym = XK_Linefeed; |
754 | event->xkey.keycode = XKeysymToKeycode(awt_display, XK_Return); |
755 | break; |
756 | default: |
757 | break; |
758 | } |
759 | |
760 | if (originalKeysym != *keysym) { |
761 | DTRACE_PRINTLN2("In adjustKeySym: originalKeysym=0x%x, keysym=0x%x" , |
762 | originalKeysym, *keysym); |
763 | } |
764 | if (originalKeycode != event->xkey.keycode) { |
765 | DTRACE_PRINTLN2("In adjustKeySym: originalKeycode=0x%x, keycode=0x%x" , |
766 | originalKeycode, event->xkey.keycode); |
767 | } |
768 | } |
769 | |
770 | /* |
771 | * What a sniffer sez? |
772 | * Xsun and Xorg if NumLock is on do two thing different: |
773 | * keep Keypad key in different places of keysyms array and |
774 | * ignore/obey "ModLock is ShiftLock", so we should choose. |
775 | * People say, it's right to use behavior and not Vendor tags to decide. |
776 | * Maybe. But why these tags were invented, then? |
777 | * TODO: use behavior, not tags. Maybe. |
778 | */ |
779 | static Boolean |
780 | isXsunServer(XEvent *event) { |
781 | if( awt_ServerDetected ) return awt_IsXsun; |
782 | if( (strncmp( ServerVendor( event->xkey.display ), "Sun Microsystems, Inc." , 22) != 0) && |
783 | (strncmp( ServerVendor( event->xkey.display ), "Oracle Corporation" , 18) != 0) ) |
784 | { |
785 | awt_ServerDetected = True; |
786 | awt_IsXsun = False; |
787 | return False; |
788 | } |
789 | // Now, it's Sun. It still may be Xorg though, eg on Solaris 10, x86. |
790 | // Today (2005), VendorRelease of Xorg is a Big Number unlike Xsun. |
791 | if( VendorRelease( event->xkey.display ) > 10000 ) { |
792 | awt_ServerDetected = True; |
793 | awt_IsXsun = False; |
794 | return False; |
795 | } |
796 | awt_ServerDetected = True; |
797 | awt_IsXsun = True; |
798 | return True; |
799 | } |
800 | /* |
801 | * +kb or -kb ? |
802 | */ |
803 | static Boolean |
804 | isXKBenabled(Display *display) { |
805 | int mop, beve, berr; |
806 | if( !awt_XKBDetected ) { |
807 | /* |
808 | * NB: TODO: hope it will return False if XkbIgnoreExtension was called! |
809 | */ |
810 | awt_UseXKB = XQueryExtension(display, "XKEYBOARD" , &mop, &beve, &berr); |
811 | awt_XKBDetected = True; |
812 | } |
813 | return awt_UseXKB; |
814 | } |
815 | |
816 | /* |
817 | * Map a keycode to the corresponding keysym. |
818 | * This replaces the deprecated X11 function XKeycodeToKeysym |
819 | */ |
820 | KeySym |
821 | keycodeToKeysym(Display *display, KeyCode keycode, int index) { |
822 | static int min_kc = -1; |
823 | static int max_kc; |
824 | if (min_kc == -1) { |
825 | (void) XDisplayKeycodes(display, &min_kc, &max_kc); |
826 | } |
827 | if (keycode < min_kc || keycode > max_kc || index < 0) { |
828 | return NoSymbol; |
829 | } |
830 | int num_syms; |
831 | KeySym *key_syms = XGetKeyboardMapping(display, keycode, 1, &num_syms); |
832 | if (index >= num_syms) { |
833 | XFree(key_syms); |
834 | return NoSymbol; |
835 | } |
836 | KeySym ks = key_syms[index]; |
837 | XFree(key_syms); |
838 | return ks; |
839 | } |
840 | |
841 | static Boolean |
842 | isKPevent(XEvent *event) |
843 | { |
844 | /* |
845 | * Xlib manual, ch 12.7 says, as a first rule for choice of keysym: |
846 | * The numlock modifier is on and the second KeySym is a keypad KeySym. In this case, |
847 | * if the Shift modifier is on, or if the Lock modifier is on and is interpreted as ShiftLock, |
848 | * then the first KeySym is used, otherwise the second KeySym is used. |
849 | * |
850 | * However, Xsun server does ignore ShiftLock and always takes 3-rd element from an array. |
851 | * |
852 | * So, is it a keypad keysym? |
853 | */ |
854 | Boolean bsun = isXsunServer( event ); |
855 | Boolean bxkb = isXKBenabled( event->xkey.display ); |
856 | return IsKeypadKey( keycodeToKeysym(event->xkey.display, event->xkey.keycode,(bsun && !bxkb ? 2 : 1) ) ); |
857 | } |
858 | static void |
859 | dumpKeysymArray(XEvent *event) { |
860 | printf(" 0x%lX\n" , (unsigned long)keycodeToKeysym(event->xkey.display, event->xkey.keycode, 0)); |
861 | printf(" 0x%lX\n" , (unsigned long)keycodeToKeysym(event->xkey.display, event->xkey.keycode, 1)); |
862 | printf(" 0x%lX\n" , (unsigned long)keycodeToKeysym(event->xkey.display, event->xkey.keycode, 2)); |
863 | printf(" 0x%lX\n" , (unsigned long)keycodeToKeysym(event->xkey.display, event->xkey.keycode, 3)); |
864 | } |
865 | /* |
866 | * In a next redesign, get rid of this code altogether. |
867 | * |
868 | */ |
869 | static void |
870 | handleKeyEventWithNumLockMask_New(XEvent *event, KeySym *keysym) |
871 | { |
872 | KeySym originalKeysym = *keysym; |
873 | if( !isKPevent( event ) ) { |
874 | return; |
875 | } |
876 | if( isXsunServer( event ) && !awt_UseXKB) { |
877 | if( (event->xkey.state & ShiftMask) ) { // shift modifier is on |
878 | *keysym = keycodeToKeysym(event->xkey.display, |
879 | event->xkey.keycode, 3); |
880 | }else { |
881 | *keysym = keycodeToKeysym(event->xkey.display, |
882 | event->xkey.keycode, 2); |
883 | } |
884 | } else { |
885 | if( (event->xkey.state & ShiftMask) || // shift modifier is on |
886 | ((event->xkey.state & LockMask) && // lock modifier is on |
887 | (awt_ModLockIsShiftLock)) ) { // it is interpreted as ShiftLock |
888 | *keysym = keycodeToKeysym(event->xkey.display, |
889 | event->xkey.keycode, 0); |
890 | }else{ |
891 | *keysym = keycodeToKeysym(event->xkey.display, |
892 | event->xkey.keycode, 1); |
893 | } |
894 | } |
895 | } |
896 | |
897 | /* Called from handleKeyEvent. |
898 | * The purpose of this function is to make some adjustments to keysyms |
899 | * that have been found to be necessary when the NumLock mask is set. |
900 | * They come from various bug fixes and rearchitectures. |
901 | * This function is meant to be called when |
902 | * (event->xkey.state & awt_NumLockMask) is TRUE. |
903 | */ |
904 | static void |
905 | handleKeyEventWithNumLockMask(XEvent *event, KeySym *keysym) |
906 | { |
907 | KeySym originalKeysym = *keysym; |
908 | |
909 | #if !defined(__linux__) && !defined(MACOSX) |
910 | /* The following code on Linux will cause the keypad keys |
911 | * not to echo on JTextField when the NumLock is on. The |
912 | * keysyms will be 0, because the last parameter 2 is not defined. |
913 | * See Xlib Programming Manual, O'Reilly & Associates, Section |
914 | * 9.1.5 "Other Keyboard-handling Routines", "The meaning of |
915 | * the keysym list beyond the first two (unmodified, Shift or |
916 | * Shift Lock) is not defined." |
917 | */ |
918 | |
919 | /* Translate again with NumLock as modifier. */ |
920 | /* ECH - I wonder why we think that NumLock corresponds to 2? |
921 | On Linux, we've seen xmodmap -pm yield mod2 as NumLock, |
922 | but I don't know that it will be for every configuration. |
923 | Perhaps using the index (modn in awt_MToolkit.c:setup_modifier_map) |
924 | would be more correct. |
925 | */ |
926 | *keysym = keycodeToKeysym(event->xkey.display, |
927 | event->xkey.keycode, 2); |
928 | if (originalKeysym != *keysym) { |
929 | DTRACE_PRINTLN3("%s originalKeysym=0x%x, keysym=0x%x" , |
930 | "In handleKeyEventWithNumLockMask ifndef linux:" , |
931 | originalKeysym, *keysym); |
932 | } |
933 | #endif |
934 | |
935 | /* Note: the XK_R? key assignments are for Type 4 kbds */ |
936 | switch (*keysym) { |
937 | case XK_R13: |
938 | *keysym = XK_KP_1; |
939 | break; |
940 | case XK_R14: |
941 | *keysym = XK_KP_2; |
942 | break; |
943 | case XK_R15: |
944 | *keysym = XK_KP_3; |
945 | break; |
946 | case XK_R10: |
947 | *keysym = XK_KP_4; |
948 | break; |
949 | case XK_R11: |
950 | *keysym = XK_KP_5; |
951 | break; |
952 | case XK_R12: |
953 | *keysym = XK_KP_6; |
954 | break; |
955 | case XK_R7: |
956 | *keysym = XK_KP_7; |
957 | break; |
958 | case XK_R8: |
959 | *keysym = XK_KP_8; |
960 | break; |
961 | case XK_R9: |
962 | *keysym = XK_KP_9; |
963 | break; |
964 | case XK_KP_Insert: |
965 | *keysym = XK_KP_0; |
966 | break; |
967 | case XK_KP_Delete: |
968 | *keysym = XK_KP_Decimal; |
969 | break; |
970 | case XK_R4: |
971 | *keysym = XK_KP_Equal; /* Type 4 kbd */ |
972 | break; |
973 | case XK_R5: |
974 | *keysym = XK_KP_Divide; |
975 | break; |
976 | case XK_R6: |
977 | *keysym = XK_KP_Multiply; |
978 | break; |
979 | /* |
980 | * Need the following keysym changes for Linux key releases. |
981 | * Sometimes the modifier state gets messed up, so we get a |
982 | * KP_Left when we should get a KP_4, for example. |
983 | * XK_KP_Insert and XK_KP_Delete were already handled above. |
984 | */ |
985 | case XK_KP_Left: |
986 | *keysym = XK_KP_4; |
987 | break; |
988 | case XK_KP_Up: |
989 | *keysym = XK_KP_8; |
990 | break; |
991 | case XK_KP_Right: |
992 | *keysym = XK_KP_6; |
993 | break; |
994 | case XK_KP_Down: |
995 | *keysym = XK_KP_2; |
996 | break; |
997 | case XK_KP_Home: |
998 | *keysym = XK_KP_7; |
999 | break; |
1000 | case XK_KP_End: |
1001 | *keysym = XK_KP_1; |
1002 | break; |
1003 | case XK_KP_Page_Up: |
1004 | *keysym = XK_KP_9; |
1005 | break; |
1006 | case XK_KP_Page_Down: |
1007 | *keysym = XK_KP_3; |
1008 | break; |
1009 | case XK_KP_Begin: |
1010 | *keysym = XK_KP_5; |
1011 | break; |
1012 | default: |
1013 | break; |
1014 | } |
1015 | |
1016 | if (originalKeysym != *keysym) { |
1017 | DTRACE_PRINTLN3("%s originalKeysym=0x%x, keysym=0x%x" , |
1018 | "In handleKeyEventWithNumLockMask:" , originalKeysym, *keysym); |
1019 | } |
1020 | } |
1021 | |
1022 | /* This function is called as the keyChar parameter of a call to |
1023 | * awt_post_java_key_event. It depends on being called after adjustKeySym. |
1024 | * |
1025 | * This function just handles a few values where we know that the |
1026 | * keysym is not the same as the unicode value. For values that |
1027 | * we don't handle explicitly, we just cast the keysym to a jchar. |
1028 | * Most of the real mapping work that gets the correct keysym is handled |
1029 | * in the mapping table, adjustKeySym, etc. |
1030 | * |
1031 | * XXX |
1032 | * Maybe we should enumerate the keysyms for which we have a mapping |
1033 | * in the keyMap, but that don't map to unicode chars, and return |
1034 | * CHAR_UNDEFINED? Then use the buffer value from XLookupString |
1035 | * instead of the keysym as the keychar when posting. Then we don't |
1036 | * need to test using mapsToUnicodeChar. That way, we would post keyTyped |
1037 | * for all the chars that generate unicode chars, including LATIN2-4, etc. |
1038 | * Note: what does the buffer from XLookupString contain when |
1039 | * the character is a non-printable unicode character like Cancel or Delete? |
1040 | */ |
1041 | jchar |
1042 | keySymToUnicodeCharacter(KeySym keysym) { |
1043 | jchar unicodeValue = (jchar) keysym; |
1044 | |
1045 | switch (keysym) { |
1046 | case XK_BackSpace: |
1047 | case XK_Tab: |
1048 | case XK_Linefeed: |
1049 | case XK_Escape: |
1050 | case XK_Delete: |
1051 | /* Strip off highorder bits defined in xkeysymdef.h |
1052 | * I think doing this converts them to values that |
1053 | * we can cast to jchars and use as java keychars. |
1054 | */ |
1055 | unicodeValue = (jchar) (keysym & 0x007F); |
1056 | break; |
1057 | case XK_Return: |
1058 | unicodeValue = (jchar) 0x000a; /* the unicode char for Linefeed */ |
1059 | break; |
1060 | case XK_Cancel: |
1061 | unicodeValue = (jchar) 0x0018; /* the unicode char for Cancel */ |
1062 | break; |
1063 | default: |
1064 | break; |
1065 | } |
1066 | |
1067 | if (unicodeValue != (jchar)keysym) { |
1068 | DTRACE_PRINTLN3("%s originalKeysym=0x%x, keysym=0x%x" , |
1069 | "In keysymToUnicode:" , keysym, unicodeValue); |
1070 | } |
1071 | |
1072 | return unicodeValue; |
1073 | } |
1074 | |
1075 | |
1076 | void |
1077 | awt_post_java_key_event(JNIEnv *env, jobject peer, jint id, |
1078 | jlong when, jint keyCode, jchar keyChar, jint keyLocation, jint state, XEvent * event) |
1079 | { |
1080 | JNU_CallMethodByName(env, NULL, peer, "postKeyEvent" , "(IJICIIJI)V" , id, |
1081 | when, keyCode, keyChar, keyLocation, state, ptr_to_jlong(event), (jint)sizeof(XEvent)); |
1082 | } /* awt_post_java_key_event() */ |
1083 | |
1084 | |
1085 | |
1086 | JNIEXPORT jint JNICALL |
1087 | Java_sun_awt_X11_XWindow_getAWTKeyCodeForKeySym(JNIEnv *env, jclass clazz, jint keysym) { |
1088 | jint keycode = java_awt_event_KeyEvent_VK_UNDEFINED; |
1089 | Boolean mapsToUnicodeChar; |
1090 | jint keyLocation; |
1091 | keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation); |
1092 | return keycode; |
1093 | } |
1094 | |
1095 | JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XWindow_haveCurrentX11InputMethodInstance |
1096 | (JNIEnv *env, jobject object) { |
1097 | /*printf("Java_sun_awt_X11_XWindow_haveCurrentX11InputMethodInstance: %s\n", (currentX11InputMethodInstance==NULL? "NULL":" notnull")); |
1098 | */ |
1099 | return currentX11InputMethodInstance != NULL ? JNI_TRUE : JNI_FALSE; |
1100 | } |
1101 | |
1102 | JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XWindow_x11inputMethodLookupString |
1103 | (JNIEnv *env, jobject object, jlong event, jlongArray keysymArray) { |
1104 | KeySym keysym = NoSymbol; |
1105 | Boolean boo; |
1106 | /* keysymArray (and testbuf[]) have dimension 2 because we put there two |
1107 | * perhaps different values of keysyms. |
1108 | * XXX: not anymore at the moment, but I'll still keep them as arrays |
1109 | * for a while. If in the course of testing we will be satisfied with |
1110 | * a current single result from awt_x11inputmethod_lookupString, we'll |
1111 | * change this. |
1112 | */ |
1113 | jlong testbuf[2]; |
1114 | |
1115 | testbuf[1]=0; |
1116 | |
1117 | boo = awt_x11inputmethod_lookupString((XKeyPressedEvent*)jlong_to_ptr(event), &keysym); |
1118 | testbuf[0] = keysym; |
1119 | |
1120 | (*env)->SetLongArrayRegion(env, keysymArray, 0, 2, (jlong *)(testbuf)); |
1121 | return boo ? JNI_TRUE : JNI_FALSE; |
1122 | } |
1123 | |
1124 | |
1125 | extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs; |
1126 | |
1127 | /* |
1128 | * Class: Java_sun_awt_X11_XWindow_getNativeColor |
1129 | * Method: getNativeColor |
1130 | * Signature (Ljava/awt/Color;Ljava/awt/GraphicsConfiguration;)I |
1131 | */ |
1132 | JNIEXPORT jint JNICALL Java_sun_awt_X11_XWindow_getNativeColor |
1133 | (JNIEnv *env, jobject this, jobject color, jobject gc_object) { |
1134 | AwtGraphicsConfigDataPtr adata; |
1135 | /* fire warning because JNU_GetLongFieldAsPtr casts jlong to (void *) */ |
1136 | adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, gc_object, x11GraphicsConfigIDs.aData); |
1137 | return awtJNI_GetColorForVis(env, color, adata); |
1138 | } |
1139 | |
1140 | /* syncTopLevelPos() is necessary to insure that the window manager has in |
1141 | * fact moved us to our final position relative to the reParented WM window. |
1142 | * We have noted a timing window which our shell has not been moved so we |
1143 | * screw up the insets thinking they are 0,0. Wait (for a limited period of |
1144 | * time to let the WM hava a chance to move us |
1145 | */ |
1146 | void syncTopLevelPos( Display *d, Window w, XWindowAttributes *winAttr ) { |
1147 | int32_t i = 0; |
1148 | do { |
1149 | XGetWindowAttributes( d, w, winAttr ); |
1150 | /* Sometimes we get here before the WM has updated the |
1151 | ** window data struct with the correct position. Loop |
1152 | ** until we get a non-zero position. |
1153 | */ |
1154 | if ((winAttr->x != 0) || (winAttr->y != 0)) { |
1155 | break; |
1156 | } |
1157 | else { |
1158 | /* What we really want here is to sync with the WM, |
1159 | ** but there's no explicit way to do this, so we |
1160 | ** call XSync for a delay. |
1161 | */ |
1162 | XSync(d, False); |
1163 | } |
1164 | } while (i++ < 50); |
1165 | } |
1166 | |
1167 | static Window getTopWindow(Window win, Window *rootWin) |
1168 | { |
1169 | Window root=None, current_window=win, parent=None, *ignore_children=NULL; |
1170 | Window prev_window=None; |
1171 | unsigned int ignore_uint=0; |
1172 | Status status = 0; |
1173 | |
1174 | if (win == None) return None; |
1175 | do { |
1176 | status = XQueryTree(awt_display, |
1177 | current_window, |
1178 | &root, |
1179 | &parent, |
1180 | &ignore_children, |
1181 | &ignore_uint); |
1182 | XFree(ignore_children); |
1183 | if (status == 0) return None; |
1184 | prev_window = current_window; |
1185 | current_window = parent; |
1186 | } while (parent != root); |
1187 | *rootWin = root; |
1188 | return prev_window; |
1189 | } |
1190 | |
1191 | JNIEXPORT jlong JNICALL Java_sun_awt_X11_XWindow_getTopWindow |
1192 | (JNIEnv *env, jclass clazz, jlong win, jlong rootWin) { |
1193 | return getTopWindow((Window) win, (Window*) jlong_to_ptr(rootWin)); |
1194 | } |
1195 | |
1196 | static void |
1197 | getWMInsets |
1198 | (Window window, int *left, int *top, int *right, int *bottom, int *border) { |
1199 | // window is event->xreparent.window |
1200 | Window topWin = None, rootWin = None, containerWindow = None; |
1201 | XWindowAttributes winAttr, topAttr; |
1202 | int screenX, screenY; |
1203 | topWin = getTopWindow(window, &rootWin); |
1204 | syncTopLevelPos(awt_display, topWin, &topAttr); |
1205 | // (screenX, screenY) is (0,0) of the reparented window |
1206 | // converted to screen coordinates. |
1207 | XTranslateCoordinates(awt_display, window, rootWin, |
1208 | 0,0, &screenX, &screenY, &containerWindow); |
1209 | *left = screenX - topAttr.x - topAttr.border_width; |
1210 | *top = screenY - topAttr.y - topAttr.border_width; |
1211 | XGetWindowAttributes(awt_display, window, &winAttr); |
1212 | *right = topAttr.width - ((winAttr.width) + *left); |
1213 | *bottom = topAttr.height - ((winAttr.height) + *top); |
1214 | *border = topAttr.border_width; |
1215 | } |
1216 | |
1217 | JNIEXPORT void JNICALL Java_sun_awt_X11_XWindow_getWMInsets |
1218 | (JNIEnv *env, jclass clazz, jlong window, jlong left, jlong top, jlong right, jlong bottom, jlong border) { |
1219 | getWMInsets((Window) window, |
1220 | (int*) jlong_to_ptr(left), |
1221 | (int*) jlong_to_ptr(top), |
1222 | (int*) jlong_to_ptr(right), |
1223 | (int*) jlong_to_ptr(bottom), |
1224 | (int*) jlong_to_ptr(border)); |
1225 | } |
1226 | |
1227 | static void |
1228 | getWindowBounds |
1229 | (Window window, int *x, int *y, int *width, int *height) { |
1230 | XWindowAttributes winAttr; |
1231 | XSync(awt_display, False); |
1232 | XGetWindowAttributes(awt_display, window, &winAttr); |
1233 | *x = winAttr.x; |
1234 | *y = winAttr.y; |
1235 | *width = winAttr.width; |
1236 | *height = winAttr.height; |
1237 | } |
1238 | |
1239 | JNIEXPORT void JNICALL Java_sun_awt_X11_XWindow_getWindowBounds |
1240 | (JNIEnv *env, jclass clazz, jlong window, jlong x, jlong y, jlong width, jlong height) { |
1241 | getWindowBounds((Window) window, (int*) jlong_to_ptr(x), (int*) jlong_to_ptr(y), |
1242 | (int*) jlong_to_ptr(width), (int*) jlong_to_ptr(height)); |
1243 | } |
1244 | |
1245 | JNIEXPORT void JNICALL Java_sun_awt_X11_XWindow_setSizeHints |
1246 | (JNIEnv *env, jclass clazz, jlong window, jlong x, jlong y, jlong width, jlong height) { |
1247 | XSizeHints *size_hints = XAllocSizeHints(); |
1248 | size_hints->flags = USPosition | PPosition | PSize; |
1249 | size_hints->x = (int)x; |
1250 | size_hints->y = (int)y; |
1251 | size_hints->width = (int)width; |
1252 | size_hints->height = (int)height; |
1253 | XSetWMNormalHints(awt_display, (Window)window, size_hints); |
1254 | XFree((char*)size_hints); |
1255 | } |
1256 | |
1257 | |
1258 | JNIEXPORT void JNICALL |
1259 | Java_sun_awt_X11_XWindow_initIDs |
1260 | (JNIEnv *env, jclass clazz) |
1261 | { |
1262 | char *ptr = NULL; |
1263 | windowID = (*env)->GetFieldID(env, clazz, "window" , "J" ); |
1264 | CHECK_NULL(windowID); |
1265 | targetID = (*env)->GetFieldID(env, clazz, "target" , "Ljava/awt/Component;" ); |
1266 | CHECK_NULL(targetID); |
1267 | graphicsConfigID = (*env)->GetFieldID(env, clazz, "graphicsConfig" , "Lsun/awt/X11GraphicsConfig;" ); |
1268 | CHECK_NULL(graphicsConfigID); |
1269 | drawStateID = (*env)->GetFieldID(env, clazz, "drawState" , "I" ); |
1270 | CHECK_NULL(drawStateID); |
1271 | ptr = getenv("_AWT_USE_TYPE4_PATCH" ); |
1272 | if( ptr != NULL && ptr[0] != 0 ) { |
1273 | if( strncmp("true" , ptr, 4) == 0 ) { |
1274 | awt_UseType4Patch = True; |
1275 | }else if( strncmp("false" , ptr, 5) == 0 ) { |
1276 | awt_UseType4Patch = False; |
1277 | } |
1278 | } |
1279 | } |
1280 | |
1281 | JNIEXPORT jint JNICALL |
1282 | Java_sun_awt_X11_XWindow_getKeySymForAWTKeyCode(JNIEnv* env, jclass clazz, jint keycode) { |
1283 | return awt_getX11KeySym(keycode); |
1284 | } |
1285 | |