334 lines
14 KiB
TeX
334 lines
14 KiB
TeX
\chapter{Overview}
|
|
|
|
\sloppy
|
|
|
|
{\GWM} like any other window manager is in charge of all that is {\bf
|
|
exterior} to other application windows on the display. It performs its task
|
|
by {\bf decorating} the existing windows on the screen with its own windows.
|
|
The appearance and behavior of these windows are described by the user through
|
|
programs written in the lisp-like {\WOOL} language, which are interpreted by
|
|
the built-in {\WOOL} interpreter of {\GWM}.
|
|
|
|
The {\GWM} Window manager is composed of 2 modules: the window manager itself,
|
|
{\GWM}, and the lisp interpreter {\WOOL}. The role of the garbage-collected
|
|
{\WOOL} objects is to build shared descriptors that will be used by {\GWM}
|
|
to build its (non-shared and non-garbage-collected) objects.
|
|
|
|
{\GWM} was designed in 1988 and was developed on 68020 unix stations with 4K
|
|
of main memory, and thus tradeoffs in its design has been made to make it as
|
|
efficient as current C window managers, often at the expense of ease of
|
|
customization. But the power is there under the hood if you need it.
|
|
|
|
My main research interest was on window management metaphors, but the design
|
|
and development of the platform flexible enough to implement my views as
|
|
{\WOOL} profiles has taken me too much time, and I did not find time to
|
|
implement the rooms-like metaphors I wanted to try. But I, and some others,
|
|
still use only {\GWM} as it provides features yet unseen in any other WMs to
|
|
date.
|
|
|
|
\section{GWM Window OBjects: the wobs}
|
|
|
|
{\GWM} is built upon the notion of a {\bf wob}, which, not unlike an X {\sl
|
|
Widget\/} is an object composed of:
|
|
|
|
\begin{description}
|
|
|
|
\item[an X11 window] used to display the wob on the screen (output)
|
|
|
|
\item[a {\WOOL} finite state machine] used to trigger {\bf WOOL}
|
|
functions in response to X11 events sent to the wob (input)
|
|
|
|
\end{description}
|
|
|
|
Wobs are not directly created with {\WOOL} constructors, they are {\bf
|
|
described}, and {\GWM} uses this description to physically create the
|
|
wobs when it needs to, when decorating a new client window for instance.
|
|
|
|
Like any X11 window, the user can choose the width, color(s), and tiling
|
|
pixmap of the border of the wob (which is considered to be in the wob for
|
|
input purposes). There are four kinds of wobs:
|
|
|
|
\begin{description}
|
|
|
|
\item[Window] An X11 application, such as XTERM(1) or XCLOCK(1) usually opens
|
|
one or more windows directly on the screen (in fact the {\em root window\/}).
|
|
We will call these windows, which are not created by {\GWM}, {\bf client
|
|
windows}. {\GWM} will ``decorate'' these client windows by {\em
|
|
reparenting\/} them, i.e. by creating a {\bf Window} wob and making the client
|
|
window a son of this newly created window.
|
|
|
|
A window is a wob made by creating a new toplevel X window, reparenting the
|
|
client window as its child, and framing it with four (optional) {\em bars},
|
|
children of the new toplevel window. Note that the inside of a window wob is
|
|
thus never visible, since it is entirely covered by the bars and the client
|
|
window.
|
|
|
|
\item[Bar] The only extensible wob, it has a width and an extensible length.
|
|
It is a line (vertical or horizontal) of bars or {\em plugs\/} centered on the
|
|
axis of the bar with optional stretchable space between them. Horizontal bars
|
|
contains vertical bars and vertical bars contains horizontal bars.
|
|
|
|
\item[Plug] The simplest of all wobs, its contents is just a graphic
|
|
which is displayed in their X window. It acts thus like some kind of button.
|
|
Current graphics are text and pixmaps.
|
|
|
|
\item[Menu] A bar of bars (horizontal menus consist of a
|
|
horizontal bar of vertical bars, vertical menus are a vertical bar of
|
|
horizontal ones).
|
|
|
|
Menus are the only ``stand-alone'' wobs, their windows are directly created
|
|
by {\GWM} on the screen. They can be used to implement pop-up, pull-down or
|
|
fixed menus, control panels, message windows and icon boxes.
|
|
|
|
\end{description}
|
|
|
|
\subsubsection{Other GWM objects}
|
|
|
|
Other gwm objects are just X objects (fonts, pixel colors \ldots) that are
|
|
referenced by their X id, and are accessed via encapsulating
|
|
{\WOOL} types, such as Numbers or Pixmaps.
|
|
|
|
\section{WOOL objects}
|
|
|
|
{\WOOL} is a lisp interpreter of a special kind, since it has some important
|
|
design differences from ``real'' lisps:
|
|
|
|
\begin{description}
|
|
|
|
\item[incremental garbage collection] {\WOOL} has a {\sl reference-count\/}
|
|
driven memory management scheme. This means that the load of memory
|
|
management is evenly distributed on all phases of computing, thus avoiding
|
|
the dreadful garbage collection pauses. But, since reference count memory
|
|
management doesn't work with circular lists, no {\WOOL} function allows the
|
|
user to do physical replacements on lists\footnote{In fact, some do, but are
|
|
flagged as ``for experts only'' in the documentation}.
|
|
|
|
\item[no real lists, but arrays] {\WOOL} lists are internally stored as
|
|
arrays, speeding up list scanning. We do not really need the
|
|
generality of the chained cells model, since we do not want to have circular
|
|
lists.
|
|
|
|
\item[monovalued atoms] In classical lisp dialects, you can give a variable
|
|
and a function the same name without conflict. In {\WOOL}, an atom can only
|
|
have one value.
|
|
|
|
\item[internally typed objects] All of the {\WOOL} interpreter is written in
|
|
an object oriented way. This is not visible to the user, since we do not
|
|
offer a way to define user types, but it greatly improves the modularity of
|
|
the code, and allows us to provide generic functions, such as the \verb"+"
|
|
function operating on numbers, lists, or strings.
|
|
|
|
\end{description}
|
|
|
|
{\WOOL} alas lacks lots of features from real lisps, for the sake of small
|
|
footprint. But the {\WOOL} code accounts for about 50k of the total text size of
|
|
150k of {\GWM}.
|
|
|
|
The different {\WOOL} objects are:
|
|
|
|
\begin{description}
|
|
|
|
\item[atoms] associates any {\WOOL} object to any other via a hash table.
|
|
Only one wool object can be referenced, which implies that a \verb"(setq foo1)"
|
|
assignment will remove any function definition made by \verb"(defun foo ...)".
|
|
There is {\bf no} limit on the length of atom names. Atom names can
|
|
be composed of any printable ASCII character except {\tt " ' ( )}, and
|
|
cannot begin by a digit.
|
|
|
|
\item[active values] are predefined atoms that can be used as atoms or
|
|
functions. If \verb"foo" is an active value, then \verb"foo" and
|
|
\verb"(foo)" give the same result, and the calls \verb"(setq foo obj)" and
|
|
\verb"(foo obj)" have the same effect.
|
|
|
|
Active values are just like other atoms, but setting and evaluating them
|
|
trigger specific functions to allow for greater expressive power. For
|
|
instance, just setting a wob's \verb"borderwidth" will actually resize the
|
|
corresponding X window's border, and declaring a local value for it by a
|
|
\verb"(with (wob-borderwidth 3) ...)" will actually change the borderwidth
|
|
of the current wob on the screen during the execution of the \verb"with"
|
|
body, and then revert to the previous value.
|
|
|
|
\item[numeric variables] are atoms that can only store integer values. Like
|
|
active values, they can be used as variables or functions. Setting them to
|
|
\verb"()" or \verb"t" equivalent to setting them to \verb"0" or \verb"1".
|
|
|
|
\item[namespaces] are sets of variable names that have a different value for
|
|
each state of the namespace. For instance, the most useful namespace is the
|
|
\verb"screen." one, having one state for each screen. So each name in this
|
|
namespace, such as \verb"white", can hold a screen-dependent value that will
|
|
always eval to the correct value relative to the screen.
|
|
|
|
\item[integers] are 32-bit signed integer values.
|
|
|
|
\item[strings] are 8-bit strings of characters, with no size limit.
|
|
|
|
\item[functions] may evaluate or not their arguments and have a fixed
|
|
or variable parity.
|
|
|
|
\item[fsms] the finite state machines. They are {\WOOL} objects shared by
|
|
wobs and respond to both X events and {\WOOL}-made events, the so-called
|
|
``user'' events.
|
|
|
|
\item[wobs descriptors: plug, bar, menu, client] are used by {\GWM} to build
|
|
its wobs.
|
|
|
|
\item[X objects: pixmaps, cursors, events, labels] allow X
|
|
resources to be shared via the {\WOOL} memory management.
|
|
|
|
\item[internal objects] used to improve efficiency (These include
|
|
collections and quoted expressions).
|
|
|
|
\end{description}
|
|
|
|
\section{Operation}
|
|
|
|
When you start {\GWM}, it:
|
|
|
|
\begin{itemize}
|
|
|
|
\item connects to the display it must manage to initialize its X11 structures
|
|
|
|
\item reads and interprets the user's {\WOOL} profile (searched for in a
|
|
user-defined path, see usage). This profile must define at least two
|
|
{\WOOL} functions:
|
|
|
|
\begin{description}
|
|
\item[describe-window] which will be called by {\GWM} to know how to decorate
|
|
any client window and must return a list of two window descriptors, one for
|
|
the window itself, and one for the associated icon;
|
|
\item[describe-screen] which will be called by {\GWM} for each managed
|
|
screen and must return a window descriptor;
|
|
\end{description}
|
|
|
|
\item looks to see if it is the only window manager running; if not, it
|
|
aborts.
|
|
|
|
\item decorates the managed screens by calling the user-defined {\tt
|
|
describe-screen} function for each one, with the \verb"screen" active value
|
|
being set to the current screen.
|
|
|
|
\item decorates all already mapped client windows, by calling {\tt
|
|
describe-window} with the current client window being set to each window.
|
|
|
|
\item executes the (user-defined) opening function for each screen.
|
|
|
|
\item enters {\GWM} main loop, which consists in:
|
|
|
|
\begin{itemize}
|
|
\item waiting for an X event
|
|
|
|
\item examining the received event, and if it is for an existing wob, sends
|
|
it to the {\em fsm\/} of this wob, else if it is a new window which is being
|
|
mapped for the first time, decorates it (by calling {\tt describe-window})
|
|
\end{itemize}
|
|
|
|
When an event is sent to a {\em fsm}, it is matched against the
|
|
transitions in the current state of the fsm, and as soon as one matches, the
|
|
corresponding {\WOOL} expression is evaluated, and the fsm changes state if
|
|
necessary. If no transition is waiting for the event, it is discarded.
|
|
|
|
\end{itemize}
|
|
|
|
\section{Lazy evaluation}
|
|
|
|
For sub-wobs of wobs, i.e., bars of a window, plugs of a bar, bars of a
|
|
menu, and menu of any wob, lazy evaluation is performed. That is, on the
|
|
realization of the wob the field is re-evaluated if the result is not
|
|
of the expected type. This allows for constructs such as:
|
|
|
|
{\exemplefont\begin{verbatim}
|
|
(plug-make '(label-make window-name))
|
|
\end{verbatim}}
|
|
|
|
which creates a plug whose text is fetched as the name of the
|
|
window on each realization, you do not have to explicitly \verb"eval" a
|
|
quoted expression.
|
|
|
|
\section{Screen-dependent objects}
|
|
|
|
An invocation of {\GWM} can manage all screens attached to a display (there
|
|
is one keyboard and mouse per display), but in X, screens are very distinct
|
|
worlds. If you create a pixmap or a color on a screen, you cannot use it on
|
|
another one. The list of objects created on one screen that cannot be used
|
|
on another is:
|
|
|
|
\desc{pixmaps}{Objects}{made by}{
|
|
colors & color-make\\
|
|
pixmaps & pixmap-make, label-make, active-label-make\\
|
|
cursor & cursor-make\\
|
|
menus & menu-make\\
|
|
}
|
|
|
|
And of course, all the wobs and windows are screen-specific.
|
|
|
|
\section{Sending commands to GWM}
|
|
|
|
Any program can make {\GWM} execute any {\WOOL} code by putting the {\WOOL}
|
|
code to execute as an ASCII string in the {\bf GWM\_EXECUTE}
|
|
\label{GWM_EXECUTE} property on any root window or client window
|
|
of the screens managed by {\GWM}, which will parse and evaluate the given
|
|
string with the current window being the one on which the property was set.
|
|
|
|
This feature is built in, so that it will work regardless of the
|
|
profile used.
|
|
|
|
You can also use the program {\tt gwmsend} in the contrib/gwmsend
|
|
directory in the distribution to send commands to {\GWM}.
|
|
It takes its first argument and puts in the {\bf GWM\_EXECUTE} property on
|
|
the root window. It can thus be used like:
|
|
\begin{verbatim}
|
|
gwmsend '(? "Hello there\n")'
|
|
\end{verbatim}
|
|
|
|
A better way is to use the \verb|-I| option to make {\GWM} read its standard
|
|
input for commands. a recommended use is to run not \verb|gwm| directly but a
|
|
command like:
|
|
\begin{verbatim}
|
|
xterm -title gwm -e fep gwm -IP
|
|
\end{verbatim}
|
|
\verb|fep| is a pseudo-tty driver which gives its argument line editing and
|
|
history capabilities, like \verb|ile| or the GNU library \verb|readline|.
|
|
|
|
\section{Using {\tt gwmchat} as a shell to GWM}
|
|
|
|
If you want to communicate with {\GWM} more interactively, via {\WOOL}, you
|
|
can use the program {\tt gwmchat} (in the contrib/gwmchat
|
|
directory). Start {\tt gwmchat} in any
|
|
terminal window, with the same flags as you would have given {\GWM}. It
|
|
forks off {\GWM} and then waits for commands to send it. Output from {\GWM}
|
|
goes to the same terminal window.
|
|
|
|
In your {\tt .xinitrc} or {\tt .xsession} or correspondingly, where
|
|
you normally would start {\GWM}, you may instead have something like:
|
|
\begin{verbatim}
|
|
xterm -e gwmchat
|
|
\end{verbatim}
|
|
or:
|
|
\begin{verbatim}
|
|
xterm -geometry =80x16-1-1 -e gwmchat -f vtwm
|
|
\end{verbatim}
|
|
|
|
{\tt gwmchat} can be compiled to use the {\tt readline} package. This
|
|
is strongly recommended if it is available and if {\tt gwmchat} is to
|
|
be used in other ways than from inside Emacs, since otherwise it will
|
|
have no command line editing mechanisms whatsoever (other than erasing
|
|
backwards).
|
|
|
|
% Obsolete formulation
|
|
%\section{Sending commands with {\tt gwmsend} }
|
|
%
|
|
%If you rather want to send commands to {\GWM} one at a time, or to an
|
|
%already running {\GWM}, you could use the program {\tt gwmsend}. It takes
|
|
%a {\WOOL} command as argument and sends it to {\GWM}:
|
|
%\begin{verbatim}
|
|
% gwmsend '(? "Hello there\n")'
|
|
%\end{verbatim}
|
|
|
|
\section{Checking that GWM is running}
|
|
|
|
On each screen it manages, {\GWM} will maintain a hidden window whose
|
|
X Id will be given as a 32-bit Id in the {\bf GWM\_RUNNING} property
|
|
on the root window {\bf and} the hidden window itself. Thus, if this
|
|
window exists, and has the {\bf GWM\_RUNNING} property set, you can be
|
|
sure that the screen is managed by {\GWM}.
|