In the first form of the repaint procedure, the only other parameter is the repaint_area.
This is a linked list of rectangular areas in the paint window that have been exposed and need
to be repainted. The Rectlist type is a linked list of Rect’s as shown in <xview/rect.h>.
The declaration for the Rect type is:
typedef struct rect {
coord r_left, r_top;
short r_width, r_height;
} Rect;
The type coord is #define’d as type short. The Rectlist is declared in
<xview/rectlist.h> as:
typedef struct rectnode {
struct rectnode *rn_next; /* Pointer to next rectnode */
struct rect rn_rect;
} Rectnode;
typedef struct rectlist {
coord rl_x, rl_y; /* Offset to apply to each rect
* in list including bound */
struct rectnode *rl_head; /* Pointer to first rectnode */
struct rectnode *rl_tail; /* Pointer to last rectnode */
struct rect rl_bound; /* Describes bounding rect of
* all rects in list */
} Rectlist;
The repaint_area parameter is of type Rectlist, so the application has several ways it
can approach repainting the window. It could just ignore the parameter and repaint the entire
window, or it could repaint the entire area described by the rl_bound field of the
rectlist structure or it could loop through all the Rectnode’s and repaint those areas
individually. Deciding which method to choose should be based on how complicated the
redrawing is.
When CANVAS_X_PAINT_WINDOW is set to FALSE, the internal clipping for the paint window
is set to be the same region or regions described by the repaint parameter of the repaint rou-
tine. In most cases, this means that OPENWIN_AUTO_CLEAR will only clear those areas—not
the entire window.* The default behavior may be overridden by setting WIN_NO_
CLIPPING to TRUE for the canvas. Setting this attribute cycles through all the paint win-
dows in the canvas and sets the window property
WIN_NO_CLIPPING. Having the clipping
on the window turned off means that OPENWIN_AUTO_CLEAR will cause the entire window to
be cleared.†
By setting the attribute CANVAS_X_PAINT_WINDOW to TRUE, the repaint routine gets passed
the extra X-specific parameters as shown in the second form of the repaint procedure. These
extra parameters include handles to the Display and the X window of the paint_
window.
*For those using the SunView-compatible drawing routines such as pw_vector(), rendering is clipped to the area
or areas described by repaint_area.
†This also affects the SunView-compatible routines—pw_vector() will not be clipped.
Canvases and
Openwin
Canvases and Openwin 95
Example 5-1 shows how a repaint procedure might be used.
Example 5-1. The line.c program
/*
* line.c -- demonstrates installing a repaint routine in a canvas.
* The routine is called whenever the canvas needs to be repainted.
* This usually occurs when the canvas is exposed or resized.
*/
#include <X11/Xlib.h>
#include <xview/xview.h>
#include <xview/canvas.h>
#include <xview/xv_xrect.h>
main(argc, argv)
int argc;
char *argv[ ];
{
Frame frame;
void canvas_repaint_proc();
xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
frame = (Frame)xv_create(NULL, FRAME, NULL);
(void) xv_create(frame, CANVAS,
CANVAS_REPAINT_PROC, canvas_repaint_proc,
CANVAS_X_PAINT_WINDOW, TRUE,
NULL);
xv_main_loop(frame);
}
/*
* repaint routine draws a line from the top left to the bottom right
* corners of the window
*/
void
canvas_repaint_proc(canvas, paint_window, dpy, xwin, xrects)
Canvas canvas; /* unused */
Xv_Window paint_window; /* unused */
Display *dpy;
Window xwin;
Xv_xrectlist *xrects; /* unused */
{
GC gc;
int width, height;
gc = DefaultGC(dpy, DefaultScreen(dpy));
width = (int)xv_get(paint_window, XV_WIDTH);
height = (int)xv_get(paint_window, XV_HEIGHT);
XDrawLine(dpy, xwin, gc, 0, 0, width, height);
}
96 XView Programming Manual
Because the program uses Xlib calls (and thus, the repaint routine is being passed different
parameters), the header files <X11/Xlib.h> and <xview/xv_xrect.h> must be added at the top
of the program. The parameters dpy and xwin are handles to the X Display and the X
Window, respectively. The GC (graphics context) is taken from the default GC of the screen.
The xrects parameter represents the exposed, or “damaged,” region of the paint window.
The Xv_xrectlist is declared in <xview/xv_xrect.h> as:
#define XV_MAX_XRECTS 32
typedef struct {
XRectangle rect_array[MAX_XRECTS];
int count;
} Xv_xrectlist;
When the canvas is first displayed, this region will be the entire paint window (or the portion
that is viewable by the view window). But in cases where another window that has partially
obscured it moves away, perhaps only a portion of the paint window will need repainting.
Therefore, the xrects variable can aid in setting the clip rectangles in the GC, as shown in
Example 5-2.
Example 5-2. Repainting objects within a damaged region
/* canvas_repaint_proc()
*
* Draws onto the canvas using Xlib drawing functions.
*
* Uses the current clipping rectangle to:
* 1. Restrict graphics output by setting the
* clip_mask in the graphics context.
* 2. Do "smart repainting" by only painting the objects
* that lie within the damaged region (not being done
* in this example).
*/
void
repaint_proc(canvas, paint_window, display, xid, xrects)
Canvas canvas;
Xv_Window paint_window;
Display *display;
Window xwin;
Xv_xrectlist *xrects;
{
extern GC gc;
int width, height;
width = (int)xv_get(paint_window, XV_WIDTH);
height = (int)xv_get(paint_window, XV_HEIGHT);
/*
* Set clip rects, if any
*/
if (xrects)
XSetClipRectangles(display, gc, 0, 0, xrects->rect_array,
xrects->count, Unsorted);
else {
XGCValues gc_val;
gc_val.clip_mask = None;
Canvases and
Openwin
Canvases and Openwin 97
Example 5-2. Repainting objects within a damaged region (continued)
XChangeGC(display, gc, GCClipMask, &gc_val);
}
XDrawLine(display, xwin, gc, 0, 0, width, height);
}
Because this routine sets the clip mask of the GC, we want to be sure that we do not use the
default GC of the screen as we did in Example 5-2 or it will interfere with other programs
(such as the window manager). The GC shown here is declared as extern, assuming that
the application has created it somewhere else using XCreateGC().
5.4 Controlling Canvas Sizes
The size of the canvas subwindow is usually determined by the frame window. Thus, the
canvas changes as the user resizes the frame. Applications largely concern themselves with
the size of the paint window.* The paint window does not affect the size of the viewable
canvas, but the viewable portion of the paint window is important.
Although the width and height of the canvas subwindow can be set explicitly, unless done so,
the default size of the subwindow and the paint window is determined by the parent frame. If
the frame resizes, the canvas object resizes proportionally according to how the frame
chooses to resize the canvas. If several other windows (canvases, panels, whatever) are in
the frame, the frame might choose to lay out and size those subwindows differently (accord-
ing to available and required space from other windows). The canvas window itself, as well
as all window objects, can be sized using
XV_WIDTH and XV_HEIGHT.
5.4.1 Automatic Canvas Sizing
The paint window’s size may fluctuate with that of the canvas subwindow’s size. The attri-
butes CANVAS_AUTO_EXPAND and CANVAS_AUTO_SHRINK maintain the relation of the canvas
subwindow and paint window in the event of any kind of window resizing. Both of these
attributes default to TRUE, allowing the paint window to always correspond to the size of the
canvas subwindow. If the canvas subwindow becomes larger, the paint window size changes
to that size. If the frame changes size, the canvas subwindow changes size and so does the
paint window. This happens regardless of how many view windows there are. The size of
view windows does not affect the size of the paint window.
Specifically, if
CANVAS_AUTO_EXPAND is TRUE, then the width and height of the paint win-
dow cannot be less than that of the canvas subwindow. Setting the attribute
CANVAS_AUTO_EXPAND allows the paint window to grow bigger as the user stretches the win-
dow. If a resize of the subwindow occurs such that the size of the paint window is less than
the size of the canvas subwindow, the paint window is expanded to be at least that size.
*There may be more than one paint window to a canvas; but all paint windows in a canvas are the same size, so it’s a
moot point.
98 XView Programming Manual
Conversely, if the canvas subwindow’s size shrinks, then the paint canvas size does not
change because its size is already greater than or equal to the size of the canvas subwin-
dow—no expansion is necessary.
If CANVAS_AUTO_SHRINK is TRUE, the canvas object checks that width and height of the paint
window are not greater than that of the canvas subwindow. Setting CANVAS_AUTO_SHRINK
forces the paint window to grow smaller as the size of the canvas subwindow gets smaller. If
the user resizes the frame such that the canvas subwindow is smaller than the size of the paint
window, then the paint window is reduced to the size of the new subwindow.
You can also set a minimum width and height for the canvas using the attributes
CANVAS_MIN_PAINT_WIDTH and CANVAS_MIN_PAINT_HEIGHT. Regardless of whether or
not CANVAS_AUTO_SHRINK is set to TRUE or FALSE, the attributes CANVAS_MIN_
PAINT_WIDTH
and CANVAS_MIN_PAINT_HEIGHT impose the minimum CANVAS_
WIDTH
and CANVAS_HEIGHT respectively.
5.4.2 Explicit Canvas Sizing
The attributes CANVAS_WIDTH and CANVAS_HEIGHT can be set to establish the size of the
paint window. Automatic sizing should be turned off. Otherwise, as soon as the canvas win-
dow is realized, the paint window may be automatically resized to the new dimensions. This
all depends on whether either or both of the auto-expand or auto-shrink attributes are set.
The following code fragment shows that one can be set and the other unset for specific needs:
Canvas canvas;
canvas = (Canvas)xv_create(frame, CANVAS,
CANVAS_AUTO_SHRINK, FALSE,
CANVAS_AUTO_EXPAND, TRUE,
CANVAS_WIDTH, 100,
CANVAS_HEIGHT, 200,
NULL);
With these settings, the paint window will initially be set to 100 by 200. If the subwindow is
realized at a larger size, the canvas will be expanded to the new dimensions. That is, if the
frame in which the canvas resides is larger, it may affect the initial size of the paint window.
However, if the canvas is realized or resized at smaller dimensions, the canvas will retain its
original size. In short, these settings will force the paint window to grow to the maximum
size that the window will ever be—it will never shrink. In typical usage, you would set the
auto-expand and auto-shrink attributes to FALSE and explicitly set CANVAS_WIDTH and
CANVAS_HEIGHT. Alternatively, you would not initialize the width and height and set both
CANVAS_AUTO_EXPAND and CANVAS_AUTO_SHRINK to TRUE. A draw program might allow
the paint window to be sized automatically, since the display list of geometric objects is the
underlying feature of the program. However, a paint program would set explicit width and
height attributes of the graphic, disallowing any resizing of that graphic.
Canvases and
Openwin
Canvases and Openwin 99

Get Volume 7A: XView Programming Manual now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.