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
81jfieldID windowID;
82jfieldID drawStateID;
83jfieldID targetID;
84jfieldID graphicsConfigID;
85
86extern jobject currentX11InputMethodInstance;
87extern Boolean awt_x11inputmethod_lookupString(XKeyPressedEvent *, KeySym *);
88Boolean awt_UseType4Patch = False;
89/* how about HEADLESS */
90Boolean awt_ServerDetected = False;
91Boolean awt_XKBDetected = False;
92Boolean awt_IsXsun = False;
93Boolean awt_UseXKB = False;
94
95typedef 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
113KeymapEntry 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
448static Boolean
449keyboardHasKanaLockKey()
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
486static void
487keysymToAWTKeyCode(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
521KeySym
522awt_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 */
554static void
555handleVendorKeySyms(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 */
641static void
642adjustKeySym(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 */
779static Boolean
780isXsunServer(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 */
803static Boolean
804isXKBenabled(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 */
820KeySym
821keycodeToKeysym(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
841static Boolean
842isKPevent(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}
858static void
859dumpKeysymArray(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 */
869static void
870handleKeyEventWithNumLockMask_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 */
904static void
905handleKeyEventWithNumLockMask(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 */
1041jchar
1042keySymToUnicodeCharacter(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
1076void
1077awt_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
1086JNIEXPORT jint JNICALL
1087Java_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
1095JNIEXPORT 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
1102JNIEXPORT 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
1125extern 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 */
1132JNIEXPORT 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 */
1146void 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
1167static 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
1191JNIEXPORT 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
1196static void
1197getWMInsets
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
1217JNIEXPORT 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
1227static void
1228getWindowBounds
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
1239JNIEXPORT 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
1245JNIEXPORT 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
1258JNIEXPORT void JNICALL
1259Java_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
1281JNIEXPORT jint JNICALL
1282Java_sun_awt_X11_XWindow_getKeySymForAWTKeyCode(JNIEnv* env, jclass clazz, jint keycode) {
1283 return awt_getX11KeySym(keycode);
1284}
1285