Query: expose
OS: hpux
Section: 4
Format: Original Unix Latex Style Formatted with HTML and a Horizontal Scroll Bar
expose() expose() Name expose - Core class method that draws a widget's graphics. Synopsis typedef void (*XtExposeProc)(Widget, XEvent *, Region); Widget w; XEvent *event; Region region; Inputs w Specifies the widget instance requiring redisplay. event Specifies the exposure event giving the rectangle requiring redisplay. region Specifies the union of all rectangles in this exposure sequence. Description The expose() method is installed on the expose field of the Core class part structure, and is called to draw or redraw the widget's window when exposure events arrive for that window. An expose() method may also be registered on the expose field of the RectObj class part structure, but because RectObj widgets do not have windows, this method will not be called by the Intrinsics. (Although some composite widgets may call the expose() methods of their non-widget children.) The w argument is the widget for which exposure events have arrived. event is the exposure event, or the latest in a series of exposure events, if the widget uses exposure compression. It contains a bounding box of the exposed area. region is NULL if there is no exposure compression, or specifies the union of all exposure events in the compressed sequence. The expose() method must redraw at least the graph- ics within the bounding box of the event. Simple widgets may simply redraw their entire window; more complicated widgets may attempt to minimize the amount of redraw required by using the region argument. Exposure compression is specified with the compress_exposure field in the Core class part structure. See the "Background" section below for details. A widget need not redisplay itself if it is not visible. A widget can obtain a hint about whether it is currently visible by checking the visible field in the Core instance structure. If visible_interest in the Core class structure is True, then the visible field is usually False if no part of the widget is currently visible. See the "Background" section for details. The expose() method is not chained. A widget class can inherit the expose() method of its superclass by specifying XtInheritExpose on the expose field of its RectObj or Core class part structure. A widget that does not display any graphics (such as many composite widgets) can set this field to NULL. The long "Usage" section below explains some common strategies to handling expose events on a widget. Usage The expose() method is responsible for initially drawing into a widget's window and for redrawing the window every time a part of the win- dow 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. Most widgets keep track of what they draw in some form of arrays or display lists. This could be an array of lines of text to be drawn, for example, or an array of lines which can be drawn with a single call to XDrawLines(). When a widget of this sort needs to redisplay itself, it simply calls the procedure that draws the widget based on the saved data. The graphic contents of a widget often change in response to user events handled with action procedures or event handlers. These proce- dures usually draw into the widget directly, but must also store the appropriate data so that the current state of the widget can be regen- erated, if necessary. An expose() method can be made more efficient if as much data as possible is pre-computed. A label widget that draws its text centered in its window, for example, should pre-compute the x and y coordinates at which the text will be drawn. If it does not, the expose method will have to compute the position based on the height of the font, the width of the string (which is time consuming to compute), and the size of the window. These pre-computed positions should only need to be updated in the resize() and set_values() methods. Simple widgets may just redisplay their entire window when the expose event is called. More complicated widgets may redisplay everything within the bounding box of the event (which will be the same as the bounding box of the specified Region if it is non-NULL). For widgets that are very time-consuming for the client or server to redraw, you might want to use this region in a more sophisticated way. You can use this region as a clip mask in your GC (see XSetRegion()) to clip output to the exposed region, and possibly calculate which drawing primitives affect this area. Xlib also provides region mathematics routines (such as XRectInRegion()) so that you can compare the regions in which your widget needs to draw graphics with the region that was exposed. If certain areas do not require redrawing, you can skip the code that redraws them. If you plan to write a sophisticated expose() method, bear in mind that the calculations required to optimize the redisplay are time consuming, too, and too much clipping and testing of rectangles may slow down your widget. The cost/benefit ratio should be examined. Some widgets do not bother to remember how to redraw themselves. Instead they draw their graphics into a pixmap and copy the contents of the pixmap into their window as needed. For some widgets this approach is much simpler than retaining the state needed to redraw from scratch. If the widget is very large, however, the pixmap will take up a lot of memory in the X server. A widget that is insensitive (see XtSetSensitive(1)) may wish to indicate this to the user by drawing itself in a different way. A common approach is to draw with a GC with a stipple to so that everything appears "grayed-out." A composite widget that accepts non-widget children which are subclasses of RectObj ("gadgets") will have to display the graphics of those children in its own window. It may narrowly define the types of children it will accept to be the type of children that it knows how to draw. Or instead it may require that its RectObj children have their own expose() methods and call those methods when it detects that the region of the window occupied by a child needs to be redrawn. 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 NorthWest- Gravity before it calls the widget's realize() method. Example The following procedure is the expose() method of the Xaw Label widget with code for handling the left bitmap and multi-line string removed. Note that it first tests that the exposed region intersects the region that the label string or pixmap occupies. It also has commented-out code that sets the region as the clipmask of the GC. For such a simple redisplay, doing the clipping may have taken more time than simply drawing the text of pixmap. This method does not test the visible field, and the widget class has its visible_interest field set to False. Finally, note that if the widget is insensitive, it uses a special GC to draw itself "grayed-out." /* ARGSUSED */ static void Redisplay(w, event, region) Widget w; XEvent *event; Region region; { LabelWidget lw = (LabelWidget) w; GC gc; if (region != NULL) { int x = lw->label.label_x; unsigned int width = lw->label.label_width; if (lw->label.lbm_width) { if (lw->label.label_x > (x = lw->label.internal_width)) width += lw->label.label_x - x; } if (XRectInRegion(region, x, lw->label.label_y, width, lw->label.label_height) == RectangleOut) return; } gc = XtIsSensitive((Widget)lw) ? lw->label.normal_GC : lw->label.gray_GC; #ifdef notdef if (region != NULL) XSetRegion(XtDisplay(w), gc, region); #endif /*notdef*/ if (lw->label.pixmap == None) { int len = lw->label.label_len; char *label = lw->label.label; Position y = lw->label.label_y + lw->label.font->max_bounds.ascent; if (len) { if (lw->label.encoding) XDrawString16(XtDisplay(w), XtWindow(w), gc, lw->label.label_x, y, (TXT16*)label, len/2); else XDrawString(XtDisplay(w), XtWindow(w), gc, lw->label.label_x, y, label, len); } } else if (lw->label.label_len == 1) { /* depth */ XCopyPlane(XtDisplay(w), lw->label.pixmap, XtWindow(w), gc, 0, 0, lw->label.label_width, lw->label.label_height, lw->label.label_x, lw->label.label_y, 1L); } else { XCopyArea(XtDisplay(w), lw->label.pixmap, XtWindow(w), gc, 0, 0, lw->label.label_width, lw->label.label_height, lw->label.label_x, lw->label.label_y); } #ifdef notdef if (region != NULL) XSetClipMask(XtDisplay(w), gc, (Pixmap)None); #endif /* notdef */ } Background Many widgets prefer to process a series of exposure events as a single expose region rather than as individual rectangles. Widgets with complex displays might use the expose region as a clip list in a graphics context, and widgets with simple displays might ignore the region entirely and redisplay their whole window or might get the bounding box from the region and redisplay only that rectangle. In either case, these widgets want some kind of exposure compression. The compress_exposure field in the widget class structure specifies the type and number of exposure events that will be dispatched to the widget's expose procedure. This field must be set to XtExposeNoCom- press, XtExposeCompressSeries, XtExposeCompressMultiple, or XtExposeCompressMaximal, optionally ORed with any combination of the XtExposeG- raphicsExpose, XtExposeGraphicsExposeMerged, and XtExposeNoExpose flags. (Specifying False for the compress_exposure field is equivalent to XtExposeNoCompress with no flags and specifying True is equivalent to XtExposeCompressSeries with no flags.) If the compress_exposure field in the widget class structure does not specify XtExposeNoCompress, the event manager calls the widget's expose procedure only once for a series of exposure events. In this case, all Expose or GraphicsExpose events are accumulated into a region. When the final event is received, the event manager replaces the rectangle in the event with the bounding box for the region and calls the widget's expose() method, passing the modified exposure event and the region. The different types of exposure compression are as follows: XtExposeNoCompress No exposure compression is performed; every selected event is individually dispatched to the expose procedure with a region argument of NULL. XtExposeCompressSeries Each series of exposure events is coalesced into a single event, which is dispatched when an exposure event with count equal to zero is reached. XtExposeCompressMultiple Consecutive series of exposure events are coalesced into a single event, which is dispatched when an exposure event with count equal to zero is reached and either the event queue is empty or the next event is not an exposure event for the same widget. XtExposeCompressMaximal All expose series currently in the queue for the widget are coalesced into a single event without regard to intervening non-exposure events. If a partial series is in the end of the queue, the Intrinsics will block until the end of the series is received. The optional flags have the following meanings: XtExposeGraphicsExpose Specifies that GraphicsExpose events are also to be dispatched to the expose procedure. GraphicsExpose events will be compressed, if specified, in the same manner as Expose events. XtExposeGraphicsExposeMerged Specifies in the case of XtExposeCompressMultiple and XtExposeCompressMaximal that a series of GraphicsExpose and Expose events are to be compressed together, with the final event type determining the type of the event passed to the expose procedure. If this flag is not set, then only series of the same event type as the event at the head of the queue are coalesced. This flag also implies XtEx- poseGraphicsExpose. XtExposeNoExpose Specifies that NoExpose events are also to be dispatched to the expose procedure. NoExpose events are never coalesced with other exposure events or with each other. 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 any part of the widget is visible, the visible field is guar- anteed 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 this case, the visible field is initialized to True and never changes. If visible_interest is True, however, the event manager asks for VisibilityNotify events for the widget and updates the visible field accordingly. Structures Region is an opaque type defined by Xlib. See Also Core(3). Xt - Intrinsics Methods expose()