SPLASH 1.1: xmessage on steroids

The tide-waves ripple, lisp and splash
And murmur, soft and low;
They urqe each other, mingle, clash,
As, ebbing out, they go.

-- Hovhannes Toumanian, "Akhtamar"


The SPLASH package provides a simple and powerful method for displaying splash screens containing warnings, notices, and other useful information under X11. It can display various data, including blocks of text, graphics, clickable URLs, and buttons to launch other programs. Finally, it is written in ANSI Common Lisp, making it infinitely extensible.

SPLASH is released under version 2.0 or greater of the GNU General Public License. The current version is always available at http://quadium.net/code/splash/.

System Requirements


Make sure that splash.lisp is somewhere in your load path. You'll need with-wish.lisp, too, so I've included it in the archive. To ensure that everything is working, find test.lisp and run it:

[cool_prompt]$ clisp ./test.lisp

Note: You'll have to run this from the current directory, because it contains a graphic, and we don't know where it'll be installed. This won't be a problem, as long as you include the full path to every graphic.

You should get a window with various text, URLs, and buttons. Play around with it a bit. Congratulations, you're done.


If you don't know Lisp, you'll be at a little bit of a disadvantage, but hopefully not much, since I tried to make this usable by the non-technical people out there. Basically, you just put a layer of parentheses around everything. You can have a lot of layers. Hopefully, everything else can be figured out from looking at test.lisp.

Create an empty file called whatever.lisp. To do this, you'll really want a spiffy editor like GNU Emacs or XEmacs. If you use vi, you're going to be using the % key a lot. If don't use either of these, pleasepleaseplease find an editor that does paren matching, and hopefully pretty Lisp indenting.

First, you need the following lines at the beginning of the file:

(load "splash.lisp")
(use-package 'splash)

If you'd like to enable some (very limited) debugging, also include this line:

(setf *debug* t)

That will cause all the Tk widget creation commands to get spewed onto standard output, as well as widget activation messages.

The only other thing you need is to call the SPLASH function. It is defined like so:

(splash widgets title &key background foreground title hover-color)

widgets is a list of widgets that should be included in the splash screen. These are normal CLOS objects, created with MAKE-INSTANCE. Each type of widget has keyword arguments of its own, which will be discussed later. Here is an example widgets list:

 (make-instance 'text
                :words "Here is an example text widget.")
 (make-instance 'button
                :words "Close the window"))

Theoretically, this should work just fine. Let's try putting it all together in a call to SPLASH (don't forget the 2 lines to load the SPLASH package):

  (make-instance 'text
		 :words "Here is an example text widget.")
  (make-instance 'button
		 :words "Close the window"))

Run it. You should get a window containing the widgets we created, but there's a problem. Due to the slight braindeadness of the Tk text widget, we'll have to explicitly specify its width and height. Unfortunately, the only way to find this is through trial and error. I've already done this for you, and I found we want a size of 30x1. So change the call to create the TEXT widget to the following:

(make-instance 'text
               :words "Here is an example text widget."
               :options '(("width" . "30")
                          ("height" . "1")))

Now everything fits, but the button seems too close to the text. Let's add some space to the bottom of the text, by adding the keyword argument :space-after 10 when we create it. Also, add the cons ("foreground" . "green") to the :options argument.

Everything looks perfect now. Since this is supposed to display splash screens for other programs, though, let's have the button kick off an xterm. Add :command "xterm &". Here's what you should have as your final result:

(load "splash.lisp")
(use-package 'splash)

  (make-instance 'text
		 :words "Here is an example text widget."
		 :options '(("foreground" . "green")
                            ("width" . "30")
			    ("height" . "1"))
		 :space-after 10)
  (make-instance 'button
		 :words "Close the window"
		 :command "xterm &"))

Everything else is basically just more of the same. For more examples, check out test.lisp. If you want to know how everything actually works, read on.

Tips and Tricks

Even though it will sometimes work to only specify a width and height for the first text widget, you should specify it explicitly for each one. Otherwise, you may observe weirdness.

Unless you know that everyone who will see your splash screen has a nice set of scalable fonts, use only bitmap fonts. gtkfontsel is an excellent tool for locating appropriate fonts; flip to "Filter" and make sure only "Bitmap" is checked.

Always specify font sizes in pixels, not points. This should make sure the width and height you specify for text widgets will always work.

Widgets and Options


This is a superclass of every other widget. It has a number of useful options inherited by the others.

Reader: widget-window-path

This is the Tk window path of the widget. Only the SPLASH package itself really needs to worry about this.

Accessor: widget-expand-p
Initarg: :expand

This specifies whether the Tk -expand option should be used when packing the widget. t or nil.

Accessor: widget-fill
Initarg: :fill

This specifies what argument should be given with the -fill option when packing the widget. "x", "y", "both", or "none".

Accessor: widget-options
Initarg: :options

This gives additional Tk options to be used when creating the widgets. A list of conses. The car of each cons should hold a string with the name of the option, and the cdr should contain a string with the option's value. Something to remember is that every widget class inherits the options of all its superclasses, with few exceptions.

Accessor: widget-space-after
Initarg: :space-after

How much vertical space, in pixels, should be added below this widget. This should be a reasonable integer.


The layout widget allows you to group several widgets together. For now, its only real purpose is to place more than one widget side by side.

Accessor: layout-children
Initarg: :children

A list of the widgets to go inside.

Accessor: layout-horizontal-p
Initarg: :horizontal

Whether the children should be laid out horizontally or not. t or nil, default t.


This is a superclass for any widgets with writing in them.

Accessor: words
Initarg: :words

What words to show. A string, obviously.


Displays a block of text on the screen. It doesn't have anything really special of its own. The visible text is inherited from WORDS.


This allows you to include a graphic in any of the formats allowed by Tk's image create photo command (GIF or PPM/PGM).

Accessor: image-file
Initarg: :file

The filename of the image. The full path should be given, and as this is simply passed on to wish, it should be specified as a string in UNIX path format.


Anything that can be activated by the user (URLs, buttons...) is a subclass of ACTIVATOR. Currently, this class doesn't do much, but there might be more later.

Accessor: activator-final-p
Initarg: :final

Whether or not the splash screen should disappear when this widget is activated. t or nil. The default is t for buttons and nil for URLs.


Duh. The visible text is inherited from WORDS.

Accessor: url-address
Initarg: :address

What address to visit. Note that Netscape's CLI doesn't grok commas in URLs, so you can't use them.

Reader: url-hover-color
Initarg: :hover-color

What color to change the URL to when the mouse moves over it. Should be a string containing an X color spec.


Buttons which launch a shell command. The visible text is inherited from WORDS.

Accessor: url-command
Initarg: :command

What command to run. If you stick & at the end, it will go off on its own. Otherwise, SPLASH will wait for it to finish before going on. Any non-string argument is passed to EVAL. A command of nil is a no-op, and can be used for a "cancel" button.

Stuff I Should Fix

Too many things use special, instead of lexical, variables. This happened during the early prototyping stage, and I didn't have time to fix it, because there was kind of a crunch to make it available.

You can't alter the hover color of a URL without using SLOT-VALUE. See previous bug.

This package should have a more interesting name.


Can now specify arbitrary form to be evaluated when a button is activated, and the splash screen is closed before final commands are executed.

Last modified: Thu Jun 29 12:59:24 MDT 2000