1 /* |
|
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 |
|
112 extern struct MComponentPeerIDs mComponentPeerIDs; |
|
113 extern struct AWTEventIDs awtEventIDs; |
|
114 extern struct KeyEventIDs keyEventIDs; |
|
115 extern struct InputEventIDs inputEventIDs; |
|
116 extern struct ComponentIDs componentIDs; |
|
117 extern struct KeyboardFocusManagerIDs keyboardFocusManagerIDs; |
|
118 |
|
119 #ifdef DEBUG |
|
120 static Boolean debugKeys = False; |
|
121 #endif |
|
122 |
|
123 jint awt_multiclick_smudge = 4; |
|
124 |
|
125 extern Widget drag_source; |
|
126 |
|
127 Widget prevWidget = NULL; /* for bug fix 4017222 */ |
|
128 |
|
129 FocusListElt *focusList = NULL, *focusListEnd = NULL; |
|
130 |
|
131 jweak forGained = NULL; |
|
132 |
|
133 extern Boolean scrollBugWorkAround; |
|
134 extern jobject currentX11InputMethodInstance; |
|
135 extern Window currentFocusWindow; |
|
136 extern Boolean awt_x11inputmethod_lookupString(XKeyPressedEvent *, KeySym *); |
|
137 Boolean awt_UseType4Patch = True; |
|
138 Boolean awt_ServerDetected = False; |
|
139 Boolean awt_IsXsun = False; |
|
140 Boolean awt_UseXKB = False; |
|
141 |
|
142 void 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); |
|
146 void awt_post_java_focus_event(XtPointer client_data, jint id, jobject cause, |
|
147 XEvent *event); |
|
148 void 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 |
|
155 typedef 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 |
|
173 KeymapEntry 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 |
|
488 static Boolean |
|
489 keyboardHasKanaLockKey() |
|
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 |
|
527 void |
|
528 keysymToAWTKeyCode(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 |
|
561 KeySym |
|
562 awt_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 |
|
581 typedef struct COLLAPSE_INFO { |
|
582 Window win; |
|
583 DamageRect *r; |
|
584 } CollapseInfo; |
|
585 |
|
586 static void |
|
587 expandDamageRect(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 |
|
616 static Bool |
|
617 checkForExpose(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 */ |
|
642 static void |
|
643 HandleExposeEvent(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. */ |
|
772 static jweak focusOwnerPeer = NULL; |
|
773 static 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 */ |
|
783 jobject |
|
784 awt_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 */ |
|
801 jobject |
|
802 awt_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 */ |
|
815 void |
|
816 awt_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 */ |
|
831 void |
|
832 awt_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 |
|
843 void 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 |
|
852 void |
|
853 handleFocusEvent(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 |
|
893 void 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 */ |
|
925 void |
|
926 awt_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 */ |
|
951 jint |
|
952 getModifiers(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 */ |
|
990 jint |
|
991 getButton(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 */ |
|
1009 void |
|
1010 awt_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 */ |
|
1141 static void |
|
1142 handleVendorKeySyms(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 */ |
|
1227 static void |
|
1228 adjustKeySym(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 */ |
|
1376 static Boolean |
|
1377 isXsunServer(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 } |
|
1395 static Boolean |
|
1396 isKPevent(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 */ |
|
1417 static void |
|
1418 handleKeyEventWithNumLockMask_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 */ |
|
1452 static void |
|
1453 handleKeyEventWithNumLockMask(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 |
|
1570 static void |
|
1571 handleKeyEvent(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 |
|
1848 static void |
|
1849 translateXY(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 */ |
|
1862 Widget |
|
1863 getRootWidget(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 */ |
|
1885 void |
|
1886 awt_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 */ |
|
2320 void |
|
2321 awt_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 |
|
2327 void |
|
2328 awt_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 |
|
2345 static void |
|
2346 Wrap_event_handler(Widget widget, |
|
2347 XtPointer client_data, |
|
2348 XmDrawingAreaCallbackStruct * call_data) |
|
2349 { |
|
2350 awt_canvas_reconfigure((struct FrameData *) client_data); |
|
2351 } |
|
2352 |
|
2353 |
|
2354 Widget |
|
2355 awt_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 |
|
2496 static void |
|
2497 messWithGravity(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 |
|
2511 struct MoveRecord { |
|
2512 long dx; |
|
2513 long dy; |
|
2514 }; |
|
2515 |
|
2516 void |
|
2517 moveWidget(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. */ |
|
2531 void |
|
2532 awt_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 |
|
2763 extern Window focusProxyWindow; |
|
2764 /* |
|
2765 * client_data is MComponentPeer instance |
|
2766 */ |
|
2767 void |
|
2768 awt_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 */ |
|
2844 jobject |
|
2845 awt_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 |
|
2901 jobject |
|
2902 findTopLevelOpposite(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 |
|
2931 void |
|
2932 cleanFocusList(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 |
|
2943 static jweak |
|
2944 computeOpposite(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 */ |
|
2998 void |
|
2999 awt_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 |
|
3065 void |
|
3066 awt_canvas_addToFocusListDefault(jobject target) { |
|
3067 awt_canvas_addToFocusListWithDuplicates(target, JNI_FALSE); |
|
3068 } |
|
3069 |
|
3070 void |
|
3071 awt_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 */ |
|
3120 void |
|
3121 awt_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 } |
|