Page: 1 2 3 4 5 6 7 8 9 10 11 12 13

Chapter 11


Event Handling Functions

This chapter discusses the Xlib functions you can use to:

NOTE
Some toolkits use their own event-handling functions and do not allow you to interchange these event-handling functions with those in Xlib. For further information, see the documentation supplied with the toolkit.

Most applications simply are event loops: they wait for an event, decide what to do with it, execute some amount of code that results in changes to the display, and then wait for the next event.

Home

11.1. Selecting Events

There are two ways to select the events you want reported to your client application. One way is to set the event_mask member of the XSetWindowAttributes structure when you call XCreateWindow and XChangeWindowAttributes. Another way is to use XSelectInput.

XSelectInput(display, w, event_mask)
   Display *display;
   Window w;
   long event_mask;
display
Specifies the connection to the X server.
w
Specifies the window whose events you are interested in.
event_mask
Specifies the event mask.

The XSelectInput function requests that the X server report the events associated with the specified event mask. Initially, X will not report any of these events. Events are reported relative to a window. If a window is not interested in a device event, it usually propagates to the closest ancestor that is interested, unless the do_not_propagate mask prohibits it.

Setting the event-mask attribute of a window overrides any previous call for the same window but not for other clients. Multiple clients can select for the same events on the same window with the following restrictions:

The server reports the event to all interested clients.

XSelectInput can generate a BadWindow error.

Home

11.2. Handling the Output Buffer

The output buffer is an area used by Xlib to store requests. The functions described in this section flush the output buffer if the function would block or not return an event. That is, all requests residing in the output buffer that have not yet been sent are transmitted to the X server. These functions differ in the additional tasks they might perform.

To flush the output buffer, use XFlush.

XFlush(display)
   Display *display;
display
Specifies the connection to the X server.

The XFlush function flushes the output buffer. Most client applications need not use this function because the output buffer is automatically flushed as needed by calls to XPending, XNextEvent, and XWindowEvent. Events generated by the server may be enqueued into the library's event queue.

To flush the output buffer and then wait unit all requests have been processed, use XSync.

XSync(display, discard)
   Display *display;
   Bool discard;
display
Specifies the connection to the X server.
discard
Specifies a Boolean value that indicates whether XSync discards all events on the event queue.

The XSync function flushes the output buffer and then waits until all requests have been received and processed by the X server. Any errors generated must be handled by the error handler. For each protocol error received by Xlib, XSync calls the client application's error handling routine (see section 11.8.2). Any events generated by the server are enqueued into the library's event queue.

Finally, if you passed False, XSync does not discard the events in the queue. If you passed True, XSync discards all events in the queue, including those events that were on the queue before XSync was called. Client applications seldom need to call XSync.

Home

11.3. Event Queue Management

Xlib maintains an event queue. However, the operating system also may be buffering data in its network connection that is not yet read into the event queue.

To check the number of events in the event queue, use XEventsQueued.

int XEventsQueued(display, mode)
    Display *display;
    int mode;
display
Specifies the connection to the X server.
mode
Specifies the mode. You can pass QueuedAlready, QueuedAfterFlush, or QueuedAfterReading.

If mode is QueuedAlready, XEventsQueued returns the number of events already in the event queue (and never performs a system call). If mode is QueuedAfterFlush, XEventsQueued returns the number of events already in the queue if the number is nonzero. If there are no events in the queue, XEventsQueued flushes the output buffer, attempts to read more events out of the application's connection, and returns the number read. If mode is QueuedAfterReading, XEventsQueued returns the number of events already in the queue if the number is nonzero. If there are no events in the queue, XEventsQueued attempts to read more events out of the application's connection without flushing the output buffer and returns the number read.

XEventsQueued always returns immediately without I/O if there are events already in the queue. XEventsQueued with mode QueuedAfterFlush is identical in behavior to XPending. XEventsQueued with mode QueuedAlready is identical to the XQLength function.

To return the number of events that are pending, use XPending.

int XPending(display)
    Display *display;
display
Specifies the connection to the X server.

The XPending function returns the number of events that have been received from the X server but have not been removed from the event queue. XPending is identical to XEventsQueued with the mode QueuedAfterFlush specified.

Home

11.4. Manipulating the Event Queue

Xlib provides functions that let you manipulate the event queue. This section discusses how to:

11.4.1. Returning the Next Event

To get the next event and remove it from the queue, use XNextEvent.

XNextEvent(display, event_return)
  Display *display;
  XEvent *event_return;
display
Specifies the connection to the X server.
event_return
Returns the next event in the queue.

The XNextEvent function copies the first event from the event queue into the specified XEvent structure and then removes it from the queue. If the event queue is empty, XNextEvent flushes the output buffer and blocks until an event is received.

To peek at the event queue, use XPeekEvent.

XPeekEvent(display, event_return)
   Display *display;
   XEvent*event_rerurn;
display
Specifies the connection to the X server.
event_return
Returns a copy of the matched event's associated structure.

The XPeekEvent function returns the first event from the event queue, but it does not remove the event from the queue. If the queue is empty, XPeekEvent flushes the output buffer and blocks until an event is received. It then copies the event into the client-supplied XEvent structure without removing it from the event queue.

Home


11.4.2. Selecting Events Using a Predicate Procedure

Each of the functions discussed in this section requires you to pass a predicate procedure that determines if an event matches what you want. Your predicate procedure must decide if the event is useful without calling any Xlib functions. If the predicate directly or indirectly causes the state of the event queue to change, the result is not defined. If Xlib has been initialized for threads, the predicate is called with the display locked and the result of a call by the predicate to any Xlib function that locks the display is not defined unless the caller has first called XLockDisplay.

The predicate procedure and its associated arguments are:

Bool (*predicate)(display, event, arg)
   Display *display;
   XEvent *event;
   XPointer arg;
display
Specifies the connection to the X server.
event
Specifies the XEvent structure.
arg
Specifies the argument passed in from the XIfEvent, XCheckIfEvent, or XPeekIfEvent function.

The predicate procedure is called once for each event in the queue until it finds a match. After finding a match, the predicate procedure must return True. If it did not find a match, it must return False.

To check the event queue for a matching event and, if found, remove the event from the queue, use XIfEvent.

XIfEvent(display, event_return, predicate, arg)
   Display *display;
   XEvent *event_return;
   Bool (*predicate)();
   XPointer arg;
display
Specifies the connection to the X server.
event_return
Returns the matched event's associated structure.
predicate
Specifies the procedure that is to be called to determine if the next event in the queue matches what you want.
arg
Specifies the user-supplied argument that will be passed to the predicate procedure.

The XIfEvent function completes only when the specified predicate procedure returns True for an event, which indicates an event in the queue matches. XIfEvent flushes the output buffer if it blocks waiting for additional events. XIfEvent removes the matching event from the queue and copies the structure into the client-supplied XEvent structure.

To check the event queue for a matching event without blocking, use XCheckIfEvent.

Bool XCheckIfEvent(display, event_return, predicate, arg)
   Display *display;
   XEvent *event_return;
   Bool (*predicate)();
   XPointer arg;
display
Specifies the connection to the X server.
event_return
Returns a copy of the matched event's associated structure.
predicate
Specifies the procedure that is to be called to determine if the next event in the queue matches what you want.
arg
Specifies the user-supplied argument that will be passed to the predicate procedure.

When the predicate procedure finds a match, XCheckIfEvent copies the matched event into the client-supplied XEvent structure and returns True. (This event is removed from the queue.) If the predicate procedure finds no match, XCheckIfEvent returns False, and the output buffer will have been flushed. All earlier events stored in the queue are not discarded.

To check the event queue for a matching event without removing the event from the queue, use XPeekIfEvent.

XPeekIfEvent(display, event_return, predicate, arg)
   Display *display;
   XEvent*event_return;
   Bool (*predicate)();
   XPointer arg;
display
Specifies the connection to the X server.
event_return
Returns a copy of the matched event's associated structure.
predicate
Specifies the procedure that is to be called to determine if the next event in the queue matches what you want.
arg
Specifies the user-supplied argument that will be passed to the predicate procedure.

The XPeekIfEvent function returns only when the specified predicate procedure returns True for an event. After the predicate procedure finds a match, XPeekIfEvent copies the matched event into the client-supplied XEvent structure without removing the event from the queue. XPeekIfEvent flushes the output buffer if it blocks waiting for additional events.

Home


11.4.3. Selecting Events Using a Window or Event Mask

The functions discussed in this section let you select events by window or event types, allowing you to process events out of order.

To remove the next event that matches both a window and an event mask, use XWindowEvent.

XWindowEvent(display, w, event_mask, event_return)
   Display *display;
   Window w;
   long event_mask;
   XEvent *event_return;
display
Specifies the connection to the X server.
w
Specifies the window whose events you are interested in.
event_mask
Specifies the event mask.
event_return
Returns the matched event's associated structure.

The XWindowEvent function searches the event queue for an event that matches both the specified window and event mask. When it finds a match, XWindowEvent removes that event from the queue and copies it into the specified XEvent structure. The other events stored in the queue are not discarded. If a matching event is not in the queue, XWindowEvent flushes the output buffer and blocks until one is received.

To remove the next event that matches both a window and an event mask (if any), use XCheckWindowEvent. This function is similar to XWindowEvent except that it never blocks and it returns a Bool indicating if the event was returned.

Bool XCheckWindowEvent(display, w, event_mask, event_return)
   Display *display;
   Window w;
   long event_mask;
   XEvent *event_return;
display
Specifies the connection to the X server.
w
Specifies the window whose events you are interested in.
event_mask
Specifies the event mask.
event_return
Returns the matched event's associated structure.

The XCheckWindowEvent function searches the event queue and then the events available on the server connection for the first event that matches the specified window and event mask. If it finds a match, XCheckWindowEvent removes that event, copies it into the specified XEvent structure, and returns True. The other events stored in the queue are not discarded. If the event you requested is not available, XCheckWindowEvent returns False, and the output buffer will have been flushed.

To remove the next event that matches an event mask, use XMaskEvent.

XMaskEvent(display, event_mask, event_return)
  Display *display;
  long event_mask;
  XEvent *event_return;
display
Specifies the connection to the X server.
event_mask
Specifies the event mask.
event_return
Returns the matched event's associated structure.

The XMaskEvent function searches the event queue for the events associated with the specified mask. When it finds a match, XMaskEvent removes that event and copies it into the specified XEvent structure. The other events stored in the queue are not discarded. If the event you requested is not in the queue, XMaskEvent flushes the output buffer and blocks until one is received.

To return and remove the next event that matches an event mask (if any), use XCheckMaskEvent. This function is similar to XMaskEvent except that it never blocks and it returns a Bool indicating if the event was returned.

Bool XCheckMaskEvent(display, event_mask, event_return)
   Display *display;
   long event_mask;
   XEvent *event_return;
display
Specifies the connection to the X server.
event_mask
Specifies the event mask.
event_return
Returns the matched event's associated structure.

The XCheckMaskEvent function searches the event queue and then any events available on the server connection for the first event that matches the specified mask. If it finds a match, XCheckMaskEvent removes that event, copies it into the specified XEvent structure, and returns True. The other events stored in the queue are not discarded. If the event you requested is not available, XCheckMaskEvent returns False, and the output buffer will have been flushed.

To return and remove the next event in the queue that matches an event type, use XCheckTypedEvent.

Bool XCheckTypedEvent(display, event_type, event_return)
   Display *display;
   int event_type;
   XEvent *event_return;
display
Specifies the connection to the X server.
event_type
Specifies the event type to be compared.
event_return
Returns the matched event's associated structure.

The XCheckTypedEvent function searches the event queue and then any events available on the server connection for the first event that matches the specified type. If it finds a match, XCheckTypedEvent removes that event, copies it into the specified XEvent structure, and returns True. The other events in the queue are not discarded. If the event is not available, XCheckTypedEvent returns False, and the output buffer will have been flushed.

To return and remove the next event in the queue that matches an event type and a window, use XCheckTypedWindowEvent.

Bool XCheckTypedWindowEvent(display, w, event_type, event_return)
   Display *display;
   Window w;
   int event_type;
   XEvent *event_return;
display
Specifies the connection to the X server.
w
Specifies the window.
event_type
Specifies the event type to be compared.
event_return
Returns the matched event's associated structure.

The XCheckTypedWindowEvent function searches the event queue and then any events available on the server connection for the first event that matches the specified type and window. If it finds a match, XCheckTypedWindowEvent removes the event from the queue, copies it into the specified XEvent structure, and returns True. The other events in the queue are not discarded. If the event is not available, XCheckTypedWindowEvent returns False, and the output buffer will have been flushed.

Home

11.5. Putting an Event Back into the Queue

To push an event back into the event queue, use XPutBackEvent.

XPutBackEvent(display, event)
   Display *display;
   XEvent *event;
display
Specifies the connection to the X server.
event
Specifies the event.

The XPutBackEvent function pushes an event back onto the head of the display's event queue by copying the event into the queue. This can be useful if you read an event and then decide that you would rather deal with it later. There is no limit to the number of times in succession that you can call XPutBackEvent.

Home

11.6. Sending Events to Other Applications

To send an event to a specified window, use XSendEvent. This function is often used in selection processing. For example, the owner of a selection should use XSendEvent to send a SelectionNotify event to a requestor when a selection has been converted and stored as a property.

Status XSendEvent(display, w, propagate, event_mask, event_send)
    Display *display;
    Window w;
    Bool propagate;
    long event_mask;
    XEvent *event_send;
display
Specifies the connection to the X server.
w
Specifies the window the event is to be sent to, or PointerWindow, or InputFocus.
propagate
Specifies a Boolean value.
event_mask
Specifies the event mask.
event_send
Specifies the event that is to be sent.

The XSendEvent function identifies the destination window, determines which clients should receive the specified events, and ignores any active grabs. This function requires you to pass an event mask. For a discussion of the valid event mask names, see section 10.3. This function uses the w argument to identify the destination window as follows:

To determine which clients should receive the specified events, XSendEvent uses the propagate argument as follows:

The event in the XEvent structure must be one of the core events or one of the events defined by an extension (or a BadValue error results) so that the X server can correctly byte-swap the contents as necessary. The contents of the event are otherwise unaltered and unchecked by the X server except to force send_event to True in the forwarded event and to set the serial number in the event correctly; therefore these fields and the display field are ignored by XSendEvent.

XSendEvent returns zero if the conversion to wire protocol format failed and returns nonzero otherwise.

XSendEvent can generate BadValue and BadWindow errors.

Home

11.7. Getting Pointer Motion History

Some X server implementations will maintain a more complete history of pointer motion than is reported by event notification. The pointer position at each pointer hardware interrupt may be stored in a buffer for later retrieval. This buffer is called the motion history buffer. For example, a few applications, such as paint programs, want to have a precise history of where the pointer traveled. However, this historical information is highly excessive for most applications.

To determine the approximate maximum number of elements in the motion buffer, use XDisplayMotionBufferSize.

unsigned long XDisplayMotionBufferSize(display)
    Display *display;
display
Specifies the connection to the X server.

The server may retain the recent history of the pointer motion and do so to a finer granularity than is reported by MotionNotify events. The XGetMotionEvents function makes this history available.

To get the motion history for a specified window and time, use XGetMotionEvents.

XTimeCoord *XGetMotionEvents(display, w, start, stop, nevents_return)
   Display *display;
   Window w;
   Time start, stop;
   int *nevents_return;
display
Specifies the connection to the X server.
w
Specifies the window.
start, stop
Specify the time interval in which the events are returned from the motion history buffer. You can pass a timestamp or CurrentTime.
nevents_return
Returns the number of events from the motion history buffer.

The XGetMotionEvents function returns all events in the motion history buffer that fall between the specified start and stop times, inclusive, and that have coordinates that lie within the specified window (including its borders) at its present placement. If the server does not support motion history, if the start time is later than the stop time, or if the start time is in the future, no events are returned; XGetMotionEvents returns NULL. If the stop time is in the future, it is equivalent to specifying CurrentTime. The return type for this function is a structure defined as follows:

typedef struct {
Time time;
short x, y;
} XTimeCoord;

The time member is set to the time, in milliseconds. The x and y members are set to the coordinates of the pointer and are reported relative to the origin of the specified window. To free the data returned from this call, use XFree.

XGetMotionEvents can generate a BadWindow error.

Home

11.8. Handling Protocol Errors

Xlib provides functions that you can use to enable or disable synchronization and to use the default error handlers.

11.8.1. Enabling or Disabling Synchronization

When debugging X applications, it often is very convenient to require Xlib to behave synchronously so that errors are reported as they occur. The following function lets you disable or enable synchronous behavior. Note that graphics may occur 30 or more times more slowly when synchronization is enabled. On POSIX-conformant systems, there is also a global variable _Xdebug that, if set to nonzero before starting a program under a debugger, will force synchronous library behavior.

After completing their work, all Xlib functions that generate protocol requests call what is known as an after function. XSetAfterFunction sets which function is to be called.

int (*XSetAfterFunction(display, procedure))()
    Display *display;
    int (*procedure)();
display
Specifies the connection to the X server.
procedure
Specifies the procedure to be called.

The specified procedure is called with only a display pointer. XSetAfterFunction returns the previous after function.

To enable or disable synchronization, use XSynchronize.

int (*XSynchronize(display, onoff)()
    Display *display;
    Bool onoff;
display
Specifies the connection to the X server.
onoff
Specifies a Boolean value that indicates whether to enable or disable synchronization.

The XSynchronize function returns the previous after function. If onoff is True, XSynchronize turns on synchronous behavior. If onoff is False, XSynchronize turns off synchronous behavior.

Home


11.8.2. Using the Default Error Handlers

There are two default error handlers in Xlib: one to handle typically fatal conditions (for example, the connection to a display server dying because a machine crashed) and one to handle protocol errors from the X server. These error handlers can be changed to user-supplied routines if you prefer your own error handling and can be changed as often as you like. If either function is passed a NULL pointer, it will reinvoke the default handler. The action of the default handlers is to print an explanatory message and exit.

To set the error handler, use XSetErrorHandler.

int (*XSetErrorHandler(handler))()
    int (*handler)(Display *, XErrorEvent*)
handler
Specifies the program's supplied error handler.

Xlib generally calls the program's supplied error handler whenever an error is received. It is not called on BadName errors from OpenFont, LookupColor, or AllocNamedColor protocol requests or on BadFont errors from a QueryFont protocol request. These errors generally are reflected back to the program through the procedural interface. Because this condition is not assumed to be fatal, it is acceptable for your error handler to return; the returned value is ignored. However, the error handler should not call any functions (directly or indirectly) on the display that will generate protocol requests or that will look for input events. The previous error handler is returned.

The XErrorEvent structure contains:

typedef struct {
int type;
Display *display;
unsigned long serial;
unsigned char error_code;
unsigned char request_code;
unsigned char minor_code;
XID resourceid;

/* Display the event was read from */
/* serial number of failed request */
/* error code of failed request */
/* Major op-code of failed request */
/* Minor op-code of failed request */
/* resource id */
} XErrorEvent;

The serial member is the number of requests, starting from one, sent over the network connection since it was opened. It is the number that was the value of NextRequest immediately before the failing call was made. The request_code member is a protocol request of the procedure that failed, as defined in <X11/Xproto.h>. The following error codes can be returned by the functions described in this chapter:

Error Code Description
BadAccess A client attempts to grab a key/button combination already grabbed by another client.
A client attempts to free a colormap entry that it had not already allocated or to free an entry in a colormap that was created with all entries writable.
A client attempts to store into a read-only or unallocated colormap entry.
A client attempts to modify the access control list from other than the local (or otherwise authorized) host.
A client attempts to select an event type that another client has already selected.
BadAlloc The server fails to allocate the requested resource. Note that the explicit listing of BadAlloc errors in requests only covers allocation errors at a very coarse level and is not intended to (nor can it in practice hope to) cover all cases of a server running out of allocation space in the middle of service. The semantics when a server runs out of allocation space are left unspecified, but a server may generate a BadAlloc error on any request for this reason, and clients should be prepared to receive such errors and handle or discard them.
BadAtom A value for an atom argument does not name a defined atom.
BadColor A value for a colormap argument does not name a defined colormap.
BadCursor A value for a cursor argument does not name a defined cursor.
BadDrawable A value for a drawable argument does not name a defined window or pixmap.
BadFont A value for a font argument does not name a defined font (or, in some cases, GContext).
BadGC A value for a GContext argument does not name a defined GContext.
BadIDChoice The value chosen for a resource identifier either is not included in the range assigned to the client or is already in use. Under normal circumstances, this cannot occur and should be considered a server or Xlib error.
BadImplementation The server does not implement some aspect of the request. A server that generates this error for a core request is deficient. As such, this error is not listed for any of the requests, but clients should be prepared to receive such errors and handle or discard them.
BadLength The length of a request is shorter or longer than that required to contain the arguments. This is an internal Xlib or server error.
The length of a request exceeds the maximum length accepted by the server.
BadMatch In a graphics request, the root and depth of the graphics context does not match that of the drawable. An InputOnly window is used as a drawable. Some argument or pair of arguments has the correct type and range, but it fails to match in some other way required by the request. An InputOnly window lacks this attribute.
BadName A font or color of the specified name does not exist.
BadPixmap A value for a pixmap argument does not name a defined pixmap.
BadRequest The major or minor opcode does not specify a valid request. This usually is an Xlib or server error.
BadValue Some numeric value falls outside of the range of values accepted by the request. Unless a specific range is specified for an argument, the full range defined by the argument's type is accepted. Any argument defined as a set of alternatives typically can generate this error (due to the encoding).
BadWindow A value for a window argument does not name a defined window.

Home


NOTE
The BadAtom, BadColor, BadCursor, BadDrawable, BadFont, BadGC, BadPixmap, and BadWindow errors are also used when the argument type is extended by a set of fixed alternatives.

To obtain textual descriptions of the specified error code, use XGetErrorText.

XGetErrorText(display, code, buffier_return, length)
  Display *display;
  int code;
  char *buffer_return;
  int length;
display
Specifies the connection to the X server.
code
Specifies the error code for which you want to obtain a description.
buffer_return
Returns the error description.
length
Specifies the size of the buffer.

The XGetErrorText function copies a null-terminated string describing the specified error code into the specified buffer. The returned text is in the encoding of the current locale. It is recommended that you use this function to obtain an error description because extensions to Xlib may define their own error codes and error strings.

To obtain error messages from the error database, use XGetErrorDatabaseText.

XGetErrorDatabaseText(display, name, message, default_string, buffer_return, length)
  Display *display;
  char *name, *message;
  char *default_string;
  char *buffer_return;
  int length;
display
Specifies the connection to the X server.
name
Specifies the name of the application.
message
Specifies the type of the error message.
default_string
Specifies the default error message if none is found in the database.
buffer_return
Returns the error description.
length
Specifies the size of the buffer.

The XGetErrorDatabaseText function returns a null-terminated message (or the default message) from the error message database. Xlib uses this function internally to look up its error messages. The text in the default_string argument is assumed to be in the encoding of the current locale, and the text stored in the buffer_return argument is in the encoding of the current locale.

The name argument should generally be the name of your application. The message argument should indicate which type of error message you want. If the name and message are not in the Host Portable Character Encoding, the result is implementation dependent. Xlib uses three predefined "application names" to report errors. In these names, uppercase and lowercase matter.

XProtoError
The protocol error number is used as a string for the message argument.
XlibMessage
These are the message strings that are used internally by the library.
XRequest
For a core protocol request, the major request protocol number is used for the message argument. For an extension request, the extension name (as given by InitExtension) followed by a period (.) and the minor request protocol number is used for the message argument. If no string is found in the error database, the default_string is returned to the buffer argument.

To report an error to the user when the requested display does not exist, use XDisplayName.

char *XDisplayName(string)
    char *string;
string
Specifies the character string.

The XDisplayName function returns the name of the display that XOpenDisplay would attempt to use. If a NULL string is specified, XDisplayName looks in the environment for the display and returns the display name that XOpenDisplay would attempt to use. This makes it easier to report to the user precisely which display the program attempted to open when the initial connection attempt failed.

To handle fatal I/O errors, use XSetIOErrorHandler.

int (*XSetIOErrorHandler(handler))()
    int (*handler)(Display *);
handler
Specifies the program's supplied error handler.

The XSetIOErrorHandler sets the fatal I/O error handler. Xlib calls the program's supplied error handler if any sort of system call error occurs (for example, the connection to the server was lost). This is assumed to be a fatal condition, and the called routine should not return. If the I/O error handler does return, the client process exits.

Note that the previous error handler is returned.

Home

Contents Previous Chapter Next Chapter