2
* $Xorg: Porthole.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $
4
Copyright 1990, 1994, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
Except as contained in this notice, the name of The Open Group shall not be
23
used in advertising or otherwise to promote the sale, use or other dealings
24
in this Software without prior written authorization from The Open Group.
26
* Author: Jim Fulton, MIT X Consortium
28
* This widget is a trivial clipping widget. It is typically used with a
29
* panner or scrollbar to navigate.
31
/* $XFree86: xc/lib/Xaw/Porthole.c,v 1.7 2001/12/14 19:54:41 dawes Exp $ */
33
#include <X11/IntrinsicP.h>
34
#include <X11/StringDefs.h>
35
#include <X11/Xmu/Misc.h>
36
#include <X11/Xaw/PortholeP.h>
37
#include <X11/Xaw/XawInit.h>
43
static void XawPortholeChangeManaged(Widget);
44
static XtGeometryResult XawPortholeGeometryManager(Widget, XtWidgetGeometry*,
46
static XtGeometryResult XawPortholeQueryGeometry(Widget, XtWidgetGeometry*,
48
static void XawPortholeRealize(Widget, Mask*, XSetWindowAttributes*);
49
static void XawPortholeResize(Widget);
54
static Widget find_child(PortholeWidget);
55
static void layout_child(PortholeWidget, Widget, XtWidgetGeometry*,
56
Position*, Position*, Dimension*, Dimension*);
57
static void SendReport(PortholeWidget, unsigned int);
62
#define offset(field) XtOffsetOf(PortholeRec, porthole.field)
63
static XtResource resources[] = {
69
offset(report_callbacks),
76
#define Superclass (&compositeClassRec)
77
PortholeClassRec portholeClassRec = {
80
(WidgetClass)Superclass, /* superclass */
81
"Porthole", /* class_name */
82
sizeof(PortholeRec), /* widget_size */
83
XawInitializeWidgetSet, /* class_initialize */
84
NULL, /* class_part_initialize */
85
False, /* class_inited */
86
NULL, /* initialize */
87
NULL, /* initialize_hook */
88
XawPortholeRealize, /* realize */
91
resources, /* resources */
92
XtNumber(resources), /* num_resources */
93
NULLQUARK, /* xrm_class */
94
True, /* compress_motion */
95
True, /* compress_exposure */
96
True, /* compress_enterleave */
97
False, /* visible_interest */
99
XawPortholeResize, /* resize */
101
NULL, /* set_values */
102
NULL, /* set_values_hook */
103
XtInheritSetValuesAlmost, /* set_values_almost */
104
NULL, /* get_values_hook */
105
NULL, /* accept_focus */
106
XtVersion, /* version */
107
NULL, /* callback_private */
109
XawPortholeQueryGeometry, /* query_geometry */
110
XtInheritDisplayAccelerator, /* display_accelerator */
111
NULL, /* extension */
115
XawPortholeGeometryManager, /* geometry_manager */
116
XawPortholeChangeManaged, /* change_managed */
117
XtInheritInsertChild, /* insert_child */
118
XtInheritDeleteChild, /* delete_child */
119
NULL, /* extension */
122
NULL, /* extension */
126
WidgetClass portholeWidgetClass = (WidgetClass)&portholeClassRec;
132
find_child(PortholeWidget pw)
138
* Find the managed child on which we should operate. Ignore multiple
141
for (i = 0, children = pw->composite.children;
142
i < pw->composite.num_children; i++, children++)
143
if (XtIsManaged(*children))
150
SendReport(PortholeWidget pw, unsigned int changed)
152
Widget child = find_child(pw);
154
if (pw->porthole.report_callbacks && child) {
155
XawPannerReport prep;
157
prep.changed = changed;
158
prep.slider_x = -XtX(child); /* porthole is "inner" */
159
prep.slider_y = -XtY(child); /* child is outer since it is larger */
160
prep.slider_width = XtWidth(pw);
161
prep.slider_height = XtHeight(pw);
162
prep.canvas_width = XtWidth(child);
163
prep.canvas_height = XtHeight(child);
164
XtCallCallbackList((Widget)pw, pw->porthole.report_callbacks,
170
layout_child(PortholeWidget pw, Widget child, XtWidgetGeometry *geomp,
171
Position *xp, Position *yp, Dimension *widthp, Dimension *heightp)
175
*xp = XtX(child); /* default to current values */
177
*widthp = XtWidth(child);
178
*heightp = XtHeight(child);
179
if (geomp) { /* mix in any requested changes */
180
if (geomp->request_mode & CWX)
182
if (geomp->request_mode & CWY)
184
if (geomp->request_mode & CWWidth)
185
*widthp = geomp->width;
186
if (geomp->request_mode & CWHeight)
187
*heightp = geomp->height;
191
* Make sure that the child is at least as large as the porthole; there
194
if (*widthp < XtWidth(pw)) *widthp = XtWidth(pw);
195
if (*heightp < XtHeight(pw)) *heightp = XtHeight(pw);
198
* Make sure that the child is still on the screen. Note that this must
199
* be done *after* the size computation so that we know where to put it
201
minx = (Position)XtWidth(pw) - (Position)*widthp;
202
miny = (Position)XtHeight(pw) - (Position)*heightp;
216
XawPortholeRealize(Widget gw, Mask *valueMask, XSetWindowAttributes *attr)
218
attr->bit_gravity = NorthWestGravity;
219
*valueMask |= CWBitGravity;
223
if (XtHeight(gw) < 1)
225
(*portholeWidgetClass->core_class.superclass->core_class.realize)
226
(gw, valueMask, attr);
230
XawPortholeResize(Widget gw)
232
PortholeWidget pw = (PortholeWidget)gw;
233
Widget child = find_child(pw);
236
* If we have a child, we need to make sure that it is at least as big
237
* as we are and in the right place
241
Dimension width, height;
243
layout_child(pw, child, NULL, &x, &y, &width, &height);
244
XtConfigureWidget(child, x, y, width, height, 0);
247
SendReport(pw, XawPRCanvasWidth | XawPRCanvasHeight);
250
static XtGeometryResult
251
XawPortholeQueryGeometry(Widget gw, XtWidgetGeometry *intended,
252
XtWidgetGeometry *preferred)
254
PortholeWidget pw = (PortholeWidget)gw;
255
Widget child = find_child(pw);
258
#define SIZEONLY (CWWidth | CWHeight)
259
preferred->request_mode = SIZEONLY;
260
preferred->width = XtWidth(child);
261
preferred->height = XtHeight(child);
263
if ((intended->request_mode & SIZEONLY) == SIZEONLY &&
264
intended->width == preferred->width &&
265
intended->height == preferred->height)
266
return (XtGeometryYes);
267
else if (preferred->width == XtWidth(pw) &&
268
preferred->height == XtHeight(pw))
269
return (XtGeometryNo);
271
return (XtGeometryAlmost);
275
return (XtGeometryNo);
278
static XtGeometryResult
279
XawPortholeGeometryManager(Widget w, XtWidgetGeometry *req,
280
XtWidgetGeometry *reply)
282
PortholeWidget pw = (PortholeWidget) w->core.parent;
283
Widget child = find_child(pw);
287
return (XtGeometryNo);
289
*reply = *req; /* assume we'll grant everything */
291
if ((req->request_mode & CWBorderWidth) && req->border_width != 0) {
292
reply->border_width = 0;
296
layout_child(pw, child, req, &reply->x, &reply->y,
297
&reply->width, &reply->height);
299
if ((req->request_mode & CWX) && req->x != reply->x)
301
if ((req->request_mode & CWY) && req->x != reply->x)
303
if ((req->request_mode & CWWidth) && req->width != reply->width)
305
if ((req->request_mode & CWHeight) && req->height != reply->height)
309
* If we failed on anything, simply return without touching widget
312
return (XtGeometryAlmost);
315
* If not just doing a query, update widget and send report. Note that
316
* we will often set fields that weren't requested because we want to keep
319
if (!(req->request_mode & XtCWQueryOnly)) {
320
unsigned int changed = 0;
322
if (XtX(child) != reply->x) {
323
changed |= XawPRSliderX;
324
XtX(child) = reply->x;
326
if (XtY(child) != reply->y) {
327
changed |= XawPRSliderY;
328
XtY(child) = reply->y;
330
if (XtWidth(child) != reply->width) {
331
changed |= XawPRSliderWidth;
332
XtWidth(child) = reply->width;
334
if (XtHeight(child) != reply->height) {
335
changed |= XawPRSliderHeight;
336
XtHeight(child) = reply->height;
339
SendReport(pw, changed);
342
return (XtGeometryYes); /* success! */
346
XawPortholeChangeManaged(Widget gw)
348
PortholeWidget pw = (PortholeWidget)gw;
349
Widget child = find_child (pw); /* ignore extra children */
352
if (!XtIsRealized (gw)) {
353
XtWidgetGeometry geom, retgeom;
355
geom.request_mode = 0;
356
if (XtWidth(pw) == 0) {
357
geom.width = XtWidth(child);
358
geom.request_mode |= CWWidth;
360
if (XtHeight(pw) == 0) {
361
geom.height = XtHeight(child);
362
geom.request_mode |= CWHeight;
364
if (geom.request_mode &&
365
XtMakeGeometryRequest (gw, &geom, &retgeom)
367
(void)XtMakeGeometryRequest(gw, &retgeom, NULL);
370
XtResizeWidget(child, Max(XtWidth(child), XtWidth(pw)),
371
Max(XtHeight(child), XtHeight(pw)), 0);
373
SendReport(pw, XawPRAll);