blob: 1a2f7dd4164efcd717c155f6c891aa22ec68ccdf [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1995-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#ifdef HEADLESS
27 #error This file should not be included in headless library
28#endif
29
30#include "awt_p.h"
31#include <sys/time.h> /* timeval */
32
33#define XK_KATAKANA
34#include <X11/keysym.h> /* standard X keysyms */
35#include <X11/DECkeysym.h> /* DEC vendor-specific */
36#include <X11/Sunkeysym.h> /* Sun vendor-specific */
37#include <X11/ap_keysym.h> /* Apollo (HP) vendor-specific */
38/*
39 * #include <X11/HPkeysym.h> HP vendor-specific
40 * I checked HPkeysym.h into the workspace because it ships
41 * with X11R6.4.2 (and later) but not with X11R6.4.1.
42 * So, it ought to ship with Solaris 9, but not Solaris 8.
43 * Same deal for Linux - newer versions of XFree have it.
44 *
45 * Note: this is mainly done for the hp keysyms; it does NOT
46 * give us the osf keysyms that are also defined in HPkeysym.h.
47 * This is because we are already getting /Xm/VirtKeys.h
48 * from awt_p.h <- /Xm/Xm.h <- /Xm/VirtKeys.h, and VirtKeys.h
49 * #defines _OSF_Keysyms before we get here. We are
50 * missing a couple of osf keysyms because of this,
51 * so I have #defined them below.
52 */
53#include "HPkeysym.h" /* HP vendor-specific */
54
55#include <Xm/Display.h>
56#include <ctype.h>
57#include "java_awt_Frame.h"
58#include "java_awt_Component.h"
59#include "java_awt_AWTEvent.h"
60#include "java_awt_event_KeyEvent.h"
61#include "java_awt_event_FocusEvent.h"
62#include "java_awt_event_MouseEvent.h"
63#include "java_awt_event_MouseWheelEvent.h"
64#include "java_awt_event_InputEvent.h"
65#include "java_awt_event_WindowEvent.h"
66#include "sun_awt_motif_MComponentPeer.h"
67#include "color.h"
68#include "canvas.h"
69#include "awt_Cursor.h"
70#include "VDrawingArea.h"
71#include "XDrawingArea.h"
72#include "awt_Component.h"
73#include "awt_AWTEvent.h"
74#include "awt_Event.h"
75#include "awt_KeyboardFocusManager.h"
76#include "awt_MToolkit.h"
77#include "awt_TopLevel.h"
78#include "awt_util.h"
79
80#include <jni.h>
81#include <jni_util.h>
82#include <jvm.h>
83#include <jawt.h>
84
85#ifdef NDEBUG /* NDEBUG overrides DEBUG */
86#undef DEBUG
87#endif
88
89/*
90 * Two osf keys are not defined in standard keysym.h,
91 * /Xm/VirtKeys.h, or HPkeysym.h, so I added them below.
92 * I found them in /usr/openwin/lib/X11/XKeysymDB
93 */
94#ifndef osfXK_Prior
95#define osfXK_Prior 0x1004FF55
96#endif
97#ifndef osfXK_Next
98#define osfXK_Next 0x1004FF56
99#endif
100/*
101 * osfXK_Escape is defined in HPkeysym.h, but not in
102 * /Xm/VirtKeys.h, so I added it below. It is also in
103 * /usr/openwin/lib/X11/XKeysymDB
104 * Note: it is in /Xm/VirtKeys.h in the AWT motif workspace,
105 * but not in /usr/local/Motif/include/Xm/VirtKeys.h
106 * on the Solaris 7, 8, or 9 machines I tried.
107 */
108#ifndef osfXK_Escape
109#define osfXK_Escape 0x1004FF1B
110#endif
111
112extern struct MComponentPeerIDs mComponentPeerIDs;
113extern struct AWTEventIDs awtEventIDs;
114extern struct KeyEventIDs keyEventIDs;
115extern struct InputEventIDs inputEventIDs;
116extern struct ComponentIDs componentIDs;
117extern struct KeyboardFocusManagerIDs keyboardFocusManagerIDs;
118
119#ifdef DEBUG
120static Boolean debugKeys = False;
121#endif
122
123jint awt_multiclick_smudge = 4;
124
125extern Widget drag_source;
126
127Widget prevWidget = NULL; /* for bug fix 4017222 */
128
129FocusListElt *focusList = NULL, *focusListEnd = NULL;
130
131jweak forGained = NULL;
132
133extern Boolean scrollBugWorkAround;
134extern jobject currentX11InputMethodInstance;
135extern Window currentFocusWindow;
136extern Boolean awt_x11inputmethod_lookupString(XKeyPressedEvent *, KeySym *);
137Boolean awt_UseType4Patch = True;
138Boolean awt_ServerDetected = False;
139Boolean awt_IsXsun = False;
140Boolean awt_UseXKB = False;
141
142void awt_post_java_key_event(XtPointer client_data, jint id,
143 XEvent *xevent, Time when, jint keycode,
144 jchar keychar, jint modifiers,
145 jint keyLocation, XEvent *anEvent);
146void awt_post_java_focus_event(XtPointer client_data, jint id, jobject cause,
147 XEvent *event);
148void awt_post_java_mouse_event(XtPointer client_data, jint id,
149 XEvent *event, Time when, jint modifiers,
150 jint x, jint y,
151 jint xAbs, jint yAbs,
152 jint clickcount, Boolean popuptrigger,
153 jint wheelAmt, jint button);
154
155typedef struct KEYMAP_ENTRY {
156 jint awtKey;
157 KeySym x11Key;
158 Boolean mapsToUnicodeChar;
159 jint keyLocation;
160} KeymapEntry;
161
162/* NB: XK_R? keysyms are for Type 4 keyboards.
163 * The corresponding XK_F? keysyms are for Type 5
164 *
165 * Note: this table must be kept in sorted order, since it is traversed
166 * according to both Java keycode and X keysym. There are a number of
167 * keycodes that map to more than one corresponding keysym, and we need
168 * to choose the right one. Unfortunately, there are some keysyms that
169 * can map to more than one keycode, depending on what kind of keyboard
170 * is in use (e.g. F11 and F12).
171 */
172
173KeymapEntry keymapTable[] =
174{
175 {java_awt_event_KeyEvent_VK_A, XK_a, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
176 {java_awt_event_KeyEvent_VK_B, XK_b, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
177 {java_awt_event_KeyEvent_VK_C, XK_c, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
178 {java_awt_event_KeyEvent_VK_D, XK_d, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
179 {java_awt_event_KeyEvent_VK_E, XK_e, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
180 {java_awt_event_KeyEvent_VK_F, XK_f, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
181 {java_awt_event_KeyEvent_VK_G, XK_g, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
182 {java_awt_event_KeyEvent_VK_H, XK_h, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
183 {java_awt_event_KeyEvent_VK_I, XK_i, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
184 {java_awt_event_KeyEvent_VK_J, XK_j, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
185 {java_awt_event_KeyEvent_VK_K, XK_k, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
186 {java_awt_event_KeyEvent_VK_L, XK_l, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
187 {java_awt_event_KeyEvent_VK_M, XK_m, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
188 {java_awt_event_KeyEvent_VK_N, XK_n, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
189 {java_awt_event_KeyEvent_VK_O, XK_o, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
190 {java_awt_event_KeyEvent_VK_P, XK_p, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
191 {java_awt_event_KeyEvent_VK_Q, XK_q, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
192 {java_awt_event_KeyEvent_VK_R, XK_r, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
193 {java_awt_event_KeyEvent_VK_S, XK_s, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
194 {java_awt_event_KeyEvent_VK_T, XK_t, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
195 {java_awt_event_KeyEvent_VK_U, XK_u, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
196 {java_awt_event_KeyEvent_VK_V, XK_v, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
197 {java_awt_event_KeyEvent_VK_W, XK_w, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
198 {java_awt_event_KeyEvent_VK_X, XK_x, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
199 {java_awt_event_KeyEvent_VK_Y, XK_y, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
200 {java_awt_event_KeyEvent_VK_Z, XK_z, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
201
202 /* TTY Function keys */
203 {java_awt_event_KeyEvent_VK_BACK_SPACE, XK_BackSpace, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
204 {java_awt_event_KeyEvent_VK_TAB, XK_Tab, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
205 {java_awt_event_KeyEvent_VK_CLEAR, XK_Clear, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
206 {java_awt_event_KeyEvent_VK_ENTER, XK_Return, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
207 {java_awt_event_KeyEvent_VK_ENTER, XK_Linefeed, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
208 {java_awt_event_KeyEvent_VK_PAUSE, XK_Pause, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
209 {java_awt_event_KeyEvent_VK_PAUSE, XK_F21, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
210 {java_awt_event_KeyEvent_VK_PAUSE, XK_R1, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
211 {java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_Scroll_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
212 {java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_F23, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
213 {java_awt_event_KeyEvent_VK_SCROLL_LOCK, XK_R3, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
214 {java_awt_event_KeyEvent_VK_ESCAPE, XK_Escape, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
215
216 /* Other vendor-specific versions of TTY Function keys */
217 {java_awt_event_KeyEvent_VK_BACK_SPACE, osfXK_BackSpace, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
218 {java_awt_event_KeyEvent_VK_CLEAR, osfXK_Clear, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
219 {java_awt_event_KeyEvent_VK_ESCAPE, osfXK_Escape, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
220
221 /* Modifier keys */
222 {java_awt_event_KeyEvent_VK_SHIFT, XK_Shift_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT},
223 {java_awt_event_KeyEvent_VK_SHIFT, XK_Shift_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT},
224 {java_awt_event_KeyEvent_VK_CONTROL, XK_Control_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT},
225 {java_awt_event_KeyEvent_VK_CONTROL, XK_Control_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT},
226 {java_awt_event_KeyEvent_VK_ALT, XK_Alt_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT},
227 {java_awt_event_KeyEvent_VK_ALT, XK_Alt_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT},
228 {java_awt_event_KeyEvent_VK_META, XK_Meta_L, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_LEFT},
229 {java_awt_event_KeyEvent_VK_META, XK_Meta_R, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_RIGHT},
230 {java_awt_event_KeyEvent_VK_CAPS_LOCK, XK_Caps_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
231
232 /* Misc Functions */
233 {java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_Print, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
234 {java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_F22, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
235 {java_awt_event_KeyEvent_VK_PRINTSCREEN, XK_R2, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
236 {java_awt_event_KeyEvent_VK_CANCEL, XK_Cancel, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
237 {java_awt_event_KeyEvent_VK_HELP, XK_Help, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
238 {java_awt_event_KeyEvent_VK_NUM_LOCK, XK_Num_Lock, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
239
240 /* Other vendor-specific versions of Misc Functions */
241 {java_awt_event_KeyEvent_VK_CANCEL, osfXK_Cancel, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
242 {java_awt_event_KeyEvent_VK_HELP, osfXK_Help, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
243
244 /* Rectangular Navigation Block */
245 {java_awt_event_KeyEvent_VK_HOME, XK_Home, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
246 {java_awt_event_KeyEvent_VK_HOME, XK_R7, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
247 {java_awt_event_KeyEvent_VK_PAGE_UP, XK_Page_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
248 {java_awt_event_KeyEvent_VK_PAGE_UP, XK_Prior, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
249 {java_awt_event_KeyEvent_VK_PAGE_UP, XK_R9, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
250 {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_Page_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
251 {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_Next, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
252 {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_R15, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
253 {java_awt_event_KeyEvent_VK_END, XK_End, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
254 {java_awt_event_KeyEvent_VK_END, XK_R13, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
255 {java_awt_event_KeyEvent_VK_INSERT, XK_Insert, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
256 {java_awt_event_KeyEvent_VK_DELETE, XK_Delete, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
257
258 /* Keypad equivalents of Rectangular Navigation Block */
259 {java_awt_event_KeyEvent_VK_HOME, XK_KP_Home, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
260 {java_awt_event_KeyEvent_VK_PAGE_UP, XK_KP_Page_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
261 {java_awt_event_KeyEvent_VK_PAGE_UP, XK_KP_Prior, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
262 {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_KP_Page_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
263 {java_awt_event_KeyEvent_VK_PAGE_DOWN, XK_KP_Next, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
264 {java_awt_event_KeyEvent_VK_END, XK_KP_End, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
265 {java_awt_event_KeyEvent_VK_INSERT, XK_KP_Insert, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
266 {java_awt_event_KeyEvent_VK_DELETE, XK_KP_Delete, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
267
268 /* Other vendor-specific Rectangular Navigation Block */
269 {java_awt_event_KeyEvent_VK_PAGE_UP, osfXK_PageUp, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
270 {java_awt_event_KeyEvent_VK_PAGE_UP, osfXK_Prior, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
271 {java_awt_event_KeyEvent_VK_PAGE_DOWN, osfXK_PageDown, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
272 {java_awt_event_KeyEvent_VK_PAGE_DOWN, osfXK_Next, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
273 {java_awt_event_KeyEvent_VK_END, osfXK_EndLine, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
274 {java_awt_event_KeyEvent_VK_INSERT, osfXK_Insert, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
275 {java_awt_event_KeyEvent_VK_DELETE, osfXK_Delete, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
276
277 /* Triangular Navigation Block */
278 {java_awt_event_KeyEvent_VK_LEFT, XK_Left, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
279 {java_awt_event_KeyEvent_VK_UP, XK_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
280 {java_awt_event_KeyEvent_VK_RIGHT, XK_Right, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
281 {java_awt_event_KeyEvent_VK_DOWN, XK_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
282
283 /* Keypad equivalents of Triangular Navigation Block */
284 {java_awt_event_KeyEvent_VK_KP_LEFT, XK_KP_Left, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
285 {java_awt_event_KeyEvent_VK_KP_UP, XK_KP_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
286 {java_awt_event_KeyEvent_VK_KP_RIGHT, XK_KP_Right, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
287 {java_awt_event_KeyEvent_VK_KP_DOWN, XK_KP_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
288
289 /* Other vendor-specific Triangular Navigation Block */
290 {java_awt_event_KeyEvent_VK_LEFT, osfXK_Left, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
291 {java_awt_event_KeyEvent_VK_UP, osfXK_Up, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
292 {java_awt_event_KeyEvent_VK_RIGHT, osfXK_Right, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
293 {java_awt_event_KeyEvent_VK_DOWN, osfXK_Down, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
294
295 /* Remaining Cursor control & motion */
296 {java_awt_event_KeyEvent_VK_BEGIN, XK_Begin, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
297 {java_awt_event_KeyEvent_VK_BEGIN, XK_KP_Begin, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
298
299 {java_awt_event_KeyEvent_VK_0, XK_0, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
300 {java_awt_event_KeyEvent_VK_1, XK_1, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
301 {java_awt_event_KeyEvent_VK_2, XK_2, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
302 {java_awt_event_KeyEvent_VK_3, XK_3, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
303 {java_awt_event_KeyEvent_VK_4, XK_4, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
304 {java_awt_event_KeyEvent_VK_5, XK_5, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
305 {java_awt_event_KeyEvent_VK_6, XK_6, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
306 {java_awt_event_KeyEvent_VK_7, XK_7, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
307 {java_awt_event_KeyEvent_VK_8, XK_8, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
308 {java_awt_event_KeyEvent_VK_9, XK_9, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
309
310 {java_awt_event_KeyEvent_VK_SPACE, XK_space, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
311 {java_awt_event_KeyEvent_VK_EXCLAMATION_MARK, XK_exclam, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
312 {java_awt_event_KeyEvent_VK_QUOTEDBL, XK_quotedbl, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
313 {java_awt_event_KeyEvent_VK_NUMBER_SIGN, XK_numbersign, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
314 {java_awt_event_KeyEvent_VK_DOLLAR, XK_dollar, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
315 {java_awt_event_KeyEvent_VK_AMPERSAND, XK_ampersand, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
316 {java_awt_event_KeyEvent_VK_QUOTE, XK_apostrophe, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
317 {java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS, XK_parenleft, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
318 {java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS, XK_parenright, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
319 {java_awt_event_KeyEvent_VK_ASTERISK, XK_asterisk, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
320 {java_awt_event_KeyEvent_VK_PLUS, XK_plus, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
321 {java_awt_event_KeyEvent_VK_COMMA, XK_comma, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
322 {java_awt_event_KeyEvent_VK_MINUS, XK_minus, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
323 {java_awt_event_KeyEvent_VK_PERIOD, XK_period, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
324 {java_awt_event_KeyEvent_VK_SLASH, XK_slash, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
325
326 {java_awt_event_KeyEvent_VK_COLON, XK_colon, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
327 {java_awt_event_KeyEvent_VK_SEMICOLON, XK_semicolon, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
328 {java_awt_event_KeyEvent_VK_LESS, XK_less, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
329 {java_awt_event_KeyEvent_VK_EQUALS, XK_equal, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
330 {java_awt_event_KeyEvent_VK_GREATER, XK_greater, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
331
332 {java_awt_event_KeyEvent_VK_AT, XK_at, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
333
334 {java_awt_event_KeyEvent_VK_OPEN_BRACKET, XK_bracketleft, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
335 {java_awt_event_KeyEvent_VK_BACK_SLASH, XK_backslash, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
336 {java_awt_event_KeyEvent_VK_CLOSE_BRACKET, XK_bracketright, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
337 {java_awt_event_KeyEvent_VK_CIRCUMFLEX, XK_asciicircum, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
338 {java_awt_event_KeyEvent_VK_UNDERSCORE, XK_underscore, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
339 {java_awt_event_KeyEvent_VK_BACK_QUOTE, XK_grave, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
340
341 {java_awt_event_KeyEvent_VK_BRACELEFT, XK_braceleft, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
342 {java_awt_event_KeyEvent_VK_BRACERIGHT, XK_braceright, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
343
344 {java_awt_event_KeyEvent_VK_INVERTED_EXCLAMATION_MARK, XK_exclamdown, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
345
346 /* Remaining Numeric Keypad Keys */
347 {java_awt_event_KeyEvent_VK_NUMPAD0, XK_KP_0, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
348 {java_awt_event_KeyEvent_VK_NUMPAD1, XK_KP_1, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
349 {java_awt_event_KeyEvent_VK_NUMPAD2, XK_KP_2, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
350 {java_awt_event_KeyEvent_VK_NUMPAD3, XK_KP_3, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
351 {java_awt_event_KeyEvent_VK_NUMPAD4, XK_KP_4, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
352 {java_awt_event_KeyEvent_VK_NUMPAD5, XK_KP_5, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
353 {java_awt_event_KeyEvent_VK_NUMPAD6, XK_KP_6, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
354 {java_awt_event_KeyEvent_VK_NUMPAD7, XK_KP_7, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
355 {java_awt_event_KeyEvent_VK_NUMPAD8, XK_KP_8, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
356 {java_awt_event_KeyEvent_VK_NUMPAD9, XK_KP_9, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
357 {java_awt_event_KeyEvent_VK_SPACE, XK_KP_Space, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
358 {java_awt_event_KeyEvent_VK_TAB, XK_KP_Tab, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
359 {java_awt_event_KeyEvent_VK_ENTER, XK_KP_Enter, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
360 {java_awt_event_KeyEvent_VK_EQUALS, XK_KP_Equal, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
361 {java_awt_event_KeyEvent_VK_EQUALS, XK_R4, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
362 {java_awt_event_KeyEvent_VK_MULTIPLY, XK_KP_Multiply, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
363 {java_awt_event_KeyEvent_VK_MULTIPLY, XK_F26, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
364 {java_awt_event_KeyEvent_VK_MULTIPLY, XK_R6, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
365 {java_awt_event_KeyEvent_VK_ADD, XK_KP_Add, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
366 {java_awt_event_KeyEvent_VK_SEPARATOR, XK_KP_Separator, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
367 {java_awt_event_KeyEvent_VK_SUBTRACT, XK_KP_Subtract, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
368 {java_awt_event_KeyEvent_VK_SUBTRACT, XK_F24, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
369 {java_awt_event_KeyEvent_VK_DECIMAL, XK_KP_Decimal, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
370 {java_awt_event_KeyEvent_VK_DIVIDE, XK_KP_Divide, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
371 {java_awt_event_KeyEvent_VK_DIVIDE, XK_F25, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
372 {java_awt_event_KeyEvent_VK_DIVIDE, XK_R5, TRUE, java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD},
373
374 /* Function Keys */
375 {java_awt_event_KeyEvent_VK_F1, XK_F1, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
376 {java_awt_event_KeyEvent_VK_F2, XK_F2, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
377 {java_awt_event_KeyEvent_VK_F3, XK_F3, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
378 {java_awt_event_KeyEvent_VK_F4, XK_F4, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
379 {java_awt_event_KeyEvent_VK_F5, XK_F5, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
380 {java_awt_event_KeyEvent_VK_F6, XK_F6, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
381 {java_awt_event_KeyEvent_VK_F7, XK_F7, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
382 {java_awt_event_KeyEvent_VK_F8, XK_F8, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
383 {java_awt_event_KeyEvent_VK_F9, XK_F9, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
384 {java_awt_event_KeyEvent_VK_F10, XK_F10, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
385 {java_awt_event_KeyEvent_VK_F11, XK_F11, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
386 {java_awt_event_KeyEvent_VK_F12, XK_F12, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
387
388 /* Sun vendor-specific version of F11 and F12 */
389 {java_awt_event_KeyEvent_VK_F11, SunXK_F36, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
390 {java_awt_event_KeyEvent_VK_F12, SunXK_F37, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
391
392 /* X11 keysym names for input method related keys don't always
393 * match keytop engravings or Java virtual key names, so here we
394 * only map constants that we've found on real keyboards.
395 */
396 /* Type 5c Japanese keyboard: kakutei */
397 {java_awt_event_KeyEvent_VK_ACCEPT, XK_Execute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
398 /* Type 5c Japanese keyboard: henkan */
399 {java_awt_event_KeyEvent_VK_CONVERT, XK_Kanji, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
400 /* Type 5c Japanese keyboard: nihongo */
401 {java_awt_event_KeyEvent_VK_INPUT_METHOD_ON_OFF, XK_Henkan_Mode, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
402 /* VK_KANA_LOCK is handled separately because it generates the
403 * same keysym as ALT_GRAPH in spite of its different behavior.
404 */
405
406 {java_awt_event_KeyEvent_VK_COMPOSE, XK_Multi_key, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
407 {java_awt_event_KeyEvent_VK_ALT_GRAPH, XK_Mode_switch, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
408
409 /* Editing block */
410 {java_awt_event_KeyEvent_VK_AGAIN, XK_Redo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
411 {java_awt_event_KeyEvent_VK_AGAIN, XK_L2, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
412 {java_awt_event_KeyEvent_VK_UNDO, XK_Undo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
413 {java_awt_event_KeyEvent_VK_UNDO, XK_L4, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
414 {java_awt_event_KeyEvent_VK_COPY, XK_L6, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
415 {java_awt_event_KeyEvent_VK_PASTE, XK_L8, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
416 {java_awt_event_KeyEvent_VK_CUT, XK_L10, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
417 {java_awt_event_KeyEvent_VK_FIND, XK_Find, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
418 {java_awt_event_KeyEvent_VK_FIND, XK_L9, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
419 {java_awt_event_KeyEvent_VK_PROPS, XK_L3, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
420 {java_awt_event_KeyEvent_VK_STOP, XK_L1, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
421
422 /* Sun vendor-specific versions for editing block */
423 {java_awt_event_KeyEvent_VK_AGAIN, SunXK_Again, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
424 {java_awt_event_KeyEvent_VK_UNDO, SunXK_Undo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
425 {java_awt_event_KeyEvent_VK_COPY, SunXK_Copy, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
426 {java_awt_event_KeyEvent_VK_PASTE, SunXK_Paste, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
427 {java_awt_event_KeyEvent_VK_CUT, SunXK_Cut, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
428 {java_awt_event_KeyEvent_VK_FIND, SunXK_Find, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
429 {java_awt_event_KeyEvent_VK_PROPS, SunXK_Props, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
430 {java_awt_event_KeyEvent_VK_STOP, SunXK_Stop, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
431
432 /* Apollo (HP) vendor-specific versions for editing block */
433 {java_awt_event_KeyEvent_VK_COPY, apXK_Copy, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
434 {java_awt_event_KeyEvent_VK_CUT, apXK_Cut, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
435 {java_awt_event_KeyEvent_VK_PASTE, apXK_Paste, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
436
437 /* Other vendor-specific versions for editing block */
438 {java_awt_event_KeyEvent_VK_COPY, osfXK_Copy, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
439 {java_awt_event_KeyEvent_VK_CUT, osfXK_Cut, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
440 {java_awt_event_KeyEvent_VK_PASTE, osfXK_Paste, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
441 {java_awt_event_KeyEvent_VK_UNDO, osfXK_Undo, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
442
443 /* Dead key mappings (for European keyboards) */
444 {java_awt_event_KeyEvent_VK_DEAD_GRAVE, XK_dead_grave, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
445 {java_awt_event_KeyEvent_VK_DEAD_ACUTE, XK_dead_acute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
446 {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, XK_dead_circumflex, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
447 {java_awt_event_KeyEvent_VK_DEAD_TILDE, XK_dead_tilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
448 {java_awt_event_KeyEvent_VK_DEAD_MACRON, XK_dead_macron, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
449 {java_awt_event_KeyEvent_VK_DEAD_BREVE, XK_dead_breve, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
450 {java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT, XK_dead_abovedot, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
451 {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, XK_dead_diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
452 {java_awt_event_KeyEvent_VK_DEAD_ABOVERING, XK_dead_abovering, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
453 {java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE, XK_dead_doubleacute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
454 {java_awt_event_KeyEvent_VK_DEAD_CARON, XK_dead_caron, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
455 {java_awt_event_KeyEvent_VK_DEAD_CEDILLA, XK_dead_cedilla, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
456 {java_awt_event_KeyEvent_VK_DEAD_OGONEK, XK_dead_ogonek, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
457 {java_awt_event_KeyEvent_VK_DEAD_IOTA, XK_dead_iota, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
458 {java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND, XK_dead_voiced_sound, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
459 {java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND, XK_dead_semivoiced_sound, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
460
461 /* Sun vendor-specific dead key mappings (for European keyboards) */
462 {java_awt_event_KeyEvent_VK_DEAD_GRAVE, SunXK_FA_Grave, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
463 {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, SunXK_FA_Circum, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
464 {java_awt_event_KeyEvent_VK_DEAD_TILDE, SunXK_FA_Tilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
465 {java_awt_event_KeyEvent_VK_DEAD_ACUTE, SunXK_FA_Acute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
466 {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, SunXK_FA_Diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
467 {java_awt_event_KeyEvent_VK_DEAD_CEDILLA, SunXK_FA_Cedilla, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
468
469 /* DEC vendor-specific dead key mappings (for European keyboards) */
470 {java_awt_event_KeyEvent_VK_DEAD_ABOVERING, DXK_ring_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
471 {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, DXK_circumflex_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
472 {java_awt_event_KeyEvent_VK_DEAD_CEDILLA, DXK_cedilla_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
473 {java_awt_event_KeyEvent_VK_DEAD_ACUTE, DXK_acute_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
474 {java_awt_event_KeyEvent_VK_DEAD_GRAVE, DXK_grave_accent, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
475 {java_awt_event_KeyEvent_VK_DEAD_TILDE, DXK_tilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
476 {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, DXK_diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
477
478 /* Other vendor-specific dead key mappings (for European keyboards) */
479 {java_awt_event_KeyEvent_VK_DEAD_ACUTE, hpXK_mute_acute, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
480 {java_awt_event_KeyEvent_VK_DEAD_GRAVE, hpXK_mute_grave, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
481 {java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX, hpXK_mute_asciicircum, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
482 {java_awt_event_KeyEvent_VK_DEAD_DIAERESIS, hpXK_mute_diaeresis, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
483 {java_awt_event_KeyEvent_VK_DEAD_TILDE, hpXK_mute_asciitilde, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_STANDARD},
484
485 {java_awt_event_KeyEvent_VK_UNDEFINED, NoSymbol, FALSE, java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN}
486};
487
488static Boolean
489keyboardHasKanaLockKey()
490{
491 static Boolean haveResult = FALSE;
492 static Boolean result = FALSE;
493
494 int32_t minKeyCode, maxKeyCode, keySymsPerKeyCode;
495 KeySym *keySyms, *keySymsStart, keySym;
496 int32_t i;
497 int32_t kanaCount = 0;
498
499 // Solaris doesn't let you swap keyboards without rebooting,
500 // so there's no need to check for the kana lock key more than once.
501 if (haveResult) {
502 return result;
503 }
504
505 // There's no direct way to determine whether the keyboard has
506 // a kana lock key. From available keyboard mapping tables, it looks
507 // like only keyboards with the kana lock key can produce keysyms
508 // for kana characters. So, as an indirect test, we check for those.
509
510 XDisplayKeycodes(awt_display, &minKeyCode, &maxKeyCode);
511 keySyms = XGetKeyboardMapping(awt_display, minKeyCode, maxKeyCode - minKeyCode + 1, &keySymsPerKeyCode);
512 keySymsStart = keySyms;
513 for (i = 0; i < (maxKeyCode - minKeyCode + 1) * keySymsPerKeyCode; i++) {
514 keySym = *keySyms++;
515 if ((keySym & 0xff00) == 0x0400) {
516 kanaCount++;
517 }
518 }
519 XFree(keySymsStart);
520
521 // use a (somewhat arbitrary) minimum so we don't get confused by a stray function key
522 result = kanaCount > 10;
523 haveResult = TRUE;
524 return result;
525}
526
527void
528keysymToAWTKeyCode(KeySym x11Key, jint *keycode, Boolean *mapsToUnicodeChar,
529 jint *keyLocation)
530{
531 int32_t i;
532
533 // Solaris uses XK_Mode_switch for both the non-locking AltGraph
534 // and the locking Kana key, but we want to keep them separate for
535 // KeyEvent.
536 if (x11Key == XK_Mode_switch && keyboardHasKanaLockKey()) {
537 *keycode = java_awt_event_KeyEvent_VK_KANA_LOCK;
538 *mapsToUnicodeChar = FALSE;
539 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
540 return;
541 }
542
543 for (i = 0;
544 keymapTable[i].awtKey != java_awt_event_KeyEvent_VK_UNDEFINED;
545 i++) {
546 if (keymapTable[i].x11Key == x11Key) {
547 *keycode = keymapTable[i].awtKey;
548 *mapsToUnicodeChar = keymapTable[i].mapsToUnicodeChar;
549 *keyLocation = keymapTable[i].keyLocation;
550 return;
551 }
552 }
553
554 *keycode = java_awt_event_KeyEvent_VK_UNDEFINED;
555 *mapsToUnicodeChar = FALSE;
556 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
557
558 DTRACE_PRINTLN1("keysymToAWTKeyCode: no key mapping found: keysym = %x", x11Key);
559}
560
561KeySym
562awt_getX11KeySym(jint awtKey)
563{
564 int32_t i;
565
566 if (awtKey == java_awt_event_KeyEvent_VK_KANA_LOCK && keyboardHasKanaLockKey()) {
567 return XK_Mode_switch;
568 }
569
570 for (i = 0; keymapTable[i].awtKey != 0; i++) {
571 if (keymapTable[i].awtKey == awtKey) {
572 return keymapTable[i].x11Key;
573 }
574 }
575
576 DTRACE_PRINTLN1("awt_getX11KeySym: no key mapping found: awtKey = %x", awtKey);
577 return NoSymbol;
578}
579
580
581typedef struct COLLAPSE_INFO {
582 Window win;
583 DamageRect *r;
584} CollapseInfo;
585
586static void
587expandDamageRect(DamageRect * drect, XEvent * xev, Boolean debug, char *str)
588{
589 int32_t x1 = xev->xexpose.x;
590 int32_t y1 = xev->xexpose.y;
591 int32_t x2 = x1 + xev->xexpose.width;
592 int32_t y2 = y1 + xev->xexpose.height;
593
594 /*
595 if (debug) {
596 printf(" %s: collapsing (%d,%d %dx%d) into (%d,%d %dx%d) ->>",
597 str, x1, y1, xev->xexpose.width, xev->xexpose.height,
598 drect->x1, drect->y1, drect->x2 - drect->x1, drect->y2 - drect->y1);
599 }
600 */
601
602 drect->x1 = MIN(x1, drect->x1);
603 drect->y1 = MIN(y1, drect->y1);
604 drect->x2 = MAX(x2, drect->x2);
605 drect->y2 = MAX(y2, drect->y2);
606
607 /*
608 if (debug) {
609 printf("(%d,%d %dx%d) %s\n",
610 drect->x1, drect->y1, drect->x2 - drect->x1, drect->y2 - drect->y1);
611 }
612 */
613
614}
615
616static Bool
617checkForExpose(Display * dpy, XEvent * evt, XPointer client_data)
618{
619 CollapseInfo *cinfo = (CollapseInfo *) client_data;
620
621 if ((evt->type == Expose && evt->xexpose.window == cinfo->win &&
622 INTERSECTS(cinfo->r->x1, cinfo->r->x2, cinfo->r->y1, cinfo->r->y2,
623 evt->xexpose.x,
624 evt->xexpose.x + evt->xexpose.width,
625 evt->xexpose.y,
626 evt->xexpose.y + evt->xexpose.height)) ||
627 (evt->type == GraphicsExpose && evt->xgraphicsexpose.drawable == cinfo->win &&
628 INTERSECTS(cinfo->r->x1, cinfo->r->x2, cinfo->r->y1, cinfo->r->y2,
629 evt->xgraphicsexpose.x,
630 evt->xgraphicsexpose.x + evt->xgraphicsexpose.width,
631 evt->xgraphicsexpose.y,
632 evt->xgraphicsexpose.y + evt->xgraphicsexpose.height))) {
633
634 return True;
635 }
636 return False;
637}
638
639/*
640 * javaObject is an MComponentPeer instance
641 */
642static void
643HandleExposeEvent(Widget w, jobject javaObject, XEvent * event)
644{
645 jobject target;
646 jint wdth, hght;
647
648 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
649
650 switch (event->type) {
651 case Expose:
652 case GraphicsExpose:
653 {
654 struct ComponentData *cdata;
655 Boolean debug = FALSE;
656 jint drawState;
657
658 /* Set the draw state */
659 drawState = (*env)->GetIntField(env, javaObject,
660 mComponentPeerIDs.drawState);
661 (*env)->SetIntField(env, javaObject, mComponentPeerIDs.drawState,
662 drawState | JAWT_LOCK_CLIP_CHANGED);
663 cdata = (struct ComponentData *)
664 JNU_GetLongFieldAsPtr(env, javaObject, mComponentPeerIDs.pData);
665 if (JNU_IsNull(env, javaObject) || (cdata == NULL)) {
666 return;
667 }
668 if (event->xexpose.send_event) {
669 if (cdata->repaintPending & RepaintPending_REPAINT) {
670 cdata->repaintPending &= ~RepaintPending_REPAINT;
671
672 JNU_CallMethodByName(env,
673 NULL,
674 javaObject,
675 "handleRepaint",
676 "(IIII)V",
677 (jint) cdata->repaintRect.x1,
678 (jint) cdata->repaintRect.y1,
679 (jint) cdata->repaintRect.x2
680 - cdata->repaintRect.x1,
681 (jint) cdata->repaintRect.y2
682 - cdata->repaintRect.y1);
683 if ((*env)->ExceptionOccurred(env)) {
684 (*env)->ExceptionDescribe(env);
685 (*env)->ExceptionClear(env);
686 }
687 }
688 return;
689 }
690 if ((cdata->repaintPending & RepaintPending_EXPOSE) == 0) {
691 cdata->exposeRect.x1 = event->xexpose.x;
692 cdata->exposeRect.y1 = event->xexpose.y;
693 cdata->exposeRect.x2 = cdata->exposeRect.x1 + event->xexpose.width;
694 cdata->exposeRect.y2 = cdata->exposeRect.y1 + event->xexpose.height;
695 cdata->repaintPending |= RepaintPending_EXPOSE;
696 } else {
697 expandDamageRect(&(cdata->exposeRect), event, debug, "1");
698 }
699
700 /* Only post Expose/Repaint if we know others arn't following
701 * directly in the queue.
702 */
703 if (event->xexpose.count == 0) {
704 int32_t count = 0;
705 CollapseInfo cinfo;
706
707 cinfo.win = XtWindow(w);
708 cinfo.r = &(cdata->exposeRect);
709
710 /* Do a little more inspecting and collapse further if there
711 * are additional expose events pending on this window where
712 * the damage rects intersect with the current exposeRect.
713 */
714 while (TRUE) {
715 XEvent xev;
716
717 if (XCheckIfEvent(XtDisplay(w), &xev
718 ,checkForExpose, (XtPointer) & cinfo)) {
719 count = xev.xexpose.count;
720 expandDamageRect(&(cdata->exposeRect), &xev, debug, "2");
721
722 } else {
723 /* XCheckIfEvent Failed. */
724 break;
725 }
726 }
727
728 cdata->repaintPending &= ~RepaintPending_EXPOSE;
729
730 /* Fix for bugtraq id 4262108. Paint events should not be
731 * delivered to components that have one of their
732 * dimensions equal to zero.
733 */
734
735 if ((*env)->EnsureLocalCapacity(env, 1) < 0) {
736 return;
737 }
738
739 target = (*env)->GetObjectField(env, javaObject,
740 mComponentPeerIDs.target);
741 wdth = (*env)->GetIntField(env, target, componentIDs.width);
742 hght = (*env)->GetIntField(env, target, componentIDs.height);
743 (*env)->DeleteLocalRef(env, target);
744
745 if ( wdth != 0 && hght != 0) {
746 JNU_CallMethodByName(env,
747 NULL,
748 javaObject,
749 "handleExpose",
750 "(IIII)V",
751 (jint) cdata->exposeRect.x1,
752 (jint) cdata->exposeRect.y1,
753 (jint) cdata->exposeRect.x2
754 - cdata->exposeRect.x1,
755 (jint) cdata->exposeRect.y2
756 - cdata->exposeRect.y1);
757 if ((*env)->ExceptionOccurred(env)) {
758 (*env)->ExceptionDescribe(env);
759 (*env)->ExceptionClear(env);
760 }
761 }
762 }
763 }
764 break;
765
766 default:
767 jio_fprintf(stderr, "Got event %d in HandleExposeEvent!\n", event->type);
768 }
769}
770
771/* We always store and return JNI GlobalRefs. */
772static jweak focusOwnerPeer = NULL;
773static jweak focusedWindowPeer = NULL;
774
775/*
776 * This function should only be called under the
777 * protection of AWT_LOCK(). Otherwise, multithreaded access
778 * can corrupt the value of focusOwnerPeer variable.
779 * This function returns LocalRef, result should be deleted
780 * explicitly if called on a thread that never returns to
781 * Java.
782 */
783jobject
784awt_canvas_getFocusOwnerPeer() {
785 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
786 jobject res;
787 AWT_LOCK();
788 res = (*env)->NewLocalRef(env, focusOwnerPeer);
789 AWT_UNLOCK();
790 return res;
791}
792
793/*
794 * This function should only be called under the
795 * protection of AWT_LOCK(). Otherwise, multithreaded access
796 * can corrupt the value of focusedWindowPeer variable.
797 * This function returns LocalRef, result should be deleted
798 * explicitly if called on a thread that never returns to
799 * Java.
800 */
801jobject
802awt_canvas_getFocusedWindowPeer() {
803 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
804 jobject res;
805 AWT_LOCK();
806 res = (*env)->NewLocalRef(env, focusedWindowPeer);
807 AWT_UNLOCK();
808 return res;
809}
810
811/*
812 * Only call this function under AWT_LOCK(). Otherwise, multithreaded
813 * access can corrupt the value of focusOwnerPeer variable.
814 */
815void
816awt_canvas_setFocusOwnerPeer(jobject peer) {
817 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
818 AWT_LOCK();
819 if (focusOwnerPeer != NULL) {
820 (*env)->DeleteWeakGlobalRef(env, focusOwnerPeer);
821 }
822 focusOwnerPeer = (peer != NULL)
823 ? (*env)->NewWeakGlobalRef(env, peer) : NULL;
824 AWT_UNLOCK();
825}
826
827/*
828 * Only call this function under AWT_LOCK(). Otherwise, multithreaded
829 * access can corrupt the value of focusedWindowPeer variable.
830 */
831void
832awt_canvas_setFocusedWindowPeer(jobject peer) {
833 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
834 AWT_LOCK();
835 if (focusedWindowPeer != NULL) {
836 (*env)->DeleteWeakGlobalRef(env, focusedWindowPeer);
837 }
838 focusedWindowPeer = (peer != NULL)
839 ? (*env)->NewWeakGlobalRef(env, peer) : NULL;
840 AWT_UNLOCK();
841}
842
843void callFocusCallback(jobject focusPeer, int focus_type, jobject cause) {
844 awt_post_java_focus_event(focusPeer,
845 focus_type,
846 cause,
847 NULL);
848 awt_canvas_setFocusOwnerPeer(focusPeer);
849}
850
851
852void
853handleFocusEvent(Widget w,
854 XFocusChangeEvent * fevent,
855 XtPointer client_data,
856 Boolean * cont,
857 Boolean passEvent,
858 jobject cause)
859{
860 if (fevent->type == FocusIn) {
861 if (fevent->mode == NotifyNormal &&
862 fevent->detail != NotifyPointer && fevent->detail != NotifyVirtual)
863 {
864#ifdef DEBUG_FOCUS
865 printf("window = %d, mode = %d, detail = %d\n", fevent->window, fevent->mode, fevent->detail);
866 printf("----posting java FOCUS GAINED on window %d, pass = %d\n", XtWindow(w), passEvent);
867#endif
868 awt_post_java_focus_event(client_data,
869 java_awt_event_FocusEvent_FOCUS_GAINED,
870 cause,
871 NULL);
872 awt_canvas_setFocusOwnerPeer(client_data);
873 }
874 } else {
875 /* FocusOut */
876 if (fevent->mode == NotifyNormal &&
877 fevent->detail != NotifyPointer && fevent->detail != NotifyVirtual)
878 {
879#ifdef DEBUG_FOCUS
880 printf("window = %d, mode = %d, detail = %d\n", fevent->window, fevent->mode, fevent->detail);
881 printf("----posting java FOCUS LOST on window %d, pass = %d, temp = %d\n", XtWindow(w), passEvent, temp);
882#endif
883 awt_post_java_focus_event(client_data,
884 java_awt_event_FocusEvent_FOCUS_LOST,
885 cause,
886 NULL);
887 awt_canvas_setFocusOwnerPeer(NULL);
888 }
889 }
890 *cont = TRUE;
891}
892
893void callFocusHandler(Widget w, int eventType, jobject cause) {
894 jobject peer = NULL;
895 XFocusChangeEvent event;
896 Boolean cont;
897 JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
898
899 if (w == NULL) {
900 return;
901 }
902
903 peer = findPeer(&w);
904 if (peer == NULL) {
905 w = findTopLevelByShell(w);
906 if (w != NULL) {
907 peer = findPeer(&w);
908 }
909 }
910 if (peer == NULL) {
911 return;
912 }
913 memset(&event, 0, sizeof(event));
914 event.type = eventType;
915 event.mode = NotifyNormal;
916 event.detail = NotifyAncestor;
917 event.window = XtWindow(w);
918 cont = FALSE;
919 handleFocusEvent(w, &event, (XtPointer)peer, &cont, TRUE, cause);
920}
921
922/**
923 * Copy XEvent to jbyteArray and save it in AWTEvent
924 */
925void
926awt_copyXEventToAWTEvent(JNIEnv *env, XEvent * xev, jobject jevent)
927{
928 jbyteArray bdata;
929 if (xev != NULL) {
930 if ((*env)->EnsureLocalCapacity(env, 1) < 0) {
931 return;
932 }
933 bdata = (*env)->NewByteArray(env, sizeof(XEvent));
934 if (bdata != NULL) {
935 (*env)->SetByteArrayRegion(env, bdata, 0, sizeof(XEvent),
936 (jbyte *)xev);
937 (*env)->SetObjectField(env, jevent, awtEventIDs.bdata, bdata);
938 (*env)->DeleteLocalRef(env, bdata);
939 }
940 }
941}
942
943/* Returns new modifiers set like ???_DOWN_MASK for keyboard and mouse after the event.
944 * The modifiers on a Java key event reflect the state of the modifier keys
945 * immediately AFTER the key press or release. This usually doesn't require
946 * us to change the modifiers: the exception is when the key pressed or
947 * released is a modifier key. Since the state of an XEvent represents
948 * the modifiers BEFORE the event, we change the modifiers according to
949 * the button and keycode.
950 */
951jint
952getModifiers(uint32_t state, jint button, jint keyCode)
953{
954 jint modifiers = 0;
955
956 if (((state & ShiftMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_SHIFT))
957 {
958 modifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK;
959 }
960 if (((state & ControlMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_CONTROL))
961 {
962 modifiers |= java_awt_event_InputEvent_CTRL_DOWN_MASK;
963 }
964 if (((state & awt_MetaMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_META))
965 {
966 modifiers |= java_awt_event_InputEvent_META_DOWN_MASK;
967 }
968 if (((state & awt_AltMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_ALT))
969 {
970 modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK;
971 }
972 if (((state & awt_ModeSwitchMask) != 0) ^ (keyCode == java_awt_event_KeyEvent_VK_ALT_GRAPH))
973 {
974 modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK;
975 }
976 if (((state & Button1Mask) != 0) ^ (button == java_awt_event_MouseEvent_BUTTON1)) {
977 modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK;
978 }
979 if (((state & Button2Mask) != 0) ^ (button == java_awt_event_MouseEvent_BUTTON2)) {
980 modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK;
981 }
982 if (((state & Button3Mask) != 0) ^ (button == java_awt_event_MouseEvent_BUTTON3)) {
983 modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK;
984 }
985 return modifiers;
986}
987
988/* Returns which mouse button has changed state
989 */
990jint
991getButton(uint32_t button)
992{
993 switch (button) {
994 case Button1:
995 return java_awt_event_MouseEvent_BUTTON1;
996 case Button2:
997 return java_awt_event_MouseEvent_BUTTON2;
998 case Button3:
999 return java_awt_event_MouseEvent_BUTTON3;
1000 }
1001 return java_awt_event_MouseEvent_NOBUTTON;
1002}
1003
1004
1005/* This function changes the state of the native XEvent AFTER
1006 * the corresponding Java event has been processed. The XEvent
1007 * needs to be modified before it is dispatched to the native widget.
1008 */
1009void
1010awt_modify_KeyEvent(JNIEnv *env, XEvent *xevent, jobject jevent)
1011{
1012 jint keyCode;
1013 jchar keyChar;
1014 jint modifiers;
1015 KeySym keysym = (KeySym) java_awt_event_KeyEvent_CHAR_UNDEFINED;
1016
1017 if (xevent->type != KeyPress && xevent->type != KeyRelease) {
1018 return;
1019 }
1020
1021 keyCode = (*env)->GetIntField(env, jevent, keyEventIDs.keyCode);
1022 keyChar = (*env)->GetCharField(env, jevent, keyEventIDs.keyChar);
1023 modifiers = (*env)->GetIntField(env, jevent, inputEventIDs.modifiers);
1024
1025 switch (keyCode) {
1026 case java_awt_event_KeyEvent_VK_MULTIPLY:
1027 case java_awt_event_KeyEvent_VK_SUBTRACT:
1028 case java_awt_event_KeyEvent_VK_DIVIDE:
1029 /* Bugid 4103229: Change the X event so these three Numpad
1030 * keys work with the NumLock off. For some reason, Motif
1031 * widgets ignore the events produced by these three keys
1032 * unless the NumLock is on. It also ignores them if some
1033 * other modifiers are set. Turn off ALL modifiers, then
1034 * turn NumLock mask on in the X event.
1035 */
1036 xevent->xkey.state = awt_NumLockMask;
1037 return;
1038 case java_awt_event_KeyEvent_VK_ENTER:
1039 case java_awt_event_KeyEvent_VK_BACK_SPACE:
1040 case java_awt_event_KeyEvent_VK_TAB:
1041 case java_awt_event_KeyEvent_VK_ESCAPE:
1042 case java_awt_event_KeyEvent_VK_ADD:
1043 case java_awt_event_KeyEvent_VK_DECIMAL:
1044 case java_awt_event_KeyEvent_VK_NUMPAD0:
1045 case java_awt_event_KeyEvent_VK_NUMPAD1:
1046 case java_awt_event_KeyEvent_VK_NUMPAD2:
1047 case java_awt_event_KeyEvent_VK_NUMPAD3:
1048 case java_awt_event_KeyEvent_VK_NUMPAD4:
1049 case java_awt_event_KeyEvent_VK_NUMPAD5:
1050 case java_awt_event_KeyEvent_VK_NUMPAD6:
1051 case java_awt_event_KeyEvent_VK_NUMPAD7:
1052 case java_awt_event_KeyEvent_VK_NUMPAD8:
1053 case java_awt_event_KeyEvent_VK_NUMPAD9:
1054 keysym = awt_getX11KeySym(keyCode);
1055 break;
1056 case java_awt_event_KeyEvent_VK_DELETE:
1057 /* For some reason XKeysymToKeycode returns incorrect value for
1058 * Delete, so we don't want to modify the original event
1059 */
1060 break;
1061 default:
1062 if (keyChar < (KeySym) 256) {
1063 keysym = (KeySym) keyChar;
1064 } else {
1065 keysym = awt_getX11KeySym(keyCode);
1066 }
1067 break;
1068 }
1069
1070 if (keysym < (KeySym) 256) {
1071 if (modifiers & java_awt_event_InputEvent_CTRL_MASK) {
1072 switch (keysym + 64) {
1073 case '[':
1074 case ']':
1075 case '\\':
1076 case '_':
1077 keysym += 64;
1078 break;
1079 default:
1080 if (isalpha((int32_t)(keysym + 'a' - 1))) {
1081 keysym += ('a' - 1);
1082 }
1083 break;
1084 }
1085 }
1086 /*
1087 * 0xff61 is Unicode value of first XK_kana_fullstop.
1088 * We need X Keysym to Unicode map in post1.1 release
1089 * to support more international keyboards.
1090 */
1091 if (keysym >= (KeySym) 0xff61 && keysym <= (KeySym) 0xff9f) {
1092 keysym = keysym - 0xff61 + XK_kana_fullstop;
1093 }
1094 xevent->xkey.keycode = XKeysymToKeycode(awt_display, keysym);
1095 }
1096
1097 if (keysym >= 'A' && keysym <= 'Z') {
1098 xevent->xkey.state |= ShiftMask;
1099 }
1100 if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
1101 xevent->xkey.state |= ShiftMask;
1102 }
1103 if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
1104 xevent->xkey.state |= ControlMask;
1105 }
1106 if (modifiers & java_awt_event_InputEvent_META_DOWN_MASK) {
1107 xevent->xkey.state |= awt_MetaMask;
1108 }
1109 if (modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) {
1110 xevent->xkey.state |= awt_AltMask;
1111 }
1112 if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
1113 xevent->xkey.state |= awt_ModeSwitchMask;
1114 }
1115 if (modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
1116 xevent->xkey.state |= Button1Mask;
1117 }
1118 if (modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) {
1119 xevent->xkey.state |= Button2Mask;
1120 }
1121 if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) {
1122 xevent->xkey.state |= Button3Mask;
1123 }
1124}
1125
1126
1127/* Called from handleKeyEvent. The purpose of this function is
1128 * to check for a list of vendor-specific keysyms, most of which
1129 * have values greater than 0xFFFF. Most of these keys don't map
1130 * to unicode characters, but some do.
1131 *
1132 * For keys that don't map to unicode characters, the keysym
1133 * is irrelevant at this point. We set the keysym to zero
1134 * to ensure that the switch statement immediately below
1135 * this function call (in adjustKeySym) won't incorrectly act
1136 * on them after the high bits are stripped off.
1137 *
1138 * For keys that do map to unicode characters, we change the keysym
1139 * to the equivalent that is < 0xFFFF
1140 */
1141static void
1142handleVendorKeySyms(XEvent *event, KeySym *keysym)
1143{
1144 KeySym originalKeysym = *keysym;
1145
1146 switch (*keysym) {
1147 /* Apollo (HP) vendor-specific from <X11/ap_keysym.h> */
1148 case apXK_Copy:
1149 case apXK_Cut:
1150 case apXK_Paste:
1151 /* DEC vendor-specific from <X11/DECkeysym.h> */
1152 case DXK_ring_accent: /* syn usldead_ring */
1153 case DXK_circumflex_accent:
1154 case DXK_cedilla_accent: /* syn usldead_cedilla */
1155 case DXK_acute_accent:
1156 case DXK_grave_accent:
1157 case DXK_tilde:
1158 case DXK_diaeresis:
1159 /* Sun vendor-specific from <X11/Sunkeysym.h> */
1160 case SunXK_FA_Grave:
1161 case SunXK_FA_Circum:
1162 case SunXK_FA_Tilde:
1163 case SunXK_FA_Acute:
1164 case SunXK_FA_Diaeresis:
1165 case SunXK_FA_Cedilla:
1166 case SunXK_F36: /* Labeled F11 */
1167 case SunXK_F37: /* Labeled F12 */
1168 case SunXK_Props:
1169 case SunXK_Copy:
1170 case SunXK_Open:
1171 case SunXK_Paste:
1172 case SunXK_Cut:
1173 /* Other vendor-specific from HPkeysym.h */
1174 case hpXK_mute_acute: /* syn usldead_acute */
1175 case hpXK_mute_grave: /* syn usldead_grave */
1176 case hpXK_mute_asciicircum: /* syn usldead_asciicircum */
1177 case hpXK_mute_diaeresis: /* syn usldead_diaeresis */
1178 case hpXK_mute_asciitilde: /* syn usldead_asciitilde */
1179 case osfXK_Copy:
1180 case osfXK_Cut:
1181 case osfXK_Paste:
1182 case osfXK_PageUp:
1183 case osfXK_PageDown:
1184 case osfXK_EndLine:
1185 case osfXK_Clear:
1186 case osfXK_Left:
1187 case osfXK_Up:
1188 case osfXK_Right:
1189 case osfXK_Down:
1190 case osfXK_Prior:
1191 case osfXK_Next:
1192 case osfXK_Insert:
1193 case osfXK_Undo:
1194 case osfXK_Help:
1195 *keysym = 0;
1196 break;
1197 /*
1198 * The rest DO map to unicode characters, so translate them
1199 */
1200 case osfXK_BackSpace:
1201 *keysym = XK_BackSpace;
1202 break;
1203 case osfXK_Escape:
1204 *keysym = XK_Escape;
1205 break;
1206 case osfXK_Cancel:
1207 *keysym = XK_Cancel;
1208 break;
1209 case osfXK_Delete:
1210 *keysym = XK_Delete;
1211 break;
1212 default:
1213 break;
1214 }
1215
1216 if (originalKeysym != *keysym) {
1217 DTRACE_PRINTLN2("In handleVendorKeySyms: originalKeysym=%x, keysym=%x",
1218 originalKeysym, *keysym);
1219 }
1220}
1221
1222/* Called from handleKeyEvent.
1223 * The purpose of this function is to adjust the keysym and XEvent
1224 * keycode for a key event. This is basically a conglomeration of
1225 * bugfixes that require these adjustments.
1226 */
1227static void
1228adjustKeySym(XEvent *event, KeySym *keysym)
1229{
1230 KeySym originalKeysym = *keysym;
1231
1232 /* We have seen bits set in the high two bytes on Linux,
1233 * which prevents this switch statement from executing
1234 * correctly. Strip off the high order bits.
1235 */
1236 *keysym &= 0x0000FFFF;
1237
1238 switch (*keysym) {
1239 case XK_Return:
1240 *keysym = XK_Linefeed; /* fall thru */
1241 case XK_BackSpace:
1242 case XK_Tab:
1243 case XK_Linefeed:
1244 case XK_Escape:
1245 case XK_Delete:
1246 /* strip off highorder bits defined in keysymdef.h
1247 * I think doing this converts them to values that
1248 * we can cast to jchars and use as java keychars.
1249 * If so, it's really a hack.
1250 */
1251 *keysym &= 0x007F;
1252 break;
1253 case XK_Cancel:
1254 *keysym = 0x0018; /* the unicode char for Cancel */
1255 break;
1256 case XK_KP_Decimal:
1257 *keysym = '.';
1258 break;
1259 case XK_KP_Add:
1260 *keysym = '+';
1261 break;
1262 case XK_F24: /* NumLock off */
1263 case XK_KP_Subtract: /* NumLock on */
1264 *keysym = '-';
1265 break;
1266 case XK_F25: /* NumLock off */
1267 case XK_KP_Divide: /* NumLock on */
1268 *keysym = '/';
1269 break;
1270 case XK_F26: /* NumLock off */
1271 case XK_KP_Multiply: /* NumLock on */
1272 *keysym = '*';
1273 break;
1274 case XK_KP_Equal:
1275 *keysym = '=';
1276 break;
1277 case XK_KP_0:
1278 *keysym = '0';
1279 break;
1280 case XK_KP_1:
1281 *keysym = '1';
1282 break;
1283 case XK_KP_2:
1284 *keysym = '2';
1285 break;
1286 case XK_KP_3:
1287 *keysym = '3';
1288 break;
1289 case XK_KP_4:
1290 *keysym = '4';
1291 break;
1292 case XK_KP_5:
1293 *keysym = '5';
1294 break;
1295 case XK_KP_6:
1296 *keysym = '6';
1297 break;
1298 case XK_KP_7:
1299 *keysym = '7';
1300 break;
1301 case XK_KP_8:
1302 *keysym = '8';
1303 break;
1304 case XK_KP_9:
1305 *keysym = '9';
1306 break;
1307 case XK_KP_Left: /* Bug 4350175 */
1308 *keysym = XK_Left;
1309 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1310 break;
1311 case XK_KP_Up:
1312 *keysym = XK_Up;
1313 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1314 break;
1315 case XK_KP_Right:
1316 *keysym = XK_Right;
1317 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1318 break;
1319 case XK_KP_Down:
1320 *keysym = XK_Down;
1321 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1322 break;
1323 case XK_KP_Home:
1324 *keysym = XK_Home;
1325 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1326 break;
1327 case XK_KP_End:
1328 *keysym = XK_End;
1329 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1330 break;
1331 case XK_KP_Page_Up:
1332 *keysym = XK_Page_Up;
1333 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1334 break;
1335 case XK_KP_Page_Down:
1336 *keysym = XK_Page_Down;
1337 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1338 break;
1339 case XK_KP_Begin:
1340 *keysym = XK_Begin;
1341 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1342 break;
1343 case XK_KP_Insert:
1344 *keysym = XK_Insert;
1345 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1346 break;
1347 case XK_KP_Delete:
1348 *keysym = XK_Delete;
1349 event->xkey.keycode = XKeysymToKeycode(awt_display, *keysym);
1350 *keysym &= 0x007F;
1351 break;
1352 case XK_KP_Enter:
1353 *keysym = XK_Linefeed;
1354 event->xkey.keycode = XKeysymToKeycode(awt_display, XK_Return);
1355 *keysym &= 0x007F;
1356 break;
1357 default:
1358 break;
1359 }
1360
1361 if (originalKeysym != *keysym) {
1362 DTRACE_PRINTLN2("In adjustKeySym: originalKeysym=%x, keysym=%x",
1363 originalKeysym, *keysym);
1364 }
1365}
1366
1367/*
1368 * What a sniffer sez?
1369 * Xsun and Xorg if NumLock is on do two thing different:
1370 * keep Keypad key in different places of keysyms array and
1371 * ignore/obey "ModLock is ShiftLock", so we should choose.
1372 * People say, it's right to use behavior and not Vendor tags to decide.
1373 * Maybe. But why these tags were invented, then?
1374 * TODO: use behavior, not tags. Maybe.
1375 */
1376static Boolean
1377isXsunServer(XEvent *event) {
1378 if( awt_ServerDetected ) return awt_IsXsun;
1379 if( strncmp( ServerVendor( event->xkey.display ), "Sun Microsystems, Inc.", 32) ) {
1380 awt_ServerDetected = True;
1381 awt_IsXsun = False;
1382 return False;
1383 }
1384 // Now, it's Sun. It still may be Xorg though, eg on Solaris 10, x86.
1385 // Today (2005), VendorRelease of Xorg is a Big Number unlike Xsun.
1386 if( VendorRelease( event->xkey.display ) > 10000 ) {
1387 awt_ServerDetected = True;
1388 awt_IsXsun = False;
1389 return False;
1390 }
1391 awt_ServerDetected = True;
1392 awt_IsXsun = True;
1393 return True;
1394}
1395static Boolean
1396isKPevent(XEvent *event)
1397{
1398 /*
1399 Xlib manual, ch 12.7 says, as a first rule for choice of keysym:
1400 The numlock modifier is on and the second KeySym is a keypad KeySym. In this case,
1401 if the Shift modifier is on, or if the Lock modifier is on and is interpreted as ShiftLock,
1402 then the first KeySym is used, otherwise the second KeySym is used.
1403
1404 However, Xsun server does ignore ShiftLock and always takes 3-rd element from an array.
1405
1406 So, is it a keypad keysym?
1407 */
1408 jint mods = getModifiers(event->xkey.state, 0, event->xkey.keycode);
1409 Boolean bsun = isXsunServer( event );
1410
1411 return IsKeypadKey( XKeycodeToKeysym(event->xkey.display, event->xkey.keycode,(bsun && !awt_UseXKB ? 2 : 1) ) );
1412}
1413/*
1414 * In a next redesign, get rid of this code altogether.
1415 *
1416 */
1417static void
1418handleKeyEventWithNumLockMask_New(XEvent *event, KeySym *keysym)
1419{
1420 KeySym originalKeysym = *keysym;
1421 if( !isKPevent( event ) ) {
1422 return;
1423 }
1424 if( isXsunServer( event ) && !awt_UseXKB ) {
1425 if( (event->xkey.state & ShiftMask) ) { // shift modifier is on
1426 *keysym = XKeycodeToKeysym(event->xkey.display,
1427 event->xkey.keycode, 3);
1428 }else {
1429 *keysym = XKeycodeToKeysym(event->xkey.display,
1430 event->xkey.keycode, 2);
1431 }
1432 } else {
1433 if( (event->xkey.state & ShiftMask) || // shift modifier is on
1434 ((event->xkey.state & LockMask) && // lock modifier is on
1435 (awt_ModLockIsShiftLock)) ) { // it is interpreted as ShiftLock
1436 *keysym = XKeycodeToKeysym(event->xkey.display,
1437 event->xkey.keycode, 0);
1438 }else{
1439 *keysym = XKeycodeToKeysym(event->xkey.display,
1440 event->xkey.keycode, 1);
1441 }
1442 }
1443}
1444
1445/* Called from handleKeyEvent.
1446 * The purpose of this function is to make some adjustments to keysyms
1447 * that have been found to be necessary when the NumLock mask is set.
1448 * They come from various bug fixes and rearchitectures.
1449 * This function is meant to be called when
1450 * (event->xkey.state & awt_NumLockMask) is TRUE.
1451 */
1452static void
1453handleKeyEventWithNumLockMask(XEvent *event, KeySym *keysym)
1454{
1455 KeySym originalKeysym = *keysym;
1456
1457#ifndef __linux__
1458 /* The following code on Linux will cause the keypad keys
1459 * not to echo on JTextField when the NumLock is on. The
1460 * keysyms will be 0, because the last parameter 2 is not defined.
1461 * See Xlib Programming Manual, O'Reilly & Associates, Section
1462 * 9.1.5 "Other Keyboard-handling Routines", "The meaning of
1463 * the keysym list beyond the first two (unmodified, Shift or
1464 * Shift Lock) is not defined."
1465 */
1466
1467 /* Translate again with NumLock as modifier. */
1468 /* ECH - I wonder why we think that NumLock corresponds to 2?
1469 * On Linux, we've seen xmodmap -pm yield mod2 as NumLock,
1470 * but I don't know that it will be for every configuration.
1471 * Perhaps using the index (modn in awt_MToolkit.c:setup_modifier_map)
1472 * would be more correct.
1473 */
1474 *keysym = XKeycodeToKeysym(event->xkey.display,
1475 event->xkey.keycode, 2);
1476 if (originalKeysym != *keysym) {
1477 DTRACE_PRINTLN3("%s=%x, keysym=%x",
1478 "In handleKeyEventWithNumLockMask ifndef linux: originalKeysym",
1479 originalKeysym, *keysym);
1480 }
1481#endif
1482
1483 /* Note: the XK_R? key assignments are for Type 4 kbds */
1484 switch (*keysym) {
1485 case XK_R13:
1486 *keysym = XK_KP_1;
1487 break;
1488 case XK_R14:
1489 *keysym = XK_KP_2;
1490 break;
1491 case XK_R15:
1492 *keysym = XK_KP_3;
1493 break;
1494 case XK_R10:
1495 *keysym = XK_KP_4;
1496 break;
1497 case XK_R11:
1498 *keysym = XK_KP_5;
1499 break;
1500 case XK_R12:
1501 *keysym = XK_KP_6;
1502 break;
1503 case XK_R7:
1504 *keysym = XK_KP_7;
1505 break;
1506 case XK_R8:
1507 *keysym = XK_KP_8;
1508 break;
1509 case XK_R9:
1510 *keysym = XK_KP_9;
1511 break;
1512 case XK_KP_Insert:
1513 *keysym = XK_KP_0;
1514 break;
1515 case XK_KP_Delete:
1516 *keysym = XK_KP_Decimal;
1517 break;
1518 case XK_R4:
1519 *keysym = XK_KP_Equal; /* Type 4 kbd */
1520 break;
1521 case XK_R5:
1522 *keysym = XK_KP_Divide;
1523 break;
1524 case XK_R6:
1525 *keysym = XK_KP_Multiply;
1526 break;
1527 /*
1528 * Need the following keysym changes for Linux key releases.
1529 * Sometimes the modifier state gets messed up, so we get a
1530 * KP_Left when we should get a KP_4, for example.
1531 * XK_KP_Insert and XK_KP_Delete were already handled above.
1532 */
1533 case XK_KP_Left:
1534 *keysym = XK_KP_4;
1535 break;
1536 case XK_KP_Up:
1537 *keysym = XK_KP_8;
1538 break;
1539 case XK_KP_Right:
1540 *keysym = XK_KP_6;
1541 break;
1542 case XK_KP_Down:
1543 *keysym = XK_KP_2;
1544 break;
1545 case XK_KP_Home:
1546 *keysym = XK_KP_7;
1547 break;
1548 case XK_KP_End:
1549 *keysym = XK_KP_1;
1550 break;
1551 case XK_KP_Page_Up:
1552 *keysym = XK_KP_9;
1553 break;
1554 case XK_KP_Page_Down:
1555 *keysym = XK_KP_3;
1556 break;
1557 case XK_KP_Begin:
1558 *keysym = XK_KP_5;
1559 break;
1560 default:
1561 break;
1562 }
1563
1564 if (originalKeysym != *keysym) {
1565 DTRACE_PRINTLN2("In handleKeyEventWithNumLockMask: originalKeysym=%x, keysym=%x",
1566 originalKeysym, *keysym);
1567 }
1568}
1569
1570static void
1571handleKeyEvent(jint keyEventId,
1572 XEvent *event,
1573 XtPointer *client_data,
1574 Boolean *cont,
1575 Boolean passEvent)
1576{
1577 KeySym keysym = NoSymbol;
1578 jint keycode = java_awt_event_KeyEvent_VK_UNDEFINED;
1579 Modifiers mods = 0;
1580 Boolean mapsToUnicodeChar = FALSE;
1581 jint keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
1582 jint modifiers = 0;
1583
1584 DTRACE_PRINTLN4("\nEntered handleKeyEvent: type=%d, xkeycode=%x, xstate=%x, keysym=%x",
1585 event->type, event->xkey.keycode, event->xkey.state, keysym);
1586
1587 if (currentX11InputMethodInstance != NULL
1588 && keyEventId == java_awt_event_KeyEvent_KEY_PRESSED
1589 && event->xkey.window == currentFocusWindow)
1590 {
1591 /* invokes XmbLookupString to get a committed string or keysym if any. */
1592 if (awt_x11inputmethod_lookupString((XKeyPressedEvent*)event, &keysym)) {
1593 *cont = FALSE;
1594 return;
1595 }
1596 }
1597
1598 /* Ignore the keysym found immediately above in
1599 * awt_x11inputmethod_lookupString; the methodology in that function
1600 * sometimes returns incorrect results.
1601 *
1602 * Get keysym without taking modifiers into account first.
1603 * This keysym is not necessarily for the character that was typed:
1604 * it is for the primary layer. So, if $ were typed by pressing
1605 * shift-4, this call should give us 4, not $
1606 *
1607 * We only want this keysym so we can use it to index into the
1608 * keymapTable to get the Java keycode associated with the
1609 * primary layer key that was pressed.
1610 */
1611 keysym = XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 0);
1612
1613 /* Linux: Sometimes the keysym returned is uppercase when CapsLock is
1614 * on and LockMask is not set in event->xkey.state.
1615 */
1616 if (keysym >= (KeySym) 'A' && keysym <= (KeySym) 'Z') {
1617 event->xkey.state |= LockMask;
1618 keysym = (KeySym) tolower((int32_t) keysym);
1619 }
1620
1621 DTRACE_PRINTLN4("In handleKeyEvent: type=%d, xkeycode=%x, xstate=%x, keysym=%x",
1622 event->type, event->xkey.keycode, event->xkey.state, keysym);
1623
1624 if (keysym == NoSymbol) {
1625 *cont = TRUE;
1626 return;
1627 }
1628
1629 if (keysym < (KeySym) 256) {
1630 keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation);
1631
1632 /* Now get real keysym which looks at modifiers
1633 * XtGetActionKeySym() returns wrong value with Kana Lock,
1634 * so use XtTranslateKeycode().
1635 */
1636 XtTranslateKeycode(event->xkey.display, (KeyCode) event->xkey.keycode,
1637 event->xkey.state, &mods, &keysym);
1638 DTRACE_PRINTLN6("%s: type=%d, xkeycode=%x, xstate=%x, keysym=%x, xmods=%d",
1639 "In handleKeyEvent keysym<256 ", event->type, event->xkey.keycode,
1640 event->xkey.state, keysym, mods);
1641
1642 /* Linux: With caps lock on, chars echo lowercase. */
1643 if ((event->xkey.state & LockMask) &&
1644 (keysym >= (KeySym) 'a' && keysym <= (KeySym) 'z'))
1645 {
1646 keysym = (KeySym) toupper((int32_t) keysym);
1647 }
1648
1649 if ((event->xkey.state & ControlMask)) {
1650 switch (keysym) {
1651 case '[':
1652 case ']':
1653 case '\\':
1654 case '_':
1655 keysym -= 64;
1656 break;
1657 default:
1658 if (isalpha((int32_t) keysym)) {
1659 keysym = (KeySym) tolower((int32_t) keysym) - 'a' + 1;
1660 }
1661 break;
1662 }
1663 }
1664
1665 if (keysym >= (KeySym) XK_kana_fullstop &&
1666 keysym <= (KeySym) XK_semivoicedsound) {
1667 /*
1668 * 0xff61 is Unicode value of first XK_kana_fullstop.
1669 * We need X Keysym to Unicode map in post1.1 release
1670 * to support more intenational keyboard.
1671 */
1672 keysym = keysym - XK_kana_fullstop + 0xff61;
1673 }
1674
1675 modifiers = getModifiers(event->xkey.state, 0, keycode);
1676 DTRACE_PRINTLN6("%s: type=%d, xkeycode=%x, xstate=%x, keysym=%x, AWTmodifiers=%d",
1677 "In handleKeyEvent keysym<256 ", event->type, event->xkey.keycode,
1678 event->xkey.state, keysym, modifiers);
1679
1680 awt_post_java_key_event(client_data,
1681 keyEventId,
1682 (passEvent == TRUE) ? event : NULL,
1683 event->xkey.time,
1684 keycode,
1685 (jchar) keysym,
1686 modifiers,
1687 keyLocation,
1688 event);
1689
1690 if (keyEventId == java_awt_event_KeyEvent_KEY_PRESSED) {
1691 awt_post_java_key_event(client_data,
1692 java_awt_event_KeyEvent_KEY_TYPED,
1693 NULL,
1694 event->xkey.time,
1695 java_awt_event_KeyEvent_VK_UNDEFINED,
1696 (jchar) keysym,
1697 modifiers,
1698 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN,
1699 event);
1700
1701 }
1702 } else {
1703 if (event->xkey.state & awt_NumLockMask) {
1704 if( awt_UseType4Patch ) {
1705 handleKeyEventWithNumLockMask(event, &keysym);
1706 }else{
1707 handleKeyEventWithNumLockMask_New(event, &keysym);
1708 }
1709 }
1710
1711 if (keysym == XK_ISO_Left_Tab) {
1712 keysym = XK_Tab;
1713 }
1714
1715 /* The keysym here does not consider modifiers, so these results
1716 * are relevant to the KEY_PRESSED event only, not the KEY_TYPED
1717 */
1718 keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation);
1719 DTRACE_PRINTLN3("In handleKeyEvent: keysym=%x, AWTkeycode=%x, mapsToUnicodeChar=%d",
1720 keysym, keycode, mapsToUnicodeChar);
1721
1722 if (keycode == java_awt_event_KeyEvent_VK_UNDEFINED) {
1723 *cont = TRUE;
1724 return;
1725 }
1726
1727 /* Need to take care of keysyms > 0xFFFF here
1728 * Most of these keys don't map to unicode characters, but some do.
1729 *
1730 * For keys that don't map to unicode characters, the keysym
1731 * is irrelevant at this point. We set the keysym to zero
1732 * to ensure that the switch statement immediately below
1733 * this function call (in adjustKeySym) won't incorrectly act
1734 * on them after the high bits are stripped off.
1735 *
1736 * For keys that do map to unicode characters, we change the keysym
1737 * to the equivalent that is < 0xFFFF
1738 */
1739 handleVendorKeySyms(event, &keysym);
1740
1741 /* This function is a conglomeration of bug fixes that adjust
1742 * the keysym and XEvent keycode for this key event.
1743 */
1744 adjustKeySym(event, &keysym);
1745
1746 modifiers = getModifiers(event->xkey.state, 0, keycode);
1747
1748 DTRACE_PRINTLN6("%s: type=%d, xkeycode=%x, xstate=%x, keysym=%x, xmods=%d",
1749 "In handleKeyEvent keysym>=256 ", event->type, event->xkey.keycode,
1750 event->xkey.state, keysym, mods);
1751 DTRACE_PRINTLN2(" AWTkeycode=%x, AWTmodifiers=%d",
1752 keycode, modifiers);
1753
1754 awt_post_java_key_event(client_data,
1755 keyEventId,
1756 (passEvent == TRUE) ? event : NULL,
1757 event->xkey.time,
1758 keycode,
1759 (jchar) (mapsToUnicodeChar ? keysym :
1760 java_awt_event_KeyEvent_CHAR_UNDEFINED),
1761 modifiers,
1762 keyLocation,
1763 event);
1764
1765 /* If this was a keyPressed event, we may need to post a
1766 * keyTyped event, too. Otherwise, return.
1767 */
1768 if (keyEventId == java_awt_event_KeyEvent_KEY_RELEASED) {
1769 return;
1770 }
1771 DTRACE_PRINTLN("This is a keyPressed event");
1772
1773 /* XtTranslateKeycode seems to return slightly bogus values for the
1774 * Escape key (keysym==1004ff69==osfXK_Cancel, xmods=2) on Solaris,
1775 * so we just create the KEY_TYPED as a special case for Escape here.
1776 * (Linux works fine, and this was also okay running under VNC.)
1777 */
1778 if (keycode == java_awt_event_KeyEvent_VK_ESCAPE) {
1779 awt_post_java_key_event(client_data,
1780 java_awt_event_KeyEvent_KEY_TYPED,
1781 NULL,
1782 event->xkey.time,
1783 java_awt_event_KeyEvent_VK_UNDEFINED,
1784 (jchar) keysym,
1785 modifiers,
1786 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN,
1787 event);
1788
1789 DTRACE_PRINTLN("Posted a keyTyped event for VK_ESCAPE");
1790 return;
1791 }
1792
1793 /* Now get real keysym which looks at modifiers for keyTyped event.
1794 * XtGetActionKeySym() returns wrong value with Kana Lock,
1795 * so use XtTranslateKeycode().
1796 */
1797 XtTranslateKeycode(event->xkey.display, (KeyCode) event->xkey.keycode,
1798 event->xkey.state, &mods, &keysym);
1799 DTRACE_PRINTLN6("%s: type=%d, xkeycode=%x, xstate=%x, keysym=%x, xmods=%d",
1800 "In handleKeyEvent keysym>=256 ", event->type, event->xkey.keycode,
1801 event->xkey.state, keysym, mods);
1802
1803 if (keysym == NoSymbol) {
1804 return;
1805 }
1806
1807 if (event->xkey.state & awt_NumLockMask) {
1808 if( awt_UseType4Patch ) {
1809 handleKeyEventWithNumLockMask(event, &keysym);
1810 }else{
1811 handleKeyEventWithNumLockMask_New(event, &keysym);
1812 }
1813 }
1814
1815 if (keysym == XK_ISO_Left_Tab) {
1816 keysym = XK_Tab;
1817 }
1818
1819 /* Map the real keysym to a Java keycode */
1820 keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation);
1821 DTRACE_PRINTLN3("In handleKeyEvent: keysym=%x, AWTkeycode=%x, mapsToUnicodeChar=%d",
1822 keysym, keycode, mapsToUnicodeChar);
1823
1824 /* If it doesn't map to a Unicode character, don't post a keyTyped event */
1825 if (!mapsToUnicodeChar) {
1826 return;
1827 }
1828
1829 handleVendorKeySyms(event, &keysym);
1830 adjustKeySym(event, &keysym);
1831 DTRACE_PRINT4("In handleKeyEvent: type=%d, xkeycode=%x, xstate=%x, keysym=%x",
1832 event->type, event->xkey.keycode, event->xkey.state, keysym);
1833 DTRACE_PRINTLN2(", AWTkeycode=%x, AWTmodifiers=%d", keycode, modifiers);
1834
1835 awt_post_java_key_event(client_data,
1836 java_awt_event_KeyEvent_KEY_TYPED,
1837 NULL,
1838 event->xkey.time,
1839 java_awt_event_KeyEvent_VK_UNDEFINED,
1840 (jchar) keysym,
1841 modifiers,
1842 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN,
1843 event);
1844 }
1845}
1846
1847
1848static void
1849translateXY(Widget w, jint *xp, jint *yp)
1850{
1851 Position wx, wy;
1852
1853 XtVaGetValues(w, XmNx, &wx, XmNy, &wy, NULL);
1854 *xp += wx;
1855 *yp += wy;
1856}
1857
1858
1859/*
1860 * Part fix for bug id 4017222. Return the root widget of the Widget parameter.
1861 */
1862Widget
1863getRootWidget(Widget w) {
1864 if(!w) return NULL;
1865
1866 if(XtParent(w))
1867 return getRootWidget(XtParent(w));
1868 else
1869 return w;
1870}
1871
1872#define ABS(x) ((x) < 0 ? -(x) : (x))
1873
1874/* This proc is the major AWT engine for processing X events
1875 * for Java components and is the proc responsible for taking
1876 * X events and posting their corresponding Java event to the
1877 * AWT EventQueue. It is set up to be called both from an Xt
1878 * event handler and directly from MToolkit.c:shouldDispatchToWidget().
1879 * For the latter case, the "passEvent" parameter will be true,
1880 * which means that the event is being posted on the Java queue
1881 * BEFORE it is being passed to Xt and so a copy of the X event
1882 * must be stored within the Java event structure so it can be
1883 * dispatched to Xt later on.
1884 */
1885void
1886awt_canvas_handleEvent(Widget w, XtPointer client_data,
1887 XEvent * event, struct WidgetInfo *winfo,
1888 Boolean * cont, Boolean passEvent)
1889{
1890 static jint clickCount = 1;
1891 static XtPointer lastPeer = NULL;
1892 static Time lastTime = 0;
1893 static jint lastx = 0;
1894 static jint lasty = 0;
1895 static int32_t rbutton = 0;
1896 static int32_t lastButton = 0;
1897 Boolean popupTrigger;
1898 jint x, y;
1899 jint modifiers = 0;
1900 jint button = java_awt_event_MouseEvent_NOBUTTON;
1901 uint32_t fullRelease = 0;
1902 WidgetClass wclass = NULL;
1903
1904 /* Any event handlers which take peer instance pointers as
1905 * client_data should check to ensure the widget has not been
1906 * marked as destroyed as a result of a dispose() call on the peer
1907 * (which can result in the peer instance pointer already haven
1908 * been gc'd by the time this event is processed)
1909 */
1910 if (w->core.being_destroyed) {
1911 return;
1912 }
1913 *cont = FALSE;
1914
1915 switch (event->type) {
1916 case SelectionClear:
1917 case SelectionNotify:
1918 case SelectionRequest:
1919 *cont = TRUE;
1920 break;
1921 case GraphicsExpose:
1922 case Expose:
1923 HandleExposeEvent(w, (jobject) client_data, event);
1924 break;
1925 case FocusIn:
1926 case FocusOut:
1927 *cont = TRUE;
1928 updateCursor(client_data, CACHE_UPDATE); // 4840883
1929 // We no longer listen to the Motif focus notifications.
1930 // Instead we call focus callbacks in the times we think
1931 // appropriate trying to simulate correct Motif widget system
1932 // behavior.
1933 break;
1934 case ButtonPress:
1935 x = (jint) event->xbutton.x;
1936 y = (jint) event->xbutton.y;
1937
1938 if (lastPeer == client_data &&
1939 lastButton == event->xbutton.button &&
1940 (event->xbutton.time - lastTime) <= (Time) awt_multiclick_time) {
1941 clickCount++;
1942 } else {
1943 clickCount = 1;
1944 lastPeer = client_data;
1945 lastButton = event->xbutton.button;
1946 lastx = x;
1947 lasty = y;
1948 }
1949 lastTime = event->xbutton.time;
1950
1951 /* On MouseEvent.MOUSE_PRESSED, RELEASED and CLICKED only new modifiers and
1952 * modifier for changed mouse button are set.
1953 */
1954 button = getButton(event->xbutton.button);
1955 modifiers = getModifiers(event->xbutton.state, button, 0);
1956
1957
1958 /* If the widget is a subwidget on a component we need to
1959 * translate the x,y into the coordinate space of the component.
1960 */
1961 if (winfo != NULL && winfo->widget != winfo->origin) {
1962 translateXY(winfo->widget, &x, &y);
1963 }
1964
1965 if (XtIsSubclass(w, xmScrollBarWidgetClass) && findWidgetInfo(w) != NULL) {
1966 passEvent = FALSE;
1967 *cont = TRUE;
1968 }
1969
1970 /* Mouse wheel events come in as button 4 (wheel up) and
1971 * button 5 (wheel down).
1972 */
1973 if (lastButton == 4 || lastButton == 5) {
1974 *cont = FALSE;
1975 awt_post_java_mouse_event(client_data,
1976 java_awt_event_MouseEvent_MOUSE_WHEEL,
1977 (passEvent == TRUE) ? event : NULL,
1978 event->xbutton.time,
1979 modifiers,
1980 x, y,
1981 (jint) (event->xbutton.x_root),
1982 (jint) (event->xbutton.y_root),
1983 clickCount,
1984 False,
1985 lastButton == 4 ? -1 : 1,
1986 java_awt_event_MouseEvent_NOBUTTON);
1987 /* we're done with this event */
1988 break;
1989 }
1990
1991 /* (4168006) Find out out how many buttons we have
1992 * If this is a two button system Right == 2
1993 * If this is a three button system Right == 3
1994 */
1995 if ( rbutton == 0 ) {
1996 unsigned char map[5];
1997 rbutton = XGetPointerMapping ( awt_display, map, 3 );
1998 }
1999
2000 if (event->xbutton.button == rbutton || event->xbutton.button > 2) {
2001 popupTrigger = True;
2002 } else {
2003 popupTrigger = False;
2004 }
2005
2006 awt_post_java_mouse_event(client_data,
2007 java_awt_event_MouseEvent_MOUSE_PRESSED,
2008 (passEvent == TRUE) ? event : NULL,
2009 event->xbutton.time,
2010 modifiers,
2011 x, y,
2012 (jint) (event->xbutton.x_root),
2013 (jint) (event->xbutton.y_root),
2014 clickCount,
2015 popupTrigger, 0,
2016 button);
2017
2018 drag_source = w;
2019
2020 break;
2021 case ButtonRelease:
2022 if (XtIsSubclass(w, xmScrollBarWidgetClass) && findWidgetInfo(w) != NULL) {
2023 passEvent = FALSE;
2024 *cont = TRUE;
2025 }
2026
2027 /*
2028 * For button 4 & 5 (mouse wheel) we can simply ignore this event.
2029 * We dispatch the wheel on the ButtonPress.
2030 */
2031 if (event->xbutton.button == 4 ||
2032 event->xbutton.button == 5) {
2033 break;
2034 }
2035
2036 prevWidget = NULL;
2037 x = (jint) event->xbutton.x;
2038 y = (jint) event->xbutton.y;
2039 /* On MouseEvent.MOUSE_PRESSED, RELEASED and CLICKED only new modifiers and
2040 * modifier for changed mouse button are set.
2041 */
2042 button = getButton(event->xbutton.button);
2043 modifiers = getModifiers(event->xbutton.state, button, 0);
2044
2045 fullRelease =
2046 ((event->xbutton.state & Button1Mask) &&
2047 !(event->xbutton.state & Button2Mask) &&
2048 !(event->xbutton.state & Button3Mask) &&
2049 (event->xbutton.button == Button1)) ||
2050 (!(event->xbutton.state & Button1Mask) &&
2051 (event->xbutton.state & Button2Mask) &&
2052 !(event->xbutton.state & Button3Mask) &&
2053 (event->xbutton.button == Button2)) ||
2054 (!(event->xbutton.state & Button1Mask) &&
2055 !(event->xbutton.state & Button2Mask) &&
2056 (event->xbutton.state & Button3Mask) &&
2057 (event->xbutton.button == Button3));
2058
2059 /* If the widget is a subwidget on a component we need to
2060 * translate the x,y into the coordinate space of the component.
2061 */
2062 if (winfo != NULL && winfo->widget != winfo->origin) {
2063 translateXY(winfo->widget, &x, &y);
2064 }
2065 drag_source = NULL;
2066 awt_post_java_mouse_event(client_data,
2067 java_awt_event_MouseEvent_MOUSE_RELEASED,
2068 (passEvent == TRUE) ? event : NULL,
2069 event->xbutton.time,
2070 modifiers,
2071 x, y,
2072 (jint) (event->xbutton.x_root),
2073 (jint) (event->xbutton.y_root),
2074 clickCount,
2075 FALSE, 0,
2076 button);
2077
2078 if (lastPeer == client_data) {
2079 awt_post_java_mouse_event(client_data,
2080 java_awt_event_MouseEvent_MOUSE_CLICKED,
2081 NULL,
2082 event->xbutton.time,
2083 modifiers,
2084 x, y,
2085 (jint) (event->xbutton.x_root),
2086 (jint) (event->xbutton.y_root),
2087 clickCount,
2088 FALSE, 0,
2089 button);
2090 }
2091
2092 if (fullRelease) {
2093 updateCursor(client_data, UPDATE_ONLY);
2094 }
2095
2096 break;
2097 case MotionNotify:
2098 if (XtIsSubclass(w, xmScrollBarWidgetClass) && findWidgetInfo(w) != NULL) {
2099 passEvent = FALSE;
2100 *cont = TRUE;
2101 }
2102
2103 x = (jint) event->xmotion.x;
2104 y = (jint) event->xmotion.y;
2105
2106 /* If a motion comes in while a multi-click is pending,
2107 * allow a smudge factor so that moving the mouse by a small
2108 * amount does not wipe out the multi-click state variables.
2109 */
2110 if (!(lastPeer == client_data &&
2111 ((event->xmotion.time - lastTime) <= (Time) awt_multiclick_time) &&
2112 (ABS(lastx - x) < awt_multiclick_smudge &&
2113 ABS(lasty - y) < awt_multiclick_smudge))) {
2114 clickCount = (jint) 0;
2115 lastTime = (Time) 0;
2116 lastPeer = NULL;
2117 lastx = (jint) 0;
2118 lasty = (jint) 0;
2119 }
2120 /* On other MouseEvent only new modifiers and
2121 * old mouse modifiers are set.
2122 */
2123 modifiers = getModifiers(event->xmotion.state, 0, 0);
2124
2125 /* If the widget is a subwidget on a component we need to
2126 * translate the x,y into the coordinate space of the component.
2127 */
2128 if (winfo != NULL && winfo->widget != winfo->origin) {
2129 translateXY(winfo->widget, &x, &y);
2130 }
2131 if (event->xmotion.state & (Button1Mask | Button2Mask | Button3Mask)) {
2132 if (!clickCount) {
2133
2134 /*
2135 Fix for bug id 4017222. A button is down, so EnterNotify and
2136 LeaveNotify events are only being sent to this widget. If
2137 the pointer has moved over a new widget, manually generate
2138 MouseEnter and MouseExit and send them to the right widgets.
2139 */
2140
2141 extern Widget awt_WidgetAtXY(Widget root, Position x, Position y);
2142 extern Widget awt_GetWidgetAtPointer();
2143 Widget currentWidget=NULL, topLevelW;
2144 Position wx=0, wy=0;
2145
2146 XtTranslateCoords(w, (int32_t) x, (int32_t) y, &wx, &wy);
2147 /* Get the top level widget underneath the mouse pointer */
2148 currentWidget = awt_GetWidgetAtPointer();
2149 /* Get the exact widget at the current XY from the top level */
2150 currentWidget = awt_WidgetAtXY(currentWidget, wx, wy);
2151 if ((prevWidget != NULL) && (prevWidget != w) &&
2152 (currentWidget != prevWidget) && awt_isAwtWidget(prevWidget) &&
2153 !prevWidget->core.being_destroyed) {
2154 XtPointer userData=NULL;
2155 XtVaGetValues(prevWidget, XmNuserData, &userData, NULL);
2156 if (userData) {
2157 awt_post_java_mouse_event(userData,
2158 java_awt_event_MouseEvent_MOUSE_EXITED,
2159 (passEvent==TRUE) ? event : NULL,
2160 event->xmotion.time,
2161 modifiers,
2162 x, y,
2163 (jint) (event->xmotion.x_root),
2164 (jint) (event->xmotion.y_root),
2165 clickCount,
2166 FALSE, 0,
2167 java_awt_event_MouseEvent_NOBUTTON);
2168 }
2169 }
2170
2171 if ((currentWidget != NULL) && (currentWidget != w) &&
2172 (currentWidget != prevWidget) && awt_isAwtWidget(currentWidget)) {
2173 XtPointer userData=NULL;
2174 XtVaGetValues(currentWidget, XmNuserData, &userData, NULL);
2175 if (userData) {
2176 awt_post_java_mouse_event(userData,
2177 java_awt_event_MouseEvent_MOUSE_ENTERED,
2178 (passEvent==TRUE) ? event : NULL,
2179 event->xmotion.time,
2180 modifiers,
2181 x, y,
2182 (jint) (event->xmotion.x_root),
2183 (jint) (event->xmotion.y_root),
2184 clickCount,
2185 FALSE, 0,
2186 java_awt_event_MouseEvent_NOBUTTON);
2187 }
2188
2189 updateCursor(userData, CACHE_ONLY);
2190 awt_util_setCursor(currentWidget, None);
2191 }
2192
2193 prevWidget = currentWidget;
2194 /* end 4017222 */
2195
2196
2197 awt_post_java_mouse_event(client_data,
2198 java_awt_event_MouseEvent_MOUSE_DRAGGED,
2199 (passEvent == TRUE) ? event : NULL,
2200 event->xmotion.time,
2201 modifiers,
2202 x, y,
2203 (jint) (event->xmotion.x_root),
2204 (jint) (event->xmotion.y_root),
2205 clickCount,
2206 FALSE, 0,
2207 java_awt_event_MouseEvent_NOBUTTON);
2208
2209 }
2210 } else {
2211
2212 awt_post_java_mouse_event(client_data,
2213 java_awt_event_MouseEvent_MOUSE_MOVED,
2214 (passEvent == TRUE) ? event : NULL,
2215 event->xmotion.time,
2216 modifiers,
2217 x, y,
2218 (jint) (event->xmotion.x_root),
2219 (jint) (event->xmotion.y_root),
2220 clickCount,
2221 FALSE, 0,
2222 java_awt_event_MouseEvent_NOBUTTON);
2223 }
2224 break;
2225 case KeyPress:
2226 handleKeyEvent(java_awt_event_KeyEvent_KEY_PRESSED,
2227 event, client_data, cont, TRUE);
2228 break;
2229 case KeyRelease:
2230 handleKeyEvent(java_awt_event_KeyEvent_KEY_RELEASED,
2231 event, client_data, cont, TRUE);
2232 break;
2233 case EnterNotify:
2234 case LeaveNotify:
2235/*
2236 printf("----->%s on %s(%x):mode=%d detail = %d\n",
2237 event->type == EnterNotify?"EnterNotify":"LeaveNotify",
2238 XtName(w), w,
2239 ((XCrossingEvent*)event)->mode, ((XCrossingEvent*)event)->detail);
2240*/
2241 if (event->xcrossing.mode != NotifyNormal ||
2242 ((event->xcrossing.detail == NotifyVirtual ||
2243 event->xcrossing.detail == NotifyNonlinearVirtual) &&
2244 !XtIsSubclass(w, xmScrolledWindowWidgetClass))) {
2245 *cont = TRUE;
2246 return;
2247 }
2248
2249 /* fix for 4454304.
2250 * We should not post MOUSE_ENTERED and MOUSE_EXITED events
2251 * if the mouse pointer is in the place between component
2252 * and its scrollbars.
2253 * kdm@sparc.spb.su
2254 */
2255 if (winfo != NULL && winfo->widget != NULL) {
2256 wclass = XtClass(winfo->widget);
2257 if (event->xcrossing.subwindow == NULL
2258 && event->xcrossing.detail == NotifyInferior
2259 && (wclass == xmTextWidgetClass
2260 || wclass == xmListWidgetClass)) {
2261 *cont = TRUE;
2262 return;
2263 }
2264 }
2265
2266 clickCount = (jint) 0;
2267 lastTime = (Time) 0;
2268 lastPeer = NULL;
2269
2270 /* On other MouseEvent only new modifiers and
2271 * old mouse modifiers are set.
2272 */
2273 modifiers = getModifiers(event->xcrossing.state, 0, 0);
2274
2275 switch (event->type) {
2276 case EnterNotify:
2277 awt_post_java_mouse_event(client_data,
2278 java_awt_event_MouseEvent_MOUSE_ENTERED,
2279 (passEvent == TRUE) ? event : NULL,
2280 event->xcrossing.time,
2281 modifiers,
2282 (jint) (event->xcrossing.x),
2283 (jint) (event->xcrossing.y),
2284 (jint) (event->xcrossing.x_root),
2285 (jint) (event->xcrossing.y_root),
2286 clickCount,
2287 FALSE, 0,
2288 java_awt_event_MouseEvent_NOBUTTON);
2289 if (!(event->xcrossing.state
2290 & (Button1Mask | Button2Mask | Button3Mask))) {
2291 updateCursor(client_data, CACHE_UPDATE);
2292 }
2293
2294 break;
2295 case LeaveNotify:
2296 awt_post_java_mouse_event(client_data,
2297 java_awt_event_MouseEvent_MOUSE_EXITED,
2298 (passEvent == TRUE) ? event : NULL,
2299 event->xcrossing.time,
2300 modifiers,
2301 (jint) (event->xcrossing.x),
2302 (jint) (event->xcrossing.y),
2303 (jint) (event->xcrossing.x_root),
2304 (jint) (event->xcrossing.y_root),
2305 clickCount,
2306 FALSE, 0,
2307 java_awt_event_MouseEvent_NOBUTTON);
2308 break;
2309 }
2310 break;
2311
2312 default:
2313 break;
2314 }
2315}
2316
2317/*
2318 * client_data is MComponentPeer subclass
2319 */
2320void
2321awt_canvas_event_handler(Widget w, XtPointer client_data,
2322 XEvent * event, Boolean * cont)
2323{
2324 awt_canvas_handleEvent(w, client_data, event, NULL, cont, FALSE);
2325}
2326
2327void
2328awt_canvas_reconfigure(struct FrameData *wdata)
2329{
2330 Dimension w, h;
2331
2332 if (wdata->winData.comp.widget == NULL ||
2333 XtParent(wdata->winData.comp.widget) == NULL) {
2334 return;
2335 }
2336 XtVaGetValues(XtParent(wdata->winData.comp.widget), XmNwidth, &w, XmNheight, &h, NULL);
2337 XtConfigureWidget(wdata->winData.comp.widget,
2338 -(wdata->left),
2339 -(wdata->top),
2340 w + (wdata->left + wdata->right),
2341 h + (wdata->top + wdata->bottom),
2342 0);
2343}
2344
2345static void
2346Wrap_event_handler(Widget widget,
2347 XtPointer client_data,
2348 XmDrawingAreaCallbackStruct * call_data)
2349{
2350 awt_canvas_reconfigure((struct FrameData *) client_data);
2351}
2352
2353
2354Widget
2355awt_canvas_create(XtPointer this,
2356 Widget parent,
2357 char *base,
2358 int32_t width,
2359 int32_t height,
2360 Boolean parentIsFrame,
2361 struct FrameData *wdata,
2362 AwtGraphicsConfigDataPtr awtData)
2363{
2364 Widget newCanvas;
2365 Widget wrap;
2366#define MAX_ARGC 20
2367 Arg args[MAX_ARGC];
2368 int32_t argc;
2369 char name[128];
2370 static XtTranslations translationKeyDown = NULL;
2371
2372 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2373
2374
2375 if (parent == NULL) {
2376 JNU_ThrowNullPointerException(env, "NullPointerException");
2377 return NULL;
2378 }
2379 if (width == 0) {
2380 width = 1;
2381 }
2382 if (height == 0) {
2383 height = 1;
2384 }
2385
2386 if (wdata != NULL) {
2387 argc = 0;
2388 if (!parentIsFrame)
2389 {
2390 XtSetArg(args[argc], XmNwidth, width);
2391 argc++;
2392 XtSetArg(args[argc], XmNheight, height);
2393 argc++;
2394 }
2395 XtSetArg(args[argc], XmNmarginWidth, 0);
2396 argc++;
2397 XtSetArg(args[argc], XmNmarginHeight, 0);
2398 argc++;
2399 XtSetArg(args[argc], XmNspacing, 0);
2400 argc++;
2401 XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE);
2402 argc++;
2403 /* check for overflowing name? */
2404 strcpy(name, base);
2405 strcat(name, "wrap");
2406
2407 DASSERT(!(argc > MAX_ARGC));
2408 wrap = XmCreateDrawingArea(parent, name, args, argc);
2409 if (!parentIsFrame)
2410 {
2411 /* Fixing bugs in frame module (awt_Frame.c). It will now
2412 provide the resize handling for this inner/parent canvas.*/
2413 XtAddCallback(wrap, XmNresizeCallback,
2414 (XtCallbackProc) Wrap_event_handler, wdata);
2415 }
2416 XtManageChild(wrap);
2417 } else {
2418 wrap = parent;
2419 }
2420
2421 /* check for overflowing name? */
2422 strcpy(name, base);
2423 strcat(name, "canvas");
2424
2425 argc = 0;
2426 XtSetArg(args[argc], XmNspacing, 0);
2427 argc++;
2428 if (!parentIsFrame)
2429 {
2430 XtSetArg(args[argc], XmNwidth, width);
2431 argc++;
2432 XtSetArg(args[argc], XmNheight, height);
2433 argc++;
2434 }
2435 XtSetArg(args[argc], XmNmarginHeight, 0);
2436 argc++;
2437 XtSetArg(args[argc], XmNmarginWidth, 0);
2438 argc++;
2439 XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE);
2440 argc++;
2441 XtSetArg(args[argc], XmNuserData, this);
2442 argc++;
2443 /* Fixed 4059430, 3/11/98, robi.khan@eng
2444 * install insert proc callback so components are ordered correctly
2445 * when added directly to frame/dialogs/windows
2446 */
2447 XtSetArg(args[argc], XmNinsertPosition, (XtPointer) awt_util_insertCallback);
2448 argc++;
2449
2450 if (awtData != getDefaultConfig(awtData->awt_visInfo.screen)) {
2451 XtSetArg (args[argc], XtNvisual, awtData->awt_visInfo.visual); argc++;
2452 XtSetArg (args[argc], XmNdepth, awtData->awt_depth); argc++;
2453 XtSetArg (args[argc], XmNscreen,
2454 ScreenOfDisplay(awt_display,
2455 awtData->awt_visInfo.screen)); argc++;
2456
2457 if (awtData->awt_cmap == None) {
2458 awtJNI_CreateColorData (env, awtData, 1);
2459 }
2460
2461 XtSetArg (args[argc], XmNcolormap, awtData->awt_cmap); argc++;
2462
2463 DASSERT(!(argc > MAX_ARGC));
2464 newCanvas = XtCreateWidget(name, vDrawingAreaClass, wrap,
2465 args, argc);
2466
2467 } else {
2468 newCanvas = XtCreateWidget(name, xDrawingAreaClass,
2469 wrap, args, argc);
2470 }
2471
2472 XtSetMappedWhenManaged(newCanvas, False);
2473 XtManageChild(newCanvas);
2474/*
2475 XXX: causes problems on 2.5
2476 if (!scrollBugWorkAround) {
2477 awt_setWidgetGravity(newCanvas, StaticGravity);
2478 }
2479*/
2480 /* Fixed 4250354 7/28/99 ssi@sparc.spb.su
2481 * XtParseTranslationTable leaks in old ver of Xtoolkit
2482 * and result should be deletetd in any case
2483 *
2484 * XtOverrideTranslations(newCanvas,
2485 * XtParseTranslationTable("<KeyDown>:DrawingAreaInput()"));
2486 */
2487 if (NULL==translationKeyDown)
2488 translationKeyDown=XtParseTranslationTable("<KeyDown>:DrawingAreaInput()");
2489 XtOverrideTranslations(newCanvas,translationKeyDown);
2490
2491 XtSetSensitive(newCanvas, True);
2492
2493 return newCanvas;
2494}
2495
2496static void
2497messWithGravity(Widget w, int32_t gravity)
2498{
2499 extern void awt_changeAttributes(Display * dpy, Widget w,
2500 unsigned long mask,
2501 XSetWindowAttributes * xattr);
2502 XSetWindowAttributes xattr;
2503
2504 xattr.bit_gravity = gravity;
2505 xattr.win_gravity = gravity;
2506
2507 awt_changeAttributes(XtDisplay(w), w, (CWBitGravity | CWWinGravity), &xattr);
2508
2509}
2510
2511struct MoveRecord {
2512 long dx;
2513 long dy;
2514};
2515
2516void
2517moveWidget(Widget w, void *data)
2518{
2519 struct MoveRecord *rec = (struct MoveRecord *) data;
2520
2521 if (XtIsRealized(w) && XmIsRowColumn(w)) {
2522 w->core.x -= rec->dx;
2523 w->core.y -= rec->dy;
2524 }
2525}
2526
2527#if 0
2528/* Scroll entire contents of window by dx and dy. Currently only
2529 dy is supported. A negative dy means scroll backwards, i.e.,
2530 contents in window move down. */
2531void
2532awt_canvas_scroll(XtPointer this,
2533 struct CanvasData *wdata,
2534 long dx,
2535 long dy)
2536{
2537
2538 Window win;
2539 XWindowChanges xchgs;
2540 Window root;
2541 int x, y;
2542 unsigned int width, height, junk;
2543 Display *dpy;
2544 struct MoveRecord mrec;
2545
2546 mrec.dx = dx;
2547 mrec.dy = dy;
2548
2549 dpy = XtDisplay(wdata->comp.widget);
2550 win = XtWindow(wdata->comp.widget);
2551
2552 /* REMIND: consider getting rid of this! */
2553 XGetGeometry(awt_display,
2554 win,
2555 &root,
2556 &x,
2557 &y,
2558 &width,
2559 &height,
2560 &junk,
2561 &junk);
2562
2563 /* we need to actually update the coordinates for manager widgets, */
2564 /* otherwise the parent won't pass down events to them properly */
2565 /* after scrolling... */
2566 awt_util_mapChildren(wdata->comp.widget, moveWidget, 0, &mrec);
2567
2568 if (dx < 0) {
2569 /* scrolling backward */
2570
2571 if (scrollBugWorkAround) {
2572 messWithGravity(wdata->comp.widget, NorthWestGravity);
2573 }
2574 xchgs.x = x + dx;
2575 xchgs.y = y;
2576 xchgs.width = width - dx;
2577 xchgs.height = height;
2578 XConfigureWindow(awt_display,
2579 win,
2580 CWX | CWY | CWWidth | CWHeight,
2581 &xchgs);
2582
2583 if (scrollBugWorkAround) {
2584 messWithGravity(wdata->comp.widget, NorthWestGravity);
2585 }
2586 xchgs.x = x;
2587 xchgs.y = y;
2588 XConfigureWindow(awt_display,
2589 win,
2590 CWX | CWY,
2591 &xchgs);
2592
2593 xchgs.width = width;
2594 xchgs.height = height;
2595 XConfigureWindow(awt_display,
2596 win,
2597 CWWidth | CWHeight,
2598 &xchgs);
2599 } else {
2600 /* forward scrolling */
2601
2602 /* make window a little taller */
2603 xchgs.width = width + dx;
2604 xchgs.height = height;
2605 XConfigureWindow(awt_display,
2606 win,
2607 CWWidth | CWHeight,
2608 &xchgs);
2609
2610 if (scrollBugWorkAround) {
2611 messWithGravity(wdata->comp.widget, NorthEastGravity);
2612 }
2613 /* move window by amount we're scrolling */
2614 xchgs.x = x - dx;
2615 xchgs.y = y;
2616 XConfigureWindow(awt_display,
2617 win,
2618 CWX | CWY,
2619 &xchgs);
2620
2621 if (scrollBugWorkAround) {
2622 messWithGravity(wdata->comp.widget, NorthWestGravity);
2623 }
2624 /* resize to original size */
2625 xchgs.x = x;
2626 xchgs.y = y;
2627 xchgs.width = width;
2628 xchgs.height = height;
2629 XConfigureWindow(awt_display,
2630 win,
2631 CWX | CWY | CWWidth | CWHeight,
2632 &xchgs);
2633 }
2634 /* Because of the weird way we're scrolling this window,
2635 we have to eat all the exposure events that result from
2636 scrolling forward, and translate them up by the amount we're
2637 scrolling by.
2638
2639 Rather than just eating all the exposures and having the
2640 java code fill in what it knows is exposed, we do it this
2641 way. The reason is that there might be some other exposure
2642 events caused by overlapping windows on top of us that we
2643 also need to deal with. */
2644 {
2645 XRectangle rect;
2646
2647 rect.x = -1;
2648 eatAllExposures(dpy, win, &rect);
2649 if (rect.x != -1) { /* we got at least one expose event */
2650 if (dx > 0) {
2651 rect.x -= dx;
2652 rect.width += dx;
2653 }
2654/*
2655 printf("EXPOSE (%d): %d, %d, %d, %d\n",
2656 dy, rect.x, rect.y, rect.width, rect.height);
2657*/
2658 callJavaExpose(this, &rect);
2659 XSync(awt_display, False);
2660 }
2661 }
2662 if (dy < 0) {
2663 /* scrolling backward */
2664
2665 if (scrollBugWorkAround) {
2666 messWithGravity(wdata->comp.widget, SouthGravity);
2667 }
2668 xchgs.x = x;
2669 xchgs.y = y + dy;
2670 xchgs.width = width;
2671 xchgs.height = height - dy;
2672 XConfigureWindow(awt_display,
2673 win,
2674 CWX | CWY | CWWidth | CWHeight,
2675 &xchgs);
2676
2677 if (scrollBugWorkAround) {
2678 messWithGravity(wdata->comp.widget, NorthWestGravity);
2679 }
2680 xchgs.x = x;
2681 xchgs.y = y;
2682 XConfigureWindow(awt_display,
2683 win,
2684 CWX | CWY,
2685 &xchgs);
2686
2687 xchgs.width = width;
2688 xchgs.height = height;
2689 XConfigureWindow(awt_display,
2690 win,
2691 CWWidth | CWHeight,
2692 &xchgs);
2693 } else {
2694 /* forward scrolling */
2695
2696 /* make window a little taller */
2697 xchgs.width = width;
2698 xchgs.height = height + dy;
2699 XConfigureWindow(awt_display,
2700 win,
2701 CWWidth | CWHeight,
2702 &xchgs);
2703
2704 /* move window by amount we're scrolling */
2705 xchgs.x = x;
2706 xchgs.y = y - dy;
2707 XConfigureWindow(awt_display,
2708 win,
2709 CWX | CWY,
2710 &xchgs);
2711
2712 if (scrollBugWorkAround) {
2713 messWithGravity(wdata->comp.widget, SouthGravity);
2714 }
2715 /* resize to original size */
2716 xchgs.x = x;
2717 xchgs.y = y;
2718 xchgs.width = width;
2719 xchgs.height = height;
2720 XConfigureWindow(awt_display,
2721 win,
2722 CWX | CWY | CWWidth | CWHeight,
2723 &xchgs);
2724 if (scrollBugWorkAround) {
2725 messWithGravity(wdata->comp.widget, NorthWestGravity);
2726 }
2727 }
2728 /* Because of the weird way we're scrolling this window,
2729 we have to eat all the exposure events that result from
2730 scrolling forward, and translate them up by the amount we're
2731 scrolling by.
2732
2733 Rather than just eating all the exposures and having the
2734 java code fill in what it knows is exposed, we do it this
2735 way. The reason is that there might be some other exposure
2736 events caused by overlapping windows on top of us that we
2737 also need to deal with. */
2738 {
2739 XRectangle rect;
2740
2741 rect.x = -1;
2742 eatAllExposures(dpy, win, &rect);
2743 if (rect.x != -1) { /* we got at least one expose event */
2744 if (dy > 0) {
2745 rect.y -= dy;
2746 rect.height += dy;
2747 }
2748 if (dx > 0) {
2749 rect.x -= dx;
2750 rect.width += dx;
2751 }
2752/*
2753 printf("EXPOSE (%d): %d, %d, %d, %d\n",
2754 dy, rect.x, rect.y, rect.width, rect.height);
2755*/
2756 callJavaExpose(this, &rect);
2757 XSync(awt_display, False);
2758 }
2759 }
2760}
2761#endif
2762
2763extern Window focusProxyWindow;
2764/*
2765 * client_data is MComponentPeer instance
2766 */
2767void
2768awt_post_java_key_event(XtPointer client_data, jint id, XEvent *event,
2769 Time when, jint keycode, jchar keychar, jint modifiers, jint keyLocation, XEvent *anEvent)
2770{
2771 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2772 jobject peer = (jobject) client_data;
2773 jobject target;
2774 static jclass classKeyEvent = NULL;
2775 static jmethodID mid = NULL;
2776 char *clsName = "java/awt/event/KeyEvent";
2777 jobject hEvent;
2778 jlong jWhen;
2779 Boolean isProxyActive = (focusProxyWindow != None);
2780
2781 if (anEvent != NULL && anEvent->xany.send_event == 2){
2782 isProxyActive = False;
2783 if (event != NULL) {
2784 event->xany.send_event = 0;
2785 }
2786 }
2787 if ((*env)->PushLocalFrame(env, 16) < 0)
2788 return;
2789
2790 target = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target);
2791
2792 if (classKeyEvent == NULL) {
2793 jobject sysClass;
2794
2795 sysClass = (*env)->FindClass(env, clsName);
2796 if (sysClass != NULL) {
2797 /* Make this class 'sticky', we don't want it GC'd */
2798 classKeyEvent = (*env)->NewGlobalRef(env, sysClass);
2799 mid = (*env)->GetMethodID(env, classKeyEvent, "<init>",
2800 "(Ljava/awt/Component;IJIICIZ)V");
2801 }
2802 if (JNU_IsNull(env, classKeyEvent) || mid == NULL) {
2803 JNU_ThrowClassNotFoundException(env, clsName);
2804 (*env)->PopLocalFrame(env, 0);
2805 return;
2806 }
2807 }
2808
2809 jWhen = awt_util_nowMillisUTC_offset(when); /* convert Time to UTC */
2810
2811 hEvent = (*env)->NewObject(env, classKeyEvent, mid,
2812 target, id, jWhen, modifiers,
2813 keycode, keychar, keyLocation,
2814 isProxyActive?JNI_TRUE:JNI_FALSE);
2815
2816 if ((*env)->ExceptionOccurred(env)) {
2817 (*env)->ExceptionDescribe(env);
2818 (*env)->ExceptionClear(env);
2819 }
2820 if (JNU_IsNull(env, hEvent)) {
2821 JNU_ThrowNullPointerException(env, "NullPointerException: constructor failed.");
2822 (*env)->PopLocalFrame(env, 0);
2823 return;
2824 }
2825 awt_copyXEventToAWTEvent(env, event, hEvent);
2826 #ifdef DEBUG
2827 if (debugKeys) {
2828 jio_fprintf(stderr, "native posting event id:%d keychar:%c\n", (int)id, (char)keychar);
2829 }
2830 #endif
2831 JNU_CallMethodByName(env, NULL, peer,
2832 "postEvent", "(Ljava/awt/AWTEvent;)V", hEvent);
2833 if ((*env)->ExceptionOccurred(env)) {
2834 (*env)->ExceptionDescribe(env);
2835 (*env)->ExceptionClear(env);
2836 }
2837 (*env)->PopLocalFrame(env, 0);
2838} /* awt_post_java_key_event() */
2839
2840/*
2841 * Note: this routine returns a global reference which should be deleted
2842 * after use.
2843 */
2844jobject
2845awt_canvas_wrapInSequenced(jobject awtevent) {
2846 static jclass classSequencedEvent = NULL;
2847 static jmethodID mid = NULL;
2848 jobject wrapperEventLocal = NULL;
2849 jobject wrapperEvent = NULL;
2850
2851 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2852
2853 if ((*env)->PushLocalFrame(env, 5) < 0)
2854 return NULL;
2855
2856 if (classSequencedEvent == NULL) {
2857 jobject sysClass = (*env)->FindClass(env, "java/awt/SequencedEvent");
2858 if (sysClass != NULL) {
2859 /* Make this class 'sticky', we don't want it GC'd */
2860 classSequencedEvent = (*env)->NewGlobalRef(env, sysClass);
2861 if (mid == NULL) {
2862 mid = (*env)->GetMethodID(env, classSequencedEvent
2863 ,"<init>"
2864 ,"(Ljava/awt/AWTEvent;)V");
2865 }
2866 }
2867 if (JNU_IsNull(env, classSequencedEvent) || mid == NULL) {
2868 JNU_ThrowClassNotFoundException(env, "java/awt/SequencedEvent");
2869 (*env)->PopLocalFrame(env, 0);
2870 return NULL;
2871 }
2872 }
2873 wrapperEventLocal = (*env)->NewObject(env, classSequencedEvent, mid, awtevent);
2874
2875 if ((*env)->ExceptionOccurred(env)) {
2876 (*env)->ExceptionDescribe(env);
2877 (*env)->ExceptionClear(env);
2878 }
2879 if (JNU_IsNull(env, wrapperEventLocal)) {
2880 JNU_ThrowNullPointerException(env, "constructor failed.");
2881 (*env)->PopLocalFrame(env, 0);
2882 return NULL;
2883 }
2884 wrapperEvent = (*env)->NewGlobalRef(env, wrapperEventLocal);
2885 if (!JNU_IsNull(env, ((*env)->ExceptionOccurred(env)))) {
2886 (*env)->ExceptionDescribe(env);
2887 (*env)->ExceptionClear(env);
2888 (*env)->PopLocalFrame(env, 0);
2889 return NULL;
2890 }
2891 if (JNU_IsNull(env, wrapperEvent)) {
2892 JNU_ThrowNullPointerException(env, "NewGlobalRef failed.");
2893 (*env)->PopLocalFrame(env, 0);
2894 return NULL;
2895 }
2896
2897 (*env)->PopLocalFrame(env, 0);
2898 return wrapperEvent;
2899}
2900
2901jobject
2902findTopLevelOpposite(JNIEnv *env, jint eventType)
2903{
2904 jobject target, peer, opposite;
2905
2906 if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
2907 return NULL;
2908 }
2909
2910 /* 4462056: Get a usable handle for a weakly referenced object */
2911 target = (*env)->NewLocalRef(env,
2912 (eventType == java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS)
2913 ? forGained
2914 : focusList->requestor);
2915 if (target == NULL) {
2916 return NULL;
2917 }
2918
2919 peer = (*env)->GetObjectField(env, target, componentIDs.peer);
2920 (*env)->DeleteLocalRef(env, target);
2921 if (peer == NULL) {
2922 return NULL;
2923 }
2924
2925 opposite = findTopLevel(peer, env);
2926 (*env)->DeleteLocalRef(env, peer);
2927
2928 return opposite;
2929}
2930
2931void
2932cleanFocusList(JNIEnv *env){
2933
2934 while(focusList) {
2935 FocusListElt *tmp = focusList->next;
2936 (*env)->DeleteWeakGlobalRef(env, focusList->requestor);
2937 free(focusList);
2938 focusList = tmp;
2939 }
2940 focusListEnd = NULL;
2941}
2942
2943static jweak
2944computeOpposite(jint id, jobject target)
2945{
2946 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2947 jobject top;
2948 jboolean isSameObject;
2949
2950 if (focusList == NULL) {
2951 return NULL;
2952 }
2953
2954 /* 4462056: Get a usable handle for a weakly referenced object */
2955 top = (*env)->NewLocalRef(env, focusList->requestor);
2956 if (top == NULL) {
2957 /* weakly referenced component was deleted -- clean up focus list */
2958 cleanFocusList(env);
2959 return NULL;
2960 }
2961
2962 isSameObject = (*env)->IsSameObject(env, target, top);
2963 (*env)->DeleteLocalRef(env, top);
2964
2965 if (isSameObject) {
2966 if (id == java_awt_event_FocusEvent_FOCUS_GAINED) {
2967 return forGained;
2968 } else { /* focus lost */
2969 FocusListElt *tmp = focusList->next;
2970 (*env)->DeleteWeakGlobalRef(env, forGained);
2971 forGained = focusList->requestor;
2972 free(focusList);
2973 focusList = tmp;
2974
2975 if (focusList == NULL) {
2976 focusListEnd = NULL;
2977 return NULL;
2978 }
2979 return focusList->requestor;
2980 }
2981 } else { /* target does not match top of list */
2982 /* be gentle with focus lost for now... */
2983 if (id == java_awt_event_FocusEvent_FOCUS_LOST) {
2984 (*env)->DeleteWeakGlobalRef(env, forGained);
2985 forGained = (*env)->NewWeakGlobalRef(env, target);
2986 return NULL;
2987 }
2988
2989 cleanFocusList(env);
2990 return NULL;
2991 }
2992}
2993
2994
2995/*
2996 * client_data is MComponentPeer instance
2997 */
2998void
2999awt_post_java_focus_event(XtPointer client_data,
3000 jint id, jobject cause,
3001 XEvent* event)
3002{
3003 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3004 jobject peer = (jobject) client_data;
3005 jobject target;
3006 jobject opposite;
3007 static jclass classFocusEvent = NULL;
3008 static jmethodID mid = NULL;
3009 char *clsName = "sun/awt/CausedFocusEvent";
3010 jobject hEvent;
3011
3012 if ((*env)->PushLocalFrame(env, 16) < 0)
3013 return;
3014
3015 target = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target);
3016
3017 opposite = (*env)->NewLocalRef(env, computeOpposite(id, target));
3018
3019 if (classFocusEvent == NULL) {
3020 jobject sysClass;
3021
3022 sysClass = (*env)->FindClass(env, clsName);
3023 if (sysClass != NULL) {
3024 /* Make this class 'sticky', we don't want it GC'd */
3025 classFocusEvent = (*env)->NewGlobalRef(env, sysClass);
3026 mid = (*env)->GetMethodID(env, classFocusEvent
3027 ,"<init>"
3028 ,"(Ljava/awt/Component;IZLjava/awt/Component;Lsun/awt/CausedFocusEvent$Cause;)V");
3029 }
3030 if (JNU_IsNull(env, classFocusEvent) || mid == 0) {
3031 JNU_ThrowClassNotFoundException(env, clsName);
3032 (*env)->PopLocalFrame(env, 0);
3033 return;
3034 }
3035 }
3036 hEvent = (*env)->NewObject(env, classFocusEvent, mid,
3037 target, id, JNI_FALSE, opposite, cause);
3038 (*env)->DeleteLocalRef(env, opposite);
3039
3040 if ((*env)->ExceptionOccurred(env)) {
3041 (*env)->ExceptionDescribe(env);
3042 (*env)->ExceptionClear(env);
3043 }
3044 if (JNU_IsNull(env, hEvent)) {
3045 JNU_ThrowNullPointerException(env, "NullPointerException: constructor failed.");
3046 (*env)->PopLocalFrame(env, 0);
3047 return;
3048 }
3049 awt_copyXEventToAWTEvent(env, event, hEvent);
3050 {
3051 jobject awtEvent = awt_canvas_wrapInSequenced(hEvent);
3052 JNU_CallMethodByName(env, NULL, peer,
3053 "postEvent", "(Ljava/awt/AWTEvent;)V",
3054 awtEvent);
3055 (*env)->DeleteGlobalRef(env, awtEvent);
3056 }
3057 if ((*env)->ExceptionOccurred(env)) {
3058 (*env)->ExceptionDescribe(env);
3059 (*env)->ExceptionClear(env);
3060 }
3061 (*env)->PopLocalFrame(env, 0);
3062}
3063
3064
3065void
3066awt_canvas_addToFocusListDefault(jobject target) {
3067 awt_canvas_addToFocusListWithDuplicates(target, JNI_FALSE);
3068}
3069
3070void
3071awt_canvas_addToFocusListWithDuplicates(jobject target, jboolean acceptDuplicates)
3072{
3073 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3074 jboolean isSameObject;
3075
3076 if (focusListEnd) {
3077 jobject localRef = (*env)->NewLocalRef(env, focusListEnd->requestor);
3078
3079 if (localRef == NULL) {
3080 isSameObject = JNI_FALSE;
3081 } else {
3082 isSameObject = (*env)->IsSameObject(env, target, localRef);
3083 (*env)->DeleteLocalRef(env, localRef);
3084 }
3085
3086 if (isSameObject && !acceptDuplicates) {
3087 return;
3088 }
3089
3090 focusListEnd->next = malloc(sizeof(FocusListElt));
3091 focusListEnd = focusListEnd->next;
3092 } else {
3093 jobject l_focusOwnerPeer = awt_canvas_getFocusOwnerPeer();
3094 if (l_focusOwnerPeer == NULL) {
3095 isSameObject = JNI_FALSE;
3096 } else {
3097 jobject l_focusOwner =
3098 (*env)->GetObjectField(env, l_focusOwnerPeer,
3099 mComponentPeerIDs.target);
3100 isSameObject =
3101 (*env)->IsSameObject(env, target, l_focusOwner);
3102 (*env)->DeleteLocalRef(env, l_focusOwner);
3103 (*env)->DeleteLocalRef(env, l_focusOwnerPeer);
3104 }
3105
3106 if (isSameObject && !acceptDuplicates) {
3107 return;
3108 }
3109
3110 focusList = focusListEnd = malloc(sizeof(FocusListElt));
3111 }
3112
3113 focusListEnd->requestor = (*env)->NewWeakGlobalRef(env, target);
3114 focusListEnd->next = NULL;
3115}
3116
3117/*
3118 * client_data is MComponentPeer instance
3119 */
3120void
3121awt_post_java_mouse_event(XtPointer client_data, jint id, XEvent* event,
3122 Time when, jint modifiers, jint x, jint y,
3123 jint xAbs, jint yAbs,
3124 jint clickcount,
3125 Boolean popuptrigger,
3126 jint wheelAmt, jint button)
3127{
3128 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3129 jobject peer = (jobject) client_data;
3130 jobject target;
3131
3132 static jclass classMouseEvent = NULL;
3133 static jclass classMouseWheelEvent = NULL;
3134
3135 static jmethodID mid = NULL;
3136 static jmethodID wheelmid = NULL;
3137
3138 char *clsName = "java/awt/event/MouseEvent";
3139 char *wheelClsName = "java/awt/event/MouseWheelEvent";
3140
3141 jobject hEvent;
3142 jobject sysClass;
3143 jlong jWhen;
3144
3145 if ((*env)->PushLocalFrame(env, 16) < 0)
3146 return;
3147
3148 target = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target);
3149
3150 if (classMouseEvent == NULL) {
3151 sysClass = (*env)->FindClass(env, clsName);
3152 if (sysClass != NULL) {
3153 /* Make this class 'sticky', we don't want it GC'd */
3154 classMouseEvent = (*env)->NewGlobalRef(env, sysClass);
3155 mid = (*env)->GetMethodID(env, classMouseEvent
3156 ,"<init>"
3157 ,"(Ljava/awt/Component;IJIIIIIIZI)V");
3158 }
3159 if (JNU_IsNull(env, classMouseEvent) || mid == 0) {
3160 JNU_ThrowClassNotFoundException(env, clsName);
3161 (*env)->PopLocalFrame(env, 0);
3162 return;
3163 }
3164 }
3165
3166 if (id == java_awt_event_MouseEvent_MOUSE_WHEEL &&
3167 classMouseWheelEvent == NULL) {
3168 sysClass = (*env)->FindClass(env, wheelClsName);
3169 if (sysClass != NULL) {
3170 /* Make this class 'sticky', we don't want it GC'd */
3171 classMouseWheelEvent = (*env)->NewGlobalRef(env, sysClass);
3172 wheelmid = (*env)->GetMethodID(env, classMouseWheelEvent,
3173 "<init>",
3174 "(Ljava/awt/Component;IJIIIIIIZIII)V");
3175 }
3176 if (JNU_IsNull(env, classMouseWheelEvent) || wheelmid == 0) {
3177 JNU_ThrowClassNotFoundException(env, wheelClsName);
3178 (*env)->PopLocalFrame(env, 0);
3179 return;
3180 }
3181 }
3182
3183 jWhen = awt_util_nowMillisUTC_offset(when); /* convert Time to UTC */
3184
3185 if (id == java_awt_event_MouseEvent_MOUSE_WHEEL) {
3186 hEvent = (*env)->NewObject(env, classMouseWheelEvent, wheelmid,
3187 target, id, jWhen, modifiers,
3188 x, y,
3189 xAbs, yAbs,
3190 clickcount, popuptrigger,
3191 /* Linux has no API for setting how a Component
3192 * should scroll in response to the mouse wheel,
3193 * so we have to make up our own.
3194 * The default behavior on Windows is 3 lines of
3195 * text, so we use that to match.
3196 */
3197 java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL,
3198 3,
3199 wheelAmt);
3200 }
3201 else {
3202 hEvent = (*env)->NewObject(env, classMouseEvent, mid,
3203 target, id, jWhen, modifiers,
3204 x, y,
3205 xAbs, yAbs,
3206 clickcount, popuptrigger, button);
3207 }
3208
3209
3210 if ((*env)->ExceptionOccurred(env)) {
3211 (*env)->ExceptionDescribe(env);
3212 (*env)->ExceptionClear(env);
3213 }
3214 if (JNU_IsNull(env, hEvent)) {
3215 JNU_ThrowNullPointerException(env, "NullPointerException: constructor failed.");
3216 (*env)->PopLocalFrame(env, 0);
3217 return;
3218 }
3219 awt_copyXEventToAWTEvent(env, event, hEvent);
3220 JNU_CallMethodByName(env, NULL, peer,
3221 "postEvent", "(Ljava/awt/AWTEvent;)V", hEvent);
3222 if ((*env)->ExceptionOccurred(env)) {
3223 (*env)->ExceptionDescribe(env);
3224 (*env)->ExceptionClear(env);
3225 }
3226 (*env)->PopLocalFrame(env, 0);
3227}