20.7 Client Events
Client events are used by an application to communicate with clients of the Notifier. With
the client event mechanism, you can have any portion of your application send an event. The
Notifier dispatches the event to any of its clients that have expressed interest in that particu-
lar client event; essentially the event is sent, via the notifier, to another portion of the applica-
tion, where it is handled. Events are posted to specific clients of the Notifier.
Client events are important and are frequently used internally by XView; they can also be
used in an application. For example, if you want an application to notify an interested Notif-
ier client that input has been received from a pipe, once the data has been read, the applica-
tion can post the data to the Notifier as a client event (see Section 20.8, “Reading and Writing
through File Descriptors”).
From the Notifier’s point of view, client events are defined and generated by the application.
Client events are not interpreted by the Notifier in any way; the Notifier does not detect client
events. An X event is also a client event. Internally, the window package reads the X event
from the server and posts it to a client via notify_post_event(). When client events
are posted to the Notifier, it dispatches these events to a receiving client’s event handler. The
receiving client then interprets the client events.
The process for the delivery of client events is similar to that of signals. However, because
the entire process happens in the application, more control can be maintained by the Notifier.
This additional level of control uses optional parameters that may be passed to client event
handlers. These optional parameters include values for safe and immediate handling. With
safe handling the Notifier sends event handlers notification when it is safe to do so. This may
involve some delay between when an event is posted and when it is delivered. Alternatively,
for immediate handling, an event handler may ask to be immediately notified when a client
event is posted. A client event handler may have both a safe and an immediate event han-
dler. Safe and immediate notification are covered in more detail later on in this section.
The remainder of this section describes how to register client event handlers and how to post
client events.
NOTE
XView internally registers event handlers for its internally defined client events
when window-based objects are created. You will almost never need to register
your own client event handler. It is more common that you will want to inter-
pose in front of one of XView’s client event handlers. Refer to Section 20.9,
“Interposition,” for details on interposition.
474 XView Programming Manual
20.7.1 Receiving Client Events
To register a client event handler, use:
Notify_func
notify_set_event_func(client, event_func, when)
Notify_client client;
Notify_func event_func;
Notify_event_type when;
typedef enum notify_event_type {
NOTIFY_SAFE = 0,
NOTIFY_IMMEDIATE = 1,
} Notify_event_type;
The when parameter indicates whether the event handler will accept notifications only when
it is safe (NOTIFY_SAFE) or for immediate notification and when it is safe (NOTIFY_IMME-
DIATE
). You may register two client event handlers to handle these cases individually, or
just one client event handler to cover both.
The calling sequence of a client event handler is:
Notify_value
event_func(client, event, arg, when)
Notify_client client;
Notify_event event;
Notify_arg arg;
Notify_event_type when;
The client is the one that was passed to notify_set_event_func(). The event is
passed through from notify_post_event(), which is described in the following sec-
tion. The arg and event parameters are completely defined by the client. The types
Notify_arg and Notify_event are of type caddr_t, a generic pointer type. The
when parameter is the actual situation in which event is being delivered. It can have the
value NOTIFY_SAFE or NOTIFY_IMMEDIATE, and can be different from when_hint of
notify_post_event().
The return value Notify_value may be one of NOTIFY_DONE, NOTIFY_IGNORED, or
NOTIFY_UNEXPECTED. NOTIFY_DONE indicates that the event was acted on in some way.
This implies that no further action is required by the client. If the safe event handler returns
NOTIFY_IGNORED, this indicates that the event failed to provoke any action. If the immedi-
ate client event handler returns NOTIFY_IGNORED, then the same notification will be
delivered to the safe client event handler when it is safe. A value of NOTIFY_UNEXPECTED
indicates the event was not handled and not recognized. This return value may indicate an
error condition.
Notifier
The Notifier 475
20.7.2 Posting Client Events
A client event may be posted to the Notifier at any time. The poster of a client event may
suggest to the Notifier when to deliver the event, but this is only a hint. The Notifier will see
to it that it is delivered at an appropriate time (more on this below). The call to post a client
event is:
typedef char * Notify_event;
Notify_error
notify_post_event(client, event, when_hint)
Notify_client client;
Notify_event event;
Notify_event_type when_hint;
The client handle from notify_set_event_func() is passed to notify_
post_event(). event is defined and interpreted solely by the client. A return code
of NOTIFY_OK indicates that the notification has been posted. Other values indicate an error
condition. NOTIFY_UNKNOWN_CLIENT indicates that client is unknown to the Notifier.
NOTIFY_NO_CONDITION indicates that client has no client event handler registered with
the Notifier.
Usually it is during the call to notify_post_event() that the client event handler is
called. Sometimes, however, the notification is queued up for later delivery. The Notifier
chooses between these two possibilities by noting which kinds of client event handlers
client has registered, whether it is safe, and what the value of when_hint is. Here are
the cases broken down by the kind of client event handlers client has registered:
Immediate only If when_hint is NOTIFY_SAFE or NOTIFY_IMMEDIATE, the event is
delivered immediately.
Safe only If when_hint is NOTIFY_SAFE or NOTIFY_IMMEDIATE, the event is
delivered when it is safe.
Both safe and immediate
A client may have both an immediate client event handler as well as a safe
client event handler. If when_hint is NOTIFY_SAFE, then the notifica-
tion is delivered to the safe client event handler when it is safe. If
when_hint is NOTIFY_IMMEDIATE, then the notification is delivered to
the immediate client event handler right away. If the immediate client
event handler returns NOTIFY_IGNORED, then the same notification will be
delivered to the safe client event handler when it is safe.
476 XView Programming Manual
20.7.2.1 Actual delivery time
For client events, other than knowing which event handler to call, the main function of the
Notifier is to know when to make the call. The Notifier defines when it is safe to make a
client notification. If it is not safe, then the event is queued up for later delivery. Here are the
conventions:
A client that has registered an immediate client event handler is sent a notification as
soon as it is received. The client has complete responsibility for handling the event
safely. It is rarely safe to do much of anything when an event is received asynchronously.
Usually, just setting a flag that indicates that the event has been received is about the
safest thing that can be done.
A client that has registered a safe client event handler will have a notification queued up
for later delivery when the notification was posted during an asynchronous signal notifi-
cation. Immediate delivery is not safe because your process, just before receiving the
signal, may have been executing code at any arbitrary place.
A client that has registered a safe client event handler will have a notification queued up
for later delivery if the client’s safe client event handler hasn’t returned from processing
a previous event. This convention is mainly to prevent the cycle: Notifier notifies A, who
notifies B, who notifies A. A could have had its data structures torn up when it notified B
and was not in a state to be re-entered.
These conventions imply that a safe client event handler is called immediately from other
signal handlers. The following sequence shows how the notification might progress.
A client’s input pending event handler is called by the Notifier.
Two characters are read by the client’s input pending event handler.
The first character is given to the Notifier to deliver to the client’s save event handler (the
delivery is accomplished with notify_post_event()).
Returning back to the input pending event handler, the second character is sent. This
character is also delivered immediately.
20.7.3 Posting with an Argument
XView posts a fixed-field structure with each event. Sometimes additional data must be pas-
sed with an event. For instance, when the scrollbar posts an event to its owner to do a scroll,
the scrollbar’s handle is passed as an argument along with the event. The function
notify_post_event_and_arg() provides this argument-passing mechanism (see
below).
When posting a client event, there is the possibility of delivery being delayed. In the case of
XView, the event being posted is a pointer to a structure. The Notifier avoids an invalid
(dangling) pointer reference by copying the event if delivery is delayed. It calls routines the
client supplies to copy the event information and later to free up the storage the copy uses.
Notifier
The Notifier 477
notify_post_event_and_arg() provides this storage management mechanism.
Notify_error
notify_post_event_and_arg(client, event, when_hint, arg,
copy_func, release_func)
Notify_client client;
Notify_event event;
Notify_event_type when_hint;
Notify_arg arg;
Notify_copy copy_func;
Notify_release release_func;
typedef caddr_t Notify_arg;
typedef Notify_arg (*Notify_copy)();
#define NOTIFY_COPY_NULL ((Notify_copy)0)
typedef void (*Notify_release)();
#define NOTIFY_RELEASE_NULL ((Notify_release)0)
copy_func() is called to copy arg (and, optionally, event) when event and arg need
to be queued for later delivery. release_func() is called to release the storage allocated
during the copy call when event and arg were no longer needed by the Notifier.
Any of arg, copy_func(), or release_func() may be NULL. If copy_func is not
NOTIFY_COPY_NULL and arg is NULL, then copy_func() is called anyway. This allows
event the opportunity to be copied because copy_func() takes a pointer to event. The
event pointed to may be replaced as a side effect of the copy call. The same applies to a
NOTIFY_RELEASE_NULL release function with a NULL arg argument.
The copy() and release() routines are client-dependent, so you must write them your-
self. Their calling sequences are the following:
Notify_arg
copy_func(client, arg, event_ptr)
Notify_client client;
Notify_arg arg;
Notify_event *event_ptr;
void
release_func(client, arg, event)
Notify_client client;
Notify_arg arg;
Notify_event event;
20.7.4 Posting Destroy Events
When a destroy notification is set, the Notifier also sets up a synchronous signal condition for
SIGTERM that will generate a DESTROY_PROCESS_DEATH destroy notification. Otherwise, a
destroy function will not be called automatically by the Notifier. One or two (depending on
whether the client can veto your notification) explicit calls to notify_post_
destroy() need to be made.
478 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.