blob: 165c1cfa56210376e79a64be0674fee0d7608844 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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__
90void 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
100static void reshape(JNIEnv *env, jobject this, struct FrameData *wdata,
101 jint x, jint y, jint w, jint h, Boolean setXY);
102Widget findTopLevelByShell(Widget widget);
103
104extern EmbeddedFrame *theEmbeddedFrameList;
105extern struct ComponentIDs componentIDs;
106extern struct MMenuBarPeerIDs mMenuBarPeerIDs;
107extern struct MComponentPeerIDs mComponentPeerIDs;
108struct WindowIDs windowIDs;
109struct MWindowPeerIDs mWindowPeerIDs;
110extern struct InsetsIDs insetsIDs;
111extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
112extern struct KeyboardFocusManagerIDs keyboardFocusManagerIDs;
113extern struct X11GraphicsDeviceIDs x11GraphicsDeviceIDs;
114
115#ifndef NOMODALFIX
116extern Boolean awt_isModal();
117extern Boolean awt_isWidgetModal(Widget w);
118extern void awt_shellPoppedUp(Widget shell, XtPointer c, XtPointer d);
119extern void awt_shellPoppedDown(Widget shell, XtPointer c, XtPointer d);
120#endif //NOMODALFIX
121
122static jclass inputMethodWindowClass = NULL;
123
124static int32_t globalTopGuess = 0;
125static int32_t globalLeftGuess = 0;
126static int32_t globalBottomGuess = 0;
127static int32_t globalRightGuess = 0;
128
129
130// Atom used for otlogenniy top-level disposal
131static 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 */
139struct FrameDataList {
140 struct FrameData* wdata;
141 struct FrameDataList* next;
142};
143
144static struct FrameDataList* allTopLevel = NULL;
145
146extern 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.
153Boolean 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
183Boolean 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
207Widget 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.
218Boolean 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 */
229void 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 */
242Boolean 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
256Boolean 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 */
264Widget 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
281Widget 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
291Widget 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
301void
302awt_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 */
378static struct FrameDataList* allInputMethodWindow = NULL;
379
380/*
381 * Add a new element into the input method window list
382 */
383void 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 */
396Boolean 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
410Boolean removeInputMethodWindow(struct FrameData* wdata) {
411 return removeInputMethodWindowR(&allInputMethodWindow, wdata);
412}
413
414/*
415 * Raise input method windows
416 */
417void 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 */
431static 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 */
444JNIEXPORT void JNICALL
445Java_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 */
456static struct DialogIDs {
457 jfieldID modal;
458 jfieldID resizable;
459} dialogIDs;
460
461JNIEXPORT void JNICALL
462Java_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
475JNIEXPORT void JNICALL
476Java_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
497static struct MWindowAttributeIDs {
498 jfieldID nativeDecor;
499 jfieldID initialFocus;
500 jfieldID isResizable;
501 jfieldID initialState;
502 jfieldID visibilityState;
503 jfieldID decorations;
504} mWindowAttributeIDs;
505
506JNIEXPORT void JNICALL
507Java_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
533JNIEXPORT void JNICALL
534Java_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
591JNIEXPORT jobject JNICALL
592Java_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
601extern jobject findTopLevelOpposite();
602
603/*
604 * Class: sun_awt_motif_MWindowPeer
605 * Method: findOpposite
606 * Signature: (Ljava/awt/AWTEvent;)Ljava/awt/Window;
607 */
608
609JNIEXPORT jobject JNICALL
610Java_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
626static void
627awtJNI_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
681static void
682awtJNI_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
790fprintf(stdout," setMenuBar.... ****************************************\n");
791fflush(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*/
828static void
829outerCanvasResizeCB(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
923static 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
985static void
986innerCanvasEH(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 */
1031void 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
1058typedef 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
1070int 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
1097void
1098shellFocusEH(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 */
1136Boolean skipNextNotifyWhileGrabbed = False;
1137Boolean skipNextFocusIn = False;
1138
1139Boolean 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*/
1147void
1148shellEH(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
2183static void
2184Frame_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
2198static void
2199setDeleteCallback(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
2222extern AwtGraphicsConfigDataPtr
2223copyGraphicsConfigToPeer(JNIEnv *env, jobject this);
2224
2225extern AwtGraphicsConfigDataPtr
2226getGraphicsConfigFromComponentPeer(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.
2231Boolean 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
2249extern Widget grabbed_widget;
2250/**
2251 * Disposes top-level component and its widgets
2252 */
2253static
2254void 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 */
2350static void
2351shellDisposeNotifyHandler(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 */
2378static
2379void 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 */
2410static char* focusProxyName = "FocusProxy";
2411
2412Widget 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 */
2457JNIEXPORT void JNICALL
2458Java_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 */
2857JNIEXPORT void JNICALL
2858Java_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 */
2936JNIEXPORT void JNICALL
2937Java_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 */
2988JNIEXPORT void JNICALL
2989Java_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 */
2999JNIEXPORT void JNICALL
3000Java_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 */
3167JNIEXPORT jint JNICALL
3168Java_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 */
3194JNIEXPORT void JNICALL
3195Java_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 */
3269JNIEXPORT void JNICALL
3270Java_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 */
3329JNIEXPORT void JNICALL
3330Java_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 */
3374JNIEXPORT void JNICALL
3375Java_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
3398static void
3399reshape(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 */
3597JNIEXPORT 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 */
3640JNIEXPORT 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 */
3667JNIEXPORT 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 */
3823JNIEXPORT 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 */
3982JNIEXPORT void JNICALL
3983Java_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 */
4071JNIEXPORT 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 */
4230JNIEXPORT 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 */
4256JNIEXPORT 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
4267JNIEXPORT 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
4306JNIEXPORT 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
4351static Atom java_protocol = None;
4352static Atom motif_wm_msgs = None;
4353
4354static 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
4363JNIEXPORT 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
4404JNIEXPORT void JNICALL
4405Java_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
4431JNIEXPORT void JNICALL
4432Java_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
4458JNIEXPORT void JNICALL
4459Java_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
4622JNIEXPORT void JNICALL
4623Java_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 */
4672JNIEXPORT jlong JNICALL
4673Java_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 */
4747JNIEXPORT jint JNICALL
4748Java_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
4762JNIEXPORT jboolean JNICALL
4763Java_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
4787JNIEXPORT jboolean JNICALL
4788Java_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
4812JNIEXPORT void JNICALL
4813Java_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 */
4839JNIEXPORT 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 */
4874JNIEXPORT 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 */
4908JNIEXPORT 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 */
4930JNIEXPORT void JNICALL
4931Java_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 */
4981JNIEXPORT void JNICALL
4982Java_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 */
5093JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs(JNIEnv *env , jclass clazz)
5094{
5095}