geometry_manager()geometry_manager()Namegeometry_manager - Composite class method called when a child requests
a new geometry.
Synopsis
typedef XtGeometryResult (*XtGeometryHandler)(Widget, XtWidgetGeometry
*,
XtWidgetGeometry *);
Widget w;
XtWidgetGeometry *request;
XtWidgetGeometry *geometry_return;
Inputs
w Specifies the child widget making the request.
request Specifies the requested geometry.
Outputs
geometry_return
Specifies the reply geometry.
Returns
The parent's reply: XtGeometryYes, XtGeometryNo, XtGeometryAlmost, or
XtGeometryDone.
Description
The geometry_manager() method is registered on the geometry_manager()
Composite class part field, and is called when a child widget requests
a new geometry or size with XtMakeGeometryRequest() or XtMakeResiz‐
eRequest(). The geometry_manager field must respond to the request by
approving it, rejecting it, or proposing a compromise.
The geometry_manager() method should examine the contents of the
request structure (see the "Structures" section below) and determine if
it can grant the request. request->request_mode contains flags which
specify which of the remaining fields of the structure the child cares
about.
If the widget can satisfy all the changes requested, it should return
XtGeometryYes. If the XtCWQueryOnly flag is not specified, then it
should update the specified widget's x, y, width, height, and bor‐
der_width fields appropriately before it returns. The Intrinsics will
take these new values and actually call XtConfigureWidget() to change
the widget's window as appropriate. Some composite widgets may find it
more convenient to call their internal layout procedure (if XtCWQuery‐
Only is not specified) from their geometry_manager() method and actu‐
ally configure the child themselves. In this case, they should return
XtGeometryDone instead of XtGeometryYes. See the warning about this
approach, however, in the "Background" section below. If the geome‐
try_manager() method returns XtGeometryYes or XtGeometryDone, it does
not need to return any values in the geometry_return argument.
If the geometry_manager() cannot grant the request (because it asks for
a position change when only size changes are allowed, for example) it
can return XtGeometryNo and the child will remain at its current size.
It may also return XtGeometryNo if the requested geometry is identical
to the current geometry. When it returns XtGeometryNo, it does not
need to return any values in the geometry_return argument.
If the geometry_manager() cannot satisfy the request exactly, but can
come close (for example, if it can change the height but not the width,
or can make the height larger but not as large as requested) it can
return XtGeometryAlmost, and set the compromise geometry in geome‐
try_return. By returning XtGeometryAlmost, it is guaranteeing that it
will return XtGeometryYes and make the change if the child requests the
compromise geometry immediately.
The geometry_manager() method is not chained. If a class does not
define its own geometry_manager() method, it can use XtInheritGeometry‐
Manager to inherit the method from its superclass. The geometry_man‐
ager field of a widget should not be NULL unless the widget class is
sure that none of its children will ever issue geometry requests.
See the "Background" section below for full details on this process.
See XtMakeGeometryRequest(1) for the child widget's perspective on
geometry negotiation.
Usage
A child will usually initiate a geometry request in response to a
change in one of its resources. When a Label widget gets a new string,
for example, it may need to grow to accommodate that label. If its
parent refuses to grant the resize request, the label may be truncated.
Note that the geometry_manager() method is not involved in the geometry
negotiations that percolate down from above when a window is resized or
when a widget is first managed.
In order to determine whether it can grant a geometry request, some
widgets will have to make a geometry request of their own to their par‐
ent, and the request may percolate up the chain. With XtCWQueryOnly
requests and XtGeometryAlmost replies, the geometry negotiation process
can become quite complicated. In practice, however, most widgets do
not perform geometry management nearly so sophisticated (and confusing)
as the mechanism allows.
Some composite widgets will have a resource that controls whether they
will allow any child to resize itself. If this resource disallows
geometry changes, the geometry manager will always return XtGeometryNo.
Constraint widgets can use constraint resources to provide this func‐
tionality on a child-by-child basis. Some widgets (the Xaw Label, for
example) have a resource that controls whether they will ever make a
resize request to their parent. All these mechanisms simplify the task
of the geometry manager procedure.
Some composite widgets will have a liberal policy towards geometry
requests. The Xaw Tree widget, for example, will allow any child's
resize request without actually testing whether it will have to become
larger and whether its parent will allow that. If the child's resize
request causes the Tree to request a resize, and the Tree is not
allowed to resize, then some of the children of the Tree will probably
not be displayed correctly. The philosophy here is that the applica‐
tion developer can take whatever steps are required to ensure that this
situation never arises.
The best approach to geometry management is probably to make do with
the simplest geometry_manager() method possible. The geometry manage‐
ment mechanism provided by the Intrinsics is so general (and so poorly
understood) that there are various incompatible styles of geometry man‐
agement that are supported. A geometry manager can be almost as com‐
plicated as you choose to make it, but most of the sophisticated situa‐
tions it is designed to handle will rarely occur in practice. Keep in
mind that many children widgets will not respond in any sophisticated
way to XtGeometryAlmost replies, and that the grandparent widget may
also not be sophisticated enough to provide useful return values to a
complex geometry manager.
Example
The procedure below is the geometry_manager() method Xaw Tree widget.
It is a permissive geometry manager which will allow resize requests,
but never position requests. It never returns XtGeometryAlmost. This
method may be a little too restrictive: if a programmer requests a
size and position change for a child in a single call to XtSetValues(),
XtSetValues() will call XtMakeGeometryRequest() for the child, but the
Tree widget will deny the size change request because it is accompanied
by the position change request.
The geometry manager for the Xaw Form widget is not shown here, but it
is worth looking at. It checks a constraint resource for each child to
determine if it is resizable. It also disallows position requests and
never returns XtGeometryAlmost.
The geometry manager for the Xaw Paned widget may also be worth some
study. It is a more sophisticated manager that does return XtGeome‐
tryAlmost sometimes. This is a more complex method because the Paned
widget constrains its children's widths to all be the same size.
/* ARGSUSED */
static XtGeometryResult GeometryManager (w, request, reply)
Widget w;
XtWidgetGeometry *request;
XtWidgetGeometry *reply;
{
TreeWidget tw = (TreeWidget) w->core.parent;
/*
* No position changes allowed!.
*/
if ((request->request_mode & CWX && request->x!=w->core.x)
(request->request_mode & CWY && request->y!=w->core.y))
return (XtGeometryNo);
/*
* Allow all resize requests.
*/
if (request->request_mode & CWWidth)
w->core.width = request->width;
if (request->request_mode & CWHeight)
w->core.height = request->height;
if (request->request_mode & CWBorderWidth)
w->core.border_width = request->border_width;
if (tw->tree.auto_reconfigure) layout_tree (tw, FALSE);
return (XtGeometryYes);
}
Background
A bit set to zero in the request request_mode field means that the
child widget does not care about the value of the corresponding field.
Then, the geometry manager can change it as it wishes. A bit set to 1
means that the child wants that geometry element changed to the value
in the corresponding field.
If the geometry manager can satisfy all changes requested, and if XtCW‐
QueryOnly is not specified, it updates the widget's x, y, width,
height, and border_width values appropriately. Then, it returns XtGe‐
ometryYes, and the value of the geometry_return argument is undefined.
The widget's window is moved and resized automatically by XtMakeGeome‐
tryRequest().
Homogeneous Composite widgets often find it convenient to treat the
widget making the request the same as any other widget, possibly recon‐
figuring it using XtConfigureWidget() or XtResizeWidget() as part of
its layout process, unless XtCWQueryOnly is specified. If it does
this, it should return XtGeometryDone to inform XtMakeGeometryRequest()
that it does not need to do the configuration itself.
To remain compatible with layout techniques used in older widgets
(before XtGeometryDone was added to the Intrinsics), a geometry manager
should avoid using XtResizeWidget() or XtConfigureWidget() on the child
making the request because the layout process of the child may be in an
intermediate state in which it is not prepared to handle a call to its
resize procedure. A self-contained widget set may choose this alterna‐
tive geometry management scheme, however, provided that it clearly
warns widget developers of the compatibility consequences.
Although XtMakeGeometryRequest() resizes the widget's window (if the
geometry manager returns XtGeometryYes), it does not call the widget
class's resize procedure. The requesting widget must perform whatever
resizing calculations are needed explicitly.
If the geometry manager chooses to disallow the request, the widget
cannot change its geometry. The value of the geometry_return argument
is undefined, and the geometry manager returns XtGeometryNo.
Sometimes the geometry manager cannot satisfy the request exactly, but
it may be able to satisfy a similar request. That is, it could satisfy
only a subset of the requests (for example, size but not position) or a
lesser request (for example, it cannot make the child as big as the
request but it can make the child bigger than its current size). In
such cases, the geometry manager fills in geometry_return with the
actual changes it is willing to make, including an appropriate mask,
and returns XtGeometryAlmost.
If a bit in geometry_return->request_mode is 0, the geometry manager
does not change the corresponding value if the geometry_return argument
is used immediately in a new request. If a bit is 1, the geometry man‐
ager does change that element to the corresponding value in geome‐
try_return. More bits may be set in geometry_return->request_mode than
in the original request if the geometry manager intends to change other
fields should the child accept the compromise.
When XtGeometryAlmost is returned, the widget must decide if the com‐
promise suggested in geometry_return is acceptable. If it is, the wid‐
get must not change its geometry directly; rather, it must make another
call to XtMakeGeometryRequest().
If the next geometry request from this child uses the geometry_return
box filled in by an XtGeometryAlmost return, and if there have been no
intervening geometry requests on either its parent or any of its other
children, the geometry manager must grant the request, if possible.
That is, if the child asks immediately with the returned geometry, it
should get an answer of XtGeometryYes. However, the user's window man‐
ager may affect the final outcome.
To return an XtGeometryYes, the geometry manager frequently rearranges
the position of other managed children by calling XtMoveWidget(). How‐
ever, a few geometry managers may sometimes change the size of other
managed children by calling XtResizeWidget() or XtConfigureWidget().
If XtCWQueryOnly is specified, the geometry manager must return how it
would react to this geometry request without actually moving or resiz‐
ing any widgets.
Geometry managers must not assume that the request and geometry_return
arguments point to independent storage. The caller is permitted to use
the same field for both, and the geometry manager must allocate its own
temporary storage, if necessary.
Sometimes a geometry manager cannot respond to a geometry request from
a child without first making a geometry request to the widget's own
parent (the original requestor's grandparent). If the request to the
grandparent would allow the parent to satisfy the original request, the
geometry manager can make the intermediate geometry request as if it
were the originator. On the other hand, if the geometry manager
already has determined that the original request cannot be completely
satisfied (for example, if it always denies position changes), it needs
to tell the grandparent to respond to the intermediate request without
actually changing the geometry because it does not know if the child
will accept the compromise. To accomplish this, the geometry manager
uses XtCWQueryOnly in the intermediate request.
When XtCWQueryOnly is used, the geometry manager needs to cache enough
information to exactly reconstruct the intermediate request. If the
grandparent's response to the intermediate query was XtGeometryAlmost,
the geometry manager needs to cache the entire reply geometry in the
event the child accepts the parent's compromise.
If the grandparent's response was XtGeometryAlmost, it may also be nec‐
essary to cache the entire reply geometry from the grandparent when
XtCWQueryOnly is not used. If the geometry manager is still able to
satisfy the original request, it may immediately accept the grandpar‐
ent's compromise and then act on the child's request. If the grandpar‐
ent's compromise geometry is insufficient to allow the child's request
and if the geometry manager is willing to offer a different compromise
to the child, the grandparent's compromise should not be accepted until
the child has accepted the new compromise.
Note that a compromise geometry returned with XtGeometryAlmost is guar‐
anteed only for the next call to the same widget; therefore, a cache of
size 1 is sufficient.
Structures
The return codes from geometry managers are:
typedef enum _XtGeometryResult {
XtGeometryYes, /* Request accepted */
XtGeometryNo, /* Request denied */
XtGeometryAlmost,/* Request denied but willing to take reply */
XtGeometryDone /* Request accepted and performed */
} XtGeometryResult;
The XtWidgetGeometry structure is similar to but not identical to the
corresponding Xlib structure:
typedef unsigned long XtGeometryMask;
typedef struct {
XtGeometryMask request_mode;
Position x, y;
Dimension width, height;
Dimension border_width;
Widget sibling;
int stack_mode;
} XtWidgetGeometry;
XtMakeGeometryRequest(), like the Xlib XConfigureWindow() function,
uses request_mode to determine which fields in the XtWidgetGeometry
structure you want to specify. The request_mode definitions are from
<X11/X.h>:
#define CWX(1<<0)
#define CWY(1<<1)
#define CWWidth(1<<2)
#define CWHeight(1<<3)
#define CWBorderWidth(1<<4)
#define CWSibling(1<<5)
#define CWStackMode(1<<6)
The Xt Intrinsics also support the following value:
#define XtCWQueryOnly (1<<7)
XtCWQueryOnly indicates that the corresponding geometry request is only
a query as to what would happen if this geometry request were made and
that no widgets should actually be changed.
The stack_mode definitions are from <X11/X.h>:
#define Above0
#define Below1
#define TopIf2
#define BottomIf3
#define Opposite4
The Intrinsics also support the following value:
#define XtSMDontChange5
XtSMDontChange indicates that the widget wants its current stacking
order preserved. For precise definitions of Above, Below, TopIf, Bot‐
tomIf, and Opposite, see the reference page for XConfigureWindow() in
Volume Two, Xlib Reference Manual.
See AlsoXtConfigureWidget(1), XtMakeResizeRequest(1), XtMoveWidget(1), XtRe‐
sizeWidget(1),
Composite(3), Constraint(3).
Xt - Intrinsics Methods geometry_manager()