5.2.1.2 Paint programs
Paint programs are pixel based, meaning that the image that the user manipulates is typically
a bitmap (monochrome) or a color pixmap. In this case, the pixmap is used as the internal
data. If the user uses a brush to modify the image, the modification to the canvas window is
handled in the event procedure as above, but the image that the user is editing is also updated
so that when the repaint routine is called, it can use a function such as XCopyArea() to
copy the portion of the image onto the canvas window. This is also a case where the event
handler may draw directly onto the window.
If the program starts up and already has an image to work with (e.g., the user requests to load
a previously saved image that was stored into the file), do not render the image onto the paint
window before xv_main_loop() is called. Eventually, the repaint procedure will be
called and the image should be rendered at that time.
5.2.1.3 Text-based programs
If you want to display text, as in desktop publishing packages, or if you just want a simple
program that displays a window with text, then the same thing applies as with the previous
examples: render the text in the repaint routine based on internal data (e.g., a text string or
set of strings). Again, the data must contain enough information to allow your repaint routine
to repaint the text as it was intended (e.g., font type, style, size, color).
Event-handling routines that accept keyboard input may render the new text directly to the
canvas window, but the text entered should also be saved internally for the benefit of the
repaint routine.
5.2.1.4 Visualization programs
It is common to have an application that displays the time, network traffic, CPU usage, file
system integrity, or the current Dow Jones Industrial Averages. Such applications get their
data from a variety of sources such as the system clock,
UNIX sockets, the file system or the
output of another application that has been forked. In the past, such applications might have
been written where the repaint routine accesses the information. This model does not apply
in a networked windowing system because of its asynchronous nature; the window system
and the application may not be in sync. A program should have a separate method for
retrieving data apart from the repaint procedure. See the program animate.c in Chapter 20,
The Notifier, for an example.
In many of these cases (with the possible exception of the meters), if the application is well
designed, the repaint routines and the event handlers may be calling the same internal rou-
tines which render graphics. Therefore, when writing functions that draw into a canvas, you
should consider the generic case where the function could be called from a repaint routine,
event handler or anywhere else. The canvas_event.c shown in Example 5-3 calls the repaint
routine directly from the event handler.
90 XView Programming Manual
5.2.1.5 Rendering graphics
The preferred form of rendering graphics from an XView application is to use Xlib graphics
calls. Volume One, Xlib Programming Manual, has a complete discussion of Xlib graphics
programming. Throughout this book, you will find examples of drawing into canvases using
Xlib graphics routines. Appendix F, Example Programs, has several longer programs that
demonstrate Xlib graphics. The XView graphics model, which is available, is almost identi-
cal to the SunView model for graphics and is provided for backwards compatibility with
SunView. Because XView graphics calls are wrappers to the underlying Xlib calls, these
functions are not recommended for graphics-intensive applications or for use by program-
mers who are not already familiar with SunView.
5.3 The Repaint Procedure
It is always the responsibility of the application to repaint its canvas at any time. Even
though there may be a retained canvas that the X server maintains, there is no guarantee that
there will be enough memory for the server to maintain it. For this reason, all canvases
should install a routine to handle repainting.
To install a repaint procedure, use the attribute CANVAS_REPAINT_PROC and specify a call-
back function as its value:
extern void my_repaint_proc();
...
canvas = (Canvas)xv_create(frame, CANVAS,
...
CANVAS_REPAINT_PROC, my_repaint_proc,
...
NULL);
The repaint routine installed is called any time all or a portion of the canvas needs to be
re-displayed. This always happens when the canvas is mapped on the screen for the first time
(causing an Expose event). If the canvas is not retained, the repaint procedure is called
when:
• The canvas is resized.
• The canvas has been moved in front of obscuring windows.
• The user uses the scrollbar to render a different part of the paint window visible.
If the canvas is retained and has not changed size, the server refreshes the window without
calling the repaint routine. This includes all exposures except for those that are the result of
a resize of the window or the initial mapping of the canvas onto the screen. However, if the
canvas is not retained, the repaint routine is called in all of these cases.
The repaint callback routine will be called once for each view the canvas is maintaining. If
the canvas has been split several times, then the repaint routine will get called for each view
that needs repainting. One of the parameters to the callback routine is a variable that
describes the region that has been exposed or needs repainting. When a window is initially
Canvases and
Openwin
Canvases and Openwin 91
displayed on the screen, the exposed region is the entire canvas. However, this area may not
be a contiguous area of the window. For example, as shown in Figure 5-4, if a window that is
partially obscured by two windows is brought forward, two separate areas are exposed.
total 49
1 sbin/ 3 etc/ 1 preserve/
1 5include 1 hosts/ 1 pub/
1 5lib/ 2 include/ 1 sccs
1 Xlir3@ 1 kvm 1 share/
1 adm@ 4 lib/ 1 spool@
6 bin/ 1 local/ 1 sqps
1 boot/ 8 lost+found/ 1 stand/
1 demo/ 1 man@ 1 sys@
1 diag/ 1 mdc/ 1 tmp@
1 dict 1 old/ 2 ucb/
colorful-96%
Before
Window partially obscured
After
Exposed in one view
XView Programming Manual
Volume Seven, XView Programming Manual, is a
complete programmer’s guide to XView Version
2. XView stands for X Window System-based
Visual/Integrated Environment for Workstations.
XView was developed by Sun Microsystems and
is derived from Sun’s proprietary programming
toolkit, Sun View. Its foremost design goal is to
provide the OPEN LOOK user interface for the X
applications. Existing Sun View applications can
be easily ported to XView and run under the X
Window
XView Programming Manual
Volume Seven, XView Programming Manual, is a
complete programmer’s guide to XView Version
2. XView stands for X Window System-based
Visual/Integrated Environment for Workstations.
XView was developed by Sun Microsystems and
is derived from Sun’s proprietary programming
toolkit, Sun View. Its foremost design goal is to
provide the OPEN LOOK user interface for the X
applications. Existing Sun View applications can
be easily ported to XView and run under the X
Window
total 49
1 sbin/ 3 etc/ 1 preserve/
1 5include 1 hosts/ 1 pub/
1 5lib/ 2 include/ 1 sccs
1 Xlir3@ 1 kvm 1 share/
1 adm@ 4 lib/ 1 spool@
6 bin/ 1 local/ 1 sqps
1 boot/ 8 lost+found/ 1 stand/
1 demo/ 1 man@ 1 sys@
1 diag/ 1 mdc/ 1 tmp@
1 dict 1 old/ 2 ucb/
colorful-96%
Figure 5-4. Window before and after an Expose event
The attribute WIN_COLLAPSE_EXPOSURES governs how many times the repaint routine is
called. By default, XView collapses Expose (and GraphicsExpose) X events destined
for the same window; that is, XView waits for the exposure count member to reach zero.
After all exposure X events have arrived (when count == 0), XView generates a
WIN_REPAINT event and calls the repaint procedure. This WIN_REPAINT represents all the
areas in the window that have been damaged (it can be a disjoint set of rectangles). The X
event associated with the WIN_REPAINT event (accessed through the event_xevent()
macro) represents a bounding rectangle of all the damaged areas in the window (basically the
union of all the damaged areas in the window).
However, sometimes the application wants to monitor the incoming Expose (and Gra-
phicsExpose) X events, monitoring piece by piece the count member in the Expose X
event itself. This can be done by setting WIN_COLLAPSE_EXPOSURES to FALSE on the can-
vas’s paint window. As exposures come into a window with this attribute set to FALSE, they
will be immediately sent to the client’s repaint procedure. The client will thus receive sev-
eral WIN_REPAINT events, all for the same window. The area of exposure is set to each
region as it is exposed.
By default, the repaint routine is called once per window exposed. However, there may be
situations where there are more windows exposed in the same canvas object. For example, in
Figure 5-5, two view windows have been exposed as a result of bringing the window to the
top of the window stack. In this case, the repaint routine will be called twice—once for the
92 XView Programming Manual
paint window of each view exposed. Only one area of each view window is exposed, so the
value of the WIN_COLLAPSE_EXPOSURES attribute does not apply.
XView Programming Manual
Volume Seven, XView Programming Manual, is a
complete programmer’s guide to XView Version
2. XView stands for X Window System-based
Visual/Integrated Environment for Workstations.
XView was developed by Sun Microsystems and
is derived from Sun’s proprietary programming
toolkit, Sun View. Its foremost design goal is to
provide the OPEN LOOK user interface for the X
applications. Existing Sun View applications can
be easily ported to XView and run under the X
Window
Before
Window partially obscured
After
Exposed in two views
XView Programming Manual
Volume Seven, XView Programming Manual, is a
complete programmer’s guide to XView Version
2. XView stands for X Window System-based
Visual/Integrated Environment for Workstations.
XView was developed by Sun Microsystems and
is derived from Sun’s proprietary programming
toolkit, Sun View. Its foremost design goal is to
provide the OPEN LOOK user interface for the X
applications. Existing Sun View applications can
be easily ported to XView and run under the X
Window
Figure 5-5. Window with two views before and after an Expose event
If at any time you need to get the entire viewable area of the canvas, or more specifically, of
an arbitrary paint window within the canvas, you can use the attribute CANVAS_VIEW-
ABLE_RECT
:
Rect *rect;
Xv_Window pw = canvas_paint_window(canvas);
rect = (Rect *)xv_get(canvas, CANVAS_VIEWABLE_RECT, pw);
The rect pointer returned points to an internal data structure that describes the viewable
area of the paint window specified. This structure changes for each call, so if the value is to
be retained, it should be copied.
Before the repaint routine is called, the window can be cleared in one of two ways. If
CANVAS_AUTO_CLEAR is set to TRUE, then the paint window being repainted is automatically
cleared. CANVAS_AUTO_CLEAR is really defined as OPENWIN_AUTO_CLEAR since this is a
property of the
OPENWIN
package. Automatically clearing the window happens any time the
window needs repainting. This means that the exposed area represents the entire window. If
this attribute is set to FALSE (the default), the repaint routine should prepare to clear all, or
portions of, the window that needs to be repainted. The contents of the window in the
exposed areas is undefined. If you are going to repaint those areas opaquely (that is, leave no
transparent portions), then you do not need to clear the area. However, if any transparent
portion of the area will be repainted (e.g., if your gc.function is set to GXxor), you
should clear the window first by using XClearArea() or XClearWindow().
Canvases and
Openwin
Canvases and Openwin 93
Alternatively, the window may be cleared automatically by the Xlib internals if the window
has actually changed size. The BitGravity attribute for the window controls whether the
data in the window is cleared or just moved around to different locations of the window
according to its new size. If BitGravity is set to ForgetGravity, then the data in the
window is discarded, resulting in the window getting cleared and the canvas’s repaint proce-
dure getting called. As mentioned before, this value can be set by setting the attribute
CANVAS_FIXED_IMAGE to FALSE. But to have more direct control over the BitGravity of
the window, the window attribute WIN_BIT_GRAVITY may be set to any of the legal values
provided by Xlib (ForgetGravity, NorthGravity, NorthWestGravity and so on).
Section 4.3.3, “Bit Gravity,” in Volume One, Xlib Programming Manual, discusses this in
full detail. Note: this should not be confused with WIN_WINDOW_GRAVITY which controls the
reposition of subwindows when a parent window is resized. This task is left to the FRAME
package, since it controls subwindow layout.
If the attribute CANVAS_CMS_REPAINT is set to TRUE, the repaint procedure is called automat-
ically whenever a new colormap segment is set on the canvas or the foreground and back-
ground colors of the canvas are changed using WIN_FOREGROUND_COLOR and WIN_BACK-
GROUND_COLOR
.
The parameters to the repaint routine provide information about which window and which
areas within the window need to be repainted.
The repaint procedure takes one of two different forms:
void
repaint_proc(canvas, paint_window, repaint_area)
Canvas canvas;
Xv_Window paint_window
Rectlist *repaint_area;
or:
void
repaint_proc(canvas, paint_window, dpy, xwin, area)
Canvas canvas;
Xv_Window paint_window
Display *dpy;
Window xwin;
Xv_xrectlist *area;
The routine takes the first or second form depending on the value of the attribute
CANVAS_X_PAINT_WINDOW. If FALSE, the first, simpler form of the repaint procedure is
called. If
TRUE, the repaint routine gets passed the parameters shown in the second form.
The second method is more useful since it saves you from writing code for extracting the
Display and the XID of the paint window.
In both forms, the first two parameters are rather obvious—the paint_window is the paint
window associated with the canvas that needs repainting (not the view window). The
paint_window contains an X window whose XID can be gotten by using xv_get():
Window xwin = (Window)xv_get(paint_window, XV_XID);
xwin is set to the actual X window referenced by the paint window. This is the way to obtain
the XID from the paint window because the first form of the repaint procedure (when
CANVAS_X_PAINT_WINDOW is FALSE) does not provide a handle for you.
94 XView Programming Manual
Get Volume 7A: XView Programming Manual now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.