Query: geometry_manager
OS: hpux
Section: 3
Format: Original Unix Latex Style Formatted with HTML and a Horizontal Scroll Bar
geometry_manager() geometry_manager() Name geometry_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 XtMakeResizeRequest(). 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 border_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 XtCWQueryOnly is not specified) from their geometry_manager() method and actually 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 geometry_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 geometry_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_manager 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 functionality 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 prob- ably not be displayed correctly. The philosophy here is that the application 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 management that are supported. A geometry manager can be almost as complicated as you choose to make it, but most of the sophisticated situations it is designed to handle will rarely occur in practice. Keep in mind that many children widgets will not respond in any sophis- ticated way to XtGeometryAlmost replies, and that the grandparent widget may also not be sophisticated enough to provide useful return val- ues 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 XtCWQueryOnly is not specified, it updates the widget's x, y, width, height, and border_width values appropriately. Then, it returns XtGeometryYes, and the value of the geometry_return argument is undefined. The widget's window is moved and resized automatically by XtMakeGeometryRequest(). 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 alternative 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 sat- isfy 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 argu- ment is used immediately in a new request. If a bit is 1, the geometry manager does change that element to the corresponding value in geometry_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 compromise 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 possi- ble. That is, if the child asks immediately with the returned geometry, it should get an answer of XtGeometryYes. However, the user's window manager may affect the final outcome. To return an XtGeometryYes, the geometry manager frequently rearranges the position of other managed children by calling XtMoveWidget(). However, a few geometry managers may sometimes change the size of other managed children by calling XtResizeWidget() or XtConfigureWid- get(). If XtCWQueryOnly is specified, the geometry manager must return how it would react to this geometry request without actually moving or resizing 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 necessary 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 grandparent'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 guaranteed 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 Also XtConfigureWidget(1), XtMakeResizeRequest(1), XtMoveWidget(1), XtResizeWidget(1), Composite(3), Constraint(3). Xt - Intrinsics Methods geometry_manager()