1 /*
2  * Copyright (c) 2002, 2014, 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 
87 jfieldID windowID;
88 jfieldID drawStateID;
89 jfieldID targetID;
90 jfieldID graphicsConfigID;
91 
92 extern jobject currentX11InputMethodInstance;
93 extern Boolean awt_x11inputmethod_lookupString(XKeyPressedEvent *, KeySym *);
94 Boolean awt_UseType4Patch = False;
95 /* how about HEADLESS */
96 Boolean awt_ServerDetected = False;
97 Boolean awt_XKBDetected = False;
98 Boolean awt_IsXsun = False;
99 Boolean awt_UseXKB = False;
100 
101 typedef 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 
119 KeymapEntry 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_Mode_switch, 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 
454 static Boolean
keyboardHasKanaLockKey()455 keyboardHasKanaLockKey()
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 
492 static void
keysymToAWTKeyCode(KeySym x11Key,jint * keycode,Boolean * mapsToUnicodeChar,jint * keyLocation)493 keysymToAWTKeyCode(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 
527 KeySym
awt_getX11KeySym(jint awtKey)528 awt_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  */
560 static void
handleVendorKeySyms(XEvent * event,KeySym * keysym)561 handleVendorKeySyms(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  */
647 static void
adjustKeySym(XEvent * event,KeySym * keysym)648 adjustKeySym(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  */
785 static Boolean
isXsunServer(XEvent * event)786 isXsunServer(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  */
809 static Boolean
isXKBenabled(Display * display)810 isXKBenabled(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 static Boolean
isKPevent(XEvent * event)822 isKPevent(XEvent *event)
823 {
824     /*
825      *  Xlib manual, ch 12.7 says, as a first rule for choice of keysym:
826      *  The numlock modifier is on and the second KeySym is a keypad KeySym. In this case,
827      *  if the Shift modifier is on, or if the Lock modifier is on and is interpreted as ShiftLock,
828      *  then the first KeySym is used, otherwise the second KeySym is used.
829      *
830      *  However, Xsun server does ignore ShiftLock and always takes 3-rd element from an array.
831      *
832      *  So, is it a keypad keysym?
833      */
834     Boolean bsun = isXsunServer( event );
835     Boolean bxkb = isXKBenabled( event->xkey.display );
836     return IsKeypadKey( XKeycodeToKeysym(event->xkey.display, event->xkey.keycode,(bsun && !bxkb ? 2 : 1) ) );
837 }
838 static void
dumpKeysymArray(XEvent * event)839 dumpKeysymArray(XEvent *event) {
840     printf("    0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 0));
841     printf("    0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 1));
842     printf("    0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 2));
843     printf("    0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 3));
844 }
845 /*
846  * In a next redesign, get rid of this code altogether.
847  *
848  */
849 static void
handleKeyEventWithNumLockMask_New(XEvent * event,KeySym * keysym)850 handleKeyEventWithNumLockMask_New(XEvent *event, KeySym *keysym)
851 {
852     KeySym originalKeysym = *keysym;
853     if( !isKPevent( event ) ) {
854         return;
855     }
856     if( isXsunServer( event ) && !awt_UseXKB) {
857         if( (event->xkey.state & ShiftMask) ) { // shift modifier is on
858             *keysym = XKeycodeToKeysym(event->xkey.display,
859                                    event->xkey.keycode, 3);
860          }else {
861             *keysym = XKeycodeToKeysym(event->xkey.display,
862                                    event->xkey.keycode, 2);
863          }
864     } else {
865         if( (event->xkey.state & ShiftMask) || // shift modifier is on
866             ((event->xkey.state & LockMask) && // lock modifier is on
867              (awt_ModLockIsShiftLock)) ) {     // it is interpreted as ShiftLock
868             *keysym = XKeycodeToKeysym(event->xkey.display,
869                                    event->xkey.keycode, 0);
870         }else{
871             *keysym = XKeycodeToKeysym(event->xkey.display,
872                                    event->xkey.keycode, 1);
873         }
874     }
875 }
876 
877 /* Called from handleKeyEvent.
878  * The purpose of this function is to make some adjustments to keysyms
879  * that have been found to be necessary when the NumLock mask is set.
880  * They come from various bug fixes and rearchitectures.
881  * This function is meant to be called when
882  * (event->xkey.state & awt_NumLockMask) is TRUE.
883  */
884 static void
handleKeyEventWithNumLockMask(XEvent * event,KeySym * keysym)885 handleKeyEventWithNumLockMask(XEvent *event, KeySym *keysym)
886 {
887     KeySym originalKeysym = *keysym;
888 
889 #if !defined(__linux__) && !defined(_ALLBSD_SOURCE)
890     /* The following code on Linux will cause the keypad keys
891      * not to echo on JTextField when the NumLock is on. The
892      * keysyms will be 0, because the last parameter 2 is not defined.
893      * See Xlib Programming Manual, O'Reilly & Associates, Section
894      * 9.1.5 "Other Keyboard-handling Routines", "The meaning of
895      * the keysym list beyond the first two (unmodified, Shift or
896      * Shift Lock) is not defined."
897      */
898 
899     /* Translate again with NumLock as modifier. */
900     /* ECH - I wonder why we think that NumLock corresponds to 2?
901        On Linux, we've seen xmodmap -pm yield mod2 as NumLock,
902        but I don't know that it will be for every configuration.
903        Perhaps using the index (modn in awt_MToolkit.c:setup_modifier_map)
904        would be more correct.
905      */
906     *keysym = XKeycodeToKeysym(event->xkey.display,
907                                event->xkey.keycode, 2);
908     if (originalKeysym != *keysym) {
909         DTRACE_PRINTLN3("%s originalKeysym=0x%x, keysym=0x%x",
910           "In handleKeyEventWithNumLockMask ifndef linux:",
911           originalKeysym, *keysym);
912     }
913 #endif
914 
915     /* Note: the XK_R? key assignments are for Type 4 kbds */
916     switch (*keysym) {
917         case XK_R13:
918             *keysym = XK_KP_1;
919             break;
920         case XK_R14:
921             *keysym = XK_KP_2;
922             break;
923         case XK_R15:
924             *keysym = XK_KP_3;
925             break;
926         case XK_R10:
927             *keysym = XK_KP_4;
928             break;
929         case XK_R11:
930             *keysym = XK_KP_5;
931             break;
932         case XK_R12:
933             *keysym = XK_KP_6;
934             break;
935         case XK_R7:
936             *keysym = XK_KP_7;
937             break;
938         case XK_R8:
939             *keysym = XK_KP_8;
940             break;
941         case XK_R9:
942             *keysym = XK_KP_9;
943             break;
944         case XK_KP_Insert:
945             *keysym = XK_KP_0;
946             break;
947         case XK_KP_Delete:
948             *keysym = XK_KP_Decimal;
949             break;
950         case XK_R4:
951             *keysym = XK_KP_Equal;  /* Type 4 kbd */
952             break;
953         case XK_R5:
954             *keysym = XK_KP_Divide;
955             break;
956         case XK_R6:
957             *keysym = XK_KP_Multiply;
958             break;
959         /*
960          * Need the following keysym changes for Linux key releases.
961          * Sometimes the modifier state gets messed up, so we get a
962          * KP_Left when we should get a KP_4, for example.
963          * XK_KP_Insert and XK_KP_Delete were already handled above.
964          */
965         case XK_KP_Left:
966             *keysym = XK_KP_4;
967             break;
968         case XK_KP_Up:
969             *keysym = XK_KP_8;
970             break;
971         case XK_KP_Right:
972             *keysym = XK_KP_6;
973             break;
974         case XK_KP_Down:
975             *keysym = XK_KP_2;
976             break;
977         case XK_KP_Home:
978             *keysym = XK_KP_7;
979             break;
980         case XK_KP_End:
981             *keysym = XK_KP_1;
982             break;
983         case XK_KP_Page_Up:
984             *keysym = XK_KP_9;
985             break;
986         case XK_KP_Page_Down:
987             *keysym = XK_KP_3;
988             break;
989         case XK_KP_Begin:
990             *keysym = XK_KP_5;
991             break;
992         default:
993             break;
994     }
995 
996     if (originalKeysym != *keysym) {
997         DTRACE_PRINTLN3("%s originalKeysym=0x%x, keysym=0x%x",
998           "In handleKeyEventWithNumLockMask:", originalKeysym, *keysym);
999     }
1000 }
1001 
1002 
1003 /* This function is called as the keyChar parameter of a call to
1004  * awt_post_java_key_event.  It depends on being called after adjustKeySym.
1005  *
1006  * This function just handles a few values where we know that the
1007  * keysym is not the same as the unicode value.  For values that
1008  * we don't handle explicitly, we just cast the keysym to a jchar.
1009  * Most of the real mapping work that gets the correct keysym is handled
1010  * in the mapping table, adjustKeySym, etc.
1011  *
1012  * XXX
1013  * Maybe we should enumerate the keysyms for which we have a mapping
1014  * in the keyMap, but that don't map to unicode chars, and return
1015  * CHAR_UNDEFINED?  Then use the buffer value from XLookupString
1016  * instead of the keysym as the keychar when posting.  Then we don't
1017  * need to test using mapsToUnicodeChar.  That way, we would post keyTyped
1018  * for all the chars that generate unicode chars, including LATIN2-4, etc.
1019  * Note: what does the buffer from XLookupString contain when
1020  * the character is a non-printable unicode character like Cancel or Delete?
1021  */
1022 jchar
keySymToUnicodeCharacter(KeySym keysym)1023 keySymToUnicodeCharacter(KeySym keysym) {
1024     jchar unicodeValue = (jchar) keysym;
1025 
1026     switch (keysym) {
1027       case XK_BackSpace:
1028       case XK_Tab:
1029       case XK_Linefeed:
1030       case XK_Escape:
1031       case XK_Delete:
1032           /* Strip off highorder bits defined in xkeysymdef.h
1033            * I think doing this converts them to values that
1034            * we can cast to jchars and use as java keychars.
1035            */
1036           unicodeValue = (jchar) (keysym & 0x007F);
1037           break;
1038       case XK_Return:
1039           unicodeValue = (jchar) 0x000a;  /* the unicode char for Linefeed */
1040           break;
1041       case XK_Cancel:
1042           unicodeValue = (jchar) 0x0018;  /* the unicode char for Cancel */
1043           break;
1044       default:
1045           break;
1046     }
1047 
1048     if (unicodeValue != (jchar)keysym) {
1049         DTRACE_PRINTLN3("%s originalKeysym=0x%x, keysym=0x%x",
1050           "In keysymToUnicode:", keysym, unicodeValue);
1051     }
1052 
1053     return unicodeValue;
1054 }
1055 
1056 
1057 void
awt_post_java_key_event(JNIEnv * env,jobject peer,jint id,jlong when,jint keyCode,jchar keyChar,jint keyLocation,jint state,XEvent * event)1058 awt_post_java_key_event(JNIEnv *env, jobject peer, jint id,
1059   jlong when, jint keyCode, jchar keyChar, jint keyLocation, jint state, XEvent * event)
1060 {
1061     JNU_CallMethodByName(env, NULL, peer, "postKeyEvent", "(IJICIIJI)V", id,
1062         when, keyCode, keyChar, keyLocation, state, ptr_to_jlong(event), (jint)sizeof(XEvent));
1063 } /* awt_post_java_key_event() */
1064 
1065 
1066 
1067 JNIEXPORT jint JNICALL
Java_sun_awt_X11_XWindow_getAWTKeyCodeForKeySym(JNIEnv * env,jclass clazz,jint keysym)1068 Java_sun_awt_X11_XWindow_getAWTKeyCodeForKeySym(JNIEnv *env, jclass clazz, jint keysym) {
1069     jint keycode = java_awt_event_KeyEvent_VK_UNDEFINED;
1070     Boolean mapsToUnicodeChar;
1071     jint keyLocation;
1072     keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation);
1073     return keycode;
1074 }
1075 
Java_sun_awt_X11_XWindow_haveCurrentX11InputMethodInstance(JNIEnv * env,jobject object)1076 JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XWindow_haveCurrentX11InputMethodInstance
1077 (JNIEnv *env, jobject object) {
1078     /*printf("Java_sun_awt_X11_XWindow_haveCurrentX11InputMethodInstance: %s\n", (currentX11InputMethodInstance==NULL? "NULL":" notnull"));
1079     */
1080     return currentX11InputMethodInstance != NULL ? JNI_TRUE : JNI_FALSE;
1081 }
1082 
Java_sun_awt_X11_XWindow_x11inputMethodLookupString(JNIEnv * env,jobject object,jlong event,jlongArray keysymArray)1083 JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XWindow_x11inputMethodLookupString
1084 (JNIEnv *env, jobject object, jlong event, jlongArray keysymArray) {
1085    KeySym keysym = NoSymbol;
1086    Boolean boo;
1087    /* keysymArray (and testbuf[]) have dimension 2 because we put there two
1088     * perhaps different values of keysyms.
1089     * XXX: not anymore at the moment, but I'll still keep them as arrays
1090     * for a while.  If in the course of testing we will be satisfied with
1091     * a current single result from awt_x11inputmethod_lookupString, we'll
1092     * change this.
1093     */
1094    jlong testbuf[2];
1095 
1096    testbuf[1]=0;
1097 
1098    boo = awt_x11inputmethod_lookupString((XKeyPressedEvent*)jlong_to_ptr(event), &keysym);
1099    testbuf[0] = keysym;
1100 
1101    (*env)->SetLongArrayRegion(env, keysymArray, 0, 2, (jlong *)(testbuf));
1102    return boo ? JNI_TRUE : JNI_FALSE;
1103 }
1104 
1105 
1106 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
1107 
1108 /*
1109  * Class:     Java_sun_awt_X11_XWindow_getNativeColor
1110  * Method:    getNativeColor
1111  * Signature  (Ljava/awt/Color;Ljava/awt/GraphicsConfiguration;)I
1112  */
Java_sun_awt_X11_XWindow_getNativeColor(JNIEnv * env,jobject this,jobject color,jobject gc_object)1113 JNIEXPORT jint JNICALL Java_sun_awt_X11_XWindow_getNativeColor
1114 (JNIEnv *env, jobject this, jobject color, jobject gc_object) {
1115     AwtGraphicsConfigDataPtr adata;
1116     /* fire warning because JNU_GetLongFieldAsPtr casts jlong to (void *) */
1117     adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, gc_object, x11GraphicsConfigIDs.aData);
1118     return awtJNI_GetColorForVis(env, color, adata);
1119 }
1120 
1121 /* syncTopLevelPos() is necessary to insure that the window manager has in
1122  * fact moved us to our final position relative to the reParented WM window.
1123  * We have noted a timing window which our shell has not been moved so we
1124  * screw up the insets thinking they are 0,0.  Wait (for a limited period of
1125  * time to let the WM hava a chance to move us
1126  */
syncTopLevelPos(Display * d,Window w,XWindowAttributes * winAttr)1127 void syncTopLevelPos( Display *d, Window w, XWindowAttributes *winAttr ) {
1128     int32_t i = 0;
1129     do {
1130          XGetWindowAttributes( d, w, winAttr );
1131          /* Sometimes we get here before the WM has updated the
1132          ** window data struct with the correct position.  Loop
1133          ** until we get a non-zero position.
1134          */
1135          if ((winAttr->x != 0) || (winAttr->y != 0)) {
1136              break;
1137          }
1138          else {
1139              /* What we really want here is to sync with the WM,
1140              ** but there's no explicit way to do this, so we
1141              ** call XSync for a delay.
1142              */
1143              XSync(d, False);
1144          }
1145     } while (i++ < 50);
1146 }
1147 
getTopWindow(Window win,Window * rootWin)1148 static Window getTopWindow(Window win, Window *rootWin)
1149 {
1150     Window root=None, current_window=win, parent=None, *ignore_children=NULL;
1151     Window prev_window=None;
1152     unsigned int ignore_uint=0;
1153     Status status = 0;
1154 
1155     if (win == None) return None;
1156     do {
1157         status = XQueryTree(awt_display,
1158                             current_window,
1159                             &root,
1160                             &parent,
1161                             &ignore_children,
1162                             &ignore_uint);
1163         XFree(ignore_children);
1164         if (status == 0) return None;
1165         prev_window = current_window;
1166         current_window = parent;
1167     } while (parent != root);
1168     *rootWin = root;
1169     return prev_window;
1170 }
1171 
Java_sun_awt_X11_XWindow_getTopWindow(JNIEnv * env,jclass clazz,jlong win,jlong rootWin)1172 JNIEXPORT jlong JNICALL Java_sun_awt_X11_XWindow_getTopWindow
1173 (JNIEnv *env, jclass clazz, jlong win, jlong rootWin) {
1174     return getTopWindow((Window) win, (Window*) jlong_to_ptr(rootWin));
1175 }
1176 
1177 static void
getWMInsets(Window window,int * left,int * top,int * right,int * bottom,int * border)1178 getWMInsets
1179 (Window window, int *left, int *top, int *right, int *bottom, int *border) {
1180     // window is event->xreparent.window
1181     Window topWin = None, rootWin = None, containerWindow = None;
1182     XWindowAttributes winAttr, topAttr;
1183     int screenX, screenY;
1184     topWin = getTopWindow(window, &rootWin);
1185     syncTopLevelPos(awt_display, topWin, &topAttr);
1186     // (screenX, screenY) is (0,0) of the reparented window
1187     // converted to screen coordinates.
1188     XTranslateCoordinates(awt_display, window, rootWin,
1189         0,0, &screenX, &screenY, &containerWindow);
1190     *left = screenX - topAttr.x - topAttr.border_width;
1191     *top  = screenY - topAttr.y - topAttr.border_width;
1192     XGetWindowAttributes(awt_display, window, &winAttr);
1193     *right  = topAttr.width  - ((winAttr.width)  + *left);
1194     *bottom = topAttr.height - ((winAttr.height) + *top);
1195     *border = topAttr.border_width;
1196 }
1197 
Java_sun_awt_X11_XWindow_getWMInsets(JNIEnv * env,jclass clazz,jlong window,jlong left,jlong top,jlong right,jlong bottom,jlong border)1198 JNIEXPORT void JNICALL Java_sun_awt_X11_XWindow_getWMInsets
1199 (JNIEnv *env, jclass clazz, jlong window, jlong left, jlong top, jlong right, jlong bottom, jlong border) {
1200     getWMInsets((Window) window,
1201                 (int*) jlong_to_ptr(left),
1202                 (int*) jlong_to_ptr(top),
1203                 (int*) jlong_to_ptr(right),
1204                 (int*) jlong_to_ptr(bottom),
1205                 (int*) jlong_to_ptr(border));
1206 }
1207 
1208 static void
getWindowBounds(Window window,int * x,int * y,int * width,int * height)1209 getWindowBounds
1210 (Window window, int *x, int *y, int *width, int *height) {
1211     XWindowAttributes winAttr;
1212     XSync(awt_display, False);
1213     XGetWindowAttributes(awt_display, window, &winAttr);
1214     *x = winAttr.x;
1215     *y = winAttr.y;
1216     *width = winAttr.width;
1217     *height = winAttr.height;
1218 }
1219 
Java_sun_awt_X11_XWindow_getWindowBounds(JNIEnv * env,jclass clazz,jlong window,jlong x,jlong y,jlong width,jlong height)1220 JNIEXPORT void JNICALL Java_sun_awt_X11_XWindow_getWindowBounds
1221 (JNIEnv *env, jclass clazz, jlong window, jlong x, jlong y, jlong width, jlong height) {
1222     getWindowBounds((Window) window, (int*) jlong_to_ptr(x), (int*) jlong_to_ptr(y),
1223                     (int*) jlong_to_ptr(width), (int*) jlong_to_ptr(height));
1224 }
1225 
Java_sun_awt_X11_XWindow_setSizeHints(JNIEnv * env,jclass clazz,jlong window,jlong x,jlong y,jlong width,jlong height)1226 JNIEXPORT void JNICALL Java_sun_awt_X11_XWindow_setSizeHints
1227 (JNIEnv *env, jclass clazz, jlong window, jlong x, jlong y, jlong width, jlong height) {
1228     XSizeHints *size_hints = XAllocSizeHints();
1229     size_hints->flags = USPosition | PPosition | PSize;
1230     size_hints->x = (int)x;
1231     size_hints->y = (int)y;
1232     size_hints->width = (int)width;
1233     size_hints->height = (int)height;
1234     XSetWMNormalHints(awt_display, (Window)window, size_hints);
1235     XFree((char*)size_hints);
1236 }
1237 
1238 
1239 JNIEXPORT void JNICALL
Java_sun_awt_X11_XWindow_initIDs(JNIEnv * env,jclass clazz)1240 Java_sun_awt_X11_XWindow_initIDs
1241   (JNIEnv *env, jclass clazz)
1242 {
1243    char *ptr = NULL;
1244    windowID = (*env)->GetFieldID(env, clazz, "window", "J");
1245    CHECK_NULL(windowID);
1246    targetID = (*env)->GetFieldID(env, clazz, "target", "Ljava/awt/Component;");
1247    CHECK_NULL(targetID);
1248    graphicsConfigID = (*env)->GetFieldID(env, clazz, "graphicsConfig", "Lsun/awt/X11GraphicsConfig;");
1249    CHECK_NULL(graphicsConfigID);
1250    drawStateID = (*env)->GetFieldID(env, clazz, "drawState", "I");
1251    CHECK_NULL(drawStateID);
1252    ptr = getenv("_AWT_USE_TYPE4_PATCH");
1253    if( ptr != NULL && ptr[0] != 0 ) {
1254        if( strncmp("true", ptr, 4) == 0 ) {
1255           awt_UseType4Patch = True;
1256        }else if( strncmp("false", ptr, 5) == 0 ) {
1257           awt_UseType4Patch = False;
1258        }
1259    }
1260 }
1261 
1262 JNIEXPORT jint JNICALL
Java_sun_awt_X11_XWindow_getKeySymForAWTKeyCode(JNIEnv * env,jclass clazz,jint keycode)1263 Java_sun_awt_X11_XWindow_getKeySymForAWTKeyCode(JNIEnv* env, jclass clazz, jint keycode) {
1264     return awt_getX11KeySym(keycode);
1265 }
1266