Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ expose(3) — OSF1 1.0

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

Core(3)

 

Name

expose — Core method for drawing graphics. 

Synopsis

typedef void (∗XtExposeProc)(Widget, XEvent ∗, Region);

    Widget w;
    XEvent ∗event;
    Region region;

Arguments

wSpecifies the widget instance requiring redisplay. 

eventSpecifies the exposure event giving the rectangle requiring redisplay. 

regionSpecifies the union of all rectangles in this exposure sequence. 

Description

The expose method is responsible for initially drawing into a widget’s window and for redrawing the window every time a part of the window becomes exposed.  This redrawing is necessary because the X server does not normally maintain the contents of windows when they are obscured.  When a window becomes visible again, it must be redrawn. 

The expose method usually needs to modify its drawing based on the geometry of the window and other instance variables set in other methods.  For example, the Label widget will left-justify, center, or right-justify its text according to the XtNjustify resource, and the actual position to draw the text depends on the widget’s current size. 

Another factor to consider when writing the expose method is that many widgets also draw from action routines, in response to user events.  For example, BitmapEdit (described in Volume Four, X Toolkit Intrinsics Programming Manual) toggles bitmap cells in action routines.  The expose method must be capable of redrawing the current state of the widget at any time.  This means that action routines usually set instance variables when they draw so that the expose method can read these instance variables and draw the right thing.  Usually, actions that draw either share drawing code with the expose method or invoke the expose method directly. 

Most widgets keep track of what they draw in some form of arrays or display lists.  When they need to redraw, they simply replay the saved drawing commands in the original order to redraw the window.  For example, BitmapEdit keeps track of the state of each bitmap cell in a character array.  It could easily traverse this array and redraw each cell that is set in the array. 

However, BitmapEdit does not use this strategy.  To improve its scrolling performance, the expose method copies an off-screen pixmap into the window whenever redisplay is required.  The actions draw into this off-screen pixmap and then call the expose method directly to have the pixmap copied to the window.  This strategy is fast, but it uses up a relatively large amount of server memory. 

The expose method is passed an event that contains the bounding box of the area exposed.  You should copy only this area from the pixmap to the window.  The BitmapEdit widget takes advantage of this, too.  It manufactures an artificial event containing the bounding box of the cell to be toggled, and it passes this event when it calls expose.  This causes the expose method to copy only the one just-updated cell to the window. 

The example below shows the expose method from the BitmapEdit widget. 

/∗ ARGSUSED ∗/
static void
Redisplay(cw, event)
BitmapEditWidget cw;
XExposeEvent ∗event;
{
    register int x, y;
    unsigned int width, height;
    if (!XtIsRealized(cw))
    return;
     if (event) {  /∗ called from btn-event ∗/
        x = event->x;
        y = event->y;
        width = event->width;
        height =  event->height;
    }
    else {        /∗ called because of expose ∗/
        x = 0;
        y = 0;
        width = cw->bitmapEdit.pixmap_width_in_pixels;
        height = cw->bitmapEdit.pixmap_height_in_pixels;
    }
     if (DefaultDepthOfScreen(XtScreen(cw)) == 1)
XCopyArea(XtDisplay(cw), cw->bitmapEdit.big_picture,
            XtWindow(cw),
            cw->bitmapEdit.copy_gc, x + cw->bitmapEdit.cur_x, y +
       cw->bitmapEdit.cur_y, width, height, x, y);
    else
XCopyPlane(XtDisplay(cw), cw->bitmapEdit.big_picture,
            XtWindow(cw),
            cw->bitmapEdit.copy_gc, x + cw->bitmapEdit.cur_x, y +
            cw->bitmapEdit.cur_y, width, height, x, y, 1);
 }

Note that the expose method first checks to see that the widget is realized using XtIsRealized.  This is a precaution against the unlikely event that an instance of this widget is suddenly destroyed or unrealized by an application while Expose events are still pending.  If this did happen, drawing on the nonexistent window would cause an X protocol error. 

Next, BitmapEdit’s expose method sets the rectangle it will redraw based on the event passed in by Xt. 

If the compress_exposure field of the class structure is initialized to XtExposeCompressMultiple, as it is in BitmapEdit, then Xt automatically merges the multiple contiguous Expose events that may occur because of one or more user actions into one Expose event.  In this case, the Expose event contains the bounding box of the areas exposed.  BitmapEdit redraws everything in this bounding box. 

If the widget’s compress_exposure class field specifies XtExposeNoCompress, or if the event type is NoExpose, then region is NULL; otherwise, the event is the final event in the compressed series, but x, y, width and height then contain the bounding box for region.  There are numerous flags for the compress_exposure field.  For more information, see Chapter 5, Inside a Widget, in Volume Four, X Toolkit Intrinsics Programming Manual. 

For widgets that are very time-consuming for the client or server to redraw, you might want to use the third  argument of the expose method, which is a region.  The Region type is opaquely defined by Xlib (internally a linked list of rectangles).  The Region passed into expose describes the union of all the areas exposed by a user action.  You can use this region to clip output to the exposed region (using XSetRegion to set the GC), and possibly calculate which drawing primitives affect this area.  Xlib provides region mathematics routines (such as XRectInRegion) to compare the regions in which your widget needs to draw with the region needing redrawing.  If certain areas do not require redrawing, you can skip the code that redraws them, thereby saving valuable time.  However, if this calculation is complicated, its cost/benefit ratio should be examined. 

Each of these exposure handling techniques may be the best for certain widgets.  For a complete description of Expose event handling strategies, see Chapter 8, Events, in Volume One, Xlib Programming Manual. 

The remainder of BitmapEdit’s expose method shown in the example above consists of a single Xlib call to copy from the backup pixmap into the widget’s window.  Note that one of two Xlib routines is called based on the depth of the screen.  This is because XCopyArea is slightly more efficient than XCopyPlane and should be used when drawing on a monochrome screen. 

Note that instance variables are used for the arguments of the Xlib routines in the example above.  See the reference page for each routine in Volume Two, Xlib Reference Manual, when you need to call them in your code. 

See Chapters 5, 6, and 7 in Volume One, Xlib Programming Manual, for more information on the GC, drawing graphics, and color, respectively. 

If a widget has no display semantics, it can specify NULL for the expose field.  Many composite widgets serve only as containers for their children and have no expose method.  If the expose method is NULL, XtRealizeWidget fills in a default bit gravity of NorthWestGravity before it calls the widget’s realize method. 

Sometimes it is possible to anticipate the display needs of several levels of subclasses.  For example, rather than maintaining separate expose methods for the widgets Command, Label, and Toggle, they share a single redisplay routine.  Doing this, however, requires the top superclass to foresee the needs of all the subclasses.  The Label widget’s expose method has parameters that it doesn’t use, but that Command and Toggle use when they inherit the expose method from Label. 

Some widgets use substantial computing resources to display data.  However, this effort is wasted if the widget is not actually visible on the screen (e.g., when the widget is obscured by another application or is iconified).  The visible field in the Core widget instance structure provides the widget with a hint that it need not display data.  If the widget is visible, the visible field is guaranteed to be True by the time an Expose event is processed; if the widget is not visible, this field is usually False. 

Widgets can either use or ignore the visible hint.  If they ignore it, the visible_interest field in their widget class record should be set to False.  In such cases, the visible field is initialized to True and never changes, but if visible_interest is True, the event manager asks for VisibilityNotify events for the widget and updates the visible field accordingly. 

Structures

The definition of a Region is given in <X11/Xutil.h>.  Region is an opaque type defined by Xlib.  A Region is a linked list of rectangles. 

See Also

Core(3)

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026