1 /***********************************************************
3 Copyright 1987, 1988, 1994, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
51 #include <X11/IntrinsicP.h>
52 #include <X11/StringDefs.h>
53 #include <X11/Xmu/Misc.h>
54 #include <X11/Xaw/Scrollbar.h>
55 #include <X11/Xaw/ViewportP.h>
56 #include <X11/Xaw/XawInit.h>
62 static Boolean Layout(FormWidget, unsigned int, unsigned int, Bool);
63 static void XawViewportChangeManaged(Widget);
64 static void XawViewportInitialize(Widget, Widget, ArgList, Cardinal*);
66 XawViewportConstraintInitialize(Widget, Widget, ArgList, Cardinal*);
67 static XtGeometryResult XawViewportGeometryManager(Widget, XtWidgetGeometry*,
69 static XtGeometryResult XawViewportQueryGeometry(Widget,
72 static void XawViewportRealize(Widget, XtValueMask*, XSetWindowAttributes*);
73 static void XawViewportResize(Widget);
74 static Boolean XawViewportSetValues(Widget, Widget, Widget,
80 static void ComputeLayout(Widget, Bool, Bool);
81 static void ComputeWithForceBars(Widget, Bool, XtWidgetGeometry*,
83 static Widget CreateScrollbar(ViewportWidget, Bool);
84 static XtGeometryResult GeometryRequestPlusScrollbar(ViewportWidget, Bool,
87 static Bool GetGeometry(Widget, unsigned int, unsigned int);
88 static void MoveChild(ViewportWidget, int, int);
89 static XtGeometryResult QueryGeometry(ViewportWidget, XtWidgetGeometry*,
91 static void RedrawThumbs(ViewportWidget);
92 static void ScrollUpDownProc(Widget, XtPointer, XtPointer);
93 static void SendReport(ViewportWidget, unsigned int);
94 static void SetBar(Widget, int, unsigned int, unsigned int);
95 static XtGeometryResult TestSmaller(ViewportWidget, XtWidgetGeometry*,
97 static void ThumbProc(Widget, XtPointer, XtPointer);
102 #define offset(field) XtOffsetOf(ViewportRec, viewport.field)
103 static XtResource resources[] = {
154 offset(report_callbacks),
161 #define Superclass (&formClassRec)
162 ViewportClassRec viewportClassRec = {
165 (WidgetClass)Superclass, /* superclass */
166 "Viewport", /* class_name */
167 sizeof(ViewportRec), /* widget_size */
168 XawInitializeWidgetSet, /* class_initialize */
169 NULL, /* class_part_init */
170 False, /* class_inited */
171 XawViewportInitialize, /* initialize */
172 NULL, /* initialize_hook */
173 XawViewportRealize, /* realize */
176 resources, /* resources */
177 XtNumber(resources), /* num_resources */
178 NULLQUARK, /* xrm_class */
179 True, /* compress_motion */
180 True, /* compress_exposure */
181 True, /* compress_enterleave */
182 False, /* visible_interest */
184 XawViewportResize, /* resize */
185 XtInheritExpose, /* expose */
186 XawViewportSetValues, /* set_values */
187 NULL, /* set_values_hook */
188 XtInheritSetValuesAlmost, /* set_values_almost */
189 NULL, /* get_values_hook */
190 NULL, /* accept_focus */
191 XtVersion, /* version */
192 NULL, /* callback_private */
194 XawViewportQueryGeometry, /* query_geometry */
195 XtInheritDisplayAccelerator, /* display_accelerator */
196 NULL, /* extension */
200 XawViewportGeometryManager, /* geometry_manager */
201 XawViewportChangeManaged, /* change_managed */
202 XtInheritInsertChild, /* insert_child */
203 XtInheritDeleteChild, /* delete_child */
204 NULL, /* extension */
208 NULL, /* subresourses */
209 0, /* subresource_count */
210 sizeof(ViewportConstraintsRec), /* constraint_size */
211 XawViewportConstraintInitialize, /* initialize */
213 NULL, /* set_values */
214 NULL, /* extension */
222 NULL, /* extension */
226 WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec;
232 CreateScrollbar(ViewportWidget w, Bool horizontal)
234 static Arg barArgs[] = {
241 {XtNmappedWhenManaged, False},
243 Widget clip = w->viewport.clip;
244 ViewportConstraints constraints =
245 (ViewportConstraints)clip->core.constraints;
248 XtSetArg(barArgs[0], XtNorientation,
249 horizontal ? XtorientHorizontal : XtorientVertical);
250 XtSetArg(barArgs[1], XtNlength,
251 horizontal ? XtWidth(clip) : XtHeight(clip));
252 XtSetArg(barArgs[2], XtNleft,
253 !horizontal && w->viewport.useright ? XtChainRight : XtChainLeft);
254 XtSetArg(barArgs[3], XtNright,
255 !horizontal && !w->viewport.useright ? XtChainLeft : XtChainRight);
256 XtSetArg(barArgs[4], XtNtop,
257 horizontal && w->viewport.usebottom ? XtChainBottom: XtChainTop);
258 XtSetArg(barArgs[5], XtNbottom,
259 horizontal && !w->viewport.usebottom ? XtChainTop: XtChainBottom);
261 bar = XtCreateWidget(horizontal ? "horizontal" : "vertical",
262 scrollbarWidgetClass, (Widget)w,
263 barArgs, XtNumber(barArgs));
264 XtAddCallback(bar, XtNscrollProc, ScrollUpDownProc, (XtPointer)w);
265 XtAddCallback(bar, XtNjumpProc, ThumbProc, (XtPointer)w);
268 w->viewport.horiz_bar = bar;
269 constraints->form.vert_base = bar;
272 w->viewport.vert_bar = bar;
273 constraints->form.horiz_base = bar;
283 XawViewportInitialize(Widget request, Widget cnew,
284 ArgList args, Cardinal *num_args)
286 ViewportWidget w = (ViewportWidget)cnew;
287 static Arg clip_args[8];
290 Dimension clip_height, clip_width;
292 w->form.default_spacing = 0; /* Reset the default spacing to 0 pixels */
295 * Initialize all widget pointers to NULL
297 w->viewport.child = NULL;
298 w->viewport.horiz_bar = w->viewport.vert_bar = NULL;
304 XtSetArg(clip_args[arg_cnt], XtNbackgroundPixmap, None); arg_cnt++;
305 XtSetArg(clip_args[arg_cnt], XtNborderWidth, 0); arg_cnt++;
306 XtSetArg(clip_args[arg_cnt], XtNleft, XtChainLeft); arg_cnt++;
307 XtSetArg(clip_args[arg_cnt], XtNright, XtChainRight); arg_cnt++;
308 XtSetArg(clip_args[arg_cnt], XtNtop, XtChainTop); arg_cnt++;
309 XtSetArg(clip_args[arg_cnt], XtNbottom, XtChainBottom); arg_cnt++;
310 XtSetArg(clip_args[arg_cnt], XtNwidth, XtWidth(w)); arg_cnt++;
311 XtSetArg(clip_args[arg_cnt], XtNheight, XtHeight(w)); arg_cnt++;
313 w->viewport.clip = XtCreateManagedWidget("clip", widgetClass, cnew,
316 if (!w->viewport.forcebars)
317 return; /* If we are not forcing the bars then we are done */
319 if (w->viewport.allowhoriz)
320 (void)CreateScrollbar(w, True);
321 if (w->viewport.allowvert)
322 (void)CreateScrollbar(w, False);
324 h_bar = w->viewport.horiz_bar;
325 v_bar = w->viewport.vert_bar;
328 * Set the clip widget to the correct height
330 clip_width = XtWidth(w);
331 clip_height = XtHeight(w);
333 if (h_bar != NULL && XtWidth(w) > XtWidth(h_bar) + XtBorderWidth(h_bar))
334 clip_width -= XtWidth(h_bar) + XtBorderWidth(h_bar);
336 if (v_bar != NULL && XtHeight(w) > XtHeight(v_bar) + XtBorderWidth(v_bar))
337 clip_height -= XtHeight(v_bar) + XtBorderWidth(v_bar);
340 XtSetArg(clip_args[arg_cnt], XtNwidth, clip_width); arg_cnt++;
341 XtSetArg(clip_args[arg_cnt], XtNheight, clip_height); arg_cnt++;
342 XtSetValues(w->viewport.clip, clip_args, arg_cnt);
347 XawViewportConstraintInitialize(Widget request, Widget cnew,
348 ArgList args, Cardinal *num_args)
350 ((ViewportConstraints)cnew->core.constraints)->viewport.reparented = False;
354 XawViewportRealize(Widget widget, XtValueMask *value_mask,
355 XSetWindowAttributes *attributes)
357 ViewportWidget w = (ViewportWidget)widget;
358 Widget child = w->viewport.child;
359 Widget clip = w->viewport.clip;
361 *value_mask |= CWBitGravity;
362 attributes->bit_gravity = NorthWestGravity;
363 (*Superclass->core_class.realize)(widget, value_mask, attributes);
365 (*w->core.widget_class->core_class.resize)(widget); /* turn on bars */
368 XtMoveWidget(child, 0, 0);
369 XtRealizeWidget(clip);
370 XtRealizeWidget(child);
371 XReparentWindow(XtDisplay(w), XtWindow(child), XtWindow(clip), 0, 0);
378 XawViewportSetValues(Widget current, Widget request, Widget cnew,
379 ArgList args, Cardinal *num_args)
381 ViewportWidget w = (ViewportWidget)cnew;
382 ViewportWidget cw = (ViewportWidget)current;
384 if (w->viewport.forcebars != cw->viewport.forcebars
385 || w->viewport.allowvert != cw->viewport.allowvert
386 || w->viewport.allowhoriz != cw->viewport.allowhoriz
387 || w->viewport.useright != cw->viewport.useright
388 || w->viewport.usebottom != cw->viewport.usebottom)
389 (*w->core.widget_class->core_class.resize)(cnew); /* Recompute layout */
395 XawViewportChangeManaged(Widget widget)
397 ViewportWidget w = (ViewportWidget)widget;
398 int num_children = w->composite.num_children;
399 Widget child, *childP;
403 for (childP = w->composite.children,
404 i = 0; i < num_children;
406 if (XtIsManaged(*childP)
407 && *childP != w->viewport.clip
408 && *childP != w->viewport.horiz_bar
409 && *childP != w->viewport.vert_bar) {
415 if (child != w->viewport.child) {
416 w->viewport.child = child;
418 XtResizeWidget(child, XtWidth(child), XtHeight(child), 0);
419 if (XtIsRealized(widget)) {
420 ViewportConstraints constraints =
421 (ViewportConstraints)child->core.constraints;
422 if (!XtIsRealized(child)) {
423 Window window = XtWindow(w);
425 XtMoveWidget(child, 0, 0);
426 w->core.window = XtWindow(w->viewport.clip);
427 XtRealizeWidget(child);
428 w->core.window = window;
429 constraints->viewport.reparented = True;
431 else if (!constraints->viewport.reparented) {
432 XReparentWindow(XtDisplay(w), XtWindow(child),
433 XtWindow(w->viewport.clip), 0, 0);
434 constraints->viewport.reparented = True;
435 if (child->core.mapped_when_managed)
439 GetGeometry(widget, XtWidth(child), XtHeight(child));
440 (*((ViewportWidgetClass)w->core.widget_class)->form_class.layout)
441 ((FormWidget)w, XtWidth(w), XtHeight(w), True /* True? */);
446 (*Superclass->composite_class.change_managed)(widget);
451 SetBar(Widget w, int top, unsigned int length, unsigned int total)
453 XawScrollbarSetThumb(w, (float)top / (float)total,
454 (float)length / (float)total);
458 RedrawThumbs(ViewportWidget w)
460 Widget child = w->viewport.child;
461 Widget clip = w->viewport.clip;
463 if (w->viewport.horiz_bar != NULL)
464 SetBar(w->viewport.horiz_bar, -(int)XtX(child),
465 XtWidth(clip), XtWidth(child));
467 if (w->viewport.vert_bar != NULL)
468 SetBar(w->viewport.vert_bar, -(int)XtY(child),
469 XtHeight(clip), XtHeight(child));
473 SendReport(ViewportWidget w, unsigned int changed)
477 if (w->viewport.report_callbacks) {
478 Widget child = w->viewport.child;
479 Widget clip = w->viewport.clip;
481 rep.changed = changed;
482 rep.slider_x = -XtX(child); /* child is canvas */
483 rep.slider_y = -XtY(child); /* clip is slider */
484 rep.slider_width = XtWidth(clip);
485 rep.slider_height = XtHeight(clip);
486 rep.canvas_width = XtWidth(child);
487 rep.canvas_height = XtHeight(child);
488 XtCallCallbackList((Widget)w, w->viewport.report_callbacks,
494 MoveChild(ViewportWidget w, int x, int y)
496 Widget child = w->viewport.child;
497 Widget clip = w->viewport.clip;
499 /* make sure we never move past right/bottom borders */
500 if (-x + (int)XtWidth(clip) > XtWidth(child))
501 x = -(int)(XtWidth(child) - XtWidth(clip));
503 if (-y + (int)XtHeight(clip) > XtHeight(child))
504 y = -(int)(XtHeight(child) - XtHeight(clip));
506 /* make sure we never move past left/top borders */
512 XtMoveWidget(child, x, y);
513 SendReport(w, (XawPRSliderX | XawPRSliderY));
519 ComputeLayout(Widget widget, Bool query, Bool destroy_scrollbars)
521 ViewportWidget w = (ViewportWidget)widget;
522 Widget child = w->viewport.child;
523 Widget clip = w->viewport.clip;
524 ViewportConstraints constraints =
525 (ViewportConstraints)clip->core.constraints;
526 Bool needshoriz, needsvert;
527 int clip_width, clip_height;
528 XtWidgetGeometry intended;
533 clip_width = XtWidth(w);
534 clip_height = XtHeight(w);
535 intended.request_mode = CWBorderWidth;
536 intended.border_width = 0;
538 if (w->viewport.forcebars) {
539 needsvert = w->viewport.allowvert;
540 needshoriz = w->viewport.allowhoriz;
541 ComputeWithForceBars(widget, query, &intended,
542 &clip_width, &clip_height);
545 Dimension prev_width, prev_height;
546 XtGeometryMask prev_mode;
547 XtWidgetGeometry preferred;
549 needshoriz = needsvert = False;
552 * intended.{width,height} caches the eventual child dimensions,
553 * but we don't set the mode bits until after we decide that the
554 * child's preferences are not acceptable
556 if (!w->viewport.allowhoriz)
557 intended.request_mode |= CWWidth;
559 if (XtWidth(child) < clip_width)
560 intended.width = clip_width;
562 intended.width = XtWidth(child);
564 if (XtHeight(child) < clip_height)
565 intended.height = clip_height;
567 intended.height = XtHeight(child);
569 if (!w->viewport.allowvert)
570 intended.request_mode |= CWHeight;
573 preferred.width = XtWidth(child);
574 preferred.height = XtHeight(child);
576 do { /* while intended != prev */
578 (void)XtQueryGeometry(child, &intended, &preferred);
579 if (!(preferred.request_mode & CWWidth))
580 preferred.width = intended.width;
581 if (!(preferred.request_mode & CWHeight))
582 preferred.height = intended.height;
584 prev_width = intended.width;
585 prev_height = intended.height;
586 prev_mode = intended.request_mode;
588 * note that having once decided to turn on either bar
589 * we'll not change our mind until we're next resized,
590 * thus avoiding potential oscillations
592 #define CheckHoriz() \
593 if (w->viewport.allowhoriz && \
594 preferred.width > clip_width) { \
599 if ((bar = w->viewport.horiz_bar) == NULL) \
600 bar = CreateScrollbar(w, True); \
601 clip_height -= XtHeight(bar) + XtBorderWidth(bar); \
602 if (clip_height < 1) \
605 intended.width = preferred.width; \
609 if (w->viewport.allowvert && preferred.height > clip_height) {
613 if ((bar = w->viewport.vert_bar) == NULL)
614 bar = CreateScrollbar(w, False);
615 clip_width -= XtWidth(bar) + XtBorderWidth(bar);
620 intended.height = preferred.height;
622 if (!w->viewport.allowhoriz || preferred.width < clip_width) {
623 intended.width = clip_width;
624 intended.request_mode |= CWWidth;
626 if (!w->viewport.allowvert || preferred.height < clip_height) {
627 intended.height = clip_height;
628 intended.request_mode |= CWHeight;
630 } while (intended.request_mode != prev_mode
631 || (intended.request_mode & CWWidth
632 && intended.width != prev_width)
633 || (intended.request_mode & CWHeight
634 && intended.height != prev_height));
637 if (XtIsRealized(clip))
638 XRaiseWindow(XtDisplay(clip), XtWindow(clip));
641 needsvert ? w->viewport.useright ? 0 :
642 XtWidth(w->viewport.vert_bar)
643 + XtBorderWidth(w->viewport.vert_bar) : 0,
644 needshoriz ? w->viewport.usebottom ? 0 :
645 XtHeight(w->viewport.horiz_bar)
646 + XtBorderWidth(w->viewport.horiz_bar) : 0);
647 XtResizeWidget(clip, clip_width, clip_height, 0);
649 if (w->viewport.horiz_bar != NULL) {
650 Widget bar = w->viewport.horiz_bar;
653 constraints->form.vert_base = NULL;
654 if (destroy_scrollbars) {
655 XtDestroyWidget(bar);
656 w->viewport.horiz_bar = NULL;
660 int bw = XtBorderWidth(bar);
662 XtResizeWidget(bar, clip_width, XtHeight(bar), bw);
664 needsvert && !w->viewport.useright
665 ? XtWidth(w->viewport.vert_bar) : -bw,
666 w->viewport.usebottom
667 ? XtHeight(w) - XtHeight(bar) - bw : -bw);
668 XtSetMappedWhenManaged(bar, True);
672 if (w->viewport.vert_bar != NULL) {
673 Widget bar = w->viewport.vert_bar;
676 constraints->form.horiz_base = NULL;
677 if (destroy_scrollbars) {
678 XtDestroyWidget(bar);
679 w->viewport.vert_bar = NULL;
683 int bw = bar->core.border_width;
685 XtResizeWidget(bar, XtWidth(bar), clip_height, bw);
688 ? XtWidth(w) - XtWidth(bar) - bw : -bw,
689 needshoriz && !w->viewport.usebottom
690 ? XtHeight(w->viewport.horiz_bar) : -bw);
691 XtSetMappedWhenManaged(bar, True);
696 XtResizeWidget(child, intended.width, intended.height, 0);
697 MoveChild(w, needshoriz ? XtX(child) : 0, needsvert ? XtY(child) : 0);
700 SendReport (w, XawPRAll);
705 * ComputeWithForceBars
708 * widget - viewport widget
709 * query - whether or not to query the child
710 * intended - cache of the childs height is stored here
711 * (used and returned)
712 * clip_width - size of clip window (used and returned)
716 * Computes the layout give forcebars is set.
719 ComputeWithForceBars(Widget widget, Bool query, XtWidgetGeometry *intended,
720 int *clip_width, int *clip_height)
722 ViewportWidget w = (ViewportWidget)widget;
723 Widget child = w->viewport.child;
724 XtWidgetGeometry preferred;
727 * If forcebars then needs = allows = has
728 * Thus if needsvert is set it MUST have a scrollbar
730 if (w->viewport.allowvert) {
731 if (w->viewport.vert_bar == NULL)
732 w->viewport.vert_bar = CreateScrollbar(w, False);
734 *clip_width -= XtWidth(w->viewport.vert_bar) +
735 XtBorderWidth(w->viewport.vert_bar);
738 if (w->viewport.allowhoriz) {
739 if (w->viewport.horiz_bar == NULL)
740 w->viewport.horiz_bar = CreateScrollbar(w, True);
742 *clip_height -= XtHeight(w->viewport.horiz_bar) +
743 XtBorderWidth(w->viewport.horiz_bar);
746 AssignMax(*clip_width, 1);
747 AssignMax(*clip_height, 1);
749 if (!w->viewport.allowvert) {
750 intended->height = *clip_height;
751 intended->request_mode = CWHeight;
753 if (!w->viewport.allowhoriz) {
754 intended->width = *clip_width;
755 intended->request_mode = CWWidth;
759 if (w->viewport.allowvert || w->viewport.allowhoriz) {
760 XtQueryGeometry(child, intended, &preferred);
762 if (!(intended->request_mode & CWWidth)) {
763 if (preferred.request_mode & CWWidth)
764 intended->width = preferred.width;
766 intended->width = XtWidth(child);
769 if (!(intended->request_mode & CWHeight)) {
770 if (preferred.request_mode & CWHeight)
771 intended->height = preferred.height;
773 intended->height = XtHeight(child);
778 if (w->viewport.allowvert)
779 intended->height = XtHeight(child);
780 if (w->viewport.allowhoriz)
781 intended->width = XtWidth(child);
784 if (*clip_width > (int)intended->width)
785 intended->width = *clip_width;
786 if (*clip_height > (int)intended->height)
787 intended->height = *clip_height;
791 XawViewportResize(Widget widget)
793 ComputeLayout(widget, True, True);
798 Layout(FormWidget w, unsigned int width, unsigned int height, Bool force)
800 ComputeLayout((Widget)w, True, True);
801 w->form.preferred_width = XtWidth(w);
802 w->form.preferred_height = XtHeight(w);
808 ScrollUpDownProc(Widget widget, XtPointer closure, XtPointer call_data)
810 ViewportWidget w = (ViewportWidget)closure;
811 Widget child = w->viewport.child;
812 int pix = (long)call_data;
818 x = XtX(child) - (widget == w->viewport.horiz_bar ? pix : 0);
819 y = XtY(child) - (widget == w->viewport.vert_bar ? pix : 0);
825 ThumbProc(Widget widget, XtPointer closure, XtPointer call_data)
827 ViewportWidget w = (ViewportWidget)closure;
828 Widget child = w->viewport.child;
829 float percent = *(float *)call_data;
835 if (widget == w->viewport.horiz_bar)
836 x = -percent * XtWidth(child);
840 if (widget == w->viewport.vert_bar)
841 y = -percent * XtHeight(child);
848 static XtGeometryResult
849 TestSmaller(ViewportWidget w, XtWidgetGeometry *request,
850 XtWidgetGeometry *reply_return)
852 if (request->width < XtWidth(w) || request->height < XtHeight(w))
853 return (XtMakeGeometryRequest((Widget)w, request, reply_return));
855 return (XtGeometryYes);
858 static XtGeometryResult
859 GeometryRequestPlusScrollbar(ViewportWidget w, Bool horizontal,
860 XtWidgetGeometry *request,
861 XtWidgetGeometry *reply_return)
864 XtWidgetGeometry plusScrollbars;
866 plusScrollbars = *request;
867 if ((sb = w->viewport.horiz_bar) == NULL)
868 sb = CreateScrollbar(w, horizontal);
869 request->width += XtWidth(sb);
870 request->height += XtHeight(sb);
872 return (XtMakeGeometryRequest((Widget)w, &plusScrollbars, reply_return));
875 #define WidthChange() (request->width != XtWidth(w))
876 #define HeightChange() (request->height != XtHeight(w))
877 static XtGeometryResult
878 QueryGeometry(ViewportWidget w, XtWidgetGeometry *request,
879 XtWidgetGeometry *reply_return)
881 if (w->viewport.allowhoriz && w->viewport.allowvert)
882 return (TestSmaller(w, request, reply_return));
884 else if (w->viewport.allowhoriz && !w->viewport.allowvert) {
885 if (WidthChange() && !HeightChange())
886 return (TestSmaller(w, request, reply_return));
887 else if (!WidthChange() && HeightChange())
888 return (XtMakeGeometryRequest((Widget)w, request, reply_return));
889 else if (WidthChange() && HeightChange())
890 return (GeometryRequestPlusScrollbar(w, True, request, reply_return));
891 else /* !WidthChange() && !HeightChange() */
892 return (XtGeometryYes);
894 else if (!w->viewport.allowhoriz && w->viewport.allowvert) {
895 if (!WidthChange() && HeightChange())
896 return (TestSmaller(w, request, reply_return));
897 else if (WidthChange() && !HeightChange())
898 return (XtMakeGeometryRequest((Widget)w, request, reply_return));
899 else if (WidthChange() && HeightChange())
900 return (GeometryRequestPlusScrollbar(w, False, request, reply_return));
901 else /* !WidthChange() && !HeightChange() */
902 return (XtGeometryYes);
904 else /* (!w->viewport.allowhoriz && !w->viewport.allowvert) */
905 return (XtMakeGeometryRequest((Widget)w, request, reply_return));
910 static XtGeometryResult
911 XawViewportGeometryManager(Widget child, XtWidgetGeometry *request,
912 XtWidgetGeometry *reply)
914 ViewportWidget w = (ViewportWidget)child->core.parent;
915 Bool rWidth = (request->request_mode & CWWidth) != 0;
916 Bool rHeight = (request->request_mode & CWHeight) != 0;
917 XtWidgetGeometry allowed;
918 XtGeometryResult result;
920 Bool child_changed_size;
921 unsigned int height_remaining;
923 if (request->request_mode & XtCWQueryOnly)
924 return (QueryGeometry(w, request, reply));
926 if (child != w->viewport.child
927 || request->request_mode & ~(CWWidth | CWHeight | CWBorderWidth)
928 || ((request->request_mode & CWBorderWidth)
929 && request->border_width > 0))
930 return (XtGeometryNo);
934 reconfigured = GetGeometry((Widget)w,
935 rWidth ? request->width : XtWidth(w),
936 rHeight ? request->height : XtHeight(w));
938 child_changed_size = (rWidth && XtWidth(child) != request->width) ||
939 (rHeight && XtHeight(child) != request->height);
941 height_remaining = XtHeight(w);
942 if (rWidth && XtWidth(w) != request->width) {
943 if (w->viewport.allowhoriz && request->width > XtWidth(w)) {
944 /* horizontal scrollbar will be needed so possibly reduce height */
947 if ((bar = w->viewport.horiz_bar) == NULL)
948 bar = CreateScrollbar(w, True);
949 height_remaining -= XtHeight(bar) + XtBorderWidth(bar);
953 allowed.width = XtWidth(w);
955 if (rHeight && height_remaining != request->height) {
956 if (w->viewport.allowvert && request->height > height_remaining) {
957 /* vertical scrollbar will be needed, so possibly reduce width */
958 if (!w->viewport.allowhoriz || request->width < XtWidth(w)) {
961 if ((bar = w->viewport.vert_bar) == NULL)
962 bar = CreateScrollbar(w, False);
964 allowed.width = XtWidth(w);
965 allowed.request_mode |= CWWidth;
967 if (allowed.width > XtWidth(bar) + XtBorderWidth(bar))
968 allowed.width -= XtWidth(bar) + XtBorderWidth(bar);
975 allowed.height = height_remaining;
978 if (allowed.width != request->width || allowed.height != request->height) {
980 result = XtGeometryAlmost;
984 XtWidth(child) = request->width;
986 XtHeight(child) = request->height;
987 result = XtGeometryYes;
990 if (reconfigured || child_changed_size)
991 ComputeLayout((Widget)w, False, result == XtGeometryYes);
997 GetGeometry(Widget w, unsigned int width, unsigned int height)
999 XtWidgetGeometry geometry, return_geom;
1000 XtGeometryResult result;
1002 if (width == XtWidth(w) && height == XtHeight(w))
1005 geometry.request_mode = CWWidth | CWHeight;
1006 geometry.width = width;
1007 geometry.height = height;
1009 if (XtIsRealized(w)) {
1010 if (((ViewportWidget)w)->viewport.allowhoriz && width > XtWidth(w))
1011 geometry.width = XtWidth(w);
1012 if (((ViewportWidget)w)->viewport.allowvert && height > XtHeight(w))
1013 geometry.height = XtHeight(w);
1016 /* This is the Realize call; we'll inherit a w&h iff none currently */
1017 if (XtWidth(w) != 0) {
1018 if (XtHeight(w) != 0)
1020 geometry.width = XtWidth(w);
1022 if (XtHeight(w) != 0)
1023 geometry.height = XtHeight(w);
1026 result = XtMakeGeometryRequest(w, &geometry, &return_geom);
1027 if (result == XtGeometryAlmost)
1028 result = XtMakeGeometryRequest(w, &return_geom, NULL);
1030 return (result == XtGeometryYes);
1033 static XtGeometryResult
1034 XawViewportQueryGeometry(Widget w, XtWidgetGeometry *constraints,
1035 XtWidgetGeometry *reply)
1037 if (((ViewportWidget)w)->viewport.child != NULL)
1038 return (XtQueryGeometry(((ViewportWidget)w)->viewport.child,
1039 constraints, reply));
1041 return (XtGeometryYes);
1045 XawViewportSetLocation
1048 #if NeedWidePrototypes
1049 double xoff, double yoff
1051 float xoff, float yoff
1055 ViewportWidget w = (ViewportWidget)gw;
1056 Widget child = w->viewport.child;
1059 if (xoff > 1.0) /* scroll to right */
1061 else if (xoff < 0.0) /* if the offset is < 0.0 nothing */
1064 x = (float)XtWidth(child) * xoff;
1067 y = XtHeight(child);
1068 else if (yoff < 0.0)
1071 y = (float)XtHeight(child) * yoff;
1073 MoveChild (w, -x, -y);
1077 XawViewportSetCoordinates(Widget gw,
1078 #if NeedWidePrototypes
1081 Position x, Position y
1085 ViewportWidget w = (ViewportWidget)gw;
1086 Widget child = w->viewport.child;
1088 if (x > XtWidth(child))
1093 if (y > XtHeight(child))
1094 y = XtHeight(child);
1098 MoveChild (w, -x, -y);