Swing menus, Actions, and enabled/disabled state

I've never liked toolbars. They inhabit this gray area for me between menus (where commands I hardly ever use live) and the keyboard (where commands I use all the time live). And I've never really got the point. Especially when they so often consist of just a row (or rows) of impenetrable little hieroglyphs. When a toolbar has text under the icons, I'm less likely to find out how to turn them off, but this just seems to mean that I never get round to learning the keyboard equivalents because, unlike menu items, toolbar buttons don't teach you how to work better.

So my programs have never had toolbars. They often didn't have menu bars (as opposed to pop-up menus) either, but becoming a Mac user changed that. If I didn't have reason to believe there would be an outcry from users, I'd probably have changed the Terminator terminal emulator to always have a menu bar even on Linux by now.

Anyway, Terminator does have a menu bar on Mac OS, and the other week I tried to automatically enable/disable "Select Next Tab" and "Select Previous Tab" on the "Window" menu, depending on whether or not there were any tabs to move to. Usually I just override Action.isEnabled and I'm done, but that's because I have special code in the Edit editor to make this possible. It's been like that since about 1998, and I'd pretty much forgotten it's not representative of how Swing works.

Swing, of course, supports toolbars, so you're supposed to call Action.setEnabled. The trouble with this is that it encourages code that I've always felt should be in the Action to leak out into the rest of program. An Action ought to know for itself when it should be available, rather than be told. (The idea of duplicating some of the program's state always seems slightly offensive too.)

A very similar alternative is to make the Action know more about the rest of the program; it could listen to other components or collections, and although this is definitely better than hard-wired interdependencies, it still seems like you're spreading what's conceptually a single piece of functionality all over the code. too complicated a web of listeners (and the notification storms that can result) is a definite bad smell.

It's interesting how many times "isEnabled" boils down to a dependency on the size of some collection. Be it the size of the undo buffer, the redo buffer, the number of tabs in some JTabbedPane, the number of Frames, or the existence of a selection. One way to ameliorate the "web of listeners" problem is to make the collections vend suitable actions. So the undo/redo buffers offer undo and redo actions, for example, and it doesn't seem at all unpleasant that they should have interdependencies because they're in a conceptual "undo/redo system".

The way a framework like Apple's Cocoa takes care of all this nonsense for you and hides it from you is one sign of how much more sophisticated it is than Swing.

The Mac actually illustrates the other common example of "isEnabled": implementing modes. If you look at the menus in Mail, for example, lots of functionality will be disabled if the Inbox has the focus, but enabled if a composition window has the focus (at which time, some of the functionality that was previously enabled will have become disabled). As displays grow larger, my doubts about the screen menu bar (and Apple's style of making it the union of all possible windows' menu bars) grow too. Modes aren't necessarily evil, but when it's not clear what they are, which one you're in, or how to move between them, you're at the evil end of the modality spectrum.

Anyway. To support a style where Action classes determine their enabled/disabled state themselves, Edit has long used a MenuListener to traverse a menu that's about to be displayed and call Action.isEnabled on each menu item's Action, and then call JMenuItem.setEnabled on the menu item itself. It's not perfect, but it's pretty good. The only limitation as far as menus are concerned is that you can't use this to disable a top-level menu (that is, a menu that's attached directly to a JMenuBar) because that's always visible, so there's no menuSelected notification to act on.

And, of course, there's the fact that if you want to use your Action on a toolbar, it won't correctly enable/disable itself.

So you can't win, but you do at least have a choice if you can live without toolbars (and as a developer but especially as user, I can easily live without toolbars). The code to implement this "pull" style is now in salma-hayek, if you'd like to use it in your own programs. If you have a better alternative technique, I'd be interested to hear about it.


Why Terminator doesn't support $WINDOWID

While getting X11 out of 800x600 (why in 2005 does Xorg still not manage to auto-detect the best resolution for the graphics hardware and connected display when Mac OS and even MS Windows have been doing so without problem for years?) and installing Terminator on someone's new machine the other day, I noticed that vim(1) behaved differently running in an XTerm window than it does in a Terminator window.

To cut a long trawl through the vim source short, It turns out that it looks to see if $WINDOWID gives it a window it can get/set the title of using Xlib, and enables its "title" setting if so. It then uses either the X11 mechanism or escape sequences to set the window's title. If you think I'm being vague, take a look at the code. It's a great example of over-complicated chronic-featuritis nested-#ifdef-hell multi-platform-the-bad-way old-style C. (If you're going to use #ifdef, it shouldn't be within the scope of a function.)

We can tease the Xlib Window out of Sun's AWT implementation like this:

private static long getX11WindowIdForFrame(Frame frame) {
long windowId = 0;
try {
Field peerField = Component.class.getDeclaredField("peer");
Class xWindowPeerClass = Class.forName("sun.awt.X11.XWindowPeer");
Method getWindowMethod = xWindowPeerClass.getMethod("getWindow", new Class[0]);
Object getWindowResult = getWindowMethod.invoke(peerField.get(frame), new Object[0]);
windowId = Long.class.cast(getWindowResult).longValue();
} catch (Exception ex) {
return windowId;

But it turns out to be quite difficult to make good use of this in Terminator.

For one thing, it's quite disruptive to the rest of the code, getting a Frame at the right point and passing it through. We already have two-stage initialization in various places in Terminator, and this would require a few more, or a lot more parameter-passing, because you don't add a component to a hierarchy until the component's constructed.

More importantly, setting $WINDOWID would interact badly with the planned ability to turn tabs into windows (and maybe vice versa). We'd have no way of changing an existing process tree's $WINDOWID, so any code making use of the $WINDOWID would end up fiddling with the window it started in, rather than the window it was currently in.

Maybe I've not looked hard enough, but I've not seen anything else rely on $WINDOWID, and there's no reason to do so for setting window titles from tty-based programs because you can just send the relevant escape sequences (the "tsl" and "fsl" capabilities). You can even query the terminal capabilities if you want to know if such a thing is supported (the "hs" capability). Basically, Vim is doing the wrong thing, and it's source code is a frightening example of what you end up with if you decide to work around every bit of brain-damage in the universe. (If there's one area of Unix that sports a lot of ugly lesions, it's terminals.)

Any Terminator user who wants Vim to update their title can add "set title" to their "~/.vimrc" and have it do the right thing anyway.

So given a choice between support for a poor design decision on Vim's part or the ability to add a fairly cool feature, I'll go with the freedom, and throw away my cool hack to get the X11 window id. Where by "throw away" I mean "give to Google via my blog".


News continues to bore me

The first time I used Unix on a real machine, it was AIX on an RS/6000. A computer science student in the year above me (I'd sign up to start my course the next day) took pity on me as I sat around waiting for term to start, logged in on the terminal next to his, and ran tin(1) or maybe tass(1) given how long ago it was, and suggested I "read news".

In my day, you see, HTTP wasn't exactly widespread. It would be a few months before I saw my first web page. (That would be on some of the few computers fancy enough to have graphics. And color.)

There were no RSS feeds, and there were no blogs. But there was another form of vanity publishing, and it was called USENET news. For a year or so, I read quite a lot. It seemed at the time like all of a sudden I had access to all kinds of people with all kinds of interesting knowledge. Especially stuff relating to computers.

Sooner or later, though, I realized that it was mostly crap. There were too many pointless pissing contests. (I should know, I took part in my share.) Too much name-calling. Too much repetition. Too many people asking the same questions. Too many people providing wrong/poor answers. It still seemed like a pretty good means of distributing porn, though, but the web was about to come along and do a much better job of that (and ruin the popularity of my scripts for collecting, collating, unsegmenting and uudecoding USENET porn automatically).

(The most visible short-term effect of the web I remember is that you couldn't get on a machine with a 3.5" disk drive because they were the only way to take porn out of the room, and transfer to 3.5" disk was insanely slow.)

Anyway, I've seen no point to reading USENET for about a decade now. I don't know (or care) if it even continues to exist.

Never one to learn from mistakes, when I came across RSS feeds, I thought all of a sudden I had access to all kinds of people with all kinds of interesting knowledge. Especially stuff relating to computers.

RSS came at a good time for me. There was a gap in my life opened by leaving Switzerland and no longer waking up to DRS-2's morning news. I'd long loathed England's Radio 4 morning news, and never did bother to tune my radio for the years I lived there. If it were a satirical short film, where pretend presenters try to get pretend politicians to say something they shouldn't while the pretend politicians try to say whatever they'd prepared, it might be funny. As "news" or "discussion", it was tiresome. And it was embarrassing to hear them on days when Science or Nature had something that sounded "newsworthy". "So," they'd ask the scientist who presumably knew this was going to be idiotic but wanted to be able to mention national radio appearances on their CV, "what do these new Hubble images tell us about God?". Or "So, elephants can talk?". (I may be paraphrasing, but I'm not making either of these up. And this is from one of England's better-quality sources.)

The newspapers, deprived of the opportunity for radio's over-aggressive live "interviews", were somewhat better, but still a mixture of "stuff you've heard before, with a few names/numbers/places changed" and "stuff the writer didn't understand". There are only so many bad science/technology articles you can read before you start to question the quality of the stuff you don't know anything about.

I won't even mention TV. I can feel it sucking the intelligence out of me. It almost manages to sap my will to live.

I'm just about getting to the point of admitting that most blogs are mostly crap. Not as bad as Slashdot, maybe, but about as bad as The Register. If a little less funny.

In particular, I've been unsubscribing left, right, and center lately. In part it's consolidation. "Planet JDK" is more convenient (and complete) than having a bunch of random Sun developers' blogs. But there just aren't that many feeds whose contents really interest me. The similarly-titled "Planet Classpath", for example, seems mainly about proponents of free software congratulating themselves for still not being as good as Sun's free software. Tom Tromey's posts are usually interesting, but the rest aren't worth the bits they're printed on. And Tromey's feed's broken, so I can't subscribe to him alone.

Then there are the dead sites, like fokelore.org. It was interesting when it was still a going concern, but there's been but one post all year, and there's no reason to expect many more. (That's one connection per hour from my copy of NetNewsWire they're having to service, and for what? How much pointless traffic are they having to deal with?)

And, without wanting to name names, there are all the bloody narcissists. Yes, I realize this is just a modern form of vanity publishing, and I realize that this very post could be considered an example of what I'm complaining about, but there's way too much personal crap for my liking. I don't want to see pictures of your pet or your child. I don't care if you/your wife/your child has toothache/is dying/died. I don't know you, so unless you can write like Hemingway, why should I care? You are not interesting in your own right. You are not a beautiful and unique snowflake.

And you wouldn't come to my wife's funeral, you heartless bastard, so screw you!

I have a friend amongst the people who might come to my wife's funeral, who complains that my blog isn't personal enough, but I think it's too personal a lot of the time. Like now, for instance. If I were reading this, I'd be waiting for the next snippet of code, the next bit of information about a bug, or the next work-around.

Maybe I'm missing the RSS equivalent of porn distribution, but I'm not sure I can see my parents ever wanting RSS. There was never any doubt in my mind they'd want email, the web, widescreen displays, and Tivo. I have no doubt they'll want "wireless broadband" as soon as they understand and consider it affordable. But RSS? They're better off with Google News.

As for me, I guess I'll continue my search for high-quality technical tidbits, and will get round to paying attention to current affairs when I've finished all the books. At one or two a week, I may be some time, so don't wait for me.

I think I've listened to myself enough for today. Time to see what's next on my to-do list.


Using the GTK LAF to access GNOME stock icons

I've written a lot about little bits of Mac OS polish for Java programs, but I'm anal about polish on all operating systems. One reason I have such a visceral dislike of Win32 is that no-one there seems to care. When I used and developed for Win32, I expended at least as much effort on getting the pixels right there. I haven't paid much attention to Unix, though, until recently.

One problem is that there are so many different Unix desktops. Even assuming that we only care about GNOME (which isn't unreasonable), there hasn't been a good way to target GNOME from portable Java. Even in Java 5, the GTK LAF is a joke. It neither looks nor feels like GTK+. And using any kind of Java GNOME bindings defeats much of the purpose of using Java, so that's not an option.

Most of the stuff I work on disables the GTK LAF in favor of the cross-platform LAF, except on Java 6. On Java 6, the GTK LAF is coming along nicely. It's using Apple's trick of calling native code to do the actual rendering. (Actually, Werner Randelshofer's Quaqua LAF is a lot more convincing than Apple's effort and it works by using images of the various UI elements. But Apple's solution ought to be better if they had the right kind of person working on it. Werner has to include separate sets of images for each version of Mac OS he supports, whereas Apple's JNI ought to just do the right thing.)

Java 6 build 62's GTK LAF seems to have a few performance problems (at least on Linux/amd64; I haven't tried it on anything else yet) but appearance-wise it's close enough to mostly convince me. The menu separator problem has been fixed, and table headers look okay now. The most glaring remaining problem is that disabled menu items have missing icons rather than grayed-out icons.

Anyway, in anticipation of being able to use the GTK LAF with a straight face, I looked in to using GNOME stock icons on menu items. I knew that they were being used for buttons, and it turns out if you look at GTKStyle.java that there's support for all the different sizes, including the menu size. Unfortunately the GKStyle.GTKStockIcon constructor isn't accessible, but that's what reflection's for.

Here's a snapshot of the code from salma-hayek for giving convenient access to the GNOME stock icon functionality locked away in the GTK LAF:

package e.gui;

import e.util.*;
import javax.swing.*;

public class GnomeStockIcon {
* These are type-safe versions of the hard-coded numbers in GTKStyle, for
* use with getGnomeStockIcon.
public enum Size {
GTK_ICON_SIZE_MENU, // 16 x 16

private GnomeStockIcon() {

* Sets the SMALL_ICON property to the given GNOME stock icon, assuming
* it's available. The SMALL_ICON property is left unchanged otherwise.
public static void useStockIcon(AbstractAction action, String name) {
// FIXME: for Java 6, use Action.LARGE_ICON_KEY too.
Icon icon = getStockIcon(name, Size.GTK_ICON_SIZE_MENU);
if (icon != null) {
action.putValue(AbstractAction.SMALL_ICON, icon);

* Returns an Icon for one of the GNOME stock icons. If the icon is not
* available for any reason, you'll get null. (Not using the GTK LAF is
* one reason why.)
* The GNOME header file listing the possible strings is here:
* http://cvs.gnome.org/viewcvs/gtk%2B/gtk/gtkstock.h?view=markup
public static Icon getStockIcon(String name, Size size) {
if (GuiUtilities.isGtk() == false) {
return null;

Icon icon = null;
try {
Class gtkStockIconClass =
java.lang.reflect.Constructor constructor =
gtkStockIconClass.getDeclaredConstructor(String.class, int.class);
icon = (Icon) constructor.newInstance(name, size.ordinal());
} catch (Exception ex) {
// Sorry! No icon for you!
return icon;

And here's an example of how you'd use it in one of your Action classes:

public NewFileAction() {
putValue(ACCELERATOR_KEY, GuiUtilities.makeKeyStroke("N", false));
GnomeStockIcon.useStockIcon(this, "gtk-new");

You can see a list of the available names and pictures of the icons they correspond to in the GTK Stock Icons documentation.

Obviously, there's more to do here. It would be nice to support more general "stock action" configuration. We could set the NAME, ACCELERATOR, and description properties for all platforms, and the MNEMONIC property everywhere but Mac OS. (Man, I hate programs that use mnemonics on Mac OS. I don't think the Aqua LAF should even render them. Ugh.)

Also, when Java 6 is more widespread, we'll want to support LARGE_ICON, as mentioned in the FIXME comment above.

There's also the question of what order menu items should come in on any given platform. I haven't thought about it much or tried to implement it yet, but that sounds like it needs something to sort the menu after you've added your items.


Ubuntu 5.10 on the Ultra 20 (or, why I prefer Java's client compiler over the server compiler)

Flush with success from running the Ubuntu 5.10 live CD on my Ultra 20, I tried the real thing.

Installation was similar to the live CD. It took about 20 minutes, and a few more questions were asked. The expected "which time zone?" question was one, and there was one difficult question about how I'd like to format my disk. More on that later.

In contrast to Solaris, I was asked for a hostname, the name of a user, and a password for that user. There was no need for a root password because you're supposed to use sudo(1), another thing that Solaris gets wrong. (Logging in as root is so 1970s. It seems to me analogous with the mistake dynamic languages like Ruby make in forcing you to pay for stuff even when it's the last thing you need. In Ruby's case, you get no static checking in return for dynamism you hardly ever need and could easily ask for. In Solaris' case, you get all the dangers of being logged in as root in return for not having to explicitly annotate each command with "sudo". Not good trade-offs.)

Ubuntu doesn't include an SSH server, nor any development tools. Mac OS makes the former a check box item (the server's installed, but not activated by default) in a handy dialog that covers all network services. I wasted some time looking for the equivalent check box before asking Google and finding out that I needed apt-get(1).

So, here's the list of packages I need to do anything (the lack of each of these is a reason why I've no time for Win32):

# For remote use:
sudo apt-get -y install openssh-server
# For editing:
sudo apt-get -y install exuberant-ctags iamerican
# For general development:
sudo apt-get -y install build-essential make ruby ri g++
# For version control:
sudo apt-get -y install bzr cvs subversion
# For C/POSIX man pages:
sudo apt-get -y install manpages-dev glibc-doc
# For X11 development:
sudo apt-get -y install x-dev libx11-dev
# For building yacc parsers:
sudo apt-get -y install bison
# For building Python programs that have C extensions:
sudo apt-get -y install python-dev

Given those, I could scp(1) my .bash_profile, .bashrc, .inputrc, and .ssh/ over, and get on with downloading Sun's JDK.

That was where things started to go weird. At work, where I use the stuff I write at home, it takes 4s to build one of my projects on Debian/Intel. With Solaris/Opteron on the Ultra 20 at home, the same build took 2s. With Ubuntu/Opteron, it took 8s. I didn't know how modern Linux and Solaris compared, but I expected them to be about the same, so this was Linux performing four times slower than I'd expected.

Not good.

Unfortunately for me in diagnosing the problem, there were a lot of variables. Three different OSes, three different kernels, three different file systems. Three different versions of GNU make, and three different versions of Sun's JDK. GNU make was easily eliminated by writing the output of make -n to a file and examining and running that. I installed Sun's 1.5.0_06 (instead of the 1.5.0_05 I'd been using) at work, with no change. So it wasn't like there was a major javac(1) performance regression (I'd already worked out that was where all the time was going). I didn't have much to lose, so I re-installed Ubuntu without LVM. No change.

Then I noticed that I was running the server compiler. There is no client compiler for amd64. And we all know that the cost of the server compiler is the increased start-up time. Passing -J-server to javac(1) on my work Debian/Intel box confirmed the theory that I probably didn't want the server compiler for this job.

Out of interest, then, I installed the x86 JVM. And got my build time back down where it should be.

At this point, I'd love to know what I was running on Solaris. Had I accidentally managed to install the x86 JVM instead of the amd64 one? We'll never know, because I had to reformat to install Ubuntu. Google doesn't seem to think there's a client compiler for Solaris/amd64, or that the Solaris/amd64 server compiler is ridiculously faster than the Linux/amd64 server compiler.

I wondered if there was any reason why I'd want to use an amd64 JVM build, given that I don't run any enormous J2EE webturds. One of my Terminator co-conspirators pointed out that, yes, there is: JNI libraries. Your JNI library needs to match your JVM, and that might be awkward to ensure without the "appropriate" 64-bit JVM for your architecture.

For the record, I think Solaris was a shade faster for my usual builds, but not to the extent that I'd be prepared to put up with the pain of its userland, or the lack anything even remotely approaching apt-get(1). Blastwave just isn't in the same league. Not in terms of range of packages, not in terms of how well what few packages there are work (the Ruby package had a dependency on a library it didn't contain, and after the last time I updated the Firefox package, it would hang on start-up), and perhaps most importantly, it's not the One True Way on Solaris; it's Yet Another Way That Doesn't Quite Solve The Problem.

The "software update" system on Ubuntu, which seems to be the Synaptic front-end to apt-get(1) is pretty good. I'd read about it on the web before, and had tried it on my Debian box at work, and been completely underwhelmed. When I ran it, it seemed to be a GUI equivalent of dselect(1), one of the worst programs of all time, both in idea and execution. I didn't see the point and never ran it again. On Ubuntu, it's set to run itself and announce updates like Mac OS' Software Update. That's the main thing I haven't liked about using apt-get(1) for everything in the past: it doesn't have a push side. Synaptic provides one, and it's pretty good. It's a little more complicated than Apple's effort, but then it tries to provide support for extra sources of packages, and that's one thing Apple don't do which I think annoys most third-party developers. (Even if you can understand why Apple might not want to sanction third-party packages in such a way, Synaptic does seem to keep the distinction between Ubuntu and external packages reasonably clear.)

Overall, I'm happy enough with Ubuntu that I'm not about to reformat for the third time in three days.

(As for NTP, it turns out to not be the real thing. If you choose the "Time and Date" administration option, there's a check box a with Mac OS. Unlike Mac OS, checking the box brings up a poorly-worded dialog mumbling something about you needing to "install and activate NTP support in the system to enable synchronization of your local time server with internet time servers". My local what? Anyway, click the button and it will do it for you, but will inexplicably fail to check the check box you first clicked on. Clicking on the check box again brings up the same "NTP support is not installed" dialog, and clicking "Install NTP support" for a second time does nothing but close the dialog. Re-start the "Time and Date Settings" program, and you can check the check box. Strangely, that leaves you with no servers selected, and there's no advice about how many upstream servers to synchronize with. So, no, this isn't a patch on Mac OS. But Solaris can consider itself knocked to the ground and urinated upon while all the other OSes stand around laughing.)


Ubuntu 5.10 live CD on the Ultra 20

At the end of my recent round-up of my Solaris 10 experience I wrote "If it were no more complicated than inserting a DVD and power-cycling, I'd be installing Linux on my Ultra 20 right about now."

Then I remembered that Ubuntu comes highly recommended, and that they have a "live CD" that you can supposedly boot without installing anything on your hard disk. That is, there's a no-risk easily backed out free trial.

What the hell; how bad could it be? I decided to give it a go.

In short, I was impressed. I didn't know Linux could be this painless. The live CD did what it was supposed to, and worked fine on my Ultra 20. It didn't take much longer to boot off CD than Solaris 10 takes to boot off disk (the Solaris x86 boot process is over-complicated), and the feedback was much better while it did so. Not quite as attractive as Mac OS, but better than the Debian installations I'm used to at work. Strangely reminiscent of the Amiga and the whole 16-bit home-computer era.

But I'm getting ahead of myself.

The "installation" asked only one stupid question, about the maximum resolution X11 should support. The question was worded incoherently, which didn't help; it asked which ones to disallow, but you actually select the ones you want to allow. The default settings -- which you couldn't see, thanks to the ugly text-based whiptail(1) interface -- was dumb: 1024x768 being the best on offer. The verbose but confusing wording implied that if you just selected everything, it would do the right thing anyway, and it certainly seemed to when I rebooted and selected everything.

Other than that, i had to hit return to accept English as my language, hit return to accept US as my keyboard layout (the alternative being "type some stuff, and i'll work out what you've got"), and ... well, that was it.

It automatically tried DHCP, it automatically chose a UTF-8 locale (w00t! first Unix ever to do that for me!), and it automatically used NTP (Mac OS made me click a check box, so this was one better, though I'm not sure it was full-on NTP rather than SNTP).

The GNOME setup seemed way better than any other I've used. As if someone had selected modern versions of the various components that actually work together, and had tried them. The default theme wasn't unreasonable; certainly much nicer than anything I've seen on any other GNOME. If a little too orange. Made me think of socal trophy wives.

There are worse things a UI can remind you of. MS Windows makes me think of sweaty little accountants. I can't believe that anyone else is the target audience.

I was surprised how fast everything was. I'd read that the problem with live CDs is that you don't get much of an impression of what the performance will be like in real life; the implication being that it was going to be really slow. But it wasn't. Firefox started the first time about as fast as the Blastwave Firefox started on Solaris 10 (when it started at all; since my last pkg-get it's stopped working), and successive starts were as fast as Safari on my PowerMac. Much better browser start-up performance than I'm used to from Linux. Of course, it had an old make(1) and a free (read: useless) Java VM, so I've no idea what real performance will be like. Last time I ran Linux instead of Solaris on a Sun, it was like getting a whole new computer. (Albeit one where the X11 server didn't work properly.) But that was years ago. Both OSes have come a long way since then.

Under the hood, stuff was familiar for being basically Debian. This might not appeal to everyone, but it pleased me. Having the stuff you're used to, where you're used to it being, working as you're used to, apt-get and all ... that's pretty cool.

So, it'll be sayonara Solaris next time I get a spare hour at home. That I'm not wasting on writing junk like this. I've no doubt that a real install will be more hassle, but at least then my computer will be in the right time zone, which was the one problem I noticed — you'd think they could use those IP geolocation web sites to guess that right!

(I'm actually serious. Apart from the X11 thing, the live CD was hugely impressive. Fixing the X11 thing by getting the monitor's details from the monitor and knowing the graphics card's limitations, and guessing my time zone would make it perfect. I'm almost glad of those flaws, because they let me know that I didn't just imagine the whole thing.)

The one bit of hardware that wasn't as well supported as with Solaris 10 was the fans. They were under control (going full blast, they're seriously loud, and this was nothing like that), but they were up a notch compared to Solaris 10 under the same conditions.

I don't understand why there wasn't a prominent "click here to do a real install off the network" button. As it is, I'll be burning another CD-R soon; this time with the real thing.