VMS DECwindows Guide to Xlib (Release 4)
Programming: MIT C Binding
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:
- Provide a client-defined error handler and specify it by calling
the SET ERROR HANDLER routine.
- Call the NEXT REQUEST routine. The NEXT REQUEST routine returns
the serial number that Xlib is to use for the next request.
- Call the routine to create the resource, such as CREATE PIXMAP.
- 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.
- 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:
- Defining the fundamentals of the resource manager---How the
resource manager operates as a database
- Getting the default values --- How to return the default values
defined for a user environment
- Storing resources---How to create a database and store resources in
it
- Retrieving resources from the database---How to look up resources
and obtain values
- Merging and storing databases---How to merge database contents and
write a database to disk
- Using representations for strings---How to use quarks with the
resurce manager
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:
- The initial letter of each component in a name is lowercase.
- The initial letter of each component in a class is uppercase.
- Where a component is made up of two words, the second letter is
capitalized in both cases.
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:
- A period (.) is used to separate immediately adjacent components.
- An asterisk (*) is used to represent any number of intervening
components (including none).
- A trailing period and asterisk are not removed.
- The library supports 100 components in a name or a class.
- Names and classes can be mixed.
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.
|
|