2 static char Xrcsid
[] = "$XConsortium: Viewport.c,v 1.48 89/12/15 11:37:22 kit Exp $";
6 /***********************************************************
7 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
8 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
12 Permission to use, copy, modify, and distribute this software and its
13 documentation for any purpose and without fee is hereby granted,
14 provided that the above copyright notice appear in all copies and that
15 both that copyright notice and this permission notice appear in
16 supporting documentation, and that the names of Digital or MIT not be
17 used in advertising or publicity pertaining to distribution of the
18 software without specific, written prior permission.
20 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28 ******************************************************************/
30 #include <X11/IntrinsicP.h>
31 #include <X11/StringDefs.h>
33 #include <./Xaw3_1XawInit.h>
34 #include <X11/Xmu/Misc.h>
35 #include <./Xaw3_1Scrollbar.h>
36 #include <./Xaw3_1ViewportP.h>
38 static void ScrollUpDownProc(), ThumbProc();
39 static Boolean
GetGeometry();
41 #define offset(field) XtOffset(ViewportWidget,viewport.field)
42 static XtResource resources
[] = {
43 {XtNforceBars
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
44 offset(forcebars
), XtRImmediate
, (caddr_t
)False
},
45 {XtNallowHoriz
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
46 offset(allowhoriz
), XtRImmediate
, (caddr_t
)False
},
47 {XtNallowVert
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
48 offset(allowvert
), XtRImmediate
, (caddr_t
)False
},
49 {XtNuseBottom
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
50 offset(usebottom
), XtRImmediate
, (caddr_t
)False
},
51 {XtNuseRight
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
52 offset(useright
), XtRImmediate
, (caddr_t
)False
},
56 static void Initialize(), ConstraintInitialize(),
57 Realize(), Resize(), ChangeManaged();
58 static Boolean
SetValues(), Layout();
59 static XtGeometryResult
GeometryManager(), PreferredGeometry();
61 #define superclass (&formClassRec)
62 ViewportClassRec viewportClassRec
= {
63 { /* core_class fields */
64 /* superclass */ (WidgetClass
) superclass
,
65 /* class_name */ "Viewport",
66 /* widget_size */ sizeof(ViewportRec
),
67 /* class_initialize */ XawInitializeWidgetSet
,
68 /* class_part_init */ NULL
,
69 /* class_inited */ FALSE
,
70 /* initialize */ Initialize
,
71 /* initialize_hook */ NULL
,
72 /* realize */ Realize
,
75 /* resources */ resources
,
76 /* num_resources */ XtNumber(resources
),
77 /* xrm_class */ NULLQUARK
,
78 /* compress_motion */ TRUE
,
79 /* compress_exposure */ TRUE
,
80 /* compress_enterleave*/ TRUE
,
81 /* visible_interest */ FALSE
,
84 /* expose */ XtInheritExpose
,
85 /* set_values */ SetValues
,
86 /* set_values_hook */ NULL
,
87 /* set_values_almost */ XtInheritSetValuesAlmost
,
88 /* get_values_hook */ NULL
,
89 /* accept_focus */ NULL
,
90 /* version */ XtVersion
,
91 /* callback_private */ NULL
,
93 /* query_geometry */ PreferredGeometry
,
94 /* display_accelerator*/ XtInheritDisplayAccelerator
,
97 { /* composite_class fields */
98 /* geometry_manager */ GeometryManager
,
99 /* change_managed */ ChangeManaged
,
100 /* insert_child */ XtInheritInsertChild
,
101 /* delete_child */ XtInheritDeleteChild
,
104 { /* constraint_class fields */
105 /* subresourses */ NULL
,
106 /* subresource_count */ 0,
107 /* constraint_size */ sizeof(ViewportConstraintsRec
),
108 /* initialize */ ConstraintInitialize
,
110 /* set_values */ NULL
,
113 { /* form_class fields */
116 { /* viewport_class fields */
122 WidgetClass viewportWidgetClass
= (WidgetClass
)&viewportClassRec
;
124 static Widget
CreateScrollbar(w
, horizontal
)
128 Widget clip
= w
->viewport
.clip
;
129 ViewportConstraints constraints
=
130 (ViewportConstraints
)clip
->core
.constraints
;
131 static Arg barArgs
[] = {
132 {XtNorientation
, NULL
},
138 {XtNmappedWhenManaged
, False
},
142 XtSetArg(barArgs
[0], XtNorientation
,
143 horizontal
? XtorientHorizontal
: XtorientVertical
);
144 XtSetArg(barArgs
[1], XtNlength
,
145 horizontal
? clip
->core
.width
: clip
->core
.height
);
146 XtSetArg(barArgs
[2], XtNleft
,
147 (!horizontal
&& w
->viewport
.useright
) ? XtChainRight
: XtChainLeft
);
148 XtSetArg(barArgs
[3], XtNright
,
149 (!horizontal
&& !w
->viewport
.useright
) ? XtChainLeft
: XtChainRight
);
150 XtSetArg(barArgs
[4], XtNtop
,
151 (horizontal
&& w
->viewport
.usebottom
) ? XtChainBottom
: XtChainTop
);
152 XtSetArg(barArgs
[5], XtNbottom
,
153 (horizontal
&& !w
->viewport
.usebottom
) ? XtChainTop
: XtChainBottom
);
155 bar
= XtCreateWidget( (horizontal
? "horizontal" : "vertical"),
156 scrollbarWidgetClass
, (Widget
)w
,
157 barArgs
, XtNumber(barArgs
) );
158 XtAddCallback( bar
, XtNscrollProc
, ScrollUpDownProc
, (caddr_t
)w
);
159 XtAddCallback( bar
, XtNjumpProc
, ThumbProc
, (caddr_t
)w
);
162 w
->viewport
.horiz_bar
= bar
;
163 constraints
->form
.vert_base
= bar
;
166 w
->viewport
.vert_bar
= bar
;
167 constraints
->form
.horiz_base
= bar
;
170 XtManageChild( bar
);
176 static void Initialize(request
, new)
179 ViewportWidget w
= (ViewportWidget
)new;
180 static Arg clip_args
[5];
183 Dimension clip_height
, clip_width
;
185 w
->form
.default_spacing
= 0; /* Reset the default spacing to 0 pixels. */
189 * Initialize all widget pointers to NULL.
192 w
->viewport
.child
= (Widget
) NULL
;
193 w
->viewport
.horiz_bar
= w
->viewport
.vert_bar
= (Widget
)NULL
;
196 * Create Clip Widget.
200 XtSetArg(clip_args
[num_args
], XtNborderWidth
, 0); num_args
++;
201 XtSetArg(clip_args
[num_args
], XtNleft
, XtChainLeft
); num_args
++;
202 XtSetArg(clip_args
[num_args
], XtNright
, XtChainRight
); num_args
++;
203 XtSetArg(clip_args
[num_args
], XtNtop
, XtChainTop
); num_args
++;
204 XtSetArg(clip_args
[num_args
], XtNbottom
, XtChainBottom
); num_args
++;
206 w
->viewport
.clip
= XtCreateManagedWidget("clip", widgetClass
, new,
207 clip_args
, num_args
);
210 if (!w
->viewport
.forcebars
)
211 return; /* If we are not forcing the bars then we are done. */
213 if (w
->viewport
.allowhoriz
)
214 (void) CreateScrollbar(w
, True
);
215 if (w
->viewport
.allowvert
)
216 (void) CreateScrollbar(w
, False
);
218 h_bar
= w
->viewport
.horiz_bar
;
219 v_bar
= w
->viewport
.vert_bar
;
222 * Set the clip widget to the correct height.
225 clip_width
= w
->core
.width
;
226 clip_height
= w
->core
.height
;
228 if ( (h_bar
!= NULL
) &&
229 (w
->core
.width
> h_bar
->core
.width
+ h_bar
->core
.border_width
) )
230 clip_width
-= h_bar
->core
.width
+ h_bar
->core
.border_width
;
232 if ( (v_bar
!= NULL
) &&
233 (w
->core
.height
> v_bar
->core
.height
+ v_bar
->core
.border_width
) )
234 clip_height
-= v_bar
->core
.height
+ v_bar
->core
.border_width
;
237 XtSetArg(clip_args
[num_args
], XtNwidth
, clip_width
); num_args
++;
238 XtSetArg(clip_args
[num_args
], XtNheight
, clip_height
); num_args
++;
239 XtSetValues(w
->viewport
.clip
, clip_args
, num_args
);
243 static void ConstraintInitialize(request
, new)
246 ((ViewportConstraints
)new->core
.constraints
)->viewport
.reparented
= False
;
249 static void Realize(widget
, value_mask
, attributes
)
251 XtValueMask
*value_mask
;
252 XSetWindowAttributes
*attributes
;
254 ViewportWidget w
= (ViewportWidget
)widget
;
255 register Widget child
= w
->viewport
.child
;
256 register Widget clip
= w
->viewport
.clip
;
258 *value_mask
|= CWBitGravity
;
259 attributes
->bit_gravity
= NorthWestGravity
;
260 (*superclass
->core_class
.realize
)(widget
, value_mask
, attributes
);
262 (*w
->core
.widget_class
->core_class
.resize
)(widget
); /* turn on bars */
264 if (child
!= (Widget
)NULL
) {
265 XtMoveWidget( child
, (Position
)0, (Position
)0 );
266 XtRealizeWidget( clip
);
267 XtRealizeWidget( child
);
268 XReparentWindow( XtDisplay(w
), XtWindow(child
), XtWindow(clip
),
269 (Position
)0, (Position
)0 );
270 XtMapWidget( child
);
275 static Boolean
SetValues(current
, request
, new)
276 Widget current
, request
, new;
278 ViewportWidget w
= (ViewportWidget
)new;
279 ViewportWidget cw
= (ViewportWidget
)current
;
281 if (w
->viewport
.forcebars
!= cw
->viewport
.forcebars
) {
282 if (w
->viewport
.forcebars
) {
283 if (w
->viewport
.allowhoriz
&& w
->viewport
.horiz_bar
== (Widget
)NULL
)
284 (void) CreateScrollbar( w
, True
);
285 if (w
->viewport
.allowvert
&& w
->viewport
.vert_bar
== (Widget
)NULL
)
286 (void) CreateScrollbar( w
, False
);
290 /* take care of bars, &tc. */
291 (*w
->core
.widget_class
->core_class
.resize
)( new );
296 static void ChangeManaged(widget
)
299 ViewportWidget w
= (ViewportWidget
)widget
;
300 register int num_children
= w
->composite
.num_children
;
301 register Widget child
, *childP
;
304 child
= (Widget
)NULL
;
305 for (childP
=w
->composite
.children
, i
=0; i
< num_children
; childP
++, i
++) {
306 if (XtIsManaged(*childP
)
307 && *childP
!= w
->viewport
.clip
308 && *childP
!= w
->viewport
.horiz_bar
309 && *childP
!= w
->viewport
.vert_bar
)
316 if (child
!= w
->viewport
.child
) {
317 w
->viewport
.child
= child
;
318 if (child
!= (Widget
)NULL
) {
319 XtResizeWidget( child
, child
->core
.width
,
320 child
->core
.height
, (Dimension
)0 );
321 if (XtIsRealized(widget
)) {
322 ViewportConstraints constraints
=
323 (ViewportConstraints
)child
->core
.constraints
;
324 if (!XtIsRealized(child
)) {
325 Window window
= XtWindow(w
);
326 XtMoveWidget( child
, (Position
)0, (Position
)0 );
328 /* this is dirty, but it saves the following code: */
329 XtRealizeWidget( child
);
330 XReparentWindow( XtDisplay(w
), XtWindow(child
),
331 XtWindow(w
->viewport
.clip
),
332 (Position
)0, (Position
)0 );
333 if (child
->core
.mapped_when_managed
)
334 XtMapWidget( child
);
336 w
->core
.window
= XtWindow(w
->viewport
.clip
);
337 XtRealizeWidget( child
);
338 w
->core
.window
= window
;
340 constraints
->viewport
.reparented
= True
;
342 else if (!constraints
->viewport
.reparented
) {
343 XReparentWindow( XtDisplay(w
), XtWindow(child
),
344 XtWindow(w
->viewport
.clip
),
345 (Position
)0, (Position
)0 );
346 constraints
->viewport
.reparented
= True
;
347 if (child
->core
.mapped_when_managed
)
348 XtMapWidget( child
);
351 GetGeometry( widget
, child
->core
.width
, child
->core
.height
);
352 (*((ViewportWidgetClass
)w
->core
.widget_class
)->form_class
.layout
)
353 ( (FormWidget
)w
, w
->core
.width
, w
->core
.height
);
354 /* %%% do we need to hide this child from Form? */
359 (*superclass
->composite_class
.change_managed
)( widget
);
364 static void SetBar(w
, top
, length
, total
)
367 Dimension length
, total
;
369 XawScrollbarSetThumb(w
, (float) top
/ total
, (float) length
/ total
);
372 static void RedrawThumbs(w
)
375 register Widget child
= w
->viewport
.child
;
376 register Widget clip
= w
->viewport
.clip
;
378 if (w
->viewport
.horiz_bar
!= (Widget
)NULL
)
379 SetBar( w
->viewport
.horiz_bar
, -(child
->core
.x
),
380 clip
->core
.width
, child
->core
.width
);
382 if (w
->viewport
.vert_bar
!= (Widget
)NULL
)
383 SetBar( w
->viewport
.vert_bar
, -(child
->core
.y
),
384 clip
->core
.height
, child
->core
.height
);
389 static void MoveChild(w
, x
, y
)
393 register Widget child
= w
->viewport
.child
;
394 register Widget clip
= w
->viewport
.clip
;
396 /* make sure we never move past right/bottom borders */
397 if (-x
+ clip
->core
.width
> child
->core
.width
)
398 x
= -(child
->core
.width
- clip
->core
.width
);
400 if (-y
+ clip
->core
.height
> child
->core
.height
)
401 y
= -(child
->core
.height
- clip
->core
.height
);
403 /* make sure we never move past left/top borders */
407 XtMoveWidget(child
, x
, y
);
412 static void ComputeWithForceBars(Widget
, Boolean
, XtWidgetGeometry
*, int *, int *);
414 static void ComputeLayout(widget
, query
, destroy_scrollbars
)
415 Widget widget
; /* Viewport */
416 Boolean query
; /* query child's preferred geom? */
417 Boolean destroy_scrollbars
; /* destroy un-needed scrollbars? */
419 ViewportWidget w
= (ViewportWidget
)widget
;
420 register Widget child
= w
->viewport
.child
;
421 register Widget clip
= w
->viewport
.clip
;
422 ViewportConstraints constraints
423 = (ViewportConstraints
)clip
->core
.constraints
;
424 Boolean needshoriz
, needsvert
;
425 int clip_width
, clip_height
;
426 XtWidgetGeometry intended
;
428 if (child
== (Widget
) NULL
) return;
430 clip_width
= w
->core
.width
;
431 clip_height
= w
->core
.height
;
432 intended
.request_mode
= CWBorderWidth
;
433 intended
.border_width
= 0;
435 if (w
->viewport
.forcebars
) {
436 needsvert
= w
->viewport
.allowvert
;
437 needshoriz
= w
->viewport
.allowhoriz
;
438 ComputeWithForceBars(widget
, query
, &intended
,
439 &clip_width
, &clip_height
);
442 Dimension prev_width
, prev_height
;
443 XtGeometryMask prev_mode
;
444 XtWidgetGeometry preferred
;
446 needshoriz
= needsvert
= False
;
449 * intended.{width,height} caches the eventual child dimensions,
450 * but we don't set the mode bits until after we decide that the
451 * child's preferences are not acceptable.
454 if (!w
->viewport
.allowhoriz
)
455 intended
.request_mode
|= CWWidth
;
457 if (child
->core
.width
< clip_width
)
458 intended
.width
= clip_width
;
460 intended
.width
= child
->core
.width
;
462 if (child
->core
.height
< clip_height
)
463 intended
.height
= clip_height
;
465 intended
.height
= child
->core
.height
;
467 if (!w
->viewport
.allowvert
)
468 intended
.request_mode
|= CWHeight
;
471 preferred
.width
= child
->core
.width
;
472 preferred
.height
= child
->core
.height
;
474 do { /* while intended != prev */
477 (void) XtQueryGeometry( child
, &intended
, &preferred
);
478 if ( !(preferred
.request_mode
& CWWidth
) )
479 preferred
.width
= intended
.width
;
480 if ( !(preferred
.request_mode
& CWHeight
) )
481 preferred
.height
= intended
.height
;
483 prev_width
= intended
.width
;
484 prev_height
= intended
.height
;
485 prev_mode
= intended
.request_mode
;
487 * note that having once decided to turn on either bar
488 * we'll not change our mind until we're next resized,
489 * thus avoiding potential oscillations.
491 #define CheckHoriz() \
492 if (w->viewport.allowhoriz && preferred.width > clip_width) { \
496 if ((bar = w->viewport.horiz_bar) == (Widget)NULL) \
497 bar = CreateScrollbar(w, True); \
498 clip_height -= bar->core.height + \
499 bar->core.border_width; \
500 if (clip_height < 1) clip_height = 1; \
502 intended.width = preferred.width; \
506 if (w
->viewport
.allowvert
&& preferred
.height
> clip_height
) {
510 if ((bar
= w
->viewport
.vert_bar
) == (Widget
)NULL
)
511 bar
= CreateScrollbar(w
, False
);
512 clip_width
-= bar
->core
.width
+ bar
->core
.border_width
;
513 if (clip_width
< 1) clip_width
= 1;
516 intended
.height
= preferred
.height
;
518 if (!w
->viewport
.allowhoriz
|| preferred
.width
< clip_width
) {
519 intended
.width
= clip_width
;
520 intended
.request_mode
|= CWWidth
;
522 if (!w
->viewport
.allowvert
|| preferred
.height
< clip_height
) {
523 intended
.height
= clip_height
;
524 intended
.request_mode
|= CWHeight
;
526 } while (intended
.request_mode
!= prev_mode
527 || (intended
.request_mode
& CWWidth
528 && intended
.width
!= prev_width
)
529 || (intended
.request_mode
& CWHeight
530 && intended
.height
!= prev_height
));
533 if (XtIsRealized(clip
))
534 XRaiseWindow( XtDisplay(clip
), XtWindow(clip
) );
537 needsvert
? (w
->viewport
.useright
? 0 :
538 w
->viewport
.vert_bar
->core
.width
+
539 w
->viewport
.vert_bar
->core
.border_width
) : 0,
540 needshoriz
? (w
->viewport
.usebottom
? 0 :
541 w
->viewport
.horiz_bar
->core
.height
+
542 w
->viewport
.horiz_bar
->core
.border_width
) : 0);
543 XtResizeWidget( clip
, (Dimension
)clip_width
,
544 (Dimension
)clip_height
, (Dimension
)0 );
546 if (w
->viewport
.horiz_bar
!= (Widget
)NULL
) {
547 register Widget bar
= w
->viewport
.horiz_bar
;
549 constraints
->form
.vert_base
= (Widget
)NULL
;
550 if (destroy_scrollbars
) {
551 XtDestroyWidget( bar
);
552 w
->viewport
.horiz_bar
= (Widget
)NULL
;
556 register int bw
= bar
->core
.border_width
;
557 XtResizeWidget( bar
, clip_width
, bar
->core
.height
, bw
);
559 ((needsvert
&& !w
->viewport
.useright
)
560 ? w
->viewport
.vert_bar
->core
.width
562 (w
->viewport
.usebottom
563 ? w
->core
.height
- bar
->core
.height
- bw
565 XtSetMappedWhenManaged( bar
, True
);
569 if (w
->viewport
.vert_bar
!= (Widget
)NULL
) {
570 register Widget bar
= w
->viewport
.vert_bar
;
572 constraints
->form
.horiz_base
= (Widget
)NULL
;
573 if (destroy_scrollbars
) {
574 XtDestroyWidget( bar
);
575 w
->viewport
.vert_bar
= (Widget
)NULL
;
579 register int bw
= bar
->core
.border_width
;
580 XtResizeWidget( bar
, bar
->core
.width
, clip_height
, bw
);
582 (w
->viewport
.useright
583 ? w
->core
.width
- bar
->core
.width
- bw
585 ((needshoriz
&& !w
->viewport
.usebottom
)
586 ? w
->viewport
.horiz_bar
->core
.height
588 XtSetMappedWhenManaged( bar
, True
);
592 if (child
!= (Widget
)NULL
) {
593 XtResizeWidget( child
, (Dimension
)intended
.width
,
594 (Dimension
)intended
.height
, (Dimension
)0 );
596 needshoriz
? child
->core
.x
: 0,
597 needsvert
? child
->core
.y
: 0);
601 /* Function Name: ComputeWithForceBars
602 * Description: Computes the layout give forcebars is set.
603 * Arguments: widget - the viewport widget.
604 * query - whether or not to query the child.
605 * intended - the cache of the childs height is
606 * stored here ( USED AND RETURNED ).
607 * clip_width, clip_height - size of clip window.
608 * (USED AND RETURNED ).
613 ComputeWithForceBars(widget
, query
, intended
, clip_width
, clip_height
)
616 XtWidgetGeometry
* intended
;
617 int *clip_width
, *clip_height
;
619 ViewportWidget w
= (ViewportWidget
)widget
;
620 register Widget child
= w
->viewport
.child
;
621 XtWidgetGeometry preferred
;
624 * If forcebars then needs = allows = has.
625 * Thus if needsvert is set it MUST have a scrollbar.
628 if (w
->viewport
.allowvert
)
629 *clip_width
-= w
->viewport
.vert_bar
->core
.width
+
630 w
->viewport
.vert_bar
->core
.border_width
;
632 if (w
->viewport
.allowhoriz
)
633 *clip_height
-= w
->viewport
.horiz_bar
->core
.height
+
634 w
->viewport
.horiz_bar
->core
.border_width
;
636 AssignMax( *clip_width
, 1 );
637 AssignMax( *clip_height
, 1 );
639 if (!w
->viewport
.allowvert
) {
640 intended
->height
= *clip_height
;
641 intended
->request_mode
= CWHeight
;
643 if (!w
->viewport
.allowhoriz
) {
644 intended
->width
= *clip_width
;
645 intended
->request_mode
= CWWidth
;
649 if ( (w
->viewport
.allowvert
|| w
->viewport
.allowhoriz
) ) {
650 XtQueryGeometry( child
, intended
, &preferred
);
652 if ( !(intended
->request_mode
& CWWidth
) )
653 if ( preferred
.request_mode
& CWWidth
)
654 intended
->width
= preferred
.width
;
656 intended
->width
= child
->core
.width
;
658 if ( !(intended
->request_mode
& CWHeight
) )
659 if ( preferred
.request_mode
& CWHeight
)
660 intended
->height
= preferred
.height
;
662 intended
->height
= child
->core
.height
;
666 if (w
->viewport
.allowvert
)
667 intended
->height
= child
->core
.height
;
668 if (w
->viewport
.allowhoriz
)
669 intended
->width
= child
->core
.width
;
672 AssignMax(intended
->width
, *clip_width
);
673 AssignMax(intended
->height
, *clip_height
);
676 static void Resize(widget
)
679 ComputeLayout( widget
, /*query=*/True
, /*destroy=*/True
);
684 static Boolean
Layout(w
, width
, height
)
686 Dimension width
, height
;
688 ComputeLayout( (Widget
)w
, /*query=*/True
, /*destroy=*/True
);
689 w
->form
.preferred_width
= w
->core
.width
;
690 w
->form
.preferred_height
= w
->core
.height
;
695 static void ScrollUpDownProc(widget
, closure
, call_data
)
700 ViewportWidget w
= (ViewportWidget
)closure
;
701 register Widget child
= w
->viewport
.child
;
702 int pix
= (int)call_data
;
705 if (child
== NULL
) return; /* no child to scroll. */
707 x
= child
->core
.x
- ((widget
== w
->viewport
.horiz_bar
) ? pix
: 0);
708 y
= child
->core
.y
- ((widget
== w
->viewport
.vert_bar
) ? pix
: 0);
714 static void ThumbProc(widget
, closure
, percent
)
719 ViewportWidget w
= (ViewportWidget
)closure
;
720 register Widget child
= w
->viewport
.child
;
723 if (child
== NULL
) return; /* no child to scroll. */
725 if (widget
== w
->viewport
.horiz_bar
)
726 #ifdef macII /* bug in the macII A/UX 1.0 cc */
727 x
= (int)(-*percent
* child
->core
.width
);
728 #else /* else not macII */
729 x
= -(int)(*percent
* child
->core
.width
);
734 if (widget
== w
->viewport
.vert_bar
)
735 #ifdef macII /* bug in the macII A/UX 1.0 cc */
736 y
= (int)(-*percent
* child
->core
.height
);
737 #else /* else not macII */
738 y
= -(int)(*percent
* child
->core
.height
);
747 static XtGeometryResult
GeometryManager(child
, request
, reply
)
749 XtWidgetGeometry
*request
, *reply
;
751 ViewportWidget w
= (ViewportWidget
)child
->core
.parent
;
752 Boolean rWidth
= (Boolean
)(request
->request_mode
& CWWidth
);
753 Boolean rHeight
= (Boolean
)(request
->request_mode
& CWHeight
);
754 XtWidgetGeometry allowed
;
755 XtGeometryResult result
;
756 Boolean reconfigured
;
757 Dimension height_remaining
;
759 if (child
!= w
->viewport
.child
760 || request
->request_mode
& ~(CWWidth
| CWHeight
| CWBorderWidth
)
761 || ((request
->request_mode
& CWBorderWidth
)
762 && request
->border_width
> 0))
768 reconfigured
= GetGeometry( (Widget
)w
,
769 (rWidth
? request
->width
: w
->core
.width
),
770 (rHeight
? request
->height
: w
->core
.height
)
773 height_remaining
= w
->core
.height
;
774 if (rWidth
&& w
->core
.width
!= request
->width
) {
775 if (w
->viewport
.allowhoriz
&& request
->width
> w
->core
.width
) {
776 /* horizontal scrollbar will be needed so possibly reduce height */
778 if ((bar
= w
->viewport
.horiz_bar
) == (Widget
)NULL
)
779 bar
= CreateScrollbar( w
, True
);
780 height_remaining
-= bar
->core
.height
+ bar
->core
.border_width
;
784 allowed
.width
= w
->core
.width
;
787 if (rHeight
&& height_remaining
!= request
->height
) {
788 if (w
->viewport
.allowvert
&& request
->height
> height_remaining
) {
789 /* vertical scrollbar will be needed, so possibly reduce width */
790 if (!w
->viewport
.allowhoriz
|| request
->width
< w
->core
.width
) {
792 if ((bar
= w
->viewport
.vert_bar
) == (Widget
)NULL
)
793 bar
= CreateScrollbar( w
, False
);
795 allowed
.width
= w
->core
.width
;
796 allowed
.request_mode
|= CWWidth
;
798 if (allowed
.width
> (bar
->core
.width
+ bar
->core
.border_width
))
799 allowed
.width
-= bar
->core
.width
+ bar
->core
.border_width
;
806 allowed
.height
= height_remaining
;
810 if (allowed
.width
!= request
->width
|| allowed
.height
!= request
->height
) {
812 result
= XtGeometryAlmost
;
815 if (rWidth
) child
->core
.width
= request
->width
;
816 if (rHeight
) child
->core
.height
= request
->height
;
817 result
= XtGeometryYes
;
821 ComputeLayout( (Widget
)w
,
823 /*destroy=*/ (result
== XtGeometryYes
) ? True
: False
);
829 static Boolean
GetGeometry(w
, width
, height
)
831 Dimension width
, height
;
833 XtWidgetGeometry geometry
;
834 XtGeometryResult result
;
836 if (width
== w
->core
.width
&& height
== w
->core
.height
)
839 geometry
.request_mode
= CWWidth
| CWHeight
;
840 geometry
.width
= width
;
841 geometry
.height
= height
;
843 if (XtIsRealized(w
)) {
844 if (((ViewportWidget
)w
)->viewport
.allowhoriz
&& width
> w
->core
.width
)
845 geometry
.width
= w
->core
.width
;
846 if (((ViewportWidget
)w
)->viewport
.allowvert
&& height
> w
->core
.height
)
847 geometry
.height
= w
->core
.height
;
849 /* This is the Realize call; we'll inherit a w&h iff none currently */
850 if (w
->core
.width
!= 0) {
851 if (w
->core
.height
!= 0) return False
;
852 geometry
.width
= w
->core
.width
;
854 if (w
->core
.height
!= 0) geometry
.height
= w
->core
.height
;
856 if ((result
= XtMakeGeometryRequest(w
, &geometry
, &geometry
))
858 result
= XtMakeGeometryRequest(w
, &geometry
, NULL
);
860 return (result
== XtGeometryYes
);
863 static XtGeometryResult
PreferredGeometry(w
, constraints
, reply
)
865 XtWidgetGeometry
*constraints
, *reply
;
867 if (((ViewportWidget
)w
)->viewport
.child
!= NULL
)
868 return XtQueryGeometry( ((ViewportWidget
)w
)->viewport
.child
,
869 constraints
, reply
);
871 return XtGeometryYes
;