| /* |
| * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| |
| #ifdef HEADLESS |
| #error This file should not be included in headless library |
| #endif |
| |
| #include "awt_p.h" |
| |
| #include <X11/Shell.h> |
| #include <Xm/VendorS.h> |
| #include <Xm/Form.h> |
| #include <Xm/DialogS.h> |
| #include <Xm/AtomMgr.h> |
| #include <Xm/Protocols.h> |
| #include <Xm/MenuShell.h> |
| #include <Xm/MwmUtil.h> |
| #include "VDrawingArea.h" |
| |
| #ifdef DEBUG |
| # include <X11/Xmu/Editres.h> |
| #endif |
| |
| #include <jni.h> |
| #include <jni_util.h> |
| |
| /* JNI headers */ |
| #include "java_awt_Color.h" |
| #include "java_awt_Component.h" |
| #include "java_awt_Dialog.h" |
| #include "java_awt_Font.h" |
| #include "java_awt_Frame.h" |
| #include "java_awt_Image.h" |
| #include "java_awt_Insets.h" |
| #include "java_awt_Insets.h" |
| #include "java_awt_MenuBar.h" |
| #include "java_awt_Window.h" |
| #include "java_awt_event_FocusEvent.h" |
| #include "java_awt_TrayIcon.h" |
| #include "sun_awt_EmbeddedFrame.h" |
| #include "sun_awt_motif_MComponentPeer.h" |
| #include "sun_awt_motif_MDialogPeer.h" |
| #include "sun_awt_motif_MEmbeddedFramePeer.h" |
| #include "sun_awt_motif_MFramePeer.h" |
| #include "sun_awt_motif_MMenuBarPeer.h" |
| #include "sun_awt_motif_MWindowPeer.h" |
| |
| /* JNI field and method ids */ |
| #include "awt_Component.h" |
| #include "awt_GraphicsEnv.h" |
| #include "awt_Insets.h" |
| #include "awt_MenuBar.h" |
| #include "awt_Window.h" |
| #include "awt_KeyboardFocusManager.h" |
| #include "awt_MToolkit.h" |
| #include "awt_Plugin.h" |
| |
| #include "color.h" |
| #include "canvas.h" |
| #include "awt_util.h" |
| #include "img_util.h" |
| #include "awt_wm.h" |
| #include "awt_util.h" |
| #include "awt_xembed.h" |
| |
| |
| #ifdef __linux__ |
| void adjustStatusWindow(Widget shell); |
| #endif |
| /* For the moment only InputMethodWindow is taking advantage of |
| ** the posibility for different decor styles |
| ** values could be passed are the MWM_DECOR defines |
| ** for the moment we are full on or full off. |
| */ |
| #define AWT_NO_DECOR 0x0 |
| #define AWT_FULL_DECOR MWM_DECOR_ALL |
| |
| static void reshape(JNIEnv *env, jobject this, struct FrameData *wdata, |
| jint x, jint y, jint w, jint h, Boolean setXY); |
| Widget findTopLevelByShell(Widget widget); |
| |
| extern EmbeddedFrame *theEmbeddedFrameList; |
| extern struct ComponentIDs componentIDs; |
| extern struct MMenuBarPeerIDs mMenuBarPeerIDs; |
| extern struct MComponentPeerIDs mComponentPeerIDs; |
| struct WindowIDs windowIDs; |
| struct MWindowPeerIDs mWindowPeerIDs; |
| extern struct InsetsIDs insetsIDs; |
| extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs; |
| extern struct KeyboardFocusManagerIDs keyboardFocusManagerIDs; |
| extern struct X11GraphicsDeviceIDs x11GraphicsDeviceIDs; |
| |
| #ifndef NOMODALFIX |
| extern Boolean awt_isModal(); |
| extern Boolean awt_isWidgetModal(Widget w); |
| extern void awt_shellPoppedUp(Widget shell, XtPointer c, XtPointer d); |
| extern void awt_shellPoppedDown(Widget shell, XtPointer c, XtPointer d); |
| #endif //NOMODALFIX |
| |
| static jclass inputMethodWindowClass = NULL; |
| |
| static int32_t globalTopGuess = 0; |
| static int32_t globalLeftGuess = 0; |
| static int32_t globalBottomGuess = 0; |
| static int32_t globalRightGuess = 0; |
| |
| |
| // Atom used for otlogenniy top-level disposal |
| static Atom _XA_JAVA_DISPOSE_PROPERTY_ATOM = 0; |
| |
| /* |
| * Fix for bug 4141361 |
| * |
| * We keep a linked list of the FrameData information for |
| * every top level window. |
| */ |
| struct FrameDataList { |
| struct FrameData* wdata; |
| struct FrameDataList* next; |
| }; |
| |
| static struct FrameDataList* allTopLevel = NULL; |
| |
| extern void checkNewXineramaScreen(JNIEnv* env, jobject peer, |
| struct FrameData* wdata, |
| int32_t newX, int32_t newY, |
| int32_t newWidth, int32_t newHeight); |
| |
| // Returns false if this Window is non-focusable |
| // or its nearest decorated parent is non-focusable. |
| Boolean isFocusableWindowByPeer(JNIEnv * env, jobject peer) { |
| jobject target, decoratedParent; |
| struct FrameData *wdata; |
| Boolean focusable; |
| |
| wdata = (struct FrameData *)JNU_GetLongFieldAsPtr(env, peer, mComponentPeerIDs.pData); |
| DASSERT(wdata != NULL); |
| |
| target = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target); |
| DASSERT(target != NULL); |
| |
| decoratedParent = getOwningFrameOrDialog(target, env); |
| (*env)->DeleteLocalRef(env, target); |
| |
| if (decoratedParent == NULL) { |
| return wdata->isFocusableWindow; |
| } else { |
| jobject parentPeer = (*env)->GetObjectField(env, decoratedParent, componentIDs.peer); |
| DASSERT(parentPeer != NULL); |
| focusable = wdata->isFocusableWindow && isFocusableWindowByPeer(env, parentPeer); |
| |
| (*env)->DeleteLocalRef(env, decoratedParent); |
| (*env)->DeleteLocalRef(env, parentPeer); |
| } |
| return focusable; |
| } |
| |
| // Returns false if this shell's Java Window is non-focusable |
| // or its nearest decorated parent is non-focusable. |
| // Returns true otherwise or if any of parameters is NULL |
| Boolean isFocusableWindowByShell(JNIEnv* env, Widget shell) { |
| Widget toplevel; |
| jobject peer; |
| Boolean focusable; |
| |
| DASSERT(shell != NULL && XtIsShell(shell)); |
| if (shell == NULL) return True; |
| if (!XtIsShell(shell)) return True; |
| |
| toplevel = findTopLevelByShell(shell); |
| if (toplevel == NULL) { |
| return True; |
| } |
| peer = findPeer(&toplevel); |
| DASSERT(peer != NULL); |
| |
| if (env == NULL) { |
| env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| } |
| return isFocusableWindowByPeer(env, peer); |
| } |
| |
| |
| // Returns Shell widget - the parent of this child |
| Widget getShellWidget(Widget child) { |
| |
| while (child != NULL && !XtIsShell(child)) { |
| child = XtParent(child); |
| } |
| return child; |
| } |
| |
| // Returns false if the parent shell of this widget is non-focusable Java Window. |
| // Returns false otherwise. |
| // Doesn't accept NULL parameters. |
| Boolean isFocusableComponentTopLevelByWidget(JNIEnv * env, Widget child) { |
| Widget shell = NULL; |
| shell = getShellWidget(child); |
| DASSERT(shell); |
| return isFocusableWindowByShell(env, shell); |
| } |
| |
| |
| /* |
| * Add a new element into the top level window list |
| */ |
| void addTopLevel(struct FrameData* wdata) { |
| struct FrameDataList* newNode; |
| newNode = (struct FrameDataList*) |
| malloc(sizeof(struct FrameDataList)); |
| newNode->wdata = wdata; |
| newNode->next = allTopLevel; |
| allTopLevel = newNode; |
| } |
| |
| /* |
| * Remove an element from the top level window list |
| * (recursive) |
| */ |
| Boolean removeTopLevelR(struct FrameDataList** ptr, |
| struct FrameData* wdata) { |
| struct FrameDataList* node = *ptr; |
| if (node == NULL) { |
| return False; |
| } |
| if (node->wdata == wdata) { |
| *ptr = node->next; |
| free(node); |
| return True; |
| } |
| return removeTopLevelR(&(node->next), wdata); |
| } |
| |
| Boolean removeTopLevel(struct FrameData* wdata) { |
| return removeTopLevelR(&allTopLevel, wdata); |
| } |
| |
| /* |
| * Return the Widget ID of the top level window underneath the |
| * mouse pointer. |
| */ |
| Widget awt_GetWidgetAtPointer() { |
| struct FrameDataList* ptr = allTopLevel; |
| Window rootWindow, childWindow, mainWindow; |
| int32_t xw, yw, xr, yr; |
| uint32_t keys; |
| while (ptr != NULL) { |
| mainWindow = XtWindow(ptr->wdata->mainWindow); |
| XQueryPointer(awt_display, mainWindow, |
| &rootWindow, &childWindow, &xr, &yr, &xw, &yw, &keys); |
| if (childWindow != None) { |
| return ptr->wdata->winData.comp.widget; |
| } |
| ptr = ptr->next; |
| } |
| return NULL; |
| } |
| |
| Widget findFocusProxy(Widget widget) { |
| struct FrameDataList* ptr = allTopLevel; |
| for (ptr = allTopLevel; ptr != NULL; ptr = ptr->next) { |
| if (ptr->wdata->winData.comp.widget == widget) { |
| return ptr->wdata->focusProxy; |
| } |
| } |
| return NULL; |
| } |
| |
| Widget findTopLevelByShell(Widget widget) { |
| struct FrameDataList* ptr; |
| for (ptr = allTopLevel; ptr != NULL; ptr = ptr->next) { |
| if (ptr->wdata->winData.shell == widget) { |
| return ptr->wdata->winData.comp.widget; |
| } |
| } |
| return NULL; |
| } |
| |
| void |
| awt_Frame_guessInsets(struct FrameData *wdata) |
| { |
| if (wdata->decor == AWT_NO_DECOR ) { |
| wdata->top = wdata->topGuess = 0; |
| wdata->left = wdata->leftGuess = 0; |
| wdata->bottom = wdata->bottomGuess = 0; |
| wdata->right = wdata->rightGuess = 0; |
| return; |
| } |
| |
| if (globalTopGuess == 0) { |
| char *insets_env; |
| |
| if (wdata->top >= 0) { |
| /* insets were set on wdata by System Properties */ |
| globalTopGuess = wdata->top; |
| globalLeftGuess = wdata->left; |
| globalBottomGuess = wdata->bottom; |
| globalRightGuess = wdata->right; |
| } |
| else switch (awt_wm_getRunningWM()) { |
| case ENLIGHTEN_WM: |
| globalTopGuess = 19; |
| globalLeftGuess = 4; |
| globalBottomGuess = 4; |
| globalRightGuess = 4; |
| break; |
| |
| case CDE_WM: |
| globalTopGuess = 28; |
| globalLeftGuess = 6; |
| globalBottomGuess = 6; |
| globalRightGuess = 6; |
| break; |
| |
| case MOTIF_WM: |
| case OPENLOOK_WM: |
| default: |
| globalTopGuess = 25; |
| globalLeftGuess = 5; |
| globalBottomGuess = 5; |
| globalRightGuess = 5; |
| break; |
| } |
| |
| if ((insets_env = getenv("AWT_INSETS")) != NULL) { |
| int guess = atoi(insets_env); |
| globalTopGuess = (guess & 0xff00) >> 8; |
| globalLeftGuess = guess & 0x00ff; |
| globalBottomGuess = wdata->leftGuess; |
| globalRightGuess = wdata->leftGuess; |
| } |
| |
| /* don't allow bizarly large insets */ |
| if ((globalTopGuess > 64) || (globalTopGuess < 0)) |
| globalTopGuess = 28; |
| if ((globalLeftGuess > 32) || (globalLeftGuess < 0)) |
| globalLeftGuess = 6; |
| if ((globalBottomGuess > 32) || (globalBottomGuess < 0)) |
| globalBottomGuess = 6; |
| if ((globalRightGuess > 32) || (globalRightGuess < 0)) |
| globalRightGuess = 6; |
| } |
| |
| wdata->top = wdata->topGuess = globalTopGuess; |
| wdata->left = wdata->leftGuess = globalLeftGuess; |
| wdata->bottom = wdata->bottomGuess = globalBottomGuess; |
| wdata->right = wdata->rightGuess = globalRightGuess; |
| } |
| |
| /* |
| * To keep input method windows floating, maintain a list of all |
| * input method windows here. When some top level window gets |
| * activated, moved, or resized, these input method windows need |
| * to be brought on top. |
| */ |
| static struct FrameDataList* allInputMethodWindow = NULL; |
| |
| /* |
| * Add a new element into the input method window list |
| */ |
| void addInputMethodWindow(struct FrameData* wdata) { |
| struct FrameDataList* newNode; |
| newNode = (struct FrameDataList*) |
| malloc(sizeof(struct FrameDataList)); |
| newNode->wdata = wdata; |
| newNode->next = allInputMethodWindow; |
| allInputMethodWindow = newNode; |
| } |
| |
| /* |
| * Remove an element from the top level window list |
| * (recursive) |
| */ |
| Boolean removeInputMethodWindowR(struct FrameDataList** ptr, |
| struct FrameData* wdata) { |
| struct FrameDataList* node = *ptr; |
| if (node == NULL) { |
| return False; |
| } |
| if (node->wdata == wdata) { |
| *ptr = node->next; |
| free(node); |
| return True; |
| } |
| return removeInputMethodWindowR(&(node->next), wdata); |
| } |
| |
| Boolean removeInputMethodWindow(struct FrameData* wdata) { |
| return removeInputMethodWindowR(&allInputMethodWindow, wdata); |
| } |
| |
| /* |
| * Raise input method windows |
| */ |
| void raiseInputMethodWindow(struct FrameData* wdata) { |
| struct FrameDataList* node = allInputMethodWindow; |
| |
| if (wdata->isInputMethodWindow) { |
| return; |
| } |
| |
| while (node != NULL) { |
| XRaiseWindow(awt_display, XtWindow(node->wdata->winData.shell)); |
| node = node->next; |
| } |
| } |
| |
| /* fieldIDs for Frame fields that may be accessed from C */ |
| static struct FrameIDs { |
| jfieldID resizable; |
| jfieldID state; |
| } frameIDs; |
| |
| /* |
| * Class: java_awt_Frame |
| * Method: initIDs |
| * Signature: ()V |
| */ |
| |
| /* This function gets called from the static initializer for Frame.java |
| to initialize the fieldIDs for fields that may be accessed from C */ |
| JNIEXPORT void JNICALL |
| Java_java_awt_Frame_initIDs |
| (JNIEnv *env, jclass cls) |
| { |
| frameIDs.resizable = (*env)->GetFieldID(env, cls, "resizable", "Z"); |
| frameIDs.state = (*env)->GetFieldID(env, cls, "state", "I"); |
| } |
| |
| /* ******* */ |
| /* Dialogs */ |
| /* ******* */ |
| /* No longer have a need for unique fields for query */ |
| static struct DialogIDs { |
| jfieldID modal; |
| jfieldID resizable; |
| } dialogIDs; |
| |
| JNIEXPORT void JNICALL |
| Java_java_awt_Dialog_initIDs |
| (JNIEnv *env, jclass cls) |
| { |
| #if 0 |
| dialogIDs.modal = (*env)->GetFieldID(env, cls, "modal", "Z"); |
| dialogIDs.resizable = (*env)->GetFieldID(env, cls, "resizable", "Z"); |
| #endif |
| } |
| |
| /* ******* */ |
| /* Windows */ |
| /* ******* */ |
| |
| JNIEXPORT void JNICALL |
| Java_java_awt_Window_initIDs |
| (JNIEnv *env, jclass cls) |
| { |
| windowIDs.warningString = (*env)->GetFieldID(env, cls, "warningString", |
| "Ljava/lang/String;"); |
| windowIDs.resetGCMID = (*env)->GetMethodID(env, cls, "resetGC", |
| "()V"); |
| |
| windowIDs.locationByPlatform = (*env)->GetFieldID(env, cls, "locationByPlatform", |
| "Z"); |
| windowIDs.isAutoRequestFocus = (*env)->GetFieldID(env, cls, "autoRequestFocus", "Z"); |
| |
| DASSERT(windowIDs.resetGCMID); |
| } |
| |
| /* |
| * Class: sun_motif_awt_WindowAttributes |
| * Method: initIDs |
| * Signature: ()V |
| */ |
| |
| static struct MWindowAttributeIDs { |
| jfieldID nativeDecor; |
| jfieldID initialFocus; |
| jfieldID isResizable; |
| jfieldID initialState; |
| jfieldID visibilityState; |
| jfieldID decorations; |
| } mWindowAttributeIDs; |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowAttributes_initIDs |
| (JNIEnv *env, jclass cls) |
| { |
| mWindowAttributeIDs.nativeDecor = |
| (*env)->GetFieldID(env, cls, "nativeDecor", "Z"); |
| mWindowAttributeIDs.initialFocus = |
| (*env)->GetFieldID(env, cls, "initialFocus", "Z"); |
| mWindowAttributeIDs.isResizable = |
| (*env)->GetFieldID(env, cls, "isResizable", "Z"); |
| mWindowAttributeIDs.initialState = |
| (*env)->GetFieldID(env, cls, "initialState", "I"); |
| mWindowAttributeIDs.visibilityState = |
| (*env)->GetFieldID(env, cls, "visibilityState", "I"); |
| mWindowAttributeIDs.decorations = |
| (*env)->GetFieldID(env, cls, "decorations", "I"); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: initIDs |
| * Signature: ()V |
| */ |
| |
| /* This function gets called from the static initializer for MWindowPeer.java |
| to initialize the fieldIDs for fields that may be accessed from C */ |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_initIDs |
| (JNIEnv *env, jclass cls) |
| { |
| mWindowPeerIDs.insets = |
| (*env)->GetFieldID(env, cls, "insets", "Ljava/awt/Insets;"); |
| mWindowPeerIDs.winAttr = |
| (*env)->GetFieldID( env, |
| cls, |
| "winAttr", |
| "Lsun/awt/motif/MWindowAttributes;" |
| ); |
| mWindowPeerIDs.iconWidth = |
| (*env)->GetFieldID(env, cls, "iconWidth", "I"); |
| mWindowPeerIDs.iconHeight = |
| (*env)->GetFieldID(env, cls, "iconHeight", "I"); |
| mWindowPeerIDs.handleWindowFocusOut = |
| (*env)->GetMethodID(env, |
| cls, |
| "handleWindowFocusOut", |
| "(Ljava/awt/Window;)V"); |
| mWindowPeerIDs.handleWindowFocusIn = |
| (*env)->GetMethodID(env, |
| cls, |
| "handleWindowFocusIn", |
| "()V"); |
| mWindowPeerIDs.handleIconify = |
| (*env)->GetMethodID(env, |
| cls, |
| "handleIconify", |
| "()V"); |
| mWindowPeerIDs.handleDeiconify = |
| (*env)->GetMethodID(env, |
| cls, |
| "handleDeiconify", |
| "()V"); |
| mWindowPeerIDs.handleStateChange = |
| (*env)->GetMethodID(env, |
| cls, |
| "handleStateChange", |
| "(II)V"); |
| |
| mWindowPeerIDs.draggedToScreenMID = (*env)->GetMethodID(env, cls, |
| "draggedToNewScreen", |
| "(I)V"); |
| DASSERT(mWindowPeerIDs.draggedToScreenMID); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: wrapInSequenced |
| * Signature: (Ljava/awt/AWTEvent;)Ljava/awt/SequencedEvent; |
| */ |
| |
| /* This method gets called from MWindowPeer to wrap a FocusEvent in |
| a SequencedEvent. We have to do this in native code, because we |
| don't want to make SequencedEvent a public class. */ |
| |
| JNIEXPORT jobject JNICALL |
| Java_sun_awt_motif_MWindowPeer_wrapInSequenced |
| (JNIEnv *env, jobject this, jobject awtevent) |
| { |
| jobject global = awt_canvas_wrapInSequenced(awtevent); |
| jobject local = (*env)->NewLocalRef(env, global); |
| (*env)->DeleteGlobalRef(env, global); |
| return local; |
| } |
| |
| extern jobject findTopLevelOpposite(); |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: findOpposite |
| * Signature: (Ljava/awt/AWTEvent;)Ljava/awt/Window; |
| */ |
| |
| JNIEXPORT jobject JNICALL |
| Java_sun_awt_motif_MWindowPeer_findOpposite |
| (JNIEnv *env, jobject this, jint eventType) |
| { |
| #ifdef HEADLESS |
| return NULL; |
| #else |
| if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
| return NULL; |
| } |
| |
| return findTopLevelOpposite(env, eventType); |
| #endif |
| } |
| |
| /* changeInsets() sets target's insets equal to X/Motif values. */ |
| |
| static void |
| awtJNI_ChangeInsets(JNIEnv * env, jobject this, struct FrameData *wdata) |
| { |
| jobject insets; |
| |
| if ((*env)->EnsureLocalCapacity(env, 1) < 0) |
| return; |
| |
| insets = (*env)->GetObjectField(env, this, mWindowPeerIDs.insets); |
| |
| if (JNU_IsNull(env, insets)) { |
| return; |
| } |
| |
| (*env)->SetIntField(env, insets, insetsIDs.top, wdata->top); |
| (*env)->SetIntField(env, insets, insetsIDs.left, wdata->left); |
| (*env)->SetIntField(env, insets, insetsIDs.bottom, wdata->bottom); |
| (*env)->SetIntField(env, insets, insetsIDs.right, wdata->right); |
| |
| /* Fix for 4106068: don't do it, rely on the window */ |
| /* manager maximizing policy instead */ |
| #if 0 |
| /* when the insets get set, make sure we set the proper */ |
| /* max window size (since it's dependent on inset size) */ |
| if (wdata->isResizable) { |
| int32_t screenWidth = XWidthOfScreen( XDefaultScreenOfDisplay(awt_display)); |
| int32_t screenHeight= XHeightOfScreen(XDefaultScreenOfDisplay(awt_display)); |
| XtVaSetValues(wdata->winData.shell, |
| XmNmaxWidth, screenWidth - (wdata->left + wdata->right), |
| XmNmaxHeight, screenHeight - (wdata->top + wdata->bottom), |
| NULL); |
| } |
| #endif |
| (*env)->DeleteLocalRef(env, insets); |
| } |
| |
| |
| /* setMbAndWwHeightAndOffsets() attempts to establish the heights |
| of frame's menu bar and warning window (if present in frame). |
| setMbAndWwHeightAndOffsets() also adjusts appropriately the |
| X/Motif offsets and calls changeInsets() to set target insets. |
| A warning window, if present, is established during ...create(). |
| wdata->warningWindow is set there, wdata->wwHeight is set here. |
| Routine pSetMenuBar() sets value of the wdata->menuBar field. |
| This routine reads that value. If it is not null, a menubar |
| has been added. In this case, calculate the current height |
| of the menu bar. This may be a partial (incomplete) menubar |
| because ths routine may be called before the X/Motif menubar |
| is completely realized. In this case, the menubar height may |
| be adjusted incrementally. This routine may be called from |
| ...pSetMenuBar(), innerCanvasEH(), and ...pReshape(). It is |
| designed to (eventually) obtain the correct menubar height. |
| On the other hand, if wdata->menuBar is NULL and the stored |
| menubar height is not zero, then we subtract off the height. */ |
| |
| static void |
| awtJNI_setMbAndWwHeightAndOffsets(JNIEnv * env, |
| jobject this, |
| struct FrameData *wdata ) |
| { |
| Dimension warningHeight, /* Motif warning window height */ |
| labelHeight; /* Motif warning label's height */ |
| |
| WidgetList warningChildrenWL; /* warning children widgets */ |
| |
| Dimension menuBarWidth, /* Motif menubar width */ |
| menuBarHeight, /* Motif menubar height */ |
| menuBarBorderSize, /* Motif menubar border size */ |
| marginHeight, /* Motif menubar margin height */ |
| menuHeight, /* Motif menubar's menu height */ |
| menuBorderSize, /* Motif menu border size */ |
| actualHeight; /* height: menu+margins+borders */ |
| |
| WidgetList menuBarChildrenWL; /* menubar children widgets */ |
| Cardinal numberChildren; /* number of menubar children */ |
| |
| #ifdef _pauly_debug |
| fprintf(stdout," ++ setMenuBar\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| /* If warning window height not yet known, try to get it now. |
| It will be added to top or bottom (iff NETSCAPE) offset. */ |
| if (wdata->warningWindow != NULL) { |
| XtVaGetValues(wdata->warningWindow, |
| XmNheight, &warningHeight, |
| XmNchildren, &warningChildrenWL, |
| XmNnumChildren, &numberChildren, |
| NULL); |
| |
| /* We may be doing this before warning window is realized ! So, |
| check for a child label in the warning. If its height is not |
| yet accounted for in the warning height, then use it here. */ |
| if (numberChildren != 0) { |
| XtVaGetValues(warningChildrenWL[0], |
| XmNheight, &labelHeight, |
| NULL); |
| #ifdef _pauly_debug |
| fprintf(stdout," setMenuBar.... warning label found with height: %d\n", labelHeight); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| if (warningHeight < labelHeight) { |
| #ifdef _pauly_debug |
| fprintf(stdout," setMenuBar.... !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| warningHeight = labelHeight; |
| } |
| } |
| |
| if (wdata->wwHeight < warningHeight) { |
| #ifdef _pauly_debug |
| fprintf(stdout, " setMenuBar.... adding warning height: %d\n", warningHeight); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| #ifdef NETSCAPE |
| wdata->bottom += (warningHeight - wdata->wwHeight); |
| #else |
| wdata->top += (warningHeight - wdata->wwHeight); |
| #endif /* NETSCAPE */ |
| awtJNI_ChangeInsets(env, this, wdata); |
| wdata->wwHeight = warningHeight; |
| } |
| } |
| |
| /* Now we adjust offsets for an added or removed menu bar */ |
| if (wdata->menuBar != NULL) { |
| #ifdef _pauly_debug |
| fprintf(stdout," setMenuBar. menu bar: %x\n", wdata->menuBar); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| XtVaGetValues(wdata->menuBar, |
| XmNwidth, &menuBarWidth, |
| XmNheight, &menuBarHeight, |
| XmNchildren, &menuBarChildrenWL, |
| XmNnumChildren, &numberChildren, |
| XmNborderWidth, &menuBarBorderSize, |
| XmNmarginHeight, &marginHeight, |
| NULL); |
| |
| /* We may be doing this before menu bar is realized ! Hence, |
| check for a menu in the menu bar. If its height is not yet |
| accounted for in the menu bar height, then add it in here. */ |
| if (numberChildren != 0) { |
| XtVaGetValues(menuBarChildrenWL[0], |
| XmNheight, &menuHeight, |
| XmNborderWidth, &menuBorderSize, |
| NULL); |
| #ifdef _pauly_debug |
| fprintf(stdout," setMenuBar.... menu found with height: %d, border: %d, margin: %d, bar border: %d\n", menuHeight, menuBorderSize, marginHeight, menuBarBorderSize); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| /* Calculate real height of menu bar by adding height of its |
| child menu and borders, margins, and the menu bar borders*/ |
| actualHeight = menuHeight + (2 * menuBorderSize) + |
| (2 * marginHeight) + (2 * menuBarBorderSize); |
| #ifdef __linux__ |
| #ifdef _pauly_debug |
| fprintf(stdout," actual height: %d mb height %d\n", actualHeight, menuBarHeight); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| #endif |
| if (menuBarHeight < actualHeight) { |
| #ifdef _pauly_debug |
| fprintf(stdout," setMenuBar.... ****************************************\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| menuBarHeight = actualHeight; |
| } |
| } |
| |
| if (wdata->mbHeight < menuBarHeight) { |
| /* Adjust the (partially) added menu bar height, top offset.*/ |
| #ifdef _pauly_debug |
| fprintf(stdout, " setMenuBar.... added menuBar height: %d\n", menuBarHeight); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| wdata->top += (menuBarHeight - wdata->mbHeight); |
| awtJNI_ChangeInsets(env, this, wdata); |
| wdata->mbHeight = menuBarHeight; |
| } |
| } else if ((wdata->menuBar == NULL) && (wdata->mbHeight > 0)) { |
| /* A menu bar has been removed; subtract height from top offset.*/ |
| wdata->top -= wdata->mbHeight; |
| #ifdef _pauly_debug |
| fprintf(stdout, " setMenuBar.... removed menuBar height: %d\n", wdata->mbHeight); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| awtJNI_ChangeInsets(env, this, wdata); |
| wdata->mbHeight = 0; |
| } |
| } |
| |
| |
| /* outerCanvasResizeCB() is Motif resize callback for outer/child canvas. |
| It reads width, height of Motif widget, sets java target accordingly, |
| and then calls handleResize() to affect any changes. |
| This call is only done for a shell resize or inner/parent resize; |
| i.e., it may not be done for a ...pReshape() to avoid doing a loop. |
| |
| client_data is MWindowPeer instance |
| */ |
| static void |
| outerCanvasResizeCB(Widget wd, XtPointer client_data, XtPointer call_data) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| jobject target; |
| struct FrameData *wdata; |
| Position screenX; /* x position of the canvas, screen */ |
| Position screenY; /* y position of the canvas, screen */ |
| Dimension width; /* width of the canvas, target */ |
| Dimension height; /* height of the canvas, target */ |
| jint oldWidth; |
| jint oldHeight; |
| |
| #ifdef _pauly_debug |
| fprintf(stdout," ++ WindowResize.\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, (jobject) client_data, |
| mComponentPeerIDs.pData); |
| if (wdata == NULL) { |
| return; |
| } |
| |
| if ((*env)->EnsureLocalCapacity(env, 1) < 0) |
| return; |
| |
| target = (*env)->GetObjectField(env, (jobject) client_data, |
| mComponentPeerIDs.target); |
| XtVaGetValues(wd, |
| XmNwidth, &width, |
| XmNheight, &height, |
| NULL); |
| #ifdef _pauly_debug |
| fprintf(stdout," outerCanvasResizeCB. width: %d, height: %d\n", width, height); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| |
| XtTranslateCoords(wd, 0, 0, &screenX, &screenY); |
| |
| if ((wdata->shellResized) || (wdata->canvasResized)) { |
| #ifdef _pauly_debug |
| fprintf(stdout," outerCanvasResizeCB\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| wdata->shellResized = False; |
| wdata->canvasResized = False; |
| /* |
| ** if you are not yet reparented, don't compute the size based on the |
| ** widgets, as the window manager shell containg the insets is not yet |
| ** there. Use the size the application has set. |
| ** If not reparented, we got here because the application set the size, |
| ** so just send them Component.RESIZED event with the size they set. |
| ** |
| ** 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. |
| */ |
| if (wdata->reparented) |
| { |
| (*env)->SetIntField(env, target, componentIDs.x, (jint) screenX); |
| (*env)->SetIntField(env, target, componentIDs.y, (jint) screenY); |
| } |
| |
| oldWidth = (*env)->GetIntField(env, target, componentIDs.width); |
| oldHeight = (*env)->GetIntField(env, target, componentIDs.height); |
| |
| if (oldWidth != width || oldHeight != height || wdata->need_reshape) |
| { |
| wdata->need_reshape = False; |
| (*env)->SetIntField(env, target, componentIDs.width, (jint)width); |
| (*env)->SetIntField(env, target, componentIDs.height, |
| (jint)height); |
| |
| /* only do this for Windows, not Canvases, btw */ |
| checkNewXineramaScreen(env, client_data, wdata, screenX, screenY, width, height); |
| |
| JNU_CallMethodByName(env, NULL, (jobject) client_data, |
| "handleResize", "(II)V", width, height); |
| if ((*env)->ExceptionOccurred(env)) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| } |
| } |
| } |
| |
| (*env)->DeleteLocalRef(env, target); |
| |
| #ifdef _pauly_debug |
| fprintf(stdout," WindowResize. Done.\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| } /* outerCanvasResizeCB() */ |
| |
| static void reconfigureOuterCanvas ( JNIEnv *env, jobject target, |
| jobject this, struct FrameData *wdata ) |
| { |
| Dimension innerDAWidth, /* width of inner Motif canvas */ |
| innerDAHeight, /* height of inner Motif canvas */ |
| outerDAWidth, /* width of outer Motif canvas */ |
| outerDAHeight; /* height of outer Motif canvas */ |
| int32_t targetWidth, /* java target object's width */ |
| targetHeight; /* java target's object height */ |
| Dimension width; /* width of the canvas, target */ |
| Dimension height; /* height of the canvas, target */ |
| |
| |
| Position innerX, /* x loc. of inner Motif canvas */ |
| innerY, /* y loc. of inner Motif canvas */ |
| x, y; |
| |
| /* canvasW is (visible) inner/parent drawing area (canvas) widget */ |
| XtVaGetValues(XtParent(wdata->winData.comp.widget), |
| XmNwidth, &innerDAWidth, |
| XmNheight, &innerDAHeight, |
| XmNx, &innerX, |
| XmNy, &innerY, |
| NULL); |
| |
| /* This resize may be due to the insertion or removal of a menu bar. |
| If so, we appropriately adjust the top offset in wdata, insets. */ |
| awtJNI_setMbAndWwHeightAndOffsets(env, this, wdata); |
| |
| outerDAWidth = innerDAWidth + wdata->left + wdata->right; |
| outerDAHeight = innerDAHeight + wdata->top + wdata->bottom; |
| |
| /* If it's a menu bar reset, do not do resize of outer/child canvas. |
| (Another thread problem; we arrest this now before damage done.) */ |
| if (wdata->menuBarReset) |
| { |
| targetWidth = (*env)->GetIntField(env, target, componentIDs.width); |
| targetHeight = (*env)->GetIntField(env, target, componentIDs.height); |
| if ((outerDAWidth != targetWidth) || (outerDAHeight != targetHeight)) |
| { |
| return; |
| } |
| } |
| |
| wdata->canvasResized = True; |
| |
| /* The outer/child drawing area (canvas) needs to be configured too. |
| If its size changes, its resize callback will thereby be invoked.*/ |
| x = -wdata->left; |
| y = -wdata->top; |
| width = innerDAWidth + wdata->left + wdata->right; |
| height = innerDAHeight + wdata->top + wdata->bottom; |
| |
| XtConfigureWidget(wdata->winData.comp.widget, x, y, width, height, 0 ); |
| } |
| |
| |
| |
| /* innerCanvasEH() is event handler for inner/parent canvas. It handles |
| map and configure notify events. It reads width and height, adjusts |
| for menubar insertion / removal and configures outer/child canvas. */ |
| |
| static void |
| innerCanvasEH(Widget canvasW, XtPointer client_data, XEvent *event, |
| Boolean* continueToDispatch) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| jobject this = (jobject) client_data; |
| jobject target; |
| struct FrameData *wdata; |
| |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL) { |
| return; |
| } |
| |
| if ((*env)->EnsureLocalCapacity(env, 1) < 0) |
| return; |
| |
| target = (*env)->GetObjectField(env, (jobject) client_data, |
| mComponentPeerIDs.target); |
| |
| /* While inside ...pSetMenuBar(), don't react to incomplete resizing |
| events supplied by Xt toolkit. Wait for completion of the routine. */ |
| |
| |
| /* For a map or resize, we need to check for the addition or deletion |
| of a menu bar to the form which is the of this drawing area (canvas). |
| We also must then configure the outer/child canvas appropriately. */ |
| |
| if ( (event->xany.type == MapNotify) || |
| (event->xany.type == ConfigureNotify) ) |
| { |
| reconfigureOuterCanvas( env, target, this, wdata ); |
| } |
| |
| (*env)->DeleteLocalRef(env, target); |
| |
| } |
| |
| /* syncTopLevelPos() is necessary to insure that the window manager has in |
| * fact moved us to our final position relative to the reParented WM window. |
| * We have noted a timing window which our shell has not been moved so we |
| * screw up the insets thinking they are 0,0. Wait (for a limited period of |
| * time to let the WM hava a chance to move us |
| */ |
| void syncTopLevelPos( Display *d, Window w, XWindowAttributes *winAttr ) |
| { |
| int32_t i = 0; |
| memset(winAttr, 0, sizeof(*winAttr)); |
| |
| do { |
| if (!XGetWindowAttributes(d, w, winAttr)) { |
| memset(winAttr, 0, sizeof(*winAttr)); |
| break; |
| } |
| /* Sometimes we get here before the WM has updated the |
| ** window data struct with the correct position. Loop |
| ** until we get a non-zero position. |
| */ |
| if ((winAttr->x != 0) || (winAttr->y != 0)) { |
| break; |
| } |
| else { |
| /* What we really want here is to sync with the WM, |
| ** but there's no explicit way to do this, so we |
| ** call XSync for a delay. |
| */ |
| XSync(d, False); |
| } |
| } while (i++ < 50); |
| } |
| |
| typedef struct FocusOutInfo_str { |
| XEvent * eventOut; |
| Window inWin; |
| Window inChild; |
| Widget defChild; |
| jobject childComp; |
| } FocusOutInfo_t; |
| |
| #define IsCanvasTypeWidget(w) \ |
| (XtIsSubclass(w, xmDrawingAreaWidgetClass) ||\ |
| XtIsSubclass(w, vDrawingAreaClass)) |
| |
| int isTopLevelPartWidget(Widget w) { |
| if (XtIsShell(w)) { |
| return TRUE; |
| } |
| if (XtIsSubclass(w, xmFormWidgetClass)) { |
| return TRUE; |
| } |
| if (IsCanvasTypeWidget(w)) { |
| Widget w1 = XtParent(w); |
| if (w1 != NULL) { |
| if (XtIsSubclass(w1, xmFormWidgetClass)) { |
| return TRUE; |
| } |
| if (IsCanvasTypeWidget(w1)) { |
| Widget w2 = XtParent(w1); |
| if (w2 != NULL) { |
| if (XtIsSubclass(w2, xmFormWidgetClass)) { |
| return TRUE; |
| } |
| } |
| } |
| |
| } |
| } |
| return FALSE; |
| } |
| |
| void |
| shellFocusEH(Widget w, XtPointer data, XEvent *event, Boolean *continueToDispatch) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| jobject this = (jobject) data; |
| jobject target; |
| struct FrameData *wdata; |
| |
| /* Any event handlers which take peer instance pointers as |
| * client_data should check to ensure the widget has not been |
| * marked as destroyed as a result of a dispose() call on the peer |
| * (which can result in the peer instance pointer already haven |
| * been gc'd by the time this event is processed) |
| */ |
| if (w->core.being_destroyed) { |
| return; |
| } |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL) { |
| return; |
| } |
| |
| switch (event->xany.type) { |
| case FocusOut: |
| // Will be handled by proxy automaticall since he is focus owner |
| break; |
| case FocusIn: |
| // Forward focus event to the proxy |
| XSetInputFocus(awt_display, XtWindow(wdata->focusProxy), RevertToParent, CurrentTime); |
| break; |
| } |
| } |
| |
| /** |
| * Fix for Alt-Tab problem. |
| * See coments on use semantics below. |
| */ |
| Boolean skipNextNotifyWhileGrabbed = False; |
| Boolean skipNextFocusIn = False; |
| |
| Boolean focusOnMapNotify = False; |
| |
| /* shellEH() is event handler for the Motif shell widget. It handles |
| focus change, map notify, configure notify events for the shell. |
| Please see internal comments pertaining to these specific events. |
| |
| data is MWindowPeer instance pointer |
| */ |
| void |
| shellEH(Widget w, XtPointer data, XEvent *event, Boolean *continueToDispatch) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| jobject this = (jobject) data; |
| jobject target; |
| struct FrameData *wdata; |
| int32_t setTargetX, |
| setTargetY, |
| getTargetX, |
| getTargetY; |
| /* Changed long to int for 64-bit */ |
| int32_t wwHeight; /* height of any warning window present */ |
| int32_t topAdjust; /* adjust top offset for menu, warning */ |
| jclass clazz; |
| int32_t x, y; |
| int32_t width, height; |
| enum wmgr_t runningWM; |
| jobject winAttrObj; |
| static jobject windowClass = NULL; |
| /* Any event handlers which take peer instance pointers as |
| * client_data should check to ensure the widget has not been |
| * marked as destroyed as a result of a dispose() call on the peer |
| * (which can result in the peer instance pointer already haven |
| * been gc'd by the time this event is processed) |
| */ |
| if (w->core.being_destroyed) { |
| return; |
| } |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL) { |
| return; |
| } |
| |
| switch (event->xany.type) { |
| |
| case FocusOut: { |
| int32_t res = 0; |
| int revert_to = 0; |
| Widget defChild = NULL; |
| Window focusOwner = None; |
| jobject oppositeWindow = NULL; |
| Widget oppositeShell = NULL; |
| XEvent inEvent; |
| Widget shell = NULL; |
| #ifdef DEBUG_FOCUS |
| fprintf(stderr, "Focusout on proxy; window = %x, mode %d, detail %d\n", |
| event->xfocus.window, event->xfocus.mode, event->xfocus.detail); |
| #endif |
| shell = wdata->winData.shell; |
| |
| if ((*env)->EnsureLocalCapacity(env, 3) < 0) { |
| break; |
| } |
| |
| /** |
| * Fix for Alt-Tab problem. We should process NotifyWhileGrabbed events |
| * only if they are due to the switch between top-levels. |
| * skipNextNotifyWhileGrabbed is set from Menu and PopupMenu code |
| * to prevent generation of focus events when user interact with these |
| * widget. |
| */ |
| if (event->xfocus.mode == NotifyWhileGrabbed) { |
| if (skipNextNotifyWhileGrabbed) { |
| skipNextNotifyWhileGrabbed = False; |
| break; |
| } |
| } else if (event->xfocus.mode != NotifyNormal) break; |
| |
| /** |
| * Fix for Alt-Tab problem. |
| * skipNextFocusIn is set in Choice code to avoid processing of |
| * next focus-in or focus-out generated by Choice as it is a fake |
| * event. |
| */ |
| if (skipNextFocusIn && event->xfocus.detail == NotifyPointer) { |
| break; |
| } |
| |
| XGetInputFocus( awt_display, &focusOwner, &revert_to); |
| |
| if (focusOwner != None) { |
| Widget inWidget = NULL; |
| jobject wpeer = NULL; |
| inWidget = XtWindowToWidget(awt_display, focusOwner); |
| if (inWidget != NULL && inWidget != shell) { |
| oppositeShell = getShellWidget(inWidget); |
| wpeer = findPeer(&inWidget); |
| if (wpeer == NULL) { |
| inWidget = findTopLevelByShell(inWidget); |
| if (inWidget != NULL) { |
| wpeer = findPeer(&inWidget); |
| } |
| } |
| if (wpeer != NULL) { |
| jobject peerComp = |
| (*env)->GetObjectField(env, |
| wpeer, |
| mComponentPeerIDs.target); |
| if (peerComp != NULL) { |
| // Check that peerComp is top-level |
| |
| // load class |
| if (windowClass == NULL) { |
| jobject localWindowClass = (*env)->FindClass(env, "java/awt/Window"); |
| windowClass = (*env)->NewGlobalRef(env, localWindowClass); |
| (*env)->DeleteLocalRef(env, localWindowClass); |
| } |
| if ((*env)->IsInstanceOf(env, peerComp, windowClass)) { |
| oppositeWindow = peerComp; |
| } else { // Opposite object is not Window - there is no opposite window. |
| (*env)->DeleteLocalRef(env, peerComp); |
| peerComp = NULL; |
| oppositeShell = NULL; |
| } |
| } |
| } |
| } |
| } else { |
| // If there is no opposite shell but we have active popup - this popup is actually |
| // the oppposite. This should mean that this focus out is due to popup - and thus |
| // should be skipped. Fix for 4478780. |
| if (skipNextNotifyWhileGrabbed) { |
| break; |
| } |
| } |
| |
| // If current window is not focusable and opposite window is not focusable - do nothing |
| // If current window is focusable and opposite is not - do not clear focus variables like |
| // focus didn't leave this window(but it will in terms of X). When we later switch to either |
| // - back to this window: variables are already here |
| // - another focusable window: variables point to focusable window and "focus lost" events |
| // will be generated for it |
| // - non-java window: variables point to focusable window and "focus lost" events |
| // will be generated for it, not for non-focusable. |
| // If current window is non-focusable and opposite is focusable then do not generate anything |
| // as if we didn't leave previous focusable window so Java events will generated for it. |
| // |
| // Fix for 6547951. |
| // Also do cleaning when switching to non-java window (opposite is null). |
| if (isFocusableWindowByShell(env, shell) && shell != oppositeShell && |
| ((oppositeShell != NULL && isFocusableWindowByShell(env, oppositeShell)) || |
| oppositeShell == NULL)) |
| { |
| // The necessary FOCUS_LOST event will be generated by DKFM. |
| // So we need to process focus list like we received FocusOut |
| // for the desired component - shell's current focus widget |
| defChild = XmGetFocusWidget(shell); |
| if (defChild != NULL) { |
| jobject peer = findPeer(&defChild); |
| if (peer == NULL) { |
| defChild = findTopLevelByShell(defChild); |
| if (defChild != NULL) { |
| peer = findPeer(&defChild); |
| } |
| } |
| if (peer != NULL) { |
| jobject comp = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target); |
| if (focusList != NULL) { |
| jobject last = (*env)->NewLocalRef(env, focusList->requestor); |
| if ((*env)->IsSameObject(env, comp, last)) { |
| FocusListElt * temp = focusList; |
| forGained = focusList->requestor; |
| focusList = focusList->next; |
| free(temp); |
| if (focusList == NULL) { |
| focusListEnd = NULL; |
| } |
| } |
| if (!JNU_IsNull(env, last)) { |
| (*env)->DeleteLocalRef(env, last); |
| } |
| } |
| (*env)->DeleteLocalRef(env, comp); |
| } |
| } |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| processTree(defChild, findWindowsProxy(target, env), False); |
| XtSetKeyboardFocus(shell, NULL); |
| (*env)->DeleteLocalRef(env, target); |
| } |
| #ifndef NOMODALFIX |
| if (!awt_isModal() || awt_isWidgetModal(shell)) { |
| #endif //NOMODALFIX |
| if ( oppositeShell != NULL |
| && isFocusableWindowByShell(env, oppositeShell) |
| && isFocusableWindowByShell(env, shell) |
| || (oppositeShell == NULL)) |
| { |
| /* |
| * Fix for 5095117. |
| * Check if current native focused window is the same as source. |
| * Sometimes it is not - we must not however clean reference to |
| * actual native focused window. |
| */ |
| jobject currentFocusedWindow = awt_canvas_getFocusedWindowPeer(); |
| if ((*env)->IsSameObject(env, this, currentFocusedWindow)) { |
| awt_canvas_setFocusedWindowPeer(NULL); |
| } |
| (*env)->DeleteLocalRef(env, currentFocusedWindow); |
| |
| JNU_CallMethodByName(env, NULL, this, "handleWindowFocusOut", "(Ljava/awt/Window;)V", |
| oppositeWindow); |
| if ((*env)->ExceptionCheck(env) == JNI_TRUE) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| } |
| } |
| #ifndef NOMODALFIX |
| } |
| #endif //NOMODALFIX |
| if (oppositeWindow != NULL) { |
| (*env)->DeleteLocalRef(env, oppositeWindow); |
| } |
| |
| break; |
| } /* FocusOut */ |
| |
| case FocusIn: { |
| Widget shell = wdata->winData.shell; |
| #ifdef DEBUG_FOCUS |
| fprintf(stderr, "FocusIn on proxy; window = %x, mode %d, detail %d\n", event->xfocus.window, |
| event->xfocus.mode, event->xfocus.detail); |
| #endif |
| if (/* event->xfocus.mode == NotifyNormal */ 1) { |
| |
| /** |
| * Fix for Alt-Tab problem. We should process NotifyWhileGrabbed events to detect |
| * switch between top-levels using alt-tab, but avoid processing these type of event |
| * when they are originated from other sources. |
| */ |
| if (event->xfocus.mode == NotifyWhileGrabbed) { |
| /** |
| * skipNextNotifyWhileGrabbed is set from Menu and PopupMenu code to |
| * skip next focus-in event with NotifyWhileGrabbed as it is generated |
| * in result of closing of the Menu's shell. |
| * Event will also have NotifyInferior if uses clicked on menu bar in the |
| * space where there is not menu items. |
| */ |
| if (skipNextNotifyWhileGrabbed || event->xfocus.detail == NotifyInferior) { |
| skipNextNotifyWhileGrabbed = False; |
| break; |
| } |
| } else if (event->xfocus.mode != NotifyNormal) { |
| break; |
| } |
| |
| /** |
| * Fix for Alt-Tab problem. |
| * skipNextFocusIn is set from Choice code to avoid processing next focus-in |
| * as it is a fake event. |
| */ |
| if (skipNextFocusIn == True) { |
| /** |
| * There could be the set of fake events, the last one |
| * will have detail == NotifyPointer |
| */ |
| if (event->xfocus.detail != NotifyPointer) { |
| skipNextFocusIn = False; |
| } |
| break; |
| } |
| #ifndef NOMODALFIX |
| if (!awt_isModal() || awt_isWidgetModal(shell)) { |
| #endif //NOMODALFIX |
| if (isFocusableWindowByShell(env, shell)) { |
| jobject currentFocusedWindow = awt_canvas_getFocusedWindowPeer(); |
| // Check if focus variables already point to this window. If so, |
| // it means there were transfer to non-focusable window and now we |
| // are back to origianl focusable window. No need to generate Java events |
| // in this case. |
| if (!(*env)->IsSameObject(env, this, currentFocusedWindow)) { |
| awt_canvas_setFocusedWindowPeer(this); |
| awt_canvas_setFocusOwnerPeer(this); |
| |
| /* |
| * Fix for 6465038. |
| * Restore focus on the toplevel widget if it's broken. |
| */ |
| Widget widgetToFocus = getFocusWidget(findTopLevelByShell(shell)); |
| Widget currentOwner = XmGetFocusWidget(shell); |
| |
| if (widgetToFocus != currentOwner) { |
| #ifdef DEBUG_FOCUS |
| fprintf(stderr, "Wrong Xm focus; resetting Xm focus from %x to toplevel %x...\n", |
| currentOwner != NULL ? XtWindow(currentOwner) : 0, |
| widgetToFocus != NULL ? XtWindow(widgetToFocus) : 0); |
| #endif |
| if ( !XmProcessTraversal(widgetToFocus, XmTRAVERSE_CURRENT) ) { |
| XtSetKeyboardFocus(shell, widgetToFocus); |
| } |
| #ifdef DEBUG_FOCUS |
| Widget _w = XmGetFocusWidget(shell); |
| fprintf(stderr, " ...focus resulted on window %x\n", _w != NULL ? XtWindow(_w) : 0); |
| #endif |
| } |
| |
| JNU_CallMethodByName(env, NULL, this, "handleWindowFocusIn", "()V"); |
| if ((*env)->ExceptionCheck(env) == JNI_TRUE) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| } |
| } |
| (*env)->DeleteLocalRef(env, currentFocusedWindow); |
| } |
| #ifndef NOMODALFIX |
| } |
| #endif //NOMODALFIX |
| } |
| raiseInputMethodWindow(wdata); |
| break; |
| } /* FocusIn */ |
| |
| case VisibilityNotify: { |
| winAttrObj = (*env)->GetObjectField(env, this, mWindowPeerIDs.winAttr); |
| (*env)->SetIntField(env, winAttrObj, |
| mWindowAttributeIDs.visibilityState, |
| event->xvisibility.state); |
| if (event->xvisibility.state == VisibilityUnobscured) { |
| raiseInputMethodWindow(wdata); |
| } |
| break; |
| } /* VisibilityNotify */ |
| |
| case MapNotify: { |
| /* Your body seems to unfade */ |
| if (wdata->initialFocus == False) { |
| XtVaSetValues(wdata->winData.shell, XmNinput, True, NULL); |
| |
| // We have to to evidently move the window to the front here. |
| Window shellWindow; |
| if ((shellWindow = XtWindow(wdata->winData.shell)) != None) { |
| XRaiseWindow(awt_display, shellWindow); |
| } |
| } |
| if (awt_wm_isStateNetHidden(XtWindow(wdata->winData.shell))) { |
| focusOnMapNotify = True; |
| } |
| /* |
| * TODO: perhaps we need this putback only for simple Window. |
| * For Frame/Dialog XmNinput==True would be enough. The native |
| * system will focus it itself. |
| */ |
| if (wdata->isFocusableWindow && focusOnMapNotify) { |
| XEvent ev; |
| memset(&ev, 0, sizeof(ev)); |
| |
| ev.type = FocusIn; |
| ev.xany.send_event = True; |
| ev.xany.display = awt_display; |
| ev.xfocus.mode = NotifyNormal; |
| ev.xfocus.detail = NotifyNonlinear; |
| ev.xfocus.window = XtWindow(wdata->winData.shell); |
| awt_put_back_event(env, &ev); |
| } |
| focusOnMapNotify = False; |
| |
| break; |
| } |
| |
| case UnmapNotify: { |
| /* Gee! All of a sudden, you can't see yourself */ |
| if (wdata->initialFocus == False) { |
| XtVaSetValues(wdata->winData.shell, XmNinput, False, NULL); |
| } |
| if (awt_wm_isStateNetHidden(XtWindow(wdata->winData.shell))) { |
| focusOnMapNotify = True; |
| } |
| break; |
| } |
| |
| case DestroyNotify: { /* Foul play! ICCCM forbids WM to do this! */ |
| /* Your window is killed by the WM */ |
| JNU_CallMethodByName(env, NULL, this, "handleDestroy", "()V"); |
| if ((*env)->ExceptionOccurred(env)) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| } |
| break; |
| } |
| |
| case PropertyNotify: { |
| jint state, old_state, changed; |
| |
| /* |
| * Let's see if this is a window state protocol message, and |
| * if it is - decode a new state in terms of java constants. |
| */ |
| if (!awt_wm_isStateChange(wdata, (XPropertyEvent *)event, &state)) { |
| /* Pakka Pakka seems not interested */ |
| break; |
| } |
| |
| changed = wdata->state ^ state; |
| if (changed == 0) { |
| /* You feel dizzy for a moment, but nothing happens... */ |
| DTRACE_PRINTLN("TL: >>> state unchanged"); |
| break; |
| } |
| |
| old_state = wdata->state; |
| wdata->state = state; |
| |
| #ifdef DEBUG |
| DTRACE_PRINT("TL: >>> State Changed:"); |
| if (changed & java_awt_Frame_ICONIFIED) { |
| if (state & java_awt_Frame_ICONIFIED) { |
| DTRACE_PRINT(" ICON"); |
| } else { |
| DTRACE_PRINT(" !icon"); |
| } |
| } |
| if (changed & java_awt_Frame_MAXIMIZED_VERT) { |
| if (state & java_awt_Frame_MAXIMIZED_VERT) { |
| DTRACE_PRINT(" MAX_VERT"); |
| } else { |
| DTRACE_PRINT(" !max_vert"); |
| } |
| } |
| if (changed & java_awt_Frame_MAXIMIZED_HORIZ) { |
| if (state & java_awt_Frame_MAXIMIZED_HORIZ) { |
| DTRACE_PRINT(" MAX_HORIZ"); |
| } else { |
| DTRACE_PRINT(" !max_horiz"); |
| } |
| } |
| DTRACE_PRINTLN(""); |
| #endif |
| |
| if (changed & java_awt_Frame_ICONIFIED) { |
| /* Generate window de/iconified event for old clients */ |
| if (state & java_awt_Frame_ICONIFIED) { |
| DTRACE_PRINTLN("TL: ... handleIconify"); |
| JNU_CallMethodByName(env, NULL, |
| this, "handleIconify", "()V"); |
| } |
| else { |
| DTRACE_PRINTLN("TL: ... handleDeiconify"); |
| JNU_CallMethodByName(env, NULL, |
| this, "handleDeiconify", "()V"); |
| } |
| if ((*env)->ExceptionOccurred(env)) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| } |
| } |
| |
| DTRACE_PRINTLN("TL: ... handleStateChange"); |
| JNU_CallMethodByName(env, NULL, |
| this, "handleStateChange", "(II)V", |
| old_state, state); |
| if ((*env)->ExceptionOccurred(env)) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| } |
| break; |
| } /* PropertyNotify */ |
| |
| case ReparentNotify: { |
| Window root = RootWindowOfScreen(XtScreen(wdata->winData.shell)); |
| |
| #ifdef DEBUG |
| DTRACE_PRINT2("TL: ReparentNotify(0x%x/0x%x) to ", |
| wdata->winData.shell, XtWindow(wdata->winData.shell)); |
| if (event->xreparent.parent == root) { |
| DTRACE_PRINTLN("root"); |
| } else { |
| DTRACE_PRINTLN1("window 0x%x", event->xreparent.parent); |
| } |
| #endif |
| |
| if (wdata->winData.flags & W_IS_EMBEDDED) { |
| DTRACE_PRINTLN("TL: embedded frame - nothing to do"); |
| break; |
| } |
| |
| #ifdef __linux__ |
| if (!wdata->fixInsets) { |
| DTRACE_PRINTLN("TL: insets already fixed"); |
| break; |
| } |
| else { |
| wdata->fixInsets = False; |
| } |
| #endif |
| |
| if ((*env)->EnsureLocalCapacity(env, 1) < 0) |
| break; |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| x = (*env)->GetIntField(env, target, componentIDs.x); |
| y = (*env)->GetIntField(env, target, componentIDs.y); |
| width = (*env)->GetIntField(env, target, componentIDs.width); |
| height = (*env)->GetIntField(env, target, componentIDs.height); |
| |
| /* The insets were literally hardcoded in the MWindowPeer. |
| But they are dependent upon both the window manager (WM) |
| and the hardware display. So, these are usually wrong. |
| This leads to problems with shell positioning and size. |
| Furthermore, there is not a published interface or way |
| to obtain from any given window manager the dimensions |
| of its decoration windows (i.e., borders and title bar). |
| So, given this problem in design, we must workaround. |
| N.B. (0) This works. But there is one functional caveat: |
| the frame.insets() function will usually return |
| the wrong values until AFTER the frame is shown. |
| It always did this before; it's just that now, |
| the values will become correct after rendering, |
| whereas before the values were never corrected. |
| (I believe this unavoidable given this design.) |
| (1) Note that we must/have to do this exactly once. |
| (2) The hardcoded values of ...create() (25,5) |
| are also utilized here and must be consistent. |
| This of course could be reworked as desired. |
| (3) Assume top border (title bar) is one width, |
| and other three borders are another width. |
| This, however, could be easily reworked below. */ |
| |
| /* |
| * The above comment is no longer completely true. |
| * The insets are no longer hardcoded but are retrieved from |
| * guessInsets(), either from a per-window manager default, |
| * set in the awt.properties file, or overwritten by the |
| * actual values determined from a previous frames |
| * reparenting. |
| */ |
| |
| if (wdata->decor == AWT_NO_DECOR) { |
| if (!wdata->isResizable && !wdata->isFixedSizeSet) { |
| reshape(env, this, wdata, x, y, width, height, False); |
| if (wdata->warningWindow != NULL) |
| awtJNI_ChangeInsets(env, this, wdata); |
| } |
| } |
| else if (event->xreparent.parent == root) { |
| wdata->reparented = False; |
| wdata->configure_seen = False; |
| |
| /* |
| * We can be repareted to root for two reasons: |
| * . setVisible(false) |
| * . WM exited |
| */ |
| if (wdata->isShowing) { /* WM exited */ |
| /* Work around 4775545 */ |
| awt_wm_unshadeKludge(wdata); |
| } |
| } |
| else { /* reparented to WM frame, figure out our insets */ |
| XWindowAttributes winAttr, actualAttr; |
| int32_t correctWMTop = -1; |
| int32_t correctWMLeft = -1; |
| int32_t correctWMBottom; |
| int32_t correctWMRight; |
| int32_t topCorrection; |
| int32_t leftCorrection; |
| int32_t bottomCorrection = 0; |
| int32_t rightCorrection = 0; |
| int32_t screenX, screenY; |
| int32_t i; |
| int32_t actualWidth, actualHeight; |
| int32_t t, l, b, r; |
| Window containerWindow; |
| |
| /* Dummies for XQueryTree */ |
| Window ignore_Window, *ignore_WindowPtr; |
| uint32_t ignore_uint; |
| |
| Boolean setXY = True; |
| XSizeHints* hints = XAllocSizeHints(); |
| |
| wdata->reparented = True; |
| |
| if (hints != NULL) { |
| long ignore = 0; |
| XGetWMNormalHints(awt_display, XtWindow(wdata->winData.shell), |
| hints, &ignore); |
| setXY = (hints->flags & (USPosition|PPosition)) != 0; |
| XFree(hints); |
| } |
| |
| /* |
| * Unfortunately the concept of "insets" borrowed to AWT |
| * from Win32 is *absolutely*, *unbelievably* foreign to |
| * X11. Few WMs provide the size of frame decor |
| * (i.e. insets) in a property they set on the client |
| * window, so we check if we can get away with just |
| * peeking at it. [Future versions of wm-spec might add a |
| * standardized hint for this]. |
| * |
| * Otherwise we do some special casing. Actually the |
| * fallback code ("default" case) seems to cover most of |
| * the existing WMs (modulo Reparent/Configure order |
| * perhaps?). |
| * |
| * Fallback code tries to account for the two most common cases: |
| * |
| * . single reparenting |
| * parent window is the WM frame |
| * [twm, olwm, sawfish] |
| * |
| * . double reparenting |
| * parent is a lining exactly the size of the client |
| * grandpa is the WM frame |
| * [mwm, e!, kwin, fvwm2 ... ] |
| */ |
| |
| if (awt_wm_getInsetsFromProp(event->xreparent.window, |
| &t, &l, &b, &r)) |
| { |
| correctWMTop = t; |
| correctWMLeft = l; |
| correctWMBottom = b; |
| correctWMRight = r; |
| setXY = False; |
| } |
| else |
| switch (awt_wm_getRunningWM()) { |
| |
| /* should've been done in awt_wm_getInsetsFromProp */ |
| case ENLIGHTEN_WM: { |
| DTRACE_PRINTLN("TL: hmm, E! insets should have been read" |
| " from _E_FRAME_SIZE"); |
| /* enlightenment does double reparenting */ |
| syncTopLevelPos(XtDisplay(wdata->winData.shell), |
| event->xreparent.parent, &winAttr); |
| |
| XQueryTree(XtDisplay(wdata->winData.shell), |
| event->xreparent.parent, |
| &ignore_Window, |
| &containerWindow, /* actual WM frame */ |
| &ignore_WindowPtr, |
| &ignore_uint); |
| if (ignore_WindowPtr) |
| XFree(ignore_WindowPtr); |
| |
| correctWMLeft = winAttr.x; |
| correctWMTop = winAttr.y; |
| |
| /* |
| * Now get the actual dimensions of the parent window |
| * resolve the difference. We can't rely on the left |
| * to be equal to right or bottom... Enlightment |
| * breaks that assumption. |
| */ |
| XGetWindowAttributes(XtDisplay(wdata->winData.shell), |
| containerWindow, &actualAttr); |
| correctWMRight = actualAttr.width |
| - (winAttr.width + correctWMLeft); |
| correctWMBottom = actualAttr.height |
| - (winAttr.height + correctWMTop) ; |
| break; |
| } |
| |
| case ICE_WM: |
| case KDE2_WM: /* should've been done in awt_wm_getInsetsFromProp */ |
| case CDE_WM: |
| case MOTIF_WM: { |
| /* these are double reparenting too */ |
| syncTopLevelPos(XtDisplay(wdata->winData.shell), |
| event->xreparent.parent, &winAttr); |
| |
| correctWMTop = winAttr.y; |
| correctWMLeft = winAttr.x; |
| correctWMRight = correctWMLeft; |
| correctWMBottom = correctWMLeft; |
| |
| XTranslateCoordinates(awt_display, event->xreparent.window, |
| root, 0,0, &screenX, &screenY, |
| &containerWindow); |
| |
| if ((screenX != x + wdata->leftGuess) |
| || (screenY != y + wdata->topGuess)) |
| { |
| /* |
| * looks like the window manager has placed us somewhere |
| * other than where we asked for, lets respect the window |
| * and go where he put us, not where we tried to put us |
| */ |
| x = screenX - correctWMLeft; |
| y = screenY - correctWMTop; |
| } |
| break; |
| } |
| |
| case SAWFISH_WM: |
| case OPENLOOK_WM: { |
| /* single reparenting */ |
| syncTopLevelPos(XtDisplay(wdata->winData.shell), |
| event->xreparent.window, &winAttr); |
| |
| correctWMTop = winAttr.y; |
| correctWMLeft = winAttr.x; |
| correctWMRight = correctWMLeft; |
| correctWMBottom = correctWMLeft; |
| break; |
| } |
| |
| case OTHER_WM: |
| default: { /* this is very similar to the E! case above */ |
| Display *dpy = event->xreparent.display; |
| Window w = event->xreparent.window; |
| Window parent = event->xreparent.parent; |
| XWindowAttributes wattr, pattr; |
| |
| XGetWindowAttributes(dpy, w, &wattr); |
| XGetWindowAttributes(dpy, parent, &pattr); |
| |
| DTRACE_PRINTLN5("TL: window attr +%d+%d+%dx%d (%d)", |
| wattr.x, wattr.y, wattr.width, wattr.height, |
| wattr.border_width); |
| DTRACE_PRINTLN5("TL: parent attr +%d+%d+%dx%d (%d)", |
| pattr.x, pattr.y, pattr.width, pattr.height, |
| pattr.border_width); |
| |
| /* |
| * Check for double-reparenting WM. |
| * |
| * If the parent is exactly the same size as the |
| * top-level assume taht it's the "lining" window and |
| * that the grandparent is the actual frame (NB: we |
| * have already handled undecorated windows). |
| * |
| * XXX: what about timing issues that syncTopLevelPos |
| * is supposed to work around? |
| */ |
| if (wattr.x == 0 && wattr.y == 0 |
| && wattr.width + 2*wattr.border_width == pattr.width |
| && wattr.height + 2*wattr.border_width == pattr.height) |
| { |
| Window ignore_root, grandparent, *children; |
| unsigned int ignore_nchildren; |
| |
| DTRACE_PRINTLN("TL: double reparenting WM detected"); |
| XQueryTree(dpy, parent, |
| &ignore_root, |
| &grandparent, |
| &children, |
| &ignore_nchildren); |
| if (children) |
| XFree(children); |
| |
| /* take lining window into account */ |
| wattr.x = pattr.x; |
| wattr.y = pattr.y; |
| wattr.border_width += pattr.border_width; |
| |
| parent = grandparent; |
| XGetWindowAttributes(dpy, parent, &pattr); |
| DTRACE_PRINTLN5("TL: window attr +%d+%d+%dx%d (%d)", |
| wattr.x, wattr.y, |
| wattr.width, wattr.height, |
| wattr.border_width); |
| DTRACE_PRINTLN5("TL: parent attr +%d+%d+%dx%d (%d)", |
| pattr.x, pattr.y, |
| pattr.width, pattr.height, |
| pattr.border_width); |
| } |
| |
| /* |
| * XXX: To be absolutely correct, we'd need to take |
| * parent's border-width into account too, but the |
| * rest of the code is happily unaware about border |
| * widths and inner/outer distinction, so for the time |
| * being, just ignore it. |
| */ |
| correctWMTop = wattr.y + wattr.border_width; |
| correctWMLeft = wattr.x + wattr.border_width; |
| correctWMBottom = pattr.height |
| - (wattr.y + wattr.height + 2*wattr.border_width); |
| correctWMRight = pattr.width |
| - (wattr.x + wattr.width + 2*wattr.border_width); |
| DTRACE_PRINTLN4("TL: insets = top %d, left %d, bottom %d, right %d", |
| correctWMTop, correctWMLeft, |
| correctWMBottom, correctWMRight); |
| break; |
| } /* default */ |
| |
| } /* switch (runningWM) */ |
| |
| |
| /* |
| * Ok, now see if we need adjust window size because |
| * initial insets were wrong (most likely they were). |
| */ |
| topCorrection = correctWMTop - wdata->topGuess; |
| leftCorrection = correctWMLeft - wdata->leftGuess; |
| bottomCorrection = correctWMBottom - wdata->bottomGuess; |
| rightCorrection = correctWMRight - wdata->rightGuess; |
| |
| DTRACE_PRINTLN3("TL: top: computed=%d, guess=%d, correction=%d", |
| correctWMTop, wdata->topGuess, topCorrection); |
| DTRACE_PRINTLN3("TL: left: computed=%d, guess=%d, correction=%d", |
| correctWMLeft, wdata->leftGuess, leftCorrection); |
| DTRACE_PRINTLN3("TL: bottom: computed=%d, guess=%d, correction=%d", |
| correctWMBottom, wdata->bottomGuess, bottomCorrection); |
| DTRACE_PRINTLN3("TL: right: computed=%d, guess=%d, correction=%d", |
| correctWMRight, wdata->rightGuess, rightCorrection); |
| |
| if (topCorrection != 0 || leftCorrection != 0 |
| || bottomCorrection != 0 || rightCorrection != 0) |
| { |
| jboolean isPacked; |
| |
| DTRACE_PRINTLN("TL: insets need correction"); |
| wdata->need_reshape = True; |
| |
| globalTopGuess = correctWMTop; |
| globalLeftGuess = correctWMLeft; |
| globalBottomGuess = correctWMBottom; |
| globalRightGuess = correctWMRight; |
| |
| /* guesses are for WM decor *only* */ |
| wdata->topGuess = correctWMTop; |
| wdata->leftGuess = correctWMLeft; |
| wdata->bottomGuess = correctWMBottom; |
| wdata->rightGuess = correctWMRight; |
| |
| /* |
| * Actual insets account for menubar/warning label, |
| * so we can't assign directly but must adjust them. |
| */ |
| wdata->top += topCorrection; |
| wdata->left += leftCorrection; |
| wdata->bottom += bottomCorrection; |
| wdata->right += rightCorrection; |
| |
| awtJNI_ChangeInsets(env, this, wdata); |
| |
| /* |
| * If this window has been sized by a pack() we need |
| * to keep the interior geometry intact. Since pack() |
| * computed width and height with wrong insets, we |
| * must adjust the target dimensions appropriately. |
| */ |
| isPacked = (*env)->GetBooleanField(env, target, |
| componentIDs.isPacked); |
| if (isPacked) { |
| int32_t correctTargetW; |
| int32_t correctTargetH; |
| |
| DTRACE_PRINTLN("TL: window is packed, " |
| "adjusting size to preserve layout"); |
| |
| correctTargetW = width + (leftCorrection + rightCorrection); |
| correctTargetH = height +(topCorrection + bottomCorrection); |
| |
| (*env)->SetIntField(env, target, componentIDs.width, |
| (jint) correctTargetW); |
| (*env)->SetIntField(env, target, componentIDs.height, |
| (jint) correctTargetH); |
| /* |
| ** Normally you only reconfigure the outerCanvas due to |
| ** handling the ReconfigureNotify on the innerCanvas. |
| ** However, in this case the innerCanvas may not have |
| ** changed, but outterCanvas may still need to, since the |
| ** insets have changed. |
| */ |
| reshape(env, this, wdata, x, y, |
| correctTargetW, correctTargetH, setXY); |
| reconfigureOuterCanvas(env, target, this, wdata); |
| } else { |
| reshape(env, this, wdata, x, y, width, height, setXY); |
| JNU_CallMethodByName(env, NULL, this, |
| "handleResize", "(II)V", width, height); |
| } |
| } |
| /* NEW for dialog */ /* XXX: what this comment is supposed to mean? */ |
| else { |
| wdata->need_reshape = False; |
| /* fix for 4976337 - son@sparc.spb.su */ |
| /* we should find better fix later if needed */ |
| if (wdata->isResizable || !wdata->isFixedSizeSet) { |
| reshape(env, this, wdata, x, y, width, height, setXY); |
| } |
| } |
| } |
| (*env)->DeleteLocalRef(env, target); |
| break; |
| } /* ReparentNotify */ |
| |
| case ConfigureNotify: { |
| DTRACE_PRINTLN2("TL: ConfigureNotify(0x%x/0x%x)", |
| wdata->winData.shell, XtWindow(wdata->winData.shell)); |
| |
| /* |
| * Some window managers configure before we are reparented and |
| * the send event flag is set! ugh... (Enlighetenment for one, |
| * possibly MWM as well). If we haven't been reparented yet |
| * this is just the WM shuffling us into position. Ignore |
| * it!!!! or we wind up in a bogus location. |
| */ |
| runningWM = awt_wm_getRunningWM(); |
| if (!wdata->reparented && wdata->isShowing && |
| runningWM != NO_WM && wdata->decor != AWT_NO_DECOR) { |
| break; |
| } |
| |
| /* |
| * Notice that we have seen a ConfigureNotify after being |
| * reparented. We should really check for it being a |
| * synthetic event, but metacity doesn't send one. |
| */ |
| if (wdata->reparented) |
| wdata->configure_seen = 1; |
| |
| if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
| break; |
| } |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| /* |
| * We can detect the difference between a move and a resize by |
| * checking the send_event flag on the event; if it's true, |
| * then it's indeed a move, if it's false, then this is a |
| * resize and we do not want to process it as a "move" (for |
| * resizes the x,y values are misleadingly set to 0,0 and so |
| * just checking for an x,y delta won't work). |
| */ |
| |
| getTargetX = (*env)->GetIntField(env, target, componentIDs.x); |
| getTargetY = (*env)->GetIntField(env, target, componentIDs.y); |
| |
| DTRACE_PRINTLN2("TL: target thinks (%d, %d)", |
| getTargetX, getTargetY); |
| DTRACE_PRINTLN3("TL: event is (%d, %d)%s", |
| event->xconfigure.x, event->xconfigure.y, |
| (event->xconfigure.send_event ? " synthetic" : "")); |
| |
| /* |
| * N.B. The wdata top offset is the offset from the outside of |
| * the entire (bordered window) to the inner/parent drawing |
| * area (canvas), NOT to the shell. Thus, if a menubar is |
| * present and/or a warning window at the top (not NETSCAPE), |
| * the top offset will also include space for these. In order |
| * to position the abstract java window relative to the shell, |
| * we must add back in the appropriate space for these when we |
| * subtract off the wdata top field. |
| */ |
| #ifdef NETSCAPE |
| wwHeight = 0; |
| #else /* NETSCAPE */ |
| if (wdata->warningWindow != NULL) |
| wwHeight = wdata->wwHeight; |
| else |
| wwHeight = 0; |
| #endif /* NETSCAPE */ |
| topAdjust = wdata->mbHeight + wwHeight; |
| |
| /* |
| * Coordinates in Component.setLocation() are treated as the |
| * upper-left corner of the outer shell. The x and y in the |
| * ConfigureNotify event, however, are the upper-left corner |
| * of the inset CLIENT window. Therefore, the coordinates |
| * from the event are massaged using the inset values in order |
| * to determine if the top-level shell has moved. In the |
| * event of a user- generated move event (i.e. dragging the |
| * window itself), these coordinates are written back into the |
| * Window object. |
| * |
| * Neat X/CDE/Native bug: |
| * If an attempt is made to move the shell in the y direction |
| * by an amount equal to the top inset, the Window isn't |
| * moved. This can be seen here by examining event->xconfigure.y |
| * before and after such a request is made: the value remains |
| * unchanged. This wrecks a little havoc here, as the x and y |
| * in the Component have already been set to the new location |
| * (in Component.reshape()), but the Window doesn't end up in |
| * the new location. What's more, if a second request is |
| * made, the window will be relocated by TWICE the requested |
| * amount, sort of "catching up" it would seem. |
| * |
| * For a test case of this, see bug 4234645. |
| */ |
| setTargetX = event->xconfigure.x - wdata->left; |
| setTargetY = event->xconfigure.y - wdata->top + topAdjust; |
| |
| width = (*env)->GetIntField(env, target, componentIDs.width); |
| height = (*env)->GetIntField(env, target, componentIDs.height); |
| checkNewXineramaScreen(env, this, wdata, setTargetX, setTargetY, |
| width, height); |
| |
| if ((getTargetX != setTargetX || getTargetY != setTargetY) |
| && (event->xconfigure.send_event || runningWM == NO_WM)) |
| { |
| (*env)->SetIntField(env, target, componentIDs.x, (jint)setTargetX); |
| (*env)->SetIntField(env, target, componentIDs.y, (jint)setTargetY); |
| #ifdef _pauly_debug |
| fprintf(stdout, " ++ shell move. Xevent x,y: %d, %d.\n", |
| event->xconfigure.x, event->xconfigure.y); |
| fprintf(stdout, " shell move. left: %d, top: %d, but offset: %d\n", wdata->left, wdata->top, topAdjust); |
| fprintf(stdout," shell move. target x: %d, target y: %d\n", setTargetX, setTargetY); |
| fprintf(stdout," shell move. ww height: %d\n", wwHeight); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| DTRACE_PRINTLN2("TL: handleMoved(%d, %d)", |
| setTargetX, setTargetY); |
| JNU_CallMethodByName(env, NULL, |
| this, "handleMoved", "(II)V", |
| setTargetX, setTargetY); |
| if ((*env)->ExceptionOccurred(env)) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| } |
| } |
| else if (event->xconfigure.send_event == False) { |
| #ifdef _pauly_debug |
| fprintf(stdout, |
| " ++ shell resize. Xevent x,y,w,h: %d, %d, %d, %d.\n", |
| event->xconfigure.x, event->xconfigure.y, |
| event->xconfigure.width, event->xconfigure.height); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| wdata->shellResized = True; |
| } |
| |
| |
| (*env)->DeleteLocalRef(env, target); |
| raiseInputMethodWindow(wdata); |
| #ifdef __linux__ |
| adjustStatusWindow(wdata->winData.shell); |
| #endif |
| break; |
| } /* ConfigureNotify */ |
| |
| default: |
| break; |
| } |
| } |
| |
| |
| static void |
| Frame_quit(Widget w, |
| XtPointer client_data, |
| XtPointer call_data) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| JNU_CallMethodByName(env, NULL, (jobject) client_data, "handleQuit", "()V"); |
| if ((*env)->ExceptionOccurred(env)) { |
| (*env)->ExceptionDescribe(env); |
| (*env)->ExceptionClear(env); |
| } |
| } |
| |
| |
| static void |
| setDeleteCallback(jobject this, struct FrameData *wdata) |
| { |
| Atom xa_WM_DELETE_WINDOW; |
| Atom xa_WM_TAKE_FOCUS; |
| Atom xa_WM_PROTOCOLS; |
| |
| XtVaSetValues(wdata->winData.shell, |
| XmNdeleteResponse, XmDO_NOTHING, |
| NULL); |
| xa_WM_DELETE_WINDOW = XmInternAtom(XtDisplay(wdata->winData.shell), |
| "WM_DELETE_WINDOW", False); |
| xa_WM_TAKE_FOCUS = XmInternAtom(XtDisplay(wdata->winData.shell), |
| "WM_TAKE_FOCUS", False); |
| xa_WM_PROTOCOLS = XmInternAtom(XtDisplay(wdata->winData.shell), |
| "WM_PROTOCOLS", False); |
| |
| XmAddProtocolCallback(wdata->winData.shell, |
| xa_WM_PROTOCOLS, |
| xa_WM_DELETE_WINDOW, |
| Frame_quit, (XtPointer) this); |
| } |
| |
| |
| extern AwtGraphicsConfigDataPtr |
| copyGraphicsConfigToPeer(JNIEnv *env, jobject this); |
| |
| extern AwtGraphicsConfigDataPtr |
| getGraphicsConfigFromComponentPeer(JNIEnv *env, jobject this); |
| |
| // Returns true if this shell has some transient shell chidlren |
| // which are either Dialogs or Windows. |
| // Returns false otherwise. |
| Boolean hasTransientChildren(Widget shell) { |
| int childIndex; |
| |
| // Enumerate through the popups |
| for (childIndex = 0; childIndex < shell->core.num_popups; childIndex++) { |
| Widget childShell = shell->core.popup_list[childIndex]; |
| // Find all transient shell which are either Dialog or Window |
| if (XtIsTransientShell(childShell)) { |
| Widget toplevel = findTopLevelByShell(childShell); |
| if (toplevel != NULL) { |
| // It is Dialog or Window - return true. |
| return True; |
| } |
| } |
| } |
| return False; |
| } |
| |
| extern Widget grabbed_widget; |
| /** |
| * Disposes top-level component and its widgets |
| */ |
| static |
| void disposeTopLevel(JNIEnv * env, jobject this) { |
| |
| struct FrameData *wdata; |
| Widget parentShell; |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || wdata->mainWindow == NULL |
| || wdata->winData.shell == NULL) |
| { |
| /* do nothing */ |
| return; |
| } |
| |
| // Save parent shell for later disposal. |
| parentShell = XtParent(wdata->winData.shell); |
| |
| removeTopLevel(wdata); |
| if (wdata->isInputMethodWindow) { |
| removeInputMethodWindow(wdata); |
| } |
| |
| XtRemoveEventHandler(wdata->focusProxy, FocusChangeMask, |
| False, shellEH, this); |
| XtUnmanageChild(wdata->focusProxy); |
| awt_util_consumeAllXEvents(wdata->focusProxy); |
| awt_util_cleanupBeforeDestroyWidget(wdata->focusProxy); |
| XtDestroyWidget(wdata->focusProxy); |
| |
| XtUnmanageChild(wdata->winData.comp.widget); |
| awt_delWidget(wdata->winData.comp.widget); |
| awt_util_consumeAllXEvents(wdata->winData.comp.widget); |
| awt_util_cleanupBeforeDestroyWidget(wdata->winData.comp.widget); |
| XtDestroyWidget(wdata->winData.comp.widget); |
| |
| XtUnmanageChild(wdata->mainWindow); |
| awt_util_consumeAllXEvents(wdata->mainWindow); |
| awt_util_consumeAllXEvents(wdata->winData.shell); |
| XtDestroyWidget(wdata->mainWindow); |
| XtDestroyWidget(wdata->winData.shell); |
| if (wdata->iconPixmap) { |
| XFreePixmap(awt_display, wdata->iconPixmap); |
| } |
| |
| if (grabbed_widget == wdata->winData.shell) { |
| XUngrabPointer(awt_display, CurrentTime); |
| XUngrabKeyboard(awt_display, CurrentTime); |
| grabbed_widget = NULL; |
| } |
| |
| free((void *) wdata); |
| |
| (*env)->SetLongField(env, this, mComponentPeerIDs.pData, 0); |
| awtJNI_DeleteGlobalRef(env, this); |
| |
| // Check if parent shell was scheduled for disposal. |
| // If it doesn't have window then we have to dispose it |
| // by ourselves right now. |
| // We can dispose shell only if it doesn't have "transient" children. |
| { |
| struct FrameData *pdata; |
| struct WidgetInfo* winfo; |
| Widget toplevel = findTopLevelByShell(parentShell); |
| if (toplevel == NULL) { |
| // Has already been deleted or it is top shell |
| return; |
| } |
| winfo = findWidgetInfo(toplevel); |
| DASSERT(winfo != NULL); |
| if (winfo == NULL) { |
| // Huh - has already been deleted? |
| return; |
| } |
| pdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, winfo->peer, mComponentPeerIDs.pData); |
| DASSERT(pdata != NULL); |
| if (pdata == NULL) { |
| // Huh - has already been deleted? |
| return; |
| } |
| // 1) scheduled 2) no children 3) no window |
| if (pdata->isDisposeScheduled |
| && !hasTransientChildren(parentShell) |
| && XtWindow(parentShell) == None) |
| { |
| disposeTopLevel(env, winfo->peer); |
| } |
| } |
| } |
| |
| |
| /** |
| * Property change listener. Listens to _XA_JAVA_DISPOSE_PROPERTY_ATOM, |
| * disposes the top-level when this property has been changed. |
| */ |
| static void |
| shellDisposeNotifyHandler(Widget w, XtPointer client_data, |
| XEvent* event, Boolean* continue_to_dispatch) { |
| struct FrameData *wdata; |
| |
| *continue_to_dispatch = True; |
| |
| if (event->type == PropertyNotify && |
| event->xproperty.atom == _XA_JAVA_DISPOSE_PROPERTY_ATOM) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, (jobject)client_data, |
| mComponentPeerIDs.pData); |
| if (wdata != NULL && wdata->isDisposeScheduled) { |
| disposeTopLevel(env, (jobject)client_data); |
| |
| // We've disposed top-level, no more actions on it |
| *continue_to_dispatch = False; |
| } |
| } |
| } |
| |
| /** |
| * Schedules top-level for later dispose - when all events |
| * on it will be processed. |
| */ |
| static |
| void scheduleDispose(JNIEnv * env, jobject peer) { |
| |
| struct FrameData *wdata; |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, peer, mComponentPeerIDs.pData); |
| |
| if (wdata->isDisposeScheduled) { |
| return; |
| } |
| |
| wdata->isDisposeScheduled = True; |
| if (XtWindow(wdata->winData.shell) != None) { |
| XChangeProperty(awt_display, XtWindow(wdata->winData.shell), |
| _XA_JAVA_DISPOSE_PROPERTY_ATOM, XA_ATOM, 32, PropModeAppend, |
| (unsigned char *)"", 0); |
| XFlush(awt_display); |
| XSync(awt_display, False); |
| } else { |
| // If this top-level has children which are still visible then |
| // their disposal could have been scheduled. We shouldn't allow this widget |
| // to destroy its children top-levels. For this purpose we postpone the disposal |
| // of this toplevel until after all its children are disposed. |
| if (!hasTransientChildren(wdata->winData.shell)) { |
| disposeTopLevel(env, peer); |
| } |
| } |
| } |
| |
| |
| /* sun_awt_motif_MWindowPeer_pCreate() is native (X/Motif) create routine */ |
| static char* focusProxyName = "FocusProxy"; |
| |
| Widget createFocusProxy(jobject globalRef, Widget parent) { |
| Widget proxy; |
| #define MAX_ARGC 20 |
| Arg args[MAX_ARGC]; |
| int32_t argc; |
| |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| |
| if (parent == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| return NULL; |
| } |
| argc = 0; |
| XtSetArg(args[argc], XmNwidth, 1); |
| argc++; |
| XtSetArg(args[argc], XmNheight, 1); |
| argc++; |
| XtSetArg(args[argc], XmNx, -1); |
| argc++; |
| XtSetArg(args[argc], XmNy, -1); |
| argc++; |
| XtSetArg(args[argc], XmNmarginWidth, 0); |
| argc++; |
| XtSetArg(args[argc], XmNmarginHeight, 0); |
| argc++; |
| XtSetArg(args[argc], XmNspacing, 0); |
| argc++; |
| XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE); |
| argc++; |
| |
| DASSERT(!(argc > MAX_ARGC)); |
| proxy = XmCreateDrawingArea(parent, focusProxyName, args, argc); |
| XtAddEventHandler(proxy, |
| FocusChangeMask, |
| False, shellEH, globalRef); |
| XtManageChild(proxy); |
| #undef MAX_ARGC |
| return proxy; |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: pCreate |
| * Signature: (Lsun/awt/motif/MComponentPeer;Ljava/lang/String;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_pCreate(JNIEnv *env, jobject this, |
| jobject parent, jstring target_class_name, jboolean isFocusableWindow) |
| { |
| #define MAX_ARGC 50 |
| Arg args[MAX_ARGC]; |
| int32_t argc; |
| struct FrameData *wdata; |
| struct FrameData *pdata = NULL; |
| char *shell_name = NULL; |
| WidgetClass shell_class; |
| Widget parent_widget; |
| jobject target; |
| jobject insets; |
| jobject winAttr; |
| jstring warningString; |
| jboolean resizable; |
| jboolean isModal; |
| jboolean initialFocus; |
| jint state; |
| jclass clazz; |
| jobject globalRef = awtJNI_CreateAndSetGlobalRef(env, this); |
| |
| uint32_t runningWM; /* the running Window Manager */ |
| Widget innerCanvasW; /* form's child, parent of the |
| outer canvas (drawing area) */ |
| Position x,y; |
| Dimension w,h; |
| AwtGraphicsConfigDataPtr adata; |
| AwtGraphicsConfigDataPtr defConfig; |
| jobject gd = NULL; |
| jobject gc = NULL; |
| char *cname = NULL; |
| jstring jname; |
| |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| if (JNU_IsNull(env, target)) { |
| JNU_ThrowNullPointerException(env, "null target"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| wdata = ZALLOC(FrameData); |
| JNU_SetLongFieldFromPtr(env, this, mComponentPeerIDs.pData, wdata); |
| if (wdata == NULL) { |
| JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| adata = copyGraphicsConfigToPeer(env, this); |
| defConfig = getDefaultConfig(adata->awt_visInfo.screen); |
| |
| |
| /* Retrieve the specified characteristics for this window */ |
| winAttr = (*env)->GetObjectField(env, this, mWindowPeerIDs.winAttr); |
| resizable = (*env)->GetBooleanField( env, |
| winAttr, |
| mWindowAttributeIDs.isResizable); |
| state = (*env)->GetIntField( env, |
| winAttr, |
| mWindowAttributeIDs.initialState); |
| initialFocus = (*env)->GetBooleanField( env, |
| winAttr, |
| mWindowAttributeIDs.initialFocus); |
| |
| /* As of today decor is either on or off... except the InputMethodWindow */ |
| if ((*env)->GetBooleanField(env, winAttr, mWindowAttributeIDs.nativeDecor)) { |
| wdata->decor = (*env)->GetIntField(env, winAttr, mWindowAttributeIDs.decorations); |
| } else { |
| wdata->decor = AWT_NO_DECOR; |
| } |
| |
| insets = (*env)->GetObjectField(env, this, mWindowPeerIDs.insets); |
| |
| /* The insets will be corrected upon the reparent |
| event in shellEH(). For now, use bogus values. */ |
| wdata->top = (*env)->GetIntField(env, insets, insetsIDs.top); |
| wdata->left = (*env)->GetIntField(env, insets, insetsIDs.left); |
| wdata->bottom = (*env)->GetIntField(env, insets, insetsIDs.bottom); |
| wdata->right = (*env)->GetIntField(env, insets, insetsIDs.right); |
| awt_Frame_guessInsets(wdata); |
| awtJNI_ChangeInsets(env, this, wdata); |
| wdata->reparented = False; |
| wdata->configure_seen = False; |
| x = (*env)->GetIntField(env, target, componentIDs.x) + wdata->left; |
| y = (*env)->GetIntField(env, target, componentIDs.y) + wdata->top; |
| |
| w = (*env)->GetIntField(env, target, componentIDs.width) |
| - (wdata->left + wdata->right); |
| h = (*env)->GetIntField(env, target, componentIDs.height) |
| - (wdata->top + wdata->bottom); |
| if (w < 0) w = 0; |
| if (h < 0) h = 0; |
| |
| DTRACE_PRINTLN1("TL: pCreate: state = 0x%X", state); |
| |
| wdata->isModal = 0; |
| wdata->initialFocus = (Boolean)initialFocus; |
| wdata->isShowing = False; |
| wdata->shellResized = False; |
| wdata->canvasResized = False; |
| wdata->menuBarReset = False; |
| wdata->need_reshape = False; |
| wdata->focusProxy = NULL; |
| #ifdef __linux__ |
| wdata->fixInsets = True; |
| #endif |
| wdata->state = state; |
| |
| /* initialize screen to screen number in GraphicsConfig's device */ |
| /* can the Window's GC ever be null? */ |
| gc = (*env)->GetObjectField(env, target, componentIDs.graphicsConfig); |
| DASSERT(gc); |
| |
| gd = (*env)->GetObjectField(env, gc, x11GraphicsConfigIDs.screen); |
| DASSERT(gd); |
| |
| wdata->screenNum = (*env)->GetIntField(env, gd, x11GraphicsDeviceIDs.screen); |
| |
| wdata->isFocusableWindow = (Boolean)isFocusableWindow; |
| |
| /* |
| * Create a top-level shell widget. |
| */ |
| argc = 0; |
| XtSetArg(args[argc], XmNsaveUnder, False); argc++; |
| if (resizable) { |
| XtSetArg(args[argc], XmNallowShellResize, True); argc++; |
| } else { |
| XtSetArg(args[argc], XmNallowShellResize, False); argc++; |
| } |
| XtSetArg(args[argc], XmNvisual, defConfig->awt_visInfo.visual); argc++; |
| XtSetArg(args[argc], XmNcolormap, defConfig->awt_cmap); argc++; |
| XtSetArg(args[argc], XmNdepth, defConfig->awt_depth); argc++; |
| XtSetArg(args[argc], XmNmappedWhenManaged, False); argc++; |
| XtSetArg(args[argc], XmNx, x); argc++; |
| XtSetArg(args[argc], XmNy, y); argc++; |
| XtSetArg(args[argc], XmNwidth, w); argc++; |
| XtSetArg(args[argc], XmNheight, h); argc++; |
| |
| XtSetArg(args[argc], XmNbuttonFontList, getMotifFontList()); argc++; |
| XtSetArg(args[argc], XmNlabelFontList, getMotifFontList()); argc++; |
| XtSetArg(args[argc], XmNtextFontList, getMotifFontList()); argc++; |
| |
| XtSetArg(args[argc], XmNmwmDecorations, wdata->decor); argc++; |
| XtSetArg(args[argc], XmNscreen, |
| ScreenOfDisplay(awt_display, defConfig->awt_visInfo.screen)); argc++; |
| |
| if (wdata->initialFocus == False || !isFocusableWindowByPeer(env, this)) { |
| XtSetArg(args[argc], XmNinput, False); argc++; |
| } |
| |
| if (wdata->decor == AWT_NO_DECOR) { |
| /* this is heinous but it can not be avoided for now. |
| ** this is the only known way to eliminate all decorations |
| ** for openlook, which btw, is a bug as ol theoretically |
| ** supports MWM_HINTS |
| */ |
| #ifndef DO_FULL_DECOR |
| if (awt_wm_getRunningWM() == OPENLOOK_WM) { |
| XtSetArg(args[argc], XmNoverrideRedirect, True); |
| argc++; |
| } |
| #endif |
| } |
| |
| /* 4334958: Widget name is set to the Java class name */ |
| shell_name = |
| (char *)JNU_GetStringPlatformChars(env, target_class_name, NULL); |
| |
| if (parent) { |
| pdata = (struct FrameData *) |
| (*env)->GetLongField(env, parent, mComponentPeerIDs.pData); |
| } |
| |
| /* Parenting tells us whether we wish to be transient or not */ |
| if (pdata == NULL) { |
| if (!shell_name) |
| shell_name = "AWTapp"; |
| shell_class = topLevelShellWidgetClass; |
| parent_widget = awt_root_shell; |
| } |
| else { |
| if (!shell_name) |
| shell_name = "AWTdialog"; |
| shell_class = transientShellWidgetClass; |
| parent_widget = pdata->winData.shell; |
| XtSetArg(args[argc], XmNtransient, True); argc++; |
| XtSetArg(args[argc], XmNtransientFor, parent_widget); argc++; |
| |
| /* Fix Forte Menu Bug. If Window name is "###overrideRedirect###", |
| * then set XmNoverrideRedirect to prevent Menus from getting focus. |
| * In JDK 1.2.2 we created Windows as xmMenuShellWidgetClass, |
| * so we did not need to do this. Swing DefaultPopupFactory's |
| * createHeavyWeightPopup sets Window name to "###overrideRedirect###". |
| */ |
| /** |
| * Fix for 4476629. Allow Swing to create heavyweight popups which will |
| * not steal focus from Frame. |
| */ |
| jname = (*env)->GetObjectField(env, target, componentIDs.name); |
| if (!JNU_IsNull(env, jname)) { |
| cname = (char *)JNU_GetStringPlatformChars(env, jname, NULL); |
| } |
| if ( (cname != NULL && strcmp(cname, "###overrideRedirect###") == 0) |
| || (!isFrameOrDialog(target, env) |
| && !isFocusableWindowByPeer(env, this) |
| ) |
| ) |
| { /* mbron */ |
| XtSetArg(args[argc], XmNoverrideRedirect, True); |
| argc++; |
| } |
| if (cname) { |
| JNU_ReleaseStringPlatformChars(env, jname, (const char *) cname); |
| } |
| (*env)->DeleteLocalRef(env, jname); |
| } |
| DASSERT(!(argc > MAX_ARGC)); |
| wdata->winData.shell = XtCreatePopupShell(shell_name, shell_class, |
| parent_widget, args, argc); |
| if (shell_name) { |
| JNU_ReleaseStringPlatformChars(env, target_class_name, shell_name); |
| } |
| |
| #ifdef DEBUG |
| /* Participate in EditRes protocol to facilitate debugging */ |
| XtAddEventHandler(wdata->winData.shell, (EventMask)0, True, |
| _XEditResCheckMessages, NULL); |
| #endif |
| |
| setDeleteCallback(globalRef, wdata); |
| |
| /* Establish resizability. For the case of not resizable, do not |
| yet set a fixed size here; we must wait until in the routine |
| sun_awt_motif_MWindowPeer_pReshape() after insets have been fixed. |
| This is because correction of the insets may affect shell size. |
| (See comments in shellEH() concerning correction of the insets. */ |
| /* |
| * Fix for BugTraq ID 4313607. |
| * Initial resizability will be set later in MWindowPeer_setResizable() |
| * called from init(). |
| */ |
| wdata->isResizable = True; |
| wdata->isFixedSizeSet = False; |
| |
| XtAddEventHandler(wdata->winData.shell, |
| (StructureNotifyMask | PropertyChangeMask |
| | VisibilityChangeMask), |
| False, shellEH, globalRef); |
| |
| XtAddEventHandler(wdata->winData.shell, |
| FocusChangeMask, |
| False, shellFocusEH, globalRef); |
| |
| |
| /** |
| * Installing property change handler for DISPOSE property. |
| * This property will be changed when we need to dispose the whole |
| * top-level. The nature of PropertyNotify will guarantee that it is |
| * the latest event on the top-level so we can freely dispose it. |
| */ |
| wdata->isDisposeScheduled = False; |
| if (_XA_JAVA_DISPOSE_PROPERTY_ATOM == 0) { |
| _XA_JAVA_DISPOSE_PROPERTY_ATOM = XInternAtom(awt_display, "_SUNW_JAVA_AWT_DISPOSE", False); |
| } |
| XtAddEventHandler(wdata->winData.shell, PropertyChangeMask, False, |
| shellDisposeNotifyHandler, globalRef); |
| |
| /* |
| * Create "main" form. |
| */ |
| argc = 0; |
| XtSetArg(args[argc], XmNmarginWidth, 0); argc++; |
| XtSetArg(args[argc], XmNmarginHeight, 0); argc++; |
| XtSetArg(args[argc], XmNhorizontalSpacing, 0); argc++; |
| XtSetArg(args[argc], XmNverticalSpacing, 0); argc++; |
| XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE); argc++; |
| |
| XtSetArg(args[argc], XmNbuttonFontList, getMotifFontList()); argc++; |
| XtSetArg(args[argc], XmNlabelFontList, getMotifFontList()); argc++; |
| XtSetArg(args[argc], XmNtextFontList, getMotifFontList()); argc++; |
| |
| DASSERT(!(argc > MAX_ARGC)); |
| wdata->mainWindow = XmCreateForm(wdata->winData.shell, "main", args, argc); |
| |
| /* The widget returned by awt_canvas_create is a drawing area |
| (i.e., canvas) which is the child of another drawing area |
| parent widget. The parent is the drawing area within the |
| form just created. The child is an drawing area layer over |
| the entire frame window, including the form, any menu bar |
| and warning windows present, and also window manager stuff. |
| The top, bottom, left, and right fields in wdata maintain |
| the respective offsets between these two drawing areas. */ |
| |
| wdata->winData.comp.widget = awt_canvas_create((XtPointer)globalRef, |
| wdata->mainWindow, |
| "frame_", |
| -1, |
| -1, |
| True, |
| wdata, |
| adata); |
| XtAddCallback(wdata->winData.comp.widget, |
| XmNresizeCallback, outerCanvasResizeCB, |
| globalRef); |
| |
| innerCanvasW = XtParent(wdata->winData.comp.widget); |
| XtVaSetValues(innerCanvasW, |
| XmNleftAttachment, XmATTACH_FORM, |
| XmNrightAttachment, XmATTACH_FORM, |
| NULL); |
| |
| XtAddEventHandler(innerCanvasW, StructureNotifyMask, FALSE, |
| innerCanvasEH, globalRef); |
| |
| wdata->focusProxy = createFocusProxy((XtPointer)globalRef, |
| wdata->mainWindow); |
| |
| /* No menu bar initially */ |
| wdata->menuBar = NULL; |
| wdata->mbHeight = 0; |
| |
| /* If a warning window (string) is needed, establish it now.*/ |
| warningString = |
| (*env)->GetObjectField(env, target, windowIDs.warningString); |
| if (!JNU_IsNull(env, warningString) ) { |
| char *wString; |
| /* Insert a warning window. It's height can't be set yet; |
| it will later be set in setMbAndWwHeightAndOffsets().*/ |
| wString = (char *) JNU_GetStringPlatformChars(env, warningString, NULL); |
| wdata->warningWindow = awt_util_createWarningWindow(wdata->mainWindow, wString); |
| JNU_ReleaseStringPlatformChars(env, warningString, (const char *) wString); |
| |
| wdata->wwHeight = 0; |
| XtVaSetValues(wdata->warningWindow, |
| XmNleftAttachment, XmATTACH_FORM, |
| XmNrightAttachment, XmATTACH_FORM, |
| NULL); |
| |
| #ifdef NETSCAPE |
| /* For NETSCAPE, warning window is at bottom of the form*/ |
| XtVaSetValues(innerCanvasW, |
| XmNtopAttachment, XmATTACH_FORM, |
| NULL); |
| XtVaSetValues(wdata->warningWindow, |
| XmNtopAttachment, XmATTACH_WIDGET, |
| XmNtopWidget, innerCanvasW, |
| XmNbottomAttachment, XmATTACH_FORM, |
| NULL); |
| #else /* NETSCAPE */ |
| /* Otherwise (not NETSCAPE), warning is at top of form */ |
| XtVaSetValues(wdata->warningWindow, |
| XmNtopAttachment, XmATTACH_FORM, |
| NULL); |
| XtVaSetValues(innerCanvasW, |
| XmNtopAttachment, XmATTACH_WIDGET, |
| XmNtopWidget, wdata->warningWindow, |
| XmNbottomAttachment, XmATTACH_FORM, |
| NULL); |
| #endif /* NETSCAPE */ |
| |
| } else { |
| /* No warning window present */ |
| XtVaSetValues(innerCanvasW, |
| XmNtopAttachment, XmATTACH_FORM, |
| XmNbottomAttachment, XmATTACH_FORM, |
| NULL); |
| wdata->warningWindow = NULL; |
| wdata->wwHeight = 0; |
| } |
| |
| awt_util_show(wdata->winData.comp.widget); |
| |
| AWT_FLUSH_UNLOCK(); |
| |
| addTopLevel(wdata); |
| |
| /* Check whether this is an instance of InputMethodWindow or not */ |
| if (inputMethodWindowClass == NULL) { |
| jclass localClass = (*env)->FindClass(env, "sun/awt/im/InputMethodWindow"); |
| inputMethodWindowClass = (jclass)(*env)->NewGlobalRef(env, localClass); |
| (*env)->DeleteLocalRef(env, localClass); |
| } |
| if ((*env)->IsInstanceOf(env, target, inputMethodWindowClass)) { |
| wdata->isInputMethodWindow = True; |
| addInputMethodWindow(wdata); |
| } |
| } /* MWindowPeer_pCreate() */ |
| |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: pSetTitle |
| * Signature: (Ljava/lang/String;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_pSetTitle(JNIEnv *env, jobject this, |
| jstring title) |
| { |
| char *ctitle; |
| char *empty_string = " "; |
| struct FrameData *wdata; |
| XTextProperty text_prop; |
| char *c[1]; |
| int32_t conv_result; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || wdata->winData.shell == NULL) { |
| JNU_ThrowNullPointerException(env, "null wdata or shell"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| /* TODO: uwe: set _NET_WM_NAME property to utf-8 name */ |
| |
| ctitle = (JNU_IsNull(env, title)) ? empty_string |
| : (char *) JNU_GetStringPlatformChars(env, title, NULL); |
| |
| if (strcmp(ctitle, "") == 0) |
| ctitle = empty_string; |
| |
| c[0] = ctitle; |
| |
| /* need to convert ctitle to CompoundText */ |
| conv_result = XmbTextListToTextProperty(awt_display, c, 1, |
| XStdICCTextStyle, |
| &text_prop); |
| |
| /* |
| * XmbTextListToTextProperty returns value that is greater |
| * than Success if the supplied text is not fully convertible |
| * to specified encoding. In this case, the return value is |
| * the number of inconvertible characters. But convertibility |
| * is guaranteed for XCompoundTextStyle, so it will actually |
| * never be greater than Success. Errors handled below are |
| * represented by values that are lower than Success. |
| */ |
| if (conv_result >= Success) { |
| XtVaSetValues(wdata->winData.shell, |
| XmNtitle, text_prop.value, |
| XmNtitleEncoding, text_prop.encoding, |
| XmNiconName, text_prop.value, |
| XmNiconNameEncoding, text_prop.encoding, |
| XmNname, ctitle, |
| NULL); |
| } |
| |
| if (ctitle != empty_string) |
| JNU_ReleaseStringPlatformChars(env, title, (const char *) ctitle); |
| |
| if (conv_result == XNoMemory) { |
| JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
| AWT_UNLOCK(); |
| return; |
| } |
| if (conv_result == XLocaleNotSupported) { |
| JNU_ThrowInternalError(env, "Current locale is not supported"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| XFree(text_prop.value); |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: pToFront |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_pToFront(JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| jobject target; |
| Window shellWindow; |
| Boolean autoRequestFocus; |
| Boolean isModal = FALSE; |
| |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL |
| || wdata->winData.comp.widget == NULL |
| || wdata->winData.shell == NULL |
| || wdata->mainWindow == NULL |
| || JNU_IsNull(env, target)) |
| { |
| JNU_ThrowNullPointerException(env, "null widget/target data"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| if ((shellWindow = XtWindow(wdata->winData.shell)) != None) { |
| XRaiseWindow(awt_display, shellWindow); |
| |
| autoRequestFocus = (*env)->GetBooleanField(env, target, windowIDs.isAutoRequestFocus); |
| |
| if (isDialog(target, env)) { |
| isModal = (*env)->GetBooleanField(env, target, dialogIDs.modal); |
| } |
| |
| // In contrast to XToolkit/WToolkit modal dialog can be unfocused. |
| // So we should also ask for modality in addition to 'autoRequestFocus'. |
| if (wdata->isFocusableWindow && (autoRequestFocus || isModal)) { |
| XSetInputFocus(awt_display, XtWindow(wdata->focusProxy), RevertToPointerRoot, CurrentTime); |
| } |
| } |
| |
| (*env)->DeleteLocalRef(env, target); |
| |
| AWT_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: pShow |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_pShow(JNIEnv *env, jobject this) |
| { |
| Java_sun_awt_motif_MWindowPeer_pShowModal(env, this, JNI_FALSE); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: pShowModal |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_pShowModal(JNIEnv *env, jobject this, |
| jboolean isModal) |
| { |
| struct FrameData *wdata; |
| Boolean iconic; |
| jobject target; |
| Boolean locationByPlatform; |
| |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL |
| || wdata->winData.comp.widget == NULL |
| || wdata->winData.shell == NULL |
| || wdata->mainWindow == NULL |
| || (wdata->winData.flags & W_IS_EMBEDDED) |
| || JNU_IsNull(env, target)) |
| { |
| JNU_ThrowNullPointerException(env, "null widget/target data"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| DTRACE_PRINTLN2("TL: pShowModal(modal = %s) state = 0x%X", |
| isModal ? "true" : "false", |
| wdata->state); |
| |
| wdata->isModal = isModal; |
| |
| /* |
| * A workaround for bug 4062589 that is really a motif problem |
| * (see bug 4064803). Before popping up a modal dialog, if a |
| * pulldown menu has the input focus (i.e. user has pulled the |
| * menu down), we send a fake click event and make sure the click |
| * event is processed. With this simulation of user clicking, X |
| * server will not get confused about the modality and a |
| * subsequent click on the popup modal dialog will not cause |
| * system lockup. |
| */ |
| if (wdata->isModal && awt_util_focusIsOnMenu(awt_display) |
| && awt_util_sendButtonClick(awt_display, InputFocus)) |
| { |
| for (;;) { |
| XEvent ev; |
| XtAppPeekEvent(awt_appContext, &ev); |
| if ((ev.type == ButtonRelease) |
| && (*(XButtonEvent *)&ev).send_event) |
| { |
| XtAppProcessEvent(awt_appContext, XtIMAll); |
| break; |
| } else { |
| XtAppProcessEvent(awt_appContext, XtIMAll); |
| } |
| } |
| } |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| // 4488209: kdm@sparc.spb.su |
| // wdata->isShowing is True when toFront calls pShow. |
| // We do not need to do some things if wdata->isShowing is True. |
| if (!wdata->isShowing) { |
| XtVaSetValues(wdata->winData.comp.widget, |
| XmNx, -(wdata->left), |
| XmNy, -(wdata->top), |
| NULL); |
| |
| /* But see below! */ |
| iconic = (wdata->state & java_awt_Frame_ICONIFIED) ? True : False; |
| XtVaSetValues(wdata->winData.shell, |
| XmNinitialState, iconic ? IconicState : NormalState, |
| NULL); |
| |
| if (wdata->menuBar != NULL) { |
| awt_util_show(wdata->menuBar); |
| } |
| XtManageChild(wdata->mainWindow); |
| XtRealizeWidget(wdata->winData.shell); /* but not map it yet */ |
| |
| /* fprintf(stderr, "*** proxy window %x\n", XtWindow(wdata->focusProxy)); */ |
| XStoreName(awt_display, XtWindow(wdata->focusProxy), "FocusProxy"); |
| /* |
| * Maximization and other stuff that requires a live Window to set |
| * properties on to communicate with WM. |
| */ |
| awt_wm_setExtendedState(wdata, wdata->state); |
| awt_wm_setShellDecor(wdata, wdata->isResizable); |
| |
| if (wdata->isModal) { |
| removePopupMenus(); |
| #ifndef NOMODALFIX |
| /* |
| * Fix for 4078176 Modal dialogs don't act modal |
| * if addNotify() is called before setModal(true). |
| * Moved from Java_sun_awt_motif_MDialogPeer_create. |
| */ |
| if (!wdata->callbacksAdded) { |
| XtAddCallback(wdata->winData.shell, |
| XtNpopupCallback, awt_shellPoppedUp, |
| NULL); |
| XtAddCallback(wdata->winData.shell, |
| XtNpopdownCallback, awt_shellPoppedDown, |
| NULL); |
| wdata->callbacksAdded = True; |
| } |
| #endif /* !NOMODALFIX */ |
| /* |
| * Set modality on the Shell, not the BB. The BB expects that |
| * its parent is an xmDialogShell, which as the result of |
| * coalescing is now a transientShell... This has resulted in |
| * a warning message generated under fvwm. The shells are |
| * virtually identical and a review of Motif src suggests that |
| * setting dialog style on BB is a convenience not functional |
| * for BB so set Modality on shell, not the BB(form) widget. |
| */ |
| XtVaSetValues(wdata->winData.shell, |
| XmNmwmInputMode, MWM_INPUT_FULL_APPLICATION_MODAL, |
| NULL); |
| XtManageChild(wdata->winData.comp.widget); |
| } |
| else { /* not modal */ |
| XtVaSetValues(wdata->winData.shell, |
| XmNmwmInputMode, MWM_INPUT_MODELESS, NULL); |
| XtManageChild(wdata->winData.comp.widget); |
| XtSetMappedWhenManaged(wdata->winData.shell, True); |
| } |
| if (wdata->isResizable) { |
| /* REMINDER: uwe: will need to revisit for setExtendedStateBounds */ |
| awt_wm_removeSizeHints(wdata->winData.shell, PMinSize|PMaxSize); |
| } |
| locationByPlatform = |
| (*env)->GetBooleanField(env, target, windowIDs.locationByPlatform); |
| if (locationByPlatform) { |
| awt_wm_removeSizeHints(wdata->winData.shell, USPosition|PPosition); |
| } |
| } |
| |
| /* |
| * 4261047: always pop up with XtGrabNone. Motif notices the |
| * modal input mode and perform the grab for us, doing its |
| * internal book-keeping as well. |
| */ |
| XtPopup(wdata->winData.shell, XtGrabNone); |
| wdata->isShowing = True; |
| |
| wdata->initialFocus = (*env)->GetBooleanField(env, target, windowIDs.isAutoRequestFocus); |
| |
| if (wdata->isFocusableWindow) { |
| if (wdata->initialFocus || wdata->isModal) { |
| focusOnMapNotify = True; |
| } else { |
| XtVaSetValues(wdata->winData.shell, XmNinput, False, NULL); |
| } |
| } |
| |
| (*env)->DeleteLocalRef(env, target); |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: getState |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_motif_MWindowPeer_getState(JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| jint state; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL || wdata->winData.shell == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return java_awt_Frame_NORMAL; |
| } |
| |
| state = wdata->state; |
| |
| AWT_FLUSH_UNLOCK(); |
| return state; |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: setState |
| * Signature: (I)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_setState(JNIEnv *env, jobject this, |
| jint state) |
| { |
| struct FrameData *wdata; |
| Widget shell; |
| Window shell_win; |
| jint changed; |
| Boolean changeIconic, iconic; |
| |
| AWT_LOCK(); |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL || wdata->winData.shell == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| shell = wdata->winData.shell; |
| shell_win = XtWindow(shell); |
| |
| DTRACE_PRINTLN4("TL: setState(0x%x/0x%x, 0x%X -> 0x%X)", |
| shell, shell_win, |
| wdata->state, state); |
| |
| if (!wdata->isShowing) { |
| /* |
| * Not showing, so just record requested state; pShow will set |
| * initial state hints/properties appropriately before poping |
| * us up again. |
| */ |
| DTRACE_PRINTLN("TL: NOT showing (just record the new state)"); |
| wdata->state = state; |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| /* |
| * Request the state transition from WM here and do java upcalls |
| * in shell event handler when WM actually changes our state. |
| */ |
| changed = wdata->state ^ state; |
| |
| changeIconic = changed & java_awt_Frame_ICONIFIED; |
| iconic = (state & java_awt_Frame_ICONIFIED) ? True : False; |
| |
| if (changeIconic && iconic) { |
| DTRACE_PRINTLN("TL: set iconic = True"); |
| XIconifyWindow(XtDisplay(shell), shell_win, |
| XScreenNumberOfScreen(XtScreen(shell))); |
| } |
| |
| /* |
| * If a change in both iconic and extended states requested, do |
| * changes to extended state when we are in iconic state. |
| */ |
| if ((changed & ~java_awt_Frame_ICONIFIED) != 0) { |
| awt_wm_setExtendedState(wdata, state); |
| } |
| |
| if (changeIconic && !iconic) { |
| DTRACE_PRINTLN("TL: set iconic = False"); |
| XMapWindow(XtDisplay(shell), shell_win); |
| } |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: pHide |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_pHide(JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| |
| AWT_LOCK(); |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL |
| || wdata->winData.comp.widget == NULL |
| || wdata->winData.shell == NULL) |
| { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| /** |
| * Disable proxy mechanism when Window's shell is being hidden |
| */ |
| clearFocusPath(wdata->winData.shell); |
| |
| wdata->isShowing = False; /* ignore window state events */ |
| |
| if (XtIsRealized(wdata->winData.shell)) { |
| /* XXX: uwe: this is bogus */ |
| /* |
| * Make sure we withdraw a window in an unmaximized state, or |
| * we'll lose out normal bounds (pShow will take care of |
| * hinting maximization, so when the window is shown again it |
| * will be correctly shown maximized). |
| */ |
| if (wdata->state & java_awt_Frame_MAXIMIZED_BOTH) { |
| awt_wm_setExtendedState(wdata, |
| wdata->state & ~java_awt_Frame_MAXIMIZED_BOTH); |
| } |
| XtUnmanageChild(wdata->winData.comp.widget); |
| XtPopdown(wdata->winData.shell); |
| } |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| |
| /* sun_awt_motif_MWindowPeer_pReshape() is native (X/Motif) routine that |
| is called to effect a reposition and / or resize of the target frame. |
| The parameters x,y,w,h specify target's x, y position, width, height.*/ |
| |
| /* |
| * This functionality is invoked from both java and native code, and |
| * we only want to lock when invoking it from java, so wrap the native |
| * method version with the locking. |
| */ |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: pReshape |
| * Signature: (IIII)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_pReshape(JNIEnv *env, jobject this, |
| jint x, jint y, jint w, jint h) |
| { |
| struct FrameData *wdata; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || |
| wdata->winData.comp.widget == NULL || |
| wdata->winData.shell == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| // See if our new location is on a new screen |
| if (wdata->reparented) { |
| checkNewXineramaScreen(env, this, wdata, x, y, w, h); |
| } |
| |
| /** |
| * Fix for 4652685. |
| * Avoid setting position for embedded frames, since this conflicts with the |
| * fix for 4419207. We assume that the embedded frame never changes its |
| * position relative to the parent. |
| */ |
| if (wdata->winData.flags & W_IS_EMBEDDED) { |
| x = 0; |
| y = 0; |
| } |
| |
| reshape(env, this, wdata, x, y, w, h, True); |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MEmbeddedFramePeer |
| * Method: pReshapePrivate |
| * Signature: (IIII)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MEmbeddedFramePeer_pReshapePrivate(JNIEnv *env, jobject this, |
| jint x, jint y, jint w, jint h) |
| { |
| struct FrameData *wdata; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || |
| wdata->winData.comp.widget == NULL || |
| wdata->winData.shell == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| reshape(env, this, wdata, x, y, w, h, True); |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| static void |
| reshape(JNIEnv *env, jobject this, struct FrameData *wdata, |
| jint x, jint y, jint w, jint h, Boolean setXY) |
| { |
| int32_t topAdjust, /* top adjustment of offset */ |
| bottomAdjust; /* bottom adjustment of offset */ |
| int32_t width, /* of X/Motif shell and form */ |
| height; /* of X/Motif shell and form */ |
| int32_t w1, h1; |
| enum wmgr_t wm; /* window manager */ |
| XWindowAttributes winAttr; |
| |
| DTRACE_PRINTLN7("TL: reshape(0x%x/0x%x,\n"/**/ |
| "TL: x = %d, y = %d, w = %d, h = %d, %s)", |
| wdata->winData.shell, XtWindow(wdata->winData.shell), |
| x, y, w, h, |
| setXY ? "setXY" : "false"); |
| |
| wm = awt_wm_getRunningWM(); |
| |
| /* Make adjustments in case of a dynamically added/removed menu bar */ |
| awtJNI_setMbAndWwHeightAndOffsets(env, this, wdata); |
| |
| #ifdef _pauly_debug |
| fprintf(stdout," reshape. offsets - top: %d, bottom: %d, left: %d, right: %d\n", |
| wdata->top, wdata->bottom, wdata->left, wdata->right); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| /* The abstract java (target) position coordinates (x,y) |
| are for the bordered window. Eventually(!), the Motif |
| (shell) coordinates (XmNx, XmNy) will exclude borders. |
| (This is true only AFTER shell is massaged by the WM.) */ |
| |
| /* The abstract java (target) width and height includes any WM |
| borders. But the Motif width and height excludes WM borders. |
| The wdata top and bottom fields may include space for menu bar, |
| warning window, etc. We must adjust by these values for shell. */ |
| topAdjust = 0; |
| bottomAdjust = 0; |
| /* Surprise - do not(!) check for nonNull MenuBar because that can |
| occur separately (in ...pSetMenubar()) from calculation of the |
| menu bar height and offsets (in setMbAndWwHeightAndOffsets()). |
| In any event, the offsets and wdata mbHeight field should jive. */ |
| topAdjust += wdata->mbHeight; |
| if (wdata->warningWindow != NULL) { |
| #ifdef NETSCAPE |
| bottomAdjust += wdata->wwHeight; |
| #else /* NETSCAPE */ |
| topAdjust += wdata->wwHeight; |
| #endif /* NETSCAPE */ |
| } |
| if (wdata->hasTextComponentNative) { |
| bottomAdjust += wdata->imHeight; |
| } |
| #ifdef _pauly_debug |
| fprintf(stdout," reshape. adjustments - top: %d, bottom: %d\n", topAdjust, bottomAdjust); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| width = w - (wdata->left + wdata->right); |
| height = h - (wdata->top + wdata->bottom) + (topAdjust + bottomAdjust); |
| |
| /* |
| * Shell size. |
| * 4033151. If nonpositive size specified (e.g., if no size |
| * given), establish minimum allowable size. Note: Motif shell |
| * can not be sized 0. |
| */ |
| w1 = (width > 0) ? width : 1; |
| h1 = (height > 0) ? height : 1; |
| |
| if (awt_wm_configureGravityBuggy() /* WM ignores window gravity */ |
| && wdata->reparented && wdata->isShowing) |
| { |
| /* |
| * Buggy WM places client window at (x,y) ignoring the window |
| * gravity. All our windows are NorthWestGravity, so adjust |
| * (x,y) by insets appropriately. |
| */ |
| x += wdata->left; |
| y += wdata->top; |
| DTRACE_PRINTLN2("TL: work around WM gravity bug: x += %d, y += %d", |
| wdata->left, wdata->top); |
| } |
| |
| if (wdata->imRemove) { |
| XtVaSetValues(XtParent(wdata->winData.comp.widget), |
| XmNheight, (((h - (wdata->top + wdata->bottom)) > 0) ? |
| (h - (wdata->top + wdata->bottom)) : 1), |
| NULL); |
| wdata->imRemove = False; |
| } |
| |
| #if 0 /* XXX: this screws insets calculation under KDE2 in the case of |
| negative x, y */ |
| /* |
| * Without these checks, kwm places windows slightly off the screen, |
| * when there is a window underneath at (0,0) and empty space below, |
| * but not to the right. |
| */ |
| if (x < 0) x = 0; |
| if (y < 0) y = 0; |
| #endif |
| if ((wdata->winData.flags & W_IS_EMBEDDED) == 0) { |
| if ((wm == MOTIF_WM) || (wm == CDE_WM)) { |
| /* |
| * By default MWM has "usePPosition: nonzero" and so ignores |
| * windows with PPosition (0,0). Work around (should we???). |
| */ |
| if ((x == 0) && (y == 0)) { |
| x = y = 1; |
| } |
| } |
| } |
| |
| if ( wdata->decor == AWT_NO_DECOR ) { |
| if (setXY) |
| XtConfigureWidget(wdata->winData.shell, x, y, w1, h1, 0 ); |
| else |
| XtResizeWidget(wdata->winData.shell, w1, h1, 0); |
| } |
| else { |
| /* |
| * 5006248, workaround for OpenLook WM. |
| * Thread gets stuck at XtVaSetValues call awaiting for first |
| * ConfigureNotify to come. For OpenLook it looks like a showstopper. |
| * We put dummy ConfigureNotify to satisfy the requirements. |
| */ |
| if (awt_wm_getRunningWM() == OPENLOOK_WM) { |
| XEvent xev; |
| xev.xconfigure.type = ConfigureNotify; |
| xev.xconfigure.display = awt_display; |
| xev.xconfigure.window = XtWindow(wdata->winData.shell); |
| xev.xconfigure.event = xev.xconfigure.window; |
| xev.xconfigure.x = x; |
| xev.xconfigure.y = y; |
| xev.xconfigure.height = h1; |
| xev.xconfigure.width = w1; |
| xev.xconfigure.serial = NextRequest(awt_display) + 1; // see isMine() Xt inner function code. |
| |
| XPutBackEvent(awt_display, &xev); |
| } |
| |
| if (wdata->isResizable) { |
| XtVaSetValues(wdata->winData.shell, |
| XmNwidth, w1, |
| XmNheight, h1, |
| NULL); |
| } |
| else { |
| /* |
| * Fix for BugTraq ID 4313607 - call awt_wm_setShellNotResizable |
| * regardless of wdata->isFixedSizeSet and wdata->reparented values. |
| */ |
| DTRACE_PRINTLN("TL: set fixed size from reshape"); |
| awt_wm_setShellNotResizable(wdata, w1, h1, True); |
| if (wdata->reparented && (w1 > 0) && (h1 > 0)) { |
| wdata->isFixedSizeSet = True; |
| } |
| } |
| if (setXY) |
| XtVaSetValues(wdata->winData.shell, |
| XmNx, x, |
| XmNy, y, |
| NULL); |
| } |
| /* inner/parent drawing area (parent is form) */ |
| h1 = h - (wdata->top + wdata->bottom); |
| h1 = ( h1 > 0 ) ? h1 : 1; |
| #if 0 |
| XtConfigureWidget(XtParent(wdata->winData.comp.widget), |
| 0, topAdjust, w1, h1, 0 ); |
| #else |
| XtVaSetValues(XtParent(wdata->winData.comp.widget), |
| XmNx, 0, |
| XmNy, topAdjust, |
| XmNwidth, w1, |
| XmNheight, h1, |
| NULL); |
| #endif |
| |
| #ifdef _pauly_debug |
| fprintf(stdout," reshape. setting inner canvas to: %d,%d,%d,%d\n", |
| 0, topAdjust, w1, h1 ); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| wdata->menuBarReset = False; |
| |
| /* DTRACE_PRINTLN("TL: reshape -> returning"); */ |
| return; |
| } |
| |
| /* |
| * Class: sun_awt_motif_MEmbeddedFramePeer |
| * Method: getBoundsPrivate |
| * Signature: ()Ljava/awt/Rectangle |
| */ |
| JNIEXPORT jobject JNICALL Java_sun_awt_motif_MEmbeddedFramePeer_getBoundsPrivate |
| (JNIEnv * env, jobject this) |
| { |
| jobject bounds = NULL; |
| struct FrameData *cdata; |
| XWindowAttributes attr; |
| |
| AWT_LOCK(); |
| |
| cdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (cdata == NULL || cdata->mainWindow == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return NULL; |
| } |
| if (!XtIsRealized(cdata->mainWindow) || !XtIsRealized(cdata->winData.shell)) { |
| JNU_ThrowInternalError(env, "widget not visible on screen"); |
| AWT_UNLOCK(); |
| return NULL; |
| } |
| |
| memset(&attr, 0, sizeof(XWindowAttributes)); |
| XGetWindowAttributes(awt_display, XtWindow(cdata->winData.shell), &attr); |
| |
| bounds = JNU_NewObjectByName(env, "java/awt/Rectangle", "(IIII)V", |
| (jint)attr.x, (jint)attr.y, (jint)attr.width, (jint)attr.height); |
| if (((*env)->ExceptionOccurred(env)) || JNU_IsNull(env, bounds)) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return NULL; |
| } |
| |
| AWT_UNLOCK(); |
| |
| return bounds; |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: pDispose |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_pDispose |
| (JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| |
| AWT_LOCK(); |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL || wdata->mainWindow == NULL || wdata->winData.shell == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| if (wdata->winData.flags & W_IS_EMBEDDED) { |
| awt_util_delEmbeddedFrame(wdata->winData.shell); |
| deinstall_xembed(wdata); |
| } |
| scheduleDispose(env, this); |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MFramePeer |
| * Method: pGetIconSize |
| * Signature: (II)Z |
| */ |
| JNIEXPORT jboolean JNICALL Java_sun_awt_motif_MFramePeer_pGetIconSize |
| (JNIEnv *env, jobject this, jint widthHint, jint heightHint) |
| { |
| struct FrameData *wdata; |
| uint32_t width, height, border_width, depth; |
| Window win; |
| int32_t x, y; |
| uint32_t mask; |
| XSetWindowAttributes attrs; |
| uint32_t saveWidth = 0; |
| uint32_t saveHeight = 0; |
| uint32_t dist = 0xffffffff; |
| int32_t diff = 0; |
| int32_t closestWidth; |
| int32_t closestHeight; |
| int32_t newDist; |
| int32_t found = 0; |
| AwtGraphicsConfigDataPtr adata; |
| |
| AWT_LOCK(); |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return FALSE; |
| } |
| XtVaGetValues(wdata->winData.shell, |
| XmNiconWindow, &win, |
| NULL); |
| if (!win) { |
| int32_t count; |
| int32_t i; |
| XIconSize *sizeList; |
| |
| adata = getGraphicsConfigFromComponentPeer(env, this); |
| |
| if (!XGetIconSizes(awt_display, |
| RootWindow(awt_display, adata->awt_visInfo.screen), |
| &sizeList, &count)) { |
| /* No icon sizes so can't set it -- Should we throw an exception?*/ |
| /* [jk] I don't think so: simply fall back to 16x16 */ |
| saveWidth = saveHeight = 16; |
| goto top; |
| } |
| for (i=0; i < count; i++) { |
| if (widthHint >= sizeList[i].min_width && |
| widthHint <= sizeList[i].max_width && |
| heightHint >= sizeList[i].min_height && |
| heightHint <= sizeList[i].max_height) { |
| found = 1; |
| if ((((widthHint-sizeList[i].min_width) |
| % sizeList[i].width_inc) == 0) && |
| (((heightHint-sizeList[i].min_height) |
| % sizeList[i].height_inc) ==0)) { |
| /* Found an exact match */ |
| saveWidth = widthHint; |
| saveHeight = heightHint; |
| dist = 0; |
| break; |
| } |
| diff = widthHint - sizeList[i].min_width; |
| if (diff == 0) { |
| closestWidth = widthHint; |
| } else { |
| diff = diff%sizeList[i].width_inc; |
| closestWidth = widthHint - diff; |
| } |
| diff = heightHint - sizeList[i].min_height; |
| if (diff == 0) { |
| closestHeight = heightHint; |
| } else { |
| diff = diff%sizeList[i].height_inc; |
| closestHeight = heightHint - diff; |
| } |
| newDist = closestWidth*closestWidth + |
| closestHeight*closestHeight; |
| if (dist > newDist) { |
| saveWidth = closestWidth; |
| saveHeight = closestHeight; |
| dist = newDist; |
| } |
| } |
| } |
| |
| if (!found) { |
| #if 1 |
| /* [sbb] this code should work better than the original Solaris |
| code */ |
| if (widthHint >= sizeList[0].max_width || |
| heightHint >= sizeList[0].max_height) { |
| /* determine which way to scale */ |
| int32_t wdiff = widthHint - sizeList[0].max_width; |
| int32_t hdiff = heightHint - sizeList[0].max_height; |
| if (wdiff >= hdiff) { /* need to scale width more */ |
| saveWidth = sizeList[0].max_width; |
| saveHeight = (int32_t)(((double)sizeList[0].max_width/widthHint) * |
| heightHint); |
| } else { |
| saveWidth = (int32_t)(((double)sizeList[0].max_height/heightHint) * |
| widthHint); |
| saveHeight = sizeList[0].max_height; |
| } |
| } else if (widthHint < sizeList[0].min_width || |
| heightHint < sizeList[0].min_height) { |
| saveWidth = (sizeList[0].min_width+sizeList[0].max_width)/2; |
| saveHeight = (sizeList[0].min_height+sizeList[0].max_height)/2; |
| } else { /* it fits within the right size */ |
| saveWidth = widthHint; |
| saveHeight = heightHint; |
| } |
| |
| #else /* XXX: old Solaris code */ |
| /* REMIND: Aspect ratio */ |
| if (widthHint >= sizeList[0].max_width && |
| heightHint >= sizeList[0].max_height) { |
| saveWidth = sizeList[0].max_width; |
| saveHeight = sizeList[0].max_height; |
| } else if (widthHint >= sizeList[0].min_width && |
| heightHint >= sizeList[0].min_height) { |
| saveWidth = sizeList[0].min_width; |
| saveHeight = sizeList[0].min_height; |
| } else { |
| saveWidth = (sizeList[0].min_width+sizeList[0].max_width)/2; |
| saveHeight = (sizeList[0].min_height+sizeList[0].max_height)/2; |
| } |
| #endif |
| } |
| free((void *) sizeList); |
| } else { |
| Window root; |
| if (XGetGeometry(awt_display, |
| win, |
| &root, |
| &x, |
| &y, |
| (uint32_t *)&saveWidth, |
| (uint32_t *)&saveHeight, |
| (uint32_t *)&border_width, |
| (uint32_t *)&depth)) { |
| } |
| } |
| |
| top: |
| (*env)->SetIntField(env, this, mWindowPeerIDs.iconWidth, (jint)saveWidth); |
| (*env)->SetIntField(env, this, mWindowPeerIDs.iconHeight, (jint)saveHeight); |
| |
| AWT_UNLOCK(); |
| return TRUE; |
| } |
| |
| /* |
| * Class: sun_awt_motif_MFramePeer |
| * Method: pSetIconImage |
| * Signature: ([B[I[SII)V |
| */ |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MFramePeer_pSetIconImage___3B_3I_3SII |
| (JNIEnv *env, jobject this, |
| jbyteArray jbyteData, jintArray jintData, jshortArray jushortData, |
| jint iconWidth, jint iconHeight) |
| { |
| struct FrameData *wdata; |
| Window win; |
| GC gc; |
| int32_t x, y; |
| XImage *dst; |
| uint32_t mask; |
| XSetWindowAttributes attrs; |
| jobject jbuf = NULL; |
| void *buf = NULL; |
| int32_t len = 0; |
| int32_t bpp, slp, bpsl; |
| AwtGraphicsConfigDataPtr adata; |
| |
| if (JNU_IsNull(env, jbyteData)) { |
| if (JNU_IsNull(env, jintData)) { |
| if (JNU_IsNull(env, jushortData)) { |
| /* [jk] Don't throw an exception here, it breaks |
| * programs that run correctly on Windows |
| * JNU_ThrowNullPointerException(env, "NullPointerException"); |
| */ |
| return; |
| } else { |
| jbuf = jushortData; |
| } |
| } else { |
| jbuf = jintData; |
| } |
| } else { |
| jbuf = jbyteData; |
| len = (*env)->GetArrayLength(env, jbyteData); |
| } |
| AWT_LOCK(); |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| /* REMIND: Need to figure out how to display image on a pixmap */ |
| |
| if (wdata == NULL || wdata->winData.shell == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| adata = getGraphicsConfigFromComponentPeer(env, this); |
| |
| /* [jk] we need a new pixmap everytime: |
| * Test case: src/share/test/awt/FrameTest.html Look at the icon, |
| * select Operations/Change IconImage, you should see a different |
| * icon now. |
| */ |
| if (wdata->iconPixmap) { |
| XFreePixmap(awt_display, wdata->iconPixmap); |
| wdata->iconPixmap = None; |
| } |
| |
| if (wdata->iconPixmap == None) { |
| if ((wdata->iconPixmap = |
| XCreatePixmap(awt_display, |
| RootWindow(awt_display, adata->awt_visInfo.screen), |
| iconWidth, iconHeight, |
| adata->awtImage->Depth)) == None) { |
| /* REMIND: How to warn that there was a problem? */ |
| AWT_UNLOCK(); |
| return; |
| } |
| wdata->iconWidth = iconWidth; |
| wdata->iconHeight = iconHeight; |
| } |
| |
| buf = (void *) (*env)->GetPrimitiveArrayCritical(env, jbuf, NULL); |
| if (jbyteData != NULL) { |
| int32_t i; |
| unsigned char *ubuf = (unsigned char *) buf; |
| /* Need to map from ICM lut to cmap */ |
| for (i=0; i < len; i++) { |
| ubuf[i] = (ubuf[i] >= adata->color_data->awt_numICMcolors) |
| ? 0 |
| : adata->color_data->awt_icmLUT2Colors[ubuf[i]]; |
| } |
| } |
| |
| bpp = adata->awtImage->wsImageFormat.bits_per_pixel; |
| slp = adata->awtImage->wsImageFormat.scanline_pad; |
| bpsl = paddedwidth(iconWidth * bpp, slp) >> 3; |
| if (((bpsl << 3) / bpp) < iconWidth) { |
| (*env)->ReleasePrimitiveArrayCritical(env, jbuf, buf, JNI_ABORT); |
| AWT_UNLOCK(); |
| return; |
| } |
| dst = XCreateImage(awt_display, adata->awt_visInfo.visual, |
| adata->awtImage->Depth, ZPixmap, 0, |
| buf, iconWidth, iconHeight, 32, bpsl); |
| if (dst == NULL) { |
| /* REMIND: How to warn that there was a problem? */ |
| (*env)->ReleasePrimitiveArrayCritical(env, jbuf, buf, JNI_ABORT); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| if ((gc = XCreateGC(awt_display, wdata->iconPixmap, 0, 0)) == NULL) { |
| XDestroyImage (dst); |
| (*env)->ReleasePrimitiveArrayCritical(env, jbuf, buf, JNI_ABORT); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| XPutImage(awt_display, wdata->iconPixmap, gc, dst, |
| 0, 0, 0, 0, iconWidth, iconHeight); |
| (*env)->ReleasePrimitiveArrayCritical(env, jbuf, buf, JNI_ABORT); |
| dst->data=NULL; |
| XDestroyImage(dst); |
| XFreeGC(awt_display, gc); |
| |
| XtVaGetValues(wdata->winData.shell, |
| XmNiconWindow, &win, |
| NULL); |
| if (!win) { |
| mask = CWBorderPixel | CWColormap | CWBackPixmap; |
| attrs.border_pixel = awt_defaultFg; |
| attrs.colormap = adata->awt_cmap; |
| attrs.background_pixmap = wdata->iconPixmap; |
| if (!(win = XCreateWindow(awt_display, |
| RootWindow(awt_display, |
| adata->awt_visInfo.screen), |
| 0, 0, iconWidth, iconHeight, |
| (uint32_t) 0, |
| adata->awtImage->Depth, |
| InputOutput, |
| adata->awt_visInfo.visual, |
| mask, &attrs))) { |
| /* Still can't create the window so try setting iconPixmap */ |
| XtVaSetValues(wdata->winData.shell, |
| XmNiconPixmap, wdata->iconPixmap, |
| NULL); |
| AWT_FLUSH_UNLOCK(); |
| return; |
| } |
| } |
| |
| XtVaSetValues(wdata->winData.shell, |
| XmNiconPixmap, wdata->iconPixmap, |
| XmNiconWindow, win, |
| NULL); |
| |
| XSetWindowBackgroundPixmap(awt_display, win, wdata->iconPixmap); |
| XClearWindow(awt_display, win); |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: setResizable |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MWindowPeer_setResizable(JNIEnv *env, jobject this, |
| jboolean resizable) |
| { |
| struct FrameData *wdata; |
| jobject target; |
| int32_t targetWidth, |
| targetHeight; |
| int32_t width, /* fixed width if not resizable */ |
| height; /* fixed height if not resizable*/ |
| int32_t verticalAdjust; /* menubar, warning window, etc.*/ |
| |
| if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
| return; |
| } |
| |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL |
| || wdata->winData.comp.widget == NULL |
| || wdata->winData.shell == NULL |
| || JNU_IsNull(env, target)) |
| { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| if (!JNU_IsNull(env, target)) |
| (*env)->DeleteLocalRef(env, target); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| DTRACE_PRINTLN3("TL: setResizable(0x%x/0x%x, %s)", |
| wdata->winData.shell, XtWindow(wdata->winData.shell), |
| resizable ? "true" : "false"); |
| |
| if ((!wdata->isResizable) && (resizable)) { |
| awt_wm_setShellResizable(wdata); |
| wdata->isFixedSizeSet = False; |
| } |
| else if ((wdata->isResizable) && (!resizable)) { |
| /* |
| * To calculate fixed window width, height, we must subtract |
| * off the window manager borders as stored in the wdata |
| * structure. But note that the wdata top and bottom fields |
| * may include space for warning window, menubar, IM status; |
| * this IS part of shell. |
| */ |
| verticalAdjust = wdata->mbHeight; |
| if (wdata->warningWindow != NULL) { |
| verticalAdjust += wdata->wwHeight; |
| } |
| if (wdata->hasTextComponentNative) { |
| verticalAdjust += wdata->imHeight; |
| } |
| |
| targetWidth = (*env)->GetIntField(env, target, componentIDs.width); |
| targetHeight = (*env)->GetIntField(env, target, componentIDs.height); |
| width = targetWidth - (wdata->left + wdata->right); |
| height = targetHeight - (wdata->top + wdata->bottom) + verticalAdjust; |
| #ifdef __linux__ |
| width = (width > 0) ? width : 1; |
| height = (height > 0) ? height : 1; |
| #endif |
| DTRACE_PRINTLN2("TL: setting fixed size %ld x %ld", width, height); |
| awt_wm_setShellNotResizable(wdata, width, height, False); |
| if ((width > 0) && (height > 0)) { |
| wdata->isFixedSizeSet = True; |
| } |
| } |
| |
| wdata->isResizable = (Boolean)resizable; |
| |
| (*env)->DeleteLocalRef(env, target); |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| |
| /* sun_awt_motif_MWindowPeer_pSetMenuBar() is native (X/Motif) routine |
| which handles insertion or deletion of a menubar from this frame. */ |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: pSetMenuBar |
| * Signature: (Lsun/awt/motif/MMenuBarPeer;)V |
| */ |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_pSetMenuBar |
| (JNIEnv *env, jobject this, jobject mb) |
| { |
| struct FrameData *wdata; |
| struct ComponentData *mdata; |
| jobject target; |
| Widget innerCanvasW; /* Motif inner canvas */ |
| #ifdef _pauly_debug |
| Dimension mbHeight; /* Motif menubar height */ |
| #endif /* _pauly_debug */ |
| |
| #ifdef _pauly_debug |
| fprintf(stdout," ++ ...pSetMenuBar.\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| |
| if ((*env)->EnsureLocalCapacity(env, 1) < 0) { |
| return; |
| } |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (JNU_IsNull(env, target) || wdata == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| if (!JNU_IsNull(env, target)) { |
| (*env)->DeleteLocalRef(env, target); |
| } |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| if (mb == NULL) { |
| #ifdef _pauly_debug |
| fprintf(stdout," ...pSetMenuBar. mb is null.\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| if (wdata->menuBar != NULL) { |
| /* Redo attachments of other form widgets appropriately now */ |
| innerCanvasW = XtParent(wdata->winData.comp.widget); |
| |
| if (wdata->warningWindow == NULL) { |
| /* no warning window: canvas is now attached to form */ |
| XtVaSetValues(innerCanvasW, |
| XmNtopAttachment, XmATTACH_FORM, |
| NULL); |
| } else { |
| /* warning window present - conditional on #define NETSCAPE: |
| if NETSCAPE, warning window is at bottom, so canvas is |
| attached to the form (as above); otherwise (not NETSCAPE), |
| warning window itself is instead attached to form. */ |
| #ifdef NETSCAPE |
| XtVaSetValues(innerCanvasW, |
| XmNtopAttachment, XmATTACH_FORM, |
| NULL); |
| #else /* NETSCAPE */ |
| XtVaSetValues(wdata->warningWindow, |
| XmNtopAttachment, XmATTACH_FORM, |
| NULL); |
| #endif /* NETSCAPE */ |
| } |
| |
| wdata->menuBarReset = True; |
| } |
| wdata->menuBar = NULL; |
| awtJNI_setMbAndWwHeightAndOffsets(env, this, wdata); |
| (*env)->DeleteLocalRef(env, target); |
| AWT_FLUSH_UNLOCK(); |
| #ifdef _pauly_debug |
| fprintf(stdout," ...pSetMenuBar. Done.\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| return; |
| } |
| |
| mdata = (struct ComponentData *) |
| JNU_GetLongFieldAsPtr(env, mb, mMenuBarPeerIDs.pData); |
| if (mdata == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| (*env)->DeleteLocalRef(env, target); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| /* OK - insert the new menu bar into the form (at the top). |
| Redo the attachments of other form widgets appropriately.*/ |
| |
| if (wdata->menuBar == NULL) |
| wdata->menuBarReset = True; |
| wdata->menuBar = mdata->widget; |
| |
| #ifdef _pauly_debug |
| XtVaGetValues(mdata->widget, XmNheight, &mbHeight, NULL); |
| fprintf(stdout," ...pSetMenuBar. new menu bar (widget %x, parent: %x) - menu bar height: %d\n", wdata->menuBar, XtParent(wdata->menuBar), mbHeight); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| XtVaSetValues(mdata->widget, |
| XmNtopAttachment, XmATTACH_FORM, |
| XmNleftAttachment, XmATTACH_FORM, |
| XmNrightAttachment, XmATTACH_FORM, |
| NULL); |
| |
| innerCanvasW = XtParent(wdata->winData.comp.widget); |
| |
| if (wdata->warningWindow == NULL) { |
| /* no warning window: menu bar at top, canvas attached to it */ |
| XtVaSetValues(innerCanvasW, |
| XmNtopAttachment, XmATTACH_WIDGET, |
| XmNtopWidget, mdata->widget, |
| NULL); |
| } else { |
| /* warning window present - conditional on #define NETSCAPE: |
| if NETSCAPE, warning window is at bottom, so canvas is |
| attached to menu bar (as above); otherwise (not NETSCAPE), |
| the warning window is attached just below the menu bar. */ |
| #ifdef NETSCAPE |
| XtVaSetValues(innerCanvasW, |
| XmNtopAttachment, XmATTACH_WIDGET, |
| XmNtopWidget, mdata->widget, |
| NULL); |
| #else /* NETSCAPE */ |
| XtVaSetValues(wdata->warningWindow, |
| XmNtopAttachment, XmATTACH_WIDGET, |
| XmNtopWidget, mdata->widget, |
| NULL); |
| #endif /* NETSCAPE */ |
| } |
| |
| XtManageChild(mdata->widget); |
| XtMapWidget(mdata->widget); |
| XSync(awt_display, False); |
| awtJNI_setMbAndWwHeightAndOffsets(env, this, wdata); |
| |
| #ifdef _pauly_debug |
| XtVaGetValues(mdata->widget, XmNheight, &mbHeight, NULL); |
| fprintf(stdout," ...pSetMenuBar. with menu bar: menu bar height: %d, top offset: %d, bottom offset: %d\n", mbHeight, wdata->top, wdata->bottom); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| |
| (*env)->DeleteLocalRef(env, target); |
| |
| AWT_FLUSH_UNLOCK(); |
| |
| #ifdef _pauly_debug |
| fprintf(stdout," ...pSetMenuBar. Done\n"); |
| fflush(stdout); |
| #endif /* _pauly_debug */ |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: toBack |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_toBack |
| (JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || wdata->winData.shell == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| if (XtWindow(wdata->winData.shell) != 0) { |
| XLowerWindow(awt_display, XtWindow(wdata->winData.shell)); |
| } |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: updateAlwaysOnTop |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_updateAlwaysOnTop |
| (JNIEnv *env, jobject this, jboolean isOnTop) |
| { |
| struct FrameData *wdata; |
| AWT_LOCK(); |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| awt_wm_updateAlwaysOnTop(wdata, isOnTop); |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_addTextComponentNative |
| (JNIEnv *env, jobject this, jobject tc) |
| { |
| struct FrameData *wdata; |
| jobject target; |
| |
| if (JNU_IsNull(env, this)) { |
| return; |
| } |
| |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || |
| wdata->winData.comp.widget==NULL || |
| wdata->winData.shell==NULL || |
| JNU_IsNull(env, target)) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| if ( !wdata->hasTextComponentNative) { |
| wdata->hasTextComponentNative = True; |
| wdata->imHeight = awt_motif_getIMStatusHeight(wdata->winData.shell, tc); |
| wdata->bottom += wdata->imHeight; |
| awtJNI_ChangeInsets(env, this, wdata); |
| reshape(env, this, wdata, |
| (*env)->GetIntField(env, target, componentIDs.x), |
| (*env)->GetIntField(env, target, componentIDs.y), |
| (*env)->GetIntField(env, target, componentIDs.width), |
| (*env)->GetIntField(env, target, componentIDs.height), |
| True); |
| } |
| AWT_UNLOCK(); |
| } |
| |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_removeTextComponentNative |
| (JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| jobject target; |
| |
| if (JNU_IsNull(env, this)) { |
| return; |
| } |
| |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || |
| wdata->winData.comp.widget== NULL || |
| wdata->winData.shell== NULL || |
| JNU_IsNull(env, target)) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| if (!wdata->hasTextComponentNative) { |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| wdata->bottom -= wdata->imHeight; |
| awtJNI_ChangeInsets(env, this, wdata); |
| wdata->imRemove = True; |
| reshape(env, this, wdata, |
| (*env)->GetIntField(env, target, componentIDs.x), |
| (*env)->GetIntField(env, target, componentIDs.y), |
| (*env)->GetIntField(env, target, componentIDs.width), |
| (*env)->GetIntField(env, target, componentIDs.height), |
| True); |
| |
| wdata->hasTextComponentNative = False; |
| wdata->imHeight = 0; |
| |
| AWT_UNLOCK(); |
| } /* ...removeTextComponentPeer() */ |
| |
| static Atom java_protocol = None; |
| static Atom motif_wm_msgs = None; |
| |
| static void im_callback(Widget shell, XtPointer client_data, XtPointer call_data) |
| { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| JNU_CallMethodByName(env, NULL, |
| (jobject)client_data, |
| "notifyIMMOptionChange", |
| "()V"); |
| } |
| |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_pSetIMMOption |
| (JNIEnv *env, jobject this, jstring option) |
| { |
| char *coption; |
| char *empty = "InputMethod"; |
| char *menuItem; |
| jobject globalRef; |
| struct FrameData *wdata; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL || wdata->winData.shell == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| globalRef = (jobject)JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.jniGlobalRef); |
| coption = (JNU_IsNull(env, option)) ? empty : (char *) JNU_GetStringPlatformChars(env, option, NULL); |
| if (java_protocol == None || motif_wm_msgs == None) { |
| java_protocol = XmInternAtom(awt_display, "_JAVA_IM_MSG", False); |
| motif_wm_msgs = XmInternAtom(awt_display, "_MOTIF_WM_MESSAGES", False); |
| } |
| XmAddProtocols (wdata->winData.shell, motif_wm_msgs, &java_protocol, 1); |
| XmAddProtocolCallback(wdata->winData.shell, motif_wm_msgs, java_protocol, im_callback, (XtPointer)globalRef); |
| |
| if ((menuItem = awt_util_makeWMMenuItem(coption, java_protocol))) { |
| XtVaSetValues(wdata->winData.shell, |
| XmNmwmMenu, |
| menuItem, |
| NULL); |
| free(menuItem); |
| } |
| if (coption != empty) |
| JNU_ReleaseStringPlatformChars(env, option, (const char *) coption); |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MEmbeddedFramePeer_synthesizeFocusInOut(JNIEnv *env, jobject this, |
| jboolean b) |
| { |
| EmbeddedFrame *ef; |
| Boolean dummy; |
| |
| AWT_LOCK(); |
| ef = theEmbeddedFrameList; |
| while (ef != NULL) { |
| if ((*env)->IsSameObject(env, ef->javaRef, this)) { |
| XFocusChangeEvent xev; |
| xev.display = awt_display; |
| xev.serial = 0; |
| xev.type = b ? FocusIn : FocusOut; |
| xev.send_event = False; |
| xev.window = XtWindow(ef->embeddedFrame); |
| xev.mode = NotifyNormal; |
| xev.detail = NotifyNonlinear; |
| shellEH(ef->embeddedFrame, this, (XEvent*)&xev, &dummy); |
| break; |
| } |
| ef = ef->next; |
| } |
| AWT_UNLOCK(); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MEmbeddedFramePeer_traverseOut(JNIEnv *env, jobject this, jboolean direction) |
| { |
| struct FrameData *wdata; |
| |
| if (JNU_IsNull(env, this)) { |
| return; |
| } |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || |
| wdata->winData.comp.widget== NULL || |
| wdata->winData.shell== NULL) |
| { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| xembed_traverse_out(wdata, direction); |
| AWT_UNLOCK(); |
| } |
| |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MEmbeddedFramePeer_NEFcreate(JNIEnv *env, jobject this, |
| jobject parent, jlong handle) |
| { |
| #undef MAX_ARGC |
| #define MAX_ARGC 40 |
| Arg args[MAX_ARGC]; |
| int32_t argc; |
| struct FrameData *wdata; |
| jobject target; |
| jstring warningString; |
| jboolean resizable; |
| jobject globalRef = awtJNI_CreateAndSetGlobalRef(env, this); |
| Widget innerCanvasW; /* form's child, parent of the outer canvas |
| drawing area */ |
| AwtGraphicsConfigDataPtr adata; |
| AwtGraphicsConfigDataPtr defConfig; |
| |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| if (JNU_IsNull(env, target)) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| wdata = ZALLOC(FrameData); |
| JNU_SetLongFieldFromPtr(env, this, mComponentPeerIDs.pData, wdata); |
| if (wdata == NULL) { |
| JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| adata = getGraphicsConfigFromComponentPeer(env, this); |
| defConfig = getDefaultConfig(adata->awt_visInfo.screen); |
| |
| /* A variation on Netscape's hack for embedded frames: the client area |
| * of the browser is a Java Frame for parenting purposes, but really a |
| * Motif child window |
| */ |
| wdata->winData.flags |= W_IS_EMBEDDED; |
| |
| wdata->top = 0; |
| wdata->left = 0; |
| wdata->bottom = 0; |
| wdata->right = 0; |
| awtJNI_ChangeInsets(env, this, wdata); |
| |
| |
| wdata->isModal = 0; |
| wdata->isShowing = False; |
| wdata->shellResized = False; |
| wdata->canvasResized = False; |
| wdata->menuBarReset = False; |
| |
| resizable = (*env)->GetBooleanField(env, target, frameIDs.resizable); |
| |
| wdata->winData.shell = (Widget)handle; |
| awt_util_addEmbeddedFrame(wdata->winData.shell, globalRef); |
| |
| install_xembed((Widget)handle, wdata); |
| |
| setDeleteCallback(globalRef, wdata); |
| /* Establish resizability. For the case of not resizable, do not |
| yet set a fixed size here; we must wait until in the routine |
| sun_awt_motif_MWindowPeer_pReshape() after insets have been fixed. |
| This is because correction of the insets may affect shell size. |
| (See comments in shellEH() concerning correction of the insets. */ |
| /* |
| * Fix for BugTraq ID 4313607. |
| * Initial resizability will be set later in MWindowPeer_setResizable() |
| * called from init(). But the real changes will be made only if the new |
| * and old resizability values are different at that point, so we |
| * initialize isResizable with inverse value here to get the job done. |
| */ |
| wdata->isResizable = !resizable; |
| wdata->isFixedSizeSet = False; |
| #if 0 |
| if (resizable) { |
| awt_wm_setShellResizable(wdata); |
| } |
| #endif |
| |
| XtAddEventHandler(wdata->winData.shell, StructureNotifyMask | FocusChangeMask, |
| FALSE, (XtEventHandler)shellEH, globalRef); |
| |
| |
| argc = 0; |
| XtSetArg(args[argc], XmNvisual, defConfig->awt_visInfo.visual); argc++; |
| XtSetArg(args[argc], XmNcolormap, defConfig->awt_cmap); argc++; |
| XtSetArg(args[argc], XmNdepth, defConfig->awt_depth); argc++; |
| XtSetArg(args[argc], XmNmarginWidth, 0); argc++; |
| XtSetArg(args[argc], XmNmarginHeight, 0); argc++; |
| XtSetArg(args[argc], XmNhorizontalSpacing, 0); argc++; |
| XtSetArg(args[argc], XmNverticalSpacing, 0); argc++; |
| XtSetArg(args[argc], XmNscreen, |
| ScreenOfDisplay(awt_display, defConfig->awt_visInfo.screen)); argc++; |
| |
| |
| XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE); argc++; |
| |
| DASSERT(!(argc > MAX_ARGC)); |
| wdata->mainWindow = XmCreateForm(wdata->winData.shell, "main", args, argc); |
| |
| /* The widget returned by awt_canvas_create is a drawing area |
| (i.e., canvas) which is the child of another drawing area |
| parent widget. The parent is the drawing area within the |
| form just created. The child is an drawing area layer over |
| the entire frame window, including the form, any menu bar |
| and warning windows present, and also window manager stuff. |
| The top, bottom, left, and right fields in wdata maintain |
| the respective offsets between these two drawing areas. */ |
| |
| wdata->winData.comp.widget = awt_canvas_create((XtPointer)globalRef, |
| wdata->mainWindow, |
| "frame_", |
| -1, |
| -1, |
| True, |
| wdata, |
| defConfig); |
| |
| XtAddCallback(wdata->winData.comp.widget, |
| XmNresizeCallback, |
| outerCanvasResizeCB, |
| globalRef); |
| |
| |
| innerCanvasW = XtParent(wdata->winData.comp.widget); |
| XtVaSetValues(innerCanvasW, |
| XmNleftAttachment, XmATTACH_FORM, |
| XmNrightAttachment, XmATTACH_FORM, |
| NULL); |
| |
| |
| XtAddEventHandler(innerCanvasW, StructureNotifyMask, FALSE, |
| (XtEventHandler)innerCanvasEH, globalRef); |
| |
| /* No menu bar initially */ |
| wdata->menuBar = NULL; |
| wdata->mbHeight = 0; |
| |
| /* If a warning window (string) is needed, establish it now.*/ |
| warningString = |
| (*env)->GetObjectField(env, target, windowIDs.warningString); |
| |
| /* No warning window present */ |
| XtVaSetValues(innerCanvasW, |
| XmNtopAttachment, XmATTACH_FORM, |
| XmNbottomAttachment, XmATTACH_FORM, |
| NULL); |
| wdata->warningWindow = NULL; |
| wdata->wwHeight = 0; |
| |
| |
| awt_util_show(wdata->winData.comp.widget); |
| |
| AWT_FLUSH_UNLOCK(); |
| } /* MEmbeddedFramePeer_NEFcreate() */ |
| |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MEmbeddedFramePeer_pShowImpl(JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL || |
| wdata->winData.comp.widget == NULL || |
| wdata->winData.shell == NULL || |
| wdata->mainWindow == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| XtVaSetValues(wdata->winData.comp.widget, |
| XmNx, -(wdata->left), |
| XmNy, -(wdata->top), NULL); |
| |
| if (wdata->menuBar != 0) { |
| awt_util_show(wdata->menuBar); |
| } |
| |
| XtManageChild(wdata->mainWindow); |
| if (XtWindow(wdata->winData.shell) == None) { |
| XtRealizeWidget(wdata->winData.shell); |
| } |
| XtManageChild(wdata->winData.comp.widget); |
| XtSetMappedWhenManaged(wdata->winData.shell, True); |
| XtPopup(wdata->winData.shell, XtGrabNone); |
| wdata->isShowing = True; |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| /* |
| * Create a local managed widget inside a given X window. |
| * We allocate a top-level shell and then reparent it into the |
| * given window id. |
| * |
| * This is used to take the X11 window ID that has been passed |
| * to us by our parent Navigator plugin and return a widget |
| * that can be used as the base for our Java EmbeddeFrame. |
| * |
| * Note that the ordering of the various calls is tricky here as |
| * we have to cope with the variations between 1.1.3, 1.1.6, |
| * and 1.2. |
| */ |
| JNIEXPORT jlong JNICALL |
| Java_sun_awt_motif_MEmbeddedFrame_getWidget( |
| JNIEnv *env, jclass clz, jlong winid) |
| { |
| Arg args[40]; |
| int argc; |
| Widget w; |
| Window child, parent; |
| Visual *visual; |
| Colormap cmap; |
| int depth; |
| int ncolors; |
| |
| /* |
| * Create a top-level shell. Note that we need to use the |
| * AWT's own awt_display to initialize the widget. If we |
| * try to create a second X11 display connection the Java |
| * runtimes get very confused. |
| */ |
| AWT_LOCK(); |
| |
| argc = 0; |
| XtSetArg(args[argc], XtNsaveUnder, False); argc++; |
| XtSetArg(args[argc], XtNallowShellResize, False); argc++; |
| |
| /* the awt initialization should be done by now (awt_GraphicsEnv.c) */ |
| |
| getAwtData(&depth,&cmap,&visual,&ncolors,NULL); |
| |
| XtSetArg(args[argc], XtNvisual, visual); argc++; |
| XtSetArg(args[argc], XtNdepth, depth); argc++; |
| XtSetArg(args[argc], XtNcolormap, cmap); argc++; |
| |
| XtSetArg(args[argc], XtNwidth, 1); argc++; |
| XtSetArg(args[argc], XtNheight, 1); argc++; |
| /* The shell has to have relative coords of O,0? */ |
| XtSetArg(args[argc], XtNx, 0); argc++; |
| XtSetArg(args[argc], XtNy, 0); argc++; |
| |
| /* The shell widget starts out as a top level widget. |
| * Without intervention, it will be managed by the window |
| * manager and will be its own widow. So, until it is reparented, |
| * we don't map it. |
| */ |
| XtSetArg(args[argc], XtNmappedWhenManaged, False); argc++; |
| |
| w = XtAppCreateShell("AWTapp","XApplication", |
| vendorShellWidgetClass, |
| awt_display, |
| args, |
| argc); |
| XtRealizeWidget(w); |
| |
| /* |
| * Now reparent our new Widget into our Navigator window |
| */ |
| parent = (Window) winid; |
| child = XtWindow(w); |
| XReparentWindow(awt_display, child, parent, 0, 0); |
| XFlush(awt_display); |
| XSync(awt_display, False); |
| XtVaSetValues(w, XtNx, 0, XtNy, 0, NULL); |
| XFlush(awt_display); |
| XSync(awt_display, False); |
| |
| AWT_UNLOCK(); |
| |
| return (jlong)w; |
| } |
| |
| /* |
| * Make sure the given widget is mapped. |
| * |
| * This isn't necessary on JDK 1.1.5 but is needed on JDK 1.1.4 |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_motif_MEmbeddedFrame_mapWidget(JNIEnv *env, jclass clz, jlong widget) |
| { |
| Widget w = (Widget)widget; |
| /* |
| * this is what JDK 1.1.5 does in MFramePeer.pShow. |
| */ |
| AWT_LOCK(); |
| XtSetMappedWhenManaged(w, True); |
| XtPopup(w, XtGrabNone); |
| AWT_UNLOCK(); |
| return (jint) 1; |
| } |
| |
| |
| JNIEXPORT jboolean JNICALL |
| Java_sun_awt_motif_MEmbeddedFramePeer_isXEmbedActive(JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| Boolean res; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL || |
| wdata->winData.comp.widget == NULL || |
| wdata->winData.shell == NULL || |
| wdata->mainWindow == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return False; |
| } |
| |
| res = isXEmbedActive(wdata); |
| AWT_UNLOCK(); |
| return res; |
| |
| } |
| |
| JNIEXPORT jboolean JNICALL |
| Java_sun_awt_motif_MEmbeddedFramePeer_isXEmbedApplicationActive(JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| Boolean res; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL || |
| wdata->winData.comp.widget == NULL || |
| wdata->winData.shell == NULL || |
| wdata->mainWindow == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return False; |
| } |
| |
| res = isXEmbedApplicationActive(wdata); |
| AWT_UNLOCK(); |
| return res; |
| |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_MEmbeddedFramePeer_requestXEmbedFocus(JNIEnv *env, jobject this) |
| { |
| struct FrameData *wdata; |
| |
| AWT_LOCK(); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| if (wdata == NULL || |
| wdata->winData.comp.widget == NULL || |
| wdata->winData.shell == NULL || |
| wdata->mainWindow == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| requestXEmbedFocus(wdata); |
| AWT_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: setSaveUnder |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_setSaveUnder |
| (JNIEnv *env, jobject this, jboolean state) |
| { |
| struct FrameData *wdata; |
| jobject target; |
| |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || |
| wdata->winData.comp.widget == NULL || |
| wdata->winData.shell == NULL || |
| JNU_IsNull(env, target)) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| if (!JNU_IsNull(env, target)) |
| (*env)->DeleteLocalRef(env, target); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| XtVaSetValues(wdata->winData.shell, XmNsaveUnder, state, NULL); |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: setFocusableWindow |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_setFocusableWindow |
| (JNIEnv *env, jobject this, jboolean isFocusableWindow) |
| { |
| struct FrameData *wdata; |
| jobject target; |
| |
| AWT_LOCK(); |
| |
| target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); |
| |
| wdata = (struct FrameData *) |
| JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
| |
| if (wdata == NULL || |
| wdata->winData.comp.widget == NULL || |
| wdata->winData.shell == NULL || |
| JNU_IsNull(env, target)) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| if (!JNU_IsNull(env, target)) |
| (*env)->DeleteLocalRef(env, target); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| wdata->isFocusableWindow = isFocusableWindow; |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_motif_MWindowPeer |
| * Method: resetTargetGC |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL Java_sun_awt_motif_MWindowPeer_resetTargetGC |
| (JNIEnv * env, jobject this, jobject target) |
| { |
| (*env)->CallVoidMethod(env, target, windowIDs.resetGCMID); |
| } |
| |
| |
| /* |
| * Old, compatibility, backdoor for DT. This is a different |
| * implementation. It keeps the signature, but acts on |
| * awt_root_shell, not the frame passed as an argument. Note, that |
| * the code that uses the old backdoor doesn't work correctly with |
| * gnome session proxy that checks for WM_COMMAND when the window is |
| * firts mapped, because DT code calls this old backdoor *after* the |
| * frame is shown or it would get NPE with old AWT (previous |
| * implementation of this backdoor) otherwise. Old style session |
| * managers (e.g. CDE) that check WM_COMMAND only during session |
| * checkpoint should work fine, though. |
| * |
| * NB: The function name looks deceptively like a JNI native method |
| * name. It's not! It's just a plain function. |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this, |
| jobject frame, jstring jcommand) |
| { |
| const char *command; |
| XTextProperty text_prop; |
| char *c[1]; |
| int32_t status; |
| |
| AWT_LOCK(); |
| |
| if (awt_root_shell == NULL) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| if (XtWindow(awt_root_shell) == None) { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| /* need to convert ctitle to CompoundText */ |
| command = (char *) JNU_GetStringPlatformChars(env, jcommand, NULL); |
| c[0] = (char *)command; |
| status = XmbTextListToTextProperty(awt_display, c, 1, |
| XStdICCTextStyle, &text_prop); |
| |
| if (status == Success || status > 0) { |
| XSetTextProperty(awt_display, XtWindow(awt_root_shell), |
| &text_prop, XA_WM_COMMAND); |
| if (text_prop.value != NULL) |
| XFree(text_prop.value); |
| } |
| |
| JNU_ReleaseStringPlatformChars(env, jcommand, command); |
| |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| |
| /* |
| * New DT backdoor to set WM_COMMAND. New code should use this |
| * backdoor and call it *before* the first frame is shown so that |
| * gnome session proxy can correctly handle it. |
| * |
| * NB: The function name looks deceptively like a JNI native method |
| * name. It's not! It's just a plain function. |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jargv) |
| { |
| static const char empty[] = ""; |
| |
| int argc; |
| const char **cargv; |
| XTextProperty text_prop; |
| int status; |
| int i; |
| |
| AWT_LOCK(); |
| |
| if (awt_root_shell == NULL) { |
| JNU_ThrowNullPointerException(env, "AWT root shell"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| if (XtWindow(awt_root_shell) == None) { |
| JNU_ThrowNullPointerException(env, "AWT root shell is unrealized"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| argc = (int)(*env)->GetArrayLength(env, jargv); |
| if (argc == 0) { |
| /* nothing to do */ |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| /* array of C strings */ |
| cargv = (const char **)calloc(argc, sizeof(char *)); |
| if (cargv == NULL) { |
| JNU_ThrowOutOfMemoryError(env, "Unable to allocate cargv"); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| /* fill C array with platform chars of java strings */ |
| for (i = 0; i < argc; ++i) { |
| jstring js; |
| const char *cs; |
| |
| cs = NULL; |
| js = (*env)->GetObjectArrayElement(env, jargv, i); |
| if (js != NULL) { |
| cs = JNU_GetStringPlatformChars(env, js, NULL); |
| } |
| if (cs == NULL) { |
| cs = empty; |
| } |
| |
| cargv[i] = cs; |
| (*env)->DeleteLocalRef(env, js); |
| } |
| |
| /* grr, X prototype doesn't declare cargv as const, thought it really is */ |
| status = XmbTextListToTextProperty(awt_display, (char **)cargv, argc, |
| XStdICCTextStyle, &text_prop); |
| if (status < 0) { |
| switch (status) { |
| case XNoMemory: |
| JNU_ThrowOutOfMemoryError(env, |
| "XmbTextListToTextProperty: XNoMemory"); |
| break; |
| case XLocaleNotSupported: |
| JNU_ThrowInternalError(env, |
| "XmbTextListToTextProperty: XLocaleNotSupported"); |
| break; |
| case XConverterNotFound: |
| JNU_ThrowNullPointerException(env, |
| "XmbTextListToTextProperty: XConverterNotFound"); |
| break; |
| default: |
| JNU_ThrowInternalError(env, |
| "XmbTextListToTextProperty: unknown error"); |
| } |
| } else { |
| /* |
| * status == Success (i.e. 0) or |
| * status > 0 - a number of unconvertible characters |
| * (cannot happen for XStdICCTextStyle). |
| */ |
| XSetTextProperty(awt_display, XtWindow(awt_root_shell), |
| &text_prop, XA_WM_COMMAND); |
| } |
| |
| /* release platform chars */ |
| for (i = 0; i < argc; ++i) { |
| jstring js; |
| |
| if (cargv[i] == empty) |
| continue; |
| |
| js = (*env)->GetObjectArrayElement(env, jargv, i); |
| JNU_ReleaseStringPlatformChars(env, js, cargv[i]); |
| (*env)->DeleteLocalRef(env, js); |
| } |
| if (text_prop.value != NULL) |
| XFree(text_prop.value); |
| |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| /* |
| * Class: java_awt_TrayIcon |
| * Method: initIDs |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs(JNIEnv *env , jclass clazz) |
| { |
| } |