GWM like any other window manager is in charge of all that is exterior to other application windows on the display. It performs its task by 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.
GWM is built upon the notion of a wob, which, not unlike an X Widget is an object composed of:
Wobs are not directly created with WOOL constructors, they are 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:
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) 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.
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.
Other gwm objects are just X objects (fonts, pixel colors ...) that are referenced by their X id, and are accessed via encapsulating WOOL types, such as Numbers or Pixmaps.
WOOL is a lisp interpreter of a special kind, since it has some important design differences from ``real'' lisps:
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:
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 borderwidth will actually resize the corresponding X window's border, and declaring a local value for it by a (with (wob-borderwidth 3) ...) will actually change the borderwidth of the current wob on the screen during the execution of the with body, and then revert to the previous value.
When you start GWM, it:
When an event is sent to a 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.
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:
(plug-make '(label-make window-name))
which creates a plug whose text is fetched as the name of the window on each realization, you do not have to explicitly eval a quoted expression.
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:
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.
Any program can make GWM execute any WOOL code by putting the WOOL code to execute as an ASCII string in the 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 gwmsend in the contrib/gwmsend directory in the distribution to send commands to GWM. It takes its first argument and puts in the GWM_EXECUTE property on the root window. It can thus be used like:
gwmsend '(? "Hello there\n")'
A better way is to use the -I option to make GWM read its standard input for commands. a recommended use is to run not gwm directly but a command like:
xterm -title gwm -e fep gwm -IP
fep is a pseudo-tty driver which gives its argument line editing and history capabilities, like ile or the GNU library readline.
If you want to communicate with GWM more interactively, via WOOL, you can use the program gwmchat (in the contrib/gwmchat directory). Start 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 .xinitrc or .xsession or correspondingly, where you normally would start GWM, you may instead have something like:
or:
xterm -e gwmchat
xterm -geometry =80x16-1-1 -e gwmchat -f vtwm
gwmchat can be compiled to use the readline package. This is strongly recommended if it is available and if 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).
On each screen it manages, GWM will maintain a hidden window whose X Id will be given as a 32-bit Id in the GWM_RUNNING property on the root window and the hidden window itself. Thus, if this window exists, and has the GWM_RUNNING property set, you can be sure that the screen is managed by GWM.