/* * Copyright 1996-2002 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 "java_awt_Adjustable.h" #include "java_awt_Insets.h" #include "java_awt_ScrollPane.h" #include "java_awt_event_AdjustmentEvent.h" #include "sun_awt_motif_MComponentPeer.h" #include "sun_awt_motif_MScrollPanePeer.h" #include "java_awt_AWTEvent.h" #include "awt_Component.h" #include "canvas.h" #include #include #include extern struct MComponentPeerIDs mComponentPeerIDs; extern AwtGraphicsConfigDataPtr copyGraphicsConfigToPeer(JNIEnv *env, jobject this); /* fieldIDs for ScrollPane fields that may be accessed from C */ static struct ScrollPaneIDs { jfieldID scrollbarDisplayPolicy; } scrollPaneIDs; /* * Class: java_awt_ScrollPane * Method: initIDs * Signature: ()V */ /* This function gets called from the static initializer for ScrollPane.java to initialize the fieldIDs for fields that may be accessed from C */ JNIEXPORT void JNICALL Java_java_awt_ScrollPane_initIDs (JNIEnv *env, jclass cls) { scrollPaneIDs.scrollbarDisplayPolicy = (*env)->GetFieldID(env, cls, "scrollbarDisplayPolicy", "I"); } /* fieldIDs for MScrollPanePeer fields that may be accessed from C */ static struct MScrollPanePeerIDs { jmethodID postScrollEventID; } mScrollPanePeerIDs; /* * Class: sun_awt_motif_MScrollPanePeer * Method: initIDs * Signature: ()V */ /* This function gets called from the static initializer for MScrollPanePeer.java to initialize the fieldIDs for fields that may be accessed from C */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_initIDs (JNIEnv *env, jclass cls) { mScrollPanePeerIDs.postScrollEventID = (*env)->GetMethodID(env, cls, "postScrollEvent", "(IIIZ)V"); } static void dump_scroll_attrs(Widget scrollbar) { unsigned char orient; int32_t value, size, incr, pIncr, max, min; XtVaGetValues(scrollbar, XmNvalue, &value, XmNincrement, &incr, XmNpageIncrement, &pIncr, XmNsliderSize, &size, XmNmaximum, &max, XmNminimum, &min, XmNorientation, &orient, NULL); jio_fprintf(stdout, "%s: min=%d max=%d slider-size=%d incr=%d pageIncr=%d value = %d\n", orient == XmVERTICAL ? "VSB" : "HSB", min, max, size, incr, pIncr, value); } /* * client_data is MScrollPanePeer instance */ static void postScrollEvent(jint jorient, jobject peer, XmScrollBarCallbackStruct *scroll) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jint jscrollcode; jboolean jadjusting = JNI_FALSE; switch (scroll->reason) { case XmCR_DECREMENT: jscrollcode = java_awt_event_AdjustmentEvent_UNIT_DECREMENT; break; case XmCR_INCREMENT: jscrollcode = java_awt_event_AdjustmentEvent_UNIT_INCREMENT; break; case XmCR_PAGE_DECREMENT: jscrollcode = java_awt_event_AdjustmentEvent_BLOCK_DECREMENT; break; case XmCR_PAGE_INCREMENT: jscrollcode = java_awt_event_AdjustmentEvent_BLOCK_INCREMENT; break; case XmCR_DRAG: jscrollcode = java_awt_event_AdjustmentEvent_TRACK; jadjusting = JNI_TRUE; break; case XmCR_VALUE_CHANGED: /* drag finished */ case XmCR_TO_TOP: case XmCR_TO_BOTTOM: jscrollcode = java_awt_event_AdjustmentEvent_TRACK; break; default: DASSERT(FALSE); return; } (*env)->CallVoidMethod(env, peer, mScrollPanePeerIDs.postScrollEventID, jorient, jscrollcode, (jint)scroll->value, jadjusting); if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } } /* * client_data is MScrollPanePeer instance */ static void ScrollPane_scrollV(Widget w, XtPointer client_data, XtPointer call_data) { postScrollEvent(java_awt_Adjustable_VERTICAL, (jobject)client_data, (XmScrollBarCallbackStruct *)call_data); } /* * client_data is MScrollPanePeer instance */ static void ScrollPane_scrollH(Widget w, XtPointer client_data, XtPointer call_data) { postScrollEvent(java_awt_Adjustable_HORIZONTAL, (jobject)client_data, (XmScrollBarCallbackStruct *)call_data); } typedef XmNavigability (*NavigableCallback) (Widget); NavigableCallback oldClipNavigable = NULL; Boolean clipCallbackInitialized = False; XmNavigability MyClipNavigable(Widget wid) { // We've installed this function for ClipWindow if (XmIsClipWindow(wid)) { // To be able to request focus on ClipWindow by call // XmProcessTraversal(, XmTRAVERSE_CURRENT) we need to make // it return XmCONTROL_NAVIGABLE. Default implementation returns // DESCENDANTS_TAB_NAVIGABLE which doesn't allow this. return XmCONTROL_NAVIGABLE; } if (oldClipNavigable) { return oldClipNavigable(wid); } // this will never happen return XmCONTROL_NAVIGABLE; } const char * ScrollPaneManagerName = "ScrolledWindowClipWindow"; NavigableCallback oldManagerNavigable = NULL; Boolean managerCallbackInitialized = False; XmNavigability MyManagerNavigable(Widget wid) { // We've installed this function for Manager // with the name ScrollPaneManagerName if (XmIsManager(wid) && ( XtName(wid) != NULL && strcmp(XtName(wid), ScrollPaneManagerName) == 0) ) { // To be able to request focus on Manager by call // XmProcessTraversal(, XmTRAVERSE_CURRENT) we need to make // it return XmCONTROL_NAVIGABLE. Default implementation returns // DESCENDANTS_TAB_NAVIGABLE which doesn't allow this. return XmCONTROL_NAVIGABLE; } if (oldManagerNavigable) { return oldManagerNavigable(wid); } // this will never happen return XmCONTROL_NAVIGABLE; } /* * Class: sun_awt_motif_MScrollPanePeer * Method: create * Signature: (Lsun/awt/motif/MComponentPeer;)V */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_create (JNIEnv *env, jobject this, jobject parent) { int32_t argc; #define MAX_ARGC 40 Arg args[MAX_ARGC]; struct ComponentData *wdata; struct ComponentData *sdata; jobject target; Pixel bg; Widget vsb, hsb; jint sbDisplay; jobject globalRef = awtJNI_CreateAndSetGlobalRef(env, this); AwtGraphicsConfigDataPtr adata; AWT_LOCK(); if (JNU_IsNull(env, parent)) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); wdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env,parent,mComponentPeerIDs.pData); if (JNU_IsNull(env, target) || wdata == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } sdata = ZALLOC(ComponentData); JNU_SetLongFieldFromPtr(env,this,mComponentPeerIDs.pData,sdata); if (sdata == NULL) { JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); AWT_UNLOCK(); return; } XtVaGetValues(wdata->widget, XmNbackground, &bg, NULL); adata = copyGraphicsConfigToPeer(env, this); argc = 0; sbDisplay = (*env)->GetIntField(env, target, scrollPaneIDs.scrollbarDisplayPolicy); XtSetArg(args[argc], XmNuserData, (XtPointer) globalRef); argc++; if (sbDisplay == java_awt_ScrollPane_SCROLLBARS_NEVER) { DASSERT(!(argc > MAX_ARGC)); sdata->widget = XtCreateWidget(ScrollPaneManagerName, xmManagerWidgetClass, wdata->widget, args, argc); { // To be able to request focus on Manager by call // XmProcessTraversal(, XmTRAVERSE_CURRENT) we need to make // it return XmCONTROL_NAVIGABLE from widgetNavigable callback. // Default implementation returns DESCENDANTS_TAB_NAVIGABLE // which doesn't allow this. if (!managerCallbackInitialized) { XmBaseClassExt *er; WidgetClass wc; managerCallbackInitialized = True; wc = (WidgetClass) &xmManagerClassRec; er = _XmGetBaseClassExtPtr(wc, XmQmotif); oldManagerNavigable = (*er)->widgetNavigable; (*er)->widgetNavigable = MyManagerNavigable; } } } else { XtSetArg(args[argc], XmNscrollingPolicy, XmAUTOMATIC); argc++; XtSetArg(args[argc], XmNvisualPolicy, XmCONSTANT); argc++; if (sbDisplay == java_awt_ScrollPane_SCROLLBARS_ALWAYS) { DASSERT(!(argc > MAX_ARGC)); XtSetArg(args[argc], XmNscrollBarDisplayPolicy, XmSTATIC); argc++; } else { XtSetArg(args[argc], XmNscrollBarDisplayPolicy, XmAS_NEEDED); argc++; } XtSetArg(args[argc], XmNspacing, 0); argc++; XtSetArg (args[argc], XmNscreen, ScreenOfDisplay(awt_display, adata->awt_visInfo.screen)); argc++; DASSERT(!(argc > MAX_ARGC)); sdata->widget = XmCreateScrolledWindow(wdata->widget, "scroller", args, argc); XtVaGetValues(sdata->widget, XmNverticalScrollBar, &vsb, XmNhorizontalScrollBar, &hsb, NULL); if (vsb != NULL) { XtAddCallback(vsb, XmNincrementCallback, ScrollPane_scrollV, (XtPointer) globalRef); XtAddCallback(vsb, XmNdecrementCallback, ScrollPane_scrollV, (XtPointer) globalRef); XtAddCallback(vsb, XmNpageIncrementCallback, ScrollPane_scrollV, (XtPointer) globalRef); XtAddCallback(vsb, XmNpageDecrementCallback, ScrollPane_scrollV, (XtPointer) globalRef); XtAddCallback(vsb, XmNtoTopCallback, ScrollPane_scrollV, (XtPointer) globalRef); XtAddCallback(vsb, XmNtoBottomCallback, ScrollPane_scrollV, (XtPointer) globalRef); XtAddCallback(vsb, XmNvalueChangedCallback, ScrollPane_scrollV, (XtPointer) globalRef); XtAddCallback(vsb, XmNdragCallback, ScrollPane_scrollV, (XtPointer) globalRef); XtVaSetValues(vsb, XmNhighlightThickness, 0, NULL); } if (hsb != NULL) { XtAddCallback(hsb, XmNincrementCallback, ScrollPane_scrollH, (XtPointer) globalRef); XtAddCallback(hsb, XmNdecrementCallback, ScrollPane_scrollH, (XtPointer) globalRef); XtAddCallback(hsb, XmNpageIncrementCallback, ScrollPane_scrollH, (XtPointer) globalRef); XtAddCallback(hsb, XmNpageDecrementCallback, ScrollPane_scrollH, (XtPointer) globalRef); XtAddCallback(hsb, XmNtoTopCallback, ScrollPane_scrollH, (XtPointer) globalRef); XtAddCallback(hsb, XmNtoBottomCallback, ScrollPane_scrollH, (XtPointer) globalRef); XtAddCallback(hsb, XmNvalueChangedCallback, ScrollPane_scrollH, (XtPointer) globalRef); XtAddCallback(hsb, XmNdragCallback, ScrollPane_scrollH, (XtPointer) globalRef); XtVaSetValues(hsb, XmNhighlightThickness, 0, NULL); } { /** * Fix for 4033837 - ScrollPane doesn't generate mouse, focus, key events * If ScrollPane created with ALWAYS or AS_NEEDED scrollbars policy then * the upper widget is ClipWindow. We should install callbacks on it to * receive event notifications. */ Widget clip = XtNameToWidget(sdata->widget, "*ClipWindow"); if (clip != NULL) { // To be able to request focus on Manager by call // XmProcessTraversal(, XmTRAVERSE_CURRENT) we need to make // it return XmCONTROL_NAVIGABLE from widgetNavigable callback. // Default implementation returns DESCENDANTS_TAB_NAVIGABLE // which doesn't allow this. if (!clipCallbackInitialized) { XmBaseClassExt *er; clipCallbackInitialized = True; er = _XmGetBaseClassExtPtr(XtClass(clip), XmQmotif); oldClipNavigable = (*er)->widgetNavigable; (*er)->widgetNavigable = MyClipNavigable; } awt_addWidget(clip, sdata->widget, globalRef, java_awt_AWTEvent_MOUSE_EVENT_MASK | java_awt_AWTEvent_MOUSE_MOTION_EVENT_MASK | java_awt_AWTEvent_KEY_EVENT_MASK); } } { /** * Fix for 4033837 - ScrollPane with ALWAYS doesn't have scrollbars visible * It seems to be the bug in Motif, the workaround is to add empty child. * User child will replace it when needed. This doesn't work if child had been * removed. */ if (sbDisplay == java_awt_ScrollPane_SCROLLBARS_ALWAYS) { Widget darea = NULL; argc = 0; XtSetArg(args[argc], XmNwidth, 1); argc++; XtSetArg(args[argc], XmNheight, 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++; darea = XmCreateDrawingArea(sdata->widget, "null_child", args, argc); XmScrolledWindowSetAreas(sdata->widget, NULL, NULL, darea); XtSetMappedWhenManaged(darea, False); XtManageChild(darea); } } } XtSetMappedWhenManaged(sdata->widget, False); XtManageChild(sdata->widget); AWT_UNLOCK(); } /* * Class: sun_awt_motif_MScrollPanePeer * Method: pSetScrollChild * Signature: (Lsun/awt/motif/MComponentPeer;)V */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_pSetScrollChild (JNIEnv *env, jobject this, jobject child) { struct ComponentData *cdata; struct ComponentData *sdata; jobject target; AWT_LOCK(); target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); if (JNU_IsNull(env, child) || JNU_IsNull(env, target)) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } cdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env,child,mComponentPeerIDs.pData); sdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData); if (sdata == NULL || cdata == NULL || sdata->widget == NULL || cdata->widget == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } if ((*env)->GetIntField(env, target, scrollPaneIDs.scrollbarDisplayPolicy) == java_awt_ScrollPane_SCROLLBARS_NEVER) { /* Do Nothing */ } else { XmScrolledWindowSetAreas(sdata->widget, NULL, NULL, cdata->widget); /* XtInsertEventHandler(cdata->widget, StructureNotifyMask, FALSE, child_event_handler, sdata->widget, XtListHead); */ } AWT_UNLOCK(); } /* * Class: sun_awt_motif_MScrollPanePeer * Method: pSetIncrement * Signature: (III)V */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_pSetIncrement (JNIEnv *env, jobject this, jint orient, jint incrType, jint incr) { struct ComponentData *sdata; Widget scrollbar = NULL; AWT_LOCK(); sdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData); if (sdata == NULL || sdata->widget == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } if (!XtIsSubclass(sdata->widget, xmScrolledWindowWidgetClass)) { AWT_UNLOCK(); return; } if (orient == java_awt_Adjustable_VERTICAL) { XtVaGetValues(sdata->widget, XmNverticalScrollBar, &scrollbar, NULL); } else { XtVaGetValues(sdata->widget, XmNhorizontalScrollBar, &scrollbar, NULL); } if (scrollbar != NULL) { if (incrType == sun_awt_motif_MScrollPanePeer_UNIT_INCREMENT) { XtVaSetValues(scrollbar, XmNincrement, (XtArgVal) incr, NULL); } else { /* BLOCK_INCREMENT */ XtVaSetValues(scrollbar, XmNpageIncrement, (XtArgVal) incr, NULL); } } AWT_FLUSH_UNLOCK(); } /* * Class: sun_awt_motif_MScrollPanePeer * Method: pGetScrollbarSpace * Signature: (I)I */ JNIEXPORT jint JNICALL Java_sun_awt_motif_MScrollPanePeer_pGetScrollbarSpace (JNIEnv *env, jobject this, jint orient) { struct ComponentData *sdata; Widget scrollbar; Dimension thickness = 0; Dimension space = 0; Dimension highlight = 0; AWT_LOCK(); sdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData); if (sdata == NULL || sdata->widget == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return 0; } if (orient == java_awt_Adjustable_VERTICAL) { XtVaGetValues(sdata->widget, XmNverticalScrollBar, &scrollbar, XmNspacing, &space, NULL); XtVaGetValues(scrollbar, XmNwidth, &thickness, XmNhighlightThickness, &highlight, NULL); } else { XtVaGetValues(sdata->widget, XmNhorizontalScrollBar, &scrollbar, XmNspacing, &space, NULL); XtVaGetValues(scrollbar, XmNheight, &thickness, XmNhighlightThickness, &highlight, NULL); } AWT_UNLOCK(); return (jint) (thickness + space + 2 * highlight); } /* * Class: sun_awt_motif_MScrollPanePeer * Method: pGetBlockIncrement * Signature: (I)I */ JNIEXPORT jint JNICALL Java_sun_awt_motif_MScrollPanePeer_pGetBlockIncrement (JNIEnv *env, jobject this, jint orient) { int32_t pageIncr = 0; struct ComponentData *sdata; Widget scrollbar; AWT_LOCK(); sdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData); if (sdata == NULL || sdata->widget == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return 0; } if (orient == java_awt_Adjustable_VERTICAL) { XtVaGetValues(sdata->widget, XmNverticalScrollBar, &scrollbar, NULL); XtVaGetValues(scrollbar, XmNpageIncrement, &pageIncr, NULL); } else { XtVaGetValues(sdata->widget, XmNhorizontalScrollBar, &scrollbar, NULL); XtVaGetValues(scrollbar, XmNpageIncrement, &pageIncr, NULL); } AWT_UNLOCK(); return (jint) (pageIncr); } /* * Class: sun_awt_motif_MScrollPanePeer * Method: pInsets * Signature: (IIII)Ljava/awt/Insets; */ JNIEXPORT jobject JNICALL Java_sun_awt_motif_MScrollPanePeer_pInsets (JNIEnv *env, jobject this, jint width, jint height, jint childWidth, jint childHeight) { struct ComponentData *sdata; jobject target; jobject insets = NULL; Widget hsb, vsb; Dimension hsbThickness, hsbHighlight, hsbSpace = 0, vsbThickness, vsbHighlight, vsbSpace = 0, space, border, shadow, hMargin, vMargin; unsigned char placement; Boolean hsbVisible, vsbVisible; jint sbDisplay; int32_t top, left, right, bottom; jclass clazz; jmethodID mid; AWT_LOCK(); sdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData); target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); if (JNU_IsNull(env, target) || sdata == NULL || sdata->widget == NULL) { JNU_ThrowNullPointerException(env, "sdata is NULL"); AWT_UNLOCK(); return 0; } sbDisplay = (*env)->GetIntField(env, target, scrollPaneIDs.scrollbarDisplayPolicy); /* REMIND: investigate caching these values rather than querying for * them each time. */ if (sbDisplay == java_awt_ScrollPane_SCROLLBARS_NEVER) { XtVaGetValues(sdata->widget, XmNshadowThickness, &shadow, NULL); space = border = hMargin = vMargin = 0; } else { XtVaGetValues(sdata->widget, XmNverticalScrollBar, &vsb, XmNhorizontalScrollBar, &hsb, XmNscrollBarPlacement, &placement, XmNspacing, &space, XmNshadowThickness, &shadow, XmNscrolledWindowMarginHeight, &vMargin, XmNscrolledWindowMarginWidth, &hMargin, XmNborderWidth, &border, NULL); XtVaGetValues(vsb, XmNwidth, &vsbThickness, XmNhighlightThickness, &vsbHighlight, NULL); XtVaGetValues(hsb, XmNheight, &hsbThickness, XmNhighlightThickness, &hsbHighlight, NULL); hsbSpace = hsbThickness + space + hsbHighlight; vsbSpace = vsbThickness + space + vsbHighlight; /* XtVaGetValues(clip, XmNwidth, &clipw, XmNheight, &cliph, XmNx, &clipx, XmNy, &clipy, NULL); printf("insets: spacing=%d shadow=%d swMarginH=%d swMarginW=%d border=%d ; \ vsb=%d vsbHL=%d ; hsb=%d hsbHL=%d ; %dx%d ->clip=%d,%d %dx%d\n", space, shadow, vMargin, hMargin, border, vsbThickness, vsbHighlight, hsbThickness, hsbHighlight, w, h, clipx, clipy, clipw, cliph); */ } /* We unfortunately have to use the size parameters to determine * whether or not "as needed" scrollbars are currently present or * not because we can't necessarily rely on getting valid geometry * values straight from the Motif widgets until they are mapped. :( */ switch (sbDisplay) { case java_awt_ScrollPane_SCROLLBARS_NEVER: vsbVisible = hsbVisible = FALSE; break; case java_awt_ScrollPane_SCROLLBARS_ALWAYS: vsbVisible = hsbVisible = TRUE; break; case java_awt_ScrollPane_SCROLLBARS_AS_NEEDED: default: vsbVisible = hsbVisible = FALSE; if (childWidth > width - 2 * shadow) { hsbVisible = TRUE; } if (childHeight > height - 2 * shadow) { vsbVisible = TRUE; } if (!hsbVisible && vsbVisible && childWidth > width - 2 * shadow - vsbSpace) { hsbVisible = TRUE; } else if (!vsbVisible && hsbVisible && childHeight > height - 2 * shadow - hsbSpace) { vsbVisible = TRUE; } } top = bottom = shadow + vMargin; left = right = shadow + hMargin; if (sbDisplay != java_awt_ScrollPane_SCROLLBARS_NEVER) { switch (placement) { case XmBOTTOM_RIGHT: bottom += (hsbVisible ? hsbSpace : (vsbVisible ? vsbHighlight : 0)); right += (vsbVisible ? vsbSpace : (hsbVisible ? hsbHighlight : 0)); top += (vsbVisible ? vsbHighlight : 0); left += (hsbVisible ? hsbHighlight : 0); break; case XmBOTTOM_LEFT: bottom += (hsbVisible ? hsbSpace : (vsbVisible ? vsbHighlight : 0)); left += (vsbVisible ? hsbSpace : (hsbVisible ? hsbHighlight : 0)); top += (vsbVisible ? vsbHighlight : 0); right += (hsbVisible ? hsbHighlight : 0); break; case XmTOP_RIGHT: top += (hsbVisible ? hsbSpace : (vsbVisible ? vsbHighlight : 0)); right += (vsbVisible ? vsbSpace : (hsbVisible ? hsbHighlight : 0)); bottom += (vsbVisible ? vsbHighlight : 0); left += (hsbVisible ? hsbHighlight : 0); break; case XmTOP_LEFT: top += (hsbVisible ? hsbSpace : (vsbVisible ? vsbHighlight : 0)); left += (vsbVisible ? vsbSpace : (hsbVisible ? hsbHighlight : 0)); bottom += (vsbVisible ? vsbHighlight : 0); right += (hsbVisible ? hsbHighlight : 0); } } /* Deadlock prevention: * don't hold the toolkit lock while invoking constructor. */ AWT_UNLOCK(); clazz = (*env)->FindClass(env, "java/awt/Insets"); mid = (*env)->GetMethodID(env, clazz, "", "(IIII)V"); if (mid != NULL) { insets = (*env)->NewObject(env, clazz, mid, (jint) top, (jint) left, (jint) bottom, (jint) right); } /* This should catch both method not found and error exceptions */ if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } if (JNU_IsNull(env, insets)) { JNU_ThrowNullPointerException(env, "NullPointerException: insets constructor failed"); } return insets; } /* * Class: sun_awt_motif_MScrollPanePeer * Method: setScrollPosition * Signature: (II)V */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_setScrollPosition (JNIEnv *env, jobject this, jint x, jint y) { struct ComponentData *sdata; jobject target; Widget hsb, vsb; int32_t size, incr, pIncr; AWT_LOCK(); sdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData); target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); if (JNU_IsNull(env, target) || sdata == NULL || sdata->widget == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } if ((*env)->GetIntField(env, target, scrollPaneIDs.scrollbarDisplayPolicy) == java_awt_ScrollPane_SCROLLBARS_NEVER) { WidgetList children; Cardinal numChildren; XtVaGetValues(sdata->widget, XmNchildren, &children, XmNnumChildren, &numChildren, NULL); if (numChildren < 1) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } XtMoveWidget(children[0], (Position) -x, (Position) -y); } else { int32_t sb_min = 0; int32_t sb_max = 0; XtVaGetValues(sdata->widget, XmNhorizontalScrollBar, &hsb, XmNverticalScrollBar, &vsb, NULL); if (vsb) { XtVaGetValues(vsb, XmNincrement, &incr, XmNpageIncrement, &pIncr, XmNsliderSize, &size, XmNminimum, &sb_min, XmNmaximum, &sb_max, NULL); /* Bug 4208972, 4275934 : Do range checking for scroll bar value. */ if (y < sb_min) y = sb_min; if (y > (sb_max - size)) y = sb_max - size; XmScrollBarSetValues(vsb, (int32_t) y, size, incr, pIncr, TRUE); } if (hsb) { XtVaGetValues(hsb, XmNincrement, &incr, XmNpageIncrement, &pIncr, XmNsliderSize, &size, XmNminimum, &sb_min, XmNmaximum, &sb_max, NULL); /* Bug 4208972, 4275934 : Do range checking for scroll bar value. */ if (x < sb_min) x = sb_min; if (x > (sb_max - size)) x = sb_max - size; XmScrollBarSetValues(hsb, (int32_t) x, size, incr, pIncr, TRUE); } } AWT_FLUSH_UNLOCK(); } /* * Class: sun_awt_motif_MScrollPanePeer * Method: pGetShadow * Signature: ()I */ JNIEXPORT jint JNICALL Java_sun_awt_motif_MScrollPanePeer_pGetShadow( JNIEnv *env, jobject this) { struct ComponentData *sdata; jobject target; Dimension shadow=0 ; AWT_LOCK() ; sdata = (struct ComponentData *) (*env)->GetLongField(env,this,mComponentPeerIDs.pData); target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); if (JNU_IsNull(env, target) || sdata == NULL || sdata->widget == NULL) { JNU_ThrowNullPointerException(env, "sdata is NULL"); AWT_UNLOCK(); return 0; } XtVaGetValues(sdata->widget, XmNshadowThickness, &shadow, NULL); AWT_UNLOCK() ; return((jint)shadow) ; } /* * Class: sun_awt_motif_MScrollPanePeer * Method: setTypedValue * Signature: (Ljava/awt/ScrollPaneAdjustable;II)V */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_setTypedValue(JNIEnv *env, jobject peer, jobject adjustable, jint value, jint type) { static jmethodID setTypedValueMID = 0; if (setTypedValueMID == NULL) { jclass clazz = (*env)->FindClass(env, "java/awt/ScrollPaneAdjustable"); if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); return; } setTypedValueMID = (*env)->GetMethodID(env, clazz, "setTypedValue", "(II)V"); (*env)->DeleteLocalRef(env, clazz); DASSERT(setTypedValueMID != NULL); } (*env)->CallVoidMethod(env, adjustable, setTypedValueMID, value, type); }