[ Previous | Next | Contents | Glossary | Home | Search ]
Motif 2.1 Widget Writer's Guide



The Parent's geometry_manager Method

A managed child widget can make a geometry request of a realized parent by calling XtMakeGeometryRequest. The Intrinsics automatically call XtMakeGeometryRequest on a parent when an application changes a geometry resource of one of its children. Any call to XtMakeGeometryRequest automatically invokes the parent's geometry_manager method. The arguments of the geometry_manager method are the same as those to XtMakeGeometryRequest.

The child passes the specifics of its geometry request inside the second argument to XtMakeGeometryRequest. The geometry_manager method must respond to this geometry request in one of the following three ways:

  1. Grant the child's request by returning XtGeometryYes.

  2. Deny the child's request by returning XtGeometryNo.

  3. Suggest a compromise to the child by returning XtGeometryAlmost.

    If the geometry_manager method can grant the request, the geometry_manager method must do the following:

    1. Update the appropriate geometry resources of the child.

    2. Return XtGeometryYes.

      If geometry_manager returns XtGeometryYes, then XtMakeGeometryRequest will take care of changing the geometry of the child's window. (In other words, the geometry_manager method does not have to do it.) The child is responsible for calling its own resize method to handle the new size.

      The geometry_manager methods for all standard Motif widgets return XtGeometryYes, not XtGeometryDone. All geometry_manager methods of widgets that you write should return XtGeometryYes.

      The geometry_manager method may be able to satisfy some, but not all, of a child's request . For example, it may be able to grant the requested width, but not the requested height. In this case, the geometry_manager method may offer the child a compromise geometry. It fills in the reply XtWidgetGeometry structure with the parameters it intends to allow, and it sets the corresponding bit in the reply bitmask for any parameter it intends to change from the value requested. If the child immediately makes another geometry request by using the compromise parameters, the geometry_manager method must grant the request.

      Following is the first part of the GeometryManager method of the ExmGrid demonstration widget:

      static XtGeometryResult
      GeometryManager (
              Widget w,  /* instigator */
              XtWidgetGeometry *request,
              XtWidgetGeometry *reply
      )
      {
       ExmGridWidget gw = (ExmGridWidget) XtParent(w);
       XtWidgetGeometry parentRequest;
       XtGeometryResult result;
       Dimension curWidth, curHeight, curBW;
       ExmGridWidgetClass gwc = (ExmGridWidgetClass) XtClass((Widget)gw);
       
        /* If the request was caused by ConstraintSetValues reset the flag */
          if (gw->grid.processing_constraints) {
            gw->grid.processing_constraints = False;
              /* The ConstraintSetValues added one to border_width;
                 This is the Xt trick used to fire the GM when a non core
                 geometry resource (like a constraint) changes.
                 now take it away. */
              request->border_width -= 1;
          }
       
        /* Save the original child resources. */
          curWidth = w->core.width;
          curHeight = w->core.height;
          curBW = w->core.border_width;
       
        /* Deny any requests for a new position. */
          if ((request->request_mode & CWX) || (request->request_mode
      & CWY))
              return XtGeometryNo;
       
         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;
       
        /* Calculate a new ideal size based on these requests. */
        /* Setting width and height to 0 tells CalcSize to override these
           fields with the calculated width and height. */
          parentRequest.width = 0;
          parentRequest.height = 0;
          if (gwc->grid_class.calc_size)
              (*(gwc->grid_class.calc_size))((Widget)gw, w,
                                             &parentRequest.width,
                                             &parentRequest.height);
          else
              CalcSize ((Widget)gw, w, &parentRequest.width,
      &parentRequest.height);

      Often a parent widget must change its own geometry in order to satisfy a child's request. The parent's geometry_manager method uses XtMakeGeometryRequest to ask its own parent for a geometry change. If an XtMakeGeometryRequest request to the grandparent returns XtGeometryYes, the geometry_manager method of the grandparent must update the requesting parent's geometry fields and may resize other child, but it should not call the requesting parent's resize method. The parent may call its own resize method as long as that routine does not call the requesting child's resize method. The parent's geometry_manager method then returns XtGeometryYes.

      Sometimes the parent needs to make a geometry request to its own parent just to find out whether the grandparent will accept a proposed change. For example, the parent may intend to offer a compromise geometry to the child but it must first determine whether the grandparent will allow the parent to change its own geometry in order to offer the compromise. In this case, the parent does not want the grandparent actually to make the proposed change; it just wants the grandparent to tell the parent whether the change is acceptable.

      In making its own geometry request to the grandparent, the parent sets the XtCWQueryOnly bit in the request bitmask. The grandparent can return XtGeometryYes, but it must not actually change any of its children. The parent then returns XtGeometryAlmost to the child, along with its compromise parameters. If the child accepts the compromise, the parent repeats its request to the grandparent without setting XtCWQueryOnly. The grandparent should grant the parent's request, and the parent can then grant the child's request.

      If the grandparent's response is XtGeometryAlmost and the parent still wishes to offer a compromise to the child, it caches the grandparent's reply and returns XtGeometryAlmost to the child. If the child accepts this compromise, the parent then makes another request of the grandparent, using the cached compromise parameters from the grandparent and without setting XtCWQueryOnly . The grandparent should grant the parent's request, and the parent can then grant the child's request.

      The following code forms the second half of the GeometryManager method of ExmGrid:

        /* Ask the Grid's parent if new calculated size is acceptable. */
          parentRequest.request_mode = CWWidth | CWHeight;
          if (request->request_mode & XtCWQueryOnly)
              parentRequest.request_mode |= XtCWQueryOnly;
          result = XtMakeGeometryRequest ((Widget)gw, &parentRequest,
      NULL);
       
        /*  Turn XtGeometryAlmost into XtGeometryNo. */
          if (result == XtGeometryAlmost)
            result = XtGeometryNo;
       
          if (result == XtGeometryNo ||
              request->request_mode & XtCWQueryOnly) {
              /* Restore original geometry. */
              w->core.width = curWidth;
              w->core.height = curHeight;
              w->core.border_width = curBW;
         } else {
             /* result == XtGeometryYes and this wasn't just a query */
             if (gwc->grid_class.layout)
                 (*(gwc->grid_class.layout))((Widget)gw, w);
             else
                 Layout ((Widget)gw, w); /* Layout with this child as the
      instigator,
                                            so that we don't resize this
      child. */
         }
       
         return (result);
      }

    3. [ Previous | Next | Contents | Glossary | Home | Search ]