jdk/src/solaris/native/sun/awt/awt_ScrollPane.c
changeset 1192 715cf9378c53
parent 1051 90cf935adb35
parent 1191 f142c1da78c2
child 1193 41afb8ee8f45
equal deleted inserted replaced
1051:90cf935adb35 1192:715cf9378c53
     1 /*
       
     2  * Copyright 1996-2002 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 #ifdef HEADLESS
       
    27     #error This file should not be included in headless library
       
    28 #endif
       
    29 
       
    30 #include "awt_p.h"
       
    31 
       
    32 #include "java_awt_Adjustable.h"
       
    33 #include "java_awt_Insets.h"
       
    34 #include "java_awt_ScrollPane.h"
       
    35 #include "java_awt_event_AdjustmentEvent.h"
       
    36 #include "sun_awt_motif_MComponentPeer.h"
       
    37 #include "sun_awt_motif_MScrollPanePeer.h"
       
    38 #include "java_awt_AWTEvent.h"
       
    39 
       
    40 #include "awt_Component.h"
       
    41 #include "canvas.h"
       
    42 
       
    43 #include <jni.h>
       
    44 #include <jni_util.h>
       
    45 #include <Xm/ScrolledWP.h>
       
    46 
       
    47 extern struct MComponentPeerIDs mComponentPeerIDs;
       
    48 extern AwtGraphicsConfigDataPtr
       
    49     copyGraphicsConfigToPeer(JNIEnv *env, jobject this);
       
    50 
       
    51 /* fieldIDs for ScrollPane fields that may be accessed from C */
       
    52 static struct ScrollPaneIDs {
       
    53     jfieldID scrollbarDisplayPolicy;
       
    54 } scrollPaneIDs;
       
    55 
       
    56 /*
       
    57  * Class:     java_awt_ScrollPane
       
    58  * Method:    initIDs
       
    59  * Signature: ()V
       
    60  */
       
    61 
       
    62 /* This function gets called from the static initializer for
       
    63    ScrollPane.java to initialize the fieldIDs for fields that may
       
    64    be accessed from C */
       
    65 
       
    66 JNIEXPORT void JNICALL Java_java_awt_ScrollPane_initIDs
       
    67   (JNIEnv *env, jclass cls)
       
    68 {
       
    69     scrollPaneIDs.scrollbarDisplayPolicy =
       
    70       (*env)->GetFieldID(env, cls, "scrollbarDisplayPolicy", "I");
       
    71 }
       
    72 
       
    73 /* fieldIDs for MScrollPanePeer fields that may be accessed from C */
       
    74 static struct MScrollPanePeerIDs {
       
    75     jmethodID postScrollEventID;
       
    76 } mScrollPanePeerIDs;
       
    77 
       
    78 /*
       
    79  * Class:     sun_awt_motif_MScrollPanePeer
       
    80  * Method:    initIDs
       
    81  * Signature: ()V
       
    82  */
       
    83 
       
    84 /* This function gets called from the static initializer for
       
    85    MScrollPanePeer.java to initialize the fieldIDs for fields that may
       
    86    be accessed from C */
       
    87 
       
    88 JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_initIDs
       
    89   (JNIEnv *env, jclass cls)
       
    90 {
       
    91     mScrollPanePeerIDs.postScrollEventID =
       
    92         (*env)->GetMethodID(env, cls, "postScrollEvent", "(IIIZ)V");
       
    93 }
       
    94 
       
    95 static void
       
    96 dump_scroll_attrs(Widget scrollbar)
       
    97 {
       
    98     unsigned char orient;
       
    99     int32_t value, size, incr, pIncr, max, min;
       
   100 
       
   101     XtVaGetValues(scrollbar,
       
   102                   XmNvalue, &value,
       
   103                   XmNincrement, &incr,
       
   104                   XmNpageIncrement, &pIncr,
       
   105                   XmNsliderSize, &size,
       
   106                   XmNmaximum, &max,
       
   107                   XmNminimum, &min,
       
   108                   XmNorientation, &orient,
       
   109                   NULL);
       
   110 
       
   111     jio_fprintf(stdout, "%s: min=%d max=%d slider-size=%d incr=%d pageIncr=%d value = %d\n",
       
   112                 orient == XmVERTICAL ? "VSB" : "HSB", min, max, size,
       
   113                 incr, pIncr, value);
       
   114 }
       
   115 
       
   116 
       
   117 /*
       
   118  * client_data is MScrollPanePeer instance
       
   119  */
       
   120 static void
       
   121 postScrollEvent(jint jorient, jobject peer, XmScrollBarCallbackStruct *scroll)
       
   122 {
       
   123     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   124 
       
   125     jint jscrollcode;
       
   126     jboolean jadjusting = JNI_FALSE;
       
   127 
       
   128     switch (scroll->reason) {
       
   129       case XmCR_DECREMENT:
       
   130           jscrollcode = java_awt_event_AdjustmentEvent_UNIT_DECREMENT;
       
   131           break;
       
   132       case XmCR_INCREMENT:
       
   133           jscrollcode = java_awt_event_AdjustmentEvent_UNIT_INCREMENT;
       
   134           break;
       
   135       case XmCR_PAGE_DECREMENT:
       
   136           jscrollcode = java_awt_event_AdjustmentEvent_BLOCK_DECREMENT;
       
   137           break;
       
   138       case XmCR_PAGE_INCREMENT:
       
   139           jscrollcode = java_awt_event_AdjustmentEvent_BLOCK_INCREMENT;
       
   140           break;
       
   141       case XmCR_DRAG:
       
   142           jscrollcode = java_awt_event_AdjustmentEvent_TRACK;
       
   143           jadjusting = JNI_TRUE;
       
   144           break;
       
   145       case XmCR_VALUE_CHANGED:  /* drag finished */
       
   146       case XmCR_TO_TOP:
       
   147       case XmCR_TO_BOTTOM:
       
   148           jscrollcode = java_awt_event_AdjustmentEvent_TRACK;
       
   149           break;
       
   150       default:
       
   151           DASSERT(FALSE);
       
   152           return;
       
   153     }
       
   154 
       
   155     (*env)->CallVoidMethod(env, peer,  mScrollPanePeerIDs.postScrollEventID,
       
   156         jorient, jscrollcode, (jint)scroll->value, jadjusting);
       
   157 
       
   158     if ((*env)->ExceptionOccurred(env)) {
       
   159         (*env)->ExceptionDescribe(env);
       
   160         (*env)->ExceptionClear(env);
       
   161     }
       
   162 }
       
   163 
       
   164 /*
       
   165  * client_data is MScrollPanePeer instance
       
   166  */
       
   167 static void
       
   168 ScrollPane_scrollV(Widget w, XtPointer client_data, XtPointer call_data)
       
   169 {
       
   170     postScrollEvent(java_awt_Adjustable_VERTICAL, (jobject)client_data,
       
   171                     (XmScrollBarCallbackStruct *)call_data);
       
   172 }
       
   173 
       
   174 /*
       
   175  * client_data is MScrollPanePeer instance
       
   176  */
       
   177 static void
       
   178 ScrollPane_scrollH(Widget w, XtPointer client_data, XtPointer call_data)
       
   179 {
       
   180     postScrollEvent(java_awt_Adjustable_HORIZONTAL, (jobject)client_data,
       
   181                     (XmScrollBarCallbackStruct *)call_data);
       
   182 }
       
   183 
       
   184 
       
   185 typedef XmNavigability (*NavigableCallback) (Widget);
       
   186 
       
   187 NavigableCallback oldClipNavigable = NULL;
       
   188 Boolean clipCallbackInitialized = False;
       
   189 XmNavigability MyClipNavigable(Widget wid) {
       
   190     // We've installed this function for ClipWindow
       
   191     if (XmIsClipWindow(wid)) {
       
   192         // To be able to request focus on ClipWindow by call
       
   193         // XmProcessTraversal(, XmTRAVERSE_CURRENT) we need to make
       
   194         // it return XmCONTROL_NAVIGABLE. Default implementation returns
       
   195         // DESCENDANTS_TAB_NAVIGABLE which doesn't allow this.
       
   196         return XmCONTROL_NAVIGABLE;
       
   197     }
       
   198     if (oldClipNavigable) {
       
   199         return oldClipNavigable(wid);
       
   200     }
       
   201     // this will never happen
       
   202     return XmCONTROL_NAVIGABLE;
       
   203 }
       
   204 
       
   205 const char * ScrollPaneManagerName = "ScrolledWindowClipWindow";
       
   206 NavigableCallback oldManagerNavigable = NULL;
       
   207 Boolean managerCallbackInitialized = False;
       
   208 XmNavigability MyManagerNavigable(Widget wid) {
       
   209     // We've installed this function for Manager
       
   210     // with the name ScrollPaneManagerName
       
   211     if (XmIsManager(wid)
       
   212         && ( XtName(wid) != NULL && strcmp(XtName(wid), ScrollPaneManagerName) == 0) )
       
   213     {
       
   214         // To be able to request focus on Manager by call
       
   215         // XmProcessTraversal(, XmTRAVERSE_CURRENT) we need to make
       
   216         // it return XmCONTROL_NAVIGABLE. Default implementation returns
       
   217         // DESCENDANTS_TAB_NAVIGABLE which doesn't allow this.
       
   218         return XmCONTROL_NAVIGABLE;
       
   219     }
       
   220     if (oldManagerNavigable) {
       
   221         return oldManagerNavigable(wid);
       
   222     }
       
   223     // this will never happen
       
   224     return XmCONTROL_NAVIGABLE;
       
   225 }
       
   226 
       
   227 /*
       
   228  * Class:     sun_awt_motif_MScrollPanePeer
       
   229  * Method:    create
       
   230  * Signature: (Lsun/awt/motif/MComponentPeer;)V
       
   231  */
       
   232 JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_create
       
   233   (JNIEnv *env, jobject this, jobject parent)
       
   234 {
       
   235     int32_t argc;
       
   236 #define MAX_ARGC 40
       
   237     Arg args[MAX_ARGC];
       
   238     struct ComponentData *wdata;
       
   239     struct ComponentData *sdata;
       
   240     jobject target;
       
   241     Pixel bg;
       
   242     Widget vsb, hsb;
       
   243     jint sbDisplay;
       
   244     jobject globalRef = awtJNI_CreateAndSetGlobalRef(env, this);
       
   245     AwtGraphicsConfigDataPtr adata;
       
   246 
       
   247     AWT_LOCK();
       
   248 
       
   249     if (JNU_IsNull(env, parent)) {
       
   250         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   251         AWT_UNLOCK();
       
   252 
       
   253         return;
       
   254     }
       
   255     target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
       
   256     wdata = (struct ComponentData *)
       
   257       JNU_GetLongFieldAsPtr(env,parent,mComponentPeerIDs.pData);
       
   258 
       
   259     if (JNU_IsNull(env, target) || wdata == NULL) {
       
   260         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   261         AWT_UNLOCK();
       
   262 
       
   263         return;
       
   264     }
       
   265     sdata = ZALLOC(ComponentData);
       
   266     JNU_SetLongFieldFromPtr(env,this,mComponentPeerIDs.pData,sdata);
       
   267 
       
   268     if (sdata == NULL) {
       
   269         JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
   270         AWT_UNLOCK();
       
   271         return;
       
   272     }
       
   273     XtVaGetValues(wdata->widget, XmNbackground, &bg, NULL);
       
   274 
       
   275     adata = copyGraphicsConfigToPeer(env, this);
       
   276 
       
   277     argc = 0;
       
   278 
       
   279     sbDisplay =
       
   280       (*env)->GetIntField(env, target, scrollPaneIDs.scrollbarDisplayPolicy);
       
   281 
       
   282     XtSetArg(args[argc], XmNuserData, (XtPointer) globalRef);
       
   283     argc++;
       
   284 
       
   285 
       
   286     if (sbDisplay == java_awt_ScrollPane_SCROLLBARS_NEVER) {
       
   287         DASSERT(!(argc > MAX_ARGC));
       
   288         sdata->widget = XtCreateWidget(ScrollPaneManagerName,
       
   289                                        xmManagerWidgetClass, wdata->widget,
       
   290                                        args, argc);
       
   291 
       
   292         {
       
   293             // To be able to request focus on Manager by call
       
   294             // XmProcessTraversal(, XmTRAVERSE_CURRENT) we need to make
       
   295             // it return XmCONTROL_NAVIGABLE from widgetNavigable callback.
       
   296             // Default implementation returns DESCENDANTS_TAB_NAVIGABLE
       
   297             // which doesn't allow this.
       
   298             if (!managerCallbackInitialized) {
       
   299                 XmBaseClassExt *er;
       
   300                 WidgetClass wc;
       
   301                 managerCallbackInitialized = True;
       
   302                 wc = (WidgetClass) &xmManagerClassRec;
       
   303                 er = _XmGetBaseClassExtPtr(wc, XmQmotif);
       
   304                 oldManagerNavigable = (*er)->widgetNavigable;
       
   305                 (*er)->widgetNavigable = MyManagerNavigable;
       
   306             }
       
   307         }
       
   308     }
       
   309     else
       
   310     {
       
   311         XtSetArg(args[argc], XmNscrollingPolicy, XmAUTOMATIC);
       
   312         argc++;
       
   313         XtSetArg(args[argc], XmNvisualPolicy, XmCONSTANT);
       
   314         argc++;
       
   315         if (sbDisplay == java_awt_ScrollPane_SCROLLBARS_ALWAYS) {
       
   316             DASSERT(!(argc > MAX_ARGC));
       
   317             XtSetArg(args[argc], XmNscrollBarDisplayPolicy, XmSTATIC);
       
   318             argc++;
       
   319         } else {
       
   320             XtSetArg(args[argc], XmNscrollBarDisplayPolicy, XmAS_NEEDED);
       
   321             argc++;
       
   322         }
       
   323 
       
   324         XtSetArg(args[argc], XmNspacing, 0);
       
   325         argc++;
       
   326         XtSetArg (args[argc], XmNscreen,
       
   327                   ScreenOfDisplay(awt_display,
       
   328                                   adata->awt_visInfo.screen));
       
   329         argc++;
       
   330 
       
   331         DASSERT(!(argc > MAX_ARGC));
       
   332         sdata->widget = XmCreateScrolledWindow(wdata->widget, "scroller", args, argc);
       
   333 
       
   334         XtVaGetValues(sdata->widget,
       
   335                       XmNverticalScrollBar, &vsb,
       
   336                       XmNhorizontalScrollBar, &hsb,
       
   337                       NULL);
       
   338 
       
   339         if (vsb != NULL) {
       
   340             XtAddCallback(vsb, XmNincrementCallback, ScrollPane_scrollV, (XtPointer) globalRef);
       
   341             XtAddCallback(vsb, XmNdecrementCallback, ScrollPane_scrollV, (XtPointer) globalRef);
       
   342             XtAddCallback(vsb, XmNpageIncrementCallback, ScrollPane_scrollV, (XtPointer) globalRef);
       
   343             XtAddCallback(vsb, XmNpageDecrementCallback, ScrollPane_scrollV, (XtPointer) globalRef);
       
   344             XtAddCallback(vsb, XmNtoTopCallback, ScrollPane_scrollV, (XtPointer) globalRef);
       
   345             XtAddCallback(vsb, XmNtoBottomCallback, ScrollPane_scrollV, (XtPointer) globalRef);
       
   346             XtAddCallback(vsb, XmNvalueChangedCallback, ScrollPane_scrollV, (XtPointer) globalRef);
       
   347             XtAddCallback(vsb, XmNdragCallback, ScrollPane_scrollV, (XtPointer) globalRef);
       
   348 
       
   349             XtVaSetValues(vsb, XmNhighlightThickness, 0, NULL);
       
   350         }
       
   351         if (hsb != NULL) {
       
   352             XtAddCallback(hsb, XmNincrementCallback, ScrollPane_scrollH, (XtPointer) globalRef);
       
   353             XtAddCallback(hsb, XmNdecrementCallback, ScrollPane_scrollH, (XtPointer) globalRef);
       
   354             XtAddCallback(hsb, XmNpageIncrementCallback, ScrollPane_scrollH, (XtPointer) globalRef);
       
   355             XtAddCallback(hsb, XmNpageDecrementCallback, ScrollPane_scrollH, (XtPointer) globalRef);
       
   356             XtAddCallback(hsb, XmNtoTopCallback, ScrollPane_scrollH, (XtPointer) globalRef);
       
   357             XtAddCallback(hsb, XmNtoBottomCallback, ScrollPane_scrollH, (XtPointer) globalRef);
       
   358             XtAddCallback(hsb, XmNvalueChangedCallback, ScrollPane_scrollH, (XtPointer) globalRef);
       
   359             XtAddCallback(hsb, XmNdragCallback, ScrollPane_scrollH, (XtPointer) globalRef);
       
   360 
       
   361             XtVaSetValues(hsb, XmNhighlightThickness, 0, NULL);
       
   362         }
       
   363         {
       
   364             /**
       
   365              * Fix for 4033837 - ScrollPane doesn't generate mouse, focus, key events
       
   366              * If ScrollPane created with ALWAYS or AS_NEEDED scrollbars policy then
       
   367              * the upper widget is ClipWindow. We should install callbacks on it to
       
   368              * receive event notifications.
       
   369              */
       
   370             Widget clip = XtNameToWidget(sdata->widget, "*ClipWindow");
       
   371             if (clip != NULL) {
       
   372                 // To be able to request focus on Manager by call
       
   373                 // XmProcessTraversal(, XmTRAVERSE_CURRENT) we need to make
       
   374                 // it return XmCONTROL_NAVIGABLE from widgetNavigable callback.
       
   375                 // Default implementation returns DESCENDANTS_TAB_NAVIGABLE
       
   376                 // which doesn't allow this.
       
   377                 if (!clipCallbackInitialized) {
       
   378                     XmBaseClassExt *er;
       
   379                     clipCallbackInitialized = True;
       
   380                     er = _XmGetBaseClassExtPtr(XtClass(clip), XmQmotif);
       
   381                     oldClipNavigable = (*er)->widgetNavigable;
       
   382                     (*er)->widgetNavigable = MyClipNavigable;
       
   383                 }
       
   384                 awt_addWidget(clip, sdata->widget, globalRef, java_awt_AWTEvent_MOUSE_EVENT_MASK |
       
   385                               java_awt_AWTEvent_MOUSE_MOTION_EVENT_MASK | java_awt_AWTEvent_KEY_EVENT_MASK);
       
   386             }
       
   387         }
       
   388         {
       
   389             /**
       
   390              * Fix for 4033837 - ScrollPane with ALWAYS doesn't have scrollbars visible
       
   391              * It seems to be the bug in Motif, the workaround is to add empty child.
       
   392              * User child will replace it when needed. This doesn't work if child had been
       
   393              * removed.
       
   394              */
       
   395             if (sbDisplay == java_awt_ScrollPane_SCROLLBARS_ALWAYS) {
       
   396                 Widget darea = NULL;
       
   397                 argc = 0;
       
   398                 XtSetArg(args[argc], XmNwidth, 1);
       
   399                 argc++;
       
   400                 XtSetArg(args[argc], XmNheight, 1);
       
   401                 argc++;
       
   402                 XtSetArg(args[argc], XmNmarginWidth, 0);
       
   403                 argc++;
       
   404                 XtSetArg(args[argc], XmNmarginHeight, 0);
       
   405                 argc++;
       
   406                 XtSetArg(args[argc], XmNspacing, 0);
       
   407                 argc++;
       
   408                 XtSetArg(args[argc], XmNresizePolicy, XmRESIZE_NONE);
       
   409                 argc++;
       
   410                 darea = XmCreateDrawingArea(sdata->widget, "null_child", args, argc);
       
   411 
       
   412                 XmScrolledWindowSetAreas(sdata->widget, NULL, NULL, darea);
       
   413                 XtSetMappedWhenManaged(darea, False);
       
   414                 XtManageChild(darea);
       
   415             }
       
   416         }
       
   417 
       
   418     }
       
   419 
       
   420     XtSetMappedWhenManaged(sdata->widget, False);
       
   421     XtManageChild(sdata->widget);
       
   422 
       
   423     AWT_UNLOCK();
       
   424 }
       
   425 
       
   426 /*
       
   427  * Class:     sun_awt_motif_MScrollPanePeer
       
   428  * Method:    pSetScrollChild
       
   429  * Signature: (Lsun/awt/motif/MComponentPeer;)V
       
   430  */
       
   431 JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_pSetScrollChild
       
   432   (JNIEnv *env, jobject this, jobject child)
       
   433 {
       
   434     struct ComponentData *cdata;
       
   435     struct ComponentData *sdata;
       
   436     jobject target;
       
   437 
       
   438     AWT_LOCK();
       
   439 
       
   440     target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
       
   441 
       
   442     if (JNU_IsNull(env, child) || JNU_IsNull(env, target)) {
       
   443         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   444         AWT_UNLOCK();
       
   445 
       
   446         return;
       
   447     }
       
   448     cdata = (struct ComponentData *)
       
   449         JNU_GetLongFieldAsPtr(env,child,mComponentPeerIDs.pData);
       
   450     sdata = (struct ComponentData *)
       
   451         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   452 
       
   453     if (sdata == NULL || cdata == NULL || sdata->widget == NULL || cdata->widget == NULL) {
       
   454         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   455         AWT_UNLOCK();
       
   456 
       
   457         return;
       
   458     }
       
   459     if ((*env)->GetIntField(env, target, scrollPaneIDs.scrollbarDisplayPolicy)
       
   460         == java_awt_ScrollPane_SCROLLBARS_NEVER) {
       
   461         /* Do Nothing */
       
   462     } else {
       
   463         XmScrolledWindowSetAreas(sdata->widget, NULL, NULL, cdata->widget);
       
   464         /*
       
   465           XtInsertEventHandler(cdata->widget, StructureNotifyMask, FALSE,
       
   466           child_event_handler, sdata->widget, XtListHead);
       
   467         */
       
   468     }
       
   469 
       
   470     AWT_UNLOCK();
       
   471 }
       
   472 
       
   473 /*
       
   474  * Class:     sun_awt_motif_MScrollPanePeer
       
   475  * Method:    pSetIncrement
       
   476  * Signature: (III)V
       
   477  */
       
   478 JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_pSetIncrement
       
   479   (JNIEnv *env, jobject this, jint orient, jint incrType, jint incr)
       
   480 {
       
   481     struct ComponentData *sdata;
       
   482     Widget scrollbar = NULL;
       
   483 
       
   484     AWT_LOCK();
       
   485 
       
   486     sdata = (struct ComponentData *)
       
   487         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   488 
       
   489     if (sdata == NULL || sdata->widget == NULL) {
       
   490         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   491         AWT_UNLOCK();
       
   492         return;
       
   493     }
       
   494     if (!XtIsSubclass(sdata->widget, xmScrolledWindowWidgetClass)) {
       
   495         AWT_UNLOCK();
       
   496         return;
       
   497     }
       
   498     if (orient == java_awt_Adjustable_VERTICAL) {
       
   499         XtVaGetValues(sdata->widget,
       
   500                       XmNverticalScrollBar, &scrollbar,
       
   501                       NULL);
       
   502     } else {
       
   503         XtVaGetValues(sdata->widget,
       
   504                       XmNhorizontalScrollBar, &scrollbar,
       
   505                       NULL);
       
   506     }
       
   507 
       
   508     if (scrollbar != NULL) {
       
   509         if (incrType == sun_awt_motif_MScrollPanePeer_UNIT_INCREMENT) {
       
   510             XtVaSetValues(scrollbar,
       
   511                           XmNincrement, (XtArgVal) incr,
       
   512                           NULL);
       
   513 
       
   514         } else {
       
   515             /* BLOCK_INCREMENT */
       
   516             XtVaSetValues(scrollbar,
       
   517                           XmNpageIncrement, (XtArgVal) incr,
       
   518                           NULL);
       
   519         }
       
   520     }
       
   521     AWT_FLUSH_UNLOCK();
       
   522 }
       
   523 
       
   524 /*
       
   525  * Class:     sun_awt_motif_MScrollPanePeer
       
   526  * Method:    pGetScrollbarSpace
       
   527  * Signature: (I)I
       
   528  */
       
   529 JNIEXPORT jint JNICALL Java_sun_awt_motif_MScrollPanePeer_pGetScrollbarSpace
       
   530   (JNIEnv *env, jobject this, jint orient)
       
   531 {
       
   532     struct ComponentData *sdata;
       
   533     Widget scrollbar;
       
   534     Dimension thickness = 0;
       
   535     Dimension space = 0;
       
   536     Dimension highlight = 0;
       
   537 
       
   538     AWT_LOCK();
       
   539 
       
   540     sdata = (struct ComponentData *)
       
   541         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   542     if (sdata == NULL || sdata->widget == NULL) {
       
   543         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   544         AWT_UNLOCK();
       
   545         return 0;
       
   546     }
       
   547     if (orient == java_awt_Adjustable_VERTICAL) {
       
   548         XtVaGetValues(sdata->widget,
       
   549                       XmNverticalScrollBar, &scrollbar,
       
   550                       XmNspacing, &space,
       
   551                       NULL);
       
   552         XtVaGetValues(scrollbar,
       
   553                       XmNwidth, &thickness,
       
   554                       XmNhighlightThickness, &highlight,
       
   555                       NULL);
       
   556     } else {
       
   557         XtVaGetValues(sdata->widget,
       
   558                       XmNhorizontalScrollBar, &scrollbar,
       
   559                       XmNspacing, &space,
       
   560                       NULL);
       
   561         XtVaGetValues(scrollbar,
       
   562                       XmNheight, &thickness,
       
   563                       XmNhighlightThickness, &highlight,
       
   564                       NULL);
       
   565     }
       
   566 
       
   567     AWT_UNLOCK();
       
   568     return (jint) (thickness + space + 2 * highlight);
       
   569 }
       
   570 
       
   571 /*
       
   572  * Class:     sun_awt_motif_MScrollPanePeer
       
   573  * Method:    pGetBlockIncrement
       
   574  * Signature: (I)I
       
   575  */
       
   576 JNIEXPORT jint JNICALL Java_sun_awt_motif_MScrollPanePeer_pGetBlockIncrement
       
   577   (JNIEnv *env, jobject this, jint orient)
       
   578 {
       
   579     int32_t pageIncr = 0;
       
   580     struct ComponentData *sdata;
       
   581     Widget scrollbar;
       
   582 
       
   583     AWT_LOCK();
       
   584 
       
   585     sdata = (struct ComponentData *)
       
   586         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   587     if (sdata == NULL || sdata->widget == NULL) {
       
   588         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   589         AWT_UNLOCK();
       
   590         return 0;
       
   591     }
       
   592     if (orient == java_awt_Adjustable_VERTICAL) {
       
   593 
       
   594         XtVaGetValues(sdata->widget,
       
   595                       XmNverticalScrollBar, &scrollbar,
       
   596                       NULL);
       
   597         XtVaGetValues(scrollbar,
       
   598                       XmNpageIncrement, &pageIncr,
       
   599                       NULL);
       
   600     } else {
       
   601 
       
   602         XtVaGetValues(sdata->widget,
       
   603                       XmNhorizontalScrollBar, &scrollbar,
       
   604                       NULL);
       
   605         XtVaGetValues(scrollbar,
       
   606                       XmNpageIncrement, &pageIncr,
       
   607                       NULL);
       
   608     }
       
   609 
       
   610     AWT_UNLOCK();
       
   611     return (jint) (pageIncr);
       
   612 }
       
   613 
       
   614 /*
       
   615  * Class:     sun_awt_motif_MScrollPanePeer
       
   616  * Method:    pInsets
       
   617  * Signature: (IIII)Ljava/awt/Insets;
       
   618  */
       
   619 JNIEXPORT jobject JNICALL Java_sun_awt_motif_MScrollPanePeer_pInsets
       
   620   (JNIEnv *env, jobject this, jint width, jint height, jint childWidth, jint childHeight)
       
   621 {
       
   622     struct ComponentData *sdata;
       
   623     jobject target;
       
   624     jobject insets = NULL;
       
   625     Widget hsb, vsb;
       
   626     Dimension hsbThickness, hsbHighlight, hsbSpace = 0,
       
   627               vsbThickness, vsbHighlight, vsbSpace = 0,
       
   628               space, border, shadow, hMargin, vMargin;
       
   629     unsigned char placement;
       
   630     Boolean hsbVisible, vsbVisible;
       
   631     jint sbDisplay;
       
   632     int32_t top, left, right, bottom;
       
   633     jclass clazz;
       
   634     jmethodID mid;
       
   635 
       
   636     AWT_LOCK();
       
   637 
       
   638     sdata = (struct ComponentData *)
       
   639         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   640     target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
       
   641 
       
   642     if (JNU_IsNull(env, target) || sdata == NULL || sdata->widget == NULL)
       
   643     {
       
   644         JNU_ThrowNullPointerException(env, "sdata is NULL");
       
   645         AWT_UNLOCK();
       
   646         return 0;
       
   647     }
       
   648     sbDisplay =
       
   649       (*env)->GetIntField(env, target, scrollPaneIDs.scrollbarDisplayPolicy);
       
   650 
       
   651     /* REMIND: investigate caching these values rather than querying for
       
   652      * them each time.
       
   653      */
       
   654 
       
   655     if (sbDisplay == java_awt_ScrollPane_SCROLLBARS_NEVER) {
       
   656         XtVaGetValues(sdata->widget,
       
   657                       XmNshadowThickness, &shadow,
       
   658                       NULL);
       
   659         space = border = hMargin = vMargin = 0;
       
   660 
       
   661     } else {
       
   662         XtVaGetValues(sdata->widget,
       
   663                       XmNverticalScrollBar, &vsb,
       
   664                       XmNhorizontalScrollBar, &hsb,
       
   665                       XmNscrollBarPlacement, &placement,
       
   666                       XmNspacing, &space,
       
   667                       XmNshadowThickness, &shadow,
       
   668                       XmNscrolledWindowMarginHeight, &vMargin,
       
   669                       XmNscrolledWindowMarginWidth, &hMargin,
       
   670                       XmNborderWidth, &border,
       
   671                       NULL);
       
   672 
       
   673         XtVaGetValues(vsb,
       
   674                       XmNwidth, &vsbThickness,
       
   675                       XmNhighlightThickness, &vsbHighlight,
       
   676                       NULL);
       
   677 
       
   678         XtVaGetValues(hsb,
       
   679                       XmNheight, &hsbThickness,
       
   680                       XmNhighlightThickness, &hsbHighlight,
       
   681                       NULL);
       
   682 
       
   683         hsbSpace = hsbThickness + space + hsbHighlight;
       
   684         vsbSpace = vsbThickness + space + vsbHighlight;
       
   685 
       
   686 /*
       
   687   XtVaGetValues(clip,
       
   688   XmNwidth, &clipw, XmNheight, &cliph,
       
   689   XmNx, &clipx, XmNy, &clipy,
       
   690   NULL);
       
   691   printf("insets: spacing=%d shadow=%d swMarginH=%d swMarginW=%d border=%d ; \
       
   692   vsb=%d vsbHL=%d ; hsb=%d hsbHL=%d ; %dx%d ->clip=%d,%d %dx%d\n",
       
   693   space, shadow, vMargin, hMargin, border,
       
   694   vsbThickness, vsbHighlight, hsbThickness, hsbHighlight,
       
   695   w, h, clipx, clipy, clipw, cliph);
       
   696 */
       
   697     }
       
   698 
       
   699     /* We unfortunately have to use the size parameters to determine
       
   700      * whether or not "as needed" scrollbars are currently present or
       
   701      * not because we can't necessarily rely on getting valid geometry
       
   702      * values straight from the Motif widgets until they are mapped. :(
       
   703      */
       
   704     switch (sbDisplay) {
       
   705         case java_awt_ScrollPane_SCROLLBARS_NEVER:
       
   706             vsbVisible = hsbVisible = FALSE;
       
   707             break;
       
   708 
       
   709         case java_awt_ScrollPane_SCROLLBARS_ALWAYS:
       
   710             vsbVisible = hsbVisible = TRUE;
       
   711             break;
       
   712 
       
   713         case java_awt_ScrollPane_SCROLLBARS_AS_NEEDED:
       
   714         default:
       
   715             vsbVisible = hsbVisible = FALSE;
       
   716             if (childWidth > width - 2 * shadow) {
       
   717                 hsbVisible = TRUE;
       
   718             }
       
   719             if (childHeight > height - 2 * shadow) {
       
   720                 vsbVisible = TRUE;
       
   721             }
       
   722             if (!hsbVisible && vsbVisible && childWidth > width - 2 * shadow - vsbSpace) {
       
   723                 hsbVisible = TRUE;
       
   724             } else if (!vsbVisible && hsbVisible && childHeight > height - 2 * shadow - hsbSpace) {
       
   725                 vsbVisible = TRUE;
       
   726             }
       
   727     }
       
   728 
       
   729     top = bottom = shadow + vMargin;
       
   730     left = right = shadow + hMargin;
       
   731 
       
   732     if (sbDisplay != java_awt_ScrollPane_SCROLLBARS_NEVER) {
       
   733         switch (placement) {
       
   734             case XmBOTTOM_RIGHT:
       
   735                 bottom += (hsbVisible ? hsbSpace : (vsbVisible ? vsbHighlight : 0));
       
   736                 right += (vsbVisible ? vsbSpace : (hsbVisible ? hsbHighlight : 0));
       
   737                 top += (vsbVisible ? vsbHighlight : 0);
       
   738                 left += (hsbVisible ? hsbHighlight : 0);
       
   739                 break;
       
   740 
       
   741             case XmBOTTOM_LEFT:
       
   742                 bottom += (hsbVisible ? hsbSpace : (vsbVisible ? vsbHighlight : 0));
       
   743                 left += (vsbVisible ? hsbSpace : (hsbVisible ? hsbHighlight : 0));
       
   744                 top += (vsbVisible ? vsbHighlight : 0);
       
   745                 right += (hsbVisible ? hsbHighlight : 0);
       
   746                 break;
       
   747 
       
   748             case XmTOP_RIGHT:
       
   749                 top += (hsbVisible ? hsbSpace : (vsbVisible ? vsbHighlight : 0));
       
   750                 right += (vsbVisible ? vsbSpace : (hsbVisible ? hsbHighlight : 0));
       
   751                 bottom += (vsbVisible ? vsbHighlight : 0);
       
   752                 left += (hsbVisible ? hsbHighlight : 0);
       
   753                 break;
       
   754 
       
   755             case XmTOP_LEFT:
       
   756                 top += (hsbVisible ? hsbSpace : (vsbVisible ? vsbHighlight : 0));
       
   757                 left += (vsbVisible ? vsbSpace : (hsbVisible ? hsbHighlight : 0));
       
   758                 bottom += (vsbVisible ? vsbHighlight : 0);
       
   759                 right += (hsbVisible ? hsbHighlight : 0);
       
   760         }
       
   761     }
       
   762     /* Deadlock prevention:
       
   763      * don't hold the toolkit lock while invoking constructor.
       
   764      */
       
   765     AWT_UNLOCK();
       
   766 
       
   767     clazz = (*env)->FindClass(env, "java/awt/Insets");
       
   768     mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V");
       
   769     if (mid != NULL) {
       
   770         insets = (*env)->NewObject(env, clazz, mid,
       
   771                                    (jint) top,
       
   772                                    (jint) left,
       
   773                                    (jint) bottom,
       
   774                                    (jint) right);
       
   775 
       
   776     }
       
   777     /* This should catch both method not found and error exceptions */
       
   778     if ((*env)->ExceptionOccurred(env)) {
       
   779         (*env)->ExceptionDescribe(env);
       
   780         (*env)->ExceptionClear(env);
       
   781     }
       
   782     if (JNU_IsNull(env, insets)) {
       
   783         JNU_ThrowNullPointerException(env, "NullPointerException: insets constructor failed");
       
   784     }
       
   785     return insets;
       
   786 }
       
   787 
       
   788 /*
       
   789  * Class:     sun_awt_motif_MScrollPanePeer
       
   790  * Method:    setScrollPosition
       
   791  * Signature: (II)V
       
   792  */
       
   793 JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollPanePeer_setScrollPosition
       
   794   (JNIEnv *env, jobject this, jint x, jint y)
       
   795 {
       
   796     struct ComponentData *sdata;
       
   797     jobject target;
       
   798     Widget hsb, vsb;
       
   799     int32_t size, incr, pIncr;
       
   800 
       
   801     AWT_LOCK();
       
   802 
       
   803     sdata = (struct ComponentData *)
       
   804         JNU_GetLongFieldAsPtr(env,this,mComponentPeerIDs.pData);
       
   805     target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
       
   806 
       
   807     if (JNU_IsNull(env, target) || sdata == NULL || sdata->widget == NULL)
       
   808     {
       
   809         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   810         AWT_UNLOCK();
       
   811         return;
       
   812     }
       
   813     if ((*env)->GetIntField(env, target, scrollPaneIDs.scrollbarDisplayPolicy)
       
   814         == java_awt_ScrollPane_SCROLLBARS_NEVER) {
       
   815         WidgetList children;
       
   816         Cardinal numChildren;
       
   817 
       
   818         XtVaGetValues(sdata->widget,
       
   819                       XmNchildren, &children,
       
   820                       XmNnumChildren, &numChildren,
       
   821                       NULL);
       
   822 
       
   823         if (numChildren < 1) {
       
   824             JNU_ThrowNullPointerException(env, "NullPointerException");
       
   825             AWT_UNLOCK();
       
   826             return;
       
   827         }
       
   828         XtMoveWidget(children[0], (Position) -x, (Position) -y);
       
   829     } else {
       
   830         int32_t sb_min = 0;
       
   831         int32_t sb_max = 0;
       
   832         XtVaGetValues(sdata->widget,
       
   833                       XmNhorizontalScrollBar, &hsb,
       
   834                       XmNverticalScrollBar, &vsb,
       
   835                       NULL);
       
   836 
       
   837         if (vsb) {
       
   838             XtVaGetValues(vsb,
       
   839                           XmNincrement, &incr,
       
   840                           XmNpageIncrement, &pIncr,
       
   841                           XmNsliderSize, &size,
       
   842                           XmNminimum, &sb_min,
       
   843                           XmNmaximum, &sb_max,
       
   844                           NULL);
       
   845             /* Bug 4208972, 4275934 : Do range checking for scroll bar value. */
       
   846             if (y < sb_min)
       
   847                 y = sb_min;
       
   848             if (y > (sb_max - size))
       
   849                 y = sb_max - size;
       
   850             XmScrollBarSetValues(vsb, (int32_t) y, size, incr, pIncr, TRUE);
       
   851         }
       
   852         if (hsb) {
       
   853             XtVaGetValues(hsb,
       
   854                           XmNincrement, &incr,
       
   855                           XmNpageIncrement, &pIncr,
       
   856                           XmNsliderSize, &size,
       
   857                           XmNminimum, &sb_min,
       
   858                           XmNmaximum, &sb_max,
       
   859                           NULL);
       
   860             /* Bug 4208972, 4275934 : Do range checking for scroll bar value. */
       
   861             if (x < sb_min)
       
   862                 x = sb_min;
       
   863             if (x > (sb_max - size))
       
   864                 x = sb_max - size;
       
   865             XmScrollBarSetValues(hsb, (int32_t) x, size, incr, pIncr, TRUE);
       
   866         }
       
   867     }
       
   868     AWT_FLUSH_UNLOCK();
       
   869 }
       
   870 
       
   871 
       
   872 /*
       
   873  * Class:     sun_awt_motif_MScrollPanePeer
       
   874  * Method:    pGetShadow
       
   875  * Signature: ()I
       
   876  */
       
   877 JNIEXPORT jint JNICALL Java_sun_awt_motif_MScrollPanePeer_pGetShadow(
       
   878                        JNIEnv *env, jobject this) {
       
   879     struct ComponentData *sdata;
       
   880     jobject target;
       
   881     Dimension shadow=0 ;
       
   882 
       
   883     AWT_LOCK() ;
       
   884     sdata = (struct ComponentData *)
       
   885     (*env)->GetLongField(env,this,mComponentPeerIDs.pData);
       
   886     target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
       
   887 
       
   888     if (JNU_IsNull(env, target) || sdata == NULL || sdata->widget == NULL)
       
   889     {
       
   890         JNU_ThrowNullPointerException(env, "sdata is NULL");
       
   891         AWT_UNLOCK();
       
   892         return 0;
       
   893     }
       
   894 
       
   895     XtVaGetValues(sdata->widget,
       
   896         XmNshadowThickness,
       
   897         &shadow,
       
   898         NULL);
       
   899 
       
   900     AWT_UNLOCK() ;
       
   901 
       
   902     return((jint)shadow) ;
       
   903 }
       
   904 
       
   905 /*
       
   906  * Class:     sun_awt_motif_MScrollPanePeer
       
   907  * Method:    setTypedValue
       
   908  * Signature: (Ljava/awt/ScrollPaneAdjustable;II)V
       
   909  */
       
   910 JNIEXPORT void JNICALL
       
   911 Java_sun_awt_motif_MScrollPanePeer_setTypedValue(JNIEnv *env, jobject peer, jobject adjustable, jint value, jint type)
       
   912 {
       
   913     static jmethodID setTypedValueMID = 0;
       
   914     if (setTypedValueMID == NULL) {
       
   915         jclass clazz = (*env)->FindClass(env, "java/awt/ScrollPaneAdjustable");
       
   916         if ((*env)->ExceptionOccurred(env)) {
       
   917             (*env)->ExceptionDescribe(env);
       
   918             (*env)->ExceptionClear(env);
       
   919             return;
       
   920         }
       
   921         setTypedValueMID = (*env)->GetMethodID(env, clazz, "setTypedValue", "(II)V");
       
   922         (*env)->DeleteLocalRef(env, clazz);
       
   923 
       
   924         DASSERT(setTypedValueMID != NULL);
       
   925     }
       
   926     (*env)->CallVoidMethod(env, adjustable, setTypedValueMID, value, type);
       
   927 }