VMS DECwindows Guide to Xlib (Release 4) Programming: MIT C Binding


Previous Contents Index

9.12.2 Returning the Next Event on the Queue

To return the first event on the event queue and copy it into the specified event data structure, use the NEXT EVENT and PEEK EVENT routines. NEXT EVENT returns the first event, copies it into an EVENT structure, and removes it from the queue. PEEK EVENT returns the first event, copies it into an event data structure, but does not remove it from the queue. In both cases, if the event queue is empty, the routine flushes the output buffer and blocks until an event is received.

9.12.3 Selecting Events That Match User-Defined Routines

Xlib enables the client to check all the events on the queue for a specific type of event by specifying a client-defined routine known as a predicate procedure. The predicate procedure determines if the event on the queue is one that the client is interested in.

The client calls the predicate procedure from inside the event routine. The predicate procedure should determine only if the event is useful and must not call Xlib routines. The predicate procedure is called once for each event in the queue until it finds a match.

Table 9-11 lists routines that use a predicate procedure and indicates whether or not the routine blocks.

Table 9-11 Selecting Events Using a Predicate Procedure
Routine Description Blocking/
No Blocking
IF EVENT Checks the event queue for the specified event. If the event matches, removes the event from the queue. This routine is also called each time an event is added to the queue. Blocking
CHECK IF EVENT Checks the event queue for the specified event. If the event matches, removes the event from the queue. If the predicate procedure does not find a match, it flushes the output buffer. No blocking
PEEK IF EVENT Checks the event queue for the specified event but does not remove it from the queue. This routine is also called each time an event is added to the queue. Blocking

9.12.4 Selecting Events Using an Event Mask

Xlib enables a client to process events out of order by specifying a window identifier and one of the event masks listed in Table 9-3 when calling routines listed in Table 9-12.

For example, the following specifies keyboard events on window window by using the event mask name constant KeymapStateMask.


               .
               .
               .
XWindowEvent(dpy, window, KeymapStateMask, &event) 

Table 9-12 lists routines that use event or window masks and indicates whether the routine blocks.

Table 9-12 Routines to Select Events Using a Mask
Routine Description Blocking/
No Blocking
WINDOW EVENT Searches the event queue and removes the next event that matches both the specified window and event mask Blocking
CHECK WINDOW EVENT Searches the event queue, then the events available on the server connection, and removes the first event that matches the specified event and window mask No blocking
MASK EVENT Searches the event queue and removes the next event that matches the event mask Blocking
CHECK MASK EVENT Searches the event queue, then the events available on the server connection, and removes the next event that matches an event mask No blocking
CHECK TYPED EVENT Returns the next event in the queue that matches an event type No blocking
CHECK TYPED WINDOW EVENT Searches the event queue, then the events available on the server connection, and removes the next event that matches the specified type and window No blocking

9.12.5 Putting Events Back on Top of the Queue

To push an event back onto the top of the event queue, use the PUT BACK EVENT routine. PUT BACK EVENT is useful when a client returns an event from the queue and decides to use it later. There is no limit to how many times in succession PUT BACK EVENT can be called.

9.12.6 Sending Events to Other Clients

To send an event to a client, use the SEND EVENT routine. For example, owners of a selection should use this routine to send a SELECTION NOTIFY event to a requestor when a selection has been converted and stored as a property.

9.13 Error Handling

Xlib has two default error handlers. One manages fatal errors, such as when the connection to a display is severed due to a system failure. The other handles error events from the server. The default error handlers print an explanatory message and text and then exit.

Each of these error handlers can be replaced by client error handling routines. If a client-supplied routine is passed a null pointer, Xlib reinvokes the default error handler.

This section describes the Xlib event error handling resources including enabling synchronous operation, handling server errors, and handling input/output (I/O) errors.

9.13.1 Enabling Synchronous Operation

When debugging programs, it is convenient to require Xlib to behave synchronously so that errors are reported at the time they occur.

To enable synchronous operation, use the SYNCHRONIZE routine. The client passes the display argument and the onoff argument. The onoff argument passes either a value of zero (disabling synchronization) or a nonzero value (enabling synchronization).

9.13.2 Using the Default Error Handlers

To handle error events when an error event is received, use the SET ERROR HANDLER routine.

Xlib provides an error event data structure that passes information to the SET ERROR HANDLER routine.

The following illustrates the error event data structure:


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

Table 9-13 describes the members of the data structure.

Table 9-13 Error Event Data Structure Members
Member Name Description
type Type of error event being reported
display Display on which the error event occurred
serial Number of requests starting at one sent over the network connection since it was opened
error_code Identifying error code of the failing routine
request_code Protocol representation of the name of the procedure that failed and defined in X11/X.h
minor_code Minor opcode of failed request
resourceid Resource ID

The routines described in this section return Xlib error codes. For a description of the error codes, see the X Window System. The following lists the codes:
BadAccess BadImplementation
BadAlloc BadLength
BadAtom BadMatch
BadColor BadName
BadCursor BadPixmap
BadDrawable BadRequest
BadFont BadValue
BadGC BadWindow
BadIDChoice  

9.13.3 Confirming X Resource Creation

When creating any X resource, such as a window, pixmap, or gc, it is important to note that these routines are asynchronous and do not return errors if the create operation fails. Although Xlib returns a resource ID for these routines, it does not indicate that a valid resource was created by the server.

Use the following method to check if the client has successfully created a resource:

  1. Provide a client-defined error handler and specify it by calling the SET ERROR HANDLER routine.
  2. Call the NEXT REQUEST routine. The NEXT REQUEST routine returns the serial number that Xlib is to use for the next request.
  3. Call the routine to create the resource, such as CREATE PIXMAP.
  4. Call the SYNC routine. The SYNC routine forces all requests in the output buffer to be processed by the server and returns any errors to the error handler.
  5. Use the error handler to compare the serial member of the error event data structure with the serial number returned by the NEXT REQUEST routine. The value of the serial member in the error event data structure reflects the number of the request immediately before the failing call was made. Therefore, if the values are equal, the server has failed to create the resource.


Chapter 10
Using the X Resource Manager

The X resource manager, also referred to as the resource manager in the rest of this chapter, is a database manager that provides a set of tools for specifying client preferences such as color, fonts, and line width.

This chapter describes using the resource manager and includes the following topics:

10.1 Defining Resource Manager Fundamentals

The resource manager is a database manager; however, it operates differently than most database managers. In most systems, the database contains precise specifications; the client then queries the database using imprecise or broad specifications. With the resource manager, a large set of resources can be specified in the database with one imprecise specification. The client queries the resource manager with a precise specification and one value is returned. Thus, the resource manager can be used by clients to return values for color, font names, or other resources.

For example, a client can specify in the resource manager database that all windows should have a blue background but that all windows used for editing text should have a white background. This specification can be done using just two entries in the database: one entry that sets the text-editing window to white and one entry that sets all other windows to blue.

To illustrate how the resource manager works, consider the following example of a simple graphics client called xgr. This client allows the user to draw simple graphic line figures and text using the command buttons at the top of the window. In addition, it provides drawing in three different line widths. Figure 10-1 illustrates the user interface of the client.

Figure 10-1 Interface of Client xgr


Assume that the interface of the client xgr uses a set of windows from the parent window (which includes all client windows) all the way down to the individual command buttons that actually draw the graphics. It is this window hierarchy that provides one method for creating and naming the resources in the database.

It is important to note here that the resource manager imposes no restrictions on the entries in the database. However, if entries in the database are formed logically, then it is easy to specify resources for any portion of the client. Incorrect entries can have unpredictable results.

10.1.1 Names and Classes

Each object that uses the resource manager must have a name and a class. A name is a more specific way of referring to a particular object or window; whereas, the class is more general and can be used for returning values for an entire set, or class, of windows or objects.

The name and the class are built from components at each level of the window hierarchy. Components within a name and a class are separated by periods. Although names and classes can have an arbitrary number of components, each name and class must be fully-qualified. A fully-qualified name has the same number of components as its reciprocal fully-qualified class. Refer to Figure 10-2 for an example of fully-qualified names and classes.

Because names and classes can often contain the same components, the following conventions are used to differentiate between a name and a class:

Although the preceding conventions are not rules, they provide one method to differentiate between names and classes.

Note that in the resource manager names and classes are created by the client and are entirely arbitrary. Section 10.1.2 shows how names and classes can be formed and used.

10.1.2 Forming Names and Classes

To illustrate how names and classes are formed, consider the client xgr from the preceding example. At the top level is the client xgr which forms the first component of the name and the class, xgr and Xgr respectively.

The parent window forms the second component for the name and the class. This window is named main; its class is MainWindow. Therefore, its fully-qualified name is the name of its parent followed by its name, or xgr.main. Its fully-qualified class is the class of its parent followed by its class, or Xgr.MainWindow.

At the next level is the window that contains the buttons that perform the graphic operations. The fully-qualified name of this window is its name, buttons, appended to the name of its parent or xgr.main.buttons. Its fully-qualified class is its class appended to its parent's class, or Xgr.MainWindow.Box.

Figure 10-2 Hierarchy of Names and Classes of the Client xgr


At the lowest level is the set of windows that actually perform the graphics operations. Each has a name such as drawText, or drawEllipse, yet each belongs to the class of windows called Commands. Therefore, the fully-qualified name of the button that draws the text is xgr.main.buttons.drawText and its fully-qualified class is Xgr.MainWindow.Box.Command.

Figure 10-2 shows the hierarchy of the windows and the names and classes of each window.

The resources that any object or window needs are called attributes, and as such have a name and a class. For example, some of the attributes that the client can set for the window named main include height, width, background color, and foreground color. The fully-qualified name of the height attribute for the window main is xgr.main.height. Its class is Xgr.MainWindow.Height.

To illustrate how names and classes differ in their uses, suppose that the client xgr needs to have a white background assigned for the window named draw, yet needs to have a red background for all command buttons. The following entries in Table 10-1 meet these requirements.

Table 10-1 Example of Using a Name and a Class
Entry Explanation
xgr.draw.background: white Within the client named xgr, the window named draw is assigned a white background.
xgr.draw.buttons.Command.background: red Within the client named xgr, all windows that belong to the class Command are assigned a red background. With this one entry, each window that draws the graphics is assigned the color red.

When a client looks up a resource, it passes the complete name and complete class of the resource to a lookup routine. The resource manager then returns the resource value that best matches the name and the class.

10.1.3 Resource Manager Matching Rules

Resources are stored with only partially specified names and classes, using pattern matching constructs. The following rules pertain to individual entries in the database:

To signal a continuation of a line, use the backslash (\) character. Use the \n characters to indicate a new line, for example when using a multiline table such as a translation table. Refer to the VMS DECwindows Guide to Application Programming for more information about translation tables.

The following are examples of resource database entries:


xgr.main.color: blue 
*MainWindow.Color: red 
xgr*Font: -Adobe-New Century Schoolbook-Bold-R-Normal-- \
          *-140-*-*-P-*-ISO8859-1 
xgr*lineWidth.thin: 1 
xgr*lineWidth.medium: 2 
xgr*lineWidth.heavy: 3 

After the lookup routine passes the fully specified name and class, the lookup algorithm then searches the database for the name that most closely matches the full name and class passed by the lookup routine. The algorithm that determines the resource name that matches a given query is the heart of the database.

Table 10-2 lists the rules for the match in order of precedence and an example of each rule.

Table 10-2 Resource Manager Matching Rules
Rule Example
The attribute of the name and the class must match. The queries xgr.main.width (name) and Xgr.MainWindow.Width (class) do not match the database entry: xgr.main: 600. (The entry is missing the attribute, width.)
Database entries with name or class prefixed by a period (.) are more specific than those prefixed by an asterisk (*). The entry xgr.font is more specific than xgr*font. The entry xgr.font will be fetched before xgr*font.
Names are more specific than classes. The entry *main.color is more specific than *MainWindow.Color.
Specifying a name or a class is more specific than omitting either. The entry *MainWindow*Color is more specific than *Color.
Left components are more specific than right components. The entry *xgr*color is more specific than *main*color for the query xgr.main.color.
If neither a period nor an asterisk is specified at the beginning, a period is implicit. The entry xgr.main is identical to .xgr.main.


Previous Next Contents Index