/* * Copyright 1995-2004 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_Scrollbar.h" #include "java_awt_event_MouseEvent.h" #include "sun_awt_motif_MScrollbarPeer.h" #include "sun_awt_motif_MComponentPeer.h" #include "awt_Component.h" #include "canvas.h" #include #include #include "multi_font.h" extern struct MComponentPeerIDs mComponentPeerIDs; extern AwtGraphicsConfigDataPtr copyGraphicsConfigToPeer(JNIEnv *env, jobject this); /* fieldIDs for java.awt.Scrollbar fields that may be accessed from C */ static struct ScrollbarIDs { jfieldID orientation; jfieldID visibleAmount; jfieldID lineIncrement; jfieldID pageIncrement; jfieldID value; jfieldID minimum; jfieldID maximum; } targetIDs; /* MScrollbarPeer callback methods */ static struct { jmethodID lineUp; jmethodID lineDown; jmethodID pageUp; jmethodID pageDown; jmethodID drag; jmethodID dragEnd; jmethodID warp; } peerIDs; /* * Class: java_awt_ScrollBar * Method: initIDs * Signature: ()V */ /* This function gets called from the static initializer for Scrollbar.java to initialize the fieldIDs for fields that may be accessed from C */ JNIEXPORT void JNICALL Java_java_awt_Scrollbar_initIDs(JNIEnv *env, jclass cls) { targetIDs.orientation = (*env)->GetFieldID(env, cls, "orientation", "I"); targetIDs.visibleAmount = (*env)->GetFieldID(env, cls, "visibleAmount", "I"); targetIDs.lineIncrement = (*env)->GetFieldID(env, cls, "lineIncrement", "I"); targetIDs.pageIncrement = (*env)->GetFieldID(env, cls, "pageIncrement", "I"); targetIDs.value = (*env)->GetFieldID(env, cls, "value", "I"); targetIDs.minimum = (*env)->GetFieldID(env, cls, "minimum", "I"); targetIDs.maximum = (*env)->GetFieldID(env, cls, "maximum", "I"); } /* * Class: sun_awt_motif_MComponentPeer * Method: initIDs * Signature: ()V */ /* This function gets called from the static initializer for MScrollbarPeer to initialize the JNI ids for fields and methods that may be accessed from C */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollbarPeer_initIDs(JNIEnv *env, jclass cls) { peerIDs.lineUp = (*env)->GetMethodID(env, cls, "lineUp", "(I)V"); peerIDs.lineDown = (*env)->GetMethodID(env, cls, "lineDown", "(I)V"); peerIDs.pageUp = (*env)->GetMethodID(env, cls, "pageUp", "(I)V"); peerIDs.pageDown = (*env)->GetMethodID(env, cls, "pageDown", "(I)V"); peerIDs.drag = (*env)->GetMethodID(env, cls, "drag", "(I)V"); peerIDs.dragEnd = (*env)->GetMethodID(env, cls, "dragEnd", "(I)V"); peerIDs.warp = (*env)->GetMethodID(env, cls, "warp", "(I)V"); } /* * Call peer.jcallback(value) */ static void DoJavaCallback(jobject peer, jmethodID jcallback, jint value) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); (*env)->CallVoidMethod(env, peer, jcallback, value); if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } } static void /* XtCallbackProc */ decrementCallback(Widget w, jobject peer, XmScrollBarCallbackStruct *scroll) { DASSERT(scroll->reason == XmCR_DECREMENT); DoJavaCallback(peer, peerIDs.lineUp, scroll->value); } static void /* XtCallbackProc */ incrementCallback(Widget w, jobject peer, XmScrollBarCallbackStruct *scroll) { DASSERT(scroll->reason == XmCR_INCREMENT); DoJavaCallback(peer, peerIDs.lineDown, scroll->value); } static void /* XtCallbackProc */ pageDecrementCallback(Widget w, jobject peer, XmScrollBarCallbackStruct *scroll) { DASSERT(scroll->reason == XmCR_PAGE_DECREMENT); DoJavaCallback(peer, peerIDs.pageUp, scroll->value); } static void /* XtCallbackProc */ pageIncrementCallback(Widget w, jobject peer, XmScrollBarCallbackStruct *scroll) { DASSERT(scroll->reason == XmCR_PAGE_INCREMENT); DoJavaCallback(peer, peerIDs.pageDown, scroll->value); } static void /* XtCallbackProc */ dragCallback(Widget w, jobject peer, XmScrollBarCallbackStruct *scroll) { DASSERT(scroll->reason == XmCR_DRAG); DoJavaCallback(peer, peerIDs.drag, scroll->value); } static void /* XtCallbackProc */ dragEndCallback(Widget w, jobject peer, XmScrollBarCallbackStruct *scroll) { DASSERT(scroll->reason == XmCR_VALUE_CHANGED); DoJavaCallback(peer, peerIDs.dragEnd, scroll->value); } static void /* XtCallbackProc */ toTopCallback(Widget w, jobject peer, XmScrollBarCallbackStruct *scroll) { DASSERT(scroll->reason == XmCR_TO_TOP); DoJavaCallback(peer, peerIDs.warp, scroll->value); } static void /* XtCallbackProc */ toBottomCallback(Widget w, jobject peer, XmScrollBarCallbackStruct *scroll) { DASSERT(scroll->reason == XmCR_TO_BOTTOM); DoJavaCallback(peer, peerIDs.warp, scroll->value); } /* * Class: sun_awt_motif_MScrollbarPeer * Method: create * Signature: (Lsun/awt/motif/MComponentPeer;)V */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollbarPeer_create(JNIEnv *env, jobject this, jobject parent) { Widget w; jobject target; XtPointer globalRef = (XtPointer) /* jobject */ awtJNI_CreateAndSetGlobalRef(env, this); struct ComponentData *pdata; /* for parent */ struct ComponentData *sdata; /* for scrollbar */ AwtGraphicsConfigDataPtr adata; int32_t value, visible, minimum, maximum; int32_t lineIncrement, pageIncrement; Pixel bg; #define MAX_ARGC 20 Arg args[MAX_ARGC]; int32_t argc = 0; AWT_LOCK(); if (JNU_IsNull(env, parent)) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } pdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env, parent, mComponentPeerIDs.pData); target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target); if (JNU_IsNull(env, target) || pdata == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } switch ((*env)->GetIntField(env, target, targetIDs.orientation)) { case java_awt_Scrollbar_HORIZONTAL: XtSetArg(args[argc], XmNorientation, XmHORIZONTAL); argc++; break; case java_awt_Scrollbar_VERTICAL: XtSetArg(args[argc], XmNorientation, XmVERTICAL); argc++; break; default: JNU_ThrowIllegalArgumentException(env, "bad scrollbar orientation"); AWT_UNLOCK(); return; } adata = copyGraphicsConfigToPeer(env, this); XtVaGetValues(pdata->widget, XmNbackground, &bg, NULL); visible = (int32_t) (*env)->GetIntField(env, target, targetIDs.visibleAmount); value = (int32_t) (*env)->GetIntField(env, target, targetIDs.value); minimum = (int32_t) (*env)->GetIntField(env, target, targetIDs.minimum); maximum = (int32_t) (*env)->GetIntField(env, target, targetIDs.maximum); lineIncrement = (int32_t) (*env)->GetIntField(env, target, targetIDs.lineIncrement); pageIncrement = (int32_t) (*env)->GetIntField(env, target, targetIDs.pageIncrement); /* * Sanity check. Scrollbar.setValues should have taken care. */ DASSERT(maximum > minimum); DASSERT(visible <= maximum - minimum); DASSERT(visible >= 1); DASSERT(value >= minimum); DASSERT(value <= maximum - visible); XtSetArg(args[argc], XmNx, 0); argc++; XtSetArg(args[argc], XmNy, 0); argc++; XtSetArg(args[argc], XmNvalue, value); argc++; XtSetArg(args[argc], XmNsliderSize, visible); argc++; XtSetArg(args[argc], XmNminimum, minimum); argc++; XtSetArg(args[argc], XmNmaximum, maximum); argc++; XtSetArg(args[argc], XmNincrement, lineIncrement); argc++; XtSetArg(args[argc], XmNpageIncrement, pageIncrement); argc++; XtSetArg(args[argc], XmNbackground, bg); argc++; XtSetArg(args[argc], XmNrecomputeSize, False); argc++; XtSetArg(args[argc], XmNuserData, globalRef); argc++; XtSetArg(args[argc], XmNscreen, ScreenOfDisplay(awt_display, adata->awt_visInfo.screen)); argc++; DASSERT(argc <= MAX_ARGC); /* sanity check */ sdata = ZALLOC(ComponentData); if (sdata == NULL) { JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); AWT_UNLOCK(); return; } JNU_SetLongFieldFromPtr(env, this, mComponentPeerIDs.pData, sdata); sdata->widget = w = XmCreateScrollBar(pdata->widget, "scrollbar", args, argc); XtAddCallback(w, XmNdecrementCallback, (XtCallbackProc)decrementCallback, globalRef); XtAddCallback(w, XmNincrementCallback, (XtCallbackProc)incrementCallback, globalRef); XtAddCallback(w, XmNpageDecrementCallback, (XtCallbackProc)pageDecrementCallback, globalRef); XtAddCallback(w, XmNpageIncrementCallback, (XtCallbackProc)pageIncrementCallback, globalRef); XtAddCallback(w, XmNtoTopCallback, (XtCallbackProc)toTopCallback, globalRef); XtAddCallback(w, XmNtoBottomCallback, (XtCallbackProc)toBottomCallback, globalRef); XtAddCallback(w, XmNdragCallback, (XtCallbackProc)dragCallback, globalRef); XtAddCallback(w, XmNvalueChangedCallback, (XtCallbackProc)dragEndCallback, globalRef); /* Set up workaround for the continuous scrolling bug */ XtAddEventHandler(w, ButtonReleaseMask, False, awt_motif_Scrollbar_ButtonReleaseHandler, NULL); /* Fix for 4955950. ButtonRelease & MotionNotify should be handled as well */ XtAddEventHandler(w, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, False, awt_canvas_event_handler, globalRef); XtSetMappedWhenManaged(w, False); XtManageChild(w); AWT_UNLOCK(); } /* * Class: sun_awt_motif_MScrollbarPeer * Method: pSetValues * Signature: (IIII)V */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollbarPeer_pSetValues(JNIEnv *env, jobject this, jint value, jint visible, jint minimum, jint maximum) { struct ComponentData *sdata; AWT_LOCK(); sdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); if (sdata == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } /* pass in visible for sliderSize since Motif will calculate the */ /* slider's size for us. */ XtVaSetValues(sdata->widget, XmNminimum, minimum, XmNmaximum, maximum, XmNvalue, value, XmNsliderSize, visible, NULL); AWT_FLUSH_UNLOCK(); } /* * Class: sun_awt_motif_MScrollbarPeer * Method: setLineIncrement * Signature: (I)V */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollbarPeer_setLineIncrement(JNIEnv *env, jobject this, jint value) { struct ComponentData *sdata; AWT_LOCK(); sdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); if (sdata == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } XtVaSetValues(sdata->widget, XmNincrement, value, NULL); AWT_FLUSH_UNLOCK(); } /* * Class: sun_awt_motif_MScrollbarPeer * Method: setPageIncrement * Signature: (I)V */ JNIEXPORT void JNICALL Java_sun_awt_motif_MScrollbarPeer_setPageIncrement(JNIEnv *env, jobject this, jint value) { struct ComponentData *sdata; AWT_LOCK(); sdata = (struct ComponentData *) JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); if (sdata == NULL) { JNU_ThrowNullPointerException(env, "NullPointerException"); AWT_UNLOCK(); return; } XtVaSetValues(sdata->widget, XmNpageIncrement, value, NULL); AWT_FLUSH_UNLOCK(); }