wm - a window manager (part 1 of 4)

sources-request at genrad.UUCP sources-request at genrad.UUCP
Sat Aug 3 03:35:53 AEST 1985


Mod.sources:  Volume 2, Issue 31
Submitted by: Tom Truscott <decvax!mcnc!rti-sel!trt>


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	wm.1
#	USINGWM
#	Paper.jacob
# This archive created: Fri Aug  2 13:13:13 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(1606 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
	A Revised Edition of the `wm' window manager
		Matt Lennon	(919) 541-6919
		Tom Truscott	(919) 541-7005
		Research Triangle Institute, NC
		P.O. Box 12194
		RTP, NC  27709


To install WM:

1) Install the provided version of the Curses library. This library
   has bug fixes *necessary* to the proper operation of WM.
   If you don't actually install libcurses.a in /usr/lib, you
   must indicate this in the WM Makefile (the LIBCURSES macro),
   and you must copy the provided curses.h to this directory
   so that it will be included during compilation.

2) Set the value of BIN in the WM makefile to the
   directory where the WM program should reside.

3) Type 'make install'.

4) Install the WM manual page, wm.1, in the appropriate place.


Note 1: This version of WM is horribly 4.2bsd-dependent, using pseudo-ttys,
        the 'select()' system call, 4.2-specific ioctl's, etc.
        Conceivably, it could be made to run under 4.1bsd with some
        minor mods, but porting to other versions of UNIX would
        probably entail a major rewrite.

Note 2: The paper 'USINGWM' is a brief essay on how we use WM
	here at RTI, and should prove helpful in getting used to
	the WM style of doing things.  It also describes some
	problems/glitches with WM that you should be aware of.

Note 3: Included in this distribution is a paper (Paper.jacob)
        by the original WM author that describe WM's
        development and structure.  While the description of
        the 4.2bsd version of WM pertains to an earlier version,
        the basics are still the same, and this paper is good reading.
SHAR_EOF
if test 1606 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 1606 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'wm.1'" '(5635 characters)'
if test -f 'wm.1'
then
	echo shar: will not over-write existing file "'wm.1'"
else
sed 's/^X//' << \SHAR_EOF > 'wm.1'
X.TH WM local wm
X.SH NAME
wm \- window manager
X.SH SYNOPSIS
X.B wm
[ \fB\-n\fP ]  [ \fB\-f\fP rfile ]
X.SH DESCRIPTION
X.I Wm
manages a collection of windows on a display terminal.
X.PP
It determines what type of terminal you are using from
the environment parameter $TERM
(see
X.IR environ (5))
and then uses
X.IR curses (3)
to adapt to it.
X.PP
Each window has its own UNIX shell
(as specified by the environment parameter $SHELL;
the default is
X.IR sh (1)),
running in parallel with those in the other windows.
The idea behind this scheme is that you can use each window
for a series of commands dealing with a single topic.
Then, you can change back and forth between the windows without
losing your place in any of them.
X.PP
At any time, you can give commands to change the window you are typing in,
to move a window or change its size,
or to create or kill a window.
Windows can overlap or completely obscure one another.
Obscured windows can subsequently be "lifted" up
and placed on top of the other windows.
When a window is partially or completely obscured,
subsequent output to that window will be held until the window
becomes completely visible again, effectively suspending the job
running in the obscured window.
X.PP
When the program is started,
it will attempt to restore the sizes and positions of the windows
in use when you last ran
X.IR wm
(unless you use
X.B \-n
option).
If you give the
X.B \-f
X.I rfile
option,
X.I wm
tries to restore windows from the file
X.I rfile.
Otherwise, it first tries the file
X.I .wmrc
in the current directory,
then, if necessary,
X.I .wmrc
in your home directory.
XFailing all this,
X.I wm
will give you a window the size of your screen.
Now, you can type UNIX commands in the new window.
X.PP
X.I Wm
commands can be issued at any time.
Every
X.I wm
command consists of a prefix character \fI<wm-esc>\fP followed by one
more character, possibly followed by some arguments.
Any other characters typed on the terminal are treated as input
to the program in the current window.
To enter \fI<wm-esc>\fP itself as input to a program, type it twice.
The \fI<wm-esc>\fP is initially set to ASCII ESC, but there is
a command for changing it.
X.PP
The available
X.I wm
commands are \fI<wm-esc>\fP followed by:
X.IP \fBn\fP
Create a new window.
To do this, move the cursor to the position you want the
lower left corner of your window
to occupy,
using the keys
X.B k
(up),
X.B j
(down),
X.B h
(left), and
X.B l
(right)
and also
X.BR K ,
X.BR J ,
X.BR H ,
and
X.B L
(for large increments in the respective directions).
Then type an
X.BR x .
Then move the cursor (using the same commands) to the upper
right corner, and type another
X.BR x .
X.IP \fBi\fP
Identify each window by outlining it with its window number
(each window has a one digit name, e.g.
#\fB1\fP, #\fB2\fP, #\fB3\fP,
used in referring to that window).
X.IP \fIdigit\fP
Change the current window.
The named window is placed on "top" of the screen
(that is, in front of any other windows that had been obscuring it).
Input from the keyboard will now be sent to this window.
(Delayed responses to commands entered in other windows will,
of course, continue to be routed to their correct windows.)
X.IP \fBl\fP
Change to the last-used window.
Change back to the window that had most recently been the current window.
X.IP \fBm\fP
Move and/or change the size of the current window.
X.I Wm
asks for the lower left and upper right corners of desired
new position of the window (same convention as for new windows).
It is not advisable to move a window except when
the program running in it is at the shell prompt level.
In particular, screen-oriented programs such as
X.I vi
can get very confused if their window size is changed while they are running.
X.IP \fBt\fP
Reset the environment variables $TERM and $TERMCAP for the current window.
This may be necessary if these variables get unset or scrambled,
for instance during a remote login.
This command should only be invoked when
the program running in it is at the shell prompt level because
it operates by sending commands to the shell as if
they were typed in from the keyboard.
X.IP \fBd\fP
Dump current window contents. An image of the current window is
written to the file
X.I wmdump
in the current directory.
X.IP \fBk\fP
Kill the named window.
XSends the signal SIGHUP (hangup) to the processes associated with the window,
then erases the window.
(The
X.I name
of this window may later be re-used in creating a new window.)
X.IP \fBp\fP
Change the prefix character.
X.IP \fBr\fP
Redraw the screen.
Clears the entire screen and redraws what should be there.
Helpful after garbage (like a broadcast message) has arrived.
X.IP \fBq\fP
Quit.
End the current 
X.I wm
session.
XFirst terminates the processes associated with each
X.I wm,
window by sending them the signal SIGHUP (hangup).
Then, if you have changed the window configuration during the session
(and didn't specify the 'no restore' (\fB\-n\fP) option),
asks you if you want to save the current window configuration
for the next session.
Then exits.
X.IP \fBz\fP
XSuspend
X.I wm
by using the Berkeley job control system,
or perhaps by spawning a non-window subshell.
X.IP "\fBh\fP or \fB?\fP"
Help.
Displays a summary of
X.I wm
commands.
X.SH FILES
X.IP \fI.wmrc\fP
X.IP \fI$HOME/.wmrc\fP
used to save the arrangement of your windows from one session to the next.
X.SH BUGS
It'll never beat a BLIT.
X.SH "SEE ALSO"
R.J.K. Jacob,
"User-Level Window Managers for UNIX,"
X.I "Proc. UniForum International Conference on UNIX,"
pp. 123-133 (1984).
X.SH AUTHOR
Robert J.K. Jacob
X.br
Naval Research Laboratory
X.sp
Revised by Matt Lennon and Tom Truscott
X.br
Research Triangle Institute
SHAR_EOF
if test 5635 -ne "`wc -c < 'wm.1'`"
then
	echo shar: error transmitting "'wm.1'" '(should have been 5635 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'USINGWM'" '(17319 characters)'
if test -f 'USINGWM'
then
	echo shar: will not over-write existing file "'USINGWM'"
else
sed 's/^X//' << \SHAR_EOF > 'USINGWM'
X.TL
How I use WM
X.AU
Tom Truscott
X.AI
Research Triangle Institute
P.O. Box 12194
RTP, NC  27709
(919) 541-7005
X.SH
XStarting up wm
X.PP
The last line in my .profile is
X.DS
X.ft PO
exec wm
X.ft P
X.DE
which puts me into the window manager,
so I am always in it.
When I need a real terminal
(e.g. to run `talk')
I can type \fI<wm-esc>\fPz.
XSince I go right into wm
it is important
that TERM be set correctly.
Earlier in my .profile I have
X.DS
X.ft PO
export TERM
case "$TERM" in
sw|su)	TERM=`whatterm`;;
esac
X.ft P
X.DE
XSo that if the TERM variable is su or sw (dataSWitch)
John Menges' whatterm program is invoked to figure things out.
(Whatterm depends on the
response characteristics of a dozen or so terminals.
A more general version, using a `responsecap' database,
is planned.)
Whatterm is doomed to fail on an ADM terminal
(unless it has the HERE-IS option)
and also fails
if the user is already in wm and and logging in to another computer,
because `wm' itself does not respond to any escape sequences.
It probably should, so whatterm will work!
Actually, nested invocations of wm, while amusing,
are probably unnecessarily confusing.
X.SH
Choosing window layout
X.PP
That is largely a matter of individual taste.
My ``#1'' window is full-screen (except for the bottom line),
my #2 window is the top half of the screen and my #3
window is the bottom half (with an unused line between them),
and my #4 window is just like #1.
I am normally (99%) in the #1 window and am generally
unaware of the existence of wm.
But when I want
to escape from the current window I can change to window #4
to get a fresh screen (one wm nuisance is
that it puts me back in my home directory on my home machine).
Or if I want split screens, say for debugging or file comparison,
I can change to window #2 and then alternate between #2 and #3.
I think of having three window layers, the #1 layer,
the #2/#3 layer, and the #4 layer.
(In reality, wm maintains a window display order,
and changing to a window puts that window on `top',
so there is not really a #2/#3 layer.)
On a 66 line display I bet things would be much nicer.
XSome people have a window which covers all but the top line,
so they can put a clock or periodic `uptime' in the top line.
(Note: two windows \fImust\fP have an unused line between them
or else they cannot be used for simultaneous displays.)
Also, some people change the wm prefix character to `^W' or `^P'
so that `vi' is easier to use.
X.PP
The undocumented experimental \fI<wm-esc>\fPf (`fit') command is also handy.
XFor example, suppose I am in my #1 window and type ``make''.
It might take a while, so I would like to switch to another window
and read news.
But I would also like to see the progress of the make.
XSo I switch to a half-screen window and type `\fI<wm-esc>\fPf 1',
which relocates the #1 window so that it is no longer obscured.
Now I can read news and keep up with the ``make'' at the same time.
This can really jumble up the windows,
but in this case I can change back to #1
and do a `\fI<wm-esc>\fPf 1' to make it full-screen again.
X.SH
Window ``Performance'' Considerations
X.PP
There are some important performance details to consider.
XFirst, your terminal needs insert-line/delete-line
or scrolling region support for wm to work well
on anything but full-screen windows.
In particular, my #2/#3 windows are sloowww without such support.
The scrolling region is best because with insert/delete-line
scrolling in the #2 window causes the #3 window to jitter up and down.
By the way, the scrolling region capability is often omitted in
many termcap entries, so you might need to put it in.
Here is the relevant vt100 stuff, which is probably the
only scrolling region support you are likely to find:
X.DS
X.ft PO
X.\" note: the '\e' below is troff's way of saying '\'
:sc=\eE7:rc=\eE8:cs=\eE[%i%d;%dr:sr=5\eEM:
X.ft P
X.DE
XFor now, all of ``cs'', ``sc'', ``rc'', and ``sr'' must be specified
or wm will not use scrolling regions.
X.PP
By all means you should make windows be the full width of the screen.
Without that wm scrolls by redrawing the whole window.
The painful slowness is tolerable for smaller windows,
and also for faster terminal speeds.
My office terminal is at 4800 baud, and wm is okay at that speed,
but even 19200 is probably too slow for a window that is full-screen
except for the right-most column.
X.SH
WM Enhancements
X.PP
The ``Hacking WM'' document mentions several possible enhancements.
XSuggestions for other improvements to wm are welcome.
Code for any new improvements are even more welcome!
X.bp
X.TL
Hacking WM
(Obscure Details for the Hard-Core User)
X.AU
Tom Truscott
X.AI
Research Triangle Institute
P.O. Box 12194
RTP, NC  27709
(919) 541-7005
X.SH
In Praise of Matt Lennon
X.PP
Matt Lennon took an interest in Robert Jacob's Usenet wm distribution,
got it running here, and talked others into trying it out.
XFrankly, the original version was too slow to be usable,
although it was indeed interesting.
(Perhaps most interesting of all was that Jacob had a version
of wm running under UNIX V6!)
Matt reorganized the program internally and put in the first
of a series of scrolling hacks (in WMinsertln and WMdeleteln).
The resulting program shares with the original wm a simplicity of design
that is important in any program, but particularly in a window manager.
I think of the revised wm as the ``A'' version.
I am afraid a ``B'' version will be along all too soon.
X.SH
Problems with Running Programs under WM
X.PP
There are three common problems when running programs under wm.
One problem is that some programs assume
the screen is at least some minimum size, such as 24 lines and 80 columns.
Typical programs betray themselves by scribbling text
intended for ``line 24'' at random places on the screen,
or by dumping core after the ``newwin'' curses routine refuses
to create a window that encompasses that line.
XFixing such programs can be a chore,
but often one can just substitute `COLS' for 80, `LINES-1' for 23,
and so on.
Rogomatic demands 24 lines so I hacked it to overlay all lines >= LINES
onto line LINES-1, which is messy but tolerable.
XFor programs beyond hope, type \fI<wm-esc>\fPz and run the program
on the real terminal.
X.PP
A second problem is with programs that assume a specific terminal type,
such as "vt100".
Wm currently understands only the pseudo-terminal
type "wmvirt", so such programs cannot be run under wm.
It would be nice if wm could emulate an arbitrary
terminal type.
Then one could run wm on an ADM terminal
with one window emulating a vt100 and another emulating a Tektronix 4014.
Of course, wm would need to support viewports into windows.
Viewports are trivial compared to emulating 4014 graphics, however.
X.PP
A third problem is that some programs use getlogin
to determine the user's login name,
but under wm getlogin fails since no one is logged in
on the window's control terminal (pseudo-tty).
The easiest fix is to replace calls to getlogin
with calls to safegetlogin:
X.DS
X.ft PO
/*
 * Returns a user name such that uid(user name) == getuid().
 * If feasible, the session login name is used,
 * but if the real uid has been changed (e.g. via 'su')
 * or if certain file descriptors have been munged
 * then a user name corresponding to the real uid is returned instead.
 * Returns NULL if everything fails.
 * Beware!  Clobbers static data from earlier calls to getpw*.
 */

#include <pwd.h>

char *
safegetlogin()
{
	register char *p;
	register int uid;
	register struct passwd *pwd;
	static char namebuf[50];
	extern char *getlogin();

	uid = getuid();
	p = getlogin();
	/* cannot trust getlogin, so here is a security check */
	if (!p || !(pwd = getpwnam(p)) || uid != pwd->pw_uid)
		p = 0;
	/* if getlogin failed, try the real uid */
	if (!p && (pwd = getpwuid(uid)))
		p = pwd->pw_name;
	if (p) {
		strncpy(namebuf, p, sizeof(namebuf)-1);
		p = namebuf;
	}
	return(p);
}
X.ft P
X.DE
This fixes the `galaxy' and `robots' programs, for example.
We keep this routine in /usr/local/liblocal.a and link programs
that call it with `-llocal'.
Alas, one case that this misses is the command ``who  am  i''.
The trade secret status of ``who'' precludes a clearer explanation.
X.SH
XSupport for Fast Scrolling of any Rectangular Window
X.PP
A (very) few terminals support general ``scrolling rectangles.''
These are wonderful for wm because then
non-full-width windows scroll quickly.
Terminfo already has the ``set_window'' string capability,
described in `tparm' format,
to set up a scrolling rectangle.
There is no such capability in termcap so a new ``sw''
capability was invented, using the same format as terminfo.
XFor example, for the HDS Concept 108 we have:
X.DS
X.ft PO
X.\" note: the '\e' below is troff's way of saying '\'
:sw=\eEv%p1%' '%+%c%p3%' '%+%c%p2%p1%-%'!'%+%c%p4%p3%-%'!'%+%c:\e
X.ft P
X.DE
XFor the HDS 200 we have (sorry, this is untested):
X.DS
X.ft PO
X.\" note: the '\e' below is troff's way of saying '\'
:sw=\eE[%p1%{1}%+%d;%p2%{1}%+%d;%p3%{1}%+%d;%p4%{1}%+%dr:\e
X.ft P
X.DE
You also need ``sr'' (scroll_reverse) for wm to use set_window.
Wm assumes that the set_window command moves the cursor
to the rectangle's home position (upper left),
that cursor motion commands work in the rectangle,
and that the motions are relative to the origin of the rectangle.
If your terminal works differently, and it probably will,
you might have to hack wm.
Look for "SET_WINDOW" which, if defined, causes
code to be generated to support scroll rectangles.
X.SH
LIBCURSES
X.PP
Wm depends heavily on the underlying screen management software (libcurses)
for correctness and efficiency.
A number of changes were found to be needed in libcurses
to provide correctness.
The major efficiency problem has been that of providing fast scrolling.
Libcurses itself does not support insert/delete line or
scrolling regions to provide fast scrolling.
We decided not to put such support into libcurses,
because that was considered too far-reaching,
so insert/delete line and scrolling regions are handled
within special code in wm itself,
and the libcurses windows are accordingly fixed up.
Wm could support scrolling regions more efficiently
(by not switching back and forth between full screen
and window-sized regions on every newline).
It could also handle certain non-full-width windows better.
XFor example to scroll a window that covers all but the rightmost column
it could scroll all lines involved and then redraw the rightmost column.
Perhaps the termlib or other packages do that sort of thing.
Also, for non-full-width windows wm could perhaps scroll two
or more lines at a time, or possibly even wrap around
to the top line rather than scroll.
X.SH
WM and TERMINFO
X.PP
Wm can be compiled with
Pavel Curtis' public domain ``terminfo'' library
in addition to the usual one (``Curses Classic'').
During compilation the TERMINFO preprocessor variable is defined
if compilation with terminfo curses is detected,
so that appropriate code is generated.
The terminfo conventions are nicer than the classic version
so wm uses the terminfo functions and variable names,
and Curses Classic is supported by redefinitions and emulation routines.
X.PP
However, wm really should only be compiled with Curses Classic.
The terminfo version is slower, bigger, buggier, and does not
support arrow keys.
Terminfo also has more fundamental problems.
It does not provide support for the TERMCAP environment variable,
and there is no easy way to construct a terminfo binary file
analogous to the 'wmvirt' TERMCAP string.
As a result wm cannot support any terminfo-compiled applications programs.
When (if) this becomes a problem there will be additional incentive
for wm to be able to emulate an arbitrary terminal
(also see ``problems with running programs under wm'', above).
Then, in conjunction with the 4.3 kernel support for window sizes,
wm can dispense with the TERMCAP variable and emulate whatever
terminal is desired, thus supporting both termcap and terminfo.
(\fI<wm-esc>\fPt will still be needed for tip and cu.)
X.SH
WM response sluggishness
X.PP
An unfortunate current side-effect of wm is that certain
normally responsive terminal operations are now sluggish.
XFor example, if you cat a file and press <Interrupt>
several lines will be printed before the interrupt
takes effect.
Other similar special characters are also handled slowly.
The reason is that wm runs in raw mode, so such characters
are not ``instantly'' handled in the kernel.
Instead they are passed to the currently selected
pseudo-tty, which then interrupts or stops or whatever.
But any characters currently queued by wm for the user's terminal
are still printed!
(The script program has the same behavior,
but it is tolerable for the normal uses of that command.)
There does not seem to be a good way around this problem.
Wm's current approach is to
X.IP a)
Only read a few (currently 64) characters from each pseudo-tty
at a time, to avoid large queues from wm to the real tty.
X.IP b)
Have wm check the size of the output queue using the undocumented
TIOCOUTQ ioctl, and delay reading from the pseudo-ttys
if the output queue is large.
X.IP c)
Have wm reduce the read and queue sizes for a while after the user
types Control-S.
X.LP
The first two hacks keep the response to <Interrupt> at a tolerable level.
They also keep the tty high water mark from
being reached, which would put wm to sleep,
which would make response very sluggish indeed.
The last hack gives somewhat better response to Control-S.
X.PP
This approach to wm sluggishness is quite new,
so more tuning and better approaches to the problem are possibilities.
Also, the parameters have been tuned for a Gould 9050,
which is quite a fast machine, and the resulting
extra cpu involved might be intolerable on a VAX.
An easy `fix' is to comment out the TIOCOUTQ code in wm.c
(you can probably just #undef TIOCOUTQ at the top).
You might want to remove the Control-S hack as well.
X.SH
The `.wmrc' File
X.PP
The first line of .wmrc is the prefix character.
The remaining lines describe the configured windows from bottom
to top.
(The last line describes the window in which the user starts.)
Each line consists of the window name, the number of rows and columns,
and the starting row and column (zero indexed).
If the number of rows (columns) is given as zero then that dimension
``flexes'' to the height (width) of the screen,
which supposedly is useful when switching among terminals
of different sizes.
X.PP
XSeveral users have asked for the ability to specify an alternate ``shell''
in a window.
That could be done by extending the .wmrc lines to include
a command to be executed in lieu of the shell.
Other users have requested the ability to set the shell prompts
in a window dependent way, among other things.
I do not know how that might be done.
X.SH
The ``SNEAKYTERMCAP'' Method
X.PP
Ordinarily, when a window changes size, wm blasts the window
with a shell command that sets TERM and TERMCAP
to indicate the new window's size.
(This is the same shell command generated by \fI<wm-esc>\fPt.)
This not only produces clutter, it can also confuse non-shell
programs running in that window.
If your version of wm was compiled with SNEAKYTERMCAP defined,
however, a different method is used.
The TERMCAP variable is set to a filename such as /tmp/WM.33445.1
and the file contains the termcap capability string.
Then, when a window changes size the /tmp file is simply rewritten.
But there is a security problem with this method
(or with any command that uses /tmp)
and /tmp gets cluttered up with lots of ``WM'' files.
It would be better if the files were kept in a subdirectory
of each user's home directory, and if wm itself cleaned
up dead temporary files (e.g. due to a system crash).
X.SH
Browsing About in WM Windows
X.PP
XSome terminals have extra memory so one can look back
at text that scrolls off the screen.
It would be nice if wm provided that too.
One hundred lines of scrolled typescript should be adequate.
A plausible approach would be to type \fI<wm-esc>\fPv
(for `view') to put the window in browse mode.
Then input to that window is interpreted as requests
to move back and forth in the typescript,
like the `vi' scrolling commands.
Any output to the real window is held pending exit from browse mode,
which might be by typing ``:q'', at which time the window
is reset to its state on entry to browse mode.
Of course, while a window is in browse mode one can still
switch between windows, move, create, and kill windows, and so on.
X.PP
All this can be implemented cleanly with about 100 lines of code
scattered here and there (it has been written),
but what about text searching and the ability to write parts
of the typescript into UNIX files?
What about all the other nifty `vi' commands?
Why not just run `vi' (or your favorite viewing program)
in the browse window!?
Well, here is why not.
Vi has to position itself at the end of the typescript
in order to provide a ``seamless interface'' to wm.
Okay, that's easy.
We need an ``ignore first clear'' kludge so that when
vi initially redraws the screen
the window is not really redrawn.
Uh, well, wm already has kludges.
We need to suppress the vi status line (``seamless interface'' remember),
say by displaying it instead in wm's status area.
Er, uhm.  Yuck!
It could be done, but it sure would be ugly.
Alas, wm does not yet support browse mode.
SHAR_EOF
if test 17319 -ne "`wc -c < 'USINGWM'`"
then
	echo shar: error transmitting "'USINGWM'" '(should have been 17319 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Paper.jacob'" '(22963 characters)'
if test -f 'Paper.jacob'
then
	echo shar: will not over-write existing file "'Paper.jacob'"
else
sed 's/^X//' << \SHAR_EOF > 'Paper.jacob'
X.rm CH
X.ds CF "\(hy \\n(PN \(hy
X.\"
X.ds >. .
X.rm <.
X.ds >, ,
X.rm <,
X.ds [. " [
X.ds .] ]
X.\"
X.TL
User-Level Window Managers for UNIX
X.AU
Robert J.K. Jacob
X.AI
Naval Research Laboratory
Washington, D.C. 20375
X.AB
X.I Wm
manages a collection of windows on a display terminal.
Each window has its own shell or other interactive program,
running in parallel with those in the other windows.
This permits a user to conduct several interactions with the system in
parallel, each in its own window.
The user can move from one window to another, re-position a window, or
create or delete a window at any time
without losing his or her place in any of the windows.
Windows can overlap or completely obscure one another;
obscured windows can be "lifted" up
and placed on top of the other windows.
X.PP
This paper describes how such a window manager for UNIX\(dg
X.FS
X.PP
\(dgUNIX is a trademark of Bell Laboratories.
X.FE
is implemented as a set of user processes,
without modifications to the UNIX kernel.
It shows how the simple, but well-chosen
facilities provided by the original
(Version 6) UNIX kernel are sufficient to support
X.I wm .
In addition, subsequent versions of
X.I wm
exploit features of the kernel introduced into newer versions of
UNIX to provide faster and more sophisticated window operations,
still implemented entirely at the user level.
X.AE
X.SH
Introduction
X.PP
This paper describes the design of a display window manager for
UNIX implemented entirely as a set of user processes, without modifications to
the UNIX kernel.
It shows how the simple facilities provided by the original
(Version 6) UNIX kernel are sufficient to support such a window
manager.
In addition, more recent versions of the window manager exploit
features of the kernel introduced into newer versions of UNIX to
provide faster and more sophisticated operations in windows,
still implemented entirely outside the kernel.
X.PP
This window manager,
X.I wm ,
provides a UNIX
user the ability to conduct several interactions in parallel, each in
a different window on a text display terminal.
The windows may be created, moved, and temporarily or permanently erased
at any time.
They may also overlap or completely obscure one another, and such hidden or
partially hidden windows may be "lifted" and placed on top of the
other windows as desired.
XFigure 1 shows a snapshot of a
X.I wm
session in progress.
X.SH
User Interface
X.PP
The notion of organizing computer data spatially was propounded
and exploited by Nicholas Negroponte in the Spatial Data Management System\*(<.\*([.2,\|3\*(.]\*(>.
In
X.I wm ,
however, spatial cues are used only to specify a context for a dialogue.
Once a window is selected, further interactions within that window
make use of the
power and abstraction of more conventional user interface techniques.
Teitelman\*([.8\*(.]
made good use of display screen windows for
a collection of parallel interactions with an INTERLISP system.
More recently, several personal computers and workstations have adopted this
window-oriented style of dialogue as their principal mode of interaction.
Other systems similar to the present one have also been provided
under UNIX\*(<.\*([.4,\|7,\|9\*(.]\*(>.
X.PP
Traditional user interfaces for computers
that handle parallel processes
place all inputs and outputs in one chronological
stream, identifying the process associated with each, but interleaving
the data.
The Berkeley job control facilities for UNIX
provide a first attempt at improving this situation\*(<.\*([.5\*(.]\*(>.
X.PP
By contrast, a window-based user interface
enables a user to manage a collection of dialogues by
associating a spatial location with each dialogue, in much the same
way one organizes a desk.
On a desk, all input papers on all topics
are not (one hopes) placed on a single
pile in chronological order, but rather they are divided into piles by topic.
When input for a particular topic is received, the corresponding pile
is located, lifted, and placed on top of other papers, and the necessary
work is done on that pile.
Each topic may thus be associated with
and remembered in terms of a location on the desk.
Recent empirical evidence showed that such a window-oriented
user interface induced better user performance than a more
traditional scrolled message interface in a particular
situation involving several parallel interactions\*(<.\*([.6\*(.]\*(>.
X.PP
X.I Wm
conducts several concurrent dialogues with a UNIX user.
Each takes the form of a UNIX shell, to which
UNIX commands can be given and from which other interactive
programs can be initiated.
Each dialogue is conducted in a separate area of the screen or
X.I window
designated by the user.
At any moment, one of the windows is considered the current input window,
and all keyboard inputs (except for
X.I wm
commands themselves) are sent to the shell
or program associated with that window.
At any time (including in the middle of typing a command in a window),
the designation of the current window may be changed
and a different dialogue begun or resumed.
Outputs resulting from these dialogues will appear in their appropriate
windows as they are generated, regardless of which window is the
current input window.
Output destined for a portion of a window that is obscured by another
window will appear whenever that portion of the window is uncovered.
Windows can be "piled" on one another in any sequence.
X.PP
X.I Wm
was originally designed for use in an intelligent terminal
that could communicate with several computers simultaneously.
Each dialogue with a different computer was associated with a window.
The method is equally applicable to a collection of dialogues,
all with the same computer but on different topics.
XStill, any or all of the present windows can run programs to conduct
interactive dialogues with other computers
(such as
X.I telnet ).
X.SH
Design for "Vanilla" UNIX
X.PP
To implement a system of this sort,
it is necessary for one user process to be able to
manage a collection of other user processes and to mediate all of
their inputs and outputs.
XFor the inputs, it must act as a switch, directing input from the keyboard to
different programs in response to user commands.
XFor the program outputs,
it must place the output of each program in its correct
position on the screen.
X.PP
If adequate primitives for creating and manipulating processes
and for catching their inputs and outputs are provided by the
operating system, a window manager can be built entirely as a
user program.
The original design of UNIX, with its
X.I pipe
and
X.I fork
mechanisms provides a user the right primitives to design such a
system in an elegant fashion without kernel modifications.
X.PP
X.I Wm
initiates and manages its own collection of UNIX processes, including
those run in response to entered commands.
Any conventional UNIX program can be used from
X.I wm ,
provided it does not make significant
assumptions about the nature of its input
and output devices\-that is, it should treat input and output from a
pipe as equivalent to input and output from a terminal or other source.
X.PP
X.I Wm
runs as
X.I 2n+2
parallel UNIX processes of four different types
(where
X.I n
is the number of windows in use).
The division into processes is dictated by the fact that the original UNIX
X.I read
call on an empty pipe or input device causes a process to
block until input becomes available.
Hence there is a separate process for each pipe or device that must be
read asynchronously.
Each such process contains a loop that reads from its
particular pipe or device,
processes the input, and then waits for more.
XFigure 2 shows the processes and pipes that comprise
X.I wm .
X.PP
The
X.B main
process reads from and waits for input from the keyboard.
Input consisting of text is sent to the shell process
associated with the current window and also to the
X.B scrn
process, described below, for echoing.
Input consisting of
X.I wm
commands is interpreted by
X.B main ,
translated into one or more primitive commands plus arguments, and sent to
X.B scrn
for execution.
XSimple changes in the input command language are thus localized in
X.B main .
To change the name, input syntax, or prompt for a command, only the code in
X.B main
need be modified.
XSince input commands are reduced to a somewhat more general set of
primitive commands, some simple new commands may be implemented entirely in
X.B main
as aliases for specific uses or combinations
of the existing primitive commands.
X.PP
The
X.B scrn
process handles all outputs to the screen.
All processes that want to affect the screen must thus place requests
to do so on a common pipe.
X.B Scrn
reads these instructions from the pipe and makes appropriate modifications to
the screen.
X.I Wm
commands that affect the screen layout, such as moving a window, are placed
on this pipe by
X.B main
and handled by
X.B scrn .
Output text characters from the individual shell processes
that belong in a window
are also placed on this pipe along
with a window identifier and a bit
indicating whether the character should be displayed immediately or
just remembered for the next time the display is refreshed.
X.B Scrn
then compares the desired configuration of the screen to a buffer
containing the actual configuration
and transmits the necessary updates.\(dg\ 
X.FS
X.PP
\(dgThe update algorithm
is less sophisticated than the optimization performed in the
X.I curses
package\*(<,\*([.1\*(.]\*(>,
but
X.I curses
was not available in Version 6 UNIX.
This update algorithm
is also somewhat easier to adapt to unusual terminals, as seen below.
X.FE
X.PP
There is a
X.B shell
process associated with each window.
This is simply the standard UNIX
X.I sh
(or any other designated program).
These
X.B shell
processes have no direct access to the terminal, but run as captives of
X.I wm ,
connected by pipes, so that their inputs and outputs can be mediated.
The input to each of these processes is a pipe from
X.B main ,
since
X.B main
knows which window is the current input window and can place the typed
input text on the pipe to the corresponding
X.B shell
process.
All outputs of the
X.B shell
processes must be sent to
X.B scrn
to be displayed, but they must first be tagged with the name of the
window in which they belong.
X.PP
To do this, each window has a
X.B shmon
process that monitors the output of the corresponding
X.B shell
process.
The output of each
X.B shell
process is a pipe to a corresponding
X.B shmon
process.
Each time output appears on that pipe,
X.B shmon
reads it, packages it with a header identifying its window,
and then places it on the common request pipe to
X.B scrn .
X.PP
X.I Wm
comprises about 1000 lines of C code\-about 500 each for the
X.B main
and
X.B scrn
processes and less than 50 for the
X.B shmon
process.
X.SH
Remarks and Problems with "Vanilla" UNIX
X.PP
Each window in
X.I wm
emulates an individual glass teletype.
Inputs appear in the bottom and scroll off the top of a window.
XSince the standard input and output for all programs run by
X.I wm
are really pipes,
all programs run under
X.I wm
should treat their inputs and outputs
simply as streams of characters, without distinctions between
terminals and pipes.
The fact that UNIX and most of its original programs permit a pipe to be
substituted for a terminal input or output stream is an elegant
aspect of UNIX that is crucial to
X.I wm .
This obtains for most UNIX programs;
they perform individual "building-block" functions and are thus intended
to be equally usable individually from the terminal
or as filters connected to other programs to perform more complex tasks.
Programs that try to determine whether they
have access to a real terminal may behave differently or even refuse to run with
X.I wm .
XFor example,
X.I stty
is meaningless when applied to a pipe rather than a terminal,
X.I vi
will refuse to run from a pipe,
and
X.I csh
will not allow job control if it cannot access the terminal.
(However, note that
X.I wm
is really an alternate approach to controlling concurrent jobs.)\ 
X.PP
A very rudimentary facility for supporting a
whole-screen-oriented program is provided.
It creates a special temporary window,
creates a
X.I termcap
description of a "terminal" that occupies only the corresponding
area of the actual
screen, and then provides that description and direct access to the terminal
to the screen-oriented program until the latter exits.
X.PP
XSince
X.I wm
operates with the terminal in raw mode,
it must provide for itself the input line editing functions normally
provided by the teletype driver.
X.PP
Because of the architecture of
X.I wm ,
there are no pipes that
connect one window to another, hence there is no explicit facility for
communication between windows.
It can be achieved, however, through the file system.
A program in one window
can append to a file while one in another window continuously tries to read
from the end of that file.
X.SH
Terminal Dependencies
X.PP
While the newer version of
X.I wm
uses
X.I curses
to perform all terminal-dependent operations in a
terminal-independent fashion, terminal dependencies can be
isolated fairly easily even without
X.I curses .
All terminal-dependent code in the original
X.I wm
is restricted to a collection of five simple procedures.
They were originally written separately for each type of terminal,
but have also been written in terms of the terminal-independent interface,
X.I termcap ,
for systems that have it.
X.PP
The five procedures perform the following tasks:
X.RS
X.IP \fBttyinit\fP 15
Performs any necessary initialization for the terminal.
X.IP \fBttyclose\fP 15
Performs any necessary closing for the terminal before
X.I wm
exits or suspends.
X.IP \fBttymov\fP 15
Moves the terminal cursor to a given row and column.
X.IP \fBclearscreen\fP 15
Clears the terminal screen.
X.IP \fBclearline\fP 15
Clears from the cursor to end of the current line
(not mandatory).
X.RE
X.LP
XFor each of several common terminals, the definitions of these
procedures comprise about 15 lines of code altogether.
X.PP
This approach isolates terminal dependencies sufficiently that
X.I wm
can also be adapted for use on graphic displays
by replacing the above procedures and making other minor changes.
XSuch a version of
X.I wm
has been written to produce output suitable
for the standard UNIX plot filters (plus some added commands for
raster graphic displays) and used with a Genisco frame buffer.
Windows may be in various colors and may use different fonts for their text.
X.SH
Design for Version 4.2 UNIX
X.PP
Berkeley Version 4.2 VAX UNIX provides new features that make it
possible to improve
X.I wm
significantly.
By using pseudo-terminals instead of pipes for interprocess
communication, several of the problems discussed above disappear.
In addition, the synchronous input/output multiplexing feature of
the new UNIX makes the former division of
X.I wm
into processes as dictated by the blocking read unnecessary.
A revised version of
X.I wm ,
then, solves many of the earlier problems and runs in a single
process (plus the user's shells).
It is, however, less interesting and certainly less portable than
the initial version.
Again, the facilities are provided entirely in user-level processes,
without the need for kernel modifications.
X.PP
This version of
X.I wm
reads from the keyboard and also from the pseudo-terminals associated
with each window, in a round-robin, using the multiplexed read call
X.I (select) .
Keyboard input consisting of text is sent to the pseudo-terminal
associated with the current window.
The pseudo-terminal driver itself handles
echoing (when enabled) and intraline editing,
obviating the need for
X.I wm
to duplicate these functions.
Keyboard input consisting of
X.I wm
commands is processed directly;
text input is sent to the appropriate pseudo-terminal.
Output from the pseudo-terminals is read by
X.I wm ,
interpreted in terms of
the cursor control commands of a simple virtual terminal defined by
X.I wm ,
and then added to the appropriate screen window for processing by the
X.I curses
package\*(<.\*([.1\*(.]\*(>.
X.PP
This version of
X.I wm
comprises about 1000 lines of C code, all in a single process.
XFigure 3 shows the architecture of the program.
X.SH
Remarks and Problems with Version 4.2 UNIX
X.PP
XSince each window is implemented with a pseudo-terminal, the fact
that a program is running in a window rather than on a real
terminal is transparent to most programs.
XSpecifically,
most screen editors and games may be used, and
X.I stty
may be called to change characteristics such as echoing or line editing
individually for each window.
XFor example, note that one of the windows in Figure 1 is running
X.I vi ,
which has adjusted itself to the window size.
XSome programs, however, assume that their output devices are
of some minimum size;
they will not run well in very small windows.
Also, programs that attempt to manipulate the controlling
terminals of process groups will not work properly under
X.I wm .
XFor this reason,
X.I csh
cannot currently be run in the individual windows instead of
X.I sh .
X.PP
It is generally
not possible to move a window while an interactive
program (other than a shell) is running in it.
XFirst, this is necessary because, whenever a window is moved,
X.I wm
sends a shell command to change the
X.I TERMCAP
variable for the shell in that window, to describe its new size.
A more fundamental reason is that the
X.I curses
library routines (sensibly)
do not expect the terminal description to change while
a program is running, and so make no provision for checking for or
adapting to such changes.
X.PP
XSince pseudo-terminals are a system-wide resource and are usually fixed in
number, the total number of
windows that can be in use by all users at any one time
is limited to the number of pseudo-terminals made available to
X.I wm .
X.PP
A facility for communicating between windows is now easy to provide.
XSince each window uses a pseudo-terminal, any data sent to its
slave pseudo-terminal
will appear in the window;
and pseudo-terminals are in the name space of the UNIX file
system and thus available to other processes.
To simplify use of this feature, when a window is created and a
pseudo-terminal obtained for it,
a link to the name of its slave pseudo-terminal is created
in the user's current directory.
Any program inside or outside
X.I wm
can then write to or read from that file name without prearrangement.
X.SH
Program Versions
X.PP
These programs are written in C for use with UNIX.
There are three principal versions:
X.B wm.v6 ,
X.B wm.v7 ,
and
X.B wm.v42 .
The first, as described above,
runs under unmodified Version 6 UNIX on a PDP-11.
The code for this version was frozen and abandoned several years
ago, but it is still available.
X.B Wm.v7
runs under Version 7 UNIX,
and the same code also runs on Berkeley 2.8
and also on a VAX on Berkeley 4.1 and 4.2.
No changes in the source code are required between the PDP-11
and VAX, except that constants for the maximum number and size of windows
are limited by the available memory on a PDP-11.
This version
is similar in design to
X.B wm.v6 ,
which was described above, but has a number of improvements.
The newest version,
X.B wm.v42 ,
runs only under Berkeley 4.2 on a VAX,
as described in this paper.
It uses the
X.I select
synchronous input/output multiplexing call,
which is unique to 4.2, and also other features
that are found in some, but not all, versions of UNIX, such as
pseudo-terminals and
X.I curses .
At this writing, this version is not yet thoroughly tested on 4.2.
An intermediate version for use with Versions 2.8 or 4.1
can also be constructed by adapting some of the features of
X.B wm.v42
to
X.B wm.v7 .
XFor example, the use of
X.I curses
can certainly be adapted to 2.8;
pseudo-terminals are available on some versions of 4.1;
and some versions of 4.1 can also simulate a non-blocking read
on a pseudo-terminal or a short time-out.
X.SH
Availability
X.PP
Three versions of
X.I wm
are available to interested researchers.
X.RS
X.IP "\fBwm.v6\fP" 10
XFor Version 6 UNIX.
X.IP "\fBwm.v7\fP" 10
XFor Version 7 UNIX, also runs on Berkeley 2.8, 4.1, and 4.2.
X.IP "\fBwm.v42\fP" 10
XFor Berkeley 4.2 UNIX only (but has some features than can be retrofitted to
X.B wm.v7 ).
X.RE
X.LP
The code can be obtained over the Arpanet by sending a request to
X.\" the two (hy is to prevent the hyphenation algorithm from splitting nrl-css
jacob at nrl\(hycss.
The author can also be reached via uucp
at ...!decvax!linus!nrl\(hycss!jacob.
X.SH
Conclusions
X.PP
It is demonstrably feasible to provide a useful and efficient
display window management facility in UNIX at the user level,
without support from kernel modifications.
XSuch a facility can even be provided for the original Version 6 UNIX,
although some improvements are obtainable by exploiting features
provided by more recent versions of UNIX.
X.SH
Acknowledgments
X.PP
I would like to thank
Mark Cornwell, Rudy Krutar, Alan Parker, and Mark Weiser
for helpful discussions of this work.
X.]<
X.\"Arnold.K.-1980-1
X.ds [F 1
X.]-
X.ds [A K. Arnold
X.ds [T Screen Updating and Cursor Movement Optimization
X.ds [R University of California, Berkeley
X.ds [D 1980
X.nr [T 0
X.nr [A 0
X.nr [O 0
X.][ 4 tech-report
X.\"Bolt.R.-1979-2
X.ds [F 2
X.]-
X.ds [A R. Bolt
X.ds [T Spatial Data Management
X.ds [I Architecture Machine Group, Massachusetts Institute of Technology
X.ds [R Technical Report
X.ds [D 1979
X.nr [T 0
X.nr [A 0
X.nr [O 0
X.][ 4 tech-report
X.\"Herot.C.F.-1980-3
X.ds [F 3
X.]-
X.ds [A C.F. Herot
X.as [A ", R. Carling
X.as [A ", M. Friedell
X.as [A ", and D. Kramlich
X.ds [T A Prototype Spatial Data Management System
X.ds [J Computer Graphics
X.ds [V 14
X.ds [N 3
X.ds [P 63-70
X.nr [P 1
X.ds [D 1980
X.nr [T 0
X.nr [A 0
X.nr [O 0
X.][ 1 journal-article
X.\"Horton.M.-1982-4
X.ds [F 4
X.]-
X.ds [A M. Horton
X.ds [I personal communication
X.ds [D September 8, 1982
X.nr [T 0
X.nr [A 0
X.nr [O 0
X.][ 2 book
X.\"Joy.W.-1980-5
X.ds [F 5
X.]-
X.ds [A W. Joy
X.ds [T An Introduction to the C Shell
X.ds [R University of California, Berkeley
X.ds [D November 1980
X.nr [T 0
X.nr [A 0
X.nr [O 0
X.][ 4 tech-report
X.\"Murrel.S.-1983-6
X.ds [F 6
X.]-
X.ds [A S. Murrel
X.ds [T Computer Communication System Design Affects Group Decision Making
X.ds [J Proc. Human Factors in Computer Systems Conference
X.ds [D 1983
X.ds [P 63-67
X.nr [P 1
X.nr [T 0
X.nr [A 0
X.nr [O 0
X.][ 1 journal-article
X.\"Pike.R.-1983-7
X.ds [F 7
X.]-
X.ds [A R. Pike
X.ds [T Graphics in Overlapping Bitmap Layers
X.ds [J ACM Transactions on Graphics
X.ds [V 2
X.ds [N 2
X.ds [D 1983
X.nr [T 0
X.nr [A 0
X.nr [O 0
X.][ 1 journal-article
X.\"Teitelman.W.-1979-8
X.ds [F 8
X.]-
X.ds [A W. Teitelman
X.ds [T A Display Oriented Programmer's Assistant
X.ds [J International Journal of Man-Machine Studies
X.ds [V 11
X.ds [P 157-187
X.nr [P 1
X.ds [D 1979
X.nr [T 0
X.nr [A 0
X.nr [O 0
X.][ 1 journal-article
X.\"Weiser.M.-1983-9
X.ds [F 9
X.]-
X.ds [A M. Weiser
X.as [A ", C. Torek
X.as [A ", R. Trigg
X.as [A ", and R. Wood
X.ds [T The Maryland Window System
X.ds [R Technical Report 1271
X.ds [I Computer Science Department, University of Maryland
X.ds [D 1983
X.nr [T 0
X.nr [A 0
X.nr [O 0
X.][ 4 tech-report
X.]>
SHAR_EOF
if test 22963 -ne "`wc -c < 'Paper.jacob'`"
then
	echo shar: error transmitting "'Paper.jacob'" '(should have been 22963 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0



More information about the Mod.sources mailing list