#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xmu/Misc.h>
#include <X11/Xaw/PortholeP.h>
#include <X11/Xaw/XawInit.h>
#include "Private.h"
static void XawPortholeChangeManaged(Widget);
static XtGeometryResult XawPortholeGeometryManager(Widget, XtWidgetGeometry*,
XtWidgetGeometry*);
static XtGeometryResult XawPortholeQueryGeometry(Widget, XtWidgetGeometry*,
XtWidgetGeometry*);
static void XawPortholeRealize(Widget, Mask*, XSetWindowAttributes*);
static void XawPortholeResize(Widget);
static Widget find_child(PortholeWidget);
static void layout_child(PortholeWidget, Widget, XtWidgetGeometry*,
Position*, Position*, Dimension*, Dimension*);
static void SendReport(PortholeWidget, unsigned int);
#define offset(field) XtOffsetOf(PortholeRec, porthole.field)
static XtResource resources[] = {
{
XtNreportCallback,
XtCReportCallback,
XtRCallback,
sizeof(XtPointer),
offset(report_callbacks),
XtRCallback,
NULL
},
};
#undef offset
#define Superclass (&compositeClassRec)
PortholeClassRec portholeClassRec = {
{
(WidgetClass)Superclass,
"Porthole",
sizeof(PortholeRec),
XawInitializeWidgetSet,
NULL,
False,
NULL,
NULL,
XawPortholeRealize,
NULL,
0,
resources,
XtNumber(resources),
NULLQUARK,
True,
True,
True,
False,
NULL,
XawPortholeResize,
NULL,
NULL,
NULL,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
NULL,
XawPortholeQueryGeometry,
XtInheritDisplayAccelerator,
NULL,
},
{
XawPortholeGeometryManager,
XawPortholeChangeManaged,
XtInheritInsertChild,
XtInheritDeleteChild,
NULL,
},
{
NULL,
},
};
WidgetClass portholeWidgetClass = (WidgetClass)&portholeClassRec;
static Widget
find_child(PortholeWidget pw)
{
Widget *children;
unsigned int i;
for (i = 0, children = pw->composite.children;
i < pw->composite.num_children; i++, children++)
if (XtIsManaged(*children))
return (*children);
return (NULL);
}
static void
SendReport(PortholeWidget pw, unsigned int changed)
{
Widget child = find_child(pw);
if (pw->porthole.report_callbacks && child) {
XawPannerReport prep;
prep.changed = changed;
prep.slider_x = -XtX(child);
prep.slider_y = -XtY(child);
prep.slider_width = XtWidth(pw);
prep.slider_height = XtHeight(pw);
prep.canvas_width = XtWidth(child);
prep.canvas_height = XtHeight(child);
XtCallCallbackList((Widget)pw, pw->porthole.report_callbacks,
(XtPointer)&prep);
}
}
static void
layout_child(PortholeWidget pw, Widget child, XtWidgetGeometry *geomp,
Position *xp, Position *yp, Dimension *widthp, Dimension *heightp)
{
Position minx, miny;
*xp = XtX(child);
*yp = XtY(child);
*widthp = XtWidth(child);
*heightp = XtHeight(child);
if (geomp) {
if (geomp->request_mode & CWX)
*xp = geomp->x;
if (geomp->request_mode & CWY)
*yp = geomp->y;
if (geomp->request_mode & CWWidth)
*widthp = geomp->width;
if (geomp->request_mode & CWHeight)
*heightp = geomp->height;
}
if (*widthp < XtWidth(pw)) *widthp = XtWidth(pw);
if (*heightp < XtHeight(pw)) *heightp = XtHeight(pw);
minx = (Position)XtWidth(pw) - (Position)*widthp;
miny = (Position)XtHeight(pw) - (Position)*heightp;
if (*xp < minx)
*xp = minx;
if (*yp < miny)
*yp = miny;
if (*xp > 0)
*xp = 0;
if (*yp > 0)
*yp = 0;
}
static void
XawPortholeRealize(Widget gw, Mask *valueMask, XSetWindowAttributes *attr)
{
attr->bit_gravity = NorthWestGravity;
*valueMask |= CWBitGravity;
if (XtWidth(gw) < 1)
XtWidth(gw) = 1;
if (XtHeight(gw) < 1)
XtHeight(gw) = 1;
(*portholeWidgetClass->core_class.superclass->core_class.realize)
(gw, valueMask, attr);
}
static void
XawPortholeResize(Widget gw)
{
PortholeWidget pw = (PortholeWidget)gw;
Widget child = find_child(pw);
if (child) {
Position x, y;
Dimension width, height;
layout_child(pw, child, NULL, &x, &y, &width, &height);
XtConfigureWidget(child, x, y, width, height, 0);
}
SendReport(pw, XawPRCanvasWidth | XawPRCanvasHeight);
}
static XtGeometryResult
XawPortholeQueryGeometry(Widget gw, XtWidgetGeometry *intended,
XtWidgetGeometry *preferred)
{
PortholeWidget pw = (PortholeWidget)gw;
Widget child = find_child(pw);
if (child) {
#define SIZEONLY (CWWidth | CWHeight)
preferred->request_mode = SIZEONLY;
preferred->width = XtWidth(child);
preferred->height = XtHeight(child);
if ((intended->request_mode & SIZEONLY) == SIZEONLY &&
intended->width == preferred->width &&
intended->height == preferred->height)
return (XtGeometryYes);
else if (preferred->width == XtWidth(pw) &&
preferred->height == XtHeight(pw))
return (XtGeometryNo);
return (XtGeometryAlmost);
#undef SIZEONLY
}
return (XtGeometryNo);
}
static XtGeometryResult
XawPortholeGeometryManager(Widget w, XtWidgetGeometry *req,
XtWidgetGeometry *reply)
{
PortholeWidget pw = (PortholeWidget) w->core.parent;
Widget child = find_child(pw);
Bool okay = True;
if (child != w)
return (XtGeometryNo);
*reply = *req;
if ((req->request_mode & CWBorderWidth) && req->border_width != 0) {
reply->border_width = 0;
okay = False;
}
layout_child(pw, child, req, &reply->x, &reply->y,
&reply->width, &reply->height);
if ((req->request_mode & CWX) && req->x != reply->x)
okay = False;
if ((req->request_mode & CWY) && req->x != reply->x)
okay = False;
if ((req->request_mode & CWWidth) && req->width != reply->width)
okay = False;
if ((req->request_mode & CWHeight) && req->height != reply->height)
okay = False;
if (!okay)
return (XtGeometryAlmost);
if (!(req->request_mode & XtCWQueryOnly)) {
unsigned int changed = 0;
if (XtX(child) != reply->x) {
changed |= XawPRSliderX;
XtX(child) = reply->x;
}
if (XtY(child) != reply->y) {
changed |= XawPRSliderY;
XtY(child) = reply->y;
}
if (XtWidth(child) != reply->width) {
changed |= XawPRSliderWidth;
XtWidth(child) = reply->width;
}
if (XtHeight(child) != reply->height) {
changed |= XawPRSliderHeight;
XtHeight(child) = reply->height;
}
if (changed)
SendReport(pw, changed);
}
return (XtGeometryYes);
}
static void
XawPortholeChangeManaged(Widget gw)
{
PortholeWidget pw = (PortholeWidget)gw;
Widget child = find_child (pw);
if (child) {
if (!XtIsRealized (gw)) {
XtWidgetGeometry geom, retgeom;
geom.request_mode = 0;
if (XtWidth(pw) == 0) {
geom.width = XtWidth(child);
geom.request_mode |= CWWidth;
}
if (XtHeight(pw) == 0) {
geom.height = XtHeight(child);
geom.request_mode |= CWHeight;
}
if (geom.request_mode &&
XtMakeGeometryRequest (gw, &geom, &retgeom)
== XtGeometryAlmost)
(void)XtMakeGeometryRequest(gw, &retgeom, NULL);
}
XtResizeWidget(child, Max(XtWidth(child), XtWidth(pw)),
Max(XtHeight(child), XtHeight(pw)), 0);
SendReport(pw, XawPRAll);
}
}