Note: This is all exceedingly out of date by today's standards. This is all based on XFree86 3, where everyone these days is using xorg 4, which deals with multiple devices completely differently. I'm leaving this here for interest value only, but it's probably no use to anyone.

(I still have the Hercules monitor and graphics card; but I don't have anything to plug it into... one day I must see if I can persuade a modern VGA card to drive a Hercules monitor. They're still great.)

A while back I `acquired' an old Hercules graphics card, and some monitors to go with it. This is a rather nice thing; it can manage 720x348 pixels of rock-solid, flicker free monochrome graphics on a tiny and nicely sharp monitor. Most Hercules monitors have slow-decay phosphor to produce wonderfully steady results.

For a while I stuck a TTY on it and echoed my system log to it. The monitor itself balances nicely on top of my mini-tower case, and this produced a useful indication of what was going on with my system. But then I decided that I should really get X running on and do something more impressive.

Eventually, I did.

[Photo of my system]

This is pearl, my work computer. Note location of second monitor, lack of case and the interesting collection of cups.

And here are some screenshots.

[Image of dpy :1][Image of dpy :2]

(Note that the Hercules monitor has a weird aspect ratio, so the above screenshot should be stretched vertically about 20% to look right.)

Putting this lot together was non-trivial. Some of it was downright hard. Here I'll explain how I did it.

Note: This is not a set of detailed instructions. This is a fairly general overview of the process needed to make it all work. The reason why I did this is (a) my setup is a grotesque hack, and I don't want to encourage people to copy it because it's not secure; (b) I'm expecting you to know what you're doing; (c) I couldn't be bothered to write any more documentation. The reason why I'm putting this up is because I could find not one reference to using a Hercules display as a second X server on the net, and it's not actually very hard.

My lawyer made me put this in: Follow the instructions on this page at your own risk. I am not responsible for any damage to your hardware, software, data, personal property, person, or mind caused by attempting this.


You will need:

  • A VGA video card. I used a Tseng Labs ET6000 PCI card. It shouldn't matter what.
  • A Hercules video card. This will have to go into an ISA slot as they don't make PCI ones. Make sure you get one that supports graphics: some Hercules cards (otherwise referred to as HGC or Mono cards) only support text mode. While these are still useful, you won't run X on one.

Kernel software


Actually, there are some anti-requirements. You must not have any kernel support for the mono card; if you're using 2.0.X then you must not have the mda module installed, and if you're using 2.1.X or 2.2.X you must not have Mono support compiled into the kernel. XFree86 does all its own hardware management and if the kernel is doing some as well it'll just get horribly confused. You will want all the usual support for your VGA card.

Setting up XFree86

This is the hard bit.

You will need to run two X servers with different configurations. Now, when you run an X server as root, it gives you an option to specify which XF86Config file it should read. Unfortunately, if you run it suid root or with XWrapper, you don't get this option. I had to resort to nasty hacks. What I did was to create a subdirectory of /etc/X11 that I, as user, could write to; this directory contains a symlink to the real XF86Config file. I then set up X to look at this link for its configuration file. This meant that I could change which configuration file to use by changing the link.

Here are the details:

dg@pearl [65] [15:56] ls -l /etc/X11/XF*
-rw-r--r--   1 root     root         1783 Feb 25 18:48 /etc/X11/XF86-mono-config
-rw-r--r--   1 root     root         5833 Feb 19 15:56 /etc/X11/XF86-svga-config
lrwxrwxrwx   1 root     root            9 Feb 24 18:24 /etc/X11/XF86Config -> user/link
-rw-r--r--   1 root     root        11726 Jul 13  1998 /etc/X11/XF86Config.bak

dg@pearl [66] [15:56] ls -l /etc/X11/user
total 0
lrwxrwxrwx   1 dg       dg             25 Mar 18 11:03 link -> /etc/X11/XF86-svga-config

Confused yet? You will be.

There is almost certainly a better way of doing this, probably involving sudo; I'm not particularly concerned about security on my machine, as I'm inside a firewalled company intranet and I'm the only one with login access to it, and if anyone really wants in then getting console access is easy. It's just I couldn't be bothered to do it like that.

XF86-svga-config should be your normal XF86Config file, with mouse and keyboard and so on set up in the normal way. XF86-mono-config should be an XF86Config file specially tailored for the Hercules card. It should also have one crucial modification: the mouse device (Section "Pointer") should point to an unused named pipe. I put mine in /dev/pipe. The reason for this is that only the VGA server should open the mouse device. Since XFree86 seems to have no way of disabling an input device, you have to point it at a null device. But you can't point it at /dev/null, because reads on /dev/null always succeed, and the X server will consume 90% of your CPU time spinning.

You should now be able to start either one of your X servers by updating the symlink and running the server.

Starting the servers

This is the hard bit too.

The problem is that each server insists on living in its own virtual console. So if you just start one server, and then the other, the second server will grab the console and cause the first server to make itself disappear, because it thinks something else is using the screen.

There are two solutions to this problem: (1) patch XFree86, (2) do really nasty hacking. Needless to say, I opted for the latter.

The secret is that XFree86 uses SIGUSR1 and SIGUSR2 internally to tell itself when it's changing virtual consoles. So, we can con it into showing itself even when its console is not active by sending it a signal at the right time.

So, to make both servers active at once, but to let the VGA server get the console, we must:

  • Start the mono server.
  • Start the VGA server.
  • Send SIGUSR1 to the mono server to make it visible.

I do this with a script (link below). This relies on the servers being setuid root. The people behind XFree86 recommend against this, but I couldn't find a way of making Xwrapper work without being even more insecure. The perfect solution would be to implement the script as a secure C program, but again, I couldn't be bothered.

The script also relies on each server starting within five seconds. This is heinously bad. The right solution would be to get XFree86 to inform us when it has started (see the Xserver man page, search for SIGNALS); this would require the script to be written in C, and (wait for it...) I couldn't be bothered.

After the servers have started, the script runs .xinitrc.0 on :0 and .xinirc.1 on :1 to start window managers and client programs. It also runs .xinitrc.common for programs common to both or neither (for example, I start my TrueType font server here). For now, copy your existing .xinitrc to .xinitrc.0 and make the other two empty.

You should now be able to run the script and have an X server start on each display. You should be able to start applications on the Hercules display by using display :1.

Making it usable

Right. You now have X successfully running on two monitors simultaneously. You can display programs on the monochrome monitor and do all kinds of funky stuff.

Unfortunately, you've only got one keyboard and mouse and that's feeding events to the VGA server. You can't type in windows on the Hercules monitor, or even move them. You can start x11amp but can't press the play button.

This is where a really handy program called x2x comes in (link to source site below). This will forward events from one X display to another. You can run it in two modes; the one I use is where it creates a one-pixel-wide window down the left hand side of :0, and when you move the mouse onto it it starts forwarding events to :1. In effect, you move the mouse pointer off the left of :0 and onto :1.

I start it in my .xinitrc.common. See below.

So, now you should be able to get a window manager and applications running seamlessly on both displays.


You'll need two window managers, of course. It seems that most window managers won't manage to seperate displays simultaneously (they'll manage to screens simultaneously, but that's different), so you'll need to run two instances of a manager. I use Window Maker so I can display the applets. Window Maker really likes to have a colour display, though. You may have better luck with something like WMX. Not only will this work quite happily on a monochrome display, it has the added advantage of putting the title bars on the left hand side of the windows instead of the top; since vertical real estate is limited on a Hercules card, this makes more efficient use of the screen. No screen shots, I'm afraid.

I did try Enlightenment on it but Imlib complained about a missing palette file. I am confused.

The main problem I have with the second screen is that the Hercules card is so slow. My nice, nippy, P166 work machine (no sarcastic comments, please) can't drag windows smoothly. The problem is almost certainly the bottleneck involved in the pathetic 8-bit ISA interface to the card. The solution is not to use solid dragging --- but even then, the card can struggle just doing line drawing.

In normal use my mono server used about 2% CPU time, and that's with all the applets scrolling away. Now, for example, the SVGA server is using 5% because I'm typing this into a nedit window. If I start dragging something around on the mono server it jumps to 20%.

I originally got the second monitor as a toy, really (I like toys). Now, however, I'm finding it extremely useful. I put status displays on it, downloads, things like that; then I can make my main display as cluttered as I like and never have to worry about covering application docks or my applets or anything like that. I just have to turn my head and there is all the information I need. Very handy. Highly recommended if you have happen to have the hardware.

Now, I gather that multiple PCI video cards will coexist in the same machine. I might be able to adapt the same technique...

Have fun.

This is source for the x2x program mentioned above, that's invaluable when dealing with multiheaded displays.

xgo 428 bytes

This script starts the two servers, making them both active. It then runs .xinitrc.0 on display 0 and .xinitrc.1 on display 1. When :0's window manager exits, it kills both servers.

xinitrc.common 107 bytes

The xinitrc file common to both displays. Starts the TrueType font server, x2x, and then waits a short amount of time to let the font server settle down.

xinitrc.0 121 bytes

The xinitrc file for the VGA display. Pretty standard.

xinitrc.1 142 bytes

The xinitrc file for the Hercules display. Also pretty standard. This file is notable because it starts a second instance of Window Maker, forcing it to use a different directory for its start-up files.