1 /* |
|
2 * Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 #include "awt_p.h" |
|
27 |
|
28 #include <sys/time.h> |
|
29 #include <limits.h> |
|
30 #include <locale.h> |
|
31 |
|
32 #ifndef HEADLESS |
|
33 #include <X11/cursorfont.h> |
|
34 #include <Xm/MenuShell.h> |
|
35 #include <Xm/RowColumn.h> |
|
36 #endif /* !HEADLESS */ |
|
37 |
|
38 #include <jvm.h> |
|
39 #include <jni.h> |
|
40 #include <jlong.h> |
|
41 #include <jni_util.h> |
|
42 |
|
43 /* JNI headers */ |
|
44 #include "java_awt_AWTEvent.h" |
|
45 #include "java_awt_Frame.h" |
|
46 #include "java_awt_SystemColor.h" |
|
47 #include "sun_awt_motif_MToolkit.h" |
|
48 |
|
49 /* JNI field and method ids */ |
|
50 #include "awt_Component.h" |
|
51 //#include "awt_Cursor.h" |
|
52 #include "awt_MenuComponent.h" |
|
53 #include "awt_TopLevel.h" |
|
54 #include "canvas.h" |
|
55 #include "color.h" |
|
56 #include "awt_mgrsel.h" |
|
57 #include "awt_wm.h" |
|
58 #include "awt_DrawingSurface.h" |
|
59 #include "awt_Window.h" |
|
60 #include "awt_xembed.h" |
|
61 #include "awt_xembed_server.h" |
|
62 |
|
63 extern JavaVM *jvm; |
|
64 |
|
65 #ifndef HEADLESS |
|
66 #ifdef __linux__ |
|
67 extern void statusWindowEventHandler(XEvent event); |
|
68 #endif |
|
69 #endif /* !HEADLESS */ |
|
70 |
|
71 JNIEXPORT jint JNICALL |
|
72 JNI_OnLoad(JavaVM *vm, void *reserved) |
|
73 { |
|
74 #ifndef HEADLESS |
|
75 awt_util_debug_init(); |
|
76 #endif /* !HEADLESS */ |
|
77 jvm = vm; |
|
78 return JNI_VERSION_1_2; |
|
79 } |
|
80 |
|
81 JNIEXPORT jboolean JNICALL AWTIsHeadless() { |
|
82 #ifdef HEADLESS |
|
83 return JNI_TRUE; |
|
84 #else |
|
85 return JNI_FALSE; |
|
86 #endif |
|
87 } |
|
88 |
|
89 #ifndef HEADLESS |
|
90 static jlong awtJNI_TimeMillis(void); |
|
91 extern void awt_initialize_Xm_DnD(Display*); |
|
92 extern void awt_initialize_DataTransferer(); |
|
93 |
|
94 extern Display *awt_init_Display(JNIEnv *env); |
|
95 |
|
96 extern void X11SD_LibDispose(JNIEnv *env); |
|
97 |
|
98 extern Widget drag_source = NULL; |
|
99 |
|
100 extern struct ComponentIDs componentIDs; |
|
101 extern struct MenuComponentIDs menuComponentIDs; |
|
102 extern struct MComponentPeerIDs mComponentPeerIDs; |
|
103 extern struct WindowIDs windowIDs; |
|
104 |
|
105 static Atom _XA_XSETTINGS_SETTINGS = None; |
|
106 struct xsettings_callback_cookie { |
|
107 jobject mtoolkit; |
|
108 jmethodID upcallMID; |
|
109 }; |
|
110 |
|
111 static struct xsettings_callback_cookie xsettings_callback_cookie; |
|
112 |
|
113 |
|
114 static XEvent focusOutEvent; |
|
115 |
|
116 static void awt_pipe_init(void); |
|
117 static void processOneEvent(XtInputMask iMask); |
|
118 extern void waitForEvents(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe); |
|
119 #ifdef USE_SELECT |
|
120 static void performSelect(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe); |
|
121 #else |
|
122 static void performPoll(JNIEnv *env,int32_t fdXPipe, int32_t fdAWTPipe); |
|
123 #endif |
|
124 |
|
125 |
|
126 #include <X11/Intrinsic.h> |
|
127 #include <dlfcn.h> |
|
128 #include <fcntl.h> |
|
129 |
|
130 #ifdef USE_SELECT |
|
131 #if defined(AIX) |
|
132 #include <sys/select.h> |
|
133 #endif |
|
134 #else |
|
135 #include <poll.h> |
|
136 #ifndef POLLRDNORM |
|
137 #define POLLRDNORM POLLIN |
|
138 #endif |
|
139 #endif |
|
140 |
|
141 #ifdef NDEBUG |
|
142 #undef DEBUG /* NDEBUG overrides DEBUG */ |
|
143 #endif |
|
144 |
|
145 static struct WidgetInfo *awt_winfo = (struct WidgetInfo *) NULL; |
|
146 static struct MenuList* menu_list = (struct MenuList*) NULL; |
|
147 |
|
148 #ifndef bzero |
|
149 #define bzero(a,b) memset(a, 0, b) |
|
150 #endif |
|
151 |
|
152 static jboolean syncUpdated = JNI_FALSE; |
|
153 static jboolean syncFailed = JNI_FALSE; |
|
154 static jint eventNumber = 0; |
|
155 static void syncWait_eventHandler(XEvent *); |
|
156 static Atom oops_atom = None; |
|
157 static Atom wm_selection = None; |
|
158 static Atom version_atom = None; |
|
159 |
|
160 static Boolean inSyncWait = False; |
|
161 |
|
162 Widget grabbed_widget = NULL; |
|
163 |
|
164 XtAppContext awt_appContext; |
|
165 Widget awt_root_shell; |
|
166 Pixel awt_defaultBg; |
|
167 Pixel awt_defaultFg; |
|
168 int32_t awt_multiclick_time; /* milliseconds */ |
|
169 uint32_t awt_MetaMask = 0; |
|
170 uint32_t awt_AltMask = 0; |
|
171 uint32_t awt_NumLockMask = 0; |
|
172 uint32_t awt_ModeSwitchMask = 0; |
|
173 Cursor awt_scrollCursor; |
|
174 Boolean awt_ModLockIsShiftLock = False; |
|
175 extern Boolean awt_UseType4Patch; |
|
176 extern Boolean awt_UseXKB; |
|
177 |
|
178 #define SPECIAL_KEY_EVENT 2 |
|
179 |
|
180 /* implement a "putback queue" -- see comments on awt_put_back_event() */ |
|
181 #define PUTBACK_QUEUE_MIN_INCREMENT 5 /* min size increase */ |
|
182 static XEvent *putbackQueue = NULL; /* the queue -- next event is 0 */ |
|
183 static int32_t putbackQueueCount = 0; /* # of events available on queue */ |
|
184 static int32_t putbackQueueCapacity = 0; /* total capacity of queue */ |
|
185 static XtInputMask awt_events_pending(XtAppContext appContext); |
|
186 static int32_t awt_get_next_put_back_event(XEvent *xev_out); |
|
187 |
|
188 #define AWT_FLUSH_TIMEOUT ((uint32_t)100) /* milliseconds */ |
|
189 #define AWT_MIN_POLL_TIMEOUT ((uint32_t)0) /* milliseconds */ |
|
190 #define AWT_MAX_POLL_TIMEOUT ((uint32_t)250) /* milliseconds */ |
|
191 |
|
192 #define AWT_POLL_BUFSIZE 100 |
|
193 #define AWT_READPIPE (awt_pipe_fds[0]) |
|
194 #define AWT_WRITEPIPE (awt_pipe_fds[1]) |
|
195 #define AWT_FLUSHOUTPUT_NOW() \ |
|
196 { \ |
|
197 XFlush(awt_display); \ |
|
198 awt_next_flush_time = 0LL; \ |
|
199 } |
|
200 |
|
201 typedef XtIntervalId (*XTFUNC)(); |
|
202 |
|
203 static jobject awt_MainThread = NULL; |
|
204 static char read_buf[AWT_POLL_BUFSIZE + 1]; /* dummy buf to empty pipe */ |
|
205 static int32_t awt_pipe_fds[2]; /* fds for wkaeup pipe */ |
|
206 static Boolean awt_pipe_inited = False; /* make sure pipe is initialized before write */ |
|
207 static int32_t def_poll_timeout = AWT_MAX_POLL_TIMEOUT; /* default value for timeout */ |
|
208 static jlong awt_next_flush_time = 0LL; /* 0 == no scheduled flush */ |
|
209 static void *xt_lib = NULL; |
|
210 static XTFUNC xt_timeout = NULL; |
|
211 |
|
212 #ifdef DEBUG_AWT_LOCK |
|
213 |
|
214 int32_t awt_locked = 0; |
|
215 char *lastF = ""; |
|
216 int32_t lastL = -1; |
|
217 |
|
218 #endif |
|
219 |
|
220 #ifndef NOMODALFIX |
|
221 extern Boolean awt_isModal(); |
|
222 extern Boolean awt_isWidgetModal(Widget w); |
|
223 #endif |
|
224 |
|
225 Boolean keyboardGrabbed = False; |
|
226 |
|
227 static uint32_t curPollTimeout = AWT_MAX_POLL_TIMEOUT; |
|
228 |
|
229 /* Font information to feed Motif widgets. */ |
|
230 static const char *motifFontList; |
|
231 static XFontSet defaultMotifFontSet; |
|
232 static XFontStruct *defaultMotifFontStruct; |
|
233 static const char *defaultMotifFont = /* a.k.a "fixed", known everywhere */ |
|
234 "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"; |
|
235 |
|
236 XFontSet getMotifFontSet() { |
|
237 char **missingList; |
|
238 int32_t missingCount; |
|
239 char *defChar; |
|
240 |
|
241 return XCreateFontSet(awt_display, motifFontList, |
|
242 &missingList, &missingCount, &defChar); |
|
243 } |
|
244 |
|
245 XFontStruct *getMotifFontStruct() { |
|
246 return XLoadQueryFont(awt_display, defaultMotifFont); |
|
247 } |
|
248 |
|
249 XmFontList getMotifFontList() { |
|
250 XmFontListEntry motifFontListEntry; |
|
251 XmFontList fontlist; |
|
252 |
|
253 if (strchr(motifFontList, ',') == NULL) { |
|
254 /* If the default font is a single font. */ |
|
255 if (defaultMotifFontStruct == NULL) |
|
256 defaultMotifFontStruct = getMotifFontStruct(); |
|
257 motifFontListEntry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, |
|
258 XmFONT_IS_FONT, |
|
259 (XtPointer)defaultMotifFontStruct); |
|
260 } |
|
261 else { |
|
262 /* If the default font is multiple fonts. */ |
|
263 if (defaultMotifFontSet == NULL) |
|
264 defaultMotifFontSet = getMotifFontSet(); |
|
265 motifFontListEntry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, |
|
266 XmFONT_IS_FONTSET, |
|
267 (XtPointer)defaultMotifFontSet); |
|
268 } |
|
269 fontlist = XmFontListAppendEntry(NULL, motifFontListEntry); |
|
270 XmFontListEntryFree(&motifFontListEntry); |
|
271 return fontlist; |
|
272 } |
|
273 |
|
274 static void |
|
275 awt_set_poll_timeout (uint32_t newTimeout) |
|
276 { |
|
277 DTRACE_PRINTLN1("awt_set_poll_timeout(%lu)", newTimeout); |
|
278 |
|
279 newTimeout = max(AWT_MIN_POLL_TIMEOUT, newTimeout); |
|
280 newTimeout = min(AWT_MAX_POLL_TIMEOUT, newTimeout); |
|
281 newTimeout = min(newTimeout, curPollTimeout); |
|
282 curPollTimeout = newTimeout; |
|
283 |
|
284 } /* awt_set_poll_timeout */ |
|
285 |
|
286 /* |
|
287 * Gets the best timeout for the next call to poll() or select(). |
|
288 * If timedOut is True, we assume that our previous timeout elapsed |
|
289 * with no events/timers arriving. Therefore, we can increase the |
|
290 * next timeout slightly. |
|
291 */ |
|
292 static uint32_t |
|
293 awt_get_poll_timeout( Boolean timedOut ) |
|
294 { |
|
295 uint32_t timeout = AWT_MAX_POLL_TIMEOUT; |
|
296 |
|
297 DTRACE_PRINTLN2("awt_get_poll_timeout(%s), awt_next_flush_time:%ld", |
|
298 (remove?"true":"false"), |
|
299 awt_next_flush_time); |
|
300 |
|
301 if (timedOut) { |
|
302 /* add 1/16 (plus 1, in case the division truncates to 0) */ |
|
303 curPollTimeout += ((curPollTimeout>>4) + 1); |
|
304 curPollTimeout = min(AWT_MAX_POLL_TIMEOUT, curPollTimeout); |
|
305 } |
|
306 if (awt_next_flush_time > 0) { |
|
307 int32_t flushDiff = (int32_t)(awt_next_flush_time - awtJNI_TimeMillis()); |
|
308 timeout = min(curPollTimeout, flushDiff); |
|
309 } else { |
|
310 timeout = curPollTimeout; |
|
311 } |
|
312 |
|
313 return timeout; |
|
314 } /* awt_get_poll_timeout() */ |
|
315 |
|
316 static jlong |
|
317 awtJNI_TimeMillis(void) |
|
318 { |
|
319 struct timeval t; |
|
320 |
|
321 gettimeofday(&t, 0); |
|
322 |
|
323 return jlong_add(jlong_mul(jint_to_jlong(t.tv_sec), jint_to_jlong(1000)), |
|
324 jint_to_jlong(t.tv_usec / 1000)); |
|
325 } |
|
326 |
|
327 static int32_t |
|
328 xtError() |
|
329 { |
|
330 #ifdef DEBUG |
|
331 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
332 |
|
333 jio_fprintf(stderr, "Xt error\n"); |
|
334 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
335 #endif |
|
336 return 0; |
|
337 } |
|
338 |
|
339 static int32_t |
|
340 xIOError(Display *dpy) |
|
341 { |
|
342 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
343 jclass cl = (*env)->FindClass(env, "java/lang/Thread"); |
|
344 |
|
345 if (errno == EPIPE) { |
|
346 jio_fprintf(stderr, "X connection to %s host broken (explicit kill or server shutdown)\n", XDisplayName(NULL)); |
|
347 } |
|
348 AWT_NOFLUSH_UNLOCK(); |
|
349 JVM_RaiseSignal(JVM_SIGTERM); /* Shut down cleanly */ |
|
350 if (cl != NULL) { |
|
351 JVM_Sleep(env, cl, 20000); |
|
352 } |
|
353 |
|
354 return 0; /* to keep compiler happy */ |
|
355 } |
|
356 |
|
357 /* Like XKeysymToKeycode, but ensures that keysym is the primary |
|
358 * symbol on the keycode returned. Returns zero otherwise. |
|
359 */ |
|
360 static int32_t |
|
361 keysym_to_keycode_if_primary(Display *dpy, KeySym sym) |
|
362 { |
|
363 KeyCode code; |
|
364 KeySym primary; |
|
365 |
|
366 code = XKeysymToKeycode(dpy, sym); |
|
367 if (code == 0) { |
|
368 return 0; |
|
369 } |
|
370 |
|
371 primary = XKeycodeToKeysym(dpy, code, 0); |
|
372 if (sym == primary) { |
|
373 return code; |
|
374 } else { |
|
375 return 0; |
|
376 } |
|
377 } |
|
378 /* |
|
379 * +kb or -kb ? |
|
380 */ |
|
381 static Boolean |
|
382 isXKBenabled(Display *display) { |
|
383 int mop, beve, berr; |
|
384 /* |
|
385 * NB: TODO: hope it will return False if XkbIgnoreExtension was called! |
|
386 */ |
|
387 return XQueryExtension(display, "XKEYBOARD", &mop, &beve, &berr); |
|
388 } |
|
389 |
|
390 |
|
391 /* Assign meaning - alt, meta, etc. - to X modifiers mod1 ... mod5. |
|
392 * Only consider primary symbols on keycodes attached to modifiers. |
|
393 */ |
|
394 static void |
|
395 setup_modifier_map(Display *disp) |
|
396 { |
|
397 KeyCode metaL = keysym_to_keycode_if_primary(disp, XK_Meta_L); |
|
398 KeyCode metaR = keysym_to_keycode_if_primary(disp, XK_Meta_R); |
|
399 KeyCode altL = keysym_to_keycode_if_primary(disp, XK_Alt_L); |
|
400 KeyCode altR = keysym_to_keycode_if_primary(disp, XK_Alt_R); |
|
401 KeyCode numLock = keysym_to_keycode_if_primary(disp, XK_Num_Lock); |
|
402 KeyCode modeSwitch = keysym_to_keycode_if_primary(disp, XK_Mode_switch); |
|
403 KeyCode shiftLock = keysym_to_keycode_if_primary(disp, XK_Shift_Lock); |
|
404 KeyCode capsLock = keysym_to_keycode_if_primary(disp, XK_Caps_Lock); |
|
405 |
|
406 XModifierKeymap *modmap = NULL; |
|
407 int32_t nkeys, modn, i; |
|
408 char *ptr = NULL; |
|
409 |
|
410 DTRACE_PRINTLN("In setup_modifier_map"); |
|
411 |
|
412 modmap = XGetModifierMapping(disp); |
|
413 nkeys = modmap->max_keypermod; |
|
414 |
|
415 for (modn = Mod1MapIndex; |
|
416 (modn <= Mod5MapIndex) && |
|
417 (awt_MetaMask == 0 || awt_AltMask == 0 || |
|
418 awt_NumLockMask == 0 || awt_ModeSwitchMask == 0); |
|
419 ++modn) |
|
420 { |
|
421 static const uint32_t modmask[8] = { |
|
422 ShiftMask, LockMask, ControlMask, |
|
423 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask |
|
424 }; |
|
425 |
|
426 |
|
427 for (i = 0; i < nkeys; ++i) { |
|
428 /* for each keycode attached to this modifier */ |
|
429 KeyCode keycode = modmap->modifiermap[modn * nkeys + i]; |
|
430 if (keycode == 0) { |
|
431 continue; |
|
432 } |
|
433 |
|
434 if (awt_MetaMask == 0 && (keycode == metaL || keycode == metaR)) { |
|
435 awt_MetaMask = modmask[modn]; |
|
436 DTRACE_PRINTLN2(" awt_MetaMask = %d, modn = %d", awt_MetaMask, modn); |
|
437 break; |
|
438 } else if (awt_AltMask == 0 && (keycode == altL || keycode == altR)) { |
|
439 awt_AltMask = modmask[modn]; |
|
440 DTRACE_PRINTLN2(" awt_AltMask = %d, modn = %d", awt_AltMask, modn); |
|
441 break; |
|
442 } else if (awt_NumLockMask == 0 && keycode == numLock) { |
|
443 awt_NumLockMask = modmask[modn]; |
|
444 DTRACE_PRINTLN2(" awt_NumLockMask = %d, modn = %d", awt_NumLockMask, modn); |
|
445 break; |
|
446 } else if (awt_ModeSwitchMask == 0 && keycode == modeSwitch) { |
|
447 awt_ModeSwitchMask = modmask[modn]; |
|
448 DTRACE_PRINTLN2(" awt_ModeSwitchMask = %d, modn = %d", awt_ModeSwitchMask, modn); |
|
449 break; |
|
450 } |
|
451 } |
|
452 } |
|
453 for(i = 0; i < nkeys; i++) { |
|
454 KeyCode keycode = modmap->modifiermap[LockMapIndex * nkeys + i]; |
|
455 if (keycode == 0) { |
|
456 break; |
|
457 } |
|
458 if (keycode == shiftLock) { |
|
459 awt_ModLockIsShiftLock = True; |
|
460 break; |
|
461 } |
|
462 if (keycode == capsLock) { |
|
463 break; |
|
464 } |
|
465 } |
|
466 |
|
467 DTRACE_PRINTLN1(" ShiftMask = %d", ShiftMask); |
|
468 DTRACE_PRINTLN1(" ControlMask = %d", ControlMask); |
|
469 |
|
470 XFreeModifiermap(modmap); |
|
471 ptr = getenv("_AWT_USE_TYPE4_PATCH"); |
|
472 if( ptr != NULL && ptr[0] != 0 ) { |
|
473 if( strncmp("true", ptr, 4) == 0 ) { |
|
474 awt_UseType4Patch = True; |
|
475 }else if( strncmp("false", ptr, 5) == 0 ) { |
|
476 awt_UseType4Patch = False; |
|
477 } |
|
478 } |
|
479 awt_UseXKB = isXKBenabled(disp); |
|
480 |
|
481 } |
|
482 |
|
483 |
|
484 Boolean scrollBugWorkAround; |
|
485 |
|
486 |
|
487 void |
|
488 awt_output_flush() |
|
489 { |
|
490 char c = 'p'; |
|
491 |
|
492 if (awt_next_flush_time == 0) |
|
493 { |
|
494 Boolean needsWakeup = False; |
|
495 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
496 if (awt_pipe_inited && (awt_get_poll_timeout(False) > (2*AWT_FLUSH_TIMEOUT))){ |
|
497 needsWakeup = True; |
|
498 } |
|
499 /* awt_next_flush_time affects awt_get_poll_timeout(), so set |
|
500 * the variable *after* calling the function. |
|
501 */ |
|
502 awt_next_flush_time = awtJNI_TimeMillis() + AWT_FLUSH_TIMEOUT; |
|
503 if (needsWakeup) |
|
504 { |
|
505 /* write to the utility pipe to wake up the event |
|
506 * loop, if it's sleeping |
|
507 */ |
|
508 write ( AWT_WRITEPIPE, &c, 1 ); |
|
509 } |
|
510 } |
|
511 #ifdef FLUSHDEBUG |
|
512 else |
|
513 jio_fprintf(stderr, "!"); |
|
514 #endif |
|
515 } /* awt_output_flush() */ |
|
516 |
|
517 void |
|
518 null_event_handler(Widget w, XtPointer client_data, |
|
519 XEvent * event, Boolean * cont) |
|
520 { |
|
521 /* do nothing */ |
|
522 } |
|
523 |
|
524 struct WidgetInfo * |
|
525 findWidgetInfo(Widget widget) |
|
526 { |
|
527 struct WidgetInfo *cw; |
|
528 |
|
529 for (cw = awt_winfo; cw != NULL; cw = cw->next) { |
|
530 if (cw->widget == widget || cw->origin == widget) { |
|
531 return cw; |
|
532 } |
|
533 } |
|
534 return NULL; |
|
535 } |
|
536 |
|
537 void |
|
538 awt_addWidget(Widget w, Widget origin, void *peer, jlong event_flags) |
|
539 { |
|
540 if (findWidgetInfo(w) != NULL) return; |
|
541 |
|
542 if (!XtIsSubclass(w, xmFileSelectionBoxWidgetClass)) { |
|
543 struct WidgetInfo *nw = (struct WidgetInfo *) malloc(sizeof(struct WidgetInfo)); |
|
544 |
|
545 if (nw) { |
|
546 nw->widget = w; |
|
547 nw->origin = origin; |
|
548 nw->peer = peer; |
|
549 nw->event_mask = event_flags; |
|
550 nw->next = awt_winfo; |
|
551 awt_winfo = nw; |
|
552 |
|
553 if (event_flags & java_awt_AWTEvent_MOUSE_EVENT_MASK) { |
|
554 XtAddEventHandler(w, |
|
555 ButtonPressMask | ButtonReleaseMask | |
|
556 EnterWindowMask | LeaveWindowMask, |
|
557 False, null_event_handler, NULL); |
|
558 if (w != origin) { |
|
559 XtAddEventHandler(origin, |
|
560 ButtonPressMask | ButtonReleaseMask | |
|
561 EnterWindowMask | LeaveWindowMask, |
|
562 False, null_event_handler, NULL); |
|
563 } |
|
564 } |
|
565 if (event_flags & java_awt_AWTEvent_MOUSE_MOTION_EVENT_MASK) { |
|
566 XtAddEventHandler(w, |
|
567 PointerMotionMask, |
|
568 False, null_event_handler, NULL); |
|
569 if (w != origin) { |
|
570 XtAddEventHandler(origin, |
|
571 PointerMotionMask, |
|
572 False, null_event_handler, NULL); |
|
573 } |
|
574 } |
|
575 if (event_flags & java_awt_AWTEvent_KEY_EVENT_MASK) { |
|
576 XtAddEventHandler(w, |
|
577 KeyPressMask | KeyReleaseMask, |
|
578 False, null_event_handler, NULL); |
|
579 if (w != origin) { |
|
580 XtAddEventHandler(origin, |
|
581 KeyPressMask | KeyReleaseMask, |
|
582 False, null_event_handler, NULL); |
|
583 } |
|
584 } |
|
585 } else { |
|
586 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
587 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
|
588 } |
|
589 |
|
590 } |
|
591 } |
|
592 |
|
593 void |
|
594 awt_delWidget(Widget w) |
|
595 { |
|
596 struct WidgetInfo *cw; |
|
597 |
|
598 if (awt_winfo != NULL) { |
|
599 if ((awt_winfo->widget == w) || |
|
600 (awt_winfo->origin == w)) { |
|
601 cw = awt_winfo; |
|
602 awt_winfo = awt_winfo->next; |
|
603 free((void *) cw); |
|
604 } else { |
|
605 struct WidgetInfo *pw; |
|
606 |
|
607 for (pw = awt_winfo, cw = awt_winfo->next; |
|
608 cw != NULL; |
|
609 pw = cw, cw = cw->next) { |
|
610 if ((cw->widget == w) || |
|
611 (cw->origin == w)) { |
|
612 pw->next = cw->next; |
|
613 free((void *) cw); |
|
614 break; |
|
615 } |
|
616 } |
|
617 } |
|
618 } |
|
619 } |
|
620 |
|
621 |
|
622 void * |
|
623 findPeer(Widget * pwidget) |
|
624 { |
|
625 struct WidgetInfo *cw; |
|
626 Widget widgetParent; |
|
627 void * peer; |
|
628 |
|
629 if ((cw = findWidgetInfo(*pwidget)) != NULL) { |
|
630 return cw->peer; |
|
631 } |
|
632 /* fix for 4053856, robi.khan@eng |
|
633 couldn't find peer corresponding to widget |
|
634 but the widget may be child of one with |
|
635 a peer, so recurse up the hierarchy */ |
|
636 widgetParent = XtParent(*pwidget); |
|
637 if (widgetParent != NULL ) { |
|
638 peer = findPeer(&widgetParent); |
|
639 if( peer != NULL ) { |
|
640 /* found peer attached to ancestor of given |
|
641 widget, so set widget return value as well */ |
|
642 *pwidget = widgetParent; |
|
643 return peer; |
|
644 } |
|
645 } |
|
646 |
|
647 return NULL; |
|
648 } |
|
649 |
|
650 Boolean |
|
651 awt_isAwtWidget(Widget widget) |
|
652 { |
|
653 return (findWidgetInfo(widget) != NULL); |
|
654 } |
|
655 |
|
656 |
|
657 static Boolean |
|
658 awt_isAwtMenuWidget(Widget wdgt) { |
|
659 struct MenuList* cur; |
|
660 |
|
661 if (!XtIsSubclass(wdgt, xmRowColumnWidgetClass)) { |
|
662 return False; |
|
663 } |
|
664 for (cur = menu_list; cur != NULL; cur = cur->next) { |
|
665 if (cur->menu == wdgt) { |
|
666 return True; |
|
667 } |
|
668 } |
|
669 return False; |
|
670 } |
|
671 |
|
672 void |
|
673 awt_addMenuWidget(Widget wdgt) { |
|
674 DASSERT(XtIsSubclass(wdgt, xmRowColumnWidgetClass)); |
|
675 |
|
676 if (!awt_isAwtMenuWidget(wdgt)) { |
|
677 struct MenuList* ml = (struct MenuList*) malloc(sizeof(struct MenuList)); |
|
678 if (ml != NULL) { |
|
679 ml->menu = wdgt; |
|
680 ml->next = menu_list; |
|
681 menu_list = ml; |
|
682 } else { |
|
683 JNIEnv* env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
684 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
|
685 } |
|
686 } |
|
687 } |
|
688 |
|
689 void |
|
690 awt_delMenuWidget(Widget wdgt) { |
|
691 struct MenuList** pp; |
|
692 struct MenuList* p; |
|
693 |
|
694 DASSERT(XtIsSubclass(wdgt, xmRowColumnWidgetClass)); |
|
695 |
|
696 for (pp = &menu_list; *pp != NULL; pp = &((*pp)->next)) { |
|
697 if ((*pp)->menu == wdgt) { |
|
698 p = *pp; |
|
699 *pp = (*pp)->next; |
|
700 free((void*)p); |
|
701 break; |
|
702 } |
|
703 } |
|
704 } |
|
705 |
|
706 |
|
707 static Widget |
|
708 getShellWidgetByPart(Widget part) { |
|
709 int i; |
|
710 for (i = 0; i < 3; i++) { |
|
711 if (part == NULL) return NULL; |
|
712 if (XtIsShell(part)) return part; |
|
713 part = XtParent(part); |
|
714 } |
|
715 return NULL; |
|
716 } |
|
717 |
|
718 static Boolean |
|
719 isTheSameShellWidget(Widget shell, Widget w) { |
|
720 Widget s1, s2; |
|
721 if (shell == NULL || w == NULL) return False; |
|
722 s1 = getShellWidgetByPart(shell); |
|
723 s2 = getShellWidgetByPart(w); |
|
724 if (s1 == s2 && s1 != NULL) { |
|
725 return True; |
|
726 } else { |
|
727 return False; |
|
728 } |
|
729 } |
|
730 |
|
731 static Boolean |
|
732 shouldDispatchToWidget(XEvent * xev) |
|
733 { |
|
734 /* If this function returns False, that means that it has not pre-posted |
|
735 this event to Java. The caller will then dispatch the event to Motif, |
|
736 and our handlers will be called to post it to Java. |
|
737 If this function returns true, then this function has posted this event |
|
738 to java before returning. The caller will not dispatch it to Motif; |
|
739 it will be dispatched to Motif via the putbackQueue after it has been |
|
740 processed by Java */ |
|
741 |
|
742 Window win; |
|
743 Widget widget = NULL; |
|
744 struct WidgetInfo *winfo; |
|
745 void *peer = NULL; |
|
746 Boolean cont = FALSE; |
|
747 |
|
748 switch (xev->type) { |
|
749 case KeyPress: |
|
750 case KeyRelease: |
|
751 win = xev->xkey.window; |
|
752 break; |
|
753 case FocusIn: |
|
754 case FocusOut: |
|
755 win = xev->xfocus.window; |
|
756 break; |
|
757 case ButtonPress: |
|
758 case ButtonRelease: |
|
759 win = xev->xbutton.window; |
|
760 break; |
|
761 case MotionNotify: |
|
762 win = xev->xmotion.window; |
|
763 break; |
|
764 case EnterNotify: |
|
765 case LeaveNotify: |
|
766 win = xev->xcrossing.window; |
|
767 break; |
|
768 default: |
|
769 return False; |
|
770 } |
|
771 |
|
772 if ((widget = XtWindowToWidget(awt_display, win)) == NULL) { |
|
773 return False; |
|
774 } |
|
775 |
|
776 if (xev->type == KeyPress || xev->type == KeyRelease) { |
|
777 Widget focusWidget = XmGetFocusWidget(widget); |
|
778 |
|
779 /* Fix for 4328561 by ibd@sparc.spb.su |
|
780 If the widget is a Choice, the widget with focus is probably lying |
|
781 outside the current widget's sub-hierarchy, so we have to go up the |
|
782 hierarchy to reach it */ |
|
783 |
|
784 if ((focusWidget == NULL) && XmIsMenuShell(widget)) { |
|
785 if ((widget = XtParent(widget)) != NULL) { |
|
786 focusWidget = XmGetFocusWidget(widget); |
|
787 } else { |
|
788 return False; |
|
789 } |
|
790 |
|
791 /* In this case, focus widget should be CascadeButtonGadget type, |
|
792 but we should send the events to its parent */ |
|
793 if (focusWidget != NULL && XmIsCascadeButtonGadget(focusWidget)) { |
|
794 widget = XtParent(focusWidget); |
|
795 } else { |
|
796 /* If something went wrong, restore the original status */ |
|
797 widget = XtWindowToWidget(awt_display, win); |
|
798 } |
|
799 } |
|
800 |
|
801 /* if focus owner is null, redirect key events to focused window */ |
|
802 if (focusWidget == NULL && findWidgetInfo(widget) == NULL) { |
|
803 focusWidget = findTopLevelByShell(widget); |
|
804 } |
|
805 |
|
806 /* If we are on a non-choice widget, process events in a normal way */ |
|
807 if ((focusWidget != NULL) && (focusWidget != widget)) { |
|
808 if (isTheSameShellWidget(focusWidget, widget)) { |
|
809 focusWidget = findTopLevelByShell(widget); |
|
810 } |
|
811 if (focusWidget != NULL) { |
|
812 peer = findPeer(&focusWidget); |
|
813 } |
|
814 if (peer != NULL) { |
|
815 widget = focusWidget; |
|
816 win = xev->xkey.window = XtWindow(focusWidget); |
|
817 } |
|
818 } |
|
819 } |
|
820 |
|
821 if ((winfo = findWidgetInfo(widget)) == NULL) { |
|
822 return False; |
|
823 } |
|
824 |
|
825 /* |
|
826 * Fix for bug 4145193 |
|
827 * |
|
828 * If a menu is up (not just a popup menu), prevent awt components from |
|
829 * getting any events until the menu is popped down. |
|
830 * Before this fix, the fact that mouse/button events were |
|
831 * preposted to the Java event queue was causing the ButtonRelease |
|
832 * (needed to pop menu down) to be seen by the menu's parent and |
|
833 * not the menu. |
|
834 */ |
|
835 if (awtMenuIsActive()) { |
|
836 Widget focusWidget = XmGetFocusWidget(widget); |
|
837 |
|
838 if (focusWidget == NULL) { |
|
839 return False; |
|
840 } |
|
841 |
|
842 /* If we are on a choice, dispatch the events to widget, but do not |
|
843 * dispatch the events if we are on popped up menu. |
|
844 */ |
|
845 if (!XmIsRowColumn(widget) || !XmIsCascadeButtonGadget(focusWidget)) { |
|
846 /* Fix for 4328557 by ibd@sparc.spb.su |
|
847 * If we are dragging mouse from choice and are currently outside |
|
848 * of it, dispatch events to the choice - the source of dragging. |
|
849 */ |
|
850 |
|
851 if ((drag_source != NULL) && (widget != drag_source) && |
|
852 (peer = findPeer(&drag_source))) { |
|
853 awt_canvas_handleEvent(drag_source, peer, xev, winfo, &cont, TRUE); |
|
854 } |
|
855 return False; |
|
856 } |
|
857 } |
|
858 |
|
859 /* If the keyboard is grabbed by a popup (such as a choice) during |
|
860 a time when a focus proxy is in effect, the abovefocusIsOnMenu |
|
861 test will not detect the sitation because the focus will be on |
|
862 the proxy. But we need events to go to Motif first, so that the |
|
863 grab can be undone when appropriate. */ |
|
864 if (keyboardGrabbed) { |
|
865 return False; |
|
866 } |
|
867 |
|
868 /* If it's a keyboard event, we need to find the peer associated */ |
|
869 /* with the widget that has the focus rather than the widget */ |
|
870 /* associated with the window in the X event. */ |
|
871 |
|
872 switch (xev->type) { |
|
873 case KeyPress: |
|
874 case KeyRelease: |
|
875 if (!(winfo->event_mask & java_awt_AWTEvent_KEY_EVENT_MASK)) |
|
876 return False; |
|
877 break; |
|
878 case FocusIn: |
|
879 case FocusOut: |
|
880 if (!(winfo->event_mask & java_awt_AWTEvent_FOCUS_EVENT_MASK)) |
|
881 return False; |
|
882 break; |
|
883 case ButtonPress: |
|
884 case ButtonRelease: |
|
885 if (!(winfo->event_mask & java_awt_AWTEvent_MOUSE_EVENT_MASK)) { |
|
886 return False; |
|
887 } |
|
888 break; |
|
889 case EnterNotify: |
|
890 case LeaveNotify: |
|
891 /* |
|
892 * Do not post the enter/leave event if it's on a subwidget |
|
893 * within the component. |
|
894 */ |
|
895 if (!(winfo->event_mask & java_awt_AWTEvent_MOUSE_EVENT_MASK) || |
|
896 widget != winfo->origin) |
|
897 return False; |
|
898 break; |
|
899 case MotionNotify: |
|
900 if (!(winfo->event_mask & java_awt_AWTEvent_MOUSE_MOTION_EVENT_MASK)) |
|
901 return False; |
|
902 break; |
|
903 default: |
|
904 return False; |
|
905 } |
|
906 |
|
907 peer = winfo->peer; |
|
908 |
|
909 /* If we found a widget and a suitable peer (either the focus |
|
910 peer above or the one associated with the widget then we |
|
911 dispatch to it. */ |
|
912 if (peer == NULL) { |
|
913 return False; |
|
914 } |
|
915 |
|
916 /* |
|
917 * Fix for bug 4173714 - java.awt.button behaves differently under |
|
918 * Win32/Solaris. |
|
919 * Component should not get any events when it's disabled. |
|
920 */ |
|
921 if (!XtIsSensitive(widget)) { |
|
922 if (xev->type == EnterNotify) { |
|
923 updateCursor(peer, CACHE_UPDATE); |
|
924 } |
|
925 return False; |
|
926 } |
|
927 |
|
928 awt_canvas_handleEvent(widget, peer, xev, winfo, &cont, TRUE); |
|
929 return (!cont); |
|
930 } /* shouldDispatchToWidget() */ |
|
931 |
|
932 |
|
933 void set_toolkit_busy(Boolean busy) { |
|
934 |
|
935 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
936 |
|
937 static jclass awtAutoShutdownClass = NULL; |
|
938 static jmethodID notifyBusyMethodID = NULL; |
|
939 static jmethodID notifyFreeMethodID = NULL; |
|
940 |
|
941 if (awtAutoShutdownClass == NULL) { |
|
942 jclass awtAutoShutdownClassLocal = (*env)->FindClass(env, "sun/awt/AWTAutoShutdown"); |
|
943 if ((*env)->ExceptionOccurred(env)) { |
|
944 (*env)->ExceptionDescribe(env); |
|
945 (*env)->ExceptionClear(env); |
|
946 } |
|
947 DASSERT(awtAutoShutdownClassLocal != NULL); |
|
948 if (awtAutoShutdownClassLocal == NULL) { |
|
949 return; |
|
950 } |
|
951 |
|
952 awtAutoShutdownClass = (jclass)(*env)->NewGlobalRef(env, awtAutoShutdownClassLocal); |
|
953 (*env)->DeleteLocalRef(env, awtAutoShutdownClassLocal); |
|
954 |
|
955 notifyBusyMethodID = (*env)->GetStaticMethodID(env, awtAutoShutdownClass, |
|
956 "notifyToolkitThreadBusy", "()V"); |
|
957 if ((*env)->ExceptionOccurred(env)) { |
|
958 (*env)->ExceptionDescribe(env); |
|
959 (*env)->ExceptionClear(env); |
|
960 } |
|
961 notifyFreeMethodID = (*env)->GetStaticMethodID(env, awtAutoShutdownClass, |
|
962 "notifyToolkitThreadFree", "()V"); |
|
963 if ((*env)->ExceptionOccurred(env)) { |
|
964 (*env)->ExceptionDescribe(env); |
|
965 (*env)->ExceptionClear(env); |
|
966 } |
|
967 DASSERT(notifyBusyMethodID != NULL); |
|
968 DASSERT(notifyFreeMethodID != NULL); |
|
969 if (notifyBusyMethodID == NULL || notifyFreeMethodID == NULL) { |
|
970 return; |
|
971 } |
|
972 } /* awtAutoShutdownClass == NULL*/ |
|
973 |
|
974 if (busy) { |
|
975 (*env)->CallStaticVoidMethod(env, awtAutoShutdownClass, |
|
976 notifyBusyMethodID); |
|
977 } else { |
|
978 (*env)->CallStaticVoidMethod(env, awtAutoShutdownClass, |
|
979 notifyFreeMethodID); |
|
980 } |
|
981 |
|
982 if ((*env)->ExceptionOccurred(env)) { |
|
983 (*env)->ExceptionDescribe(env); |
|
984 (*env)->ExceptionClear(env); |
|
985 } |
|
986 } |
|
987 |
|
988 #ifdef DEBUG |
|
989 static int32_t debugPrintLineCount = 0; /* limit debug output per line */ |
|
990 #endif |
|
991 |
|
992 /* |
|
993 * This is the main Xt event loop for the AWT. |
|
994 * |
|
995 * Because java applications are multithreaded, but X and Xt |
|
996 * are thread-dumb, we must make special considerations to |
|
997 * make ensure that the X/Xt libraries are not entered by |
|
998 * multiple threads simultaneously. |
|
999 * |
|
1000 * The biggest difference between the standard Xt loop |
|
1001 * and this loop is that we go to great lengths never to block |
|
1002 * in the X libraries. We poll() on the X event pipe, waiting |
|
1003 * for events, rather than simply calling XtAppNextEvent() and |
|
1004 * blocking. If this thread were to block in XtAppNextEvent(), |
|
1005 * no other thread could enter (e.g., to perform a paint or |
|
1006 * retrieve data). |
|
1007 */ |
|
1008 /* #ifdef DEBUG */ |
|
1009 int32_t numEventsHandled = 0; |
|
1010 /* #endif */ |
|
1011 static void |
|
1012 awt_MToolkit_loop(JNIEnv *env) |
|
1013 { |
|
1014 XtInputMask iMask; |
|
1015 int32_t fdXPipe = -1; /* pipe where X events arrive */ |
|
1016 |
|
1017 /* only privileged thread should be running here */ |
|
1018 DASSERT(awt_currentThreadIsPrivileged(env)); |
|
1019 |
|
1020 /* The pipe where X events arrive */ |
|
1021 fdXPipe = ConnectionNumber(awt_display) ; |
|
1022 |
|
1023 /* We execute events while locked, unlocking only when waiting |
|
1024 * for an event |
|
1025 */ |
|
1026 AWT_LOCK(); |
|
1027 |
|
1028 /* Create the AWT utility pipe. See the comments on awt_pipe_init() */ |
|
1029 awt_pipe_init(); |
|
1030 |
|
1031 /* |
|
1032 * Need to flush here in case data on the connection was read |
|
1033 * before we acquired the monitor. |
|
1034 * |
|
1035 * I don't get this, but I'm too chicken to remove it. -jethro 2Sep98 |
|
1036 */ |
|
1037 AWT_FLUSHOUTPUT_NOW(); |
|
1038 |
|
1039 /* |
|
1040 * ACTUALLY PROCESS EVENTS |
|
1041 */ |
|
1042 while(True) { |
|
1043 |
|
1044 /* process all events in the queue */ |
|
1045 /* #ifdef DEBUG */ |
|
1046 /* numEventsHandled = 0; */ |
|
1047 /* #endif */ |
|
1048 while (((iMask = awt_events_pending(awt_appContext)) & XtIMAll) > 0) { |
|
1049 |
|
1050 /* #ifdef DEBUG */ |
|
1051 ++numEventsHandled; |
|
1052 /* #endif */ |
|
1053 processOneEvent(iMask); |
|
1054 |
|
1055 } /* end while awt_events_pending() */ |
|
1056 /* At this point, we have exhausted the event queue */ |
|
1057 |
|
1058 /* print the number of events handled in parens */ |
|
1059 DTRACE_PRINT1("(%d events)",(int32_t)numEventsHandled); |
|
1060 #ifdef DEBUG |
|
1061 if (++debugPrintLineCount > 8) { |
|
1062 DTRACE_PRINTLN(""); |
|
1063 debugPrintLineCount = 0; |
|
1064 } |
|
1065 #endif |
|
1066 |
|
1067 AWT_NOTIFY_ALL(); /* wake up modalWait() */ |
|
1068 |
|
1069 set_toolkit_busy(False); |
|
1070 |
|
1071 /* Here, we wait for X events, outside of the X libs. When |
|
1072 * it's likely that an event is waiting, we process the queue |
|
1073 */ |
|
1074 waitForEvents(env, fdXPipe, AWT_READPIPE); |
|
1075 |
|
1076 set_toolkit_busy(True); |
|
1077 |
|
1078 } /* while(True) */ |
|
1079 |
|
1080 /* If we ever exit the loop, must unlock the toolkit */ |
|
1081 |
|
1082 } /* awt_MToolkit_loop() */ |
|
1083 |
|
1084 /* |
|
1085 * Creates the AWT utility pipe. This pipe exists solely so that |
|
1086 * we can cause the main event thread to wake up from a poll() or |
|
1087 * select() by writing to this pipe. |
|
1088 */ |
|
1089 static void |
|
1090 awt_pipe_init(void) { |
|
1091 |
|
1092 if (awt_pipe_inited) { |
|
1093 return; |
|
1094 } |
|
1095 |
|
1096 if ( pipe ( awt_pipe_fds ) == 0 ) |
|
1097 { |
|
1098 /* |
|
1099 ** the write wakes us up from the infinite sleep, which |
|
1100 ** then we cause a delay of AWT_FLUSHTIME and then we |
|
1101 ** flush. |
|
1102 */ |
|
1103 int32_t flags = 0; |
|
1104 awt_set_poll_timeout (def_poll_timeout); |
|
1105 /* set the pipe to be non-blocking */ |
|
1106 flags = fcntl ( AWT_READPIPE, F_GETFL, 0 ); |
|
1107 fcntl( AWT_READPIPE, F_SETFL, flags | O_NDELAY | O_NONBLOCK ); |
|
1108 flags = fcntl ( AWT_WRITEPIPE, F_GETFL, 0 ); |
|
1109 fcntl( AWT_WRITEPIPE, F_SETFL, flags | O_NDELAY | O_NONBLOCK ); |
|
1110 awt_pipe_inited = True; |
|
1111 } |
|
1112 else |
|
1113 { |
|
1114 AWT_READPIPE = -1; |
|
1115 AWT_WRITEPIPE = -1; |
|
1116 awt_pipe_inited = False; |
|
1117 } |
|
1118 } /* awt_pipe_init() */ |
|
1119 |
|
1120 static Window |
|
1121 proxyTopLevel(Window proxyWindow) { |
|
1122 Window parent = None, root = None, *children = NULL, retvalue = None; |
|
1123 uint32_t nchildren = 0; |
|
1124 Status res = XQueryTree(awt_display, proxyWindow, &root, &parent, |
|
1125 &children, &nchildren); |
|
1126 if (res != 0) { |
|
1127 if (nchildren > 0) { |
|
1128 retvalue = children[0]; |
|
1129 } |
|
1130 else retvalue = None; |
|
1131 if (children != NULL) { |
|
1132 XFree(children); |
|
1133 } |
|
1134 return retvalue; |
|
1135 } else { |
|
1136 return None; |
|
1137 } |
|
1138 } |
|
1139 |
|
1140 static jclass clazzF, clazzD = NULL; |
|
1141 |
|
1142 static Boolean |
|
1143 initClazzD(JNIEnv *env) { |
|
1144 jclass t_clazzD = (*env)->FindClass(env, "java/awt/Dialog"); |
|
1145 if ((*env)->ExceptionOccurred(env)) { |
|
1146 (*env)->ExceptionDescribe(env); |
|
1147 (*env)->ExceptionClear(env); |
|
1148 } |
|
1149 DASSERT(t_clazzD != NULL); |
|
1150 if (t_clazzD == NULL) { |
|
1151 return False; |
|
1152 } |
|
1153 clazzD = (*env)->NewGlobalRef(env, t_clazzD); |
|
1154 DASSERT(clazzD != NULL); |
|
1155 (*env)->DeleteLocalRef(env, t_clazzD); |
|
1156 return True; |
|
1157 } |
|
1158 |
|
1159 Boolean |
|
1160 isFrameOrDialog(jobject target, JNIEnv *env) { |
|
1161 if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
|
1162 return False; |
|
1163 } |
|
1164 |
|
1165 if (clazzF == NULL) { |
|
1166 jclass t_clazzF = (*env)->FindClass(env, "java/awt/Frame"); |
|
1167 if ((*env)->ExceptionOccurred(env)) { |
|
1168 (*env)->ExceptionDescribe(env); |
|
1169 (*env)->ExceptionClear(env); |
|
1170 } |
|
1171 DASSERT(t_clazzF != NULL); |
|
1172 if (t_clazzF == NULL) { |
|
1173 return False; |
|
1174 } |
|
1175 clazzF = (*env)->NewGlobalRef(env, t_clazzF); |
|
1176 DASSERT(clazzF != NULL); |
|
1177 (*env)->DeleteLocalRef(env, t_clazzF); |
|
1178 } |
|
1179 |
|
1180 if (clazzD == NULL && !initClazzD(env)) { |
|
1181 return False; |
|
1182 } |
|
1183 |
|
1184 return (*env)->IsInstanceOf(env, target, clazzF) || |
|
1185 (*env)->IsInstanceOf(env, target, clazzD); |
|
1186 } |
|
1187 |
|
1188 Boolean |
|
1189 isDialog(jobject target, JNIEnv *env) { |
|
1190 if (clazzD == NULL && !initClazzD(env)) { |
|
1191 return False; |
|
1192 } |
|
1193 return (*env)->IsInstanceOf(env, target, clazzD); |
|
1194 } |
|
1195 |
|
1196 // Returns a local ref to a decorated owner of the target, |
|
1197 // or NULL if the target is Frame or Dialog itself. |
|
1198 // The local ref returned should be deleted by the caller. |
|
1199 jobject |
|
1200 getOwningFrameOrDialog(jobject target, JNIEnv *env) { |
|
1201 jobject _target = (*env)->NewLocalRef(env, target); |
|
1202 jobject parent = _target; |
|
1203 Boolean isSelfFrameOrDialog = True; |
|
1204 |
|
1205 while (!isFrameOrDialog(parent, env)) { |
|
1206 isSelfFrameOrDialog = False; |
|
1207 parent = (*env)->CallObjectMethod(env, _target, componentIDs.getParent); |
|
1208 (*env)->DeleteLocalRef(env, _target); |
|
1209 _target = parent; |
|
1210 } |
|
1211 |
|
1212 if (isSelfFrameOrDialog) { |
|
1213 (*env)->DeleteLocalRef(env, parent); |
|
1214 return NULL; |
|
1215 } |
|
1216 return parent; |
|
1217 } |
|
1218 |
|
1219 Widget |
|
1220 findWindowsProxy(jobject window, JNIEnv *env) { |
|
1221 struct ComponentData *cdata; |
|
1222 jobject tlPeer; |
|
1223 jobject owner_prev = NULL, owner_new = NULL; |
|
1224 /* the owner of a Window is in its parent field */ |
|
1225 /* we may have a chain of Windows; go up the chain till we find the |
|
1226 owning Frame or Dialog */ |
|
1227 if ((*env)->EnsureLocalCapacity(env, 4) < 0) { |
|
1228 return NULL; |
|
1229 } |
|
1230 |
|
1231 if (window == NULL) return NULL; |
|
1232 |
|
1233 owner_prev = (*env)->NewLocalRef(env, window); |
|
1234 while (!JNU_IsNull(env, owner_prev) && !(isFrameOrDialog(owner_prev, env))) { |
|
1235 owner_new = (*env)->CallObjectMethod(env, owner_prev, componentIDs.getParent); |
|
1236 (*env)->DeleteLocalRef(env, owner_prev); |
|
1237 owner_prev = owner_new; |
|
1238 } |
|
1239 |
|
1240 if (owner_prev == NULL) return NULL; |
|
1241 |
|
1242 tlPeer = (*env)->GetObjectField(env, owner_prev, componentIDs.peer); |
|
1243 (*env)->DeleteLocalRef(env, owner_prev); |
|
1244 if (tlPeer == NULL) return NULL; |
|
1245 |
|
1246 cdata = (struct ComponentData *) |
|
1247 JNU_GetLongFieldAsPtr(env, tlPeer, mComponentPeerIDs.pData); |
|
1248 (*env)->DeleteLocalRef(env, tlPeer); |
|
1249 |
|
1250 if (cdata == NULL) return NULL; |
|
1251 return(findFocusProxy(cdata->widget)); |
|
1252 } |
|
1253 |
|
1254 jobject |
|
1255 findTopLevel(jobject peer, JNIEnv *env) { |
|
1256 jobject target_prev = NULL; |
|
1257 static jclass clazzW = NULL; |
|
1258 |
|
1259 if ((*env)->EnsureLocalCapacity(env, 3) < 0) { |
|
1260 return NULL; |
|
1261 } |
|
1262 |
|
1263 if (clazzW == NULL) { |
|
1264 jclass t_clazzW = (*env)->FindClass(env, "java/awt/Window"); |
|
1265 if ((*env)->ExceptionOccurred(env)) { |
|
1266 (*env)->ExceptionDescribe(env); |
|
1267 (*env)->ExceptionClear(env); |
|
1268 } |
|
1269 DASSERT(t_clazzW != NULL); |
|
1270 if (t_clazzW == NULL) { |
|
1271 return NULL; |
|
1272 } |
|
1273 clazzW = (*env)->NewGlobalRef(env, t_clazzW); |
|
1274 DASSERT(clazzW != NULL); |
|
1275 (*env)->DeleteLocalRef(env, t_clazzW); |
|
1276 } |
|
1277 target_prev = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target); |
|
1278 if (target_prev == NULL) { |
|
1279 return NULL; |
|
1280 } |
|
1281 |
|
1282 while ((target_prev != NULL) |
|
1283 && !(*env)->IsInstanceOf(env, target_prev, clazzW) ) |
|
1284 { |
|
1285 /* go up the hierarchy until we find a window */ |
|
1286 jobject target_new = (*env)->CallObjectMethod(env, target_prev, componentIDs.getParent); |
|
1287 (*env)->DeleteLocalRef(env, target_prev); |
|
1288 target_prev = target_new; |
|
1289 } |
|
1290 return target_prev; |
|
1291 } |
|
1292 |
|
1293 static Window |
|
1294 rootWindow(Window w) { |
|
1295 Window root = None; |
|
1296 Window parent = None; |
|
1297 Window *children = NULL; |
|
1298 uint32_t nchildren = 0; |
|
1299 |
|
1300 if (w != None) { |
|
1301 Status res = XQueryTree(awt_display, w, &root, &parent, &children, &nchildren); |
|
1302 if (res == 0) { |
|
1303 return None; |
|
1304 } |
|
1305 if (children != NULL) { |
|
1306 XFree(children); |
|
1307 } |
|
1308 return root; |
|
1309 } else { |
|
1310 return None; |
|
1311 } |
|
1312 } |
|
1313 |
|
1314 Boolean IsRootOf(Window root, Window child) { |
|
1315 Window w_root = None, w_parent = None, * children = NULL; |
|
1316 uint32_t c_count = 0; |
|
1317 if (root == None || child == None) { |
|
1318 return False; |
|
1319 } |
|
1320 do { |
|
1321 w_root = None; |
|
1322 w_parent = None; |
|
1323 children = NULL; |
|
1324 c_count = 0; |
|
1325 if (XQueryTree(awt_display, child, &w_root, &w_parent, |
|
1326 &children, &c_count)) { |
|
1327 if (children != NULL) { |
|
1328 XFree(children); |
|
1329 } |
|
1330 if (w_parent == None) { |
|
1331 return False; |
|
1332 } |
|
1333 if (w_parent == root) { |
|
1334 return True; |
|
1335 } |
|
1336 } else { |
|
1337 return False; |
|
1338 } |
|
1339 child = w_parent; |
|
1340 } while (True); |
|
1341 } |
|
1342 |
|
1343 Window findShellByProxy(Window proxy) { |
|
1344 Widget proxy_wid = XtWindowToWidget(awt_display, proxy); |
|
1345 while (proxy_wid != NULL && !XtIsShell(proxy_wid)) { |
|
1346 proxy_wid = XtParent(proxy_wid); |
|
1347 } |
|
1348 if (proxy_wid == NULL) { |
|
1349 return None; |
|
1350 } |
|
1351 return XtWindow(proxy_wid); |
|
1352 } |
|
1353 |
|
1354 // Window which contains focus owner when focus proxy is enabled |
|
1355 Window trueFocusWindow = None; |
|
1356 // Window which works as proxy for input events for real focus owner. |
|
1357 Window focusProxyWindow = None; |
|
1358 |
|
1359 void clearFocusPathOnWindow(Window win) { |
|
1360 if (focusProxyWindow != None && IsRootOf(win, trueFocusWindow)) { |
|
1361 XEvent ev; |
|
1362 memset(&ev, 0, sizeof(ev)); |
|
1363 ev.type = FocusOut; |
|
1364 ev.xany.send_event = True; |
|
1365 ev.xany.display = awt_display; |
|
1366 ev.xfocus.mode = NotifyNormal; |
|
1367 ev.xfocus.detail = NotifyNonlinear; |
|
1368 { |
|
1369 Window root = rootWindow(trueFocusWindow); |
|
1370 JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
1371 ev.xfocus.window = trueFocusWindow; |
|
1372 while (ev.xfocus.window != root && |
|
1373 ev.xfocus.window != None) { |
|
1374 Widget w = XtWindowToWidget(awt_display, |
|
1375 ev.xfocus.window); |
|
1376 awt_put_back_event(env, &ev); |
|
1377 if (w == NULL) { |
|
1378 break; |
|
1379 } |
|
1380 if (XtParent(w) != NULL) { |
|
1381 ev.xfocus.window = XtWindow(XtParent(w)); |
|
1382 } else { |
|
1383 ev.xfocus.window = None; |
|
1384 } |
|
1385 } |
|
1386 } |
|
1387 XSetInputFocus(awt_display, findShellByProxy(focusProxyWindow), RevertToPointerRoot, CurrentTime); |
|
1388 trueFocusWindow = None; |
|
1389 focusProxyWindow = None; |
|
1390 } |
|
1391 } |
|
1392 void clearFocusPath(Widget shell) { |
|
1393 Window w = None; |
|
1394 if (shell == NULL) { |
|
1395 return; |
|
1396 } |
|
1397 w = XtWindow(shell); |
|
1398 clearFocusPathOnWindow(w); |
|
1399 } |
|
1400 |
|
1401 void globalClearFocusPath(Widget focusOwnerShell ) { |
|
1402 if (focusProxyWindow != None) { |
|
1403 Window shellWindow = findShellByProxy(trueFocusWindow); |
|
1404 if (shellWindow != None) { |
|
1405 Widget shell = XtWindowToWidget(awt_display, shellWindow); |
|
1406 if (shell != NULL && shell != focusOwnerShell) { |
|
1407 clearFocusPath(shell); |
|
1408 } |
|
1409 } |
|
1410 } |
|
1411 } |
|
1412 |
|
1413 static void |
|
1414 focusEventForProxy(XEvent xev, |
|
1415 JNIEnv *env, |
|
1416 Window *trueFocusWindow, |
|
1417 Window *focusProxyWindow) { |
|
1418 |
|
1419 DASSERT (trueFocusWindow != NULL && focusProxyWindow != NULL); |
|
1420 if (xev.type == FocusOut) { |
|
1421 if (xev.xfocus.window == *focusProxyWindow) { |
|
1422 if (*trueFocusWindow != None) { |
|
1423 Window root = rootWindow(*trueFocusWindow); |
|
1424 focusOutEvent.xfocus.window = *trueFocusWindow; |
|
1425 #ifdef DEBUG_FOCUS |
|
1426 printf(" nulling out proxy; putting back event" |
|
1427 "\n"); |
|
1428 #endif |
|
1429 |
|
1430 while (focusOutEvent.xfocus.window != root && |
|
1431 focusOutEvent.xfocus.window != None) { |
|
1432 Widget w = XtWindowToWidget(awt_display, |
|
1433 focusOutEvent.xfocus.window); |
|
1434 awt_put_back_event(env, &focusOutEvent); |
|
1435 if (w != NULL && XtParent(w) != NULL) { |
|
1436 focusOutEvent.xfocus.window = XtWindow(XtParent(w)); |
|
1437 } else { |
|
1438 focusOutEvent.xfocus.window = None; |
|
1439 } |
|
1440 } |
|
1441 *trueFocusWindow = None; |
|
1442 *focusProxyWindow = None; |
|
1443 return; |
|
1444 } else { |
|
1445 #ifdef DEBUG_FOCUS |
|
1446 printf("\n"); |
|
1447 #endif |
|
1448 return; |
|
1449 } |
|
1450 } else { |
|
1451 #ifdef DEBUG_FOCUS |
|
1452 printf("\n"); |
|
1453 #endif |
|
1454 return; |
|
1455 } |
|
1456 } |
|
1457 } |
|
1458 |
|
1459 static void |
|
1460 focusEventForFrame(XEvent xev, Window focusProxyWindow) { |
|
1461 if (xev.type == FocusIn) { |
|
1462 if (focusProxyWindow != None) { |
|
1463 /* eat it */ |
|
1464 return; |
|
1465 } else /* FocusIn on Frame or Dialog */ { |
|
1466 XtDispatchEvent(&xev); |
|
1467 } |
|
1468 } else /* FocusOut on Frame or Dialog */{ |
|
1469 XtDispatchEvent(&xev); |
|
1470 } |
|
1471 } |
|
1472 |
|
1473 static void |
|
1474 focusEventForWindow(XEvent xev, JNIEnv *env, Window *trueFocusWindow, |
|
1475 Window *focusProxyWindow, jobject target) { |
|
1476 XEvent pev; |
|
1477 if (xev.type == FocusIn && xev.xfocus.mode == NotifyNormal) { |
|
1478 /* If it's a FocusIn, allow it to process, then set |
|
1479 focus to focus proxy */ |
|
1480 Widget focusProxy; |
|
1481 focusProxy = findWindowsProxy(target, env); |
|
1482 if (focusProxy != NULL) { |
|
1483 XtDispatchEvent(&xev); |
|
1484 *focusProxyWindow = XtWindow(focusProxy); |
|
1485 |
|
1486 XSetInputFocus(awt_display, *focusProxyWindow, |
|
1487 RevertToParent, |
|
1488 CurrentTime); |
|
1489 |
|
1490 XPeekEvent(awt_display, &pev); |
|
1491 while (pev.type == FocusIn) { |
|
1492 XNextEvent(awt_display, &xev); |
|
1493 XPeekEvent(awt_display, &pev); |
|
1494 } |
|
1495 *trueFocusWindow = xev.xany.window; |
|
1496 |
|
1497 } /* otherwise error */ |
|
1498 } else /* FocusOut */ { |
|
1499 /* If it's a FocusOut on a Window, discard it unless |
|
1500 it's an event generated by us. */ |
|
1501 if (xev.xany.send_event) { |
|
1502 XtDispatchEvent(&xev); |
|
1503 } |
|
1504 } |
|
1505 } |
|
1506 |
|
1507 Boolean |
|
1508 isAncestor(Window ancestor, Window child) { |
|
1509 Window *children; |
|
1510 uint32_t nchildren; |
|
1511 Boolean retvalue = False; |
|
1512 |
|
1513 while (child != ancestor) { |
|
1514 Window parent, root; |
|
1515 Status status; |
|
1516 |
|
1517 status = XQueryTree(awt_display, child, &root, &parent, |
|
1518 &children, &nchildren); |
|
1519 if (status == 0) return False; /* should be an error of some sort? */ |
|
1520 |
|
1521 if (parent == root) { |
|
1522 if (child != ancestor) { |
|
1523 retvalue = False; |
|
1524 break; |
|
1525 } else { |
|
1526 retvalue = True; |
|
1527 break; |
|
1528 } |
|
1529 } |
|
1530 if (parent == ancestor) { retvalue = True; break; } |
|
1531 if (nchildren > 0) XFree(children); |
|
1532 child = parent; |
|
1533 } |
|
1534 if (nchildren > 0) XFree(children); |
|
1535 return retvalue; |
|
1536 } |
|
1537 |
|
1538 /** |
|
1539 * Returns focusability of the corresponding Java Window object |
|
1540 */ |
|
1541 Boolean |
|
1542 isFocusableWindow(Window w) { |
|
1543 Widget wid = NULL; |
|
1544 JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
1545 |
|
1546 wid = XtWindowToWidget(awt_display, w); |
|
1547 while (wid != NULL && !XtIsShell(wid)) { |
|
1548 wid = XtParent(wid); |
|
1549 } |
|
1550 |
|
1551 // If the window doesn't have shell consider it focusable as all windows |
|
1552 // are focusable by default |
|
1553 if (wid == NULL) return True; |
|
1554 |
|
1555 return isFocusableWindowByShell(env, wid); |
|
1556 } |
|
1557 |
|
1558 void postUngrabEvent(Widget shell) { |
|
1559 JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
1560 Widget canvas = findTopLevelByShell(shell); |
|
1561 if (canvas != NULL) { |
|
1562 jobject peer = findPeer(&canvas); |
|
1563 if (peer != NULL) { |
|
1564 JNU_CallMethodByName(env, NULL, peer, "postUngrabEvent", "()V", NULL); |
|
1565 } |
|
1566 } |
|
1567 } |
|
1568 |
|
1569 Boolean eventInsideGrabbed(XEvent * ev) { |
|
1570 if (grabbed_widget == NULL) { |
|
1571 return False; |
|
1572 } |
|
1573 |
|
1574 switch (ev->xany.type) { |
|
1575 case LeaveNotify: |
|
1576 case ButtonPress: |
|
1577 case ButtonRelease: |
|
1578 case MotionNotify: |
|
1579 case EnterNotify: |
|
1580 { |
|
1581 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
1582 Widget grab = findTopLevelByShell(grabbed_widget); |
|
1583 if (grab != NULL) { |
|
1584 jobject peer = findPeer(&grab); |
|
1585 Widget target = XtWindowToWidget(awt_display, ev->xbutton.window); |
|
1586 jobject targetPeer = findPeer(&target); |
|
1587 if (peer != NULL) { |
|
1588 return JNU_CallMethodByName(env, NULL, peer, "processUngrabMouseEvent", "(Lsun/awt/motif/MComponentPeer;III)Z", |
|
1589 targetPeer, ev->xbutton.x_root, ev->xbutton.y_root, |
|
1590 ev->xany.type, NULL).z; |
|
1591 } |
|
1592 } |
|
1593 return False; |
|
1594 } |
|
1595 case FocusOut: |
|
1596 if (ev->xfocus.window == XtWindow(grabbed_widget) || |
|
1597 isAncestor(XtWindow(grabbed_widget), ev->xfocus.window)) |
|
1598 { |
|
1599 postUngrabEvent(grabbed_widget); |
|
1600 return True; |
|
1601 } |
|
1602 default: |
|
1603 return True; |
|
1604 } |
|
1605 } |
|
1606 |
|
1607 /** |
|
1608 * Processes and removes one X/Xt event from the Xt event queue. |
|
1609 * Handles events pushed back via awt_put_back_event() FIRST, |
|
1610 * then new events on the X queue |
|
1611 */ |
|
1612 static void |
|
1613 processOneEvent(XtInputMask iMask) { |
|
1614 XEvent xev; |
|
1615 Boolean haveEvent = False; |
|
1616 if (putbackQueueCount > 0) { |
|
1617 // There is a pushed-back event - handle it first |
|
1618 if (awt_get_next_put_back_event(&xev) == 0) { |
|
1619 if (xev.xany.send_event != SPECIAL_KEY_EVENT) { |
|
1620 #ifdef DEBUG_FOCUS |
|
1621 if (xev.type == FocusOut) { |
|
1622 printf("putback FocusOut on window %d, mode %d, " |
|
1623 "detail %d, send_event %d\n", |
|
1624 xev.xfocus.window, xev.xfocus.mode, |
|
1625 xev.xfocus.detail, xev.xfocus.send_event); |
|
1626 } |
|
1627 #endif |
|
1628 eventNumber++; |
|
1629 XtDispatchEvent(&xev); |
|
1630 return; |
|
1631 } else { |
|
1632 haveEvent = True; |
|
1633 } |
|
1634 } |
|
1635 } |
|
1636 |
|
1637 if (haveEvent || XtAppPeekEvent(awt_appContext, &xev)) { |
|
1638 /* |
|
1639 * Fix for BugTraq ID 4041235, 4100167: |
|
1640 * First check that the event still has a widget, because |
|
1641 * the widget may have been destroyed by another thread. |
|
1642 */ |
|
1643 Widget widget=XtWindowToWidget(awt_display, xev.xany.window); |
|
1644 eventNumber++; |
|
1645 #ifdef __linux__ |
|
1646 statusWindowEventHandler(xev); |
|
1647 #endif |
|
1648 xembed_eventHandler(&xev); |
|
1649 xembed_serverEventHandler(&xev); |
|
1650 syncWait_eventHandler(&xev); |
|
1651 |
|
1652 if (!haveEvent && awt_dnd_process_event(&xev)) { |
|
1653 return; |
|
1654 } |
|
1655 |
|
1656 if ((widget == NULL) || (!XtIsObject(widget)) || |
|
1657 (widget->core.being_destroyed)) { |
|
1658 /* |
|
1659 * if we get here, the event could be one of |
|
1660 * the following: |
|
1661 * - notification that a "container" of |
|
1662 * any of our embedded frame has been moved |
|
1663 * - event understandable by XFilterEvent |
|
1664 * - for one of our old widget which has gone away |
|
1665 */ |
|
1666 XNextEvent(awt_display, &xev); |
|
1667 |
|
1668 if (widget == NULL) { |
|
1669 /* an embedded frame container has been moved? */ |
|
1670 if (awt_util_processEventForEmbeddedFrame(&xev)) { |
|
1671 return; |
|
1672 } |
|
1673 |
|
1674 /* manager selections related event? */ |
|
1675 if (awt_mgrsel_processEvent(&xev)) { |
|
1676 return; |
|
1677 } |
|
1678 } |
|
1679 |
|
1680 /* |
|
1681 * Fix for BugTraq ID 4196573: |
|
1682 * Call XFilterEvent() to give a chance to X Input |
|
1683 * Method to process this event before being |
|
1684 * discarded. |
|
1685 */ |
|
1686 (void) XFilterEvent(&xev, NULL); |
|
1687 return; |
|
1688 } |
|
1689 |
|
1690 /* There is an X event on the queue. */ |
|
1691 switch (xev.type) { |
|
1692 case KeyPress: |
|
1693 case KeyRelease: |
|
1694 case ButtonPress: |
|
1695 case ButtonRelease: |
|
1696 case MotionNotify: |
|
1697 case EnterNotify: |
|
1698 case LeaveNotify: |
|
1699 /* Fix for BugTraq ID 4048060. Dispatch scrolling events |
|
1700 immediately to the ScrollBar widget to prevent spurious |
|
1701 continuous scrolling. Otherwise, if the application is busy, |
|
1702 the ButtonRelease event is not dispatched in time to prevent |
|
1703 a ScrollBar timeout from expiring, and restarting the |
|
1704 continuous scrolling timer. |
|
1705 */ |
|
1706 if ((xev.type == ButtonPress || |
|
1707 xev.type == ButtonRelease || |
|
1708 (xev.type == MotionNotify && |
|
1709 (xev.xmotion.state == Button1Mask || |
|
1710 xev.xmotion.state == Button2Mask || |
|
1711 xev.xmotion.state == Button3Mask))) && |
|
1712 (XtIsSubclass(widget, xmScrollBarWidgetClass))) { |
|
1713 /* Use XNextEvent instead of XtAppNextEvent, because |
|
1714 XtAppNextEvent processes timers before getting the next X |
|
1715 event, causing a race condition, since the TimerEvent |
|
1716 callback in the ScrollBar widget restarts the continuous |
|
1717 scrolling timer. |
|
1718 */ |
|
1719 XNextEvent(awt_display, &xev); |
|
1720 |
|
1721 XtDispatchEvent(&xev); |
|
1722 XSync(awt_display, False); |
|
1723 |
|
1724 // This is the event on scrollbar. Key, Motion, |
|
1725 // Enter/Leave dispatch as usual, Button should |
|
1726 // generate Ungrab after Java mouse event |
|
1727 if (xev.type == ButtonPress && grabbed_widget != NULL) { |
|
1728 eventInsideGrabbed(&xev); |
|
1729 } |
|
1730 } |
|
1731 else { |
|
1732 if (!haveEvent) XtAppNextEvent(awt_appContext, &xev); |
|
1733 |
|
1734 // This is an event on one of our widgets. Key, |
|
1735 // Motion, Enter/Leave dispatch as usual, Button |
|
1736 // should generate Ungrab after Java mouse event |
|
1737 /* if (grabbed_widget != NULL && !eventInsideGrabbed(&xev)) { */ |
|
1738 /* return; */ |
|
1739 /* } */ |
|
1740 |
|
1741 if (xev.type == ButtonPress) { |
|
1742 Window window = findShellByProxy(xev.xbutton.window); |
|
1743 if (window != None) { |
|
1744 XWindowAttributes winAttr; |
|
1745 memset(&winAttr, 0, sizeof(XWindowAttributes)); |
|
1746 XGetWindowAttributes(awt_display, window, &winAttr); |
|
1747 if (winAttr.override_redirect == TRUE && isFocusableWindow(window)) { |
|
1748 XSetInputFocus(awt_display, window, RevertToPointerRoot, CurrentTime); |
|
1749 } |
|
1750 } |
|
1751 } |
|
1752 if(xev.type == KeyPress) { |
|
1753 #ifdef DEBUG_FOCUS |
|
1754 printf("KeyPress on window %d\n", xev.xany.window); |
|
1755 #endif |
|
1756 } |
|
1757 |
|
1758 /* this could be moved to shouldDispatchToWidget */ |
|
1759 /* if there is a proxy in effect, dispatch key events |
|
1760 through the proxy */ |
|
1761 if ((xev.type == KeyPress || xev.type == KeyRelease) && |
|
1762 !keyboardGrabbed && !haveEvent) { |
|
1763 if (focusProxyWindow != None) { |
|
1764 Widget widget; |
|
1765 struct WidgetInfo *winfo; |
|
1766 Boolean cont; |
|
1767 /* Key event should be posted to the top-level |
|
1768 widget of the proxy */ |
|
1769 xev.xany.window = proxyTopLevel(focusProxyWindow); |
|
1770 widget = XtWindowToWidget(awt_display, |
|
1771 xev.xany.window); |
|
1772 if (widget == NULL) return; |
|
1773 if ((winfo = findWidgetInfo(widget)) == NULL) { |
|
1774 return; |
|
1775 } |
|
1776 awt_canvas_handleEvent(widget, winfo->peer, &xev, |
|
1777 winfo, &cont, TRUE); |
|
1778 return; |
|
1779 } |
|
1780 } |
|
1781 if (!shouldDispatchToWidget(&xev)) { |
|
1782 XtDispatchEvent(&xev); |
|
1783 } |
|
1784 |
|
1785 // See comment above - "after time" is here. |
|
1786 if (grabbed_widget != NULL && xev.type == ButtonPress) { |
|
1787 eventInsideGrabbed(&xev); |
|
1788 } |
|
1789 } |
|
1790 |
|
1791 |
|
1792 break; |
|
1793 |
|
1794 case FocusIn: |
|
1795 case FocusOut: { |
|
1796 void *peer; |
|
1797 jobject target; |
|
1798 |
|
1799 JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
1800 |
|
1801 #ifdef DEBUG_FOCUS |
|
1802 if (xev.type == FocusIn) { |
|
1803 |
|
1804 fprintf(stderr, "FocusIn on window %x, mode %d, detail %d, " |
|
1805 "send_event %d\n", xev.xfocus.window, |
|
1806 xev.xfocus.mode, xev.xfocus.detail, |
|
1807 xev.xfocus.send_event); |
|
1808 } else { |
|
1809 fprintf(stderr, "FocusOut on window %x, mode %d, detail %d, " |
|
1810 "send_event %d\n", xev.xfocus.window, |
|
1811 xev.xfocus.mode, xev.xfocus.detail, |
|
1812 xev.xfocus.send_event); |
|
1813 } |
|
1814 #endif |
|
1815 XtAppNextEvent(awt_appContext, &xev); |
|
1816 |
|
1817 if (xev.xfocus.detail == NotifyVirtual || |
|
1818 xev.xfocus.detail == NotifyNonlinearVirtual) { |
|
1819 #ifdef DEBUG_FOCUS |
|
1820 printf("discarding\n"); |
|
1821 #endif |
|
1822 return; |
|
1823 } |
|
1824 |
|
1825 // Check for xembed on this window. If it is active and this is not XEmbed focus |
|
1826 // event(send_event = 0) then we should skip it |
|
1827 if (isXEmbedActiveByWindow(xev.xfocus.window) && !xev.xfocus.send_event) { |
|
1828 return; |
|
1829 } |
|
1830 |
|
1831 /* In general, we need to to block out focus events |
|
1832 that are caused by keybaord grabs initiated by |
|
1833 dragging the title bar or the scrollbar. But we |
|
1834 need to let through the ones that are aimed at |
|
1835 choice boxes or menus. So we keep track of when |
|
1836 the keyboard is grabbed by a popup. */ |
|
1837 |
|
1838 if (awt_isAwtMenuWidget(widget)) { |
|
1839 if (xev.type == FocusIn && |
|
1840 xev.xfocus.mode == NotifyGrab) { |
|
1841 extern Boolean poppingDown; |
|
1842 if (!poppingDown) { |
|
1843 keyboardGrabbed = True; |
|
1844 } |
|
1845 } else /* FocusOut */ { |
|
1846 if (xev.type == FocusOut && |
|
1847 xev.xfocus.mode == NotifyUngrab) { |
|
1848 keyboardGrabbed = False; |
|
1849 } |
|
1850 } |
|
1851 } |
|
1852 |
|
1853 if (focusProxyWindow != None) { |
|
1854 #ifdef DEBUG_FOCUS |
|
1855 printf("non-null proxy; proxy = %d ", focusProxyWindow); |
|
1856 #endif |
|
1857 if (trueFocusWindow != None) { |
|
1858 /* trueFocusWindow should never be None here, but if |
|
1859 things ever get skewed, we want to be able to |
|
1860 recover rather than crash */ |
|
1861 focusEventForProxy(xev, env, &trueFocusWindow, |
|
1862 &focusProxyWindow); |
|
1863 return; |
|
1864 } else { |
|
1865 /* beartrap -- remove before shipping */ |
|
1866 /* printf("trueFocusWindow None in processOneEvent;\n"); */ |
|
1867 /* printf("Please file a bug\n"); */ |
|
1868 } |
|
1869 } |
|
1870 |
|
1871 peer = findPeer(&widget); |
|
1872 if (peer == NULL) { |
|
1873 #ifdef DEBUG_FOCUS |
|
1874 printf("null peer -- shouldn't see in java handler\n"); |
|
1875 #endif |
|
1876 XtDispatchEvent(&xev); |
|
1877 return; |
|
1878 } |
|
1879 |
|
1880 /* Find the top-level component */ |
|
1881 |
|
1882 if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
|
1883 return; |
|
1884 } |
|
1885 target = findTopLevel(peer, env); |
|
1886 if (target == NULL) { |
|
1887 JNU_ThrowNullPointerException(env, "component without a " |
|
1888 "window"); |
|
1889 return; |
|
1890 } |
|
1891 |
|
1892 if (isFrameOrDialog(target, env)) { |
|
1893 #ifdef DEBUG_FOCUS |
|
1894 printf("Focus event directed at a frame; frame = %d\n", |
|
1895 xev.xany.window); |
|
1896 #endif |
|
1897 focusEventForFrame(xev, focusProxyWindow); |
|
1898 (*env)->DeleteLocalRef(env, target); |
|
1899 return; |
|
1900 } else { |
|
1901 #ifdef DEBUG_FOCUS |
|
1902 printf("Focus event directed at a window; window = %d\n", |
|
1903 xev.xany.window); |
|
1904 #endif |
|
1905 focusEventForWindow(xev, env, &trueFocusWindow, |
|
1906 &focusProxyWindow, target); |
|
1907 (*env)->DeleteLocalRef(env, target); |
|
1908 return; |
|
1909 } |
|
1910 } |
|
1911 |
|
1912 case UnmapNotify: |
|
1913 #ifdef DEBUG_FOCUS |
|
1914 printf("Unmap on window %d\n", xev.xany.window); |
|
1915 printf("True focus window is %d\n", trueFocusWindow); |
|
1916 #endif |
|
1917 clearFocusPathOnWindow(xev.xunmap.window); |
|
1918 |
|
1919 default: |
|
1920 XtAppProcessEvent(awt_appContext, iMask); |
|
1921 break; |
|
1922 } |
|
1923 } |
|
1924 else { |
|
1925 /* There must be a timer, alternate input, or signal event. */ |
|
1926 XtAppProcessEvent(awt_appContext, iMask & ~XtIMXEvent); |
|
1927 } |
|
1928 |
|
1929 } /* processOneEvent() */ |
|
1930 |
|
1931 /* |
|
1932 * Waits for X/Xt events to appear on the pipe. Returns only when |
|
1933 * it is likely (but not definite) that there are events waiting to |
|
1934 * be processed. |
|
1935 * |
|
1936 * This routine also flushes the outgoing X queue, when the |
|
1937 * awt_next_flush_time has been reached. |
|
1938 * |
|
1939 * If fdAWTPipe is greater or equal than zero the routine also |
|
1940 * checks if there are events pending on the putback queue. |
|
1941 */ |
|
1942 void |
|
1943 waitForEvents(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe) { |
|
1944 |
|
1945 while ((fdAWTPipe >= 0 && awt_events_pending(awt_appContext) == 0) || |
|
1946 (fdAWTPipe < 0 && XtAppPending(awt_appContext) == 0)) { |
|
1947 #ifdef USE_SELECT |
|
1948 performSelect(env,fdXPipe,fdAWTPipe); |
|
1949 #else |
|
1950 performPoll(env,fdXPipe,fdAWTPipe); |
|
1951 #endif |
|
1952 if ((awt_next_flush_time > 0) && |
|
1953 (awtJNI_TimeMillis() > awt_next_flush_time)) { |
|
1954 AWT_FLUSHOUTPUT_NOW(); |
|
1955 } |
|
1956 } /* end while awt_events_pending() == 0 */ |
|
1957 } /* waitForEvents() */ |
|
1958 |
|
1959 /************************************************************************* |
|
1960 ** ** |
|
1961 ** WE USE EITHER select() OR poll(), DEPENDING ON THE USE_SELECT ** |
|
1962 ** COMPILE-TIME CONSTANT. ** |
|
1963 ** ** |
|
1964 *************************************************************************/ |
|
1965 |
|
1966 #ifdef USE_SELECT |
|
1967 |
|
1968 static struct fd_set rdset; |
|
1969 struct timeval sel_time; |
|
1970 |
|
1971 /* |
|
1972 * Performs select() on both the X pipe and our AWT utility pipe. |
|
1973 * Returns when data arrives or the operation times out. |
|
1974 * |
|
1975 * Not all Xt events come across the X pipe (e.g., timers |
|
1976 * and alternate inputs), so we must time out every now and |
|
1977 * then to check the Xt event queue. |
|
1978 * |
|
1979 * The fdAWTPipe will be empty when this returns. |
|
1980 */ |
|
1981 static void |
|
1982 performSelect(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe) { |
|
1983 |
|
1984 int32_t result; |
|
1985 int32_t count; |
|
1986 int32_t nfds = 1; |
|
1987 uint32_t timeout = awt_get_poll_timeout(False); |
|
1988 |
|
1989 /* Fixed 4250354 7/28/99 ssi@sparc.spb.su |
|
1990 * Cleaning up Global Refs in case of No Events |
|
1991 */ |
|
1992 awtJNI_CleanupGlobalRefs(); |
|
1993 |
|
1994 FD_ZERO( &rdset ); |
|
1995 FD_SET(fdXPipe, &rdset); |
|
1996 if (fdAWTPipe >= 0) { |
|
1997 nfds++; |
|
1998 FD_SET(fdAWTPipe, &rdset); |
|
1999 } |
|
2000 if (timeout == 0) { |
|
2001 // be sure other threads get a chance |
|
2002 awtJNI_ThreadYield(env); |
|
2003 } |
|
2004 // set the appropriate time values. The DASSERT() in |
|
2005 // MToolkit_run() makes sure that this will not overflow |
|
2006 sel_time.tv_sec = (timeout * 1000) / (1000 * 1000); |
|
2007 sel_time.tv_usec = (timeout * 1000) % (1000 * 1000); |
|
2008 AWT_NOFLUSH_UNLOCK(); |
|
2009 result = select(nfds, &rdset, 0, 0, &sel_time); |
|
2010 AWT_LOCK(); |
|
2011 |
|
2012 /* reset tick if this was not a time out */ |
|
2013 if (result == 0) { |
|
2014 /* select() timed out -- update timeout value */ |
|
2015 awt_get_poll_timeout(True); |
|
2016 } |
|
2017 if (fdAWTPipe >= 0 && FD_ISSET ( fdAWTPipe, &rdset ) ) |
|
2018 { |
|
2019 /* There is data on the AWT pipe - empty it */ |
|
2020 do { |
|
2021 count = read(fdAWTPipe, read_buf, AWT_POLL_BUFSIZE ); |
|
2022 } while (count == AWT_POLL_BUFSIZE ); |
|
2023 } |
|
2024 } /* performSelect() */ |
|
2025 |
|
2026 #else /* !USE_SELECT */ |
|
2027 |
|
2028 /* |
|
2029 * Polls both the X pipe and our AWT utility pipe. Returns |
|
2030 * when there is data on one of the pipes, or the operation times |
|
2031 * out. |
|
2032 * |
|
2033 * Not all Xt events come across the X pipe (e.g., timers |
|
2034 * and alternate inputs), so we must time out every now and |
|
2035 * then to check the Xt event queue. |
|
2036 * |
|
2037 * The fdAWTPipe will be empty when this returns. |
|
2038 */ |
|
2039 static void |
|
2040 performPoll(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe) { |
|
2041 |
|
2042 static struct pollfd pollFds[2]; |
|
2043 uint32_t timeout = awt_get_poll_timeout(False); |
|
2044 int32_t result; |
|
2045 int32_t count; |
|
2046 |
|
2047 /* Fixed 4250354 7/28/99 ssi@sparc.spb.su |
|
2048 * Cleaning up Global Refs in case of No Events |
|
2049 */ |
|
2050 awtJNI_CleanupGlobalRefs(); |
|
2051 |
|
2052 pollFds[0].fd = fdXPipe; |
|
2053 pollFds[0].events = POLLRDNORM; |
|
2054 pollFds[0].revents = 0; |
|
2055 |
|
2056 pollFds[1].fd = fdAWTPipe; |
|
2057 pollFds[1].events = POLLRDNORM; |
|
2058 pollFds[1].revents = 0; |
|
2059 |
|
2060 AWT_NOFLUSH_UNLOCK(); |
|
2061 |
|
2062 /* print the poll timeout time in brackets */ |
|
2063 DTRACE_PRINT1("[%dms]",(int32_t)timeout); |
|
2064 #ifdef DEBUG |
|
2065 if (++debugPrintLineCount > 8) { |
|
2066 DTRACE_PRINTLN(""); |
|
2067 debugPrintLineCount = 0; |
|
2068 } |
|
2069 #endif |
|
2070 /* ACTUALLY DO THE POLL() */ |
|
2071 if (timeout == 0) { |
|
2072 // be sure other threads get a chance |
|
2073 awtJNI_ThreadYield(env); |
|
2074 } |
|
2075 result = poll( pollFds, 2, (int32_t) timeout ); |
|
2076 |
|
2077 #ifdef DEBUG |
|
2078 DTRACE_PRINT1("[poll()->%d]", result); |
|
2079 if (++debugPrintLineCount > 8) { |
|
2080 DTRACE_PRINTLN(""); |
|
2081 debugPrintLineCount = 0; |
|
2082 } |
|
2083 #endif |
|
2084 AWT_LOCK(); |
|
2085 if (result == 0) { |
|
2086 /* poll() timed out -- update timeout value */ |
|
2087 awt_get_poll_timeout(True); |
|
2088 } |
|
2089 if ( pollFds[1].revents ) |
|
2090 { |
|
2091 /* There is data on the AWT pipe - empty it */ |
|
2092 do { |
|
2093 count = read(AWT_READPIPE, read_buf, AWT_POLL_BUFSIZE ); |
|
2094 } while (count == AWT_POLL_BUFSIZE ); |
|
2095 DTRACE_PRINTLN1("wokeup on AWTPIPE, timeout:%d", timeout); |
|
2096 } |
|
2097 return; |
|
2098 |
|
2099 } /* performPoll() */ |
|
2100 |
|
2101 #endif /* !USE_SELECT */ |
|
2102 |
|
2103 /* |
|
2104 * Pushes an X event back on the queue to be handled |
|
2105 * later. |
|
2106 * |
|
2107 * Ignores the request if event is NULL |
|
2108 */ |
|
2109 void |
|
2110 awt_put_back_event(JNIEnv *env, XEvent *event) { |
|
2111 |
|
2112 Boolean addIt = True; |
|
2113 if (putbackQueueCount >= putbackQueueCapacity) { |
|
2114 /* not enough room - alloc 50% more space */ |
|
2115 int32_t newCapacity; |
|
2116 XEvent *newQueue; |
|
2117 newCapacity = putbackQueueCapacity * 3 / 2; |
|
2118 if ((newCapacity - putbackQueueCapacity) |
|
2119 < PUTBACK_QUEUE_MIN_INCREMENT) { |
|
2120 /* always increase by at least min increment */ |
|
2121 newCapacity = putbackQueueCapacity + PUTBACK_QUEUE_MIN_INCREMENT; |
|
2122 } |
|
2123 newQueue = (XEvent*)realloc( |
|
2124 putbackQueue, newCapacity*(sizeof(XEvent))); |
|
2125 if (newQueue == NULL) { |
|
2126 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
|
2127 addIt = False; |
|
2128 } else { |
|
2129 putbackQueue = newQueue; |
|
2130 putbackQueueCapacity = newCapacity; |
|
2131 } |
|
2132 } |
|
2133 if (addIt) { |
|
2134 char oneChar = 'p'; |
|
2135 memcpy(&(putbackQueue[putbackQueueCount]), event, sizeof(XEvent)); |
|
2136 putbackQueueCount++; |
|
2137 |
|
2138 // wake up the event loop, if it's sleeping |
|
2139 write (AWT_WRITEPIPE, &oneChar, 1); |
|
2140 } |
|
2141 |
|
2142 return; |
|
2143 } /* awt_put_back_event() */ |
|
2144 |
|
2145 /* |
|
2146 * Gets the next event that has been pushed back onto the queue. |
|
2147 * Returns 0 and fills in xev_out if successful |
|
2148 */ |
|
2149 static int32_t |
|
2150 awt_get_next_put_back_event(XEvent *xev_out) { |
|
2151 |
|
2152 Boolean err = False; |
|
2153 if (putbackQueueCount < 1) { |
|
2154 err = True; |
|
2155 } else { |
|
2156 memcpy(xev_out, &(putbackQueue[0]), sizeof(XEvent)); |
|
2157 } |
|
2158 if (!err) { |
|
2159 /* remove it from the queue */ |
|
2160 if (putbackQueueCount == 1) { |
|
2161 |
|
2162 // queue is now empty |
|
2163 if (putbackQueueCapacity > PUTBACK_QUEUE_MIN_INCREMENT) { |
|
2164 |
|
2165 /* Too much space -- delete it and rebuild later */ |
|
2166 free(putbackQueue); |
|
2167 putbackQueue = NULL; |
|
2168 putbackQueueCapacity = 0; |
|
2169 } |
|
2170 } else { |
|
2171 /* more than 1 event in queue - shift all events to the left */ |
|
2172 /* We don't free the allocated memory until the queue |
|
2173 becomes empty, just 'cause it's easier that way. */ |
|
2174 /* NOTE: use memmove(), because the memory blocks overlap */ |
|
2175 memmove(&(putbackQueue[0]), &(putbackQueue[1]), |
|
2176 (putbackQueueCount-1)*sizeof(XEvent)); |
|
2177 } |
|
2178 --putbackQueueCount; |
|
2179 } |
|
2180 DASSERT(putbackQueueCount >= 0); |
|
2181 |
|
2182 return (err? -1:0); |
|
2183 |
|
2184 } /* awt_get_next_put_back_event() */ |
|
2185 |
|
2186 /** |
|
2187 * Determines whether or not there are X or Xt events pending. |
|
2188 * Looks at the putbackQueue. |
|
2189 */ |
|
2190 static XtInputMask |
|
2191 awt_events_pending(XtAppContext appContext) { |
|
2192 XtInputMask imask = 0L; |
|
2193 imask = XtAppPending(appContext); |
|
2194 if (putbackQueueCount > 0) { |
|
2195 imask |= XtIMXEvent; |
|
2196 } |
|
2197 return imask; |
|
2198 } |
|
2199 |
|
2200 |
|
2201 #ifndef NOMODALFIX |
|
2202 #define WIDGET_ARRAY_SIZE 5; |
|
2203 static int32_t arraySize = 0; |
|
2204 static int32_t arrayIndx = 0; |
|
2205 static Widget *dShells = NULL; |
|
2206 |
|
2207 void |
|
2208 awt_shellPoppedUp(Widget shell, |
|
2209 XtPointer modal, |
|
2210 XtPointer call_data) |
|
2211 { |
|
2212 if (arrayIndx == arraySize ) { |
|
2213 /* if we have not allocate an array, do it first */ |
|
2214 if (arraySize == 0) { |
|
2215 arraySize += WIDGET_ARRAY_SIZE; |
|
2216 dShells = (Widget *) malloc(sizeof(Widget) * arraySize); |
|
2217 } else { |
|
2218 arraySize += WIDGET_ARRAY_SIZE; |
|
2219 dShells = (Widget *) realloc((void *)dShells, sizeof(Widget) * arraySize); |
|
2220 } |
|
2221 } |
|
2222 |
|
2223 dShells[arrayIndx] = shell; |
|
2224 arrayIndx++; |
|
2225 } |
|
2226 |
|
2227 void |
|
2228 awt_shellPoppedDown(Widget shell, |
|
2229 XtPointer modal, |
|
2230 XtPointer call_data) |
|
2231 { |
|
2232 arrayIndx--; |
|
2233 |
|
2234 if (dShells[arrayIndx] == shell) { |
|
2235 dShells[arrayIndx] = NULL; |
|
2236 return; |
|
2237 } else { |
|
2238 int32_t i; |
|
2239 |
|
2240 /* find the position of the shell in the array */ |
|
2241 for (i = arrayIndx; i >= 0; i--) { |
|
2242 if (dShells[i] == shell) { |
|
2243 break; |
|
2244 } |
|
2245 } |
|
2246 |
|
2247 /* remove the found element */ |
|
2248 while (i <= arrayIndx-1) { |
|
2249 dShells[i] = dShells[i+1]; |
|
2250 i++; |
|
2251 } |
|
2252 } |
|
2253 } |
|
2254 |
|
2255 Boolean |
|
2256 awt_isWidgetModal(Widget widget) |
|
2257 { |
|
2258 Widget w; |
|
2259 |
|
2260 for (w = widget; !XtIsShell(w); w = XtParent(w)) { } |
|
2261 |
|
2262 while (w != NULL) { |
|
2263 if (w == dShells[arrayIndx-1]) { |
|
2264 return True; |
|
2265 } |
|
2266 w = XtParent(w); |
|
2267 } |
|
2268 return False; |
|
2269 } |
|
2270 |
|
2271 Boolean |
|
2272 awt_isModal() |
|
2273 { |
|
2274 return (arrayIndx > 0); |
|
2275 } |
|
2276 #endif // NOMODALFIX |
|
2277 |
|
2278 |
|
2279 /* |
|
2280 * Simply waits for terminateFn() to return True. Waits on the |
|
2281 * awt lock and is notified to check its state by the main event |
|
2282 * loop whenever the Xt event queue is empty. |
|
2283 * |
|
2284 * NOTE: when you use this routine check if it can be called on the event |
|
2285 * dispatch thread during drag-n-drop operation and update |
|
2286 * secondary_loop_event() predicate to prevent deadlock. |
|
2287 */ |
|
2288 void |
|
2289 awt_MToolkit_modalWait(int32_t (*terminateFn) (void *data), void *data ) |
|
2290 { |
|
2291 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
2292 |
|
2293 AWT_LOCK(); |
|
2294 AWT_FLUSHOUTPUT_NOW(); |
|
2295 while ((*terminateFn) (data) == 0) { |
|
2296 AWT_WAIT(AWT_MAX_POLL_TIMEOUT); |
|
2297 if ((*env)->ExceptionCheck(env)) { |
|
2298 (*env)->ExceptionClear(env); |
|
2299 break; |
|
2300 } |
|
2301 } |
|
2302 AWT_NOTIFY_ALL(); |
|
2303 AWT_UNLOCK(); |
|
2304 } |
|
2305 |
|
2306 static uint32_t |
|
2307 colorToRGB(XColor * color) |
|
2308 { |
|
2309 int32_t rgb = 0; |
|
2310 |
|
2311 rgb |= ((color->red >> 8) << 16); |
|
2312 rgb |= ((color->green >> 8) << 8); |
|
2313 rgb |= ((color->blue >> 8) << 0); |
|
2314 |
|
2315 return rgb; |
|
2316 } |
|
2317 |
|
2318 /* |
|
2319 * fix for bug #4088106 - ugly text boxes and grayed out looking text |
|
2320 */ |
|
2321 |
|
2322 XmColorProc oldColorProc; |
|
2323 |
|
2324 void |
|
2325 ColorProc(XColor* bg_color, |
|
2326 XColor* fg_color, |
|
2327 XColor* sel_color, |
|
2328 XColor* ts_color, |
|
2329 XColor* bs_color) |
|
2330 { |
|
2331 unsigned long plane_masks[1]; |
|
2332 unsigned long colors[5]; |
|
2333 |
|
2334 AwtGraphicsConfigDataPtr defaultConfig = |
|
2335 getDefaultConfig(DefaultScreen(awt_display)); |
|
2336 |
|
2337 /* use the default procedure to calculate colors */ |
|
2338 oldColorProc(bg_color, fg_color, sel_color, ts_color, bs_color); |
|
2339 |
|
2340 /* check if there is enought free color cells */ |
|
2341 if (XAllocColorCells(awt_display, defaultConfig->awt_cmap, False, |
|
2342 plane_masks, 0, colors, 5)) { |
|
2343 XFreeColors(awt_display, defaultConfig->awt_cmap, colors, 5, 0); |
|
2344 return; |
|
2345 } |
|
2346 |
|
2347 /* find the closest matches currently available */ |
|
2348 fg_color->pixel = defaultConfig->AwtColorMatch(fg_color->red >> 8, |
|
2349 fg_color->green >> 8, |
|
2350 fg_color->blue >> 8, |
|
2351 defaultConfig); |
|
2352 fg_color->flags = DoRed | DoGreen | DoBlue; |
|
2353 XQueryColor(awt_display, defaultConfig->awt_cmap, fg_color); |
|
2354 sel_color->pixel = defaultConfig->AwtColorMatch(sel_color->red >> 8, |
|
2355 sel_color->green >> 8, |
|
2356 sel_color->blue >> 8, |
|
2357 defaultConfig); |
|
2358 sel_color->flags = DoRed | DoGreen | DoBlue; |
|
2359 XQueryColor(awt_display, defaultConfig->awt_cmap, sel_color); |
|
2360 ts_color->pixel = defaultConfig->AwtColorMatch(ts_color->red >> 8, |
|
2361 ts_color->green >> 8, |
|
2362 ts_color->blue >> 8, |
|
2363 defaultConfig); |
|
2364 ts_color->flags = DoRed | DoGreen | DoBlue; |
|
2365 XQueryColor(awt_display, defaultConfig->awt_cmap, ts_color); |
|
2366 bs_color->pixel = defaultConfig->AwtColorMatch(bs_color->red >> 8, |
|
2367 bs_color->green >> 8, |
|
2368 bs_color->blue >> 8, |
|
2369 defaultConfig); |
|
2370 bs_color->flags = DoRed | DoGreen | DoBlue; |
|
2371 XQueryColor(awt_display, defaultConfig->awt_cmap, bs_color); |
|
2372 } |
|
2373 |
|
2374 |
|
2375 /* |
|
2376 * Read _XSETTINGS_SETTINGS property from _XSETTINGS selection owner |
|
2377 * and pass its value to the java world for processing. |
|
2378 */ |
|
2379 /*static*/ void |
|
2380 awt_xsettings_update(int scr, Window owner, void *cookie) |
|
2381 { |
|
2382 Display *dpy = awt_display; |
|
2383 int status; |
|
2384 |
|
2385 JNIEnv *env; |
|
2386 jobject mtoolkit; |
|
2387 jmethodID upcall; |
|
2388 jbyteArray array; |
|
2389 |
|
2390 struct xsettings_callback_cookie *upcall_cookie = cookie; |
|
2391 |
|
2392 /* Returns of XGetWindowProperty */ |
|
2393 Atom actual_type; |
|
2394 int actual_format; |
|
2395 unsigned long nitems; |
|
2396 unsigned long bytes_after; |
|
2397 unsigned char *xsettings; |
|
2398 |
|
2399 DTRACE_PRINTLN2("XS: update screen %d, owner 0x%08lx", |
|
2400 scr, owner); |
|
2401 |
|
2402 #if 1 /* XXX: kludge */ |
|
2403 /* |
|
2404 * As toolkit cannot yet cope with per-screen desktop properties, |
|
2405 * only report XSETTINGS changes on the default screen. This |
|
2406 * should be "good enough" for most cases. |
|
2407 */ |
|
2408 if (scr != DefaultScreen(dpy)) { |
|
2409 DTRACE_PRINTLN2("XS: XXX: default screen is %d, update is for %d, ignoring", DefaultScreen(dpy), scr); |
|
2410 return; |
|
2411 } |
|
2412 #endif /* kludge */ |
|
2413 |
|
2414 env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
2415 DASSERT(env != NULL); |
|
2416 |
|
2417 DASSERT(upcall_cookie != NULL); |
|
2418 mtoolkit = upcall_cookie->mtoolkit; |
|
2419 upcall = upcall_cookie->upcallMID; |
|
2420 |
|
2421 DASSERT(!JNU_IsNull(env, mtoolkit)); |
|
2422 DASSERT(upcall != NULL); |
|
2423 |
|
2424 /* |
|
2425 * XXX: move awt_getPropertyFOO from awt_wm.c to awt_util.c and |
|
2426 * use the appropriate one. |
|
2427 */ |
|
2428 status = XGetWindowProperty(dpy, owner, |
|
2429 _XA_XSETTINGS_SETTINGS, 0, 0xFFFF, False, |
|
2430 _XA_XSETTINGS_SETTINGS, |
|
2431 &actual_type, &actual_format, &nitems, &bytes_after, |
|
2432 &xsettings); |
|
2433 |
|
2434 if (status != Success) { |
|
2435 DTRACE_PRINTLN("XS: unable to read _XSETTINGS"); |
|
2436 return; |
|
2437 } |
|
2438 |
|
2439 if (xsettings == NULL) { |
|
2440 DTRACE_PRINTLN("XS: reading _XSETTINGS, got NULL"); |
|
2441 return; |
|
2442 } |
|
2443 |
|
2444 if (actual_type != _XA_XSETTINGS_SETTINGS) { |
|
2445 XFree(xsettings); /* NULL data already catched above */ |
|
2446 DTRACE_PRINTLN("XS: _XSETTINGS_SETTINGS is not of type _XSETTINGS_SETTINGS"); |
|
2447 return; |
|
2448 } |
|
2449 |
|
2450 DTRACE_PRINTLN1("XS: read %lu bytes of _XSETTINGS_SETTINGS", |
|
2451 nitems); |
|
2452 |
|
2453 /* ok, propagate xsettings to the toolkit for processing */ |
|
2454 if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
|
2455 DTRACE_PRINTLN("XS: EnsureLocalCapacity failed"); |
|
2456 XFree(xsettings); |
|
2457 return; |
|
2458 } |
|
2459 |
|
2460 array = (*env)->NewByteArray(env, (jint)nitems); |
|
2461 if (JNU_IsNull(env, array)) { |
|
2462 DTRACE_PRINTLN("awt_xsettings_update: NewByteArray failed"); |
|
2463 XFree(xsettings); |
|
2464 return; |
|
2465 } |
|
2466 |
|
2467 (*env)->SetByteArrayRegion(env, array, 0, (jint)nitems, |
|
2468 (jbyte *)xsettings); |
|
2469 XFree(xsettings); |
|
2470 |
|
2471 (*env)->CallVoidMethod(env, mtoolkit, upcall, (jint)scr, array); |
|
2472 (*env)->DeleteLocalRef(env, array); |
|
2473 } |
|
2474 |
|
2475 |
|
2476 /* |
|
2477 * Event handler for events on XSETTINGS selection owner. |
|
2478 * We are interested in PropertyNotify only. |
|
2479 */ |
|
2480 static void |
|
2481 awt_xsettings_callback(int scr, XEvent *xev, void *cookie) |
|
2482 { |
|
2483 Display *dpy = awt_display; /* xev->xany.display */ |
|
2484 XPropertyEvent *ev; |
|
2485 |
|
2486 if (xev->type != PropertyNotify) { |
|
2487 DTRACE_PRINTLN2("XS: awt_xsettings_callback(%d) event %d ignored", |
|
2488 scr, xev->type); |
|
2489 return; |
|
2490 } |
|
2491 |
|
2492 ev = &xev->xproperty; |
|
2493 |
|
2494 if (ev->atom == None) { |
|
2495 DTRACE_PRINTLN("XS: awt_xsettings_callback(%d) atom == None"); |
|
2496 return; |
|
2497 } |
|
2498 |
|
2499 #ifdef DEBUG |
|
2500 { |
|
2501 char *name; |
|
2502 |
|
2503 DTRACE_PRINT2("XS: awt_xsettings_callback(%d) 0x%08lx ", |
|
2504 scr, ev->window); |
|
2505 name = XGetAtomName(dpy, ev->atom); |
|
2506 if (name == NULL) { |
|
2507 DTRACE_PRINT1("atom #%d", ev->atom); |
|
2508 } else { |
|
2509 DTRACE_PRINT1("%s", name); |
|
2510 XFree(name); |
|
2511 } |
|
2512 DTRACE_PRINTLN1(" %s", ev->state == PropertyNewValue ? |
|
2513 "changed" : "deleted"); |
|
2514 } |
|
2515 #endif |
|
2516 |
|
2517 if (ev->atom != _XA_XSETTINGS_SETTINGS) { |
|
2518 DTRACE_PRINTLN("XS: property != _XSETTINGS_SETTINGS ... ignoring"); |
|
2519 return; |
|
2520 } |
|
2521 |
|
2522 |
|
2523 if (ev->state == PropertyDelete) { |
|
2524 /* XXX: notify toolkit to reset to "defaults"? */ |
|
2525 return; |
|
2526 } |
|
2527 |
|
2528 awt_xsettings_update(scr, ev->window, cookie); |
|
2529 } |
|
2530 |
|
2531 |
|
2532 /* |
|
2533 * Owner of XSETTINGS selection changed on the given screen. |
|
2534 */ |
|
2535 static void |
|
2536 awt_xsettings_owner_callback(int scr, Window owner, long *data_unused, |
|
2537 void *cookie) |
|
2538 { |
|
2539 if (owner == None) { |
|
2540 DTRACE_PRINTLN("XS: awt_xsettings_owner_callback: owner = None"); |
|
2541 /* XXX: reset to defaults??? */ |
|
2542 return; |
|
2543 } |
|
2544 |
|
2545 DTRACE_PRINTLN1("XS: awt_xsettings_owner_callback: owner = 0x%08lx", |
|
2546 owner); |
|
2547 |
|
2548 awt_xsettings_update(scr, owner, cookie); |
|
2549 } |
|
2550 |
|
2551 /* |
|
2552 * Returns a reference to the class java.awt.Component. |
|
2553 */ |
|
2554 jclass |
|
2555 getComponentClass(JNIEnv *env) |
|
2556 { |
|
2557 static jclass componentCls = NULL; |
|
2558 |
|
2559 // get global reference of java/awt/Component class (run only once) |
|
2560 if (componentCls == NULL) { |
|
2561 jclass componentClsLocal = (*env)->FindClass(env, "java/awt/Component"); |
|
2562 DASSERT(componentClsLocal != NULL); |
|
2563 if (componentClsLocal == NULL) { |
|
2564 /* exception already thrown */ |
|
2565 return NULL; |
|
2566 } |
|
2567 componentCls = (jclass)(*env)->NewGlobalRef(env, componentClsLocal); |
|
2568 (*env)->DeleteLocalRef(env, componentClsLocal); |
|
2569 } |
|
2570 return componentCls; |
|
2571 } |
|
2572 |
|
2573 |
|
2574 /* |
|
2575 * Returns a reference to the class java.awt.MenuComponent. |
|
2576 */ |
|
2577 jclass |
|
2578 getMenuComponentClass(JNIEnv *env) |
|
2579 { |
|
2580 static jclass menuComponentCls = NULL; |
|
2581 |
|
2582 // get global reference of java/awt/MenuComponent class (run only once) |
|
2583 if (menuComponentCls == NULL) { |
|
2584 jclass menuComponentClsLocal = (*env)->FindClass(env, "java/awt/MenuComponent"); |
|
2585 DASSERT(menuComponentClsLocal != NULL); |
|
2586 if (menuComponentClsLocal == NULL) { |
|
2587 /* exception already thrown */ |
|
2588 return NULL; |
|
2589 } |
|
2590 menuComponentCls = (jclass)(*env)->NewGlobalRef(env, menuComponentClsLocal); |
|
2591 (*env)->DeleteLocalRef(env, menuComponentClsLocal); |
|
2592 } |
|
2593 return menuComponentCls; |
|
2594 } |
|
2595 |
|
2596 /* |
|
2597 * Class: sun_awt_motif_MToolkit |
|
2598 * Method: init |
|
2599 * Signature: (Ljava/lang/String;)V |
|
2600 */ |
|
2601 JNIEXPORT void JNICALL |
|
2602 Java_sun_awt_motif_MToolkit_init(JNIEnv *env, jobject this, |
|
2603 jstring mainClassName) |
|
2604 { |
|
2605 char *appName = NULL; |
|
2606 char *mainChars = NULL; |
|
2607 |
|
2608 int32_t argc = 0; |
|
2609 char *argv[10] = { NULL }; |
|
2610 |
|
2611 /* |
|
2612 * Note: The MToolkit object depends on the static initializer |
|
2613 * of X11GraphicsEnvironment to initialize the connection to |
|
2614 * the X11 server. |
|
2615 */ |
|
2616 XFontStruct *xfont; |
|
2617 XmFontListEntry tmpFontListEntry; |
|
2618 char *multiclick_time_query; |
|
2619 AwtGraphicsConfigDataPtr defaultConfig = |
|
2620 getDefaultConfig(DefaultScreen(awt_display)); |
|
2621 AwtScreenDataPtr defaultScreen = |
|
2622 getScreenData(DefaultScreen(awt_display)); |
|
2623 |
|
2624 static String fallback_resources[] = |
|
2625 { |
|
2626 "*enableThinThickness: True", |
|
2627 "*XmFileSelectionBox.fileFilterStyle: XmFILTER_HIDDEN_FILES", |
|
2628 "*XmFileSelectionBox.pathMode: XmPATH_MODE_RELATIVE", |
|
2629 "*XmFileSelectionBox.resizePolicy: XmRESIZE_GROW", |
|
2630 "*XmFileSelectionBox*dirTextLabelString: Enter path or folder name:", |
|
2631 "*XmFileSelectionBox*applyLabelString: Update", |
|
2632 "*XmFileSelectionBox*selectionLabelString: Enter file name:", |
|
2633 "*XmFileSelectionBox*dirListLabelString: Folders", |
|
2634 NULL /* Must be NULL terminated */ |
|
2635 }; |
|
2636 |
|
2637 focusOutEvent.type = FocusOut; |
|
2638 focusOutEvent.xfocus.send_event = True; |
|
2639 focusOutEvent.xfocus.display = awt_display; |
|
2640 focusOutEvent.xfocus.mode = NotifyNormal; |
|
2641 focusOutEvent.xfocus.detail = NotifyNonlinear; |
|
2642 |
|
2643 /* Need to make sure this is deleted someplace! */ |
|
2644 AWT_LOCK(); |
|
2645 |
|
2646 XSetIOErrorHandler(xIOError); |
|
2647 |
|
2648 if (!XSupportsLocale()) { |
|
2649 jio_fprintf(stderr, |
|
2650 "current locale is not supported in X11, locale is set to C"); |
|
2651 setlocale(LC_ALL, "C"); |
|
2652 } |
|
2653 if (!XSetLocaleModifiers("")) { |
|
2654 jio_fprintf(stderr, "X locale modifiers are not supported, using default"); |
|
2655 } |
|
2656 #ifdef NETSCAPE |
|
2657 if (awt_init_xt) { |
|
2658 XtToolkitInitialize(); |
|
2659 } |
|
2660 #else |
|
2661 XtToolkitInitialize(); |
|
2662 #endif |
|
2663 |
|
2664 { |
|
2665 jclass fontConfigClass; |
|
2666 jmethodID methID; |
|
2667 jstring jFontList; |
|
2668 char *cFontRsrc; |
|
2669 char *cFontRsrc2; |
|
2670 |
|
2671 fontConfigClass = (*env)->FindClass(env, "sun/awt/motif/MFontConfiguration"); |
|
2672 methID = (*env)->GetStaticMethodID(env, fontConfigClass, |
|
2673 "getDefaultMotifFontSet", |
|
2674 "()Ljava/lang/String;"); |
|
2675 jFontList = (*env)->CallStaticObjectMethod(env, fontConfigClass, methID); |
|
2676 if (jFontList == NULL) { |
|
2677 motifFontList = |
|
2678 "-monotype-arial-regular-r-normal--*-140-*-*-p-*-iso8859-1"; |
|
2679 } else { |
|
2680 motifFontList = JNU_GetStringPlatformChars(env, jFontList, NULL); |
|
2681 } |
|
2682 |
|
2683 /* fprintf(stderr, "motifFontList: %s\n", motifFontList); */ |
|
2684 |
|
2685 cFontRsrc = malloc(strlen(motifFontList) + 20); |
|
2686 strcpy(cFontRsrc, "*fontList: "); |
|
2687 strcat(cFontRsrc, motifFontList); |
|
2688 cFontRsrc2 = malloc(strlen(motifFontList) + 20); |
|
2689 strcpy(cFontRsrc2, "*labelFontList: "); |
|
2690 strcat(cFontRsrc2, motifFontList); |
|
2691 |
|
2692 argc = 1; |
|
2693 argv[argc++] = "-xrm"; |
|
2694 argv[argc++] = cFontRsrc; |
|
2695 argv[argc++] = "-xrm"; |
|
2696 argv[argc++] = cFontRsrc2; |
|
2697 argv[argc++] = "-font"; |
|
2698 argv[argc++] = (char *)defaultMotifFont; |
|
2699 } |
|
2700 |
|
2701 awt_appContext = XtCreateApplicationContext(); |
|
2702 XtAppSetErrorHandler(awt_appContext, (XtErrorHandler) xtError); |
|
2703 XtAppSetFallbackResources(awt_appContext, fallback_resources); |
|
2704 |
|
2705 appName = NULL; |
|
2706 mainChars = NULL; |
|
2707 if (!JNU_IsNull(env, mainClassName)) { |
|
2708 mainChars = (char *)JNU_GetStringPlatformChars(env, mainClassName, NULL); |
|
2709 appName = mainChars; |
|
2710 } |
|
2711 if (appName == NULL || appName[0] == '\0') { |
|
2712 appName = "AWT"; |
|
2713 } |
|
2714 |
|
2715 XtDisplayInitialize(awt_appContext, awt_display, |
|
2716 appName, /* application name */ |
|
2717 appName, /* application class */ |
|
2718 NULL, 0, &argc, argv); |
|
2719 |
|
2720 /* Root shell widget that serves as a parent for all AWT top-levels. */ |
|
2721 awt_root_shell = XtVaAppCreateShell(appName, /* application name */ |
|
2722 appName, /* application class */ |
|
2723 applicationShellWidgetClass, |
|
2724 awt_display, |
|
2725 /* va_list */ |
|
2726 XmNmappedWhenManaged, False, |
|
2727 NULL); |
|
2728 XtRealizeWidget(awt_root_shell); |
|
2729 |
|
2730 if (mainChars != NULL) { |
|
2731 JNU_ReleaseStringPlatformChars(env, mainClassName, mainChars); |
|
2732 } |
|
2733 |
|
2734 awt_mgrsel_init(); |
|
2735 awt_wm_init(); |
|
2736 init_xembed(); |
|
2737 |
|
2738 /* |
|
2739 * Find the correct awt_multiclick_time to use. We normally |
|
2740 * would call XtMultiClickTime() and wouldn't have to do |
|
2741 * anything special, but because OpenWindows defines its own |
|
2742 * version (OpenWindows.MultiClickTimeout), we need to |
|
2743 * determine out which resource to use. |
|
2744 * |
|
2745 * We do this by searching in order for: |
|
2746 * |
|
2747 * 1) an explicit definition of multiClickTime |
|
2748 * (this is the resource that XtGetMultiClickTime uses) |
|
2749 * |
|
2750 * if that fails, search for: |
|
2751 * |
|
2752 * 2) an explicit definition of Openwindows.MultiClickTimeout |
|
2753 * |
|
2754 * if both searches fail: |
|
2755 * |
|
2756 * 3) use the fallback provided by XtGetMultiClickTime() |
|
2757 * (which is 200 milliseconds... I looked at the source :-) |
|
2758 * |
|
2759 */ |
|
2760 multiclick_time_query = XGetDefault(awt_display, "*", "multiClickTime"); |
|
2761 if (multiclick_time_query) { |
|
2762 awt_multiclick_time = XtGetMultiClickTime(awt_display); |
|
2763 } else { |
|
2764 multiclick_time_query = XGetDefault(awt_display, |
|
2765 "OpenWindows", "MultiClickTimeout"); |
|
2766 if (multiclick_time_query) { |
|
2767 /* Note: OpenWindows.MultiClickTimeout is in tenths of |
|
2768 a second, so we need to multiply by 100 to convert to |
|
2769 milliseconds */ |
|
2770 awt_multiclick_time = atoi(multiclick_time_query) * 100; |
|
2771 } else { |
|
2772 awt_multiclick_time = XtGetMultiClickTime(awt_display); |
|
2773 } |
|
2774 } |
|
2775 |
|
2776 scrollBugWorkAround = TRUE; |
|
2777 |
|
2778 /* |
|
2779 * Create the cursor for TextArea scrollbars... |
|
2780 */ |
|
2781 awt_scrollCursor = XCreateFontCursor(awt_display, XC_left_ptr); |
|
2782 |
|
2783 awt_defaultBg = defaultConfig->AwtColorMatch(200, 200, 200, defaultConfig); |
|
2784 awt_defaultFg = defaultScreen->blackpixel; |
|
2785 setup_modifier_map(awt_display); |
|
2786 |
|
2787 awt_initialize_DataTransferer(); |
|
2788 awt_initialize_Xm_DnD(awt_display); |
|
2789 |
|
2790 /* |
|
2791 * fix for bug #4088106 - ugly text boxes and grayed out looking text |
|
2792 */ |
|
2793 oldColorProc = XmGetColorCalculation(); |
|
2794 XmSetColorCalculation(ColorProc); |
|
2795 |
|
2796 AWT_UNLOCK(); |
|
2797 } |
|
2798 |
|
2799 /* |
|
2800 * Class: sun_awt_motif_MToolkit |
|
2801 * Method: run |
|
2802 * Signature: ()V |
|
2803 */ |
|
2804 JNIEXPORT void JNICALL Java_sun_awt_motif_MToolkit_run |
|
2805 (JNIEnv *env, jobject this) |
|
2806 { |
|
2807 /* |
|
2808 * in performSelect(), we multiply the timeout by 1000. Make sure |
|
2809 * that the maximum value will not cause an overflow. |
|
2810 */ |
|
2811 DASSERT(AWT_MAX_POLL_TIMEOUT <= (ULONG_MAX/1000)); |
|
2812 |
|
2813 awt_MainThread = (*env)->NewGlobalRef(env, awtJNI_GetCurrentThread(env)); |
|
2814 awt_MToolkit_loop(env); /* never returns */ |
|
2815 } |
|
2816 |
|
2817 /* |
|
2818 * Class: sun_awt_motif_MToolkit |
|
2819 * Method: makeColorModel |
|
2820 * Signature: ()Ljava/awt/image/ColorModel; |
|
2821 */ |
|
2822 JNIEXPORT jobject JNICALL Java_sun_awt_motif_MToolkit_makeColorModel |
|
2823 (JNIEnv *env, jclass this) |
|
2824 { |
|
2825 AwtGraphicsConfigDataPtr defaultConfig = |
|
2826 getDefaultConfig(DefaultScreen(awt_display)); |
|
2827 |
|
2828 return awtJNI_GetColorModel(env, defaultConfig); |
|
2829 } |
|
2830 |
|
2831 /* |
|
2832 * Class: sun_awt_motif_MToolkit |
|
2833 * Method: getScreenResolution |
|
2834 * Signature: ()I |
|
2835 */ |
|
2836 JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getScreenResolution |
|
2837 (JNIEnv *env, jobject this) |
|
2838 { |
|
2839 return (jint) ((DisplayWidth(awt_display, DefaultScreen(awt_display)) |
|
2840 * 25.4) / |
|
2841 DisplayWidthMM(awt_display, DefaultScreen(awt_display))); |
|
2842 } |
|
2843 |
|
2844 /* |
|
2845 * Class: sun_awt_motif_MToolkit |
|
2846 * Method: getScreenWidth |
|
2847 * Signature: ()I |
|
2848 */ |
|
2849 JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getScreenWidth |
|
2850 (JNIEnv *env, jobject this) |
|
2851 { |
|
2852 return DisplayWidth(awt_display, DefaultScreen(awt_display)); |
|
2853 } |
|
2854 /* |
|
2855 * Class: sun_awt_motif_MToolkit |
|
2856 * Method: getScreenHeight |
|
2857 * Signature: ()I |
|
2858 */ |
|
2859 JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getScreenHeight |
|
2860 (JNIEnv *env, jobject this) |
|
2861 { |
|
2862 return DisplayHeight(awt_display, DefaultScreen(awt_display)); |
|
2863 } |
|
2864 |
|
2865 /* |
|
2866 * Class: sun_awt_motif_MToolkit |
|
2867 * Method: beep |
|
2868 * Signature: ()V |
|
2869 */ |
|
2870 JNIEXPORT void JNICALL Java_sun_awt_motif_MToolkit_beep |
|
2871 (JNIEnv *env, jobject this) |
|
2872 { |
|
2873 AWT_LOCK(); |
|
2874 XBell(awt_display, 0); |
|
2875 AWT_FLUSH_UNLOCK(); |
|
2876 } |
|
2877 |
|
2878 /* |
|
2879 * Class: sun_awt_motif_MToolkit |
|
2880 * Method: shutdown |
|
2881 * Signature: ()V |
|
2882 */ |
|
2883 |
|
2884 JNIEXPORT void JNICALL Java_sun_awt_motif_MToolkit_shutdown |
|
2885 (JNIEnv *env, jobject this) |
|
2886 { |
|
2887 X11SD_LibDispose(env); |
|
2888 } |
|
2889 |
|
2890 /* |
|
2891 * Class: sun_awt_motif_MToolkit |
|
2892 * Method: getLockingKeyStateNative |
|
2893 * Signature: (I)B |
|
2894 */ |
|
2895 JNIEXPORT jboolean JNICALL Java_sun_awt_motif_MToolkit_getLockingKeyStateNative |
|
2896 (JNIEnv *env, jobject this, jint awtKey) |
|
2897 { |
|
2898 KeySym sym; |
|
2899 KeyCode keyCode; |
|
2900 uint32_t byteIndex; |
|
2901 uint32_t bitIndex; |
|
2902 char keyVector[32]; |
|
2903 |
|
2904 AWT_LOCK(); |
|
2905 |
|
2906 sym = awt_getX11KeySym(awtKey); |
|
2907 keyCode = XKeysymToKeycode(awt_display, sym); |
|
2908 if (sym == NoSymbol || keyCode == 0) { |
|
2909 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "Keyboard doesn't have requested key"); |
|
2910 AWT_UNLOCK(); |
|
2911 return False; |
|
2912 } |
|
2913 |
|
2914 byteIndex = (keyCode/8); |
|
2915 bitIndex = keyCode & 7; |
|
2916 XQueryKeymap(awt_display, keyVector); |
|
2917 |
|
2918 AWT_UNLOCK(); |
|
2919 |
|
2920 return (1 & (keyVector[byteIndex] >> bitIndex)); |
|
2921 } |
|
2922 |
|
2923 /* |
|
2924 * Class: sun_awt_motif_MToolkit |
|
2925 * Method: loadSystemColors |
|
2926 * Signature: ([I)V |
|
2927 */ |
|
2928 JNIEXPORT void JNICALL Java_sun_awt_motif_MToolkit_loadSystemColors |
|
2929 (JNIEnv *env, jobject this, jintArray systemColors) |
|
2930 { |
|
2931 Widget frame, panel, control, menu, text, scrollbar; |
|
2932 Colormap cmap; |
|
2933 Pixel bg, fg, highlight, shadow; |
|
2934 Pixel pixels[java_awt_SystemColor_NUM_COLORS]; |
|
2935 XColor *colorsPtr; |
|
2936 jint rgbColors[java_awt_SystemColor_NUM_COLORS]; |
|
2937 int32_t count = 0; |
|
2938 int32_t i, j; |
|
2939 Arg args[10]; |
|
2940 int32_t argc; |
|
2941 AwtGraphicsConfigDataPtr defaultConfig = |
|
2942 getDefaultConfig(DefaultScreen(awt_display)); |
|
2943 |
|
2944 AWT_LOCK(); |
|
2945 |
|
2946 /* |
|
2947 * initialize array of pixels |
|
2948 */ |
|
2949 for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) { |
|
2950 pixels[i] = -1; |
|
2951 } |
|
2952 |
|
2953 /* |
|
2954 * Create phantom widgets in order to determine the default |
|
2955 * colors; this is somewhat inelegant, however it is the simplest |
|
2956 * and most reliable way to determine the system's default colors |
|
2957 * for objects. |
|
2958 */ |
|
2959 argc = 0; |
|
2960 XtSetArg(args[argc], XmNbuttonFontList, getMotifFontList()); argc++; |
|
2961 XtSetArg(args[argc], XmNlabelFontList, getMotifFontList()); argc++; |
|
2962 XtSetArg(args[argc], XmNtextFontList, getMotifFontList()); argc++; |
|
2963 frame = XtAppCreateShell("AWTColors", "XApplication", |
|
2964 vendorShellWidgetClass, |
|
2965 awt_display, |
|
2966 args, argc); |
|
2967 /* |
|
2968 XtSetMappedWhenManaged(frame, False); |
|
2969 XtRealizeWidget(frame); |
|
2970 */ |
|
2971 panel = XmCreateDrawingArea(frame, "awtPanelColor", NULL, 0); |
|
2972 argc = 0; |
|
2973 XtSetArg(args[argc], XmNfontList, getMotifFontList()); argc++; |
|
2974 control = XmCreatePushButton(panel, "awtControlColor", args, argc); |
|
2975 argc = 0; |
|
2976 XtSetArg(args[argc], XmNlabelFontList, getMotifFontList()); argc++; |
|
2977 XtSetArg(args[argc], XmNbuttonFontList, getMotifFontList()); argc++; |
|
2978 menu = XmCreatePulldownMenu(control, "awtColorMenu", args, argc); |
|
2979 argc = 0; |
|
2980 XtSetArg(args[argc], XmNfontList, getMotifFontList()); argc++; |
|
2981 text = XmCreateText(panel, "awtTextColor", args, argc); |
|
2982 scrollbar = XmCreateScrollBar(panel, "awtScrollbarColor", NULL, 0); |
|
2983 |
|
2984 XtVaGetValues(panel, |
|
2985 XmNbackground, &bg, |
|
2986 XmNforeground, &fg, |
|
2987 XmNcolormap, &cmap, |
|
2988 NULL); |
|
2989 |
|
2990 pixels[java_awt_SystemColor_WINDOW] = bg; |
|
2991 count++; |
|
2992 pixels[java_awt_SystemColor_INFO] = bg; |
|
2993 count++; |
|
2994 pixels[java_awt_SystemColor_WINDOW_TEXT] = fg; |
|
2995 count++; |
|
2996 pixels[java_awt_SystemColor_INFO_TEXT] = fg; |
|
2997 count++; |
|
2998 |
|
2999 XtVaGetValues(menu, |
|
3000 XmNbackground, &bg, |
|
3001 XmNforeground, &fg, |
|
3002 NULL); |
|
3003 |
|
3004 pixels[java_awt_SystemColor_MENU] = bg; |
|
3005 count++; |
|
3006 pixels[java_awt_SystemColor_MENU_TEXT] = fg; |
|
3007 count++; |
|
3008 |
|
3009 XtVaGetValues(text, |
|
3010 XmNbackground, &bg, |
|
3011 XmNforeground, &fg, |
|
3012 NULL); |
|
3013 |
|
3014 pixels[java_awt_SystemColor_TEXT] = bg; |
|
3015 count++; |
|
3016 pixels[java_awt_SystemColor_TEXT_TEXT] = fg; |
|
3017 count++; |
|
3018 pixels[java_awt_SystemColor_TEXT_HIGHLIGHT] = fg; |
|
3019 count++; |
|
3020 pixels[java_awt_SystemColor_TEXT_HIGHLIGHT_TEXT] = bg; |
|
3021 count++; |
|
3022 |
|
3023 XtVaGetValues(control, |
|
3024 XmNbackground, &bg, |
|
3025 XmNforeground, &fg, |
|
3026 XmNtopShadowColor, &highlight, |
|
3027 XmNbottomShadowColor, &shadow, |
|
3028 NULL); |
|
3029 |
|
3030 pixels[java_awt_SystemColor_CONTROL] = bg; |
|
3031 count++; |
|
3032 pixels[java_awt_SystemColor_CONTROL_TEXT] = fg; |
|
3033 count++; |
|
3034 pixels[java_awt_SystemColor_CONTROL_HIGHLIGHT] = highlight; |
|
3035 count++; |
|
3036 pixels[java_awt_SystemColor_CONTROL_LT_HIGHLIGHT] = highlight; |
|
3037 count++; |
|
3038 pixels[java_awt_SystemColor_CONTROL_SHADOW] = shadow; |
|
3039 count++; |
|
3040 pixels[java_awt_SystemColor_CONTROL_DK_SHADOW] = shadow; |
|
3041 count++; |
|
3042 |
|
3043 XtVaGetValues(scrollbar, |
|
3044 XmNbackground, &bg, |
|
3045 NULL); |
|
3046 pixels[java_awt_SystemColor_SCROLLBAR] = bg; |
|
3047 count++; |
|
3048 |
|
3049 /* |
|
3050 * Convert pixel values to RGB |
|
3051 */ |
|
3052 colorsPtr = (XColor *) malloc(count * sizeof(XColor)); |
|
3053 j = 0; |
|
3054 for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) { |
|
3055 if (pixels[i] != -1) { |
|
3056 colorsPtr[j++].pixel = pixels[i]; |
|
3057 } |
|
3058 } |
|
3059 XQueryColors(awt_display, cmap, colorsPtr, count); |
|
3060 |
|
3061 /* Get current System Colors */ |
|
3062 |
|
3063 (*env)->GetIntArrayRegion (env, systemColors, 0, |
|
3064 java_awt_SystemColor_NUM_COLORS, |
|
3065 rgbColors); |
|
3066 |
|
3067 /* |
|
3068 * Fill systemColor array with new rgb values |
|
3069 */ |
|
3070 |
|
3071 j = 0; |
|
3072 for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) { |
|
3073 if (pixels[i] != -1) { |
|
3074 uint32_t rgb = colorToRGB(&colorsPtr[j++]); |
|
3075 |
|
3076 /* |
|
3077 printf("SystemColor[%d] = %x\n", i, rgb); |
|
3078 */ |
|
3079 rgbColors[i] = (rgb | 0xFF000000); |
|
3080 } |
|
3081 } |
|
3082 |
|
3083 (*env)->SetIntArrayRegion(env, |
|
3084 systemColors, |
|
3085 0, |
|
3086 java_awt_SystemColor_NUM_COLORS, |
|
3087 rgbColors); |
|
3088 |
|
3089 /* Duplicate system colors. If color allocation is unsuccessful, |
|
3090 system colors will be approximated with matched colors */ |
|
3091 if (defaultConfig->awt_depth == 8) |
|
3092 awt_allocate_systemcolors(colorsPtr, count, defaultConfig); |
|
3093 |
|
3094 /* |
|
3095 * Cleanup |
|
3096 */ |
|
3097 XtDestroyWidget(frame); |
|
3098 free(colorsPtr); |
|
3099 |
|
3100 AWT_UNLOCK(); |
|
3101 } |
|
3102 |
|
3103 /* |
|
3104 * Class: sun_awt_motif_MToolkit |
|
3105 * Method: isDynamicLayoutSupportedNative |
|
3106 * Signature: ()Z |
|
3107 * |
|
3108 * Note: there doesn't seem to be a protocol for querying the WM |
|
3109 * about its opaque resize settings, so this function just returns |
|
3110 * whether there is a solid resize option available for that WM. |
|
3111 */ |
|
3112 JNIEXPORT jboolean JNICALL |
|
3113 Java_sun_awt_motif_MToolkit_isDynamicLayoutSupportedNative(JNIEnv *env, jobject this) |
|
3114 { |
|
3115 enum wmgr_t wm; |
|
3116 |
|
3117 AWT_LOCK(); |
|
3118 wm = awt_wm_getRunningWM(); |
|
3119 AWT_UNLOCK(); |
|
3120 |
|
3121 switch (wm) { |
|
3122 case ENLIGHTEN_WM: |
|
3123 case KDE2_WM: |
|
3124 case SAWFISH_WM: |
|
3125 case ICE_WM: |
|
3126 case METACITY_WM: |
|
3127 return JNI_TRUE; |
|
3128 case OPENLOOK_WM: |
|
3129 case MOTIF_WM: |
|
3130 case CDE_WM: |
|
3131 return JNI_FALSE; |
|
3132 default: |
|
3133 return JNI_FALSE; |
|
3134 } |
|
3135 } |
|
3136 |
|
3137 /* |
|
3138 * Class: sun_awt_motif_MToolkit |
|
3139 * Method: isFrameStateSupported |
|
3140 * Signature: (I)Z |
|
3141 */ |
|
3142 JNIEXPORT jboolean JNICALL |
|
3143 Java_sun_awt_motif_MToolkit_isFrameStateSupported(JNIEnv *env, jobject this, |
|
3144 jint state) |
|
3145 { |
|
3146 if (state == java_awt_Frame_NORMAL || state == java_awt_Frame_ICONIFIED) { |
|
3147 return JNI_TRUE; |
|
3148 } else { |
|
3149 return awt_wm_supportsExtendedState(state) ? JNI_TRUE : JNI_FALSE; |
|
3150 } |
|
3151 } |
|
3152 |
|
3153 /* |
|
3154 * Class: sun_awt_motif_MToolkit |
|
3155 * Method: getMulticlickTime |
|
3156 * Signature: ()I |
|
3157 */ |
|
3158 JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getMulticlickTime |
|
3159 (JNIEnv *env, jobject this) |
|
3160 { |
|
3161 return awt_multiclick_time; |
|
3162 } |
|
3163 |
|
3164 /* |
|
3165 * Class: sun_awt_motif_MToolkit |
|
3166 * Method: loadXSettings |
|
3167 * Signature: ()V |
|
3168 */ |
|
3169 JNIEXPORT void JNICALL |
|
3170 Java_sun_awt_motif_MToolkit_loadXSettings(JNIEnv *env, jobject this) |
|
3171 { |
|
3172 static Boolean registered = False; |
|
3173 |
|
3174 jclass mtoolkitCLS; |
|
3175 Display *dpy = awt_display; |
|
3176 const Window *owners; |
|
3177 int scr; |
|
3178 |
|
3179 AWT_LOCK(); |
|
3180 |
|
3181 if (registered) { |
|
3182 AWT_UNLOCK(); |
|
3183 return; |
|
3184 } |
|
3185 |
|
3186 if (_XA_XSETTINGS_SETTINGS == None) { |
|
3187 _XA_XSETTINGS_SETTINGS = XInternAtom(dpy, "_XSETTINGS_SETTINGS", False); |
|
3188 if (_XA_XSETTINGS_SETTINGS == None) { |
|
3189 JNU_ThrowNullPointerException(env, |
|
3190 "unable to intern _XSETTINGS_SETTINGS"); |
|
3191 AWT_UNLOCK(); |
|
3192 return; |
|
3193 } |
|
3194 } |
|
3195 |
|
3196 mtoolkitCLS = (*env)->GetObjectClass(env, this); |
|
3197 |
|
3198 xsettings_callback_cookie.mtoolkit = |
|
3199 (*env)->NewGlobalRef(env, this); |
|
3200 xsettings_callback_cookie.upcallMID = |
|
3201 (*env)->GetMethodID(env, mtoolkitCLS, |
|
3202 "parseXSettings", "(I[B)V"); |
|
3203 |
|
3204 if (JNU_IsNull(env, xsettings_callback_cookie.upcallMID)) { |
|
3205 JNU_ThrowNoSuchMethodException(env, |
|
3206 "sun.awt.motif.MToolkit.parseXSettings"); |
|
3207 AWT_UNLOCK(); |
|
3208 return; |
|
3209 } |
|
3210 |
|
3211 owners = awt_mgrsel_select("_XSETTINGS", PropertyChangeMask, |
|
3212 &xsettings_callback_cookie, |
|
3213 awt_xsettings_callback, |
|
3214 awt_xsettings_owner_callback); |
|
3215 if (owners == NULL) { |
|
3216 JNU_ThrowNullPointerException(env, |
|
3217 "unable to regiser _XSETTINGS with mgrsel"); |
|
3218 AWT_UNLOCK(); |
|
3219 return; |
|
3220 } |
|
3221 |
|
3222 registered = True; |
|
3223 |
|
3224 for (scr = 0; scr < ScreenCount(dpy); ++scr) { |
|
3225 if (owners[scr] == None) { |
|
3226 DTRACE_PRINTLN1("XS: MToolkit.loadXSettings: none on screen %d", |
|
3227 scr); |
|
3228 continue; |
|
3229 } |
|
3230 |
|
3231 awt_xsettings_update(scr, owners[scr], &xsettings_callback_cookie); |
|
3232 } |
|
3233 |
|
3234 AWT_UNLOCK(); |
|
3235 } |
|
3236 |
|
3237 JNIEXPORT jboolean JNICALL |
|
3238 Java_sun_awt_motif_MToolkit_isAlwaysOnTopSupported(JNIEnv *env, jobject toolkit) { |
|
3239 Boolean res; |
|
3240 AWT_LOCK(); |
|
3241 res = awt_wm_supportsAlwaysOnTop(); |
|
3242 AWT_UNLOCK(); |
|
3243 return res; |
|
3244 } |
|
3245 |
|
3246 /* |
|
3247 * Returns true if the current thread is privileged. Currently, |
|
3248 * only the main event loop thread is considered to be privileged. |
|
3249 */ |
|
3250 Boolean |
|
3251 awt_currentThreadIsPrivileged(JNIEnv *env) { |
|
3252 return (*env)->IsSameObject(env, |
|
3253 awt_MainThread, awtJNI_GetCurrentThread(env)); |
|
3254 } |
|
3255 |
|
3256 JNIEXPORT jboolean JNICALL |
|
3257 Java_sun_awt_motif_MToolkit_isSyncUpdated(JNIEnv *env, jobject toolkit) { |
|
3258 return syncUpdated; |
|
3259 } |
|
3260 |
|
3261 JNIEXPORT jboolean JNICALL |
|
3262 Java_sun_awt_motif_MToolkit_isSyncFailed(JNIEnv *env, jobject toolkit) { |
|
3263 return syncFailed; |
|
3264 } |
|
3265 |
|
3266 JNIEXPORT void JNICALL |
|
3267 Java_sun_awt_motif_MToolkit_updateSyncSelection(JNIEnv *env, jobject toolkit) { |
|
3268 |
|
3269 // AWT_LOCK is held by calling function |
|
3270 if (wm_selection == None) { |
|
3271 wm_selection = XInternAtom(awt_display, "WM_S0", False); |
|
3272 } |
|
3273 if (version_atom == None) { |
|
3274 version_atom = XInternAtom(awt_display, "VERSION", False); |
|
3275 } |
|
3276 if (oops_atom == None) { |
|
3277 oops_atom = XInternAtom(awt_display, "OOPS", False); |
|
3278 } |
|
3279 syncUpdated = False; |
|
3280 syncFailed = False; |
|
3281 XConvertSelection(awt_display, wm_selection, version_atom, oops_atom, XtWindow(awt_root_shell), CurrentTime); |
|
3282 XSync(awt_display, False); |
|
3283 inSyncWait = True; // Protect from spurious events |
|
3284 // Calling function will call AWT_LOCK_WAIT instead of AWT_UNLOCK |
|
3285 } |
|
3286 |
|
3287 JNIEXPORT jint JNICALL |
|
3288 Java_sun_awt_motif_MToolkit_getEventNumber(JNIEnv *env, jobject toolkit) { |
|
3289 // AWT_LOCK must be held by the calling method |
|
3290 return eventNumber; |
|
3291 } |
|
3292 |
|
3293 static void |
|
3294 syncWait_eventHandler(XEvent * event) { |
|
3295 static jmethodID syncNotifyMID = NULL; |
|
3296 if (event != NULL && event->xany.type == SelectionNotify && |
|
3297 event->xselection.requestor == XtWindow(awt_root_shell) && |
|
3298 event->xselection.property == oops_atom && |
|
3299 inSyncWait) |
|
3300 { |
|
3301 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
3302 syncUpdated = True; |
|
3303 inSyncWait = False; |
|
3304 AWT_NOTIFY_ALL(); |
|
3305 } else if (event != NULL && event->xany.type == SelectionNotify && |
|
3306 event->xselection.requestor == XtWindow(awt_root_shell) && |
|
3307 event->xselection.target == version_atom && |
|
3308 event->xselection.property == None && |
|
3309 XGetSelectionOwner(awt_display, wm_selection) == None && |
|
3310 event->xselection.selection == wm_selection) |
|
3311 { |
|
3312 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
3313 syncFailed = True; |
|
3314 inSyncWait = False; |
|
3315 AWT_NOTIFY_ALL(); |
|
3316 } |
|
3317 } |
|
3318 |
|
3319 JNIEXPORT void JNICALL |
|
3320 Java_sun_awt_motif_MToolkit_nativeGrab(JNIEnv *env, jobject toolkit, jobject window) { |
|
3321 struct FrameData *wdata; |
|
3322 static Cursor cursor = None; |
|
3323 int grab_result; |
|
3324 |
|
3325 AWT_LOCK(); |
|
3326 |
|
3327 wdata = (struct FrameData *) |
|
3328 JNU_GetLongFieldAsPtr(env, window, mComponentPeerIDs.pData); |
|
3329 |
|
3330 if (wdata == NULL || |
|
3331 wdata->winData.comp.widget == NULL || |
|
3332 wdata->winData.shell == NULL) |
|
3333 { |
|
3334 AWT_UNLOCK(); |
|
3335 return; |
|
3336 } |
|
3337 if (None == cursor) { |
|
3338 cursor = XCreateFontCursor(awt_display, XC_hand2); |
|
3339 } |
|
3340 grabbed_widget = wdata->winData.shell; |
|
3341 grab_result = XGrabPointer(awt_display, XtWindow(wdata->winData.shell), |
|
3342 True, (ButtonPressMask | ButtonReleaseMask |
|
3343 | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
|
3344 | ButtonMotionMask), |
|
3345 GrabModeAsync, GrabModeAsync, None, |
|
3346 cursor, CurrentTime); |
|
3347 if (GrabSuccess != grab_result) { |
|
3348 XUngrabPointer(awt_display, CurrentTime); |
|
3349 AWT_UNLOCK(); |
|
3350 DTRACE_PRINTLN1("XGrabPointer() failed, result %d", grab_result); |
|
3351 return; |
|
3352 } |
|
3353 grab_result = XGrabKeyboard(awt_display, XtWindow(wdata->winData.shell), |
|
3354 True, |
|
3355 GrabModeAsync, GrabModeAsync, CurrentTime); |
|
3356 if (GrabSuccess != grab_result) { |
|
3357 XUngrabKeyboard(awt_display, CurrentTime); |
|
3358 XUngrabPointer(awt_display, CurrentTime); |
|
3359 DTRACE_PRINTLN1("XGrabKeyboard() failed, result %d", grab_result); |
|
3360 } |
|
3361 AWT_UNLOCK(); |
|
3362 } |
|
3363 |
|
3364 JNIEXPORT void JNICALL |
|
3365 Java_sun_awt_motif_MToolkit_nativeUnGrab(JNIEnv *env, jobject toolkit, jobject window) { |
|
3366 struct FrameData *wdata; |
|
3367 |
|
3368 AWT_LOCK(); |
|
3369 |
|
3370 wdata = (struct FrameData *) |
|
3371 JNU_GetLongFieldAsPtr(env, window, mComponentPeerIDs.pData); |
|
3372 |
|
3373 if (wdata == NULL || |
|
3374 wdata->winData.comp.widget == NULL || |
|
3375 wdata->winData.shell == NULL) |
|
3376 { |
|
3377 AWT_UNLOCK(); |
|
3378 return; |
|
3379 } |
|
3380 |
|
3381 XUngrabPointer(awt_display, CurrentTime); |
|
3382 XUngrabKeyboard(awt_display, CurrentTime); |
|
3383 grabbed_widget = NULL; |
|
3384 AWT_FLUSHOUTPUT_NOW(); |
|
3385 |
|
3386 AWT_UNLOCK(); |
|
3387 |
|
3388 } |
|
3389 |
|
3390 /* |
|
3391 * Class: sun_awt_motif_MToolkit |
|
3392 * Method: getWMName |
|
3393 * Signature: ()Ljava/lang/String; |
|
3394 */ |
|
3395 JNIEXPORT jstring JNICALL |
|
3396 Java_sun_awt_motif_MToolkit_getWMName(JNIEnv *env, jclass this) |
|
3397 { |
|
3398 enum wmgr_t wm; |
|
3399 |
|
3400 AWT_LOCK(); |
|
3401 wm = awt_wm_getRunningWM(); |
|
3402 AWT_UNLOCK(); |
|
3403 |
|
3404 switch (wm) { |
|
3405 case NO_WM: |
|
3406 return (*env)->NewStringUTF(env, "NO_WM"); |
|
3407 case OTHER_WM: |
|
3408 return (*env)->NewStringUTF(env, "OTHER_WM"); |
|
3409 case ENLIGHTEN_WM: |
|
3410 return (*env)->NewStringUTF(env, "ENLIGHTEN_WM"); |
|
3411 case KDE2_WM: |
|
3412 return (*env)->NewStringUTF(env, "KDE2_WM"); |
|
3413 case SAWFISH_WM: |
|
3414 return (*env)->NewStringUTF(env, "SAWFISH_WM"); |
|
3415 case ICE_WM: |
|
3416 return (*env)->NewStringUTF(env, "ICE_WM"); |
|
3417 case METACITY_WM: |
|
3418 return (*env)->NewStringUTF(env, "METACITY_WM"); |
|
3419 case OPENLOOK_WM: |
|
3420 return (*env)->NewStringUTF(env, "OPENLOOK_WM"); |
|
3421 case MOTIF_WM: |
|
3422 return (*env)->NewStringUTF(env, "MOTIF_WM"); |
|
3423 case CDE_WM: |
|
3424 return (*env)->NewStringUTF(env, "CDE_WM"); |
|
3425 } |
|
3426 return (*env)->NewStringUTF(env, "UNDETERMINED_WM"); |
|
3427 } |
|
3428 |
|
3429 |
|
3430 #endif /* !HEADLESS */ |
|