X-Windows
Volume Number: 7
Issue Number: 4
Column Tag: The Cross Developer
X Windows for Mac Programmers
By Paul Hyman, Fullerton, CA
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
X Windows for Mac Programmers
[Paul Hyman is a software engineer with Hughes Aircraft Company in Fullerton,
CA. He is currently writing X window applications on Sun workstations and is
developing demos of proposed software on a Mac using Supercard. He has written
several public domain and shareware applications for the Mac.]
Introduction
Porting programs between windowing systems, particularly between the Mac and
Microsoft Windows on PC’s has become common recently. With the X window system
established as the principal windowing system for Unix workstations, there is
beginning to be interest in porting Macintosh applications to that environment. This
article explains many of the differences between writing an application for the Mac and
for X windows for people who are familiar with Macintosh programming but not with X
windows.
As a sidelight, this article takes a brief look at Apple’s implementation of X
windows under A/UX 2.0. The Mac is, after all, capable of being used as a Unix
workstation, and Apple has done an excellent job of integrating the Mac and Unix (and X)
environments.
The X window system was developed as part of project Athena at MIT. X was the
outgrowth of another project called “W” (for Windows), with the version upgraded
from W to X. Part of project Athena involved finding ways to use graphics on a
network, where programs could run on one machine and display graphics on another.
Since its adoption by industry, X standards are now controlled by the X Consortium, a
group of interested companies.
Basics of X Windows
The X window system is not a complete environment like the Macintosh. There
is, for example, no such thing as a Finder equivalent for managing files and launching
applications or a Chooser for selecting a printer. To perform such functions, users
must rely on the capabilities provided by the operating system of the computer they are
using, or the application must provide these functions.
The original specifications for X windows included nothing regarding user
interfaces. X simply provided a library of routines to handle drawing functions,
window creation and related operations, and event handling. There was nothing
corresponding to the Macintosh user interface toolbox routines provided by the Dialog
manager, Menu manager, etc.
The main reason for the lack of user interface routines was probably that in
order for the system to be accepted by a wide variety of workstation manufacturers, the
implementors of X could not dictate a particular user interface, since whatever they
picked would probably conflict with someone or other’s proprietary user interface.
Recently, however, user interface toolkits have become available for X. Included with
the X release is a library of routines called the X intrinsics. These provide a means to
create Widgets, which are user interface elements such as buttons, text editors,
selection lists, menus, etc. Also included with the X release is the Athena widget set,
which is a set of widgets that illustrate the use of the intrinsics. Although functional,
the Athena widgets are not generally used in commercial programs.
Two commercial widget sets, Open Look and Motif, are much more extensive than
the Athena set and are generally used for commercial applications. In addition to
widgets, Motif and Open Look also provide window managers, which are applications that
allow the user to move and resize windows and provide other useful functions as well.
(In contrast with the Mac, moving and resizing windows is not handled by the
application which owns the window. Instead, a window manager handles this and
notifies the owing application via events when the windows have been changed.)
Although the X standard doesn’t specify anything about user interfaces, Motif and Open
Look do have user interface standards. Motif currently seems to be the most popular
one, and is the one discussed in this article but many vendors are creating both Motif
and Open Look versions of their programs. Just to complicate matters a little bit,
there are two versions of Open Look - an intrinsics based widget set from AT&T, and
the XView toolkit from Sun Micro systems which is not based on the intrinsics.
Clients and Servers
One of the most important characteristics of X windows is that the process which
does the actual drawing (the server process) is separate from the program which is
giving the drawing commands (the client process). They may reside on the same or
different machines, but they are always different processes. This, however, is
invisible to the application programmer. As far as the programmer is concerned, calls
to library routines perform drawing functions and/or return status or event
information, just as on the Mac. The only time that the separation becomes important
is in the case of certain things such as pixmaps, which reside in the server’s memory
and therefore are not directly accessible to the application program. Also, drawing
directly to the video buffer is impossible, since it may reside on another machine. All
inter-client communication must be handled via the server as well, since the clients
may well be on different machines (even different kinds of machines).
The release from MIT contains X servers for many types of workstations. These
servers are considered to be samples, and are written with portability and clarity in
mind, rather than efficiency. Most manufacturers adapt the X servers to their own
machines. The real standard is not the code, but the definitions of the library routines
(called XLIB) which the user (client) programs call, and the protocol which is used to
send the client requests from XLIB to the server and to send responses and event
notifications from the server to the client.
The X and Mac Environments
Many of the calls to XLIB look very much like Quickdraw calls and perform
similar functions. In listing 1 is a program which creates a window, displays the
string “Hello World” with a green rectangle around the letters, and exits when the
mouse is clicked or the letter “Q” is typed. As this program requires no menus, dialog
boxes, or other user interface components, it can be written entirely using XLIB.
Unlike the Mac, there is no single menu bar on the screen. If an application
creates a menu bar, it appears inside an application window.
Windows in X are different in nature from Mac windows. An X window is simply
a rectangular area on the screen, possibly with a simple border around it. It has no
title bar, close box, or other features. X windows have parents, except for the root
window which covers the background of the screen. Windows which are children of the
root window are the most like Macintosh windows. Windows which are children of
other windows are not moveable under window manager control, but are moved along
with their parent windows. Most X applications have lots of windows - in fact every
widget has its own window. Although an X window has no title bar, close box, or other
components, a window manager may add such things to the application windows.
Actually, it doesn’t add these things. Rather it reparents the application’s top window,
making it not a child of the root, but the child of a window created by the window
manager, which also contains windows which provide the title bar and other things. All
of these manipulations are invisible to the application program.
Note that the example programs are written in C. XLIB, the sample servers, and
the X intrinsics are all written in C, and therefore all of the required header files
which define the routines and data types are available for C only. While there may be
vendors supplying bindings for other languages, it would complicate the situation to try
to port an application written in a language other than C to X windows.
As was stated before, an application does not control the size or position of its
windows. This is handled by a special application called a window manager. If no
window manager is running, windows may not be moved or resized. In the program in
listing 1, the program sets up some hints for the window manager, suggesting a size
and position, and passes them in the XCreateSimpleWindow call. The window manager
may or may not pay attention to these hints. The Motif window manager, for example,
has different user-selectable modes. One of these puts the window where the
application requested and uses the application’s suggested size, while another lets the
user select the size and position.
Events
In the program in listing 1, note that no drawing is done until an Expose event is
received. An Expose event is equivalent to a Macintosh Update event. The reason for not
doing any drawing first, is that a window is not necessarily placed on the screen at the
time the request (the XMapRaised call in the example) is made. At the time of the call,
the window manager may allow the user to place the window and it could be a
considerable period of time before the window is actually displayed.
There are many types of X events. The only three this program handles are the
Expose, ButtonPress, and KeyPress. These all have Mac equivalents. The buttonpress
event returns, in addition to the location of the button press, which button was pressed,
although the example program doesn’t bother to check. X assumes a three button
mouse, and the Motif Style Guide assigns functions to each of the buttons.
If you’ve looked ahead at the example program using Motif, you will have noticed
that it looks very different from the first program. Programs written using only XLIB
look similar in structure to Mac programs, with a main event loop. Programs written
using a toolkit, such as Motif, are generally made up of event handling routines which
are registered with the toolkit to be called when specific events happen.
Graphics Operations
Notice the call the XCreateGC in the first sample program. A GC is a Graphics
Context, and it contains much of the same information that a Grafport contains, such as
pen characteristics and color settings. There are several functions, such as
XSetForeground, which alter fields in the GC.
Most of the same drawing functions exist in X and in Quickdraw, although
sometimes there are more options in one environment than the other.
Regions in X consist of areas defined by intersecting rectangles. Arbitrary
regions defined by drawing commands as with Quickdraw are not supported.
Color
Unlike Mac programs, X programs don’t need to worry about whether color is
available or not, since all Xlib routines are available on all X servers. On monochrome
screens, colors are mapped to black or white depending on their darkness. Also, users
can’t change the pixel depth of the screen in the middle of an application the way they
can on the Mac.
User selection of colors is generally handled differently in X programs than in
Mac programs. There is no equivalent of the Color Picker dialog in any of the widget
sets. There is, however, a set of named colors (with corresponding RGB values) in a
text file which is always in a known place, so that applications can read it. While some
systems may augment this list with extra names, there is a basic set of names always
present. The example program uses one of these names (“MediumForestGreen”) in a
call to XAllocNamedColor. It is necessary to call XAllocNamedColor before a color can be
used, since it adds the color to the color map (if it’s not already there) and returns a
pixel value to be used in subsequent calls such as to XSetForeground.
Fonts
The call to XLoadQueryFont is used to get information about a particular font, and
the call to XSetFont establishes it as the current font in the GC. In the sample program,
the font used is 14 point Courier. The fonts have rather long, involved names in most
cases (there are some earlier fonts which exist in only one size and style which have
simple names), and the name includes the font family, the size, and the style. Unlike
the Mac, X will not create different sizes or styles if they do not exist. To use 18 point
helvetica bold, for example, the font name must be known. Fortunately, the names have
a predictable pattern so that it is relatively easy to determine the name, given the font
family name, size, and style.
Printing
One of the big difficulties in using X, in contrast to the Mac, is in the area of
printing. X provides no printing facilities. To print to a postscript printer, an
application has to generate the postscript itself. In addition, choosing which printer to
use may have to be included in the application as well, if the program is to be
user-friendly. Otherwise, the user would have to use commands provided by the
operating system to choose the printer.
Cutting and pasting between applications.
The original X standards did not address inter-client communication, but a
document called the ICCCM (inter-client Communication Conventions Manual) has been
released by the X Consortium. The inter-client communication standards are somewhat
complicated, but basically define methods by which clients can exchange data with each
other through the X server.
When using a widget set such as Motif, application developers generally do not
have to be concerned with how to cut and paste text between applications. The Text
widgets, which are used where Text Edit records would be used in Mac applications, take
care of handling things that affect them, such as character entry and deletion, and
cutting and pasting.
Although transferring text between applications is pretty well defined, there is
no standard picture format, such as PICT, for transferring graphics. Except for
bitmaps, copying and pasting pictures between applications is not possible, unless the
applications are from a single vendor and understand a common format. There is also
no equivalent to the Quickdraw DrawPicture call, and therefore no easy way to save and
re-execute a series of drawing commands.
The preferred method of cutting and pasting is through a process called
Selections, which involves communications between the current owner of a selection
and an application which wants to obtain it. This is in contrast to the Mac clipboard
which passes data between programs without having the programs directly
communicate.
Widgets
Widgets are the user interface building blocks. The widgets in the available
toolkits (Motif, Open Look, and Athena) are written in an object-oriented fashion
(although implemented in C), with classes and subclasses of widgets where the
subclasses inherit behavior and appearance characteristics from their superclasses.
Writing a program using a widget set is different from writing a pure Xlib program, in
that the program generally does not have its own event loop, but makes a call to
XtMainLoop and then exits. XtMainLoop dispatches events, calling appropriate routines
to handle them, until one of the routines causes the program to terminate. Widgets
have routines which are invoked by XtMainLoop when events occur within the widget
window, and therefore widgets take care of handling button presses, key presses, mouse
movements, and other actions which affect them. This is in contrast to typical Mac
programs where the application handles events and calls appropriate routines, such as
Textedit routines, when events happen.
Most widgets allow the programmer to specify callback routines to be called
when certain things happen. For example, pushbutton widgets will call a
programmer-specified routine when the user clicks the mouse inside the push button.
Some widgets don’t handle user actions directly, but serve to manage other
widgets. For example, a Form widget positions its child widgets and rearranges them
when the window it is in is resized. This can be very useful in something such as a
dialog box containing a list, where the user is allowed to resize the dialog box and the
list will enlarge correspondingly, while buttons will not. The actions of the widgets
inside a widget such as a Form when the window is resized are all specified by the
programmer by setting various attributes of the Form and its children. (In the Motif
sample program in listing 2, a bulletin board widget is used. This widget keeps its
children at fixed locations regardless of the window size.) All of the resizing and
moving of widgets when an window is resized is handled without any application code
being called. This sort of thing has no equivalent in the Macintosh environment.
A feature of X which is used extensively by the intrinsics and the widgets based
on them is the use of resources. These are not the same as Mac resources. They are
user-settable attributes which can be changed by editing a text file which specifies the
values for the attributes. Most widgets allow setting such things as colors, patterns,
and fonts via resource specifications, unless the programmer explicitly provides the
values in the code. Allowing changes to the widget attributes without having to change
the source code of the program is a very useful feature, very similar in nature to
allowing changes to the text of menus and dialog boxes on the Mac by using ResEdit.
UIL
One feature provided by Motif which the other widget sets do not have is UIL, the
user interface language. Originally developed by Digital Equipment Corporation for use
in DecWindows, UIL provides a means for the programmer to define the widgets and
their characteristics for a program without embedding the definitions in the program
code. Typically, far fewer UIL statements are needed to define a widget than are
necessary in program code. In addition, the UIL can be changed and recompiled without
the necessity of relinking the program, which can be a big time saver during
development.
Apple’s Implementation of X under A/UX