X Application Software Engineering:
Debugging X Input Events
Published in The X Journal, January, 1995.
Copyright © 1995 Kenton Lee. All rights reserved.
Key words: X Window System, X11, Motif widgets, xev, xmon, xscope, events, debugging
Abstract
In November's column, we looked at tools that,
primarily, helped the programmer control and debug the output of X Toolkit
application programs. In this column, we'll look at tools to debug the
input to these programs.
Table Of Contents
- Introduction
- What Are X Events?
- Problems With Events
- A Simple Event Watcher: xev
- Display modes
- Event reports
- xev vs. debuggers
- Other uses for xev
- Limitations of xev
- Complete Event Watchers: xscope
and xmon
- Managing the level of output
- Correlating events and requests
- Obtaining xscope
and xmon
- Conclusion
- References
- The Author
In my November column[1], we looked at editres,
a powerful tool for studying X Toolkit widget resources. editres
is very useful for studying the static part of your user interface (widget
hierarchy and resource specifications), but it does not help very much with
the dynamic part (handling input).
The X server reports input to your client as X events. In this column, we
will take a look at X events and common problems application programmers have
with them. Then, we will take examine some tools that help analyze input
problems: xev, xscope, and xmon.
Events are one of the major components of the X
client-server protocol.[2] In the X protocol, X clients send
requests to the X server. The server sends replies,
errors, and events to its clients.
While the replies and errors received by a client are always the direct
result of requests sent by that client, events are more complex. Some
events are the result (directly or indirectly) of the requests. Others
are the result of user input.
While the X Toolkit does a good job of hiding the X protocol from the
application programmer, a good understanding of events is often very
useful when designing or debugging your applications. In some cases,
the data in an event structure can be directly used by an application: most
widget callback functions return the event structure to the application in
the call data.
The X protocol defines a large number of events. All the Xlib tutorials
and references list them. Some of the more important (to the application
programmer) are:
- pointer button press events
- pointer motion events
- pointer enter and leave window events
- keyboard key press events
- window configuration change (size, position) events
- exposure events
In addition to the event type, each event includes several data fields,
such as the button number and (x, y) coordinates of a button press.
Applications usually react to both the event type and the data in the event.
Why, you might ask, would an application programmer be interested in
events? Application programs based on the X Toolkit usually receive
their input through widget callback functions. When must the application
programmer deal with events?
My answer is that the callback mechanism is robust enough so that
application programmers will only rarely need to debug their applications
at the event level. In those cases, however, good tools will make your
debugging tasks much simpler.
Most problems occur when either:
- your application does not receive an event it is expecting
(e.g., missing a mouse button press event).
- your application receives events it was not expecting
(e.g., multiple exposure events).
- your application was expecting a particular event to contain
different data.
These problems occur most often when you are writing low level code,
such as writing your own widgets. They sometimes also occur when standard
widgets or multiple clients interact in unexpected ways.
In some cases, you can even use events to debug application problems not
related to input. We will discuss this more later.
The simplest and most popular event debugging tool is xev.
xev is distributed in the X Consortium's source code distribution.
xev is a stand alone X client that prints out events that occur on
a window.
xev has two modes. In its default mode, xev creates
its own window, then reports events that occur on that window. For debugging,
a second mode is usually more useful. In this mode, you specify a window ID
on the command line:
xev -id window_id
and xev prints out events that occur on that window. This mode
can tell you what events are occurring on a window in your application. (You
can determine the ID of a window in your application via print messages,
a debugger, or, as we discussed in November, the
editres[1] program.)
When events occur, xev reports them immediately by printing out
the event structure. This immediate reporting allows you to experiment with
different inputs to your application to see which and when (or if)
events occur. If you move the mouse button or press a keyboard key, you should
immediately see a report from xev. If there is no report, no
events were generated on your window.
The details of the event structure should help you figure out why the
event occurred and help you design algorithms for dealing with the
events. Some of the event structures are complex and the programmer
could easily misinterpret the manual's description of them. Seeing
the actual event data should quickly clear up such misunderstandings.
You may also need to find some implementation-specific information
contained in an event. For example, one common way to remap your
keyboard mapping is to use xmodmap to change the mapping from
implementation-specific key codes to portable keysyms. You could dig
up your keyboard manual to find the key codes. I usually just run
xev, press the interesting keys, and see what key codes
xev reports.
You often can generate information similar to that of xev by
using a debugger. You could set a break point in your event loop and
print out each event structure as it arrives. This can be
problematical, however, since the debugger will change the
performance of your application and event-related problems
are often very timing-dependent.
Previously, I mentioned that xev can be useful for debugging
non-event parts of your application. Here's one example. You may be able
to think of others in your development environment.
One common application problem is window layout. If you are using the
X Toolkit, widgets (and their windows) are laid out using complex
algorithms. Occasionally, you will not get the results you want and
the problem will be that certain windows/widgets have incorrect sizes
and/or positions.
As we discussed in November's column, you can ask editres to
show you the borders of a suspect window. Unfortunately,
editres will occasionally get these wrong. editres
looks in the widget structure for size and position information, but, in
some cases (such as due to clipping), these values will not correspond to
what you see on the screen.
xev allows you to go directly to the X server to find window
boundaries. Get the window ID from editres and run xev
on that window ID. Drag your pointer over and around the window. As you
pass over the window's borders, xev will report enter and
leave events. These will tell you the window's exact position.
Unfortunately, xev is not fool proof if you ask it to track
events on a window it does not own (the -id mode). It
receives these events by requesting them with Xlib's
XSelectInput() function. This technique has three
major limitations:
- grabs - If one client activates a server, pointer, or keyboard grab,
then event reporting to all other clients will be affected. xev
will not be able to report some (or all) events, even though the client
activating the grab may be receiving them.
- non-maskable events - The X protocol does not allow certain events
to be reported to clients other than the one that created the event
window. Most of these events deal with selections.
- redirection events - The X protocol allows only one client to
request certain events. xev cannot receive these if another
client is receiving them. These events include window manager
redirection events (e.g., substructure notify on the root window) and
implicit passive grab events (e.g., mouse button presses).
Users of xev must find alternate techniques for studying the above
areas. The xscope and xmon programs, discussed in
the next section, may be helpful.
As mentioned above, the power of xev is limited because its protocol
semantics are slightly different from those of the original X client.
You can avoid these problems by using one of the pseudo-server event
watchers, xscope and xmon.
xscope was available first (X11R3) and is probably still the more
popular program. When you run your X client, you connect it to
xscope, rather than to the X server. xscope passes
on all X protocol your client sends to or receives from the X server.
xscope also prints out the X protocol information to the
standard output.
As you will see, even the smallest X clients will generate a lot of
X protocol. xscope allows you to control the volume, to a certain
extent, by supporting five different detail levels. The three least
detailed levels are probably adequate for all application programmers.
The two most detailed levels are probably only of interest to people
working on the X server or on Xlib.
Unfortunately, even with the detail levels, the amount of output can
be difficult to examine. Most people simply redirect the output to
a file to study later, possibly with the search function of a text
editor or with some pattern analysis (e.g., awk or
perl) scripts.
Another solution to the data volume problem is the xmon program,
which appears in the X11R5 contrib. directory. xmon
works basically the same way as xscope, but adds a graphical
user interface that allows you to specify, at run-time, which request
and event types you want to see.
Since xscope and xmon print out both the requests
and the events, you can now correlate the two. At xscope's
detail level two and above, sequence numbers are included in the output.
All requests include a sequence number, indicating the number of requests
since the client started. Most requests also include a sequence number,
copied from the request that caused the event.
When you match the two sequence numbers, you can find the request that
caused the event. Since the X protocol is normally asynchronous, the
correlation might be difficult to determine without the use of the
sequence numbers. With them, you can easily determine the cause of an
unexpected event.
Obtaining xscope and
xmon
xscope and xmon are not standard parts of
the X Consortium distribution, though some X vendors do include one
or the other with their products. If yours does not, you may FTP the
source code for both programs from the contrib section of X11R5
(both are in contrib-1.tar.Z):
ftp://ftp.x.org/pub/R5/.
While input problems are probably less common than output problems,
I still find that I occasionally need to debug input problems. We have
looked at some common input-related problems and several tools that
you can use to debug them. No one tool is best for everyone. I encourage
you to try them all to see which best meets your data needs and debugging
style.
- Kenton Lee, "Debugging X Toolkit Resources
with editres," The X Journal,
November, 1994.
- Robert Scheifler and James Gettys,
X Window System (3rd edition), Digital Press, 1993.
Kenton Lee is an
independent software consultant specializing in X Window System and
OSF/Motif software development.
He has been developing UNIX graphical user interface software since 1981.
Ken has published over two dozen technical papers on the X Window System.
Most are available over the World Wide Web at
http://www.rahul.net/kenton/bib.html.
Ken may be reached by Internet electronic mail to
kenton @ rahul.net or the World Wide Web at
http://www.rahul.net/kenton/.
For more information on the X Window System, please visit my home page..