3 Copyright 1990, 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.
25 * Author: Jim Fulton, MIT X Consortium
27 * This widget is a trivial clipping widget. It is typically used with a
28 * panner or scrollbar to navigate.
34 #include <X11/IntrinsicP.h>
35 #include <X11/StringDefs.h>
36 #include <X11/Xmu/Misc.h>
37 #include <X11/Xaw/PortholeP.h>
38 #include <X11/Xaw/XawInit.h>
44 static void XawPortholeChangeManaged(Widget);
45 static XtGeometryResult XawPortholeGeometryManager(Widget, XtWidgetGeometry*,
47 static XtGeometryResult XawPortholeQueryGeometry(Widget, XtWidgetGeometry*,
49 static void XawPortholeRealize(Widget, Mask*, XSetWindowAttributes*);
50 static void XawPortholeResize(Widget);
55 static Widget find_child(PortholeWidget);
56 static void layout_child(PortholeWidget, Widget, XtWidgetGeometry*,
57 Position*, Position*, Dimension*, Dimension*);
58 static void SendReport(PortholeWidget, unsigned int);
63 #define offset(field) XtOffsetOf(PortholeRec, porthole.field)
64 static XtResource resources[] = {
70 offset(report_callbacks),
77 #define Superclass (&compositeClassRec)
78 PortholeClassRec portholeClassRec = {
81 (WidgetClass)Superclass, /* superclass */
82 "Porthole", /* class_name */
83 sizeof(PortholeRec), /* widget_size */
84 XawInitializeWidgetSet, /* class_initialize */
85 NULL, /* class_part_initialize */
86 False, /* class_inited */
87 NULL, /* initialize */
88 NULL, /* initialize_hook */
89 XawPortholeRealize, /* realize */
92 resources, /* resources */
93 XtNumber(resources), /* num_resources */
94 NULLQUARK, /* xrm_class */
95 True, /* compress_motion */
96 True, /* compress_exposure */
97 True, /* compress_enterleave */
98 False, /* visible_interest */
100 XawPortholeResize, /* resize */
102 NULL, /* set_values */
103 NULL, /* set_values_hook */
104 XtInheritSetValuesAlmost, /* set_values_almost */
105 NULL, /* get_values_hook */
106 NULL, /* accept_focus */
107 XtVersion, /* version */
108 NULL, /* callback_private */
110 XawPortholeQueryGeometry, /* query_geometry */
111 XtInheritDisplayAccelerator, /* display_accelerator */
112 NULL, /* extension */
116 XawPortholeGeometryManager, /* geometry_manager */
117 XawPortholeChangeManaged, /* change_managed */
118 XtInheritInsertChild, /* insert_child */
119 XtInheritDeleteChild, /* delete_child */
120 NULL, /* extension */
123 NULL, /* extension */
127 WidgetClass portholeWidgetClass = (WidgetClass)&portholeClassRec;
133 find_child(PortholeWidget pw)
139 * Find the managed child on which we should operate. Ignore multiple
142 for (i = 0, children = pw->composite.children;
143 i < pw->composite.num_children; i++, children++)
144 if (XtIsManaged(*children))
151 SendReport(PortholeWidget pw, unsigned int changed)
153 Widget child = find_child(pw);
155 if (pw->porthole.report_callbacks && child) {
156 XawPannerReport prep;
158 prep.changed = changed;
159 prep.slider_x = -XtX(child); /* porthole is "inner" */
160 prep.slider_y = -XtY(child); /* child is outer since it is larger */
161 prep.slider_width = XtWidth(pw);
162 prep.slider_height = XtHeight(pw);
163 prep.canvas_width = XtWidth(child);
164 prep.canvas_height = XtHeight(child);
165 XtCallCallbackList((Widget)pw, pw->porthole.report_callbacks,
171 layout_child(PortholeWidget pw, Widget child, XtWidgetGeometry *geomp,
172 Position *xp, Position *yp, Dimension *widthp, Dimension *heightp)
176 *xp = XtX(child); /* default to current values */
178 *widthp = XtWidth(child);
179 *heightp = XtHeight(child);
180 if (geomp) { /* mix in any requested changes */
181 if (geomp->request_mode & CWX)
183 if (geomp->request_mode & CWY)
185 if (geomp->request_mode & CWWidth)
186 *widthp = geomp->width;
187 if (geomp->request_mode & CWHeight)
188 *heightp = geomp->height;
192 * Make sure that the child is at least as large as the porthole; there
195 if (*widthp < XtWidth(pw)) *widthp = XtWidth(pw);
196 if (*heightp < XtHeight(pw)) *heightp = XtHeight(pw);
199 * Make sure that the child is still on the screen. Note that this must
200 * be done *after* the size computation so that we know where to put it
202 minx = (Position)XtWidth(pw) - (Position)*widthp;
203 miny = (Position)XtHeight(pw) - (Position)*heightp;
217 XawPortholeRealize(Widget gw, Mask *valueMask, XSetWindowAttributes *attr)
219 attr->bit_gravity = NorthWestGravity;
220 *valueMask |= CWBitGravity;
224 if (XtHeight(gw) < 1)
226 (*portholeWidgetClass->core_class.superclass->core_class.realize)
227 (gw, valueMask, attr);
231 XawPortholeResize(Widget gw)
233 PortholeWidget pw = (PortholeWidget)gw;
234 Widget child = find_child(pw);
237 * If we have a child, we need to make sure that it is at least as big
238 * as we are and in the right place
242 Dimension width, height;
244 layout_child(pw, child, NULL, &x, &y, &width, &height);
245 XtConfigureWidget(child, x, y, width, height, 0);
248 SendReport(pw, XawPRCanvasWidth | XawPRCanvasHeight);
251 static XtGeometryResult
252 XawPortholeQueryGeometry(Widget gw, XtWidgetGeometry *intended,
253 XtWidgetGeometry *preferred)
255 PortholeWidget pw = (PortholeWidget)gw;
256 Widget child = find_child(pw);
259 #define SIZEONLY (CWWidth | CWHeight)
260 preferred->request_mode = SIZEONLY;
261 preferred->width = XtWidth(child);
262 preferred->height = XtHeight(child);
264 if ((intended->request_mode & SIZEONLY) == SIZEONLY &&
265 intended->width == preferred->width &&
266 intended->height == preferred->height)
267 return (XtGeometryYes);
268 else if (preferred->width == XtWidth(pw) &&
269 preferred->height == XtHeight(pw))
270 return (XtGeometryNo);
272 return (XtGeometryAlmost);
276 return (XtGeometryNo);
279 static XtGeometryResult
280 XawPortholeGeometryManager(Widget w, XtWidgetGeometry *req,
281 XtWidgetGeometry *reply)
283 PortholeWidget pw = (PortholeWidget) w->core.parent;
284 Widget child = find_child(pw);
288 return (XtGeometryNo);
290 *reply = *req; /* assume we'll grant everything */
292 if ((req->request_mode & CWBorderWidth) && req->border_width != 0) {
293 reply->border_width = 0;
297 layout_child(pw, child, req, &reply->x, &reply->y,
298 &reply->width, &reply->height);
300 if ((req->request_mode & CWX) && req->x != reply->x)
302 if ((req->request_mode & CWY) && req->x != reply->x)
304 if ((req->request_mode & CWWidth) && req->width != reply->width)
306 if ((req->request_mode & CWHeight) && req->height != reply->height)
310 * If we failed on anything, simply return without touching widget
313 return (XtGeometryAlmost);
316 * If not just doing a query, update widget and send report. Note that
317 * we will often set fields that weren't requested because we want to keep
320 if (!(req->request_mode & XtCWQueryOnly)) {
321 unsigned int changed = 0;
323 if (XtX(child) != reply->x) {
324 changed |= XawPRSliderX;
325 XtX(child) = reply->x;
327 if (XtY(child) != reply->y) {
328 changed |= XawPRSliderY;
329 XtY(child) = reply->y;
331 if (XtWidth(child) != reply->width) {
332 changed |= XawPRSliderWidth;
333 XtWidth(child) = reply->width;
335 if (XtHeight(child) != reply->height) {
336 changed |= XawPRSliderHeight;
337 XtHeight(child) = reply->height;
340 SendReport(pw, changed);
343 return (XtGeometryYes); /* success! */
347 XawPortholeChangeManaged(Widget gw)
349 PortholeWidget pw = (PortholeWidget)gw;
350 Widget child = find_child (pw); /* ignore extra children */
353 if (!XtIsRealized (gw)) {
354 XtWidgetGeometry geom, retgeom;
356 geom.request_mode = 0;
357 if (XtWidth(pw) == 0) {
358 geom.width = XtWidth(child);
359 geom.request_mode |= CWWidth;
361 if (XtHeight(pw) == 0) {
362 geom.height = XtHeight(child);
363 geom.request_mode |= CWHeight;
365 if (geom.request_mode &&
366 XtMakeGeometryRequest (gw, &geom, &retgeom)
368 (void)XtMakeGeometryRequest(gw, &retgeom, NULL);
371 XtResizeWidget(child, Max(XtWidth(child), XtWidth(pw)),
372 Max(XtHeight(child), XtHeight(pw)), 0);
374 SendReport(pw, XawPRAll);