1 /* |
|
2 * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 |
|
26 #ifdef HEADLESS |
|
27 #error This file should not be included in headless library |
|
28 #endif |
|
29 |
|
30 #include "awt_p.h" |
|
31 |
|
32 #include <X11/Shell.h> |
|
33 #include <Xm/VendorS.h> |
|
34 #include <Xm/Form.h> |
|
35 #include <Xm/DialogS.h> |
|
36 #include <Xm/AtomMgr.h> |
|
37 #include <Xm/Protocols.h> |
|
38 #include <Xm/MenuShell.h> |
|
39 #include <Xm/MwmUtil.h> |
|
40 #include "VDrawingArea.h" |
|
41 |
|
42 #ifdef DEBUG |
|
43 # include <X11/Xmu/Editres.h> |
|
44 #endif |
|
45 |
|
46 #include <jni.h> |
|
47 #include <jni_util.h> |
|
48 |
|
49 /* JNI headers */ |
|
50 #include "java_awt_Color.h" |
|
51 #include "java_awt_Component.h" |
|
52 #include "java_awt_Dialog.h" |
|
53 #include "java_awt_Font.h" |
|
54 #include "java_awt_Frame.h" |
|
55 #include "java_awt_Image.h" |
|
56 #include "java_awt_Insets.h" |
|
57 #include "java_awt_Insets.h" |
|
58 #include "java_awt_MenuBar.h" |
|
59 #include "java_awt_Window.h" |
|
60 #include "java_awt_event_FocusEvent.h" |
|
61 #include "java_awt_TrayIcon.h" |
|
62 #include "sun_awt_EmbeddedFrame.h" |
|
63 #include "sun_awt_motif_MComponentPeer.h" |
|
64 #include "sun_awt_motif_MDialogPeer.h" |
|
65 #include "sun_awt_motif_MEmbeddedFramePeer.h" |
|
66 #include "sun_awt_motif_MFramePeer.h" |
|
67 #include "sun_awt_motif_MMenuBarPeer.h" |
|
68 #include "sun_awt_motif_MWindowPeer.h" |
|
69 |
|
70 /* JNI field and method ids */ |
|
71 #include "awt_Component.h" |
|
72 #include "awt_GraphicsEnv.h" |
|
73 #include "awt_Insets.h" |
|
74 #include "awt_MenuBar.h" |
|
75 #include "awt_Window.h" |
|
76 #include "awt_KeyboardFocusManager.h" |
|
77 #include "awt_MToolkit.h" |
|
78 #include "awt_Plugin.h" |
|
79 |
|
80 #include "color.h" |
|
81 #include "canvas.h" |
|
82 #include "awt_util.h" |
|
83 #include "img_util.h" |
|
84 #include "awt_wm.h" |
|
85 #include "awt_util.h" |
|
86 #include "awt_xembed.h" |
|
87 |
|
88 |
|
89 #ifdef __linux__ |
|
90 void adjustStatusWindow(Widget shell); |
|
91 #endif |
|
92 /* For the moment only InputMethodWindow is taking advantage of |
|
93 ** the posibility for different decor styles |
|
94 ** values could be passed are the MWM_DECOR defines |
|
95 ** for the moment we are full on or full off. |
|
96 */ |
|
97 #define AWT_NO_DECOR 0x0 |
|
98 #define AWT_FULL_DECOR MWM_DECOR_ALL |
|
99 |
|
100 static void reshape(JNIEnv *env, jobject this, struct FrameData *wdata, |
|
101 jint x, jint y, jint w, jint h, Boolean setXY); |
|
102 Widget findTopLevelByShell(Widget widget); |
|
103 |
|
104 extern EmbeddedFrame *theEmbeddedFrameList; |
|
105 extern struct ComponentIDs componentIDs; |
|
106 extern struct MMenuBarPeerIDs mMenuBarPeerIDs; |
|
107 extern struct MComponentPeerIDs mComponentPeerIDs; |
|
108 struct WindowIDs windowIDs; |
|
109 struct MWindowPeerIDs mWindowPeerIDs; |
|
110 extern struct InsetsIDs insetsIDs; |
|
111 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs; |
|
112 extern struct KeyboardFocusManagerIDs keyboardFocusManagerIDs; |
|
113 extern struct X11GraphicsDeviceIDs x11GraphicsDeviceIDs; |
|
114 |
|
115 #ifndef NOMODALFIX |
|
116 extern Boolean awt_isModal(); |
|
117 extern Boolean awt_isWidgetModal(Widget w); |
|
118 extern void awt_shellPoppedUp(Widget shell, XtPointer c, XtPointer d); |
|
119 extern void awt_shellPoppedDown(Widget shell, XtPointer c, XtPointer d); |
|
120 #endif //NOMODALFIX |
|
121 |
|
122 static jclass inputMethodWindowClass = NULL; |
|
123 |
|
124 static int32_t globalTopGuess = 0; |
|
125 static int32_t globalLeftGuess = 0; |
|
126 static int32_t globalBottomGuess = 0; |
|
127 static int32_t globalRightGuess = 0; |
|
128 |
|
129 |
|
130 // Atom used for otlogenniy top-level disposal |
|
131 static Atom _XA_JAVA_DISPOSE_PROPERTY_ATOM = 0; |
|
132 |
|
133 /* |
|
134 * Fix for bug 4141361 |
|
135 * |
|
136 * We keep a linked list of the FrameData information for |
|
137 * every top level window. |
|
138 */ |
|
139 struct FrameDataList { |
|
140 struct FrameData* wdata; |
|
141 struct FrameDataList* next; |
|
142 }; |
|
143 |
|
144 static struct FrameDataList* allTopLevel = NULL; |
|
145 |
|
146 extern void checkNewXineramaScreen(JNIEnv* env, jobject peer, |
|
147 struct FrameData* wdata, |
|
148 int32_t newX, int32_t newY, |
|
149 int32_t newWidth, int32_t newHeight); |
|
150 |
|
151 // Returns false if this Window is non-focusable |
|
152 // or its nearest decorated parent is non-focusable. |
|
153 Boolean isFocusableWindowByPeer(JNIEnv * env, jobject peer) { |
|
154 jobject target, decoratedParent; |
|
155 struct FrameData *wdata; |
|
156 Boolean focusable; |
|
157 |
|
158 wdata = (struct FrameData *)JNU_GetLongFieldAsPtr(env, peer, mComponentPeerIDs.pData); |
|
159 DASSERT(wdata != NULL); |
|
160 |
|
161 target = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target); |
|
162 DASSERT(target != NULL); |
|
163 |
|
164 decoratedParent = getOwningFrameOrDialog(target, env); |
|
165 (*env)->DeleteLocalRef(env, target); |
|
166 |
|
167 if (decoratedParent == NULL) { |
|
168 return wdata->isFocusableWindow; |
|
169 } else { |
|
170 jobject parentPeer = (*env)->GetObjectField(env, decoratedParent, componentIDs.peer); |
|
171 DASSERT(parentPeer != NULL); |
|
172 focusable = wdata->isFocusableWindow && isFocusableWindowByPeer(env, parentPeer); |
|
173 |
|
174 (*env)->DeleteLocalRef(env, decoratedParent); |
|
175 (*env)->DeleteLocalRef(env, parentPeer); |
|
176 } |
|
177 return focusable; |
|
178 } |
|
179 |
|
180 // Returns false if this shell's Java Window is non-focusable |
|
181 // or its nearest decorated parent is non-focusable. |
|
182 // Returns true otherwise or if any of parameters is NULL |
|
183 Boolean isFocusableWindowByShell(JNIEnv* env, Widget shell) { |
|
184 Widget toplevel; |
|
185 jobject peer; |
|
186 Boolean focusable; |
|
187 |
|
188 DASSERT(shell != NULL && XtIsShell(shell)); |
|
189 if (shell == NULL) return True; |
|
190 if (!XtIsShell(shell)) return True; |
|
191 |
|
192 toplevel = findTopLevelByShell(shell); |
|
193 if (toplevel == NULL) { |
|
194 return True; |
|
195 } |
|
196 peer = findPeer(&toplevel); |
|
197 DASSERT(peer != NULL); |
|
198 |
|
199 if (env == NULL) { |
|
200 env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
201 } |
|
202 return isFocusableWindowByPeer(env, peer); |
|
203 } |
|
204 |
|
205 |
|
206 // Returns Shell widget - the parent of this child |
|
207 Widget getShellWidget(Widget child) { |
|
208 |
|
209 while (child != NULL && !XtIsShell(child)) { |
|
210 child = XtParent(child); |
|
211 } |
|
212 return child; |
|
213 } |
|
214 |
|
215 // Returns false if the parent shell of this widget is non-focusable Java Window. |
|
216 // Returns false otherwise. |
|
217 // Doesn't accept NULL parameters. |
|
218 Boolean isFocusableComponentTopLevelByWidget(JNIEnv * env, Widget child) { |
|
219 Widget shell = NULL; |
|
220 shell = getShellWidget(child); |
|
221 DASSERT(shell); |
|
222 return isFocusableWindowByShell(env, shell); |
|
223 } |
|
224 |
|
225 |
|
226 /* |
|
227 * Add a new element into the top level window list |
|
228 */ |
|
229 void addTopLevel(struct FrameData* wdata) { |
|
230 struct FrameDataList* newNode; |
|
231 newNode = (struct FrameDataList*) |
|
232 malloc(sizeof(struct FrameDataList)); |
|
233 newNode->wdata = wdata; |
|
234 newNode->next = allTopLevel; |
|
235 allTopLevel = newNode; |
|
236 } |
|
237 |
|
238 /* |
|
239 * Remove an element from the top level window list |
|
240 * (recursive) |
|
241 */ |
|
242 Boolean removeTopLevelR(struct FrameDataList** ptr, |
|
243 struct FrameData* wdata) { |
|
244 struct FrameDataList* node = *ptr; |
|
245 if (node == NULL) { |
|
246 return False; |
|
247 } |
|
248 if (node->wdata == wdata) { |
|
249 *ptr = node->next; |
|
250 free(node); |
|
251 return True; |
|
252 } |
|
253 return removeTopLevelR(&(node->next), wdata); |
|
254 } |
|
255 |
|
256 Boolean removeTopLevel(struct FrameData* wdata) { |
|
257 return removeTopLevelR(&allTopLevel, wdata); |
|
258 } |
|
259 |
|
260 /* |
|
261 * Return the Widget ID of the top level window underneath the |
|
262 * mouse pointer. |
|
263 */ |
|
264 Widget awt_GetWidgetAtPointer() { |
|
265 struct FrameDataList* ptr = allTopLevel; |
|
266 Window rootWindow, childWindow, mainWindow; |
|
267 int32_t xw, yw, xr, yr; |
|
268 uint32_t keys; |
|
269 while (ptr != NULL) { |
|
270 mainWindow = XtWindow(ptr->wdata->mainWindow); |
|
271 XQueryPointer(awt_display, mainWindow, |
|
272 &rootWindow, &childWindow, &xr, &yr, &xw, &yw, &keys); |
|
273 if (childWindow != None) { |
|
274 return ptr->wdata->winData.comp.widget; |
|
275 } |
|
276 ptr = ptr->next; |
|
277 } |
|
278 return NULL; |
|
279 } |
|
280 |
|
281 Widget findFocusProxy(Widget widget) { |
|
282 struct FrameDataList* ptr = allTopLevel; |
|
283 for (ptr = allTopLevel; ptr != NULL; ptr = ptr->next) { |
|
284 if (ptr->wdata->winData.comp.widget == widget) { |
|
285 return ptr->wdata->focusProxy; |
|
286 } |
|
287 } |
|
288 return NULL; |
|
289 } |
|
290 |
|
291 Widget findTopLevelByShell(Widget widget) { |
|
292 struct FrameDataList* ptr; |
|
293 for (ptr = allTopLevel; ptr != NULL; ptr = ptr->next) { |
|
294 if (ptr->wdata->winData.shell == widget) { |
|
295 return ptr->wdata->winData.comp.widget; |
|
296 } |
|
297 } |
|
298 return NULL; |
|
299 } |
|
300 |
|
301 void |
|
302 awt_Frame_guessInsets(struct FrameData *wdata) |
|
303 { |
|
304 if (wdata->decor == AWT_NO_DECOR ) { |
|
305 wdata->top = wdata->topGuess = 0; |
|
306 wdata->left = wdata->leftGuess = 0; |
|
307 wdata->bottom = wdata->bottomGuess = 0; |
|
308 wdata->right = wdata->rightGuess = 0; |
|
309 return; |
|
310 } |
|
311 |
|
312 if (globalTopGuess == 0) { |
|
313 char *insets_env; |
|
314 |
|
315 if (wdata->top >= 0) { |
|
316 /* insets were set on wdata by System Properties */ |
|
317 globalTopGuess = wdata->top; |
|
318 globalLeftGuess = wdata->left; |
|
319 globalBottomGuess = wdata->bottom; |
|
320 globalRightGuess = wdata->right; |
|
321 } |
|
322 else switch (awt_wm_getRunningWM()) { |
|
323 case ENLIGHTEN_WM: |
|
324 globalTopGuess = 19; |
|
325 globalLeftGuess = 4; |
|
326 globalBottomGuess = 4; |
|
327 globalRightGuess = 4; |
|
328 break; |
|
329 |
|
330 case CDE_WM: |
|
331 globalTopGuess = 28; |
|
332 globalLeftGuess = 6; |
|
333 globalBottomGuess = 6; |
|
334 globalRightGuess = 6; |
|
335 break; |
|
336 |
|
337 case MOTIF_WM: |
|
338 case OPENLOOK_WM: |
|
339 default: |
|
340 globalTopGuess = 25; |
|
341 globalLeftGuess = 5; |
|
342 globalBottomGuess = 5; |
|
343 globalRightGuess = 5; |
|
344 break; |
|
345 } |
|
346 |
|
347 if ((insets_env = getenv("AWT_INSETS")) != NULL) { |
|
348 int guess = atoi(insets_env); |
|
349 globalTopGuess = (guess & 0xff00) >> 8; |
|
350 globalLeftGuess = guess & 0x00ff; |
|
351 globalBottomGuess = wdata->leftGuess; |
|
352 globalRightGuess = wdata->leftGuess; |
|
353 } |
|
354 |
|
355 /* don't allow bizarly large insets */ |
|
356 if ((globalTopGuess > 64) || (globalTopGuess < 0)) |
|
357 globalTopGuess = 28; |
|
358 if ((globalLeftGuess > 32) || (globalLeftGuess < 0)) |
|
359 globalLeftGuess = 6; |
|
360 if ((globalBottomGuess > 32) || (globalBottomGuess < 0)) |
|
361 globalBottomGuess = 6; |
|
362 if ((globalRightGuess > 32) || (globalRightGuess < 0)) |
|
363 globalRightGuess = 6; |
|
364 } |
|
365 |
|
366 wdata->top = wdata->topGuess = globalTopGuess; |
|
367 wdata->left = wdata->leftGuess = globalLeftGuess; |
|
368 wdata->bottom = wdata->bottomGuess = globalBottomGuess; |
|
369 wdata->right = wdata->rightGuess = globalRightGuess; |
|
370 } |
|
371 |
|
372 /* |
|
373 * To keep input method windows floating, maintain a list of all |
|
374 * input method windows here. When some top level window gets |
|
375 * activated, moved, or resized, these input method windows need |
|
376 * to be brought on top. |
|
377 */ |
|
378 static struct FrameDataList* allInputMethodWindow = NULL; |
|
379 |
|
380 /* |
|
381 * Add a new element into the input method window list |
|
382 */ |
|
383 void addInputMethodWindow(struct FrameData* wdata) { |
|
384 struct FrameDataList* newNode; |
|
385 newNode = (struct FrameDataList*) |
|
386 malloc(sizeof(struct FrameDataList)); |
|
387 newNode->wdata = wdata; |
|
388 newNode->next = allInputMethodWindow; |
|
389 allInputMethodWindow = newNode; |
|
390 } |
|
391 |
|
392 /* |
|
393 * Remove an element from the top level window list |
|
394 * (recursive) |
|
395 */ |
|
396 Boolean removeInputMethodWindowR(struct FrameDataList** ptr, |
|
397 struct FrameData* wdata) { |
|
398 struct FrameDataList* node = *ptr; |
|
399 if (node == NULL) { |
|
400 return False; |
|
401 } |
|
402 if (node->wdata == wdata) { |
|
403 *ptr = node->next; |
|
404 free(node); |
|
405 return True; |
|
406 } |
|
407 return removeInputMethodWindowR(&(node->next), wdata); |
|
408 } |
|
409 |
|
410 Boolean removeInputMethodWindow(struct FrameData* wdata) { |
|
411 return removeInputMethodWindowR(&allInputMethodWindow, wdata); |
|
412 } |
|
413 |
|
414 /* |
|
415 * Raise input method windows |
|
416 */ |
|
417 void raiseInputMethodWindow(struct FrameData* wdata) { |
|
418 struct FrameDataList* node = allInputMethodWindow; |
|
419 |
|
420 if (wdata->isInputMethodWindow) { |
|
421 return; |
|
422 } |
|
423 |
|
424 while (node != NULL) { |
|
425 XRaiseWindow(awt_display, XtWindow(node->wdata->winData.shell)); |
|
426 node = node->next; |
|
427 } |
|
428 } |
|
429 |
|
430 /* fieldIDs for Frame fields that may be accessed from C */ |
|
431 static struct FrameIDs { |
|
432 jfieldID resizable; |
|
433 jfieldID state; |
|
434 } frameIDs; |
|
435 |
|
436 /* |
|
437 * Class: java_awt_Frame |
|
438 * Method: initIDs |
|
439 * Signature: ()V |
|
440 */ |
|
441 |
|
442 /* This function gets called from the static initializer for Frame.java |
|
443 to initialize the fieldIDs for fields that may be accessed from C */ |
|
444 JNIEXPORT void JNICALL |
|
445 Java_java_awt_Frame_initIDs |
|
446 (JNIEnv *env, jclass cls) |
|
447 { |
|
448 frameIDs.resizable = (*env)->GetFieldID(env, cls, "resizable", "Z"); |
|
449 frameIDs.state = (*env)->GetFieldID(env, cls, "state", "I"); |
|
450 } |
|
451 |
|
452 /* ******* */ |
|
453 /* Dialogs */ |
|
454 /* ******* */ |
|
455 /* No longer have a need for unique fields for query */ |
|
456 static struct DialogIDs { |
|
457 jfieldID modal; |
|
458 jfieldID resizable; |
|
459 } dialogIDs; |
|
460 |
|
461 JNIEXPORT void JNICALL |
|
462 Java_java_awt_Dialog_initIDs |
|
463 (JNIEnv *env, jclass cls) |
|
464 { |
|
465 #if 0 |
|
466 dialogIDs.modal = (*env)->GetFieldID(env, cls, "modal", "Z"); |
|
467 dialogIDs.resizable = (*env)->GetFieldID(env, cls, "resizable", "Z"); |
|
468 #endif |
|
469 } |
|
470 |
|
471 /* ******* */ |
|
472 /* Windows */ |
|
473 /* ******* */ |
|
474 |
|
475 JNIEXPORT void JNICALL |
|
476 Java_java_awt_Window_initIDs |
|
477 (JNIEnv *env, jclass cls) |
|
478 { |
|
479 windowIDs.warningString = (*env)->GetFieldID(env, cls, "warningString", |
|
480 "Ljava/lang/String;"); |
|
481 windowIDs.resetGCMID = (*env)->GetMethodID(env, cls, "resetGC", |
|
482 "()V"); |
|
483 |
|
484 windowIDs.locationByPlatform = (*env)->GetFieldID(env, cls, "locationByPlatform", |
|
485 "Z"); |
|
486 windowIDs.isAutoRequestFocus = (*env)->GetFieldID(env, cls, "autoRequestFocus", "Z"); |
|
487 |
|
488 DASSERT(windowIDs.resetGCMID); |
|
489 } |
|
490 |
|
491 /* |
|
492 * Class: sun_motif_awt_WindowAttributes |
|
493 * Method: initIDs |
|
494 * Signature: ()V |
|
495 */ |
|
496 |
|
497 static struct MWindowAttributeIDs { |
|
498 jfieldID nativeDecor; |
|
499 jfieldID initialFocus; |
|
500 jfieldID isResizable; |
|
501 jfieldID initialState; |
|
502 jfieldID visibilityState; |
|
503 jfieldID decorations; |
|
504 } mWindowAttributeIDs; |
|
505 |
|
506 JNIEXPORT void JNICALL |
|
507 Java_sun_awt_motif_MWindowAttributes_initIDs |
|
508 (JNIEnv *env, jclass cls) |
|
509 { |
|
510 mWindowAttributeIDs.nativeDecor = |
|
511 (*env)->GetFieldID(env, cls, "nativeDecor", "Z"); |
|
512 mWindowAttributeIDs.initialFocus = |
|
513 (*env)->GetFieldID(env, cls, "initialFocus", "Z"); |
|
514 mWindowAttributeIDs.isResizable = |
|
515 (*env)->GetFieldID(env, cls, "isResizable", "Z"); |
|
516 mWindowAttributeIDs.initialState = |
|
517 (*env)->GetFieldID(env, cls, "initialState", "I"); |
|
518 mWindowAttributeIDs.visibilityState = |
|
519 (*env)->GetFieldID(env, cls, "visibilityState", "I"); |
|
520 mWindowAttributeIDs.decorations = |
|
521 (*env)->GetFieldID(env, cls, "decorations", "I"); |
|
522 } |
|
523 |
|
524 /* |
|
525 * Class: sun_awt_motif_MWindowPeer |
|
526 * Method: initIDs |
|
527 * Signature: ()V |
|
528 */ |
|
529 |
|
530 /* This function gets called from the static initializer for MWindowPeer.java |
|
531 to initialize the fieldIDs for fields that may be accessed from C */ |
|
532 |
|
533 JNIEXPORT void JNICALL |
|
534 Java_sun_awt_motif_MWindowPeer_initIDs |
|
535 (JNIEnv *env, jclass cls) |
|
536 { |
|
537 mWindowPeerIDs.insets = |
|
538 (*env)->GetFieldID(env, cls, "insets", "Ljava/awt/Insets;"); |
|
539 mWindowPeerIDs.winAttr = |
|
540 (*env)->GetFieldID( env, |
|
541 cls, |
|
542 "winAttr", |
|
543 "Lsun/awt/motif/MWindowAttributes;" |
|
544 ); |
|
545 mWindowPeerIDs.iconWidth = |
|
546 (*env)->GetFieldID(env, cls, "iconWidth", "I"); |
|
547 mWindowPeerIDs.iconHeight = |
|
548 (*env)->GetFieldID(env, cls, "iconHeight", "I"); |
|
549 mWindowPeerIDs.handleWindowFocusOut = |
|
550 (*env)->GetMethodID(env, |
|
551 cls, |
|
552 "handleWindowFocusOut", |
|
553 "(Ljava/awt/Window;)V"); |
|
554 mWindowPeerIDs.handleWindowFocusIn = |
|
555 (*env)->GetMethodID(env, |
|
556 cls, |
|
557 "handleWindowFocusIn", |
|
558 "()V"); |
|
559 mWindowPeerIDs.handleIconify = |
|
560 (*env)->GetMethodID(env, |
|
561 cls, |
|
562 "handleIconify", |
|
563 "()V"); |
|
564 mWindowPeerIDs.handleDeiconify = |
|
565 (*env)->GetMethodID(env, |
|
566 cls, |
|
567 "handleDeiconify", |
|
568 "()V"); |
|
569 mWindowPeerIDs.handleStateChange = |
|
570 (*env)->GetMethodID(env, |
|
571 cls, |
|
572 "handleStateChange", |
|
573 "(II)V"); |
|
574 |
|
575 mWindowPeerIDs.draggedToScreenMID = (*env)->GetMethodID(env, cls, |
|
576 "draggedToNewScreen", |
|
577 "(I)V"); |
|
578 DASSERT(mWindowPeerIDs.draggedToScreenMID); |
|
579 } |
|
580 |
|
581 /* |
|
582 * Class: sun_awt_motif_MWindowPeer |
|
583 * Method: wrapInSequenced |
|
584 * Signature: (Ljava/awt/AWTEvent;)Ljava/awt/SequencedEvent; |
|
585 */ |
|
586 |
|
587 /* This method gets called from MWindowPeer to wrap a FocusEvent in |
|
588 a SequencedEvent. We have to do this in native code, because we |
|
589 don't want to make SequencedEvent a public class. */ |
|
590 |
|
591 JNIEXPORT jobject JNICALL |
|
592 Java_sun_awt_motif_MWindowPeer_wrapInSequenced |
|
593 (JNIEnv *env, jobject this, jobject awtevent) |
|
594 { |
|
595 jobject global = awt_canvas_wrapInSequenced(awtevent); |
|
596 jobject local = (*env)->NewLocalRef(env, global); |
|
597 (*env)->DeleteGlobalRef(env, global); |
|
598 return local; |
|
599 } |
|
600 |
|
601 extern jobject findTopLevelOpposite(); |
|
602 |
|
603 /* |
|
604 * Class: sun_awt_motif_MWindowPeer |
|
605 * Method: findOpposite |
|
606 * Signature: (Ljava/awt/AWTEvent;)Ljava/awt/Window; |
|
607 */ |
|
608 |
|
609 JNIEXPORT jobject JNICALL |
|
610 Java_sun_awt_motif_MWindowPeer_findOpposite |
|
611 (JNIEnv *env, jobject this, jint eventType) |
|
612 { |
|
613 #ifdef HEADLESS |
|
614 return NULL; |
|
615 #else |
|
616 if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
|
617 return NULL; |
|
618 } |
|
619 |
|
620 return findTopLevelOpposite(env, eventType); |
|
621 #endif |
|
622 } |
|
623 |
|
624 /* changeInsets() sets target's insets equal to X/Motif values. */ |
|
625 |
|
626 static void |
|
627 awtJNI_ChangeInsets(JNIEnv * env, jobject this, struct FrameData *wdata) |
|
628 { |
|
629 jobject insets; |
|
630 |
|
631 if ((*env)->EnsureLocalCapacity(env, 1) < 0) |
|
632 return; |
|
633 |
|
634 insets = (*env)->GetObjectField(env, this, mWindowPeerIDs.insets); |
|
635 |
|
636 if (JNU_IsNull(env, insets)) { |
|
637 return; |
|
638 } |
|
639 |
|
640 (*env)->SetIntField(env, insets, insetsIDs.top, wdata->top); |
|
641 (*env)->SetIntField(env, insets, insetsIDs.left, wdata->left); |
|
642 (*env)->SetIntField(env, insets, insetsIDs.bottom, wdata->bottom); |
|
643 (*env)->SetIntField(env, insets, insetsIDs.right, wdata->right); |
|
644 |
|
645 /* Fix for 4106068: don't do it, rely on the window */ |
|
646 /* manager maximizing policy instead */ |
|
647 #if 0 |
|
648 /* when the insets get set, make sure we set the proper */ |
|
649 /* max window size (since it's dependent on inset size) */ |
|
650 if (wdata->isResizable) { |
|
651 int32_t screenWidth = XWidthOfScreen( XDefaultScreenOfDisplay(awt_display)); |
|
652 int32_t screenHeight= XHeightOfScreen(XDefaultScreenOfDisplay(awt_display)); |
|
653 XtVaSetValues(wdata->winData.shell, |
|
654 XmNmaxWidth, screenWidth - (wdata->left + wdata->right), |
|
655 XmNmaxHeight, screenHeight - (wdata->top + wdata->bottom), |
|
656 NULL); |
|
657 } |
|
658 #endif |
|
659 (*env)->DeleteLocalRef(env, insets); |
|
660 } |
|
661 |
|
662 |
|
663 /* setMbAndWwHeightAndOffsets() attempts to establish the heights |
|
664 of frame's menu bar and warning window (if present in frame). |
|
665 setMbAndWwHeightAndOffsets() also adjusts appropriately the |
|
666 X/Motif offsets and calls changeInsets() to set target insets. |
|
667 A warning window, if present, is established during ...create(). |
|
668 wdata->warningWindow is set there, wdata->wwHeight is set here. |
|
669 Routine pSetMenuBar() sets value of the wdata->menuBar field. |
|
670 This routine reads that value. If it is not null, a menubar |
|
671 has been added. In this case, calculate the current height |
|
672 of the menu bar. This may be a partial (incomplete) menubar |
|
673 because ths routine may be called before the X/Motif menubar |
|
674 is completely realized. In this case, the menubar height may |
|
675 be adjusted incrementally. This routine may be called from |
|
676 ...pSetMenuBar(), innerCanvasEH(), and ...pReshape(). It is |
|
677 designed to (eventually) obtain the correct menubar height. |
|
678 On the other hand, if wdata->menuBar is NULL and the stored |
|
679 menubar height is not zero, then we subtract off the height. */ |
|
680 |
|
681 static void |
|
682 awtJNI_setMbAndWwHeightAndOffsets(JNIEnv * env, |
|
683 jobject this, |
|
684 struct FrameData *wdata ) |
|
685 { |
|
686 Dimension warningHeight, /* Motif warning window height */ |
|
687 labelHeight; /* Motif warning label's height */ |
|
688 |
|
689 WidgetList warningChildrenWL; /* warning children widgets */ |
|
690 |
|
691 Dimension menuBarWidth, /* Motif menubar width */ |
|
692 menuBarHeight, /* Motif menubar height */ |
|
693 menuBarBorderSize, /* Motif menubar border size */ |
|
694 marginHeight, /* Motif menubar margin height */ |
|
695 menuHeight, /* Motif menubar's menu height */ |
|
696 menuBorderSize, /* Motif menu border size */ |
|
697 actualHeight; /* height: menu+margins+borders */ |
|
698 |
|
699 WidgetList menuBarChildrenWL; /* menubar children widgets */ |
|
700 Cardinal numberChildren; /* number of menubar children */ |
|
701 |
|
702 #ifdef _pauly_debug |
|
703 fprintf(stdout," ++ setMenuBar\n"); |
|
704 fflush(stdout); |
|
705 #endif /* _pauly_debug */ |
|
706 |
|
707 /* If warning window height not yet known, try to get it now. |
|
708 It will be added to top or bottom (iff NETSCAPE) offset. */ |
|
709 if (wdata->warningWindow != NULL) { |
|
710 XtVaGetValues(wdata->warningWindow, |
|
711 XmNheight, &warningHeight, |
|
712 XmNchildren, &warningChildrenWL, |
|
713 XmNnumChildren, &numberChildren, |
|
714 NULL); |
|
715 |
|
716 /* We may be doing this before warning window is realized ! So, |
|
717 check for a child label in the warning. If its height is not |
|
718 yet accounted for in the warning height, then use it here. */ |
|
719 if (numberChildren != 0) { |
|
720 XtVaGetValues(warningChildrenWL[0], |
|
721 XmNheight, &labelHeight, |
|
722 NULL); |
|
723 #ifdef _pauly_debug |
|
724 fprintf(stdout," setMenuBar.... warning label found with height: %d\n", labelHeight); |
|
725 fflush(stdout); |
|
726 #endif /* _pauly_debug */ |
|
727 if (warningHeight < labelHeight) { |
|
728 #ifdef _pauly_debug |
|
729 fprintf(stdout," setMenuBar.... !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); |
|
730 fflush(stdout); |
|
731 #endif /* _pauly_debug */ |
|
732 warningHeight = labelHeight; |
|
733 } |
|
734 } |
|
735 |
|
736 if (wdata->wwHeight < warningHeight) { |
|
737 #ifdef _pauly_debug |
|
738 fprintf(stdout, " setMenuBar.... adding warning height: %d\n", warningHeight); |
|
739 fflush(stdout); |
|
740 #endif /* _pauly_debug */ |
|
741 #ifdef NETSCAPE |
|
742 wdata->bottom += (warningHeight - wdata->wwHeight); |
|
743 #else |
|
744 wdata->top += (warningHeight - wdata->wwHeight); |
|
745 #endif /* NETSCAPE */ |
|
746 awtJNI_ChangeInsets(env, this, wdata); |
|
747 wdata->wwHeight = warningHeight; |
|
748 } |
|
749 } |
|
750 |
|
751 /* Now we adjust offsets for an added or removed menu bar */ |
|
752 if (wdata->menuBar != NULL) { |
|
753 #ifdef _pauly_debug |
|
754 fprintf(stdout," setMenuBar. menu bar: %x\n", wdata->menuBar); |
|
755 fflush(stdout); |
|
756 #endif /* _pauly_debug */ |
|
757 XtVaGetValues(wdata->menuBar, |
|
758 XmNwidth, &menuBarWidth, |
|
759 XmNheight, &menuBarHeight, |
|
760 XmNchildren, &menuBarChildrenWL, |
|
761 XmNnumChildren, &numberChildren, |
|
762 XmNborderWidth, &menuBarBorderSize, |
|
763 XmNmarginHeight, &marginHeight, |
|
764 NULL); |
|
765 |
|
766 /* We may be doing this before menu bar is realized ! Hence, |
|
767 check for a menu in the menu bar. If its height is not yet |
|
768 accounted for in the menu bar height, then add it in here. */ |
|
769 if (numberChildren != 0) { |
|
770 XtVaGetValues(menuBarChildrenWL[0], |
|
771 XmNheight, &menuHeight, |
|
772 XmNborderWidth, &menuBorderSize, |
|
773 NULL); |
|
774 #ifdef _pauly_debug |
|
775 fprintf(stdout," setMenuBar.... menu found with height: %d, border: %d, margin: %d, bar border: %d\n", menuHeight, menuBorderSize, marginHeight, menuBarBorderSize); |
|
776 fflush(stdout); |
|
777 #endif /* _pauly_debug */ |
|
778 /* Calculate real height of menu bar by adding height of its |
|
779 child menu and borders, margins, and the menu bar borders*/ |
|
780 actualHeight = menuHeight + (2 * menuBorderSize) + |
|
781 (2 * marginHeight) + (2 * menuBarBorderSize); |
|
782 #ifdef __linux__ |
|
783 #ifdef _pauly_debug |
|
784 fprintf(stdout," actual height: %d mb height %d\n", actualHeight, menuBarHeight); |
|
785 fflush(stdout); |
|
786 #endif /* _pauly_debug */ |
|
787 #endif |
|
788 if (menuBarHeight < actualHeight) { |
|
789 #ifdef _pauly_debug |
|
790 fprintf(stdout," setMenuBar.... ****************************************\n"); |
|
791 fflush(stdout); |
|
792 #endif /* _pauly_debug */ |
|
793 menuBarHeight = actualHeight; |
|
794 } |
|
795 } |
|
796 |
|
797 if (wdata->mbHeight < menuBarHeight) { |
|
798 /* Adjust the (partially) added menu bar height, top offset.*/ |
|
799 #ifdef _pauly_debug |
|
800 fprintf(stdout, " setMenuBar.... added menuBar height: %d\n", menuBarHeight); |
|
801 fflush(stdout); |
|
802 #endif /* _pauly_debug */ |
|
803 wdata->top += (menuBarHeight - wdata->mbHeight); |
|
804 awtJNI_ChangeInsets(env, this, wdata); |
|
805 wdata->mbHeight = menuBarHeight; |
|
806 } |
|
807 } else if ((wdata->menuBar == NULL) && (wdata->mbHeight > 0)) { |
|
808 /* A menu bar has been removed; subtract height from top offset.*/ |
|
809 wdata->top -= wdata->mbHeight; |
|
810 #ifdef _pauly_debug |
|
811 fprintf(stdout, " setMenuBar.... removed menuBar height: %d\n", wdata->mbHeight); |
|
812 fflush(stdout); |
|
813 #endif /* _pauly_debug */ |
|
814 awtJNI_ChangeInsets(env, this, wdata); |
|
815 wdata->mbHeight = 0; |
|
816 } |
|
817 } |
|
818 |
|
819 |
|
820 /* outerCanvasResizeCB() is Motif resize callback for outer/child canvas. |
|
821 It reads width, height of Motif widget, sets java target accordingly, |
|
822 and then calls handleResize() to affect any changes. |
|
823 This call is only done for a shell resize or inner/parent resize; |
|
824 i.e., it may not be done for a ...pReshape() to avoid doing a loop. |
|
825 |
|
826 client_data is MWindowPeer instance |
|
827 */ |
|
828 static void |
|
829 outerCanvasResizeCB(Widget wd, XtPointer client_data, XtPointer call_data) |
|
830 { |
|
831 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
832 jobject target; |
|
833 struct FrameData *wdata; |
|
834 Position screenX; /* x position of the canvas, screen */ |
|
835 Position screenY; /* y position of the canvas, screen */ |
|
836 Dimension width; /* width of the canvas, target */ |
|
837 Dimension height; /* height of the canvas, target */ |
|
838 jint oldWidth; |
|
839 jint oldHeight; |
|
840 |
|
841 #ifdef _pauly_debug |
|
842 fprintf(stdout," ++ WindowResize.\n"); |
|
843 fflush(stdout); |
|
844 #endif /* _pauly_debug */ |
|
845 |
|
846 wdata = (struct FrameData *) |
|
847 JNU_GetLongFieldAsPtr(env, (jobject) client_data, |
|
848 mComponentPeerIDs.pData); |
|
849 if (wdata == NULL) { |
|
850 return; |
|
851 } |
|
852 |
|
853 if ((*env)->EnsureLocalCapacity(env, 1) < 0) |
|
854 return; |
|
855 |
|
856 target = (*env)->GetObjectField(env, (jobject) client_data, |
|
857 mComponentPeerIDs.target); |
|
858 XtVaGetValues(wd, |
|
859 XmNwidth, &width, |
|
860 XmNheight, &height, |
|
861 NULL); |
|
862 #ifdef _pauly_debug |
|
863 fprintf(stdout," outerCanvasResizeCB. width: %d, height: %d\n", width, height); |
|
864 fflush(stdout); |
|
865 #endif /* _pauly_debug */ |
|
866 |
|
867 |
|
868 XtTranslateCoords(wd, 0, 0, &screenX, &screenY); |
|
869 |
|
870 if ((wdata->shellResized) || (wdata->canvasResized)) { |
|
871 #ifdef _pauly_debug |
|
872 fprintf(stdout," outerCanvasResizeCB\n"); |
|
873 fflush(stdout); |
|
874 #endif /* _pauly_debug */ |
|
875 wdata->shellResized = False; |
|
876 wdata->canvasResized = False; |
|
877 /* |
|
878 ** if you are not yet reparented, don't compute the size based on the |
|
879 ** widgets, as the window manager shell containg the insets is not yet |
|
880 ** there. Use the size the application has set. |
|
881 ** If not reparented, we got here because the application set the size, |
|
882 ** so just send them Component.RESIZED event with the size they set. |
|
883 ** |
|
884 ** If the reparenting causes a resize ( only when inset guess is wrong ) ** the new size will be sent in a Component.RESIZED event at that time. |
|
885 */ |
|
886 if (wdata->reparented) |
|
887 { |
|
888 (*env)->SetIntField(env, target, componentIDs.x, (jint) screenX); |
|
889 (*env)->SetIntField(env, target, componentIDs.y, (jint) screenY); |
|
890 } |
|
891 |
|
892 oldWidth = (*env)->GetIntField(env, target, componentIDs.width); |
|
893 oldHeight = (*env)->GetIntField(env, target, componentIDs.height); |
|
894 |
|
895 if (oldWidth != width || oldHeight != height || wdata->need_reshape) |
|
896 { |
|
897 wdata->need_reshape = False; |
|
898 (*env)->SetIntField(env, target, componentIDs.width, (jint)width); |
|
899 (*env)->SetIntField(env, target, componentIDs.height, |
|
900 (jint)height); |
|
901 |
|
902 /* only do this for Windows, not Canvases, btw */ |
|
903 checkNewXineramaScreen(env, client_data, wdata, screenX, screenY, width, height); |
|
904 |
|
905 JNU_CallMethodByName(env, NULL, (jobject) client_data, |
|
906 "handleResize", "(II)V", width, height); |
|
907 if ((*env)->ExceptionOccurred(env)) { |
|
908 (*env)->ExceptionDescribe(env); |
|
909 (*env)->ExceptionClear(env); |
|
910 } |
|
911 } |
|
912 } |
|
913 |
|
914 (*env)->DeleteLocalRef(env, target); |
|
915 |
|
916 #ifdef _pauly_debug |
|
917 fprintf(stdout," WindowResize. Done.\n"); |
|
918 fflush(stdout); |
|
919 #endif /* _pauly_debug */ |
|
920 |
|
921 } /* outerCanvasResizeCB() */ |
|
922 |
|
923 static void reconfigureOuterCanvas ( JNIEnv *env, jobject target, |
|
924 jobject this, struct FrameData *wdata ) |
|
925 { |
|
926 Dimension innerDAWidth, /* width of inner Motif canvas */ |
|
927 innerDAHeight, /* height of inner Motif canvas */ |
|
928 outerDAWidth, /* width of outer Motif canvas */ |
|
929 outerDAHeight; /* height of outer Motif canvas */ |
|
930 int32_t targetWidth, /* java target object's width */ |
|
931 targetHeight; /* java target's object height */ |
|
932 Dimension width; /* width of the canvas, target */ |
|
933 Dimension height; /* height of the canvas, target */ |
|
934 |
|
935 |
|
936 Position innerX, /* x loc. of inner Motif canvas */ |
|
937 innerY, /* y loc. of inner Motif canvas */ |
|
938 x, y; |
|
939 |
|
940 /* canvasW is (visible) inner/parent drawing area (canvas) widget */ |
|
941 XtVaGetValues(XtParent(wdata->winData.comp.widget), |
|
942 XmNwidth, &innerDAWidth, |
|
943 XmNheight, &innerDAHeight, |
|
944 XmNx, &innerX, |
|
945 XmNy, &innerY, |
|
946 NULL); |
|
947 |
|
948 /* This resize may be due to the insertion or removal of a menu bar. |
|
949 If so, we appropriately adjust the top offset in wdata, insets. */ |
|
950 awtJNI_setMbAndWwHeightAndOffsets(env, this, wdata); |
|
951 |
|
952 outerDAWidth = innerDAWidth + wdata->left + wdata->right; |
|
953 outerDAHeight = innerDAHeight + wdata->top + wdata->bottom; |
|
954 |
|
955 /* If it's a menu bar reset, do not do resize of outer/child canvas. |
|
956 (Another thread problem; we arrest this now before damage done.) */ |
|
957 if (wdata->menuBarReset) |
|
958 { |
|
959 targetWidth = (*env)->GetIntField(env, target, componentIDs.width); |
|
960 targetHeight = (*env)->GetIntField(env, target, componentIDs.height); |
|
961 if ((outerDAWidth != targetWidth) || (outerDAHeight != targetHeight)) |
|
962 { |
|
963 return; |
|
964 } |
|
965 } |
|
966 |
|
967 wdata->canvasResized = True; |
|
968 |
|
969 /* The outer/child drawing area (canvas) needs to be configured too. |
|
970 If its size changes, its resize callback will thereby be invoked.*/ |
|
971 x = -wdata->left; |
|
972 y = -wdata->top; |
|
973 width = innerDAWidth + wdata->left + wdata->right; |
|
974 height = innerDAHeight + wdata->top + wdata->bottom; |
|
975 |
|
976 XtConfigureWidget(wdata->winData.comp.widget, x, y, width, height, 0 ); |
|
977 } |
|
978 |
|
979 |
|
980 |
|
981 /* innerCanvasEH() is event handler for inner/parent canvas. It handles |
|
982 map and configure notify events. It reads width and height, adjusts |
|
983 for menubar insertion / removal and configures outer/child canvas. */ |
|
984 |
|
985 static void |
|
986 innerCanvasEH(Widget canvasW, XtPointer client_data, XEvent *event, |
|
987 Boolean* continueToDispatch) |
|
988 { |
|
989 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
990 jobject this = (jobject) client_data; |
|
991 jobject target; |
|
992 struct FrameData *wdata; |
|
993 |
|
994 |
|
995 wdata = (struct FrameData *) |
|
996 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
997 if (wdata == NULL) { |
|
998 return; |
|
999 } |
|
1000 |
|
1001 if ((*env)->EnsureLocalCapacity(env, 1) < 0) |
|
1002 return; |
|
1003 |
|
1004 target = (*env)->GetObjectField(env, (jobject) client_data, |
|
1005 mComponentPeerIDs.target); |
|
1006 |
|
1007 /* While inside ...pSetMenuBar(), don't react to incomplete resizing |
|
1008 events supplied by Xt toolkit. Wait for completion of the routine. */ |
|
1009 |
|
1010 |
|
1011 /* For a map or resize, we need to check for the addition or deletion |
|
1012 of a menu bar to the form which is the of this drawing area (canvas). |
|
1013 We also must then configure the outer/child canvas appropriately. */ |
|
1014 |
|
1015 if ( (event->xany.type == MapNotify) || |
|
1016 (event->xany.type == ConfigureNotify) ) |
|
1017 { |
|
1018 reconfigureOuterCanvas( env, target, this, wdata ); |
|
1019 } |
|
1020 |
|
1021 (*env)->DeleteLocalRef(env, target); |
|
1022 |
|
1023 } |
|
1024 |
|
1025 /* syncTopLevelPos() is necessary to insure that the window manager has in |
|
1026 * fact moved us to our final position relative to the reParented WM window. |
|
1027 * We have noted a timing window which our shell has not been moved so we |
|
1028 * screw up the insets thinking they are 0,0. Wait (for a limited period of |
|
1029 * time to let the WM hava a chance to move us |
|
1030 */ |
|
1031 void syncTopLevelPos( Display *d, Window w, XWindowAttributes *winAttr ) |
|
1032 { |
|
1033 int32_t i = 0; |
|
1034 memset(winAttr, 0, sizeof(*winAttr)); |
|
1035 |
|
1036 do { |
|
1037 if (!XGetWindowAttributes(d, w, winAttr)) { |
|
1038 memset(winAttr, 0, sizeof(*winAttr)); |
|
1039 break; |
|
1040 } |
|
1041 /* Sometimes we get here before the WM has updated the |
|
1042 ** window data struct with the correct position. Loop |
|
1043 ** until we get a non-zero position. |
|
1044 */ |
|
1045 if ((winAttr->x != 0) || (winAttr->y != 0)) { |
|
1046 break; |
|
1047 } |
|
1048 else { |
|
1049 /* What we really want here is to sync with the WM, |
|
1050 ** but there's no explicit way to do this, so we |
|
1051 ** call XSync for a delay. |
|
1052 */ |
|
1053 XSync(d, False); |
|
1054 } |
|
1055 } while (i++ < 50); |
|
1056 } |
|
1057 |
|
1058 typedef struct FocusOutInfo_str { |
|
1059 XEvent * eventOut; |
|
1060 Window inWin; |
|
1061 Window inChild; |
|
1062 Widget defChild; |
|
1063 jobject childComp; |
|
1064 } FocusOutInfo_t; |
|
1065 |
|
1066 #define IsCanvasTypeWidget(w) \ |
|
1067 (XtIsSubclass(w, xmDrawingAreaWidgetClass) ||\ |
|
1068 XtIsSubclass(w, vDrawingAreaClass)) |
|
1069 |
|
1070 int isTopLevelPartWidget(Widget w) { |
|
1071 if (XtIsShell(w)) { |
|
1072 return TRUE; |
|
1073 } |
|
1074 if (XtIsSubclass(w, xmFormWidgetClass)) { |
|
1075 return TRUE; |
|
1076 } |
|
1077 if (IsCanvasTypeWidget(w)) { |
|
1078 Widget w1 = XtParent(w); |
|
1079 if (w1 != NULL) { |
|
1080 if (XtIsSubclass(w1, xmFormWidgetClass)) { |
|
1081 return TRUE; |
|
1082 } |
|
1083 if (IsCanvasTypeWidget(w1)) { |
|
1084 Widget w2 = XtParent(w1); |
|
1085 if (w2 != NULL) { |
|
1086 if (XtIsSubclass(w2, xmFormWidgetClass)) { |
|
1087 return TRUE; |
|
1088 } |
|
1089 } |
|
1090 } |
|
1091 |
|
1092 } |
|
1093 } |
|
1094 return FALSE; |
|
1095 } |
|
1096 |
|
1097 void |
|
1098 shellFocusEH(Widget w, XtPointer data, XEvent *event, Boolean *continueToDispatch) |
|
1099 { |
|
1100 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
1101 jobject this = (jobject) data; |
|
1102 jobject target; |
|
1103 struct FrameData *wdata; |
|
1104 |
|
1105 /* Any event handlers which take peer instance pointers as |
|
1106 * client_data should check to ensure the widget has not been |
|
1107 * marked as destroyed as a result of a dispose() call on the peer |
|
1108 * (which can result in the peer instance pointer already haven |
|
1109 * been gc'd by the time this event is processed) |
|
1110 */ |
|
1111 if (w->core.being_destroyed) { |
|
1112 return; |
|
1113 } |
|
1114 |
|
1115 wdata = (struct FrameData *) |
|
1116 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
1117 if (wdata == NULL) { |
|
1118 return; |
|
1119 } |
|
1120 |
|
1121 switch (event->xany.type) { |
|
1122 case FocusOut: |
|
1123 // Will be handled by proxy automaticall since he is focus owner |
|
1124 break; |
|
1125 case FocusIn: |
|
1126 // Forward focus event to the proxy |
|
1127 XSetInputFocus(awt_display, XtWindow(wdata->focusProxy), RevertToParent, CurrentTime); |
|
1128 break; |
|
1129 } |
|
1130 } |
|
1131 |
|
1132 /** |
|
1133 * Fix for Alt-Tab problem. |
|
1134 * See coments on use semantics below. |
|
1135 */ |
|
1136 Boolean skipNextNotifyWhileGrabbed = False; |
|
1137 Boolean skipNextFocusIn = False; |
|
1138 |
|
1139 Boolean focusOnMapNotify = False; |
|
1140 |
|
1141 /* shellEH() is event handler for the Motif shell widget. It handles |
|
1142 focus change, map notify, configure notify events for the shell. |
|
1143 Please see internal comments pertaining to these specific events. |
|
1144 |
|
1145 data is MWindowPeer instance pointer |
|
1146 */ |
|
1147 void |
|
1148 shellEH(Widget w, XtPointer data, XEvent *event, Boolean *continueToDispatch) |
|
1149 { |
|
1150 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
1151 jobject this = (jobject) data; |
|
1152 jobject target; |
|
1153 struct FrameData *wdata; |
|
1154 int32_t setTargetX, |
|
1155 setTargetY, |
|
1156 getTargetX, |
|
1157 getTargetY; |
|
1158 /* Changed long to int for 64-bit */ |
|
1159 int32_t wwHeight; /* height of any warning window present */ |
|
1160 int32_t topAdjust; /* adjust top offset for menu, warning */ |
|
1161 jclass clazz; |
|
1162 int32_t x, y; |
|
1163 int32_t width, height; |
|
1164 enum wmgr_t runningWM; |
|
1165 jobject winAttrObj; |
|
1166 static jobject windowClass = NULL; |
|
1167 /* Any event handlers which take peer instance pointers as |
|
1168 * client_data should check to ensure the widget has not been |
|
1169 * marked as destroyed as a result of a dispose() call on the peer |
|
1170 * (which can result in the peer instance pointer already haven |
|
1171 * been gc'd by the time this event is processed) |
|
1172 */ |
|
1173 if (w->core.being_destroyed) { |
|
1174 return; |
|
1175 } |
|
1176 |
|
1177 wdata = (struct FrameData *) |
|
1178 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
1179 if (wdata == NULL) { |
|
1180 return; |
|
1181 } |
|
1182 |
|
1183 switch (event->xany.type) { |
|
1184 |
|
1185 case FocusOut: { |
|
1186 int32_t res = 0; |
|
1187 int revert_to = 0; |
|
1188 Widget defChild = NULL; |
|
1189 Window focusOwner = None; |
|
1190 jobject oppositeWindow = NULL; |
|
1191 Widget oppositeShell = NULL; |
|
1192 XEvent inEvent; |
|
1193 Widget shell = NULL; |
|
1194 #ifdef DEBUG_FOCUS |
|
1195 fprintf(stderr, "Focusout on proxy; window = %x, mode %d, detail %d\n", |
|
1196 event->xfocus.window, event->xfocus.mode, event->xfocus.detail); |
|
1197 #endif |
|
1198 shell = wdata->winData.shell; |
|
1199 |
|
1200 if ((*env)->EnsureLocalCapacity(env, 3) < 0) { |
|
1201 break; |
|
1202 } |
|
1203 |
|
1204 /** |
|
1205 * Fix for Alt-Tab problem. We should process NotifyWhileGrabbed events |
|
1206 * only if they are due to the switch between top-levels. |
|
1207 * skipNextNotifyWhileGrabbed is set from Menu and PopupMenu code |
|
1208 * to prevent generation of focus events when user interact with these |
|
1209 * widget. |
|
1210 */ |
|
1211 if (event->xfocus.mode == NotifyWhileGrabbed) { |
|
1212 if (skipNextNotifyWhileGrabbed) { |
|
1213 skipNextNotifyWhileGrabbed = False; |
|
1214 break; |
|
1215 } |
|
1216 } else if (event->xfocus.mode != NotifyNormal) break; |
|
1217 |
|
1218 /** |
|
1219 * Fix for Alt-Tab problem. |
|
1220 * skipNextFocusIn is set in Choice code to avoid processing of |
|
1221 * next focus-in or focus-out generated by Choice as it is a fake |
|
1222 * event. |
|
1223 */ |
|
1224 if (skipNextFocusIn && event->xfocus.detail == NotifyPointer) { |
|
1225 break; |
|
1226 } |
|
1227 |
|
1228 XGetInputFocus( awt_display, &focusOwner, &revert_to); |
|
1229 |
|
1230 if (focusOwner != None) { |
|
1231 Widget inWidget = NULL; |
|
1232 jobject wpeer = NULL; |
|
1233 inWidget = XtWindowToWidget(awt_display, focusOwner); |
|
1234 if (inWidget != NULL && inWidget != shell) { |
|
1235 oppositeShell = getShellWidget(inWidget); |
|
1236 wpeer = findPeer(&inWidget); |
|
1237 if (wpeer == NULL) { |
|
1238 inWidget = findTopLevelByShell(inWidget); |
|
1239 if (inWidget != NULL) { |
|
1240 wpeer = findPeer(&inWidget); |
|
1241 } |
|
1242 } |
|
1243 if (wpeer != NULL) { |
|
1244 jobject peerComp = |
|
1245 (*env)->GetObjectField(env, |
|
1246 wpeer, |
|
1247 mComponentPeerIDs.target); |
|
1248 if (peerComp != NULL) { |
|
1249 // Check that peerComp is top-level |
|
1250 |
|
1251 // load class |
|
1252 if (windowClass == NULL) { |
|
1253 jobject localWindowClass = (*env)->FindClass(env, "java/awt/Window"); |
|
1254 windowClass = (*env)->NewGlobalRef(env, localWindowClass); |
|
1255 (*env)->DeleteLocalRef(env, localWindowClass); |
|
1256 } |
|
1257 if ((*env)->IsInstanceOf(env, peerComp, windowClass)) { |
|
1258 oppositeWindow = peerComp; |
|
1259 } else { // Opposite object is not Window - there is no opposite window. |
|
1260 (*env)->DeleteLocalRef(env, peerComp); |
|
1261 peerComp = NULL; |
|
1262 oppositeShell = NULL; |
|
1263 } |
|
1264 } |
|
1265 } |
|
1266 } |
|
1267 } else { |
|
1268 // If there is no opposite shell but we have active popup - this popup is actually |
|
1269 // the oppposite. This should mean that this focus out is due to popup - and thus |
|
1270 // should be skipped. Fix for 4478780. |
|
1271 if (skipNextNotifyWhileGrabbed) { |
|
1272 break; |
|
1273 } |
|
1274 } |
|
1275 |
|
1276 // If current window is not focusable and opposite window is not focusable - do nothing |
|
1277 // If current window is focusable and opposite is not - do not clear focus variables like |
|
1278 // focus didn't leave this window(but it will in terms of X). When we later switch to either |
|
1279 // - back to this window: variables are already here |
|
1280 // - another focusable window: variables point to focusable window and "focus lost" events |
|
1281 // will be generated for it |
|
1282 // - non-java window: variables point to focusable window and "focus lost" events |
|
1283 // will be generated for it, not for non-focusable. |
|
1284 // If current window is non-focusable and opposite is focusable then do not generate anything |
|
1285 // as if we didn't leave previous focusable window so Java events will generated for it. |
|
1286 // |
|
1287 // Fix for 6547951. |
|
1288 // Also do cleaning when switching to non-java window (opposite is null). |
|
1289 if (isFocusableWindowByShell(env, shell) && shell != oppositeShell && |
|
1290 ((oppositeShell != NULL && isFocusableWindowByShell(env, oppositeShell)) || |
|
1291 oppositeShell == NULL)) |
|
1292 { |
|
1293 // The necessary FOCUS_LOST event will be generated by DKFM. |
|
1294 // So we need to process focus list like we received FocusOut |
|
1295 // for the desired component - shell's current focus widget |
|
1296 defChild = XmGetFocusWidget(shell); |
|
1297 if (defChild != NULL) { |
|
1298 jobject peer = findPeer(&defChild); |
|
1299 if (peer == NULL) { |
|
1300 defChild = findTopLevelByShell(defChild); |
|
1301 if (defChild != NULL) { |
|
1302 peer = findPeer(&defChild); |
|
1303 } |
|
1304 } |
|
1305 if (peer != NULL) { |
|
1306 jobject comp = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target); |
|
1307 if (focusList != NULL) { |
|
1308 jobject last = (*env)->NewLocalRef(env, focusList->requestor); |
|
1309 if ((*env)->IsSameObject(env, comp, last)) { |
|
1310 FocusListElt * temp = focusList; |
|
1311 forGained = focusList->requestor; |
|
1312 focusList = focusList->next; |
|
1313 free(temp); |
|
1314 if (focusList == NULL) { |
|
1315 focusListEnd = NULL; |
|
1316 } |
|
1317 } |
|
1318 if (!JNU_IsNull(env, last)) { |
|
1319 (*env)->DeleteLocalRef(env, last); |
|
1320 } |
|
1321 } |
|
1322 (*env)->DeleteLocalRef(env, comp); |
|
1323 } |
|
1324 } |
|
1325 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
1326 processTree(defChild, findWindowsProxy(target, env), False); |
|
1327 XtSetKeyboardFocus(shell, NULL); |
|
1328 (*env)->DeleteLocalRef(env, target); |
|
1329 } |
|
1330 #ifndef NOMODALFIX |
|
1331 if (!awt_isModal() || awt_isWidgetModal(shell)) { |
|
1332 #endif //NOMODALFIX |
|
1333 if ( oppositeShell != NULL |
|
1334 && isFocusableWindowByShell(env, oppositeShell) |
|
1335 && isFocusableWindowByShell(env, shell) |
|
1336 || (oppositeShell == NULL)) |
|
1337 { |
|
1338 /* |
|
1339 * Fix for 5095117. |
|
1340 * Check if current native focused window is the same as source. |
|
1341 * Sometimes it is not - we must not however clean reference to |
|
1342 * actual native focused window. |
|
1343 */ |
|
1344 jobject currentFocusedWindow = awt_canvas_getFocusedWindowPeer(); |
|
1345 if ((*env)->IsSameObject(env, this, currentFocusedWindow)) { |
|
1346 awt_canvas_setFocusedWindowPeer(NULL); |
|
1347 } |
|
1348 (*env)->DeleteLocalRef(env, currentFocusedWindow); |
|
1349 |
|
1350 JNU_CallMethodByName(env, NULL, this, "handleWindowFocusOut", "(Ljava/awt/Window;)V", |
|
1351 oppositeWindow); |
|
1352 if ((*env)->ExceptionCheck(env) == JNI_TRUE) { |
|
1353 (*env)->ExceptionDescribe(env); |
|
1354 (*env)->ExceptionClear(env); |
|
1355 } |
|
1356 } |
|
1357 #ifndef NOMODALFIX |
|
1358 } |
|
1359 #endif //NOMODALFIX |
|
1360 if (oppositeWindow != NULL) { |
|
1361 (*env)->DeleteLocalRef(env, oppositeWindow); |
|
1362 } |
|
1363 |
|
1364 break; |
|
1365 } /* FocusOut */ |
|
1366 |
|
1367 case FocusIn: { |
|
1368 Widget shell = wdata->winData.shell; |
|
1369 #ifdef DEBUG_FOCUS |
|
1370 fprintf(stderr, "FocusIn on proxy; window = %x, mode %d, detail %d\n", event->xfocus.window, |
|
1371 event->xfocus.mode, event->xfocus.detail); |
|
1372 #endif |
|
1373 if (/* event->xfocus.mode == NotifyNormal */ 1) { |
|
1374 |
|
1375 /** |
|
1376 * Fix for Alt-Tab problem. We should process NotifyWhileGrabbed events to detect |
|
1377 * switch between top-levels using alt-tab, but avoid processing these type of event |
|
1378 * when they are originated from other sources. |
|
1379 */ |
|
1380 if (event->xfocus.mode == NotifyWhileGrabbed) { |
|
1381 /** |
|
1382 * skipNextNotifyWhileGrabbed is set from Menu and PopupMenu code to |
|
1383 * skip next focus-in event with NotifyWhileGrabbed as it is generated |
|
1384 * in result of closing of the Menu's shell. |
|
1385 * Event will also have NotifyInferior if uses clicked on menu bar in the |
|
1386 * space where there is not menu items. |
|
1387 */ |
|
1388 if (skipNextNotifyWhileGrabbed || event->xfocus.detail == NotifyInferior) { |
|
1389 skipNextNotifyWhileGrabbed = False; |
|
1390 break; |
|
1391 } |
|
1392 } else if (event->xfocus.mode != NotifyNormal) { |
|
1393 break; |
|
1394 } |
|
1395 |
|
1396 /** |
|
1397 * Fix for Alt-Tab problem. |
|
1398 * skipNextFocusIn is set from Choice code to avoid processing next focus-in |
|
1399 * as it is a fake event. |
|
1400 */ |
|
1401 if (skipNextFocusIn == True) { |
|
1402 /** |
|
1403 * There could be the set of fake events, the last one |
|
1404 * will have detail == NotifyPointer |
|
1405 */ |
|
1406 if (event->xfocus.detail != NotifyPointer) { |
|
1407 skipNextFocusIn = False; |
|
1408 } |
|
1409 break; |
|
1410 } |
|
1411 #ifndef NOMODALFIX |
|
1412 if (!awt_isModal() || awt_isWidgetModal(shell)) { |
|
1413 #endif //NOMODALFIX |
|
1414 if (isFocusableWindowByShell(env, shell)) { |
|
1415 jobject currentFocusedWindow = awt_canvas_getFocusedWindowPeer(); |
|
1416 // Check if focus variables already point to this window. If so, |
|
1417 // it means there were transfer to non-focusable window and now we |
|
1418 // are back to origianl focusable window. No need to generate Java events |
|
1419 // in this case. |
|
1420 if (!(*env)->IsSameObject(env, this, currentFocusedWindow)) { |
|
1421 awt_canvas_setFocusedWindowPeer(this); |
|
1422 awt_canvas_setFocusOwnerPeer(this); |
|
1423 |
|
1424 /* |
|
1425 * Fix for 6465038. |
|
1426 * Restore focus on the toplevel widget if it's broken. |
|
1427 */ |
|
1428 Widget widgetToFocus = getFocusWidget(findTopLevelByShell(shell)); |
|
1429 Widget currentOwner = XmGetFocusWidget(shell); |
|
1430 |
|
1431 if (widgetToFocus != currentOwner) { |
|
1432 #ifdef DEBUG_FOCUS |
|
1433 fprintf(stderr, "Wrong Xm focus; resetting Xm focus from %x to toplevel %x...\n", |
|
1434 currentOwner != NULL ? XtWindow(currentOwner) : 0, |
|
1435 widgetToFocus != NULL ? XtWindow(widgetToFocus) : 0); |
|
1436 #endif |
|
1437 if ( !XmProcessTraversal(widgetToFocus, XmTRAVERSE_CURRENT) ) { |
|
1438 XtSetKeyboardFocus(shell, widgetToFocus); |
|
1439 } |
|
1440 #ifdef DEBUG_FOCUS |
|
1441 Widget _w = XmGetFocusWidget(shell); |
|
1442 fprintf(stderr, " ...focus resulted on window %x\n", _w != NULL ? XtWindow(_w) : 0); |
|
1443 #endif |
|
1444 } |
|
1445 |
|
1446 JNU_CallMethodByName(env, NULL, this, "handleWindowFocusIn", "()V"); |
|
1447 if ((*env)->ExceptionCheck(env) == JNI_TRUE) { |
|
1448 (*env)->ExceptionDescribe(env); |
|
1449 (*env)->ExceptionClear(env); |
|
1450 } |
|
1451 } |
|
1452 (*env)->DeleteLocalRef(env, currentFocusedWindow); |
|
1453 } |
|
1454 #ifndef NOMODALFIX |
|
1455 } |
|
1456 #endif //NOMODALFIX |
|
1457 } |
|
1458 raiseInputMethodWindow(wdata); |
|
1459 break; |
|
1460 } /* FocusIn */ |
|
1461 |
|
1462 case VisibilityNotify: { |
|
1463 winAttrObj = (*env)->GetObjectField(env, this, mWindowPeerIDs.winAttr); |
|
1464 (*env)->SetIntField(env, winAttrObj, |
|
1465 mWindowAttributeIDs.visibilityState, |
|
1466 event->xvisibility.state); |
|
1467 if (event->xvisibility.state == VisibilityUnobscured) { |
|
1468 raiseInputMethodWindow(wdata); |
|
1469 } |
|
1470 break; |
|
1471 } /* VisibilityNotify */ |
|
1472 |
|
1473 case MapNotify: { |
|
1474 /* Your body seems to unfade */ |
|
1475 if (wdata->initialFocus == False) { |
|
1476 XtVaSetValues(wdata->winData.shell, XmNinput, True, NULL); |
|
1477 |
|
1478 // We have to to evidently move the window to the front here. |
|
1479 Window shellWindow; |
|
1480 if ((shellWindow = XtWindow(wdata->winData.shell)) != None) { |
|
1481 XRaiseWindow(awt_display, shellWindow); |
|
1482 } |
|
1483 } |
|
1484 if (awt_wm_isStateNetHidden(XtWindow(wdata->winData.shell))) { |
|
1485 focusOnMapNotify = True; |
|
1486 } |
|
1487 /* |
|
1488 * TODO: perhaps we need this putback only for simple Window. |
|
1489 * For Frame/Dialog XmNinput==True would be enough. The native |
|
1490 * system will focus it itself. |
|
1491 */ |
|
1492 if (wdata->isFocusableWindow && focusOnMapNotify) { |
|
1493 XEvent ev; |
|
1494 memset(&ev, 0, sizeof(ev)); |
|
1495 |
|
1496 ev.type = FocusIn; |
|
1497 ev.xany.send_event = True; |
|
1498 ev.xany.display = awt_display; |
|
1499 ev.xfocus.mode = NotifyNormal; |
|
1500 ev.xfocus.detail = NotifyNonlinear; |
|
1501 ev.xfocus.window = XtWindow(wdata->winData.shell); |
|
1502 awt_put_back_event(env, &ev); |
|
1503 } |
|
1504 focusOnMapNotify = False; |
|
1505 |
|
1506 break; |
|
1507 } |
|
1508 |
|
1509 case UnmapNotify: { |
|
1510 /* Gee! All of a sudden, you can't see yourself */ |
|
1511 if (wdata->initialFocus == False) { |
|
1512 XtVaSetValues(wdata->winData.shell, XmNinput, False, NULL); |
|
1513 } |
|
1514 if (awt_wm_isStateNetHidden(XtWindow(wdata->winData.shell))) { |
|
1515 focusOnMapNotify = True; |
|
1516 } |
|
1517 break; |
|
1518 } |
|
1519 |
|
1520 case DestroyNotify: { /* Foul play! ICCCM forbids WM to do this! */ |
|
1521 /* Your window is killed by the WM */ |
|
1522 JNU_CallMethodByName(env, NULL, this, "handleDestroy", "()V"); |
|
1523 if ((*env)->ExceptionOccurred(env)) { |
|
1524 (*env)->ExceptionDescribe(env); |
|
1525 (*env)->ExceptionClear(env); |
|
1526 } |
|
1527 break; |
|
1528 } |
|
1529 |
|
1530 case PropertyNotify: { |
|
1531 jint state, old_state, changed; |
|
1532 |
|
1533 /* |
|
1534 * Let's see if this is a window state protocol message, and |
|
1535 * if it is - decode a new state in terms of java constants. |
|
1536 */ |
|
1537 if (!awt_wm_isStateChange(wdata, (XPropertyEvent *)event, &state)) { |
|
1538 /* Pakka Pakka seems not interested */ |
|
1539 break; |
|
1540 } |
|
1541 |
|
1542 changed = wdata->state ^ state; |
|
1543 if (changed == 0) { |
|
1544 /* You feel dizzy for a moment, but nothing happens... */ |
|
1545 DTRACE_PRINTLN("TL: >>> state unchanged"); |
|
1546 break; |
|
1547 } |
|
1548 |
|
1549 old_state = wdata->state; |
|
1550 wdata->state = state; |
|
1551 |
|
1552 #ifdef DEBUG |
|
1553 DTRACE_PRINT("TL: >>> State Changed:"); |
|
1554 if (changed & java_awt_Frame_ICONIFIED) { |
|
1555 if (state & java_awt_Frame_ICONIFIED) { |
|
1556 DTRACE_PRINT(" ICON"); |
|
1557 } else { |
|
1558 DTRACE_PRINT(" !icon"); |
|
1559 } |
|
1560 } |
|
1561 if (changed & java_awt_Frame_MAXIMIZED_VERT) { |
|
1562 if (state & java_awt_Frame_MAXIMIZED_VERT) { |
|
1563 DTRACE_PRINT(" MAX_VERT"); |
|
1564 } else { |
|
1565 DTRACE_PRINT(" !max_vert"); |
|
1566 } |
|
1567 } |
|
1568 if (changed & java_awt_Frame_MAXIMIZED_HORIZ) { |
|
1569 if (state & java_awt_Frame_MAXIMIZED_HORIZ) { |
|
1570 DTRACE_PRINT(" MAX_HORIZ"); |
|
1571 } else { |
|
1572 DTRACE_PRINT(" !max_horiz"); |
|
1573 } |
|
1574 } |
|
1575 DTRACE_PRINTLN(""); |
|
1576 #endif |
|
1577 |
|
1578 if (changed & java_awt_Frame_ICONIFIED) { |
|
1579 /* Generate window de/iconified event for old clients */ |
|
1580 if (state & java_awt_Frame_ICONIFIED) { |
|
1581 DTRACE_PRINTLN("TL: ... handleIconify"); |
|
1582 JNU_CallMethodByName(env, NULL, |
|
1583 this, "handleIconify", "()V"); |
|
1584 } |
|
1585 else { |
|
1586 DTRACE_PRINTLN("TL: ... handleDeiconify"); |
|
1587 JNU_CallMethodByName(env, NULL, |
|
1588 this, "handleDeiconify", "()V"); |
|
1589 } |
|
1590 if ((*env)->ExceptionOccurred(env)) { |
|
1591 (*env)->ExceptionDescribe(env); |
|
1592 (*env)->ExceptionClear(env); |
|
1593 } |
|
1594 } |
|
1595 |
|
1596 DTRACE_PRINTLN("TL: ... handleStateChange"); |
|
1597 JNU_CallMethodByName(env, NULL, |
|
1598 this, "handleStateChange", "(II)V", |
|
1599 old_state, state); |
|
1600 if ((*env)->ExceptionOccurred(env)) { |
|
1601 (*env)->ExceptionDescribe(env); |
|
1602 (*env)->ExceptionClear(env); |
|
1603 } |
|
1604 break; |
|
1605 } /* PropertyNotify */ |
|
1606 |
|
1607 case ReparentNotify: { |
|
1608 Window root = RootWindowOfScreen(XtScreen(wdata->winData.shell)); |
|
1609 |
|
1610 #ifdef DEBUG |
|
1611 DTRACE_PRINT2("TL: ReparentNotify(0x%x/0x%x) to ", |
|
1612 wdata->winData.shell, XtWindow(wdata->winData.shell)); |
|
1613 if (event->xreparent.parent == root) { |
|
1614 DTRACE_PRINTLN("root"); |
|
1615 } else { |
|
1616 DTRACE_PRINTLN1("window 0x%x", event->xreparent.parent); |
|
1617 } |
|
1618 #endif |
|
1619 |
|
1620 if (wdata->winData.flags & W_IS_EMBEDDED) { |
|
1621 DTRACE_PRINTLN("TL: embedded frame - nothing to do"); |
|
1622 break; |
|
1623 } |
|
1624 |
|
1625 #ifdef __linux__ |
|
1626 if (!wdata->fixInsets) { |
|
1627 DTRACE_PRINTLN("TL: insets already fixed"); |
|
1628 break; |
|
1629 } |
|
1630 else { |
|
1631 wdata->fixInsets = False; |
|
1632 } |
|
1633 #endif |
|
1634 |
|
1635 if ((*env)->EnsureLocalCapacity(env, 1) < 0) |
|
1636 break; |
|
1637 |
|
1638 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
1639 |
|
1640 x = (*env)->GetIntField(env, target, componentIDs.x); |
|
1641 y = (*env)->GetIntField(env, target, componentIDs.y); |
|
1642 width = (*env)->GetIntField(env, target, componentIDs.width); |
|
1643 height = (*env)->GetIntField(env, target, componentIDs.height); |
|
1644 |
|
1645 /* The insets were literally hardcoded in the MWindowPeer. |
|
1646 But they are dependent upon both the window manager (WM) |
|
1647 and the hardware display. So, these are usually wrong. |
|
1648 This leads to problems with shell positioning and size. |
|
1649 Furthermore, there is not a published interface or way |
|
1650 to obtain from any given window manager the dimensions |
|
1651 of its decoration windows (i.e., borders and title bar). |
|
1652 So, given this problem in design, we must workaround. |
|
1653 N.B. (0) This works. But there is one functional caveat: |
|
1654 the frame.insets() function will usually return |
|
1655 the wrong values until AFTER the frame is shown. |
|
1656 It always did this before; it's just that now, |
|
1657 the values will become correct after rendering, |
|
1658 whereas before the values were never corrected. |
|
1659 (I believe this unavoidable given this design.) |
|
1660 (1) Note that we must/have to do this exactly once. |
|
1661 (2) The hardcoded values of ...create() (25,5) |
|
1662 are also utilized here and must be consistent. |
|
1663 This of course could be reworked as desired. |
|
1664 (3) Assume top border (title bar) is one width, |
|
1665 and other three borders are another width. |
|
1666 This, however, could be easily reworked below. */ |
|
1667 |
|
1668 /* |
|
1669 * The above comment is no longer completely true. |
|
1670 * The insets are no longer hardcoded but are retrieved from |
|
1671 * guessInsets(), either from a per-window manager default, |
|
1672 * set in the awt.properties file, or overwritten by the |
|
1673 * actual values determined from a previous frames |
|
1674 * reparenting. |
|
1675 */ |
|
1676 |
|
1677 if (wdata->decor == AWT_NO_DECOR) { |
|
1678 if (!wdata->isResizable && !wdata->isFixedSizeSet) { |
|
1679 reshape(env, this, wdata, x, y, width, height, False); |
|
1680 if (wdata->warningWindow != NULL) |
|
1681 awtJNI_ChangeInsets(env, this, wdata); |
|
1682 } |
|
1683 } |
|
1684 else if (event->xreparent.parent == root) { |
|
1685 wdata->reparented = False; |
|
1686 wdata->configure_seen = False; |
|
1687 |
|
1688 /* |
|
1689 * We can be repareted to root for two reasons: |
|
1690 * . setVisible(false) |
|
1691 * . WM exited |
|
1692 */ |
|
1693 if (wdata->isShowing) { /* WM exited */ |
|
1694 /* Work around 4775545 */ |
|
1695 awt_wm_unshadeKludge(wdata); |
|
1696 } |
|
1697 } |
|
1698 else { /* reparented to WM frame, figure out our insets */ |
|
1699 XWindowAttributes winAttr, actualAttr; |
|
1700 int32_t correctWMTop = -1; |
|
1701 int32_t correctWMLeft = -1; |
|
1702 int32_t correctWMBottom; |
|
1703 int32_t correctWMRight; |
|
1704 int32_t topCorrection; |
|
1705 int32_t leftCorrection; |
|
1706 int32_t bottomCorrection = 0; |
|
1707 int32_t rightCorrection = 0; |
|
1708 int32_t screenX, screenY; |
|
1709 int32_t i; |
|
1710 int32_t actualWidth, actualHeight; |
|
1711 int32_t t, l, b, r; |
|
1712 Window containerWindow; |
|
1713 |
|
1714 /* Dummies for XQueryTree */ |
|
1715 Window ignore_Window, *ignore_WindowPtr; |
|
1716 uint32_t ignore_uint; |
|
1717 |
|
1718 Boolean setXY = True; |
|
1719 XSizeHints* hints = XAllocSizeHints(); |
|
1720 |
|
1721 wdata->reparented = True; |
|
1722 |
|
1723 if (hints != NULL) { |
|
1724 long ignore = 0; |
|
1725 XGetWMNormalHints(awt_display, XtWindow(wdata->winData.shell), |
|
1726 hints, &ignore); |
|
1727 setXY = (hints->flags & (USPosition|PPosition)) != 0; |
|
1728 XFree(hints); |
|
1729 } |
|
1730 |
|
1731 /* |
|
1732 * Unfortunately the concept of "insets" borrowed to AWT |
|
1733 * from Win32 is *absolutely*, *unbelievably* foreign to |
|
1734 * X11. Few WMs provide the size of frame decor |
|
1735 * (i.e. insets) in a property they set on the client |
|
1736 * window, so we check if we can get away with just |
|
1737 * peeking at it. [Future versions of wm-spec might add a |
|
1738 * standardized hint for this]. |
|
1739 * |
|
1740 * Otherwise we do some special casing. Actually the |
|
1741 * fallback code ("default" case) seems to cover most of |
|
1742 * the existing WMs (modulo Reparent/Configure order |
|
1743 * perhaps?). |
|
1744 * |
|
1745 * Fallback code tries to account for the two most common cases: |
|
1746 * |
|
1747 * . single reparenting |
|
1748 * parent window is the WM frame |
|
1749 * [twm, olwm, sawfish] |
|
1750 * |
|
1751 * . double reparenting |
|
1752 * parent is a lining exactly the size of the client |
|
1753 * grandpa is the WM frame |
|
1754 * [mwm, e!, kwin, fvwm2 ... ] |
|
1755 */ |
|
1756 |
|
1757 if (awt_wm_getInsetsFromProp(event->xreparent.window, |
|
1758 &t, &l, &b, &r)) |
|
1759 { |
|
1760 correctWMTop = t; |
|
1761 correctWMLeft = l; |
|
1762 correctWMBottom = b; |
|
1763 correctWMRight = r; |
|
1764 setXY = False; |
|
1765 } |
|
1766 else |
|
1767 switch (awt_wm_getRunningWM()) { |
|
1768 |
|
1769 /* should've been done in awt_wm_getInsetsFromProp */ |
|
1770 case ENLIGHTEN_WM: { |
|
1771 DTRACE_PRINTLN("TL: hmm, E! insets should have been read" |
|
1772 " from _E_FRAME_SIZE"); |
|
1773 /* enlightenment does double reparenting */ |
|
1774 syncTopLevelPos(XtDisplay(wdata->winData.shell), |
|
1775 event->xreparent.parent, &winAttr); |
|
1776 |
|
1777 XQueryTree(XtDisplay(wdata->winData.shell), |
|
1778 event->xreparent.parent, |
|
1779 &ignore_Window, |
|
1780 &containerWindow, /* actual WM frame */ |
|
1781 &ignore_WindowPtr, |
|
1782 &ignore_uint); |
|
1783 if (ignore_WindowPtr) |
|
1784 XFree(ignore_WindowPtr); |
|
1785 |
|
1786 correctWMLeft = winAttr.x; |
|
1787 correctWMTop = winAttr.y; |
|
1788 |
|
1789 /* |
|
1790 * Now get the actual dimensions of the parent window |
|
1791 * resolve the difference. We can't rely on the left |
|
1792 * to be equal to right or bottom... Enlightment |
|
1793 * breaks that assumption. |
|
1794 */ |
|
1795 XGetWindowAttributes(XtDisplay(wdata->winData.shell), |
|
1796 containerWindow, &actualAttr); |
|
1797 correctWMRight = actualAttr.width |
|
1798 - (winAttr.width + correctWMLeft); |
|
1799 correctWMBottom = actualAttr.height |
|
1800 - (winAttr.height + correctWMTop) ; |
|
1801 break; |
|
1802 } |
|
1803 |
|
1804 case ICE_WM: |
|
1805 case KDE2_WM: /* should've been done in awt_wm_getInsetsFromProp */ |
|
1806 case CDE_WM: |
|
1807 case MOTIF_WM: { |
|
1808 /* these are double reparenting too */ |
|
1809 syncTopLevelPos(XtDisplay(wdata->winData.shell), |
|
1810 event->xreparent.parent, &winAttr); |
|
1811 |
|
1812 correctWMTop = winAttr.y; |
|
1813 correctWMLeft = winAttr.x; |
|
1814 correctWMRight = correctWMLeft; |
|
1815 correctWMBottom = correctWMLeft; |
|
1816 |
|
1817 XTranslateCoordinates(awt_display, event->xreparent.window, |
|
1818 root, 0,0, &screenX, &screenY, |
|
1819 &containerWindow); |
|
1820 |
|
1821 if ((screenX != x + wdata->leftGuess) |
|
1822 || (screenY != y + wdata->topGuess)) |
|
1823 { |
|
1824 /* |
|
1825 * looks like the window manager has placed us somewhere |
|
1826 * other than where we asked for, lets respect the window |
|
1827 * and go where he put us, not where we tried to put us |
|
1828 */ |
|
1829 x = screenX - correctWMLeft; |
|
1830 y = screenY - correctWMTop; |
|
1831 } |
|
1832 break; |
|
1833 } |
|
1834 |
|
1835 case SAWFISH_WM: |
|
1836 case OPENLOOK_WM: { |
|
1837 /* single reparenting */ |
|
1838 syncTopLevelPos(XtDisplay(wdata->winData.shell), |
|
1839 event->xreparent.window, &winAttr); |
|
1840 |
|
1841 correctWMTop = winAttr.y; |
|
1842 correctWMLeft = winAttr.x; |
|
1843 correctWMRight = correctWMLeft; |
|
1844 correctWMBottom = correctWMLeft; |
|
1845 break; |
|
1846 } |
|
1847 |
|
1848 case OTHER_WM: |
|
1849 default: { /* this is very similar to the E! case above */ |
|
1850 Display *dpy = event->xreparent.display; |
|
1851 Window w = event->xreparent.window; |
|
1852 Window parent = event->xreparent.parent; |
|
1853 XWindowAttributes wattr, pattr; |
|
1854 |
|
1855 XGetWindowAttributes(dpy, w, &wattr); |
|
1856 XGetWindowAttributes(dpy, parent, &pattr); |
|
1857 |
|
1858 DTRACE_PRINTLN5("TL: window attr +%d+%d+%dx%d (%d)", |
|
1859 wattr.x, wattr.y, wattr.width, wattr.height, |
|
1860 wattr.border_width); |
|
1861 DTRACE_PRINTLN5("TL: parent attr +%d+%d+%dx%d (%d)", |
|
1862 pattr.x, pattr.y, pattr.width, pattr.height, |
|
1863 pattr.border_width); |
|
1864 |
|
1865 /* |
|
1866 * Check for double-reparenting WM. |
|
1867 * |
|
1868 * If the parent is exactly the same size as the |
|
1869 * top-level assume taht it's the "lining" window and |
|
1870 * that the grandparent is the actual frame (NB: we |
|
1871 * have already handled undecorated windows). |
|
1872 * |
|
1873 * XXX: what about timing issues that syncTopLevelPos |
|
1874 * is supposed to work around? |
|
1875 */ |
|
1876 if (wattr.x == 0 && wattr.y == 0 |
|
1877 && wattr.width + 2*wattr.border_width == pattr.width |
|
1878 && wattr.height + 2*wattr.border_width == pattr.height) |
|
1879 { |
|
1880 Window ignore_root, grandparent, *children; |
|
1881 unsigned int ignore_nchildren; |
|
1882 |
|
1883 DTRACE_PRINTLN("TL: double reparenting WM detected"); |
|
1884 XQueryTree(dpy, parent, |
|
1885 &ignore_root, |
|
1886 &grandparent, |
|
1887 &children, |
|
1888 &ignore_nchildren); |
|
1889 if (children) |
|
1890 XFree(children); |
|
1891 |
|
1892 /* take lining window into account */ |
|
1893 wattr.x = pattr.x; |
|
1894 wattr.y = pattr.y; |
|
1895 wattr.border_width += pattr.border_width; |
|
1896 |
|
1897 parent = grandparent; |
|
1898 XGetWindowAttributes(dpy, parent, &pattr); |
|
1899 DTRACE_PRINTLN5("TL: window attr +%d+%d+%dx%d (%d)", |
|
1900 wattr.x, wattr.y, |
|
1901 wattr.width, wattr.height, |
|
1902 wattr.border_width); |
|
1903 DTRACE_PRINTLN5("TL: parent attr +%d+%d+%dx%d (%d)", |
|
1904 pattr.x, pattr.y, |
|
1905 pattr.width, pattr.height, |
|
1906 pattr.border_width); |
|
1907 } |
|
1908 |
|
1909 /* |
|
1910 * XXX: To be absolutely correct, we'd need to take |
|
1911 * parent's border-width into account too, but the |
|
1912 * rest of the code is happily unaware about border |
|
1913 * widths and inner/outer distinction, so for the time |
|
1914 * being, just ignore it. |
|
1915 */ |
|
1916 correctWMTop = wattr.y + wattr.border_width; |
|
1917 correctWMLeft = wattr.x + wattr.border_width; |
|
1918 correctWMBottom = pattr.height |
|
1919 - (wattr.y + wattr.height + 2*wattr.border_width); |
|
1920 correctWMRight = pattr.width |
|
1921 - (wattr.x + wattr.width + 2*wattr.border_width); |
|
1922 DTRACE_PRINTLN4("TL: insets = top %d, left %d, bottom %d, right %d", |
|
1923 correctWMTop, correctWMLeft, |
|
1924 correctWMBottom, correctWMRight); |
|
1925 break; |
|
1926 } /* default */ |
|
1927 |
|
1928 } /* switch (runningWM) */ |
|
1929 |
|
1930 |
|
1931 /* |
|
1932 * Ok, now see if we need adjust window size because |
|
1933 * initial insets were wrong (most likely they were). |
|
1934 */ |
|
1935 topCorrection = correctWMTop - wdata->topGuess; |
|
1936 leftCorrection = correctWMLeft - wdata->leftGuess; |
|
1937 bottomCorrection = correctWMBottom - wdata->bottomGuess; |
|
1938 rightCorrection = correctWMRight - wdata->rightGuess; |
|
1939 |
|
1940 DTRACE_PRINTLN3("TL: top: computed=%d, guess=%d, correction=%d", |
|
1941 correctWMTop, wdata->topGuess, topCorrection); |
|
1942 DTRACE_PRINTLN3("TL: left: computed=%d, guess=%d, correction=%d", |
|
1943 correctWMLeft, wdata->leftGuess, leftCorrection); |
|
1944 DTRACE_PRINTLN3("TL: bottom: computed=%d, guess=%d, correction=%d", |
|
1945 correctWMBottom, wdata->bottomGuess, bottomCorrection); |
|
1946 DTRACE_PRINTLN3("TL: right: computed=%d, guess=%d, correction=%d", |
|
1947 correctWMRight, wdata->rightGuess, rightCorrection); |
|
1948 |
|
1949 if (topCorrection != 0 || leftCorrection != 0 |
|
1950 || bottomCorrection != 0 || rightCorrection != 0) |
|
1951 { |
|
1952 jboolean isPacked; |
|
1953 |
|
1954 DTRACE_PRINTLN("TL: insets need correction"); |
|
1955 wdata->need_reshape = True; |
|
1956 |
|
1957 globalTopGuess = correctWMTop; |
|
1958 globalLeftGuess = correctWMLeft; |
|
1959 globalBottomGuess = correctWMBottom; |
|
1960 globalRightGuess = correctWMRight; |
|
1961 |
|
1962 /* guesses are for WM decor *only* */ |
|
1963 wdata->topGuess = correctWMTop; |
|
1964 wdata->leftGuess = correctWMLeft; |
|
1965 wdata->bottomGuess = correctWMBottom; |
|
1966 wdata->rightGuess = correctWMRight; |
|
1967 |
|
1968 /* |
|
1969 * Actual insets account for menubar/warning label, |
|
1970 * so we can't assign directly but must adjust them. |
|
1971 */ |
|
1972 wdata->top += topCorrection; |
|
1973 wdata->left += leftCorrection; |
|
1974 wdata->bottom += bottomCorrection; |
|
1975 wdata->right += rightCorrection; |
|
1976 |
|
1977 awtJNI_ChangeInsets(env, this, wdata); |
|
1978 |
|
1979 /* |
|
1980 * If this window has been sized by a pack() we need |
|
1981 * to keep the interior geometry intact. Since pack() |
|
1982 * computed width and height with wrong insets, we |
|
1983 * must adjust the target dimensions appropriately. |
|
1984 */ |
|
1985 isPacked = (*env)->GetBooleanField(env, target, |
|
1986 componentIDs.isPacked); |
|
1987 if (isPacked) { |
|
1988 int32_t correctTargetW; |
|
1989 int32_t correctTargetH; |
|
1990 |
|
1991 DTRACE_PRINTLN("TL: window is packed, " |
|
1992 "adjusting size to preserve layout"); |
|
1993 |
|
1994 correctTargetW = width + (leftCorrection + rightCorrection); |
|
1995 correctTargetH = height +(topCorrection + bottomCorrection); |
|
1996 |
|
1997 (*env)->SetIntField(env, target, componentIDs.width, |
|
1998 (jint) correctTargetW); |
|
1999 (*env)->SetIntField(env, target, componentIDs.height, |
|
2000 (jint) correctTargetH); |
|
2001 /* |
|
2002 ** Normally you only reconfigure the outerCanvas due to |
|
2003 ** handling the ReconfigureNotify on the innerCanvas. |
|
2004 ** However, in this case the innerCanvas may not have |
|
2005 ** changed, but outterCanvas may still need to, since the |
|
2006 ** insets have changed. |
|
2007 */ |
|
2008 reshape(env, this, wdata, x, y, |
|
2009 correctTargetW, correctTargetH, setXY); |
|
2010 reconfigureOuterCanvas(env, target, this, wdata); |
|
2011 } else { |
|
2012 reshape(env, this, wdata, x, y, width, height, setXY); |
|
2013 JNU_CallMethodByName(env, NULL, this, |
|
2014 "handleResize", "(II)V", width, height); |
|
2015 } |
|
2016 } |
|
2017 /* NEW for dialog */ /* XXX: what this comment is supposed to mean? */ |
|
2018 else { |
|
2019 wdata->need_reshape = False; |
|
2020 /* fix for 4976337 - son@sparc.spb.su */ |
|
2021 /* we should find better fix later if needed */ |
|
2022 if (wdata->isResizable || !wdata->isFixedSizeSet) { |
|
2023 reshape(env, this, wdata, x, y, width, height, setXY); |
|
2024 } |
|
2025 } |
|
2026 } |
|
2027 (*env)->DeleteLocalRef(env, target); |
|
2028 break; |
|
2029 } /* ReparentNotify */ |
|
2030 |
|
2031 case ConfigureNotify: { |
|
2032 DTRACE_PRINTLN2("TL: ConfigureNotify(0x%x/0x%x)", |
|
2033 wdata->winData.shell, XtWindow(wdata->winData.shell)); |
|
2034 |
|
2035 /* |
|
2036 * Some window managers configure before we are reparented and |
|
2037 * the send event flag is set! ugh... (Enlighetenment for one, |
|
2038 * possibly MWM as well). If we haven't been reparented yet |
|
2039 * this is just the WM shuffling us into position. Ignore |
|
2040 * it!!!! or we wind up in a bogus location. |
|
2041 */ |
|
2042 runningWM = awt_wm_getRunningWM(); |
|
2043 if (!wdata->reparented && wdata->isShowing && |
|
2044 runningWM != NO_WM && wdata->decor != AWT_NO_DECOR) { |
|
2045 break; |
|
2046 } |
|
2047 |
|
2048 /* |
|
2049 * Notice that we have seen a ConfigureNotify after being |
|
2050 * reparented. We should really check for it being a |
|
2051 * synthetic event, but metacity doesn't send one. |
|
2052 */ |
|
2053 if (wdata->reparented) |
|
2054 wdata->configure_seen = 1; |
|
2055 |
|
2056 if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
|
2057 break; |
|
2058 } |
|
2059 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
2060 |
|
2061 /* |
|
2062 * We can detect the difference between a move and a resize by |
|
2063 * checking the send_event flag on the event; if it's true, |
|
2064 * then it's indeed a move, if it's false, then this is a |
|
2065 * resize and we do not want to process it as a "move" (for |
|
2066 * resizes the x,y values are misleadingly set to 0,0 and so |
|
2067 * just checking for an x,y delta won't work). |
|
2068 */ |
|
2069 |
|
2070 getTargetX = (*env)->GetIntField(env, target, componentIDs.x); |
|
2071 getTargetY = (*env)->GetIntField(env, target, componentIDs.y); |
|
2072 |
|
2073 DTRACE_PRINTLN2("TL: target thinks (%d, %d)", |
|
2074 getTargetX, getTargetY); |
|
2075 DTRACE_PRINTLN3("TL: event is (%d, %d)%s", |
|
2076 event->xconfigure.x, event->xconfigure.y, |
|
2077 (event->xconfigure.send_event ? " synthetic" : "")); |
|
2078 |
|
2079 /* |
|
2080 * N.B. The wdata top offset is the offset from the outside of |
|
2081 * the entire (bordered window) to the inner/parent drawing |
|
2082 * area (canvas), NOT to the shell. Thus, if a menubar is |
|
2083 * present and/or a warning window at the top (not NETSCAPE), |
|
2084 * the top offset will also include space for these. In order |
|
2085 * to position the abstract java window relative to the shell, |
|
2086 * we must add back in the appropriate space for these when we |
|
2087 * subtract off the wdata top field. |
|
2088 */ |
|
2089 #ifdef NETSCAPE |
|
2090 wwHeight = 0; |
|
2091 #else /* NETSCAPE */ |
|
2092 if (wdata->warningWindow != NULL) |
|
2093 wwHeight = wdata->wwHeight; |
|
2094 else |
|
2095 wwHeight = 0; |
|
2096 #endif /* NETSCAPE */ |
|
2097 topAdjust = wdata->mbHeight + wwHeight; |
|
2098 |
|
2099 /* |
|
2100 * Coordinates in Component.setLocation() are treated as the |
|
2101 * upper-left corner of the outer shell. The x and y in the |
|
2102 * ConfigureNotify event, however, are the upper-left corner |
|
2103 * of the inset CLIENT window. Therefore, the coordinates |
|
2104 * from the event are massaged using the inset values in order |
|
2105 * to determine if the top-level shell has moved. In the |
|
2106 * event of a user- generated move event (i.e. dragging the |
|
2107 * window itself), these coordinates are written back into the |
|
2108 * Window object. |
|
2109 * |
|
2110 * Neat X/CDE/Native bug: |
|
2111 * If an attempt is made to move the shell in the y direction |
|
2112 * by an amount equal to the top inset, the Window isn't |
|
2113 * moved. This can be seen here by examining event->xconfigure.y |
|
2114 * before and after such a request is made: the value remains |
|
2115 * unchanged. This wrecks a little havoc here, as the x and y |
|
2116 * in the Component have already been set to the new location |
|
2117 * (in Component.reshape()), but the Window doesn't end up in |
|
2118 * the new location. What's more, if a second request is |
|
2119 * made, the window will be relocated by TWICE the requested |
|
2120 * amount, sort of "catching up" it would seem. |
|
2121 * |
|
2122 * For a test case of this, see bug 4234645. |
|
2123 */ |
|
2124 setTargetX = event->xconfigure.x - wdata->left; |
|
2125 setTargetY = event->xconfigure.y - wdata->top + topAdjust; |
|
2126 |
|
2127 width = (*env)->GetIntField(env, target, componentIDs.width); |
|
2128 height = (*env)->GetIntField(env, target, componentIDs.height); |
|
2129 checkNewXineramaScreen(env, this, wdata, setTargetX, setTargetY, |
|
2130 width, height); |
|
2131 |
|
2132 if ((getTargetX != setTargetX || getTargetY != setTargetY) |
|
2133 && (event->xconfigure.send_event || runningWM == NO_WM)) |
|
2134 { |
|
2135 (*env)->SetIntField(env, target, componentIDs.x, (jint)setTargetX); |
|
2136 (*env)->SetIntField(env, target, componentIDs.y, (jint)setTargetY); |
|
2137 #ifdef _pauly_debug |
|
2138 fprintf(stdout, " ++ shell move. Xevent x,y: %d, %d.\n", |
|
2139 event->xconfigure.x, event->xconfigure.y); |
|
2140 fprintf(stdout, " shell move. left: %d, top: %d, but offset: %d\n", wdata->left, wdata->top, topAdjust); |
|
2141 fprintf(stdout," shell move. target x: %d, target y: %d\n", setTargetX, setTargetY); |
|
2142 fprintf(stdout," shell move. ww height: %d\n", wwHeight); |
|
2143 fflush(stdout); |
|
2144 #endif /* _pauly_debug */ |
|
2145 |
|
2146 DTRACE_PRINTLN2("TL: handleMoved(%d, %d)", |
|
2147 setTargetX, setTargetY); |
|
2148 JNU_CallMethodByName(env, NULL, |
|
2149 this, "handleMoved", "(II)V", |
|
2150 setTargetX, setTargetY); |
|
2151 if ((*env)->ExceptionOccurred(env)) { |
|
2152 (*env)->ExceptionDescribe(env); |
|
2153 (*env)->ExceptionClear(env); |
|
2154 } |
|
2155 } |
|
2156 else if (event->xconfigure.send_event == False) { |
|
2157 #ifdef _pauly_debug |
|
2158 fprintf(stdout, |
|
2159 " ++ shell resize. Xevent x,y,w,h: %d, %d, %d, %d.\n", |
|
2160 event->xconfigure.x, event->xconfigure.y, |
|
2161 event->xconfigure.width, event->xconfigure.height); |
|
2162 fflush(stdout); |
|
2163 #endif /* _pauly_debug */ |
|
2164 |
|
2165 wdata->shellResized = True; |
|
2166 } |
|
2167 |
|
2168 |
|
2169 (*env)->DeleteLocalRef(env, target); |
|
2170 raiseInputMethodWindow(wdata); |
|
2171 #ifdef __linux__ |
|
2172 adjustStatusWindow(wdata->winData.shell); |
|
2173 #endif |
|
2174 break; |
|
2175 } /* ConfigureNotify */ |
|
2176 |
|
2177 default: |
|
2178 break; |
|
2179 } |
|
2180 } |
|
2181 |
|
2182 |
|
2183 static void |
|
2184 Frame_quit(Widget w, |
|
2185 XtPointer client_data, |
|
2186 XtPointer call_data) |
|
2187 { |
|
2188 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
2189 |
|
2190 JNU_CallMethodByName(env, NULL, (jobject) client_data, "handleQuit", "()V"); |
|
2191 if ((*env)->ExceptionOccurred(env)) { |
|
2192 (*env)->ExceptionDescribe(env); |
|
2193 (*env)->ExceptionClear(env); |
|
2194 } |
|
2195 } |
|
2196 |
|
2197 |
|
2198 static void |
|
2199 setDeleteCallback(jobject this, struct FrameData *wdata) |
|
2200 { |
|
2201 Atom xa_WM_DELETE_WINDOW; |
|
2202 Atom xa_WM_TAKE_FOCUS; |
|
2203 Atom xa_WM_PROTOCOLS; |
|
2204 |
|
2205 XtVaSetValues(wdata->winData.shell, |
|
2206 XmNdeleteResponse, XmDO_NOTHING, |
|
2207 NULL); |
|
2208 xa_WM_DELETE_WINDOW = XmInternAtom(XtDisplay(wdata->winData.shell), |
|
2209 "WM_DELETE_WINDOW", False); |
|
2210 xa_WM_TAKE_FOCUS = XmInternAtom(XtDisplay(wdata->winData.shell), |
|
2211 "WM_TAKE_FOCUS", False); |
|
2212 xa_WM_PROTOCOLS = XmInternAtom(XtDisplay(wdata->winData.shell), |
|
2213 "WM_PROTOCOLS", False); |
|
2214 |
|
2215 XmAddProtocolCallback(wdata->winData.shell, |
|
2216 xa_WM_PROTOCOLS, |
|
2217 xa_WM_DELETE_WINDOW, |
|
2218 Frame_quit, (XtPointer) this); |
|
2219 } |
|
2220 |
|
2221 |
|
2222 extern AwtGraphicsConfigDataPtr |
|
2223 copyGraphicsConfigToPeer(JNIEnv *env, jobject this); |
|
2224 |
|
2225 extern AwtGraphicsConfigDataPtr |
|
2226 getGraphicsConfigFromComponentPeer(JNIEnv *env, jobject this); |
|
2227 |
|
2228 // Returns true if this shell has some transient shell chidlren |
|
2229 // which are either Dialogs or Windows. |
|
2230 // Returns false otherwise. |
|
2231 Boolean hasTransientChildren(Widget shell) { |
|
2232 int childIndex; |
|
2233 |
|
2234 // Enumerate through the popups |
|
2235 for (childIndex = 0; childIndex < shell->core.num_popups; childIndex++) { |
|
2236 Widget childShell = shell->core.popup_list[childIndex]; |
|
2237 // Find all transient shell which are either Dialog or Window |
|
2238 if (XtIsTransientShell(childShell)) { |
|
2239 Widget toplevel = findTopLevelByShell(childShell); |
|
2240 if (toplevel != NULL) { |
|
2241 // It is Dialog or Window - return true. |
|
2242 return True; |
|
2243 } |
|
2244 } |
|
2245 } |
|
2246 return False; |
|
2247 } |
|
2248 |
|
2249 extern Widget grabbed_widget; |
|
2250 /** |
|
2251 * Disposes top-level component and its widgets |
|
2252 */ |
|
2253 static |
|
2254 void disposeTopLevel(JNIEnv * env, jobject this) { |
|
2255 |
|
2256 struct FrameData *wdata; |
|
2257 Widget parentShell; |
|
2258 |
|
2259 wdata = (struct FrameData *) |
|
2260 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
2261 |
|
2262 if (wdata == NULL || wdata->mainWindow == NULL |
|
2263 || wdata->winData.shell == NULL) |
|
2264 { |
|
2265 /* do nothing */ |
|
2266 return; |
|
2267 } |
|
2268 |
|
2269 // Save parent shell for later disposal. |
|
2270 parentShell = XtParent(wdata->winData.shell); |
|
2271 |
|
2272 removeTopLevel(wdata); |
|
2273 if (wdata->isInputMethodWindow) { |
|
2274 removeInputMethodWindow(wdata); |
|
2275 } |
|
2276 |
|
2277 XtRemoveEventHandler(wdata->focusProxy, FocusChangeMask, |
|
2278 False, shellEH, this); |
|
2279 XtUnmanageChild(wdata->focusProxy); |
|
2280 awt_util_consumeAllXEvents(wdata->focusProxy); |
|
2281 awt_util_cleanupBeforeDestroyWidget(wdata->focusProxy); |
|
2282 XtDestroyWidget(wdata->focusProxy); |
|
2283 |
|
2284 XtUnmanageChild(wdata->winData.comp.widget); |
|
2285 awt_delWidget(wdata->winData.comp.widget); |
|
2286 awt_util_consumeAllXEvents(wdata->winData.comp.widget); |
|
2287 awt_util_cleanupBeforeDestroyWidget(wdata->winData.comp.widget); |
|
2288 XtDestroyWidget(wdata->winData.comp.widget); |
|
2289 |
|
2290 XtUnmanageChild(wdata->mainWindow); |
|
2291 awt_util_consumeAllXEvents(wdata->mainWindow); |
|
2292 awt_util_consumeAllXEvents(wdata->winData.shell); |
|
2293 XtDestroyWidget(wdata->mainWindow); |
|
2294 XtDestroyWidget(wdata->winData.shell); |
|
2295 if (wdata->iconPixmap) { |
|
2296 XFreePixmap(awt_display, wdata->iconPixmap); |
|
2297 } |
|
2298 |
|
2299 if (grabbed_widget == wdata->winData.shell) { |
|
2300 XUngrabPointer(awt_display, CurrentTime); |
|
2301 XUngrabKeyboard(awt_display, CurrentTime); |
|
2302 grabbed_widget = NULL; |
|
2303 } |
|
2304 |
|
2305 free((void *) wdata); |
|
2306 |
|
2307 (*env)->SetLongField(env, this, mComponentPeerIDs.pData, 0); |
|
2308 awtJNI_DeleteGlobalRef(env, this); |
|
2309 |
|
2310 // Check if parent shell was scheduled for disposal. |
|
2311 // If it doesn't have window then we have to dispose it |
|
2312 // by ourselves right now. |
|
2313 // We can dispose shell only if it doesn't have "transient" children. |
|
2314 { |
|
2315 struct FrameData *pdata; |
|
2316 struct WidgetInfo* winfo; |
|
2317 Widget toplevel = findTopLevelByShell(parentShell); |
|
2318 if (toplevel == NULL) { |
|
2319 // Has already been deleted or it is top shell |
|
2320 return; |
|
2321 } |
|
2322 winfo = findWidgetInfo(toplevel); |
|
2323 DASSERT(winfo != NULL); |
|
2324 if (winfo == NULL) { |
|
2325 // Huh - has already been deleted? |
|
2326 return; |
|
2327 } |
|
2328 pdata = (struct FrameData *) |
|
2329 JNU_GetLongFieldAsPtr(env, winfo->peer, mComponentPeerIDs.pData); |
|
2330 DASSERT(pdata != NULL); |
|
2331 if (pdata == NULL) { |
|
2332 // Huh - has already been deleted? |
|
2333 return; |
|
2334 } |
|
2335 // 1) scheduled 2) no children 3) no window |
|
2336 if (pdata->isDisposeScheduled |
|
2337 && !hasTransientChildren(parentShell) |
|
2338 && XtWindow(parentShell) == None) |
|
2339 { |
|
2340 disposeTopLevel(env, winfo->peer); |
|
2341 } |
|
2342 } |
|
2343 } |
|
2344 |
|
2345 |
|
2346 /** |
|
2347 * Property change listener. Listens to _XA_JAVA_DISPOSE_PROPERTY_ATOM, |
|
2348 * disposes the top-level when this property has been changed. |
|
2349 */ |
|
2350 static void |
|
2351 shellDisposeNotifyHandler(Widget w, XtPointer client_data, |
|
2352 XEvent* event, Boolean* continue_to_dispatch) { |
|
2353 struct FrameData *wdata; |
|
2354 |
|
2355 *continue_to_dispatch = True; |
|
2356 |
|
2357 if (event->type == PropertyNotify && |
|
2358 event->xproperty.atom == _XA_JAVA_DISPOSE_PROPERTY_ATOM) |
|
2359 { |
|
2360 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
2361 |
|
2362 wdata = (struct FrameData *) |
|
2363 JNU_GetLongFieldAsPtr(env, (jobject)client_data, |
|
2364 mComponentPeerIDs.pData); |
|
2365 if (wdata != NULL && wdata->isDisposeScheduled) { |
|
2366 disposeTopLevel(env, (jobject)client_data); |
|
2367 |
|
2368 // We've disposed top-level, no more actions on it |
|
2369 *continue_to_dispatch = False; |
|
2370 } |
|
2371 } |
|
2372 } |
|
2373 |
|
2374 /** |
|
2375 * Schedules top-level for later dispose - when all events |
|
2376 * on it will be processed. |
|
2377 */ |
|
2378 static |
|
2379 void scheduleDispose(JNIEnv * env, jobject peer) { |
|
2380 |
|
2381 struct FrameData *wdata; |
|
2382 |
|
2383 wdata = (struct FrameData *) |
|
2384 JNU_GetLongFieldAsPtr(env, peer, mComponentPeerIDs.pData); |
|
2385 |
|
2386 if (wdata->isDisposeScheduled) { |
|
2387 return; |
|
2388 } |
|
2389 |
|
2390 wdata->isDisposeScheduled = True; |
|
2391 if (XtWindow(wdata->winData.shell) != None) { |
|
2392 XChangeProperty(awt_display, XtWindow(wdata->winData.shell), |
|
2393 _XA_JAVA_DISPOSE_PROPERTY_ATOM, XA_ATOM, 32, PropModeAppend, |
|
2394 (unsigned char *)"", 0); |
|
2395 XFlush(awt_display); |
|
2396 XSync(awt_display, False); |
|
2397 } else { |
|
2398 // If this top-level has children which are still visible then |
|
2399 // their disposal could have been scheduled. We shouldn't allow this widget |
|
2400 // to destroy its children top-levels. For this purpose we postpone the disposal |
|
2401 // of this toplevel until after all its children are disposed. |
|
2402 if (!hasTransientChildren(wdata->winData.shell)) { |
|
2403 disposeTopLevel(env, peer); |
|
2404 } |
|
2405 } |
|
2406 } |
|
2407 |
|
2408 |
|
2409 /* sun_awt_motif_MWindowPeer_pCreate() is native (X/Motif) create routine */ |
|
2410 static char* focusProxyName = "FocusProxy"; |
|
2411 |
|
2412 Widget createFocusProxy(jobject globalRef, Widget parent) { |
|
2413 Widget proxy; |
|
2414 #define MAX_ARGC 20 |
|
2415 Arg args[MAX_ARGC]; |
|
2416 int32_t argc; |
|
2417 |
|
2418 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
2419 |
|
2420 if (parent == NULL) { |
|
2421 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
2422 return NULL; |
|
2423 } |
|
2424 argc = 0; |
|
2425 XtSetArg(args[argc], XmNwidth, 1); |
|
2426 argc++; |
|
2427 XtSetArg(args[argc], XmNheight, 1); |
|
2428 argc++; |
|
2429 XtSetArg(args[argc], XmNx, -1); |
|
2430 argc++; |
|
2431 XtSetArg(args[argc], XmNy, -1); |
|
2432 argc++; |
|
2433 XtSetArg(args[argc], XmNmarginWidth, 0); |
|
2434 argc++; |
|
2435 XtSetArg(args[argc], XmNmarginHeight, 0); |
|
2436 argc++; |
|
2437 XtSetArg(args[argc], XmNspacing, 0); |
|
2438 argc++; |
|
2439 XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE); |
|
2440 argc++; |
|
2441 |
|
2442 DASSERT(!(argc > MAX_ARGC)); |
|
2443 proxy = XmCreateDrawingArea(parent, focusProxyName, args, argc); |
|
2444 XtAddEventHandler(proxy, |
|
2445 FocusChangeMask, |
|
2446 False, shellEH, globalRef); |
|
2447 XtManageChild(proxy); |
|
2448 #undef MAX_ARGC |
|
2449 return proxy; |
|
2450 } |
|
2451 |
|
2452 /* |
|
2453 * Class: sun_awt_motif_MWindowPeer |
|
2454 * Method: pCreate |
|
2455 * Signature: (Lsun/awt/motif/MComponentPeer;Ljava/lang/String;)V |
|
2456 */ |
|
2457 JNIEXPORT void JNICALL |
|
2458 Java_sun_awt_motif_MWindowPeer_pCreate(JNIEnv *env, jobject this, |
|
2459 jobject parent, jstring target_class_name, jboolean isFocusableWindow) |
|
2460 { |
|
2461 #define MAX_ARGC 50 |
|
2462 Arg args[MAX_ARGC]; |
|
2463 int32_t argc; |
|
2464 struct FrameData *wdata; |
|
2465 struct FrameData *pdata = NULL; |
|
2466 char *shell_name = NULL; |
|
2467 WidgetClass shell_class; |
|
2468 Widget parent_widget; |
|
2469 jobject target; |
|
2470 jobject insets; |
|
2471 jobject winAttr; |
|
2472 jstring warningString; |
|
2473 jboolean resizable; |
|
2474 jboolean isModal; |
|
2475 jboolean initialFocus; |
|
2476 jint state; |
|
2477 jclass clazz; |
|
2478 jobject globalRef = awtJNI_CreateAndSetGlobalRef(env, this); |
|
2479 |
|
2480 uint32_t runningWM; /* the running Window Manager */ |
|
2481 Widget innerCanvasW; /* form's child, parent of the |
|
2482 outer canvas (drawing area) */ |
|
2483 Position x,y; |
|
2484 Dimension w,h; |
|
2485 AwtGraphicsConfigDataPtr adata; |
|
2486 AwtGraphicsConfigDataPtr defConfig; |
|
2487 jobject gd = NULL; |
|
2488 jobject gc = NULL; |
|
2489 char *cname = NULL; |
|
2490 jstring jname; |
|
2491 |
|
2492 AWT_LOCK(); |
|
2493 |
|
2494 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
2495 |
|
2496 if (JNU_IsNull(env, target)) { |
|
2497 JNU_ThrowNullPointerException(env, "null target"); |
|
2498 AWT_UNLOCK(); |
|
2499 return; |
|
2500 } |
|
2501 |
|
2502 wdata = ZALLOC(FrameData); |
|
2503 JNU_SetLongFieldFromPtr(env, this, mComponentPeerIDs.pData, wdata); |
|
2504 if (wdata == NULL) { |
|
2505 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
|
2506 AWT_UNLOCK(); |
|
2507 return; |
|
2508 } |
|
2509 |
|
2510 adata = copyGraphicsConfigToPeer(env, this); |
|
2511 defConfig = getDefaultConfig(adata->awt_visInfo.screen); |
|
2512 |
|
2513 |
|
2514 /* Retrieve the specified characteristics for this window */ |
|
2515 winAttr = (*env)->GetObjectField(env, this, mWindowPeerIDs.winAttr); |
|
2516 resizable = (*env)->GetBooleanField( env, |
|
2517 winAttr, |
|
2518 mWindowAttributeIDs.isResizable); |
|
2519 state = (*env)->GetIntField( env, |
|
2520 winAttr, |
|
2521 mWindowAttributeIDs.initialState); |
|
2522 initialFocus = (*env)->GetBooleanField( env, |
|
2523 winAttr, |
|
2524 mWindowAttributeIDs.initialFocus); |
|
2525 |
|
2526 /* As of today decor is either on or off... except the InputMethodWindow */ |
|
2527 if ((*env)->GetBooleanField(env, winAttr, mWindowAttributeIDs.nativeDecor)) { |
|
2528 wdata->decor = (*env)->GetIntField(env, winAttr, mWindowAttributeIDs.decorations); |
|
2529 } else { |
|
2530 wdata->decor = AWT_NO_DECOR; |
|
2531 } |
|
2532 |
|
2533 insets = (*env)->GetObjectField(env, this, mWindowPeerIDs.insets); |
|
2534 |
|
2535 /* The insets will be corrected upon the reparent |
|
2536 event in shellEH(). For now, use bogus values. */ |
|
2537 wdata->top = (*env)->GetIntField(env, insets, insetsIDs.top); |
|
2538 wdata->left = (*env)->GetIntField(env, insets, insetsIDs.left); |
|
2539 wdata->bottom = (*env)->GetIntField(env, insets, insetsIDs.bottom); |
|
2540 wdata->right = (*env)->GetIntField(env, insets, insetsIDs.right); |
|
2541 awt_Frame_guessInsets(wdata); |
|
2542 awtJNI_ChangeInsets(env, this, wdata); |
|
2543 wdata->reparented = False; |
|
2544 wdata->configure_seen = False; |
|
2545 x = (*env)->GetIntField(env, target, componentIDs.x) + wdata->left; |
|
2546 y = (*env)->GetIntField(env, target, componentIDs.y) + wdata->top; |
|
2547 |
|
2548 w = (*env)->GetIntField(env, target, componentIDs.width) |
|
2549 - (wdata->left + wdata->right); |
|
2550 h = (*env)->GetIntField(env, target, componentIDs.height) |
|
2551 - (wdata->top + wdata->bottom); |
|
2552 if (w < 0) w = 0; |
|
2553 if (h < 0) h = 0; |
|
2554 |
|
2555 DTRACE_PRINTLN1("TL: pCreate: state = 0x%X", state); |
|
2556 |
|
2557 wdata->isModal = 0; |
|
2558 wdata->initialFocus = (Boolean)initialFocus; |
|
2559 wdata->isShowing = False; |
|
2560 wdata->shellResized = False; |
|
2561 wdata->canvasResized = False; |
|
2562 wdata->menuBarReset = False; |
|
2563 wdata->need_reshape = False; |
|
2564 wdata->focusProxy = NULL; |
|
2565 #ifdef __linux__ |
|
2566 wdata->fixInsets = True; |
|
2567 #endif |
|
2568 wdata->state = state; |
|
2569 |
|
2570 /* initialize screen to screen number in GraphicsConfig's device */ |
|
2571 /* can the Window's GC ever be null? */ |
|
2572 gc = (*env)->GetObjectField(env, target, componentIDs.graphicsConfig); |
|
2573 DASSERT(gc); |
|
2574 |
|
2575 gd = (*env)->GetObjectField(env, gc, x11GraphicsConfigIDs.screen); |
|
2576 DASSERT(gd); |
|
2577 |
|
2578 wdata->screenNum = (*env)->GetIntField(env, gd, x11GraphicsDeviceIDs.screen); |
|
2579 |
|
2580 wdata->isFocusableWindow = (Boolean)isFocusableWindow; |
|
2581 |
|
2582 /* |
|
2583 * Create a top-level shell widget. |
|
2584 */ |
|
2585 argc = 0; |
|
2586 XtSetArg(args[argc], XmNsaveUnder, False); argc++; |
|
2587 if (resizable) { |
|
2588 XtSetArg(args[argc], XmNallowShellResize, True); argc++; |
|
2589 } else { |
|
2590 XtSetArg(args[argc], XmNallowShellResize, False); argc++; |
|
2591 } |
|
2592 XtSetArg(args[argc], XmNvisual, defConfig->awt_visInfo.visual); argc++; |
|
2593 XtSetArg(args[argc], XmNcolormap, defConfig->awt_cmap); argc++; |
|
2594 XtSetArg(args[argc], XmNdepth, defConfig->awt_depth); argc++; |
|
2595 XtSetArg(args[argc], XmNmappedWhenManaged, False); argc++; |
|
2596 XtSetArg(args[argc], XmNx, x); argc++; |
|
2597 XtSetArg(args[argc], XmNy, y); argc++; |
|
2598 XtSetArg(args[argc], XmNwidth, w); argc++; |
|
2599 XtSetArg(args[argc], XmNheight, h); argc++; |
|
2600 |
|
2601 XtSetArg(args[argc], XmNbuttonFontList, getMotifFontList()); argc++; |
|
2602 XtSetArg(args[argc], XmNlabelFontList, getMotifFontList()); argc++; |
|
2603 XtSetArg(args[argc], XmNtextFontList, getMotifFontList()); argc++; |
|
2604 |
|
2605 XtSetArg(args[argc], XmNmwmDecorations, wdata->decor); argc++; |
|
2606 XtSetArg(args[argc], XmNscreen, |
|
2607 ScreenOfDisplay(awt_display, defConfig->awt_visInfo.screen)); argc++; |
|
2608 |
|
2609 if (wdata->initialFocus == False || !isFocusableWindowByPeer(env, this)) { |
|
2610 XtSetArg(args[argc], XmNinput, False); argc++; |
|
2611 } |
|
2612 |
|
2613 if (wdata->decor == AWT_NO_DECOR) { |
|
2614 /* this is heinous but it can not be avoided for now. |
|
2615 ** this is the only known way to eliminate all decorations |
|
2616 ** for openlook, which btw, is a bug as ol theoretically |
|
2617 ** supports MWM_HINTS |
|
2618 */ |
|
2619 #ifndef DO_FULL_DECOR |
|
2620 if (awt_wm_getRunningWM() == OPENLOOK_WM) { |
|
2621 XtSetArg(args[argc], XmNoverrideRedirect, True); |
|
2622 argc++; |
|
2623 } |
|
2624 #endif |
|
2625 } |
|
2626 |
|
2627 /* 4334958: Widget name is set to the Java class name */ |
|
2628 shell_name = |
|
2629 (char *)JNU_GetStringPlatformChars(env, target_class_name, NULL); |
|
2630 |
|
2631 if (parent) { |
|
2632 pdata = (struct FrameData *) |
|
2633 (*env)->GetLongField(env, parent, mComponentPeerIDs.pData); |
|
2634 } |
|
2635 |
|
2636 /* Parenting tells us whether we wish to be transient or not */ |
|
2637 if (pdata == NULL) { |
|
2638 if (!shell_name) |
|
2639 shell_name = "AWTapp"; |
|
2640 shell_class = topLevelShellWidgetClass; |
|
2641 parent_widget = awt_root_shell; |
|
2642 } |
|
2643 else { |
|
2644 if (!shell_name) |
|
2645 shell_name = "AWTdialog"; |
|
2646 shell_class = transientShellWidgetClass; |
|
2647 parent_widget = pdata->winData.shell; |
|
2648 XtSetArg(args[argc], XmNtransient, True); argc++; |
|
2649 XtSetArg(args[argc], XmNtransientFor, parent_widget); argc++; |
|
2650 |
|
2651 /* Fix Forte Menu Bug. If Window name is "###overrideRedirect###", |
|
2652 * then set XmNoverrideRedirect to prevent Menus from getting focus. |
|
2653 * In JDK 1.2.2 we created Windows as xmMenuShellWidgetClass, |
|
2654 * so we did not need to do this. Swing DefaultPopupFactory's |
|
2655 * createHeavyWeightPopup sets Window name to "###overrideRedirect###". |
|
2656 */ |
|
2657 /** |
|
2658 * Fix for 4476629. Allow Swing to create heavyweight popups which will |
|
2659 * not steal focus from Frame. |
|
2660 */ |
|
2661 jname = (*env)->GetObjectField(env, target, componentIDs.name); |
|
2662 if (!JNU_IsNull(env, jname)) { |
|
2663 cname = (char *)JNU_GetStringPlatformChars(env, jname, NULL); |
|
2664 } |
|
2665 if ( (cname != NULL && strcmp(cname, "###overrideRedirect###") == 0) |
|
2666 || (!isFrameOrDialog(target, env) |
|
2667 && !isFocusableWindowByPeer(env, this) |
|
2668 ) |
|
2669 ) |
|
2670 { /* mbron */ |
|
2671 XtSetArg(args[argc], XmNoverrideRedirect, True); |
|
2672 argc++; |
|
2673 } |
|
2674 if (cname) { |
|
2675 JNU_ReleaseStringPlatformChars(env, jname, (const char *) cname); |
|
2676 } |
|
2677 (*env)->DeleteLocalRef(env, jname); |
|
2678 } |
|
2679 DASSERT(!(argc > MAX_ARGC)); |
|
2680 wdata->winData.shell = XtCreatePopupShell(shell_name, shell_class, |
|
2681 parent_widget, args, argc); |
|
2682 if (shell_name) { |
|
2683 JNU_ReleaseStringPlatformChars(env, target_class_name, shell_name); |
|
2684 } |
|
2685 |
|
2686 #ifdef DEBUG |
|
2687 /* Participate in EditRes protocol to facilitate debugging */ |
|
2688 XtAddEventHandler(wdata->winData.shell, (EventMask)0, True, |
|
2689 _XEditResCheckMessages, NULL); |
|
2690 #endif |
|
2691 |
|
2692 setDeleteCallback(globalRef, wdata); |
|
2693 |
|
2694 /* Establish resizability. For the case of not resizable, do not |
|
2695 yet set a fixed size here; we must wait until in the routine |
|
2696 sun_awt_motif_MWindowPeer_pReshape() after insets have been fixed. |
|
2697 This is because correction of the insets may affect shell size. |
|
2698 (See comments in shellEH() concerning correction of the insets. */ |
|
2699 /* |
|
2700 * Fix for BugTraq ID 4313607. |
|
2701 * Initial resizability will be set later in MWindowPeer_setResizable() |
|
2702 * called from init(). |
|
2703 */ |
|
2704 wdata->isResizable = True; |
|
2705 wdata->isFixedSizeSet = False; |
|
2706 |
|
2707 XtAddEventHandler(wdata->winData.shell, |
|
2708 (StructureNotifyMask | PropertyChangeMask |
|
2709 | VisibilityChangeMask), |
|
2710 False, shellEH, globalRef); |
|
2711 |
|
2712 XtAddEventHandler(wdata->winData.shell, |
|
2713 FocusChangeMask, |
|
2714 False, shellFocusEH, globalRef); |
|
2715 |
|
2716 |
|
2717 /** |
|
2718 * Installing property change handler for DISPOSE property. |
|
2719 * This property will be changed when we need to dispose the whole |
|
2720 * top-level. The nature of PropertyNotify will guarantee that it is |
|
2721 * the latest event on the top-level so we can freely dispose it. |
|
2722 */ |
|
2723 wdata->isDisposeScheduled = False; |
|
2724 if (_XA_JAVA_DISPOSE_PROPERTY_ATOM == 0) { |
|
2725 _XA_JAVA_DISPOSE_PROPERTY_ATOM = XInternAtom(awt_display, "_SUNW_JAVA_AWT_DISPOSE", False); |
|
2726 } |
|
2727 XtAddEventHandler(wdata->winData.shell, PropertyChangeMask, False, |
|
2728 shellDisposeNotifyHandler, globalRef); |
|
2729 |
|
2730 /* |
|
2731 * Create "main" form. |
|
2732 */ |
|
2733 argc = 0; |
|
2734 XtSetArg(args[argc], XmNmarginWidth, 0); argc++; |
|
2735 XtSetArg(args[argc], XmNmarginHeight, 0); argc++; |
|
2736 XtSetArg(args[argc], XmNhorizontalSpacing, 0); argc++; |
|
2737 XtSetArg(args[argc], XmNverticalSpacing, 0); argc++; |
|
2738 XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE); argc++; |
|
2739 |
|
2740 XtSetArg(args[argc], XmNbuttonFontList, getMotifFontList()); argc++; |
|
2741 XtSetArg(args[argc], XmNlabelFontList, getMotifFontList()); argc++; |
|
2742 XtSetArg(args[argc], XmNtextFontList, getMotifFontList()); argc++; |
|
2743 |
|
2744 DASSERT(!(argc > MAX_ARGC)); |
|
2745 wdata->mainWindow = XmCreateForm(wdata->winData.shell, "main", args, argc); |
|
2746 |
|
2747 /* The widget returned by awt_canvas_create is a drawing area |
|
2748 (i.e., canvas) which is the child of another drawing area |
|
2749 parent widget. The parent is the drawing area within the |
|
2750 form just created. The child is an drawing area layer over |
|
2751 the entire frame window, including the form, any menu bar |
|
2752 and warning windows present, and also window manager stuff. |
|
2753 The top, bottom, left, and right fields in wdata maintain |
|
2754 the respective offsets between these two drawing areas. */ |
|
2755 |
|
2756 wdata->winData.comp.widget = awt_canvas_create((XtPointer)globalRef, |
|
2757 wdata->mainWindow, |
|
2758 "frame_", |
|
2759 -1, |
|
2760 -1, |
|
2761 True, |
|
2762 wdata, |
|
2763 adata); |
|
2764 XtAddCallback(wdata->winData.comp.widget, |
|
2765 XmNresizeCallback, outerCanvasResizeCB, |
|
2766 globalRef); |
|
2767 |
|
2768 innerCanvasW = XtParent(wdata->winData.comp.widget); |
|
2769 XtVaSetValues(innerCanvasW, |
|
2770 XmNleftAttachment, XmATTACH_FORM, |
|
2771 XmNrightAttachment, XmATTACH_FORM, |
|
2772 NULL); |
|
2773 |
|
2774 XtAddEventHandler(innerCanvasW, StructureNotifyMask, FALSE, |
|
2775 innerCanvasEH, globalRef); |
|
2776 |
|
2777 wdata->focusProxy = createFocusProxy((XtPointer)globalRef, |
|
2778 wdata->mainWindow); |
|
2779 |
|
2780 /* No menu bar initially */ |
|
2781 wdata->menuBar = NULL; |
|
2782 wdata->mbHeight = 0; |
|
2783 |
|
2784 /* If a warning window (string) is needed, establish it now.*/ |
|
2785 warningString = |
|
2786 (*env)->GetObjectField(env, target, windowIDs.warningString); |
|
2787 if (!JNU_IsNull(env, warningString) ) { |
|
2788 char *wString; |
|
2789 /* Insert a warning window. It's height can't be set yet; |
|
2790 it will later be set in setMbAndWwHeightAndOffsets().*/ |
|
2791 wString = (char *) JNU_GetStringPlatformChars(env, warningString, NULL); |
|
2792 wdata->warningWindow = awt_util_createWarningWindow(wdata->mainWindow, wString); |
|
2793 JNU_ReleaseStringPlatformChars(env, warningString, (const char *) wString); |
|
2794 |
|
2795 wdata->wwHeight = 0; |
|
2796 XtVaSetValues(wdata->warningWindow, |
|
2797 XmNleftAttachment, XmATTACH_FORM, |
|
2798 XmNrightAttachment, XmATTACH_FORM, |
|
2799 NULL); |
|
2800 |
|
2801 #ifdef NETSCAPE |
|
2802 /* For NETSCAPE, warning window is at bottom of the form*/ |
|
2803 XtVaSetValues(innerCanvasW, |
|
2804 XmNtopAttachment, XmATTACH_FORM, |
|
2805 NULL); |
|
2806 XtVaSetValues(wdata->warningWindow, |
|
2807 XmNtopAttachment, XmATTACH_WIDGET, |
|
2808 XmNtopWidget, innerCanvasW, |
|
2809 XmNbottomAttachment, XmATTACH_FORM, |
|
2810 NULL); |
|
2811 #else /* NETSCAPE */ |
|
2812 /* Otherwise (not NETSCAPE), warning is at top of form */ |
|
2813 XtVaSetValues(wdata->warningWindow, |
|
2814 XmNtopAttachment, XmATTACH_FORM, |
|
2815 NULL); |
|
2816 XtVaSetValues(innerCanvasW, |
|
2817 XmNtopAttachment, XmATTACH_WIDGET, |
|
2818 XmNtopWidget, wdata->warningWindow, |
|
2819 XmNbottomAttachment, XmATTACH_FORM, |
|
2820 NULL); |
|
2821 #endif /* NETSCAPE */ |
|
2822 |
|
2823 } else { |
|
2824 /* No warning window present */ |
|
2825 XtVaSetValues(innerCanvasW, |
|
2826 XmNtopAttachment, XmATTACH_FORM, |
|
2827 XmNbottomAttachment, XmATTACH_FORM, |
|
2828 NULL); |
|
2829 wdata->warningWindow = NULL; |
|
2830 wdata->wwHeight = 0; |
|
2831 } |
|
2832 |
|
2833 awt_util_show(wdata->winData.comp.widget); |
|
2834 |
|
2835 AWT_FLUSH_UNLOCK(); |
|
2836 |
|
2837 addTopLevel(wdata); |
|
2838 |
|
2839 /* Check whether this is an instance of InputMethodWindow or not */ |
|
2840 if (inputMethodWindowClass == NULL) { |
|
2841 jclass localClass = (*env)->FindClass(env, "sun/awt/im/InputMethodWindow"); |
|
2842 inputMethodWindowClass = (jclass)(*env)->NewGlobalRef(env, localClass); |
|
2843 (*env)->DeleteLocalRef(env, localClass); |
|
2844 } |
|
2845 if ((*env)->IsInstanceOf(env, target, inputMethodWindowClass)) { |
|
2846 wdata->isInputMethodWindow = True; |
|
2847 addInputMethodWindow(wdata); |
|
2848 } |
|
2849 } /* MWindowPeer_pCreate() */ |
|
2850 |
|
2851 |
|
2852 /* |
|
2853 * Class: sun_awt_motif_MWindowPeer |
|
2854 * Method: pSetTitle |
|
2855 * Signature: (Ljava/lang/String;)V |
|
2856 */ |
|
2857 JNIEXPORT void JNICALL |
|
2858 Java_sun_awt_motif_MWindowPeer_pSetTitle(JNIEnv *env, jobject this, |
|
2859 jstring title) |
|
2860 { |
|
2861 char *ctitle; |
|
2862 char *empty_string = " "; |
|
2863 struct FrameData *wdata; |
|
2864 XTextProperty text_prop; |
|
2865 char *c[1]; |
|
2866 int32_t conv_result; |
|
2867 |
|
2868 AWT_LOCK(); |
|
2869 |
|
2870 wdata = (struct FrameData *) |
|
2871 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
2872 |
|
2873 if (wdata == NULL || wdata->winData.shell == NULL) { |
|
2874 JNU_ThrowNullPointerException(env, "null wdata or shell"); |
|
2875 AWT_UNLOCK(); |
|
2876 return; |
|
2877 } |
|
2878 |
|
2879 /* TODO: uwe: set _NET_WM_NAME property to utf-8 name */ |
|
2880 |
|
2881 ctitle = (JNU_IsNull(env, title)) ? empty_string |
|
2882 : (char *) JNU_GetStringPlatformChars(env, title, NULL); |
|
2883 |
|
2884 if (strcmp(ctitle, "") == 0) |
|
2885 ctitle = empty_string; |
|
2886 |
|
2887 c[0] = ctitle; |
|
2888 |
|
2889 /* need to convert ctitle to CompoundText */ |
|
2890 conv_result = XmbTextListToTextProperty(awt_display, c, 1, |
|
2891 XStdICCTextStyle, |
|
2892 &text_prop); |
|
2893 |
|
2894 /* |
|
2895 * XmbTextListToTextProperty returns value that is greater |
|
2896 * than Success if the supplied text is not fully convertible |
|
2897 * to specified encoding. In this case, the return value is |
|
2898 * the number of inconvertible characters. But convertibility |
|
2899 * is guaranteed for XCompoundTextStyle, so it will actually |
|
2900 * never be greater than Success. Errors handled below are |
|
2901 * represented by values that are lower than Success. |
|
2902 */ |
|
2903 if (conv_result >= Success) { |
|
2904 XtVaSetValues(wdata->winData.shell, |
|
2905 XmNtitle, text_prop.value, |
|
2906 XmNtitleEncoding, text_prop.encoding, |
|
2907 XmNiconName, text_prop.value, |
|
2908 XmNiconNameEncoding, text_prop.encoding, |
|
2909 XmNname, ctitle, |
|
2910 NULL); |
|
2911 } |
|
2912 |
|
2913 if (ctitle != empty_string) |
|
2914 JNU_ReleaseStringPlatformChars(env, title, (const char *) ctitle); |
|
2915 |
|
2916 if (conv_result == XNoMemory) { |
|
2917 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
|
2918 AWT_UNLOCK(); |
|
2919 return; |
|
2920 } |
|
2921 if (conv_result == XLocaleNotSupported) { |
|
2922 JNU_ThrowInternalError(env, "Current locale is not supported"); |
|
2923 AWT_UNLOCK(); |
|
2924 return; |
|
2925 } |
|
2926 |
|
2927 XFree(text_prop.value); |
|
2928 AWT_FLUSH_UNLOCK(); |
|
2929 } |
|
2930 |
|
2931 /* |
|
2932 * Class: sun_awt_motif_MWindowPeer |
|
2933 * Method: pToFront |
|
2934 * Signature: ()V |
|
2935 */ |
|
2936 JNIEXPORT void JNICALL |
|
2937 Java_sun_awt_motif_MWindowPeer_pToFront(JNIEnv *env, jobject this) |
|
2938 { |
|
2939 struct FrameData *wdata; |
|
2940 jobject target; |
|
2941 Window shellWindow; |
|
2942 Boolean autoRequestFocus; |
|
2943 Boolean isModal = FALSE; |
|
2944 |
|
2945 AWT_LOCK(); |
|
2946 |
|
2947 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
2948 |
|
2949 wdata = (struct FrameData *) |
|
2950 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
2951 if (wdata == NULL |
|
2952 || wdata->winData.comp.widget == NULL |
|
2953 || wdata->winData.shell == NULL |
|
2954 || wdata->mainWindow == NULL |
|
2955 || JNU_IsNull(env, target)) |
|
2956 { |
|
2957 JNU_ThrowNullPointerException(env, "null widget/target data"); |
|
2958 AWT_UNLOCK(); |
|
2959 return; |
|
2960 } |
|
2961 |
|
2962 if ((shellWindow = XtWindow(wdata->winData.shell)) != None) { |
|
2963 XRaiseWindow(awt_display, shellWindow); |
|
2964 |
|
2965 autoRequestFocus = (*env)->GetBooleanField(env, target, windowIDs.isAutoRequestFocus); |
|
2966 |
|
2967 if (isDialog(target, env)) { |
|
2968 isModal = (*env)->GetBooleanField(env, target, dialogIDs.modal); |
|
2969 } |
|
2970 |
|
2971 // In contrast to XToolkit/WToolkit modal dialog can be unfocused. |
|
2972 // So we should also ask for modality in addition to 'autoRequestFocus'. |
|
2973 if (wdata->isFocusableWindow && (autoRequestFocus || isModal)) { |
|
2974 XSetInputFocus(awt_display, XtWindow(wdata->focusProxy), RevertToPointerRoot, CurrentTime); |
|
2975 } |
|
2976 } |
|
2977 |
|
2978 (*env)->DeleteLocalRef(env, target); |
|
2979 |
|
2980 AWT_UNLOCK(); |
|
2981 } |
|
2982 |
|
2983 /* |
|
2984 * Class: sun_awt_motif_MWindowPeer |
|
2985 * Method: pShow |
|
2986 * Signature: ()V |
|
2987 */ |
|
2988 JNIEXPORT void JNICALL |
|
2989 Java_sun_awt_motif_MWindowPeer_pShow(JNIEnv *env, jobject this) |
|
2990 { |
|
2991 Java_sun_awt_motif_MWindowPeer_pShowModal(env, this, JNI_FALSE); |
|
2992 } |
|
2993 |
|
2994 /* |
|
2995 * Class: sun_awt_motif_MWindowPeer |
|
2996 * Method: pShowModal |
|
2997 * Signature: (Z)V |
|
2998 */ |
|
2999 JNIEXPORT void JNICALL |
|
3000 Java_sun_awt_motif_MWindowPeer_pShowModal(JNIEnv *env, jobject this, |
|
3001 jboolean isModal) |
|
3002 { |
|
3003 struct FrameData *wdata; |
|
3004 Boolean iconic; |
|
3005 jobject target; |
|
3006 Boolean locationByPlatform; |
|
3007 |
|
3008 AWT_LOCK(); |
|
3009 |
|
3010 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
3011 |
|
3012 wdata = (struct FrameData *) |
|
3013 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3014 if (wdata == NULL |
|
3015 || wdata->winData.comp.widget == NULL |
|
3016 || wdata->winData.shell == NULL |
|
3017 || wdata->mainWindow == NULL |
|
3018 || (wdata->winData.flags & W_IS_EMBEDDED) |
|
3019 || JNU_IsNull(env, target)) |
|
3020 { |
|
3021 JNU_ThrowNullPointerException(env, "null widget/target data"); |
|
3022 AWT_UNLOCK(); |
|
3023 return; |
|
3024 } |
|
3025 |
|
3026 DTRACE_PRINTLN2("TL: pShowModal(modal = %s) state = 0x%X", |
|
3027 isModal ? "true" : "false", |
|
3028 wdata->state); |
|
3029 |
|
3030 wdata->isModal = isModal; |
|
3031 |
|
3032 /* |
|
3033 * A workaround for bug 4062589 that is really a motif problem |
|
3034 * (see bug 4064803). Before popping up a modal dialog, if a |
|
3035 * pulldown menu has the input focus (i.e. user has pulled the |
|
3036 * menu down), we send a fake click event and make sure the click |
|
3037 * event is processed. With this simulation of user clicking, X |
|
3038 * server will not get confused about the modality and a |
|
3039 * subsequent click on the popup modal dialog will not cause |
|
3040 * system lockup. |
|
3041 */ |
|
3042 if (wdata->isModal && awt_util_focusIsOnMenu(awt_display) |
|
3043 && awt_util_sendButtonClick(awt_display, InputFocus)) |
|
3044 { |
|
3045 for (;;) { |
|
3046 XEvent ev; |
|
3047 XtAppPeekEvent(awt_appContext, &ev); |
|
3048 if ((ev.type == ButtonRelease) |
|
3049 && (*(XButtonEvent *)&ev).send_event) |
|
3050 { |
|
3051 XtAppProcessEvent(awt_appContext, XtIMAll); |
|
3052 break; |
|
3053 } else { |
|
3054 XtAppProcessEvent(awt_appContext, XtIMAll); |
|
3055 } |
|
3056 } |
|
3057 } |
|
3058 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
3059 |
|
3060 // 4488209: kdm@sparc.spb.su |
|
3061 // wdata->isShowing is True when toFront calls pShow. |
|
3062 // We do not need to do some things if wdata->isShowing is True. |
|
3063 if (!wdata->isShowing) { |
|
3064 XtVaSetValues(wdata->winData.comp.widget, |
|
3065 XmNx, -(wdata->left), |
|
3066 XmNy, -(wdata->top), |
|
3067 NULL); |
|
3068 |
|
3069 /* But see below! */ |
|
3070 iconic = (wdata->state & java_awt_Frame_ICONIFIED) ? True : False; |
|
3071 XtVaSetValues(wdata->winData.shell, |
|
3072 XmNinitialState, iconic ? IconicState : NormalState, |
|
3073 NULL); |
|
3074 |
|
3075 if (wdata->menuBar != NULL) { |
|
3076 awt_util_show(wdata->menuBar); |
|
3077 } |
|
3078 XtManageChild(wdata->mainWindow); |
|
3079 XtRealizeWidget(wdata->winData.shell); /* but not map it yet */ |
|
3080 |
|
3081 /* fprintf(stderr, "*** proxy window %x\n", XtWindow(wdata->focusProxy)); */ |
|
3082 XStoreName(awt_display, XtWindow(wdata->focusProxy), "FocusProxy"); |
|
3083 /* |
|
3084 * Maximization and other stuff that requires a live Window to set |
|
3085 * properties on to communicate with WM. |
|
3086 */ |
|
3087 awt_wm_setExtendedState(wdata, wdata->state); |
|
3088 awt_wm_setShellDecor(wdata, wdata->isResizable); |
|
3089 |
|
3090 if (wdata->isModal) { |
|
3091 removePopupMenus(); |
|
3092 #ifndef NOMODALFIX |
|
3093 /* |
|
3094 * Fix for 4078176 Modal dialogs don't act modal |
|
3095 * if addNotify() is called before setModal(true). |
|
3096 * Moved from Java_sun_awt_motif_MDialogPeer_create. |
|
3097 */ |
|
3098 if (!wdata->callbacksAdded) { |
|
3099 XtAddCallback(wdata->winData.shell, |
|
3100 XtNpopupCallback, awt_shellPoppedUp, |
|
3101 NULL); |
|
3102 XtAddCallback(wdata->winData.shell, |
|
3103 XtNpopdownCallback, awt_shellPoppedDown, |
|
3104 NULL); |
|
3105 wdata->callbacksAdded = True; |
|
3106 } |
|
3107 #endif /* !NOMODALFIX */ |
|
3108 /* |
|
3109 * Set modality on the Shell, not the BB. The BB expects that |
|
3110 * its parent is an xmDialogShell, which as the result of |
|
3111 * coalescing is now a transientShell... This has resulted in |
|
3112 * a warning message generated under fvwm. The shells are |
|
3113 * virtually identical and a review of Motif src suggests that |
|
3114 * setting dialog style on BB is a convenience not functional |
|
3115 * for BB so set Modality on shell, not the BB(form) widget. |
|
3116 */ |
|
3117 XtVaSetValues(wdata->winData.shell, |
|
3118 XmNmwmInputMode, MWM_INPUT_FULL_APPLICATION_MODAL, |
|
3119 NULL); |
|
3120 XtManageChild(wdata->winData.comp.widget); |
|
3121 } |
|
3122 else { /* not modal */ |
|
3123 XtVaSetValues(wdata->winData.shell, |
|
3124 XmNmwmInputMode, MWM_INPUT_MODELESS, NULL); |
|
3125 XtManageChild(wdata->winData.comp.widget); |
|
3126 XtSetMappedWhenManaged(wdata->winData.shell, True); |
|
3127 } |
|
3128 if (wdata->isResizable) { |
|
3129 /* REMINDER: uwe: will need to revisit for setExtendedStateBounds */ |
|
3130 awt_wm_removeSizeHints(wdata->winData.shell, PMinSize|PMaxSize); |
|
3131 } |
|
3132 locationByPlatform = |
|
3133 (*env)->GetBooleanField(env, target, windowIDs.locationByPlatform); |
|
3134 if (locationByPlatform) { |
|
3135 awt_wm_removeSizeHints(wdata->winData.shell, USPosition|PPosition); |
|
3136 } |
|
3137 } |
|
3138 |
|
3139 /* |
|
3140 * 4261047: always pop up with XtGrabNone. Motif notices the |
|
3141 * modal input mode and perform the grab for us, doing its |
|
3142 * internal book-keeping as well. |
|
3143 */ |
|
3144 XtPopup(wdata->winData.shell, XtGrabNone); |
|
3145 wdata->isShowing = True; |
|
3146 |
|
3147 wdata->initialFocus = (*env)->GetBooleanField(env, target, windowIDs.isAutoRequestFocus); |
|
3148 |
|
3149 if (wdata->isFocusableWindow) { |
|
3150 if (wdata->initialFocus || wdata->isModal) { |
|
3151 focusOnMapNotify = True; |
|
3152 } else { |
|
3153 XtVaSetValues(wdata->winData.shell, XmNinput, False, NULL); |
|
3154 } |
|
3155 } |
|
3156 |
|
3157 (*env)->DeleteLocalRef(env, target); |
|
3158 |
|
3159 AWT_FLUSH_UNLOCK(); |
|
3160 } |
|
3161 |
|
3162 /* |
|
3163 * Class: sun_awt_motif_MWindowPeer |
|
3164 * Method: getState |
|
3165 * Signature: ()I |
|
3166 */ |
|
3167 JNIEXPORT jint JNICALL |
|
3168 Java_sun_awt_motif_MWindowPeer_getState(JNIEnv *env, jobject this) |
|
3169 { |
|
3170 struct FrameData *wdata; |
|
3171 jint state; |
|
3172 |
|
3173 AWT_LOCK(); |
|
3174 |
|
3175 wdata = (struct FrameData *) |
|
3176 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3177 if (wdata == NULL || wdata->winData.shell == NULL) { |
|
3178 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3179 AWT_UNLOCK(); |
|
3180 return java_awt_Frame_NORMAL; |
|
3181 } |
|
3182 |
|
3183 state = wdata->state; |
|
3184 |
|
3185 AWT_FLUSH_UNLOCK(); |
|
3186 return state; |
|
3187 } |
|
3188 |
|
3189 /* |
|
3190 * Class: sun_awt_motif_MWindowPeer |
|
3191 * Method: setState |
|
3192 * Signature: (I)V |
|
3193 */ |
|
3194 JNIEXPORT void JNICALL |
|
3195 Java_sun_awt_motif_MWindowPeer_setState(JNIEnv *env, jobject this, |
|
3196 jint state) |
|
3197 { |
|
3198 struct FrameData *wdata; |
|
3199 Widget shell; |
|
3200 Window shell_win; |
|
3201 jint changed; |
|
3202 Boolean changeIconic, iconic; |
|
3203 |
|
3204 AWT_LOCK(); |
|
3205 wdata = (struct FrameData *) |
|
3206 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3207 if (wdata == NULL || wdata->winData.shell == NULL) { |
|
3208 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3209 AWT_UNLOCK(); |
|
3210 return; |
|
3211 } |
|
3212 |
|
3213 shell = wdata->winData.shell; |
|
3214 shell_win = XtWindow(shell); |
|
3215 |
|
3216 DTRACE_PRINTLN4("TL: setState(0x%x/0x%x, 0x%X -> 0x%X)", |
|
3217 shell, shell_win, |
|
3218 wdata->state, state); |
|
3219 |
|
3220 if (!wdata->isShowing) { |
|
3221 /* |
|
3222 * Not showing, so just record requested state; pShow will set |
|
3223 * initial state hints/properties appropriately before poping |
|
3224 * us up again. |
|
3225 */ |
|
3226 DTRACE_PRINTLN("TL: NOT showing (just record the new state)"); |
|
3227 wdata->state = state; |
|
3228 AWT_UNLOCK(); |
|
3229 return; |
|
3230 } |
|
3231 |
|
3232 /* |
|
3233 * Request the state transition from WM here and do java upcalls |
|
3234 * in shell event handler when WM actually changes our state. |
|
3235 */ |
|
3236 changed = wdata->state ^ state; |
|
3237 |
|
3238 changeIconic = changed & java_awt_Frame_ICONIFIED; |
|
3239 iconic = (state & java_awt_Frame_ICONIFIED) ? True : False; |
|
3240 |
|
3241 if (changeIconic && iconic) { |
|
3242 DTRACE_PRINTLN("TL: set iconic = True"); |
|
3243 XIconifyWindow(XtDisplay(shell), shell_win, |
|
3244 XScreenNumberOfScreen(XtScreen(shell))); |
|
3245 } |
|
3246 |
|
3247 /* |
|
3248 * If a change in both iconic and extended states requested, do |
|
3249 * changes to extended state when we are in iconic state. |
|
3250 */ |
|
3251 if ((changed & ~java_awt_Frame_ICONIFIED) != 0) { |
|
3252 awt_wm_setExtendedState(wdata, state); |
|
3253 } |
|
3254 |
|
3255 if (changeIconic && !iconic) { |
|
3256 DTRACE_PRINTLN("TL: set iconic = False"); |
|
3257 XMapWindow(XtDisplay(shell), shell_win); |
|
3258 } |
|
3259 |
|
3260 AWT_FLUSH_UNLOCK(); |
|
3261 } |
|
3262 |
|
3263 |
|
3264 /* |
|
3265 * Class: sun_awt_motif_MWindowPeer |
|
3266 * Method: pHide |
|
3267 * Signature: ()V |
|
3268 */ |
|
3269 JNIEXPORT void JNICALL |
|
3270 Java_sun_awt_motif_MWindowPeer_pHide(JNIEnv *env, jobject this) |
|
3271 { |
|
3272 struct FrameData *wdata; |
|
3273 |
|
3274 AWT_LOCK(); |
|
3275 wdata = (struct FrameData *) |
|
3276 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3277 |
|
3278 if (wdata == NULL |
|
3279 || wdata->winData.comp.widget == NULL |
|
3280 || wdata->winData.shell == NULL) |
|
3281 { |
|
3282 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3283 AWT_UNLOCK(); |
|
3284 return; |
|
3285 } |
|
3286 |
|
3287 /** |
|
3288 * Disable proxy mechanism when Window's shell is being hidden |
|
3289 */ |
|
3290 clearFocusPath(wdata->winData.shell); |
|
3291 |
|
3292 wdata->isShowing = False; /* ignore window state events */ |
|
3293 |
|
3294 if (XtIsRealized(wdata->winData.shell)) { |
|
3295 /* XXX: uwe: this is bogus */ |
|
3296 /* |
|
3297 * Make sure we withdraw a window in an unmaximized state, or |
|
3298 * we'll lose out normal bounds (pShow will take care of |
|
3299 * hinting maximization, so when the window is shown again it |
|
3300 * will be correctly shown maximized). |
|
3301 */ |
|
3302 if (wdata->state & java_awt_Frame_MAXIMIZED_BOTH) { |
|
3303 awt_wm_setExtendedState(wdata, |
|
3304 wdata->state & ~java_awt_Frame_MAXIMIZED_BOTH); |
|
3305 } |
|
3306 XtUnmanageChild(wdata->winData.comp.widget); |
|
3307 XtPopdown(wdata->winData.shell); |
|
3308 } |
|
3309 |
|
3310 AWT_FLUSH_UNLOCK(); |
|
3311 } |
|
3312 |
|
3313 |
|
3314 /* sun_awt_motif_MWindowPeer_pReshape() is native (X/Motif) routine that |
|
3315 is called to effect a reposition and / or resize of the target frame. |
|
3316 The parameters x,y,w,h specify target's x, y position, width, height.*/ |
|
3317 |
|
3318 /* |
|
3319 * This functionality is invoked from both java and native code, and |
|
3320 * we only want to lock when invoking it from java, so wrap the native |
|
3321 * method version with the locking. |
|
3322 */ |
|
3323 |
|
3324 /* |
|
3325 * Class: sun_awt_motif_MWindowPeer |
|
3326 * Method: pReshape |
|
3327 * Signature: (IIII)V |
|
3328 */ |
|
3329 JNIEXPORT void JNICALL |
|
3330 Java_sun_awt_motif_MWindowPeer_pReshape(JNIEnv *env, jobject this, |
|
3331 jint x, jint y, jint w, jint h) |
|
3332 { |
|
3333 struct FrameData *wdata; |
|
3334 |
|
3335 AWT_LOCK(); |
|
3336 |
|
3337 wdata = (struct FrameData *) |
|
3338 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3339 |
|
3340 if (wdata == NULL || |
|
3341 wdata->winData.comp.widget == NULL || |
|
3342 wdata->winData.shell == NULL) { |
|
3343 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3344 AWT_UNLOCK(); |
|
3345 return; |
|
3346 } |
|
3347 |
|
3348 // See if our new location is on a new screen |
|
3349 if (wdata->reparented) { |
|
3350 checkNewXineramaScreen(env, this, wdata, x, y, w, h); |
|
3351 } |
|
3352 |
|
3353 /** |
|
3354 * Fix for 4652685. |
|
3355 * Avoid setting position for embedded frames, since this conflicts with the |
|
3356 * fix for 4419207. We assume that the embedded frame never changes its |
|
3357 * position relative to the parent. |
|
3358 */ |
|
3359 if (wdata->winData.flags & W_IS_EMBEDDED) { |
|
3360 x = 0; |
|
3361 y = 0; |
|
3362 } |
|
3363 |
|
3364 reshape(env, this, wdata, x, y, w, h, True); |
|
3365 |
|
3366 AWT_FLUSH_UNLOCK(); |
|
3367 } |
|
3368 |
|
3369 /* |
|
3370 * Class: sun_awt_motif_MEmbeddedFramePeer |
|
3371 * Method: pReshapePrivate |
|
3372 * Signature: (IIII)V |
|
3373 */ |
|
3374 JNIEXPORT void JNICALL |
|
3375 Java_sun_awt_motif_MEmbeddedFramePeer_pReshapePrivate(JNIEnv *env, jobject this, |
|
3376 jint x, jint y, jint w, jint h) |
|
3377 { |
|
3378 struct FrameData *wdata; |
|
3379 |
|
3380 AWT_LOCK(); |
|
3381 |
|
3382 wdata = (struct FrameData *) |
|
3383 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3384 |
|
3385 if (wdata == NULL || |
|
3386 wdata->winData.comp.widget == NULL || |
|
3387 wdata->winData.shell == NULL) { |
|
3388 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3389 AWT_UNLOCK(); |
|
3390 return; |
|
3391 } |
|
3392 |
|
3393 reshape(env, this, wdata, x, y, w, h, True); |
|
3394 |
|
3395 AWT_FLUSH_UNLOCK(); |
|
3396 } |
|
3397 |
|
3398 static void |
|
3399 reshape(JNIEnv *env, jobject this, struct FrameData *wdata, |
|
3400 jint x, jint y, jint w, jint h, Boolean setXY) |
|
3401 { |
|
3402 int32_t topAdjust, /* top adjustment of offset */ |
|
3403 bottomAdjust; /* bottom adjustment of offset */ |
|
3404 int32_t width, /* of X/Motif shell and form */ |
|
3405 height; /* of X/Motif shell and form */ |
|
3406 int32_t w1, h1; |
|
3407 enum wmgr_t wm; /* window manager */ |
|
3408 XWindowAttributes winAttr; |
|
3409 |
|
3410 DTRACE_PRINTLN7("TL: reshape(0x%x/0x%x,\n"/**/ |
|
3411 "TL: x = %d, y = %d, w = %d, h = %d, %s)", |
|
3412 wdata->winData.shell, XtWindow(wdata->winData.shell), |
|
3413 x, y, w, h, |
|
3414 setXY ? "setXY" : "false"); |
|
3415 |
|
3416 wm = awt_wm_getRunningWM(); |
|
3417 |
|
3418 /* Make adjustments in case of a dynamically added/removed menu bar */ |
|
3419 awtJNI_setMbAndWwHeightAndOffsets(env, this, wdata); |
|
3420 |
|
3421 #ifdef _pauly_debug |
|
3422 fprintf(stdout," reshape. offsets - top: %d, bottom: %d, left: %d, right: %d\n", |
|
3423 wdata->top, wdata->bottom, wdata->left, wdata->right); |
|
3424 fflush(stdout); |
|
3425 #endif /* _pauly_debug */ |
|
3426 |
|
3427 /* The abstract java (target) position coordinates (x,y) |
|
3428 are for the bordered window. Eventually(!), the Motif |
|
3429 (shell) coordinates (XmNx, XmNy) will exclude borders. |
|
3430 (This is true only AFTER shell is massaged by the WM.) */ |
|
3431 |
|
3432 /* The abstract java (target) width and height includes any WM |
|
3433 borders. But the Motif width and height excludes WM borders. |
|
3434 The wdata top and bottom fields may include space for menu bar, |
|
3435 warning window, etc. We must adjust by these values for shell. */ |
|
3436 topAdjust = 0; |
|
3437 bottomAdjust = 0; |
|
3438 /* Surprise - do not(!) check for nonNull MenuBar because that can |
|
3439 occur separately (in ...pSetMenubar()) from calculation of the |
|
3440 menu bar height and offsets (in setMbAndWwHeightAndOffsets()). |
|
3441 In any event, the offsets and wdata mbHeight field should jive. */ |
|
3442 topAdjust += wdata->mbHeight; |
|
3443 if (wdata->warningWindow != NULL) { |
|
3444 #ifdef NETSCAPE |
|
3445 bottomAdjust += wdata->wwHeight; |
|
3446 #else /* NETSCAPE */ |
|
3447 topAdjust += wdata->wwHeight; |
|
3448 #endif /* NETSCAPE */ |
|
3449 } |
|
3450 if (wdata->hasTextComponentNative) { |
|
3451 bottomAdjust += wdata->imHeight; |
|
3452 } |
|
3453 #ifdef _pauly_debug |
|
3454 fprintf(stdout," reshape. adjustments - top: %d, bottom: %d\n", topAdjust, bottomAdjust); |
|
3455 fflush(stdout); |
|
3456 #endif /* _pauly_debug */ |
|
3457 |
|
3458 width = w - (wdata->left + wdata->right); |
|
3459 height = h - (wdata->top + wdata->bottom) + (topAdjust + bottomAdjust); |
|
3460 |
|
3461 /* |
|
3462 * Shell size. |
|
3463 * 4033151. If nonpositive size specified (e.g., if no size |
|
3464 * given), establish minimum allowable size. Note: Motif shell |
|
3465 * can not be sized 0. |
|
3466 */ |
|
3467 w1 = (width > 0) ? width : 1; |
|
3468 h1 = (height > 0) ? height : 1; |
|
3469 |
|
3470 if (awt_wm_configureGravityBuggy() /* WM ignores window gravity */ |
|
3471 && wdata->reparented && wdata->isShowing) |
|
3472 { |
|
3473 /* |
|
3474 * Buggy WM places client window at (x,y) ignoring the window |
|
3475 * gravity. All our windows are NorthWestGravity, so adjust |
|
3476 * (x,y) by insets appropriately. |
|
3477 */ |
|
3478 x += wdata->left; |
|
3479 y += wdata->top; |
|
3480 DTRACE_PRINTLN2("TL: work around WM gravity bug: x += %d, y += %d", |
|
3481 wdata->left, wdata->top); |
|
3482 } |
|
3483 |
|
3484 if (wdata->imRemove) { |
|
3485 XtVaSetValues(XtParent(wdata->winData.comp.widget), |
|
3486 XmNheight, (((h - (wdata->top + wdata->bottom)) > 0) ? |
|
3487 (h - (wdata->top + wdata->bottom)) : 1), |
|
3488 NULL); |
|
3489 wdata->imRemove = False; |
|
3490 } |
|
3491 |
|
3492 #if 0 /* XXX: this screws insets calculation under KDE2 in the case of |
|
3493 negative x, y */ |
|
3494 /* |
|
3495 * Without these checks, kwm places windows slightly off the screen, |
|
3496 * when there is a window underneath at (0,0) and empty space below, |
|
3497 * but not to the right. |
|
3498 */ |
|
3499 if (x < 0) x = 0; |
|
3500 if (y < 0) y = 0; |
|
3501 #endif |
|
3502 if ((wdata->winData.flags & W_IS_EMBEDDED) == 0) { |
|
3503 if ((wm == MOTIF_WM) || (wm == CDE_WM)) { |
|
3504 /* |
|
3505 * By default MWM has "usePPosition: nonzero" and so ignores |
|
3506 * windows with PPosition (0,0). Work around (should we???). |
|
3507 */ |
|
3508 if ((x == 0) && (y == 0)) { |
|
3509 x = y = 1; |
|
3510 } |
|
3511 } |
|
3512 } |
|
3513 |
|
3514 if ( wdata->decor == AWT_NO_DECOR ) { |
|
3515 if (setXY) |
|
3516 XtConfigureWidget(wdata->winData.shell, x, y, w1, h1, 0 ); |
|
3517 else |
|
3518 XtResizeWidget(wdata->winData.shell, w1, h1, 0); |
|
3519 } |
|
3520 else { |
|
3521 /* |
|
3522 * 5006248, workaround for OpenLook WM. |
|
3523 * Thread gets stuck at XtVaSetValues call awaiting for first |
|
3524 * ConfigureNotify to come. For OpenLook it looks like a showstopper. |
|
3525 * We put dummy ConfigureNotify to satisfy the requirements. |
|
3526 */ |
|
3527 if (awt_wm_getRunningWM() == OPENLOOK_WM) { |
|
3528 XEvent xev; |
|
3529 xev.xconfigure.type = ConfigureNotify; |
|
3530 xev.xconfigure.display = awt_display; |
|
3531 xev.xconfigure.window = XtWindow(wdata->winData.shell); |
|
3532 xev.xconfigure.event = xev.xconfigure.window; |
|
3533 xev.xconfigure.x = x; |
|
3534 xev.xconfigure.y = y; |
|
3535 xev.xconfigure.height = h1; |
|
3536 xev.xconfigure.width = w1; |
|
3537 xev.xconfigure.serial = NextRequest(awt_display) + 1; // see isMine() Xt inner function code. |
|
3538 |
|
3539 XPutBackEvent(awt_display, &xev); |
|
3540 } |
|
3541 |
|
3542 if (wdata->isResizable) { |
|
3543 XtVaSetValues(wdata->winData.shell, |
|
3544 XmNwidth, w1, |
|
3545 XmNheight, h1, |
|
3546 NULL); |
|
3547 } |
|
3548 else { |
|
3549 /* |
|
3550 * Fix for BugTraq ID 4313607 - call awt_wm_setShellNotResizable |
|
3551 * regardless of wdata->isFixedSizeSet and wdata->reparented values. |
|
3552 */ |
|
3553 DTRACE_PRINTLN("TL: set fixed size from reshape"); |
|
3554 awt_wm_setShellNotResizable(wdata, w1, h1, True); |
|
3555 if (wdata->reparented && (w1 > 0) && (h1 > 0)) { |
|
3556 wdata->isFixedSizeSet = True; |
|
3557 } |
|
3558 } |
|
3559 if (setXY) |
|
3560 XtVaSetValues(wdata->winData.shell, |
|
3561 XmNx, x, |
|
3562 XmNy, y, |
|
3563 NULL); |
|
3564 } |
|
3565 /* inner/parent drawing area (parent is form) */ |
|
3566 h1 = h - (wdata->top + wdata->bottom); |
|
3567 h1 = ( h1 > 0 ) ? h1 : 1; |
|
3568 #if 0 |
|
3569 XtConfigureWidget(XtParent(wdata->winData.comp.widget), |
|
3570 0, topAdjust, w1, h1, 0 ); |
|
3571 #else |
|
3572 XtVaSetValues(XtParent(wdata->winData.comp.widget), |
|
3573 XmNx, 0, |
|
3574 XmNy, topAdjust, |
|
3575 XmNwidth, w1, |
|
3576 XmNheight, h1, |
|
3577 NULL); |
|
3578 #endif |
|
3579 |
|
3580 #ifdef _pauly_debug |
|
3581 fprintf(stdout," reshape. setting inner canvas to: %d,%d,%d,%d\n", |
|
3582 0, topAdjust, w1, h1 ); |
|
3583 fflush(stdout); |
|
3584 #endif /* _pauly_debug */ |
|
3585 |
|
3586 wdata->menuBarReset = False; |
|
3587 |
|
3588 /* DTRACE_PRINTLN("TL: reshape -> returning"); */ |
|
3589 return; |
|
3590 } |
|
3591 |
|
3592 /* |
|
3593 * Class: sun_awt_motif_MEmbeddedFramePeer |
|
3594 * Method: getBoundsPrivate |
|
3595 * Signature: ()Ljava/awt/Rectangle |
|
3596 */ |
|
3597 JNIEXPORT jobject JNICALL Java_sun_awt_motif_MEmbeddedFramePeer_getBoundsPrivate |
|
3598 (JNIEnv * env, jobject this) |
|
3599 { |
|
3600 jobject bounds = NULL; |
|
3601 struct FrameData *cdata; |
|
3602 XWindowAttributes attr; |
|
3603 |
|
3604 AWT_LOCK(); |
|
3605 |
|
3606 cdata = (struct FrameData *) |
|
3607 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3608 if (cdata == NULL || cdata->mainWindow == NULL) { |
|
3609 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3610 AWT_UNLOCK(); |
|
3611 return NULL; |
|
3612 } |
|
3613 if (!XtIsRealized(cdata->mainWindow) || !XtIsRealized(cdata->winData.shell)) { |
|
3614 JNU_ThrowInternalError(env, "widget not visible on screen"); |
|
3615 AWT_UNLOCK(); |
|
3616 return NULL; |
|
3617 } |
|
3618 |
|
3619 memset(&attr, 0, sizeof(XWindowAttributes)); |
|
3620 XGetWindowAttributes(awt_display, XtWindow(cdata->winData.shell), &attr); |
|
3621 |
|
3622 bounds = JNU_NewObjectByName(env, "java/awt/Rectangle", "(IIII)V", |
|
3623 (jint)attr.x, (jint)attr.y, (jint)attr.width, (jint)attr.height); |
|
3624 if (((*env)->ExceptionOccurred(env)) || JNU_IsNull(env, bounds)) { |
|
3625 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3626 AWT_UNLOCK(); |
|
3627 return NULL; |
|
3628 } |
|
3629 |
|
3630 AWT_UNLOCK(); |
|
3631 |
|
3632 return bounds; |
|
3633 } |
|
3634 |
|
3635 /* |
|
3636 * Class: sun_awt_motif_MWindowPeer |
|
3637 * Method: pDispose |
|
3638 * Signature: ()V |
|
3639 */ |
|
3640 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_pDispose |
|
3641 (JNIEnv *env, jobject this) |
|
3642 { |
|
3643 struct FrameData *wdata; |
|
3644 |
|
3645 AWT_LOCK(); |
|
3646 wdata = (struct FrameData *) |
|
3647 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3648 if (wdata == NULL || wdata->mainWindow == NULL || wdata->winData.shell == NULL) { |
|
3649 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3650 AWT_UNLOCK(); |
|
3651 return; |
|
3652 } |
|
3653 if (wdata->winData.flags & W_IS_EMBEDDED) { |
|
3654 awt_util_delEmbeddedFrame(wdata->winData.shell); |
|
3655 deinstall_xembed(wdata); |
|
3656 } |
|
3657 scheduleDispose(env, this); |
|
3658 |
|
3659 AWT_FLUSH_UNLOCK(); |
|
3660 } |
|
3661 |
|
3662 /* |
|
3663 * Class: sun_awt_motif_MFramePeer |
|
3664 * Method: pGetIconSize |
|
3665 * Signature: (II)Z |
|
3666 */ |
|
3667 JNIEXPORT jboolean JNICALL Java_sun_awt_motif_MFramePeer_pGetIconSize |
|
3668 (JNIEnv *env, jobject this, jint widthHint, jint heightHint) |
|
3669 { |
|
3670 struct FrameData *wdata; |
|
3671 uint32_t width, height, border_width, depth; |
|
3672 Window win; |
|
3673 int32_t x, y; |
|
3674 uint32_t mask; |
|
3675 XSetWindowAttributes attrs; |
|
3676 uint32_t saveWidth = 0; |
|
3677 uint32_t saveHeight = 0; |
|
3678 uint32_t dist = 0xffffffff; |
|
3679 int32_t diff = 0; |
|
3680 int32_t closestWidth; |
|
3681 int32_t closestHeight; |
|
3682 int32_t newDist; |
|
3683 int32_t found = 0; |
|
3684 AwtGraphicsConfigDataPtr adata; |
|
3685 |
|
3686 AWT_LOCK(); |
|
3687 wdata = (struct FrameData *) |
|
3688 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3689 if (wdata == NULL) { |
|
3690 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3691 AWT_UNLOCK(); |
|
3692 return FALSE; |
|
3693 } |
|
3694 XtVaGetValues(wdata->winData.shell, |
|
3695 XmNiconWindow, &win, |
|
3696 NULL); |
|
3697 if (!win) { |
|
3698 int32_t count; |
|
3699 int32_t i; |
|
3700 XIconSize *sizeList; |
|
3701 |
|
3702 adata = getGraphicsConfigFromComponentPeer(env, this); |
|
3703 |
|
3704 if (!XGetIconSizes(awt_display, |
|
3705 RootWindow(awt_display, adata->awt_visInfo.screen), |
|
3706 &sizeList, &count)) { |
|
3707 /* No icon sizes so can't set it -- Should we throw an exception?*/ |
|
3708 /* [jk] I don't think so: simply fall back to 16x16 */ |
|
3709 saveWidth = saveHeight = 16; |
|
3710 goto top; |
|
3711 } |
|
3712 for (i=0; i < count; i++) { |
|
3713 if (widthHint >= sizeList[i].min_width && |
|
3714 widthHint <= sizeList[i].max_width && |
|
3715 heightHint >= sizeList[i].min_height && |
|
3716 heightHint <= sizeList[i].max_height) { |
|
3717 found = 1; |
|
3718 if ((((widthHint-sizeList[i].min_width) |
|
3719 % sizeList[i].width_inc) == 0) && |
|
3720 (((heightHint-sizeList[i].min_height) |
|
3721 % sizeList[i].height_inc) ==0)) { |
|
3722 /* Found an exact match */ |
|
3723 saveWidth = widthHint; |
|
3724 saveHeight = heightHint; |
|
3725 dist = 0; |
|
3726 break; |
|
3727 } |
|
3728 diff = widthHint - sizeList[i].min_width; |
|
3729 if (diff == 0) { |
|
3730 closestWidth = widthHint; |
|
3731 } else { |
|
3732 diff = diff%sizeList[i].width_inc; |
|
3733 closestWidth = widthHint - diff; |
|
3734 } |
|
3735 diff = heightHint - sizeList[i].min_height; |
|
3736 if (diff == 0) { |
|
3737 closestHeight = heightHint; |
|
3738 } else { |
|
3739 diff = diff%sizeList[i].height_inc; |
|
3740 closestHeight = heightHint - diff; |
|
3741 } |
|
3742 newDist = closestWidth*closestWidth + |
|
3743 closestHeight*closestHeight; |
|
3744 if (dist > newDist) { |
|
3745 saveWidth = closestWidth; |
|
3746 saveHeight = closestHeight; |
|
3747 dist = newDist; |
|
3748 } |
|
3749 } |
|
3750 } |
|
3751 |
|
3752 if (!found) { |
|
3753 #if 1 |
|
3754 /* [sbb] this code should work better than the original Solaris |
|
3755 code */ |
|
3756 if (widthHint >= sizeList[0].max_width || |
|
3757 heightHint >= sizeList[0].max_height) { |
|
3758 /* determine which way to scale */ |
|
3759 int32_t wdiff = widthHint - sizeList[0].max_width; |
|
3760 int32_t hdiff = heightHint - sizeList[0].max_height; |
|
3761 if (wdiff >= hdiff) { /* need to scale width more */ |
|
3762 saveWidth = sizeList[0].max_width; |
|
3763 saveHeight = (int32_t)(((double)sizeList[0].max_width/widthHint) * |
|
3764 heightHint); |
|
3765 } else { |
|
3766 saveWidth = (int32_t)(((double)sizeList[0].max_height/heightHint) * |
|
3767 widthHint); |
|
3768 saveHeight = sizeList[0].max_height; |
|
3769 } |
|
3770 } else if (widthHint < sizeList[0].min_width || |
|
3771 heightHint < sizeList[0].min_height) { |
|
3772 saveWidth = (sizeList[0].min_width+sizeList[0].max_width)/2; |
|
3773 saveHeight = (sizeList[0].min_height+sizeList[0].max_height)/2; |
|
3774 } else { /* it fits within the right size */ |
|
3775 saveWidth = widthHint; |
|
3776 saveHeight = heightHint; |
|
3777 } |
|
3778 |
|
3779 #else /* XXX: old Solaris code */ |
|
3780 /* REMIND: Aspect ratio */ |
|
3781 if (widthHint >= sizeList[0].max_width && |
|
3782 heightHint >= sizeList[0].max_height) { |
|
3783 saveWidth = sizeList[0].max_width; |
|
3784 saveHeight = sizeList[0].max_height; |
|
3785 } else if (widthHint >= sizeList[0].min_width && |
|
3786 heightHint >= sizeList[0].min_height) { |
|
3787 saveWidth = sizeList[0].min_width; |
|
3788 saveHeight = sizeList[0].min_height; |
|
3789 } else { |
|
3790 saveWidth = (sizeList[0].min_width+sizeList[0].max_width)/2; |
|
3791 saveHeight = (sizeList[0].min_height+sizeList[0].max_height)/2; |
|
3792 } |
|
3793 #endif |
|
3794 } |
|
3795 free((void *) sizeList); |
|
3796 } else { |
|
3797 Window root; |
|
3798 if (XGetGeometry(awt_display, |
|
3799 win, |
|
3800 &root, |
|
3801 &x, |
|
3802 &y, |
|
3803 (uint32_t *)&saveWidth, |
|
3804 (uint32_t *)&saveHeight, |
|
3805 (uint32_t *)&border_width, |
|
3806 (uint32_t *)&depth)) { |
|
3807 } |
|
3808 } |
|
3809 |
|
3810 top: |
|
3811 (*env)->SetIntField(env, this, mWindowPeerIDs.iconWidth, (jint)saveWidth); |
|
3812 (*env)->SetIntField(env, this, mWindowPeerIDs.iconHeight, (jint)saveHeight); |
|
3813 |
|
3814 AWT_UNLOCK(); |
|
3815 return TRUE; |
|
3816 } |
|
3817 |
|
3818 /* |
|
3819 * Class: sun_awt_motif_MFramePeer |
|
3820 * Method: pSetIconImage |
|
3821 * Signature: ([B[I[SII)V |
|
3822 */ |
|
3823 JNIEXPORT void JNICALL Java_sun_awt_motif_MFramePeer_pSetIconImage___3B_3I_3SII |
|
3824 (JNIEnv *env, jobject this, |
|
3825 jbyteArray jbyteData, jintArray jintData, jshortArray jushortData, |
|
3826 jint iconWidth, jint iconHeight) |
|
3827 { |
|
3828 struct FrameData *wdata; |
|
3829 Window win; |
|
3830 GC gc; |
|
3831 int32_t x, y; |
|
3832 XImage *dst; |
|
3833 uint32_t mask; |
|
3834 XSetWindowAttributes attrs; |
|
3835 jobject jbuf = NULL; |
|
3836 void *buf = NULL; |
|
3837 int32_t len = 0; |
|
3838 int32_t bpp, slp, bpsl; |
|
3839 AwtGraphicsConfigDataPtr adata; |
|
3840 |
|
3841 if (JNU_IsNull(env, jbyteData)) { |
|
3842 if (JNU_IsNull(env, jintData)) { |
|
3843 if (JNU_IsNull(env, jushortData)) { |
|
3844 /* [jk] Don't throw an exception here, it breaks |
|
3845 * programs that run correctly on Windows |
|
3846 * JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3847 */ |
|
3848 return; |
|
3849 } else { |
|
3850 jbuf = jushortData; |
|
3851 } |
|
3852 } else { |
|
3853 jbuf = jintData; |
|
3854 } |
|
3855 } else { |
|
3856 jbuf = jbyteData; |
|
3857 len = (*env)->GetArrayLength(env, jbyteData); |
|
3858 } |
|
3859 AWT_LOCK(); |
|
3860 wdata = (struct FrameData *) |
|
3861 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
3862 /* REMIND: Need to figure out how to display image on a pixmap */ |
|
3863 |
|
3864 if (wdata == NULL || wdata->winData.shell == NULL) { |
|
3865 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
3866 AWT_UNLOCK(); |
|
3867 return; |
|
3868 } |
|
3869 |
|
3870 adata = getGraphicsConfigFromComponentPeer(env, this); |
|
3871 |
|
3872 /* [jk] we need a new pixmap everytime: |
|
3873 * Test case: src/share/test/awt/FrameTest.html Look at the icon, |
|
3874 * select Operations/Change IconImage, you should see a different |
|
3875 * icon now. |
|
3876 */ |
|
3877 if (wdata->iconPixmap) { |
|
3878 XFreePixmap(awt_display, wdata->iconPixmap); |
|
3879 wdata->iconPixmap = None; |
|
3880 } |
|
3881 |
|
3882 if (wdata->iconPixmap == None) { |
|
3883 if ((wdata->iconPixmap = |
|
3884 XCreatePixmap(awt_display, |
|
3885 RootWindow(awt_display, adata->awt_visInfo.screen), |
|
3886 iconWidth, iconHeight, |
|
3887 adata->awtImage->Depth)) == None) { |
|
3888 /* REMIND: How to warn that there was a problem? */ |
|
3889 AWT_UNLOCK(); |
|
3890 return; |
|
3891 } |
|
3892 wdata->iconWidth = iconWidth; |
|
3893 wdata->iconHeight = iconHeight; |
|
3894 } |
|
3895 |
|
3896 buf = (void *) (*env)->GetPrimitiveArrayCritical(env, jbuf, NULL); |
|
3897 if (jbyteData != NULL) { |
|
3898 int32_t i; |
|
3899 unsigned char *ubuf = (unsigned char *) buf; |
|
3900 /* Need to map from ICM lut to cmap */ |
|
3901 for (i=0; i < len; i++) { |
|
3902 ubuf[i] = (ubuf[i] >= adata->color_data->awt_numICMcolors) |
|
3903 ? 0 |
|
3904 : adata->color_data->awt_icmLUT2Colors[ubuf[i]]; |
|
3905 } |
|
3906 } |
|
3907 |
|
3908 bpp = adata->awtImage->wsImageFormat.bits_per_pixel; |
|
3909 slp = adata->awtImage->wsImageFormat.scanline_pad; |
|
3910 bpsl = paddedwidth(iconWidth * bpp, slp) >> 3; |
|
3911 if (((bpsl << 3) / bpp) < iconWidth) { |
|
3912 (*env)->ReleasePrimitiveArrayCritical(env, jbuf, buf, JNI_ABORT); |
|
3913 AWT_UNLOCK(); |
|
3914 return; |
|
3915 } |
|
3916 dst = XCreateImage(awt_display, adata->awt_visInfo.visual, |
|
3917 adata->awtImage->Depth, ZPixmap, 0, |
|
3918 buf, iconWidth, iconHeight, 32, bpsl); |
|
3919 if (dst == NULL) { |
|
3920 /* REMIND: How to warn that there was a problem? */ |
|
3921 (*env)->ReleasePrimitiveArrayCritical(env, jbuf, buf, JNI_ABORT); |
|
3922 AWT_UNLOCK(); |
|
3923 return; |
|
3924 } |
|
3925 |
|
3926 if ((gc = XCreateGC(awt_display, wdata->iconPixmap, 0, 0)) == NULL) { |
|
3927 XDestroyImage (dst); |
|
3928 (*env)->ReleasePrimitiveArrayCritical(env, jbuf, buf, JNI_ABORT); |
|
3929 AWT_UNLOCK(); |
|
3930 return; |
|
3931 } |
|
3932 |
|
3933 XPutImage(awt_display, wdata->iconPixmap, gc, dst, |
|
3934 0, 0, 0, 0, iconWidth, iconHeight); |
|
3935 (*env)->ReleasePrimitiveArrayCritical(env, jbuf, buf, JNI_ABORT); |
|
3936 dst->data=NULL; |
|
3937 XDestroyImage(dst); |
|
3938 XFreeGC(awt_display, gc); |
|
3939 |
|
3940 XtVaGetValues(wdata->winData.shell, |
|
3941 XmNiconWindow, &win, |
|
3942 NULL); |
|
3943 if (!win) { |
|
3944 mask = CWBorderPixel | CWColormap | CWBackPixmap; |
|
3945 attrs.border_pixel = awt_defaultFg; |
|
3946 attrs.colormap = adata->awt_cmap; |
|
3947 attrs.background_pixmap = wdata->iconPixmap; |
|
3948 if (!(win = XCreateWindow(awt_display, |
|
3949 RootWindow(awt_display, |
|
3950 adata->awt_visInfo.screen), |
|
3951 0, 0, iconWidth, iconHeight, |
|
3952 (uint32_t) 0, |
|
3953 adata->awtImage->Depth, |
|
3954 InputOutput, |
|
3955 adata->awt_visInfo.visual, |
|
3956 mask, &attrs))) { |
|
3957 /* Still can't create the window so try setting iconPixmap */ |
|
3958 XtVaSetValues(wdata->winData.shell, |
|
3959 XmNiconPixmap, wdata->iconPixmap, |
|
3960 NULL); |
|
3961 AWT_FLUSH_UNLOCK(); |
|
3962 return; |
|
3963 } |
|
3964 } |
|
3965 |
|
3966 XtVaSetValues(wdata->winData.shell, |
|
3967 XmNiconPixmap, wdata->iconPixmap, |
|
3968 XmNiconWindow, win, |
|
3969 NULL); |
|
3970 |
|
3971 XSetWindowBackgroundPixmap(awt_display, win, wdata->iconPixmap); |
|
3972 XClearWindow(awt_display, win); |
|
3973 AWT_FLUSH_UNLOCK(); |
|
3974 } |
|
3975 |
|
3976 |
|
3977 /* |
|
3978 * Class: sun_awt_motif_MWindowPeer |
|
3979 * Method: setResizable |
|
3980 * Signature: (Z)V |
|
3981 */ |
|
3982 JNIEXPORT void JNICALL |
|
3983 Java_sun_awt_motif_MWindowPeer_setResizable(JNIEnv *env, jobject this, |
|
3984 jboolean resizable) |
|
3985 { |
|
3986 struct FrameData *wdata; |
|
3987 jobject target; |
|
3988 int32_t targetWidth, |
|
3989 targetHeight; |
|
3990 int32_t width, /* fixed width if not resizable */ |
|
3991 height; /* fixed height if not resizable*/ |
|
3992 int32_t verticalAdjust; /* menubar, warning window, etc.*/ |
|
3993 |
|
3994 if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
|
3995 return; |
|
3996 } |
|
3997 |
|
3998 AWT_LOCK(); |
|
3999 |
|
4000 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
4001 |
|
4002 wdata = (struct FrameData *) |
|
4003 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4004 |
|
4005 if (wdata == NULL |
|
4006 || wdata->winData.comp.widget == NULL |
|
4007 || wdata->winData.shell == NULL |
|
4008 || JNU_IsNull(env, target)) |
|
4009 { |
|
4010 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4011 if (!JNU_IsNull(env, target)) |
|
4012 (*env)->DeleteLocalRef(env, target); |
|
4013 AWT_UNLOCK(); |
|
4014 return; |
|
4015 } |
|
4016 |
|
4017 DTRACE_PRINTLN3("TL: setResizable(0x%x/0x%x, %s)", |
|
4018 wdata->winData.shell, XtWindow(wdata->winData.shell), |
|
4019 resizable ? "true" : "false"); |
|
4020 |
|
4021 if ((!wdata->isResizable) && (resizable)) { |
|
4022 awt_wm_setShellResizable(wdata); |
|
4023 wdata->isFixedSizeSet = False; |
|
4024 } |
|
4025 else if ((wdata->isResizable) && (!resizable)) { |
|
4026 /* |
|
4027 * To calculate fixed window width, height, we must subtract |
|
4028 * off the window manager borders as stored in the wdata |
|
4029 * structure. But note that the wdata top and bottom fields |
|
4030 * may include space for warning window, menubar, IM status; |
|
4031 * this IS part of shell. |
|
4032 */ |
|
4033 verticalAdjust = wdata->mbHeight; |
|
4034 if (wdata->warningWindow != NULL) { |
|
4035 verticalAdjust += wdata->wwHeight; |
|
4036 } |
|
4037 if (wdata->hasTextComponentNative) { |
|
4038 verticalAdjust += wdata->imHeight; |
|
4039 } |
|
4040 |
|
4041 targetWidth = (*env)->GetIntField(env, target, componentIDs.width); |
|
4042 targetHeight = (*env)->GetIntField(env, target, componentIDs.height); |
|
4043 width = targetWidth - (wdata->left + wdata->right); |
|
4044 height = targetHeight - (wdata->top + wdata->bottom) + verticalAdjust; |
|
4045 #ifdef __linux__ |
|
4046 width = (width > 0) ? width : 1; |
|
4047 height = (height > 0) ? height : 1; |
|
4048 #endif |
|
4049 DTRACE_PRINTLN2("TL: setting fixed size %ld x %ld", width, height); |
|
4050 awt_wm_setShellNotResizable(wdata, width, height, False); |
|
4051 if ((width > 0) && (height > 0)) { |
|
4052 wdata->isFixedSizeSet = True; |
|
4053 } |
|
4054 } |
|
4055 |
|
4056 wdata->isResizable = (Boolean)resizable; |
|
4057 |
|
4058 (*env)->DeleteLocalRef(env, target); |
|
4059 AWT_FLUSH_UNLOCK(); |
|
4060 } |
|
4061 |
|
4062 |
|
4063 /* sun_awt_motif_MWindowPeer_pSetMenuBar() is native (X/Motif) routine |
|
4064 which handles insertion or deletion of a menubar from this frame. */ |
|
4065 |
|
4066 /* |
|
4067 * Class: sun_awt_motif_MWindowPeer |
|
4068 * Method: pSetMenuBar |
|
4069 * Signature: (Lsun/awt/motif/MMenuBarPeer;)V |
|
4070 */ |
|
4071 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_pSetMenuBar |
|
4072 (JNIEnv *env, jobject this, jobject mb) |
|
4073 { |
|
4074 struct FrameData *wdata; |
|
4075 struct ComponentData *mdata; |
|
4076 jobject target; |
|
4077 Widget innerCanvasW; /* Motif inner canvas */ |
|
4078 #ifdef _pauly_debug |
|
4079 Dimension mbHeight; /* Motif menubar height */ |
|
4080 #endif /* _pauly_debug */ |
|
4081 |
|
4082 #ifdef _pauly_debug |
|
4083 fprintf(stdout," ++ ...pSetMenuBar.\n"); |
|
4084 fflush(stdout); |
|
4085 #endif /* _pauly_debug */ |
|
4086 |
|
4087 |
|
4088 if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
|
4089 return; |
|
4090 } |
|
4091 AWT_LOCK(); |
|
4092 |
|
4093 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
4094 |
|
4095 wdata = (struct FrameData *) |
|
4096 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4097 |
|
4098 if (JNU_IsNull(env, target) || wdata == NULL) { |
|
4099 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4100 if (!JNU_IsNull(env, target)) { |
|
4101 (*env)->DeleteLocalRef(env, target); |
|
4102 } |
|
4103 AWT_UNLOCK(); |
|
4104 return; |
|
4105 } |
|
4106 |
|
4107 if (mb == NULL) { |
|
4108 #ifdef _pauly_debug |
|
4109 fprintf(stdout," ...pSetMenuBar. mb is null.\n"); |
|
4110 fflush(stdout); |
|
4111 #endif /* _pauly_debug */ |
|
4112 if (wdata->menuBar != NULL) { |
|
4113 /* Redo attachments of other form widgets appropriately now */ |
|
4114 innerCanvasW = XtParent(wdata->winData.comp.widget); |
|
4115 |
|
4116 if (wdata->warningWindow == NULL) { |
|
4117 /* no warning window: canvas is now attached to form */ |
|
4118 XtVaSetValues(innerCanvasW, |
|
4119 XmNtopAttachment, XmATTACH_FORM, |
|
4120 NULL); |
|
4121 } else { |
|
4122 /* warning window present - conditional on #define NETSCAPE: |
|
4123 if NETSCAPE, warning window is at bottom, so canvas is |
|
4124 attached to the form (as above); otherwise (not NETSCAPE), |
|
4125 warning window itself is instead attached to form. */ |
|
4126 #ifdef NETSCAPE |
|
4127 XtVaSetValues(innerCanvasW, |
|
4128 XmNtopAttachment, XmATTACH_FORM, |
|
4129 NULL); |
|
4130 #else /* NETSCAPE */ |
|
4131 XtVaSetValues(wdata->warningWindow, |
|
4132 XmNtopAttachment, XmATTACH_FORM, |
|
4133 NULL); |
|
4134 #endif /* NETSCAPE */ |
|
4135 } |
|
4136 |
|
4137 wdata->menuBarReset = True; |
|
4138 } |
|
4139 wdata->menuBar = NULL; |
|
4140 awtJNI_setMbAndWwHeightAndOffsets(env, this, wdata); |
|
4141 (*env)->DeleteLocalRef(env, target); |
|
4142 AWT_FLUSH_UNLOCK(); |
|
4143 #ifdef _pauly_debug |
|
4144 fprintf(stdout," ...pSetMenuBar. Done.\n"); |
|
4145 fflush(stdout); |
|
4146 #endif /* _pauly_debug */ |
|
4147 return; |
|
4148 } |
|
4149 |
|
4150 mdata = (struct ComponentData *) |
|
4151 JNU_GetLongFieldAsPtr(env, mb, mMenuBarPeerIDs.pData); |
|
4152 if (mdata == NULL) { |
|
4153 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4154 (*env)->DeleteLocalRef(env, target); |
|
4155 AWT_UNLOCK(); |
|
4156 return; |
|
4157 } |
|
4158 |
|
4159 /* OK - insert the new menu bar into the form (at the top). |
|
4160 Redo the attachments of other form widgets appropriately.*/ |
|
4161 |
|
4162 if (wdata->menuBar == NULL) |
|
4163 wdata->menuBarReset = True; |
|
4164 wdata->menuBar = mdata->widget; |
|
4165 |
|
4166 #ifdef _pauly_debug |
|
4167 XtVaGetValues(mdata->widget, XmNheight, &mbHeight, NULL); |
|
4168 fprintf(stdout," ...pSetMenuBar. new menu bar (widget %x, parent: %x) - menu bar height: %d\n", wdata->menuBar, XtParent(wdata->menuBar), mbHeight); |
|
4169 fflush(stdout); |
|
4170 #endif /* _pauly_debug */ |
|
4171 |
|
4172 XtVaSetValues(mdata->widget, |
|
4173 XmNtopAttachment, XmATTACH_FORM, |
|
4174 XmNleftAttachment, XmATTACH_FORM, |
|
4175 XmNrightAttachment, XmATTACH_FORM, |
|
4176 NULL); |
|
4177 |
|
4178 innerCanvasW = XtParent(wdata->winData.comp.widget); |
|
4179 |
|
4180 if (wdata->warningWindow == NULL) { |
|
4181 /* no warning window: menu bar at top, canvas attached to it */ |
|
4182 XtVaSetValues(innerCanvasW, |
|
4183 XmNtopAttachment, XmATTACH_WIDGET, |
|
4184 XmNtopWidget, mdata->widget, |
|
4185 NULL); |
|
4186 } else { |
|
4187 /* warning window present - conditional on #define NETSCAPE: |
|
4188 if NETSCAPE, warning window is at bottom, so canvas is |
|
4189 attached to menu bar (as above); otherwise (not NETSCAPE), |
|
4190 the warning window is attached just below the menu bar. */ |
|
4191 #ifdef NETSCAPE |
|
4192 XtVaSetValues(innerCanvasW, |
|
4193 XmNtopAttachment, XmATTACH_WIDGET, |
|
4194 XmNtopWidget, mdata->widget, |
|
4195 NULL); |
|
4196 #else /* NETSCAPE */ |
|
4197 XtVaSetValues(wdata->warningWindow, |
|
4198 XmNtopAttachment, XmATTACH_WIDGET, |
|
4199 XmNtopWidget, mdata->widget, |
|
4200 NULL); |
|
4201 #endif /* NETSCAPE */ |
|
4202 } |
|
4203 |
|
4204 XtManageChild(mdata->widget); |
|
4205 XtMapWidget(mdata->widget); |
|
4206 XSync(awt_display, False); |
|
4207 awtJNI_setMbAndWwHeightAndOffsets(env, this, wdata); |
|
4208 |
|
4209 #ifdef _pauly_debug |
|
4210 XtVaGetValues(mdata->widget, XmNheight, &mbHeight, NULL); |
|
4211 fprintf(stdout," ...pSetMenuBar. with menu bar: menu bar height: %d, top offset: %d, bottom offset: %d\n", mbHeight, wdata->top, wdata->bottom); |
|
4212 fflush(stdout); |
|
4213 #endif /* _pauly_debug */ |
|
4214 |
|
4215 (*env)->DeleteLocalRef(env, target); |
|
4216 |
|
4217 AWT_FLUSH_UNLOCK(); |
|
4218 |
|
4219 #ifdef _pauly_debug |
|
4220 fprintf(stdout," ...pSetMenuBar. Done\n"); |
|
4221 fflush(stdout); |
|
4222 #endif /* _pauly_debug */ |
|
4223 } |
|
4224 |
|
4225 /* |
|
4226 * Class: sun_awt_motif_MWindowPeer |
|
4227 * Method: toBack |
|
4228 * Signature: ()V |
|
4229 */ |
|
4230 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_toBack |
|
4231 (JNIEnv *env, jobject this) |
|
4232 { |
|
4233 struct FrameData *wdata; |
|
4234 |
|
4235 AWT_LOCK(); |
|
4236 |
|
4237 wdata = (struct FrameData *) |
|
4238 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4239 |
|
4240 if (wdata == NULL || wdata->winData.shell == NULL) { |
|
4241 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4242 AWT_UNLOCK(); |
|
4243 return; |
|
4244 } |
|
4245 if (XtWindow(wdata->winData.shell) != 0) { |
|
4246 XLowerWindow(awt_display, XtWindow(wdata->winData.shell)); |
|
4247 } |
|
4248 AWT_FLUSH_UNLOCK(); |
|
4249 } |
|
4250 |
|
4251 /* |
|
4252 * Class: sun_awt_motif_MWindowPeer |
|
4253 * Method: updateAlwaysOnTop |
|
4254 * Signature: ()V |
|
4255 */ |
|
4256 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_updateAlwaysOnTop |
|
4257 (JNIEnv *env, jobject this, jboolean isOnTop) |
|
4258 { |
|
4259 struct FrameData *wdata; |
|
4260 AWT_LOCK(); |
|
4261 wdata = (struct FrameData *) |
|
4262 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4263 awt_wm_updateAlwaysOnTop(wdata, isOnTop); |
|
4264 AWT_FLUSH_UNLOCK(); |
|
4265 } |
|
4266 |
|
4267 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_addTextComponentNative |
|
4268 (JNIEnv *env, jobject this, jobject tc) |
|
4269 { |
|
4270 struct FrameData *wdata; |
|
4271 jobject target; |
|
4272 |
|
4273 if (JNU_IsNull(env, this)) { |
|
4274 return; |
|
4275 } |
|
4276 |
|
4277 AWT_LOCK(); |
|
4278 |
|
4279 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
4280 wdata = (struct FrameData *) |
|
4281 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4282 |
|
4283 if (wdata == NULL || |
|
4284 wdata->winData.comp.widget==NULL || |
|
4285 wdata->winData.shell==NULL || |
|
4286 JNU_IsNull(env, target)) { |
|
4287 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4288 AWT_UNLOCK(); |
|
4289 return; |
|
4290 } |
|
4291 if ( !wdata->hasTextComponentNative) { |
|
4292 wdata->hasTextComponentNative = True; |
|
4293 wdata->imHeight = awt_motif_getIMStatusHeight(wdata->winData.shell, tc); |
|
4294 wdata->bottom += wdata->imHeight; |
|
4295 awtJNI_ChangeInsets(env, this, wdata); |
|
4296 reshape(env, this, wdata, |
|
4297 (*env)->GetIntField(env, target, componentIDs.x), |
|
4298 (*env)->GetIntField(env, target, componentIDs.y), |
|
4299 (*env)->GetIntField(env, target, componentIDs.width), |
|
4300 (*env)->GetIntField(env, target, componentIDs.height), |
|
4301 True); |
|
4302 } |
|
4303 AWT_UNLOCK(); |
|
4304 } |
|
4305 |
|
4306 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_removeTextComponentNative |
|
4307 (JNIEnv *env, jobject this) |
|
4308 { |
|
4309 struct FrameData *wdata; |
|
4310 jobject target; |
|
4311 |
|
4312 if (JNU_IsNull(env, this)) { |
|
4313 return; |
|
4314 } |
|
4315 |
|
4316 AWT_LOCK(); |
|
4317 |
|
4318 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
4319 wdata = (struct FrameData *) |
|
4320 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4321 |
|
4322 if (wdata == NULL || |
|
4323 wdata->winData.comp.widget== NULL || |
|
4324 wdata->winData.shell== NULL || |
|
4325 JNU_IsNull(env, target)) { |
|
4326 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4327 AWT_UNLOCK(); |
|
4328 return; |
|
4329 } |
|
4330 if (!wdata->hasTextComponentNative) { |
|
4331 AWT_UNLOCK(); |
|
4332 return; |
|
4333 } |
|
4334 |
|
4335 wdata->bottom -= wdata->imHeight; |
|
4336 awtJNI_ChangeInsets(env, this, wdata); |
|
4337 wdata->imRemove = True; |
|
4338 reshape(env, this, wdata, |
|
4339 (*env)->GetIntField(env, target, componentIDs.x), |
|
4340 (*env)->GetIntField(env, target, componentIDs.y), |
|
4341 (*env)->GetIntField(env, target, componentIDs.width), |
|
4342 (*env)->GetIntField(env, target, componentIDs.height), |
|
4343 True); |
|
4344 |
|
4345 wdata->hasTextComponentNative = False; |
|
4346 wdata->imHeight = 0; |
|
4347 |
|
4348 AWT_UNLOCK(); |
|
4349 } /* ...removeTextComponentPeer() */ |
|
4350 |
|
4351 static Atom java_protocol = None; |
|
4352 static Atom motif_wm_msgs = None; |
|
4353 |
|
4354 static void im_callback(Widget shell, XtPointer client_data, XtPointer call_data) |
|
4355 { |
|
4356 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
4357 JNU_CallMethodByName(env, NULL, |
|
4358 (jobject)client_data, |
|
4359 "notifyIMMOptionChange", |
|
4360 "()V"); |
|
4361 } |
|
4362 |
|
4363 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_pSetIMMOption |
|
4364 (JNIEnv *env, jobject this, jstring option) |
|
4365 { |
|
4366 char *coption; |
|
4367 char *empty = "InputMethod"; |
|
4368 char *menuItem; |
|
4369 jobject globalRef; |
|
4370 struct FrameData *wdata; |
|
4371 |
|
4372 AWT_LOCK(); |
|
4373 |
|
4374 wdata = (struct FrameData *) |
|
4375 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4376 if (wdata == NULL || wdata->winData.shell == NULL) { |
|
4377 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4378 AWT_UNLOCK(); |
|
4379 return; |
|
4380 } |
|
4381 |
|
4382 globalRef = (jobject)JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.jniGlobalRef); |
|
4383 coption = (JNU_IsNull(env, option)) ? empty : (char *) JNU_GetStringPlatformChars(env, option, NULL); |
|
4384 if (java_protocol == None || motif_wm_msgs == None) { |
|
4385 java_protocol = XmInternAtom(awt_display, "_JAVA_IM_MSG", False); |
|
4386 motif_wm_msgs = XmInternAtom(awt_display, "_MOTIF_WM_MESSAGES", False); |
|
4387 } |
|
4388 XmAddProtocols (wdata->winData.shell, motif_wm_msgs, &java_protocol, 1); |
|
4389 XmAddProtocolCallback(wdata->winData.shell, motif_wm_msgs, java_protocol, im_callback, (XtPointer)globalRef); |
|
4390 |
|
4391 if ((menuItem = awt_util_makeWMMenuItem(coption, java_protocol))) { |
|
4392 XtVaSetValues(wdata->winData.shell, |
|
4393 XmNmwmMenu, |
|
4394 menuItem, |
|
4395 NULL); |
|
4396 free(menuItem); |
|
4397 } |
|
4398 if (coption != empty) |
|
4399 JNU_ReleaseStringPlatformChars(env, option, (const char *) coption); |
|
4400 AWT_FLUSH_UNLOCK(); |
|
4401 } |
|
4402 |
|
4403 |
|
4404 JNIEXPORT void JNICALL |
|
4405 Java_sun_awt_motif_MEmbeddedFramePeer_synthesizeFocusInOut(JNIEnv *env, jobject this, |
|
4406 jboolean b) |
|
4407 { |
|
4408 EmbeddedFrame *ef; |
|
4409 Boolean dummy; |
|
4410 |
|
4411 AWT_LOCK(); |
|
4412 ef = theEmbeddedFrameList; |
|
4413 while (ef != NULL) { |
|
4414 if ((*env)->IsSameObject(env, ef->javaRef, this)) { |
|
4415 XFocusChangeEvent xev; |
|
4416 xev.display = awt_display; |
|
4417 xev.serial = 0; |
|
4418 xev.type = b ? FocusIn : FocusOut; |
|
4419 xev.send_event = False; |
|
4420 xev.window = XtWindow(ef->embeddedFrame); |
|
4421 xev.mode = NotifyNormal; |
|
4422 xev.detail = NotifyNonlinear; |
|
4423 shellEH(ef->embeddedFrame, this, (XEvent*)&xev, &dummy); |
|
4424 break; |
|
4425 } |
|
4426 ef = ef->next; |
|
4427 } |
|
4428 AWT_UNLOCK(); |
|
4429 } |
|
4430 |
|
4431 JNIEXPORT void JNICALL |
|
4432 Java_sun_awt_motif_MEmbeddedFramePeer_traverseOut(JNIEnv *env, jobject this, jboolean direction) |
|
4433 { |
|
4434 struct FrameData *wdata; |
|
4435 |
|
4436 if (JNU_IsNull(env, this)) { |
|
4437 return; |
|
4438 } |
|
4439 |
|
4440 AWT_LOCK(); |
|
4441 |
|
4442 wdata = (struct FrameData *) |
|
4443 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4444 |
|
4445 if (wdata == NULL || |
|
4446 wdata->winData.comp.widget== NULL || |
|
4447 wdata->winData.shell== NULL) |
|
4448 { |
|
4449 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4450 AWT_UNLOCK(); |
|
4451 return; |
|
4452 } |
|
4453 xembed_traverse_out(wdata, direction); |
|
4454 AWT_UNLOCK(); |
|
4455 } |
|
4456 |
|
4457 |
|
4458 JNIEXPORT void JNICALL |
|
4459 Java_sun_awt_motif_MEmbeddedFramePeer_NEFcreate(JNIEnv *env, jobject this, |
|
4460 jobject parent, jlong handle) |
|
4461 { |
|
4462 #undef MAX_ARGC |
|
4463 #define MAX_ARGC 40 |
|
4464 Arg args[MAX_ARGC]; |
|
4465 int32_t argc; |
|
4466 struct FrameData *wdata; |
|
4467 jobject target; |
|
4468 jstring warningString; |
|
4469 jboolean resizable; |
|
4470 jobject globalRef = awtJNI_CreateAndSetGlobalRef(env, this); |
|
4471 Widget innerCanvasW; /* form's child, parent of the outer canvas |
|
4472 drawing area */ |
|
4473 AwtGraphicsConfigDataPtr adata; |
|
4474 AwtGraphicsConfigDataPtr defConfig; |
|
4475 |
|
4476 AWT_LOCK(); |
|
4477 |
|
4478 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
4479 |
|
4480 if (JNU_IsNull(env, target)) { |
|
4481 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4482 AWT_UNLOCK(); |
|
4483 return; |
|
4484 } |
|
4485 |
|
4486 wdata = ZALLOC(FrameData); |
|
4487 JNU_SetLongFieldFromPtr(env, this, mComponentPeerIDs.pData, wdata); |
|
4488 if (wdata == NULL) { |
|
4489 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
|
4490 AWT_UNLOCK(); |
|
4491 return; |
|
4492 } |
|
4493 |
|
4494 adata = getGraphicsConfigFromComponentPeer(env, this); |
|
4495 defConfig = getDefaultConfig(adata->awt_visInfo.screen); |
|
4496 |
|
4497 /* A variation on Netscape's hack for embedded frames: the client area |
|
4498 * of the browser is a Java Frame for parenting purposes, but really a |
|
4499 * Motif child window |
|
4500 */ |
|
4501 wdata->winData.flags |= W_IS_EMBEDDED; |
|
4502 |
|
4503 wdata->top = 0; |
|
4504 wdata->left = 0; |
|
4505 wdata->bottom = 0; |
|
4506 wdata->right = 0; |
|
4507 awtJNI_ChangeInsets(env, this, wdata); |
|
4508 |
|
4509 |
|
4510 wdata->isModal = 0; |
|
4511 wdata->isShowing = False; |
|
4512 wdata->shellResized = False; |
|
4513 wdata->canvasResized = False; |
|
4514 wdata->menuBarReset = False; |
|
4515 |
|
4516 resizable = (*env)->GetBooleanField(env, target, frameIDs.resizable); |
|
4517 |
|
4518 wdata->winData.shell = (Widget)handle; |
|
4519 awt_util_addEmbeddedFrame(wdata->winData.shell, globalRef); |
|
4520 |
|
4521 install_xembed((Widget)handle, wdata); |
|
4522 |
|
4523 setDeleteCallback(globalRef, wdata); |
|
4524 /* Establish resizability. For the case of not resizable, do not |
|
4525 yet set a fixed size here; we must wait until in the routine |
|
4526 sun_awt_motif_MWindowPeer_pReshape() after insets have been fixed. |
|
4527 This is because correction of the insets may affect shell size. |
|
4528 (See comments in shellEH() concerning correction of the insets. */ |
|
4529 /* |
|
4530 * Fix for BugTraq ID 4313607. |
|
4531 * Initial resizability will be set later in MWindowPeer_setResizable() |
|
4532 * called from init(). But the real changes will be made only if the new |
|
4533 * and old resizability values are different at that point, so we |
|
4534 * initialize isResizable with inverse value here to get the job done. |
|
4535 */ |
|
4536 wdata->isResizable = !resizable; |
|
4537 wdata->isFixedSizeSet = False; |
|
4538 #if 0 |
|
4539 if (resizable) { |
|
4540 awt_wm_setShellResizable(wdata); |
|
4541 } |
|
4542 #endif |
|
4543 |
|
4544 XtAddEventHandler(wdata->winData.shell, StructureNotifyMask | FocusChangeMask, |
|
4545 FALSE, (XtEventHandler)shellEH, globalRef); |
|
4546 |
|
4547 |
|
4548 argc = 0; |
|
4549 XtSetArg(args[argc], XmNvisual, defConfig->awt_visInfo.visual); argc++; |
|
4550 XtSetArg(args[argc], XmNcolormap, defConfig->awt_cmap); argc++; |
|
4551 XtSetArg(args[argc], XmNdepth, defConfig->awt_depth); argc++; |
|
4552 XtSetArg(args[argc], XmNmarginWidth, 0); argc++; |
|
4553 XtSetArg(args[argc], XmNmarginHeight, 0); argc++; |
|
4554 XtSetArg(args[argc], XmNhorizontalSpacing, 0); argc++; |
|
4555 XtSetArg(args[argc], XmNverticalSpacing, 0); argc++; |
|
4556 XtSetArg(args[argc], XmNscreen, |
|
4557 ScreenOfDisplay(awt_display, defConfig->awt_visInfo.screen)); argc++; |
|
4558 |
|
4559 |
|
4560 XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE); argc++; |
|
4561 |
|
4562 DASSERT(!(argc > MAX_ARGC)); |
|
4563 wdata->mainWindow = XmCreateForm(wdata->winData.shell, "main", args, argc); |
|
4564 |
|
4565 /* The widget returned by awt_canvas_create is a drawing area |
|
4566 (i.e., canvas) which is the child of another drawing area |
|
4567 parent widget. The parent is the drawing area within the |
|
4568 form just created. The child is an drawing area layer over |
|
4569 the entire frame window, including the form, any menu bar |
|
4570 and warning windows present, and also window manager stuff. |
|
4571 The top, bottom, left, and right fields in wdata maintain |
|
4572 the respective offsets between these two drawing areas. */ |
|
4573 |
|
4574 wdata->winData.comp.widget = awt_canvas_create((XtPointer)globalRef, |
|
4575 wdata->mainWindow, |
|
4576 "frame_", |
|
4577 -1, |
|
4578 -1, |
|
4579 True, |
|
4580 wdata, |
|
4581 defConfig); |
|
4582 |
|
4583 XtAddCallback(wdata->winData.comp.widget, |
|
4584 XmNresizeCallback, |
|
4585 outerCanvasResizeCB, |
|
4586 globalRef); |
|
4587 |
|
4588 |
|
4589 innerCanvasW = XtParent(wdata->winData.comp.widget); |
|
4590 XtVaSetValues(innerCanvasW, |
|
4591 XmNleftAttachment, XmATTACH_FORM, |
|
4592 XmNrightAttachment, XmATTACH_FORM, |
|
4593 NULL); |
|
4594 |
|
4595 |
|
4596 XtAddEventHandler(innerCanvasW, StructureNotifyMask, FALSE, |
|
4597 (XtEventHandler)innerCanvasEH, globalRef); |
|
4598 |
|
4599 /* No menu bar initially */ |
|
4600 wdata->menuBar = NULL; |
|
4601 wdata->mbHeight = 0; |
|
4602 |
|
4603 /* If a warning window (string) is needed, establish it now.*/ |
|
4604 warningString = |
|
4605 (*env)->GetObjectField(env, target, windowIDs.warningString); |
|
4606 |
|
4607 /* No warning window present */ |
|
4608 XtVaSetValues(innerCanvasW, |
|
4609 XmNtopAttachment, XmATTACH_FORM, |
|
4610 XmNbottomAttachment, XmATTACH_FORM, |
|
4611 NULL); |
|
4612 wdata->warningWindow = NULL; |
|
4613 wdata->wwHeight = 0; |
|
4614 |
|
4615 |
|
4616 awt_util_show(wdata->winData.comp.widget); |
|
4617 |
|
4618 AWT_FLUSH_UNLOCK(); |
|
4619 } /* MEmbeddedFramePeer_NEFcreate() */ |
|
4620 |
|
4621 |
|
4622 JNIEXPORT void JNICALL |
|
4623 Java_sun_awt_motif_MEmbeddedFramePeer_pShowImpl(JNIEnv *env, jobject this) |
|
4624 { |
|
4625 struct FrameData *wdata; |
|
4626 |
|
4627 AWT_LOCK(); |
|
4628 |
|
4629 wdata = (struct FrameData *) |
|
4630 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4631 if (wdata == NULL || |
|
4632 wdata->winData.comp.widget == NULL || |
|
4633 wdata->winData.shell == NULL || |
|
4634 wdata->mainWindow == NULL) { |
|
4635 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4636 AWT_UNLOCK(); |
|
4637 return; |
|
4638 } |
|
4639 XtVaSetValues(wdata->winData.comp.widget, |
|
4640 XmNx, -(wdata->left), |
|
4641 XmNy, -(wdata->top), NULL); |
|
4642 |
|
4643 if (wdata->menuBar != 0) { |
|
4644 awt_util_show(wdata->menuBar); |
|
4645 } |
|
4646 |
|
4647 XtManageChild(wdata->mainWindow); |
|
4648 if (XtWindow(wdata->winData.shell) == None) { |
|
4649 XtRealizeWidget(wdata->winData.shell); |
|
4650 } |
|
4651 XtManageChild(wdata->winData.comp.widget); |
|
4652 XtSetMappedWhenManaged(wdata->winData.shell, True); |
|
4653 XtPopup(wdata->winData.shell, XtGrabNone); |
|
4654 wdata->isShowing = True; |
|
4655 |
|
4656 AWT_FLUSH_UNLOCK(); |
|
4657 } |
|
4658 |
|
4659 /* |
|
4660 * Create a local managed widget inside a given X window. |
|
4661 * We allocate a top-level shell and then reparent it into the |
|
4662 * given window id. |
|
4663 * |
|
4664 * This is used to take the X11 window ID that has been passed |
|
4665 * to us by our parent Navigator plugin and return a widget |
|
4666 * that can be used as the base for our Java EmbeddeFrame. |
|
4667 * |
|
4668 * Note that the ordering of the various calls is tricky here as |
|
4669 * we have to cope with the variations between 1.1.3, 1.1.6, |
|
4670 * and 1.2. |
|
4671 */ |
|
4672 JNIEXPORT jlong JNICALL |
|
4673 Java_sun_awt_motif_MEmbeddedFrame_getWidget( |
|
4674 JNIEnv *env, jclass clz, jlong winid) |
|
4675 { |
|
4676 Arg args[40]; |
|
4677 int argc; |
|
4678 Widget w; |
|
4679 Window child, parent; |
|
4680 Visual *visual; |
|
4681 Colormap cmap; |
|
4682 int depth; |
|
4683 int ncolors; |
|
4684 |
|
4685 /* |
|
4686 * Create a top-level shell. Note that we need to use the |
|
4687 * AWT's own awt_display to initialize the widget. If we |
|
4688 * try to create a second X11 display connection the Java |
|
4689 * runtimes get very confused. |
|
4690 */ |
|
4691 AWT_LOCK(); |
|
4692 |
|
4693 argc = 0; |
|
4694 XtSetArg(args[argc], XtNsaveUnder, False); argc++; |
|
4695 XtSetArg(args[argc], XtNallowShellResize, False); argc++; |
|
4696 |
|
4697 /* the awt initialization should be done by now (awt_GraphicsEnv.c) */ |
|
4698 |
|
4699 getAwtData(&depth,&cmap,&visual,&ncolors,NULL); |
|
4700 |
|
4701 XtSetArg(args[argc], XtNvisual, visual); argc++; |
|
4702 XtSetArg(args[argc], XtNdepth, depth); argc++; |
|
4703 XtSetArg(args[argc], XtNcolormap, cmap); argc++; |
|
4704 |
|
4705 XtSetArg(args[argc], XtNwidth, 1); argc++; |
|
4706 XtSetArg(args[argc], XtNheight, 1); argc++; |
|
4707 /* The shell has to have relative coords of O,0? */ |
|
4708 XtSetArg(args[argc], XtNx, 0); argc++; |
|
4709 XtSetArg(args[argc], XtNy, 0); argc++; |
|
4710 |
|
4711 /* The shell widget starts out as a top level widget. |
|
4712 * Without intervention, it will be managed by the window |
|
4713 * manager and will be its own widow. So, until it is reparented, |
|
4714 * we don't map it. |
|
4715 */ |
|
4716 XtSetArg(args[argc], XtNmappedWhenManaged, False); argc++; |
|
4717 |
|
4718 w = XtAppCreateShell("AWTapp","XApplication", |
|
4719 vendorShellWidgetClass, |
|
4720 awt_display, |
|
4721 args, |
|
4722 argc); |
|
4723 XtRealizeWidget(w); |
|
4724 |
|
4725 /* |
|
4726 * Now reparent our new Widget into our Navigator window |
|
4727 */ |
|
4728 parent = (Window) winid; |
|
4729 child = XtWindow(w); |
|
4730 XReparentWindow(awt_display, child, parent, 0, 0); |
|
4731 XFlush(awt_display); |
|
4732 XSync(awt_display, False); |
|
4733 XtVaSetValues(w, XtNx, 0, XtNy, 0, NULL); |
|
4734 XFlush(awt_display); |
|
4735 XSync(awt_display, False); |
|
4736 |
|
4737 AWT_UNLOCK(); |
|
4738 |
|
4739 return (jlong)w; |
|
4740 } |
|
4741 |
|
4742 /* |
|
4743 * Make sure the given widget is mapped. |
|
4744 * |
|
4745 * This isn't necessary on JDK 1.1.5 but is needed on JDK 1.1.4 |
|
4746 */ |
|
4747 JNIEXPORT jint JNICALL |
|
4748 Java_sun_awt_motif_MEmbeddedFrame_mapWidget(JNIEnv *env, jclass clz, jlong widget) |
|
4749 { |
|
4750 Widget w = (Widget)widget; |
|
4751 /* |
|
4752 * this is what JDK 1.1.5 does in MFramePeer.pShow. |
|
4753 */ |
|
4754 AWT_LOCK(); |
|
4755 XtSetMappedWhenManaged(w, True); |
|
4756 XtPopup(w, XtGrabNone); |
|
4757 AWT_UNLOCK(); |
|
4758 return (jint) 1; |
|
4759 } |
|
4760 |
|
4761 |
|
4762 JNIEXPORT jboolean JNICALL |
|
4763 Java_sun_awt_motif_MEmbeddedFramePeer_isXEmbedActive(JNIEnv *env, jobject this) |
|
4764 { |
|
4765 struct FrameData *wdata; |
|
4766 Boolean res; |
|
4767 |
|
4768 AWT_LOCK(); |
|
4769 |
|
4770 wdata = (struct FrameData *) |
|
4771 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4772 if (wdata == NULL || |
|
4773 wdata->winData.comp.widget == NULL || |
|
4774 wdata->winData.shell == NULL || |
|
4775 wdata->mainWindow == NULL) { |
|
4776 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4777 AWT_UNLOCK(); |
|
4778 return False; |
|
4779 } |
|
4780 |
|
4781 res = isXEmbedActive(wdata); |
|
4782 AWT_UNLOCK(); |
|
4783 return res; |
|
4784 |
|
4785 } |
|
4786 |
|
4787 JNIEXPORT jboolean JNICALL |
|
4788 Java_sun_awt_motif_MEmbeddedFramePeer_isXEmbedApplicationActive(JNIEnv *env, jobject this) |
|
4789 { |
|
4790 struct FrameData *wdata; |
|
4791 Boolean res; |
|
4792 |
|
4793 AWT_LOCK(); |
|
4794 |
|
4795 wdata = (struct FrameData *) |
|
4796 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4797 if (wdata == NULL || |
|
4798 wdata->winData.comp.widget == NULL || |
|
4799 wdata->winData.shell == NULL || |
|
4800 wdata->mainWindow == NULL) { |
|
4801 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4802 AWT_UNLOCK(); |
|
4803 return False; |
|
4804 } |
|
4805 |
|
4806 res = isXEmbedApplicationActive(wdata); |
|
4807 AWT_UNLOCK(); |
|
4808 return res; |
|
4809 |
|
4810 } |
|
4811 |
|
4812 JNIEXPORT void JNICALL |
|
4813 Java_sun_awt_motif_MEmbeddedFramePeer_requestXEmbedFocus(JNIEnv *env, jobject this) |
|
4814 { |
|
4815 struct FrameData *wdata; |
|
4816 |
|
4817 AWT_LOCK(); |
|
4818 |
|
4819 wdata = (struct FrameData *) |
|
4820 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4821 if (wdata == NULL || |
|
4822 wdata->winData.comp.widget == NULL || |
|
4823 wdata->winData.shell == NULL || |
|
4824 wdata->mainWindow == NULL) { |
|
4825 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4826 AWT_UNLOCK(); |
|
4827 return; |
|
4828 } |
|
4829 |
|
4830 requestXEmbedFocus(wdata); |
|
4831 AWT_UNLOCK(); |
|
4832 } |
|
4833 |
|
4834 /* |
|
4835 * Class: sun_awt_motif_MWindowPeer |
|
4836 * Method: setSaveUnder |
|
4837 * Signature: (Z)V |
|
4838 */ |
|
4839 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_setSaveUnder |
|
4840 (JNIEnv *env, jobject this, jboolean state) |
|
4841 { |
|
4842 struct FrameData *wdata; |
|
4843 jobject target; |
|
4844 |
|
4845 AWT_LOCK(); |
|
4846 |
|
4847 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
4848 |
|
4849 wdata = (struct FrameData *) |
|
4850 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4851 |
|
4852 if (wdata == NULL || |
|
4853 wdata->winData.comp.widget == NULL || |
|
4854 wdata->winData.shell == NULL || |
|
4855 JNU_IsNull(env, target)) { |
|
4856 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4857 if (!JNU_IsNull(env, target)) |
|
4858 (*env)->DeleteLocalRef(env, target); |
|
4859 AWT_UNLOCK(); |
|
4860 return; |
|
4861 } |
|
4862 |
|
4863 XtVaSetValues(wdata->winData.shell, XmNsaveUnder, state, NULL); |
|
4864 |
|
4865 AWT_FLUSH_UNLOCK(); |
|
4866 } |
|
4867 |
|
4868 |
|
4869 /* |
|
4870 * Class: sun_awt_motif_MWindowPeer |
|
4871 * Method: setFocusableWindow |
|
4872 * Signature: (Z)V |
|
4873 */ |
|
4874 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_setFocusableWindow |
|
4875 (JNIEnv *env, jobject this, jboolean isFocusableWindow) |
|
4876 { |
|
4877 struct FrameData *wdata; |
|
4878 jobject target; |
|
4879 |
|
4880 AWT_LOCK(); |
|
4881 |
|
4882 target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
|
4883 |
|
4884 wdata = (struct FrameData *) |
|
4885 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
4886 |
|
4887 if (wdata == NULL || |
|
4888 wdata->winData.comp.widget == NULL || |
|
4889 wdata->winData.shell == NULL || |
|
4890 JNU_IsNull(env, target)) { |
|
4891 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4892 if (!JNU_IsNull(env, target)) |
|
4893 (*env)->DeleteLocalRef(env, target); |
|
4894 AWT_UNLOCK(); |
|
4895 return; |
|
4896 } |
|
4897 |
|
4898 wdata->isFocusableWindow = isFocusableWindow; |
|
4899 |
|
4900 AWT_FLUSH_UNLOCK(); |
|
4901 } |
|
4902 |
|
4903 /* |
|
4904 * Class: sun_awt_motif_MWindowPeer |
|
4905 * Method: resetTargetGC |
|
4906 * Signature: ()V |
|
4907 */ |
|
4908 JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_resetTargetGC |
|
4909 (JNIEnv * env, jobject this, jobject target) |
|
4910 { |
|
4911 (*env)->CallVoidMethod(env, target, windowIDs.resetGCMID); |
|
4912 } |
|
4913 |
|
4914 |
|
4915 /* |
|
4916 * Old, compatibility, backdoor for DT. This is a different |
|
4917 * implementation. It keeps the signature, but acts on |
|
4918 * awt_root_shell, not the frame passed as an argument. Note, that |
|
4919 * the code that uses the old backdoor doesn't work correctly with |
|
4920 * gnome session proxy that checks for WM_COMMAND when the window is |
|
4921 * firts mapped, because DT code calls this old backdoor *after* the |
|
4922 * frame is shown or it would get NPE with old AWT (previous |
|
4923 * implementation of this backdoor) otherwise. Old style session |
|
4924 * managers (e.g. CDE) that check WM_COMMAND only during session |
|
4925 * checkpoint should work fine, though. |
|
4926 * |
|
4927 * NB: The function name looks deceptively like a JNI native method |
|
4928 * name. It's not! It's just a plain function. |
|
4929 */ |
|
4930 JNIEXPORT void JNICALL |
|
4931 Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this, |
|
4932 jobject frame, jstring jcommand) |
|
4933 { |
|
4934 const char *command; |
|
4935 XTextProperty text_prop; |
|
4936 char *c[1]; |
|
4937 int32_t status; |
|
4938 |
|
4939 AWT_LOCK(); |
|
4940 |
|
4941 if (awt_root_shell == NULL) { |
|
4942 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4943 AWT_UNLOCK(); |
|
4944 return; |
|
4945 } |
|
4946 |
|
4947 if (XtWindow(awt_root_shell) == None) { |
|
4948 JNU_ThrowNullPointerException(env, "NullPointerException"); |
|
4949 AWT_UNLOCK(); |
|
4950 return; |
|
4951 } |
|
4952 |
|
4953 /* need to convert ctitle to CompoundText */ |
|
4954 command = (char *) JNU_GetStringPlatformChars(env, jcommand, NULL); |
|
4955 c[0] = (char *)command; |
|
4956 status = XmbTextListToTextProperty(awt_display, c, 1, |
|
4957 XStdICCTextStyle, &text_prop); |
|
4958 |
|
4959 if (status == Success || status > 0) { |
|
4960 XSetTextProperty(awt_display, XtWindow(awt_root_shell), |
|
4961 &text_prop, XA_WM_COMMAND); |
|
4962 if (text_prop.value != NULL) |
|
4963 XFree(text_prop.value); |
|
4964 } |
|
4965 |
|
4966 JNU_ReleaseStringPlatformChars(env, jcommand, command); |
|
4967 |
|
4968 AWT_UNLOCK(); |
|
4969 return; |
|
4970 } |
|
4971 |
|
4972 |
|
4973 /* |
|
4974 * New DT backdoor to set WM_COMMAND. New code should use this |
|
4975 * backdoor and call it *before* the first frame is shown so that |
|
4976 * gnome session proxy can correctly handle it. |
|
4977 * |
|
4978 * NB: The function name looks deceptively like a JNI native method |
|
4979 * name. It's not! It's just a plain function. |
|
4980 */ |
|
4981 JNIEXPORT void JNICALL |
|
4982 Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jargv) |
|
4983 { |
|
4984 static const char empty[] = ""; |
|
4985 |
|
4986 int argc; |
|
4987 const char **cargv; |
|
4988 XTextProperty text_prop; |
|
4989 int status; |
|
4990 int i; |
|
4991 |
|
4992 AWT_LOCK(); |
|
4993 |
|
4994 if (awt_root_shell == NULL) { |
|
4995 JNU_ThrowNullPointerException(env, "AWT root shell"); |
|
4996 AWT_UNLOCK(); |
|
4997 return; |
|
4998 } |
|
4999 |
|
5000 if (XtWindow(awt_root_shell) == None) { |
|
5001 JNU_ThrowNullPointerException(env, "AWT root shell is unrealized"); |
|
5002 AWT_UNLOCK(); |
|
5003 return; |
|
5004 } |
|
5005 |
|
5006 argc = (int)(*env)->GetArrayLength(env, jargv); |
|
5007 if (argc == 0) { |
|
5008 /* nothing to do */ |
|
5009 AWT_UNLOCK(); |
|
5010 return; |
|
5011 } |
|
5012 |
|
5013 /* array of C strings */ |
|
5014 cargv = (const char **)calloc(argc, sizeof(char *)); |
|
5015 if (cargv == NULL) { |
|
5016 JNU_ThrowOutOfMemoryError(env, "Unable to allocate cargv"); |
|
5017 AWT_UNLOCK(); |
|
5018 return; |
|
5019 } |
|
5020 |
|
5021 /* fill C array with platform chars of java strings */ |
|
5022 for (i = 0; i < argc; ++i) { |
|
5023 jstring js; |
|
5024 const char *cs; |
|
5025 |
|
5026 cs = NULL; |
|
5027 js = (*env)->GetObjectArrayElement(env, jargv, i); |
|
5028 if (js != NULL) { |
|
5029 cs = JNU_GetStringPlatformChars(env, js, NULL); |
|
5030 } |
|
5031 if (cs == NULL) { |
|
5032 cs = empty; |
|
5033 } |
|
5034 |
|
5035 cargv[i] = cs; |
|
5036 (*env)->DeleteLocalRef(env, js); |
|
5037 } |
|
5038 |
|
5039 /* grr, X prototype doesn't declare cargv as const, thought it really is */ |
|
5040 status = XmbTextListToTextProperty(awt_display, (char **)cargv, argc, |
|
5041 XStdICCTextStyle, &text_prop); |
|
5042 if (status < 0) { |
|
5043 switch (status) { |
|
5044 case XNoMemory: |
|
5045 JNU_ThrowOutOfMemoryError(env, |
|
5046 "XmbTextListToTextProperty: XNoMemory"); |
|
5047 break; |
|
5048 case XLocaleNotSupported: |
|
5049 JNU_ThrowInternalError(env, |
|
5050 "XmbTextListToTextProperty: XLocaleNotSupported"); |
|
5051 break; |
|
5052 case XConverterNotFound: |
|
5053 JNU_ThrowNullPointerException(env, |
|
5054 "XmbTextListToTextProperty: XConverterNotFound"); |
|
5055 break; |
|
5056 default: |
|
5057 JNU_ThrowInternalError(env, |
|
5058 "XmbTextListToTextProperty: unknown error"); |
|
5059 } |
|
5060 } else { |
|
5061 /* |
|
5062 * status == Success (i.e. 0) or |
|
5063 * status > 0 - a number of unconvertible characters |
|
5064 * (cannot happen for XStdICCTextStyle). |
|
5065 */ |
|
5066 XSetTextProperty(awt_display, XtWindow(awt_root_shell), |
|
5067 &text_prop, XA_WM_COMMAND); |
|
5068 } |
|
5069 |
|
5070 /* release platform chars */ |
|
5071 for (i = 0; i < argc; ++i) { |
|
5072 jstring js; |
|
5073 |
|
5074 if (cargv[i] == empty) |
|
5075 continue; |
|
5076 |
|
5077 js = (*env)->GetObjectArrayElement(env, jargv, i); |
|
5078 JNU_ReleaseStringPlatformChars(env, js, cargv[i]); |
|
5079 (*env)->DeleteLocalRef(env, js); |
|
5080 } |
|
5081 if (text_prop.value != NULL) |
|
5082 XFree(text_prop.value); |
|
5083 |
|
5084 AWT_UNLOCK(); |
|
5085 return; |
|
5086 } |
|
5087 |
|
5088 /* |
|
5089 * Class: java_awt_TrayIcon |
|
5090 * Method: initIDs |
|
5091 * Signature: ()V |
|
5092 */ |
|
5093 JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs(JNIEnv *env , jclass clazz) |
|
5094 { |
|
5095 } |
|