138 The X-Windows Disaster 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 three hours for scheduled maintenance, another message goes onto my screen like a court reporter with Tourette’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 wipe 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 sup- port person said “Why would you ever need to point to something that you've drawn in 3D?” Myth: X Is Device Independent X is extremely device dependent because all X graphics are specified in pixel coordinates. Graphics drawn on different resolution screens come out at different sizes, so you have to scale all the coordinates yourself if you want to draw at a certain size. Not all screens even 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 filling 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 man- ual 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 pixels units, so if your display has rectangular pixels, the vertical and horizontal lines will have different thicknesses even though you scaled the rectangle corner coordinates to compensate for the aspect ratio.
X Myths 139 The color situation is a total flying circus. The X approach to device inde- pendence 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 dif- ficult questions: Server: What is your Display? Client: display = XOpenDisplay("unix:0") Server: What is your Root? Client: root = RootWindow(display,DefaultScreen(display)) Server: And what is your Window? Client: win = XCreateSimpleWindow(display, root, 0, 0, 256, 256, 1, BlackPixel(display,DefaultScreen(display)), WhitePixel(display,DefaultScreen(display))) Server: Oh all right, you can go on. (client passes) Server: What is your Display? Client: display = XOpenDisplay("unix:0") Server: What is your Colormap? Client: cmap = DefaultColormap(display, DefaultScreen(display)) Server: And what is your favorite color? Client: favorite_color = 0 /* Black. */ /* Whoops! No, I mean: */ favorite_color = BlackPixel(display, DefaultScreen(display)) Client: /* AAAYYYYEEEEE!!*/ (client dumps core and falls into the chasm) Server: What is your display? Client: display = XOpenDisplay("unix:0") Server: What is your visual? Client: struct XVisualInfo vinfo if (XMatchVisualInfo(display,DefaultScreen(display), 8, PseudoColor, &vinfo) != 0) visual = vinfo.visual Server: And what is the net speed velocity of an XConfigureWindow request? Client: /* Is that a SubStructureRedirectMask or * a ResizeRedirectMask? */ Server: What?! how am I supposed to know that? Aaaauuuggghhh!!!! (server dumps core and falls into the chasm)