Don Hopkins, ≈1994
If the designers of X-Windows built cars, there would be no fewer than five steering wheels hidden about the cockpit, none of which followed the same principles — but you'd be able to shift gears with your car stereo. Useful feature, that.
— Marus J. Ranum, Digital Equipment Corporation
X-Windows is the Iran-Contra of graphical user interfaces: a tragedy of political compromises, entangled alliances, marketing hype, and just plain greed. X-Windows is to memory as Ronald Reagan was to money. Years of “Voodoo Ergonomics” have resulted in an unprecedented memory deficit of gargantuan proportions. Divisive dependencies, distributed deadlocks, and partisan protocols have tightened gridlocks, aggravated race conditions, and promulgated double standards.
X has had its share of $5,000 toilet seats — like Sun's Open Look clock tool, which gobbles up 1.4 megabytes of real memory! If you sacrificed all the RAM from 22 Commodore 64s to clock tool, it still wouldn't have enough to tell you the time. Even the vanilla X11R4 “xclock” utility consumed 656K to run. And X's memory usage is increasing.
X-Windows started out as one man's project in an office on the fifth floor of MIT's Laboratory for Computer Science. A wizardly hacker, who was familiar with W, a window system written at Stanford University as part of the V project, decided to write a distributed graphical display server. The idea was to allow a program, called a client, to run on one computer and allow it to display on another computer that was running a special program called a window server. The two computers might be VAXes or Suns, or one of each, as long as the computers were networked together and each implemented the X protocol.
[Footnote: We have tried to avoid paragraph-length footnotes in this book, but X has defeated us by switching the meaning of client and server. In all other client/server relationships, the server is the remote machine that runs the application (i.e., the server provides services, such as database service or computational service). For some perverse reason that's better left to the imagination, X insists on calling the program running on the remote machine “the client.” This program displays its windows on the “window server.” We're going to follow X terminology when discussing graphical client/servers. So when you see “client” think “the remote machine where the application is running,” and when you see “Server” think “the local machine that displays output and accepts user input.”]
X was designed to run three programs: xterm, xload, and xclock. (The idea of a window manager was added as an afterthought, and it shows.) For the first few years of its development at MIT, these were, in fact, the only programs that ran under the window system. Notice that none of these program have any semblance of a graphical user interface (except xclock), only one of these programs implements anything in the way of cut-and-paste (and then, only a single data type is supported), and none of them requires a particularly sophisticated approach to color management. Is it any wonder, then, that these are all areas in which modern X falls down?
Ten years later, most computers running X run just four programs: xterm, xload, xclock, and a window manager. And most xterm windows run Emacs! X has to be the most expensive way ever of popping up an Emacs window. It sure would have been much cheaper and easier to put terminal handling in the kernel where it belongs, rather than forcing people to purchase expensive bitmapped terminals to run character-based applications. On the other hand, then users wouldn't get all of those ugly fonts. It's a trade-off.
X gave Unix vendors something they had professed to want for years: a standard that allowed programs built for different computers to interoperate. But it didn't give them enough. X gave programmers a way to display windows and pixels, but it didn't speak to buttons, menus, scroll bars, or any of the other necessary elements of a graphical user interface. Programmers invented their own. Soon the Unix community had six or so different interface standards. A bunch of people who hadn't written 10 lines of code in as many years set up shop in a brick building in Cambridge, Massachusetts, that was the former home of a failed computer company and came up with a “solution:” the Open Software Foundation's Motif.
What Motif does is make Unix slow. Real slow. A stated design goal of Motif was to give the X Window System the window management capabilities of HP's circa-1988 window manager and the visual elegance of Microsoft Windows. We kid you not.
Recipe for disaster: start with the Microsoft Windows metaphor, which was designed and hand coded in assembler. Build something on top of three or four layers of X to look like Windows. Call it “Motif.” Now put two 486 boxes side by side, one running Windows and one running Unix/Motif. Watch one crawl. Watch it wither. Watch it drop faster than the putsch in Russia. Motif can't compete with the Macintosh OS or with DOS/Windows as a delivery platform.
One of the fundamental design goals of X was to separate the window manager from the window server. “Mechanism, not policy” was the mantra. That is, the X server provided a mechanism for drawing on the screen and managing windows, but did not implement a particular policy for human-computer interaction. While this might have seemed like a good idea at the time (especially if you are in a research community, experimenting with different approaches for solving the human-computer interaction problem), it can create a veritable user interface Tower of Babel.
If you sit down at a friend's Macintosh, with its single mouse button, you can use it with no problems. If you sit down at a friend's Windows box, with two buttons, you can use it, again with no problems. But just try making sense of a friend's X terminal: three buttons, each one programmed a different way to perform a different function on each different day of the week — and that's before you consider combinations like control-left-button, shift-right-button, control-shift-meta-middle-button, and so on. Things are not much better from the programmer's point of view.
As a result, one of the most amazing pieces of literature to come out of the X Consortium is the “Inter Client Communication Conventions Manual,” more fondly known as the “ICCCM”, “Ice Cubed,” or “I39L” (short for “I, 39 letters, L”). It describes protocols that X clients ust use to communicate with each other via the X server, including diverse topics like window management, selections, keyboard and colormap focus, and session management. In short, it tries to cover everything the X designers forgot and tries to fix everything they got wrong. But it was too late — by the time ICCCM was published, people were already writing window managers and toolkits, so each new version of the ICCCM was forced to bend over backwards to be backward compatible with the mistakes of the past.
The ICCCM is unbelievably dense, it must be followed to the last letter, and it still doesn't work. ICCCM compliance is one of the most complex ordeals of implementing X toolkits, window managers, and even simple applications. It's so difficult, that many of the benefits just aren't worth the hassle of compliance. And when one program doesn't comply, it screws up other programs. This is the reason cut-and-paste never works properly with X (unless you are cutting and pasting straight ASCII text), drag-and-drop locks up the system, colormaps flash wildly and are never installed at the right time, keyboard focus lags behind the cursor, keys go to the wrong window, and deleting a popup window can quit the whole application. If you want to write an interoperable ICCCM compliant application, you have to crossbar test it with every other application, and with all possible window managers, and then plead with the vendors to fix their problems in the next release.
In summary, ICCCM is a technological disaster: a toxic waste dump of broken protocols, backward compatibility nightmares, complex nonsolutions to obsolete nonproblems, a twisted mass of scabs and scar tissue intended to cover up the moral and intellectual depravity of the industry's standard naked emperor.
Using these toolkits is like trying to make a bookshelf out of mashed potatoes.
- Jamie Zawinski
X is a colletion of myths that have become so widespread and so prolific in the computer industry that many of them are now accepted as “fact,” without any thought or reflection.
At the mere mention of network window systems, certain propeller heads who confuse technology with economics will start foaming at the mouth about their client/server models and how in the future palmtops will just run the X server and let the other half of the program run on some Cray down the street. They've become unwitting pawns in the hardware manufacturers' conspiracy to sell newer systems each year. After all, what better way is there to fore suers to upgrade their hardware than to give them X, where a single application can bog down the client, the server, and the network between them, simultaneously!
The database client/server model (the server machine stores all the data, and the clients beseech it for data) makes sense. The computation client/server model (where the server is a very expensive or experimental supercomputer, and the client is a desktop workstation or portable computer) makes sense. But a graphical client/server model that slies the interface down some arbitrary middle is like Solomon following through with his child-sharing strategy. The legs, heart, and left eye end up on the server, the arms and lungs go to the client, the head is left rolling around on the floor, and blood spurts everywhere.
The fundamental problem with X's notion of client/server is that the proper division of labor between the client and the server can only be decided on an application-by-application basis. Some applications (like a flight simulator) require that all mouse movement be sent to the application. Others need only mouse clicks. Still others need a sophisticated combination of the two, depending on the program's state or the region of the screen where the mouse happens to be. Some programs need to update meters or widgets on the screen every second. Other programs just want to display clocks; the server could just as well do the updating, provided that there was some way to tell it to do so.
The right graphical client/server model is to have an extensible server. Application programs on remote machines can download their own special extension on demand and share libraries in the server. Downloaded code can draw windows, track input eents, provide fast interactive feedback, and minimize network traffic by communicating with the application using a dynamic, high-level protocol.
As an example, imagine a CAD application built on top of such an extensible server. The application could download a program to draw an IC and associate it with a name. From then on, the client could draw the IC anywhere on the screen simply by sending the name and a pair of coordinates. Better yet, the client an download programs and data structures to draw the whole schematic, which are called automatically to refresh and scroll the window, without bothering the client. The user can drag an IC around smoothly, without any network traffic or context switching, and the server sends a single message to the client when the interaction is complete. This makes it possible to run interactive clients over low-speed (that is, slow-bandwidth) communication lines.
Sounds like science fiction? An extensible window server was precisely the strategy taken by the NeWS (Network extensible Window System) window system written by James Gosling at Sun. With such an extensible system, the user interfae toolkit becomes an extensible server library of classes that clients download directly into the server (the approach taken by Sun's TNT Toolkit). Toolkit objects in different applications share common objects in the server, saving both time and memory, and reating a look-and-feel that is both consistent aross applications and customizable. With NeWS, the window manager itself was implemented inside the server, eliminating network overhead for window manipulation operations — and along with it the race conditions, context switching overhead, and interaction problems that plague X toolkits and window manager.
Ultimately, NeWS was not economically or politically viable because it the
very problems that X was designed to create.
Graphical interfaces can only paper over misdesigns and kludges in the underlying operating system; they can't eliminate them.
The “drag-and-drop” metaphor tires to cover up the Unix file system, but so little of Unix is designed for the desktop metaphor that it's just one kludge on top of another with little holes and sharp edges popping up everywhere. Maybe the “sag-and-drop” metaphor is more appropriate for such ineffective and unreliable performance.
A shining example is Sun's Open Windows File Manager, which goes out of its way to display ore dump files as cute little red bomb icons. When you double-click on the bomb, it runs a text editor on the core dump. Harmless, but not very useful. But if you intuitively drag and drop the bomb on the DBX Debugger Tool, it does exactly what you'd expect if you were a terrorist: it ties the entire system up, as the core dump (including a huge unmapped gap of zeros) is pumped through the server and into the debugger text window, which inflates to the maximum capacity of swap space, then violently explodes, dumping an even bigger core file in place of your original one, filling up the entire file system, overwhelming the file server, and taking out the File Manager with shrapnel. (This bug has since been fixed.)
But that's not all: the File Manager puts even more power at your fingertips if you run it as root! When you drag and drop a directory onto itself, it beeps and prints “rename: invalid argument” at the bottom of the window, then instantly deletes the entire directory trwe without bothering to update the graphical directory browser.
The following message illustrates the X approach to “security through obscurity”:
Date: Wed, 30 Jan 91 15:35:46 -0800 From: David Chapman <firstname.lastname@example.org> To: UNIX-HATERS Subject: MIT-MAGIC-COOKIE-1
For the first time today I tried to use X for the purpose for which it was intended, namely cross-network display. So I got a telnet window from boris, where I was logged in and running X, to akbar, where my program runs. Ran the program and it dumped core. Oh. No doubt there's some magic I have to do to turn cross-network X on. That's stupid. OK, ask the unix wizard. You say “setenv DISPLAY boris:0”. Presumably this means that X is too stupid to figure out where you are coming from, or unix is too stupid to tell it. Well, that's unix for you. (Better not speculate about what the 0 is for.)
Run the program again. Now it tells me that the server is not authorized to talk to the client. Talk to the unix wizard again. Oh, yes, you have have to run xauth, to tell it that it's OK for boris to talk to akbar. This is done on a per-user basis for some reason. I give this ten seconds of thought: what sort of security violation is this going to help with? Can't come up with any model. Oh, well, just run xauth and don't worry about it. xauth has a command processor and wants to have a long talk with you. It manipulates a .Xauthority file, apparently. OK, presumably we want to add an entry for boris. Do:xauth> help add add dpyname protoname hexkey add entry
Well, that's not very helpful. Presumably dpy is unix for “display” and protoname must be… uh… right, protocol name. What the hell protocol am I supposed to use? Why should I have to know? Well, maybe it will default sensibly. Since we set the DISPLAY variable to “boris:0”, maybe that's a dpyname.xauth> add boris:0 xauth: (stdin):4 bad "add" command line
Great. I suppose I'll need to know what a hexkey is, too. I thought that was the tool I used for locking the strings into the Floyd Rose on my guitar. Oh, well, let's look at the man page.
I won't include the whole man page here; you might want to man xauth yourself, for a good joke. Here's the explanation of the add command:add displayname protocolname hexkey An authorization entry for the indicated display using the given protocol and key data is added to the authorization file. The data is specified as an even-lengthed string of hexadecimal digits, each pair representing one octet. The first digit gives the most significant 4 bits of the octet and the second digit gives the least significant 4 bits. A protocol name consisting of just a single period is treated as an abbreviation for MIT-MAGIC-COOKIE-1.
This is obviously totally out of control. In order to run a program across the f���ing network I'm supposed to be typing in strings of hexadecimal digits which do god knows what using a program that has a special abbreviation for MIT-MAGIC-COOKIE-1?? And what the hell kind of a name for a network protocol is THAT? Why is it so important that it's the default protocol name?
F��� this shit.
Obviously it is Allah's will that I throw the unix box out the window. I submit to the will of Allah.
Anybody who has ever used X knows that Chapman's error was trying to use xauth in the first place. he should have known better. (Blame the victim, not the program.)
…And so is a molten blob of pig iron. But it's getting better; at least now you don't hasve to use your bare hands. Hewlett-Packard's Visual User Environment is so cutting-edge that it even has an icon you can click on to bring up the resource manager: it pops up a vi on your .Xdefaults file! Quite a labor-saving contraption, as long as you're omniscient enough to understand X defaults and archaic enough to use vi. The following message describes the awesome flexibility and unbounded freedom of expression that X defaults fail to provide.
Date: Fri, 22 Feb 91 08:17:14 -0800 From: email@example.com (Gardner Cohen)I guess josh just sent you mail about .Xdefaults. I'm interested in the answer as well. How do x programs handle defaults? Do they all roll their own?
If they're xt, they follow some semblance of standards, and you can walk the widget tree of an running application to find out what there is to modify. If they're not Xt, they can do any damn thing they want. They can XGetDefault, which doesn't look at any class names, and doesn't notice command line -xrm things.
Figuring out where a particular resource value is for a running application is much fun, as resource can have come from any of the following: (there is a specified order for this, which has changed from r2 to r3 to r4)
.Xdefaults (only if they didn't xrdb something)
command line -xrm 'thing.resource: value'
xrdb, which the user runs in .xsession or .xinitrc; this program runs cpp on the supplied filename argument, so shit can have been #included from another planet. Oh, and it #defines COLOR and a few other things as appropriate, so you better know what kind of display it's running on.
file name, pointed to by XENVIRONMENT
file name that's the class name of the application (usually completely non-intuitively generated: XParty for xparty, Mwm for mwm, XRn for xrn, etc) in the directory /usr/lib/X11/app-defaults (or the directory pointed to by the XAPPLRESDIR environment variable). The default for this directory may have been changed by whoever built and installed the x libraries.
Or, the truly inventive program may actively seek out and merge resource databases from other happy places. The Motifified xrn posted recently had a retarded resource editor which drops modified resources in files in the current directory as well as in the user's home. On startup, it happily looks all over the place for amusing looking file names to load, many of them starting with dots so they won't 'bother' you when you list your files.
Or, writers of WCL based applications can load resource files that actually generate new widgets with names specified in those (or other) resource files.
What this means is that the smarter-than-the-average-bear user who actually managed to figure out that
is the resource to change the font in his snot application, could be unable to figure out where to put it. Suzie sitting in the next cubicle will tell him, “just put it in your .Xdefaults”, but if he happens to have copied Fred's .xsession, he does an xrdb .xresources, so .Xdefaults never gets read. Susie either doesn't xrdb, or was told by someone once to xrdb .Xdefaults. She wonders why when she edits .Xdefaults, the changes don't happen until she 'logs out', since she never reran xrdb to reload the resources. Oh, and when she uses the NCD from home, things act `different’, and she doesn't know why. “It's just different sometimes.”
Joe Smartass has figured out that XAPPLRESDIR is the way to go, as it allows him to have separate files for each application. But he doesn't know what the class name for this thing is. He knows his copy of the executable is called snot, but when he adds a file Snot or XSnot or Xsnot, nothing happens. He has a man page which forgot to mention the application class name, and always describes resources starting with '*', which is no help. He asks Gardner, who fires up emacs on the executable, and searches for (case insensitve) snot, and finds a few SNot strings, and suggests that. It works, hooray. He figures he can even use SNot*fontList: micro to change all the fonts in the application, but finds that a few widgets don't get that font for some reason. Someone points out that he has a line in his .xresources (or was it a file that was #included in .xresources) of the form *f�cked*fontList: 10x22, which he copied from Steve who quit last year, and that of course that resources is 'more specific' than his, whatever the f��� that means, so it takes precedence. Sorry, guy. He can't even remember what application that resource was supposed to change anymore. Too bad.
Sigh. It goes on and on. Try to explain to someone how to modify some behavior of the window manager, with having to re-xrdb, then select the window manager restart menu item (which most people don't have, as they copied the guy next door's .mwmrc), or logging out. Which file do I have to edit? .mwmrc? Mwm? .Xdefaults? .xrdb? .xresources? .xsession? .xinitrc? .xinitrc.ncd?
Why doesn't all this work the way I want? How come when I try to use the workstation sitting next to mine, some of the windows come up on my workstation? Why is it when I rlogin to another machine, I get these weird X messages and core dumps when I try to run this application? How do I turn this autoraising behavior off? I don't know where it came from, I just #included Bob's color scheme file, and everything went wrong, and I can't figure out why!
SOMEBODY SHOOT ME I'M IN HELL!!!
…And Iran-Contra wasn't Arms for Hostages.
Even if you can get an X program to compile, there's no guarantee it'll work with your server. If an application requires an X extension that your server doesn't provide, then it fails. X applications can't extend the server themselves — the extension has to be compiled and linked into the server. Most interesting extensions actually require extensive modification and recompilation of the X server itself, a decidedly nontrivial task. The next message tells how much brain-searing, eye-popping fun compiling “portable” X server extensions can be:
Date: Wed 4 Mar 92 02:53:53 PST X-Windows: Boy, Is my Butt Sore From: Jamie Zawinski [firstname.lastname@example.org] To: UNIX-HATERS Subject: X: or, How I Learned to Stop Worring and Love the Bomb
Don't ever believe the installation instructions of an X server extension. Just don't, it's an utter waste of time. You may be thinking to your self, “I'll just install this piece of code and recompile my X server and then X will be JUST a LITTLE BIT less MORONIC; it'll be EASY. I'll have worked around another STUPID MISDESIGN, and I'll be WINNING.” Ha! Consider whether chewing on glass might have more of a payoff than what you're about to go through.
After four hours of pain, including such loveliness as a dozen directories in which you have to make a symlink called “X11” pointing at wherever the real X includes are, because the automatically-generated makefiles are coming out with stuff like:-I../../../../../../include
or, even better,-I../../.././../mit/./../../../include
and then having to hand-hack these automatically-generated makefiles anyway because some random preprocessor symbols weren't defined and are causing spurious "don't know how to make" errors, and then realizing that makedepend, which you don't really care about running anyway, is getting errors because the extension's installation script made symlinks to directories instead of copies, and .. doesn't WORK with symlinks, and and and …
You'll finally realize that the only way to compile anything that's a basic part of X is to go to the top of the tree, five levels higher than the executable that you actually want to generate, and say "make Everything". Then come back an hour later when it's done making the MAKEFILES to see if there were any actual COMPILATION problems.
And then you'll find yourself asking questions like, "why is it compiling that? I didn't change that, what's it DOING?"
And don't forget that you HAVE to compile ALL of PEX, even though none of it actually gets linked in to any executables that you'll ever run. This is for your OWN GOOD!
And then you'll realize what you did wrong, of course, you'll realize what you should have done ALL ALONG:all:: $(RM) -rf $(TOP)
But BE CAREFUL! That second line can't begin with a tab.
On the whole, X extensions are a failure. The notable exception that proves the rule is the Shaped Window extension, which was specifically designed to implement round clocks and eyeballs. But most application writers just don't bother using proprietarty extensions like Display PostScript, because X terminals and MIT servers don't support them. Many find it too much of a hassle to use more ubiquitous extensions like shared memory, double buffering, or splines: they still don't work in many cases, so you have to be prepared to do without them. If you really don't need the extension, then why complicate your code with the special cases? And most applications that do use extensions just assume they're supported and bomb if they're not.
The most that can be said about the lowest-common-denominator approach that X takes to graphics is that it levels the playing field, allowing incredibly stupid companies to jump on the bandwagon and sell obsolete junk that's just as unusable as high-end brand-name workstations:
Date: Wed 10 Apr 91 08:14:16 EDT From: Steve Strassmann <email@example.com> To: UNIX-HATERS Subject: the display from hell
I have a “window system” on my unix box. You see, in the unix world, “system” means “a bunch of unrelated programs.” But that's not what I want to talk about here today. I want to talk about overlay planes.
My HP 9000/835 console has two 19'' color monitors, and some extremely expensive Turbo SRX graphics hardware to drive them. You'd think that I could simply tell X windows that it has two displays, the left one and the right one, but that would be unthinkably simple. After all, if toys like Macintoshes can do this, unix has to make it much more difficult to prove how advanced it is.
So, what I really have is two display devices, /dev/crt0 and /dev/crt1. No, sorry, I lied about that.
You see, the Turbo SRX display has a graphics plane (with 24 bits per pixel) and an overlay plane (with 4 bits per pixel). The overlay plane is for things like, well, window systems, which need things like cursors, and the graphics plane is to draw 3D graphics. So I really need four devices:/dev/crt0 --- the graphics plane of the right monitor /dev/crt1 --- the graphics plane of the left monitor /dev/ocrt0 --- the overlay plane of the right monitor /dev/ocrt1 --- the overlay plane of the left monitor
No, sorry, I lied about that.
/dev/ocrt0 only gives you 3 out of the 4 overlay bits. The fourth bit is reserved exclusively for the private use of federal emergency relief teams in case of a national outbreak of Pixel Rot. If you want to live dangerously and under threat of FBI investigation, you can use /dev/o4crt0 and /dev/o4crt1 in order to really draw on the overlay planes. So, all you have to do is tell X windows to use these o4 overlays, and you can draw graphics on the graphics plane.
No, sorry, I lied about that.
X will not run in these 4 bit overlay planes. This is because I'm using Motif, which is so sophisticated it forces you to put a 1'' thick border around each window in case your mouse is so worthless you can't hit anything you aim at, so you need widgets designed from the same style manual as the runway at Moscow International Airport. My program has a browser that actually uses different colors to distinguish different kinds of nodes. Unlike a PC Jr, however, this workstation with $150,000 worth of 28 bits-per-pixel supercharged display hardware cannot display more than 16 colors at a time. If you're using the Motif self-abuse kit, asking for the 17th color causes your program to crash horribly.
So, thinks I to myself cleverly, I shall run X windows on the graphics plane. This means X will not use the overlay planes, which have special hardware for cursors. This also means I cannot use the super cool 3D graphics hardware either, because in order to draw a cube, I would have to “steal” the frame buffer from X, which is surly and uncooperative about that sort of thing.
What it does give me, however, is a unique pleasure. The overlay plane is used for /dev/console, which means all console messages get printed in 10 Point Troglodyte Bold, superimposed in white over whatever else is on my screen, like for example, a demo that I may be happen to be giving at the time. Every time anyone in the lab prints to the printer attached to my machine, or NFS wets its pants with a timeout, or some file server threatens to go down in only 3 hours for scheduled maintenance, another message goes onto my screen like a court reporter with Turett's syndrome.
The usual X commands for refreshing the screen are helpless to remove this incontinence, because X has no access to the overlay planes. I had to write a program in C to be invoked from some xterm window that does nothing but wipes up after the mess on the overlay planes.
My super 3D graphics, then, runs only on /dev/crt1, and X windows runs only on /dev/crt0. Of course, this means I cannot move my mouse over to the 3d graphics display, but as the HP technical support person said “Why would you ever need to point to something that you've drawn in 3D?”
Of course, HP claims X has a mode which allows you to run X in the overlay planes and “see through” to the graphics planes underneath. But of course, after 3 months of calls to HP technical support, we agreed that that doesn't actually work with my particular hardware configuration. You see, I have the top-of-the-line Turbo SRX model (not one, but two on a single workstation!), and they've only tested it on the simpler, less advanced configurations. When you've got a hip, forward-thinking software innovator like Hewlett-Packard, they think running X windows release 2 is pretty advanced.
X is extremely device dependent because all X graphics are specified in pixel coordinates. graphics drawn on different resulution screens come out at different sizes, so you have to scale all the coordinates yourself if you want to draw at a ertain size. Not all screens have square pixels: unless you don't mind rectangular squares and oval circles, you also have to adjust all coordinates according to the pixel aspect ratio.
A task as simple as filing and stroking shapes is quite complicated because of X's bizarre pixel-oriented imaging rules. When you fill a 10x10 square with XFillRectangle, it fills the 100 pixels you expect. But you get extra “bonus pixels” when you pass the same arguments to XDrawRectangle, because it actually draws an 11x11 square, hanging out one pixel below and to the right!!! If you find this hard to believe, look it up in the X manual yourself: Volume 1, Section 6.1.4. The manual patronizingly explains how easy it is to add 1 to the x and y position of the filled rectangle, while subtracting 1 from the width and height to compensate, so it fits neatly inside the outline. Then it points out that “in the case of arcs, however, this is a much more difficult proposition (probably impossible in a portable fashion).” This means that portably filling and stroking an arbitrarily scaled arc without overlapping or leaving gaps is an intractable problem when using the X Window System. Think about that. You can't even draw a proper rectangle with a thick outline, since the line width is specified in unscaled pixel units, so if your display has rectangular pixels, the vertical and horizontal lines will have different thicknesses enen though you scaled the rectangle corner coordinates to compensate for the aspect ratio.
The color situation is a total flying circus. The X approach to device independence is to treat everything like a MicroVAX framebuffer on acid. A truly portable X application is required to act like the persistent customer in Monty Python's “Cheese Shop” sketch, or a grail seeker in “Monty Python and the Holy Grail.” Even the simplest applications must answer many difficult questions:
WHAT IS YOUR DISPLAY?display = XOpenDisplay("unix:0");
WHAT IS YOUR ROOT?root = RootWindow(display, DefaultScreen(display));
AND WHAT IS YOUR WINDOW?win = XCreateSimpleWindow(display, root, 0, 0, 256, 256, 1, BlackPixel(display, DefaultScreen(display)), WhitePixel(display, DefaultScreen(display)));
OH ALL RIGHT, YOU CAN GO ON.
WHAT IS YOUR DISPLAY?display = XOpenDisplay("unix:0");
WHAT IS YOUR COLORMAP?cmap = DefaultColormap(display, DefaultScreen(display));
AND WHAT IS YOUR FAVORITE COLOR?favorite_color = 0; /* Black. */ /* Whoops! No, I mean: */ favorite_color = BlackPixel(display, DefaultScreen(display)); /* AAAYYYYEEEEE!! */
(client dumps core & falls into the chasm)
WHAT IS YOUR DISPLAY?display = XOpenDisplay("unix:0");
WHAT IS YOUR VISUAL?struct XVisualInfo vinfo; if (XMatchVisualInfo(display, DefaultScreen(display), 8, PseudoColor, &vinfo) != 0) visual = vinfo.visual;
AND WHAT IS THE NET SPEED VELOCITY OF AN XConfigureWindow REQUEST?/* Is that a SubStructureRedirectMask or a ResizeRedirectMask? */
WHAT??! HOW AM I SUPPOSED TO KNOW THAT?(server dumps core & falls into the chasm)
Programming X-Windows is like trying to find the square root of π using roman numerals.
The PostScript imaging model, used by NeWS and Display PostScript, solves all these horrible problems in a high-level, standard, device independent manner. NeWS has integrated extensions for input, lightweight processes, networking, and windows. It can draw and respond to input in the same arbitrary coordinate system and define window shapes with PostScript paths. The Display PostScript extension for X is intended for output only and doesn't address any window system issues, which must be dealt with through X. NEXTSTEP is a toolkit written in Objective-C, on top of NeXT's own window server. NEXTSTEP uses Display PostScript for imaging, but not for input. It has an excellent imaging model and well designed toolkit, but the Display PostScript server is not designed to be programmed with interactive code: instead all events are sent to the client for processing, and the toolkit runs in the client, so it does not have the low bandwidth, context-switching, and code-sharing advantages of NeWS. Nevertheless, it is still superior to X, which lacks the device-independent imaging model.
On the other hand, X's spelling has remained constant over the years, while NeXT has at various times spelled their flagship product “NextStep,” “NeXTstep,” “NeXTStep,” “NeXTSTEP,” “NEXTSTEP”, and finally “OpenStep.” A standardized, consistent spelling is certainly easier on the marketing 'droids.
Unfortunately, NeWS an d NEXTSTEP were political failures because they suffer from the same two problems: oBNoXiOuS capitalization, and Amiga Persecution Attitude(TM).
X is just so stupid, why do people use it? Beats us. Maybe it's because they don't have a choice. (See Figure 2)
Nobody really wants to run X: what they do want is a way to run several applications at the same time using a large screen. If you want to run Unix, it's either X or a dumb character-based terminal.
Pick your poison.
Don Hopkins is a migrant user interface designer and graphics programmer. Don received a BSCS degree from the University of Maryland while working as a researcher at the Human Computer Interaction Lab. Don has worked at UniPress Software, Sun Microsystems, the Turing Institute, Carnegie Mellon University, Kaleida Labs, and Interval Research. He ported SimCity to NeWS and X11 for DUX Software. Don wrote the chapter on the X-Windows Disaster. (To annoy X fanatics, Don specifically asked that we include the hyphen after the letter “X,”, as well as the plural of the word “Windows,” in his chapter title.)
This article is written by Don Hopkins. (donhopkins.com) It is Chapter 7 of the UNIX-HATERS Handbook (1994).
The Unix-Hater's Handbook is authored by Simson Garfinkel, Daniel Weise, Steven Strassmann, Don Hopkins in 1994. It is now available online at http://web.mit.edu/~simsong/www/ugh.pdf.Disqus