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