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 } |
|