A tutorial prepared for SciC 8011, Spring 1995, by
Anybody who uses a modern Unix based workstation for scientific visualization has almost certainly used programs running under X. While little technical knowledge is required to use today's point-and-click interfaces, a little knowledge about what goes on behind the scenes can make things less imposing and mysterious.
In scientific visualization, like other fields, we are often faced with the age-old decision to ``build or buy.'' To make reasonable decisions, we must have a realistic idea of the amount of time required to ``build'' a portable, graphical program.
Hopefully, this paper will provide readers with a starting point for this understanding, and make them go back and re-examine existing software packages should they get the urge to write a custom X11 based program.
X is a system for implementing a window-based user interface on bit-mapped displays. More technically, it is a specification for a high level communications protocol that is used between two programs. One of these programs is called the ``server'' and does the actually drawing on the screen and receives the raw input from the keyboard and mouse. The other program is called the ``client'' and this is where the useful work gets done. These programs may be on different computers, or they may be on the same computer.
It is important to notice that the location of the client and server are reversed compared to many client/server situations. This often causes confusion among people new to X. For example, you have a Sun workstation at your desk: you are running a CAD/simulation program on a large computer somewhere else and displaying the user interface on your desktop Sun. The Sun is running the server (it's what talks to the keyboard, mouse, and graphics hardware). The CAD program on the large computer is the ``client'' program.
The client requests that graphical operations be performed and the server provides those services.
The X protocol specification defines what goes back and forth between those two programs. The X protocol is usually implemented as a layer on top of another transport layer such as TCP/IP.
Printing is another area where the X specifications are mute. X does not provide any printing or hardcopy services as does Microsoft Windows or the Mac OS tool box. In the absence of any other standard, postscript has been largely adopted as a de facto standard for hardcopy output by designers of X applications.
The server receives input from the keyboard and mouse. These are passed as ``events'' to the appropriate client program. The method used to decide which window should receive input events various depending on the window manager (which is actually just another client). Typical events are key-presses, mouse movements and mouse button press/release.
These allow a client to tell the server to create or destroy a ``window'' which is a rectangular area on the screen. Windows may be nested hierarchically within other windows. Various operations may be performed on windows (set or query the size and position, for example).
The client can request that the server draw lines, rectangles, arcs, dots, and polygons. The color, line-width, and fill style are specified by the client. X11 also supports various bitmap operations [often called ``bitblt'' operations (short for bit block transfer] that can be performed on regions of windows.
The client can request that text strings be ``drawn'' into a window at a particular position using a specified font. Before this can be done, the client must tell the server to load the font to be used. The client can request information about what fonts are available and also about sizes and parameters of loaded fonts.
A request packet is sent by the client to the server to ask that the server perform some action or return some information.
A reply packet is sent by the server to the client in response to a request from the server. Not all requests generate replies.
An event packet is sent by the server to the client to inform it of user input or some other happening about which it might want to do something (for example a window was re-sized or a previously obscured window was uncovered).
An error packet is sent by the server to the client to inform it that a request was not valid. Since requests are queued, the error might not be discovered until after several more requests have been queued by the client.
It is theoretically possible to write a client program using just the standard C run-time library routines. The client would have to open a socket-based connection to a server, construct requests and write them to the socket and interpret the reply, event, and error error packets. Though possible, this is unnecessary since there are libraries available that contain routines to interface to an X server using the X protocol. The most common such library is called ``Xlib'' and is intended to be called from the C programming language. The definitive books on Xlib are probably those published by O'Reilly and Associates: Xlib Programming Manual and Xlib Reference Manual. Though Xlib hides the details of communicating with the server, it does little else. The functions provided by Xlib perform only the basic tasks described above. Even a simple program written using nothing but Xlib can require large amounts of code. A ``hello world'' program [the ``basicwn'' program shown as an example in by Adrian Nye's Xlib Programming Manual] whose output is shown below requires 200 lines of C code.
This program does nothing other than create a window, check the window size and the size of the root display, display the text shown, and wait for any key or mouse button before exiting. The source code for this program is available for the morbidly curious.
As you might guess, writing an entire application using Xlib directly is not practical. The client application must specify every window to be drawn and every bit of text or line to be drawn. The application must then read events from the the server and process them. When a window is resized, the application must take appropriate actions and redraw everything in the correct places. What is needed is a higher level interface that hides much of the gritty details from the application programmer.
All of these toolkits provide an additional level of abstraction. Rather than dealing with windows, lines, text strings, key-presses and mouse buttons, the applications programmer deals with objects called ``widgets'' that would be recognizable to the end user: list-boxes, text-entry fields, buttons, pop-up menus, etc. The application programmer now writes code to create these high-level objects and to specify what action is to be taken when a button is pressed or a menu entry is selected. The toolkits handle most (if not all) of the X events, and invoke the call-back routines provided by the application as required.
Though toolkits provide ways for users to define new widgets, many applications are written using only predefined widgets Much of the rest contain a single customized widget along with predefined widgets.
The typical Athena look is exemplified by rectangular monochrome buttons and an overall flat, monochrome look similar to (but uglier than) the original Macintosh interface. [Later extensions to Athena widgets added support for ``shaped'' buttons which allowed for Macintosh-like buttons with rounded corners.] While the Athena widgets can be seen used in much of the free software available on the net, they are rarely used in commercial products which tend to use ``prettier'' toolkits.
The output of a small application using Xt and the Athena widgets is shown above. This application displays a main window containing a label widget at the top containing the text ``Pick one'' and below that two buttons. If the left button is pressed, ``Hi there'' is written to stdout; if the right button is pressed, the program exits. This program took 43 lines of C code and is available for examination by clicking here. This is obviously an improvement over the Xlib program since it takes significantly fewer lines of code even though the application is more complex.
The Motif look and feel is shown by a dialog box below:
One of the oft-cited differences in philosophy between Motif and OPEN LOOK involve the movement of the mouse pointer on the screen. Using the Motif library, the mouse pointer only moves when the user moves the mouse. The OPEN LOOK widgets will move the mouse pointer independently. In X parlance this is known as ``warping'' the pointer. This may seem like a trivial point, but many users strongly object to having the mouse pointer moved when they didn't move the mouse. [I happen to agree with them. I find that having the mouse pointer jump to another portion of the screen on its own is very jarring and disrupts my already fragile thought processes. I've been told recently that XView's pointer warping "feature" can be disabled by the user.]
Tcl is a string-based, interpreted language similar to a Unix ``shell'' language. Up to this point, all of the toolkits that have been discussed were for use by C programs. Tk, however, was designed to be used with an interpreter, and all communication between the Tk toolkit and the user program is done with strings rather than C language data structures. Since its original use with the Tcl interpreter, the Tk toolkit has been adapted for use with interpreters for other languages including scheme, python, and perl.
Tk was designed to have a ``look and feel'' very similar to Motif, and users switching back forth between Motif and Tk applications will not notice paradigm differences the way they would switching between OPEN LOOK and either Motif or Tk.
The Tk toolkit provides a very high level of abstraction and the user doesn't see any of the details of X11. A simple application can be written in just a few lines of code. The Xt/Athena program was re-written using the STk Scheme interpreter that incorporates the Tk toolkit. The application window produced is shown here:
The scheme version looks like this:
Originally, the intended use for Tcl/Tk was to provide an easy way to program a user interface (either graphical using Tk or command-line using Tcl alone). The real work in the application was done by C language routines that implemented application specific Tcl commands which were invoked by the Tcl based user-interface. This allowed a set of basic blocks to be implemented in C and then they could be ``glued'' together using Tcl.
However, the popularity of Tcl has resulted in fairly large
applications being written solely in Tcl/Tk with little or no
additional C coding. Though Tcl is the most popular language that has
been mated with Tk, some prefer a more powerful or general programming
language like scheme. One of the drawbacks of Tcl is that all data is
stored as strings --- thus the interpreter is roughly an order of
magnitude slower than a language like scheme. While the speed of the
Tcl interpreter is quite adequate for use as a user interface, it's a
bit slow if any intensive computation is to be done. Both Tcl/Tk and
STk are free software packages that run on most Unix/X11 systems. The
standard reference for Tcl/Tk is John Ousterhout's book Tcl and the
Tk Toolkit.
STk was developed by Erick Gallesio at the University
of Nice in France. The
STk FAQ is available
via WWW, and the software can be ftp'd from ftp.cs.umn.edu/pub/misc/STk.
Custom and Add-on Widgets
No matter what toolkit you choose, there is a distinct possibility that the
standard widgets either just won't do what you want or the performance is so
poor that something else must be done. That something else is buying or
writing a new widget. There are available commercial add-on packages of
widgets for some toolkits. These widgets offer some very sophisticated,
high-level functionality. Recently, add-on widget packages that do
moderately sophisticated rendering have become available. Some of the
products seen advertised include ``XRT Widgets'' from KL Group and the ``Generic Logic Toolkit''
from Generic Logic.
Or, if you've got more time/money than you can find a use for, you can write your own custom widget. Toolkits generally provide a way for the user to create a new widget. This is generally done in an ``object oriented'' way based on one of the existing widgets:
Even with a high level toolkit like Tk, a full-featured user interface for a non-trivial application requires a significant amount of effort. Writing a significant user interface using Xlib would be masochistic at best and futile at worst.