In this chapter, we look at the Notifier in greater detail, discussing its role in processing
events for an XView application. This chapter serves as an introduction to the Notifier and
covers its use for most applications. You should be familiar with the topics covered in Chap-
ter 6, Handling Input, before you read this chapter.
20.1 Basic Concepts
The Notiﬁer maintains the ﬂow of control in an application. To understand the basic con-
cepts of the Notiﬁer, we must distinguish between two different styles of input handling,
mainline and event-driven input, and consider how they affect where the ﬂow of control
resides within a program.
20.1.1 Mainline Input Handling
The traditional type of input handling of most text-based applications is mainline-based and
input-driven. The ﬂow of control resides in the main routine and the program blocks when it
expects input. That is to say, no other portion of the program may be executed while the pro-
gram is waiting for input. For example, in a mainline-driven application, a C programmer
will use fgets() or getchar() to wait for characters that the user types. Based on the
user’s input, the program chooses an action to take. Sometimes, that action requires more
input, so the application calls getchar() again. The program does not return to the main
routine until the processing for the current input is done.
The tight control represented by this form of input handling is the easiest to program since
you have control at all times over what to expect from the user and you can control the direc-
tion that the application takes. There is only one source of input—the keyboard—and the
user can only respond to one interface element at a time. A user’s responses are predictable
in the sense that you know that the user is going to type something, even if you do not know
what it is.
The Notiﬁer 459
20.1.2 Event-driven Input Handling
Windowing systems are designed such that many sources of input are available to the user at
any given time. In addition to the keyboard, there are other input devices, such as the mouse.
Each keystroke and mouse movement causes an event that the application might consider.
These keystroke and mouse events are generated from the window system. Further, there are
other types of events that are generated from the window system itself and from other
processes. Another aspect of event-driven input handling is that you are not guaranteed to
have any predictable sequence of events from the user. That is, a user can position the mouse
on an object that receives text as input. Before the user is done typing, the user can move the
mouse to another window and select a panel button of some sort. The application cannot
(and should not) expect the user to type in window A ﬁrst, then move to window B and select
the button. A well-written program should expect input from any window to happen at any
20.2 Functions of the Notifier
The Notiﬁer can do any of the following:
• Handle software interrupts—speciﬁcally, UNIX signals such as SIGINT or SIGCONT.
• Notice state changes in processes that your process has spawned (e.g., a child process that
• Read and write through ﬁle descriptors (e.g., ﬁles, pipes, and sockets).
• Receive notiﬁcation of the expiration of timers so that you can regularly ﬂash a caret or
• Extend, modify, or monitor XView Notiﬁer clients (e.g., noticing when a frame is opened,
closed, or about to be destroyed.)
• Use a non-notiﬁcation-based control structure while running under XView (e.g., porting
programs to XView).
The Notiﬁer also has provisions, to a limited degree, to allow programs to run in the Notiﬁer
environment without inverting their control structure.
460 XView Programming Manual
20.3 How the Notifier Works
Up until now, we have been saying that you should register an event handler for objects when
they want to be notiﬁed of certain events such as mouse motion or selection or keyboard
input. What you may not have been aware of is that you are indirectly registering these event
handlers with the Notiﬁer. When you specify callbacks or notify procedures, the XView
object speciﬁed is said to be the client of the Notiﬁer. Look at the following code:
extern void my_event_handler();
WIN_CONSUME_X_EVENT_MASK, ButtonPressMask | KeyPressMask,
In the above code, each paint window of the canvas becomes a client of the Notiﬁer.*
Generally stated, the Notiﬁer detects events in which its clients have expressed an interest
and dispatches these events to the proper clients in a predictable order. In the X Window
System, events are delivered to the application by the X server. In XView, it is the Notiﬁer
that receives the events from the server and dispatches them to its clients. After the client’s
notify procedure processes the event, control is returned to the Notiﬁer.
The Notiﬁer imposes some restrictions on its clients. Designers should be aware of these
restrictions when developing software to work in the Notiﬁer environment. These restric-
tions exist so that the application and the Notiﬁer do not interfere with each other. More pre-
cisely, since the Notiﬁer is multiplexing access to user process resources, the application
needs to respect this effort so as not to violate the sharing mechanism.
For example, a client should not call signal (3). The Notiﬁer is catching signals on behalf
of its clients. If a client sets up its own signal handler, then the Notiﬁer will never notice the
signal. The program should call notify_set_signal_func() instead of signal (3)
(see Section 20.5, “Signal Handling”).
*CANVAS_PAINTWINDOW_ATTRS tells the CANVAS package to register the input mask and callback routine for
each of its paint windows.
The Notiﬁer 461
220.127.116.11 System calls to avoid
Assuming an environment with multiple clients and an unknown Notiﬁer usage pattern, you
should not use any of the following system calls or C library routines:
signal (3) The Notiﬁer is catching signals on behalf of its clients. If you set up your
own signal handler over the one that the Notiﬁer has set up, then the Notif-
ier will never notice the signal.
sigvec (2) The same applies for sigvec (2) as for signal (3) above.
sigaction (2) The same applies for sigaction (2) as for signal (3) above.
setitimer (2) The Notiﬁer is managing two of the process’s interval timers on behalf of
its many clients. If you access an interval timer directly, the Notiﬁer could
miss a timeout. Use notify_set_itimer_func() instead of seti-
alarm (3) Because alarm (3) sets the process’s interval timer directly, the same
applies here as for setitimer (2) above.
getitimer (2) When using a Notiﬁer-managed interval timer, you should call
notify_itimer_value() to get its current status. Otherwise, you
can get inaccurate results.
wait3 (2) The Notiﬁer notices child process state changes on behalf of its clients. If
you do your own wait3 (2), then the Notiﬁer may never notice the
change in a child process or you may get a change of state for a child pro-
cess in which you have no interest. Use notify_set
_wait3_func() instead of wait3 (2).
wait (2) The same applies for wait (2) as does for wait3 (2) above.
ioctl (2) ( . . . , FIONBIO, . . . )
This call sets the blocking status of a ﬁle descriptor. The Notiﬁer needs to
know the blocking status of a ﬁle descriptor in order to determine if there
is activity on it. fcntl (2) has an analogous request that should be used
instead of ioctl (2).
ioctl (2) ( . . . , FIOASYNC, . . . )
This call controls a ﬁle descriptor’s asynchronous IO (input/output) mode
setting. The Notiﬁer needs to know this mode in order to determine if
there is activity on it. fcntl (2) has an analogous request that should be
used instead of ioctl (2).
popen and pclose (2)
In the SunOS, these functions call wait (2). Hence, you should avoid
using these for the reasons mentioned above.
system (3) In the SunOS, this function calls signal (3) and wait (2). Hence, you
should avoid using this for the reasons mentioned above.
462 XView Programming Manual
20.4 What is a Notifier Client?
A client of the Notiﬁer is anything that has registered a callback routine with it. In XView, a
client is an object such as a canvas or panel that you have created using xv_create().
Typically, most of the event registration happens at the time such clients are created. How-
ever, to the Notiﬁer, a client is nothing more than an ID that distinguishes it from all other
Notiﬁer clients. Thus, you could identify a client using a number such as “43” or the address
of an object as in &foo. XView objects are commonly used as Notiﬁer clients because
xv_create() returns a unique handle to an object that has been allocated dynamically.
The client ID is of type Notify_client as declared in <xview/notify.h>.
Certain notify_* functions create Notiﬁer clients. For example:
Notify_client client = (Notify_client)10101; /* arbitrary */
In this code fragment, up until the call to notify_set_destroy_func(), the client
may not have been registered as a client to the Notiﬁer. When you call
notify_set_destroy_func(), internally, the Notiﬁer package looks up in its table of
clients whether there is any other client using that identiﬁer (the client handle is the identif-
ier, in this case this is an arbitrary value). If there is a client using the identiﬁer, then the des-
troy function speciﬁed is set for that client’s destroy handling. Otherwise, a new Notiﬁer cli-
ent is allocated and the client handle is also used as a handle to the new Notiﬁer client.
Notiﬁer clients are not XView objects for you to create or manipulate using xv_create()
or xv_set(). In fact, the Notiﬁer is completely independent of XView and can be used in
applications that do not even use XView objects.
20.4.1 Types of Interaction
Client interaction with the Notiﬁer falls into two general categories:
• Event Handling – A client may receive events and respond to them using event handlers.
As you have seen, event handlers (callbacks and notify procedures) do much of the work
in the Notiﬁer environment.
• Interposition – A client may request that the Notiﬁer install a special type of event han-
dler, supplied by the client, to be interposed ahead of the current event handler for a
given type of event and client. This allows clients to screen incoming events and redirect
them and to monitor and change the status of other clients. A thorough discussion of
interposition is presented later in this chapter.
A client establishes an interest in a certain type of event by registering an event handler to
respond to it. The following sections cover registration procedures for special signal and
UNIX-related event handlers, for application-deﬁned client event handlers, and for interpos-
ing event handlers. All event handlers, including interposers, return a value of
NOTIFY_DONE, NOTIFY_IGNORED, or NOTIFY_UNEXPECTED, depending on how the event
The Notiﬁer 463