Copying

Sawfish is copyright (C) 1999 John Harper and is released under the
terms of the GNU General Public License. See the included file
COPYING for the full text of the license (or see Copying).

This is free software - you are welcome to redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2, or
(at your option) any later version.

Sawfish is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

Introduction

Sawfish is a lisp-extensible window manager for X11. Its aim is to
allow all areas of window management (decoration, manipulation) to be
customized as far as is possible, yet still remain as fast or faster
than existing window managers.

Despite this extensibility its policy is very minimal compared to most
window managers. It does not implement desktop backgrounds,
applications docks, or other things that may be achieved through
separate applications.

All high-level window management functions are implemented in Lisp for
future extensibility or redefinition. Also, most received events are
exported to the Lisp environment through key-bindings and hooks,
similar to in Emacs. These events include pointer behavior and many
internal X11 events.

Sawfish uses the librep Lisp environment (see Top), this is a run-time library implementing a
language similar to Emacs Lisp (see Top), but with many extensions, and using lexical
instead of dynamic scope. This manual assumes at least a basic
knowledge of the language.

News

This lists the user-visible changes made to Sawfish, and which releases
they occurred between. For more detailed information see the
ChangeLog files in the Sawfish source tree.

0.31

Requires librep version 0.13

Organized all lisp code into a hierarchy of modules. Root points
are sawfish.wm for window manager code, sawfish.ui for
configurator and sawfish.gtk for GTK+ utilities

Compatibility should have been preserved as far as possible, through
the use of module aliases. The user module that unmodularized
user code is loaded in should look very similar to the old environment.
However, code using private functions, probably will not work

New features written as modules can either import modules individually,
or just open sawfish.wm to get the core functionality

All command handling is now written in Lisp. It's fully
compatible except for how commands are defined. Since there is no
longer a unified namespace the mapping from names to command
definitions is maintained separately.

define-command and autoload-command add entries to this
mapping. define-command takes a name and a function (and some
other optional arguments). The old style of defining commands still
works, but only in the user module

sawfish-client now provides the same repl as the normal
rep program. E.g. this allows the module system to be easily
inspected

Also, the module of each loaded theme is available for inspection under
themes.theme-name. (With themes using top-level defines
instead of a single let* block, this is useful for debugging)

sawfish.client module provides lisp functions for
communicating with a running window manager. Also, the protocol has
been modified to support proper communication of errors, which are then
re-raised on the client-side. This should make debugging client-server
code more obvious

`Action' parts of menu items may now be lisp objects that don't
have a read syntax. (E.g. this allows closures to be used, avoiding the
problems arising from modularization)

Handle ConfigureRequest events in a way that is compliant
with the ICCCM--honour the window's win_gravity setting
(defaulting to NorthWest gravity), instead of assuming
Static gravity

Support more GC attributes in the sawfish.wm.util.x plugin
(Ryan Pavlik)

Support for handling arbitrary windows as extra "root" windows.
Used, e.g., to support Nautilus' desktop window. Allows the focus modes
to work correctly

To support this, new window property desktop denoting a
"desktop" window; new function desktop-window-p recognizing
one of these things (or the symbol root)

Added pointer-motion-threshold option. Pointer motion
events are only generated when the pointer moves at this many pixes
away from the position it had when the button was pressed

Added function variable-customized-p; use this to avoid
redefining user-modified options

Do type-directed deep conversion of values when converting
to/from readable representations. This fixes the bug that options with
:type (optional color) weren't being converted when passed
between the wm and the configurator, leading to reader errors

A side-effect of this is that updated custom files will not be
compatible with previous versions of the wm (though old custom files
will work with new versions)

Fixed handling of WM_NORMAL_HINTS (was using base-size
instead of min-size in places)

Fixed further locale / FontSet bug (Tomohiro KUBOTA)

window-history module won't resize a window to a size that
violates its size constraints

0.29

Rewrote the configuration user interface. Improvements include:

Key bindings may now include parameters. E.g. this finally allows
shell commands to be bound to keys using the GUI (use the new
run-shell-command command)

Nautilus-like user-levels to tailor the options shown to the
expertise of the user

Options may have much richer type descriptions (including
match-window options). Also, extra widget types and containers
may be added as extra Lisp modules

By default the stand-alone configurator commits changes to the
window manager as they are made, instead of waiting for the Try
button to be pressed

Added dependences--options with dependences are only editable
when the value of their dependence is non-nil

Rewrote window stacking code to be based on "stacking
predicates"--functions that accept or reject a possible stacking
configuration. This allows the "stack-transients-above-parents"
option to work correctly, only keeping transient windows above their
own parent windows

The configure-event handler now understands and handles the full
complexity of stacking requests (Brad Thompson)

New frame-part attribute: scale-foreground. The
cursor attribute may now be a function

Made the centered, centered-on-parent and
under-pointer placement modes clamp the window into the current
work area (i.e. without overlapping windows that shouldn't be covered).
Added a stagger placement mode

When grabbing window icons to images, preserve their shape masks

Moved window-history options to placement group.
Fixed some more bugs and sub-optimal default option values

Don't set cursors for button classes, use the default value

GNOME SKIP_FOCUS window hint sets never-focus
property on window, as well as the ignored property

Added mostly-complete support for using gdk-pixbuf instead of
Imlib (requires an experimental Xlib version of the gdk-pixbuf library)

Various bug fixes and other minor changes...

0.28.1

New options --visual=TYPE and
--depth=DEPTH. These tell the window manager to use a
different visual than the default

Made the window-history module behave more sanely (don't
save iconified or shaded state; include window name when generating
keys for transient windows)

Made beos-window-module the standard window menu (require
old-window-menu to get the original version). Also made this
display the windows' class names

Updated translations: es (Iñaki García Etxebarria), tr (Fatih
Demir)

0.28

New module window-history--automatically saves window
attributes when they are explicitly set by the user, then copies these
attributes to windows with the same WM_CLASS as they are
created. This is loaded automatically if you have no .sawfishrc

New method of allowing themes to implement only some of the
(currently) four frame types. The variable
frame-type-fallback-alist maps each frame type to the type to
try if the original type isn't available in the chosen frame style.

Note that for this to work, themes must return nil when they
don't support the requested frame type, until now, the convention had
been to return the default frame definition, so most if not all themes
will need changing. (This doesn't include themes created using the
make-theme module.)

Made the metrics used by the best-fit placement mode
user-controllable. Set the sp-cost-components variable to a list
of cost functions and the weight to apply to that metric. E.g. by
default it gives 50% importance to the distance from the placement to
the focused window, and 25% each to the distance to the pointer and to
the "future-unusefulness" of the area being covered

New module beos-window-menu to redefine the window menu to
group items by the window group that they are a member of (in the
absence of actual group information, it will heuristically build groups
by matching window titles)

New option edge-flip-warp-pointer, whether or not to warp
the pointer after edge-flipping (Paul Warren)

New option display-window:uniconify-to-current-workspace,
controls whether windows uniconified by display-window should be
moved to the current workspace (John N S Gill)

Changed method of selecting when to use multi-byte aware
rendering functions (except when initializing the locale fails, or
returns a 7-bit locale); also, when creating a fontset fails, try to
intelligently fall back to a similar group of fonts (Tomohiro Kubota)

The x library now supports creating and then drawing to
pixmaps. The pixmaps can then be grabbed to images using the
make-image-from-x-drawable function

Fixed bug When transferring focus after a window is unmapped
(inverted choice of when to look under pointer, and when to look in
focus history)

0.27

Changed the name from sawmill to sawfish; all
user-visible binaries have been renamed appropriately, the old programs
will still work for now...

Added support for accelerators in menu definitions (this requires
a new rep-gtk package) (Richard Kilgore). Added accelerators to many of
the standard menu items

Added some (untested) support for Xinerama: current-head,
current-head-dimensions, current-head-offset. Some
placement modes should handle multiple heads sensibly, as should window
maximization and edge snapping.

Added icons for GNOME control center applets (all icons by
Tigert, except for the saw-blade logo by Glyph Lefkowitz)

New functions define-placement-mode and
define-focus-mode--make defining these things easier. Focus
modes are now settable for each window individually

Made the tree-organised customization groups work better with the
GNOME control center. Add the sawmill capplet desktop entries to the
GNOME programs menu (under Settings). Also, beautify the names
displayed in the bindings widget

When applicable, load the GNOME applications menu when the wm is
first idle, reduces the latency of displaying the first root menu

0.24

Configure requests events are now passed to the hook
configure-request-hook. The new configure handler respects
window gravity when resizing

New option configure-auto-gravity. When enabled the window
gravity is implied by the position of the center of the window. (e.g.
try placing the GNOME control center in the bottom right corner of the
screen, then click on an item that causes it to resize)

Worked around the numerous reports of non-existent font errors
that using XCreateFontSet causes--fall back to
XLoadQueryFont if possible

There's now a library custom-defaults giving default
customization options (only if the user has no
~/.sawmill/custom)

Also, remove the need to call custom-add-required in
.sawmillrc, it's always done now

Removed fp->win == 0 assertion, it should be harmless and
was triggering for some people

Fixed bug of sending configure notify events to too many windows

Fixed off-by-one error in ws-insert-workspace (Kirk
Saranathan)

Fixed maximization in single directions to work additively

Fixed bug of leaving tooltips displayed after the associated
window has been deleted

Fixed bug of not removing -clientId option from restart
parameters

Fixed bug of not translating customize group names

0.23

Customization groups are now organized as a tree structure, with
groups able to contain subgroups

Define the list of features that will be presented to the user in
sawmill-defaults.jl, by calling custom-add-required. If
you have a .sawmillrc you'll need to do this manually

New function move-resize-window-to doing a combined
move/resize. New variable synthetic-configure-mutex, when set
holds off sending synthetic ConfigureNotify events to windows
until it's unset (this is held while interactively moving or resizing
windows)

New hook after-add-window-hook. Called with a single
parameter, the window that's has just been adopted

Updated sawmill-themer to emit code to tell the window
manager that the theme is editable. The wm adds an Edit Theme...
option to the Customize menu when appropriate

The call-after-property-changed function can now be given
a list of properties to monitor (James Antill)

New function call-after-state-changed, monitors a list of
window states (i.e. things like iconified, shaded, ...) and calls a
function when any of them change. The window-state-change-hook
now has a second argument (apart from the window), the list of symbolic
states that changed (James Antill)

Add support for skip-winlist and skip-tasklist to
the window matcher when GNOME support is enabled (Ben Liblit)

0.21

Frame pattern definitions (foreground, background, font) may now
take alists as well as the old single object, or list of four objects.
Possible states are inactive, focused,
highlighted, clicked, inactive-highlighted,
inactive-clicked. (Last two are new)

New program sawmill-themer. A GUI for creating simple
themes (those without any parts defined by functions)

New module gnome-int, loaded by sawmill-defaults if
GNOME is around, sets up some GNOME'ish things

Work around Imlib's annoying image caching, make-image now
always returns a new image

Fixed gc bug when building window frames

Fixed X property handling on Alpha's (George Lebl)

Make call-command accept closures

Make (cursor . nil) work correctly in frame definitions

Grab on frame window, not client window (ICCCM compliant)

Fixed the "uniconify to current workspace" option

Added window-maximization predicates to the gaol

0.20

Rewrote workspace handling--windows can now appear on multiple
workspaces, with each instance having different properties (position,
size, whatever...)

Create new window instances by using the copy-to-next-workspace,
copy-to-previous-workspace, and copy-to-workspace:n
commands. Merge instances by moving them to the same workspace, or
using the delete-window-instance command

Fixed screen corruption when doing wireframe moving and
move-resize-raise-window is set

Hacked around window-order problem when sticky windows exist

0.18

General subsystem for matching windows to properties as they're
created. Allows matching on one or more of the window's X properties
(e.g. name, class, etc...), and then setting any number of window
manager properties as a result. See the Matched Windows
customize group

Removed all auto-foo-alist and
bar-windows-re variables, they're obsoleted by the general
match-windows mechanism

Respect window's size hints when maximizing (both to see if the
window is maximizable, and to truncate the maximized dimensions to an
integral number of rows and columns)

Show actual colors in the configurator, not just their names

Added a new directory to the theme search path:
prefix/share/sawmill/themes. Use this for system-wide
themes (don't use the version specific directory)

Included a new theme mono

Deprecated the show-message function, replaced by
display-message with a better calling interface; also displays
multi-line strings

Deprecated the menu "expand variables when first in list"
behaviour. Instead expand variables when the list is dotted to them, as
is done for functions

Added option to disable the ability to grab a second edge while
resizing (resize-add-edges)

Included Danish message catalogue (Kenneth Christiansen)

Renamed fixed-position property as sticky-viewport,
and focus-proxy-click as focus-click-through

When evaluating mouse events, look in the window that the pointer
was in when the button was pressed, not where the pointer currently is

Fixed bug where focus gets totally lost after closing a Motif
application that has grabbed the keyboard

Fixed (again) the problems when handling remapped windows; also
should be more ICCCM-compliant

Fixed typos in one-dimensional maximisation (Gérard Milmeister)

Fixed the logic deciding when it's necessary to switch workspaces
after merging an empty one

Fixed interactive placement showing the window when edge-flipping
(but it still doesn't work properly, rubber band traces are left)

Removed flicker when focusing already-focused windows

0.17

First version to use lexically scoped librep. This enables themes
to run in a "safe" environment, but all existing themes will need to
be ported; other language changes include the use of a single symbol
namespace, and scheme-like function call semantics

Support for internationalization of messages and run-time
documentation; an en_GB catalogue is the only translation currently, so
please send me .po files for your native languages!

New option --disable-nls to disable i18n

New functions call-after-property-changed and
gtkrc-call-after-changed to allow themes to receive these events
(hooks are now off-limits to themes)

New command raise-window-and-pass-through-click; bind it
to a mouse button in the window-keymap to get the "raise window
on click" behaviour that seems popular

New commands to move windows incrementally:
slide-window-x and slide-group-x for x
one of: left, right, up, down

New commands to control ignored property of windows
(Julian Missig)

New commands to toggle GNOME skip-winlist and skip-tasklist
properties of windows

Never look in the focused window's keymap by default with mouse
events

Hacked around the "need an X11 connection to compile" misfeature

Fixed bug in gnome-menu code when GNOME binaries aren't in
the first $PATH item; also accept non-alphanumeric language codes

Fixed interactive window placement (again)

Rewrote obscure documentation for some custom options

Fixed bug when grabbing events with AnyModifier and a
specific button

0.16

Support window groups, both as defined by applications, and
defined by the user (either interactively through the window's menu, or
via the auto-group-alist and persistent-group-ids
variables).

For most commands working on single windows, there's also one operating
on the group that the current window is a member of. (With the notable
exception currently of moving windows.) There's also options
controlling whether (de)iconification operates on windows or groups

0.15

Changed how themes are loaded from tar files--the tar file must
now contain a directory with the same name as the theme; it's this
directory that stores the data files

Allow viewport edge-flipping to be enabled by the customization
system, also enable flipping while moving windows

Unified the method of marking which windows should be avoided
when maximizing, and which windows should be avoided when using the
fitted placement methods. Set the avoid property instead of the
maximize-avoid property; new functions window-avoided-p
and avoided-windows; new regexp avoided-windows-re

New command delete-empty-workspaces

Default theme is now microGUI

When resizing only one edge of a window, moving the pointer past
one of the perpendicular edges grabs that edge also

Fix _WIN_CLIENT_LIST property not being set properly (both
missing windows immediately after they're adopted, and of intentionally
skipping ignored windows)

Fix some problems with viewports when exiting/restarting

Fix broken stacking of windows after they're mapped

Prevent smart window placement blowing up when large numbers of
windows are open/opened (throttle back to random placement when the
event queue is too large, as well as trying to prune the search space)

0.12

Remember most recently focused windows on each workspace,
activate that window after changing workspaces; also, try to preserve
focus when moving windows between workspaces

Option to disable auto-raise while cycling through windows
(cycle-disable-auto-raise); option to restrict cycling to the
current viewport (cycle-all-viewports)

Option lock-first-workspace is now enabled by default, and
prevents both the first and last interesting workspaces being moved
inwards

Support X installations without X11R6 session management (by not
doing any session management)

Don't ask the session manager to save our environment

Fix bug where a window is destroyed/unmapped while it's being
resized or moved

Fix bug where window can still be auto-raised even if it's been
defocused

Fix problems when --prefix option has a trailing slash

Now handles client windows being reparented by a third party
(i.e. swallowing apps)

0.9

The first-fit and best-fit algorithms are now much more
intelligent, e.g. instead of falling back to random placement when a
window can't be placed without overlapping an existing window, they
will attempt to minimize this degree of overlapping

The foreground property of each frame part may now be an
image instead of a piece of text

New variables eval-modifier-events and
eval-key-release-events to allow catching these types of
keyboard events, disabled by default

Added functions for actively grabbing the keyboard

Removed the long names of the keyboard modifiers, only the single
character modifiers are left

If no alt modifier, set it to the same as meta; new variables
alt-keysyms and meta-keysyms describe the virtual
modifier assignments

Fix bug when handling shaped frame parts--it was possible to go
into a long enter-, leave-notify loop when the old shape was cleared

Fix bug where opaque resizing with snap-to-edges on moved the
window as well as resizing it

Fix bug when raising the only managed window

Fix bug where very small client windows got weirdly shaped
frames

0.6

Define the standard classes of frame parts (i.e. things
like close button, title, left border, etc...) then allow the state of
members of these classes to be set in one place (the
frame-part-classes variable). This should ensure that different
themes have the same feel (but a feel that may be customized by the
user)

Allow frame parts to be removed if possible (if they have the
removable property). Nothing makes use of this yet

Added window-shading, double-click button1 on the title bar

Created a sawmill capplet for the GNOME control center. Use the
--enable-capplet configure option to build it

First attempt at a technical manual (very quickly written, so
probably some inaccuracies)

Fix bug where iconifying a sticky or ignored window gave no way
of reclaiming it--these windows now appear at the end of the window
menu

0.5

Now does session management. The scheme is extensible, arbitrary
Lisp modules can save and restore window state due to their own
functionality (using the sm-window-save-functions and
sm-restore-window-hook hooks). See lisp/workspace.jl for
an example

Mechanism for setting frame styles on a per-window basis (this
was always possible, just not easy). The auto-frame-style-alist
variable associates window name regular expressions with frame styles.
Also, the window-ops-menu has a new submenu with all possible
styles

New option preallocated-workspaces, the number of
workspaces to create at startup

Window-workspace mapping is preserved through restart (as long as
the GNOME hints are enabled)

Theme directories may contain a short README file that
will be displayed in the configuration tool

Changed the custom file to ~/.sawmill/custom instead of
~/.sawmill-custom. The old file will be moved to the new
location if it exists

Changed most of the menus and custom customize
options into normal variables (they're not particularly intuitive)

0.4

Frame parts can now be highlighted when the mouse is over them,
also they "un-click" and "re-click" as the pointer leaves and
re-enters their window. ButtonRelease bindings are only activated when
the mouse is in the window at the time

Frame part backgrounds can now be rendered on-the-fly using the
new renderer property in frame definitions. This property is a
function called with args (imagestate); it should
draw a background into image for the specified state (nil,
focused, highlighted or clicked)

New theme gtk. This reads the default GTK style and uses
the associated colors and pixmaps to decorate windows. It doesn't try
to handle engine-based themes. It should automatically detect when the
default style changes (if changed by the GNOME control center). Do
sawmill-client -c gtk-reload-style in the shell to reload the
style manually

Functions for drawing color gradients and bevels into images. The
new gradient theme uses these and on-the-fly rendering to do
afterstep-like window titles

Configurator changes: use a paned widget to separate the list of
groups from the settings (stops their relative sizes changing), allow
each group to be customized separately, either through a new set of
root-submenus or the commands customize:group for each
group.

Changed the way that "themes" are organised, each theme now
gets its own directory, which must include a theme.jl or
theme.jlc script to initialise a frame-style of the same name as
the directory. While this script is being evaluated the image path is
set so that the theme can load any images stored in its directory.

Also created the variable theme-load-path containing the list of
directories searched when trying to load a theme. By default it
contains two directories: ~/.sawmill/themes/ and
prefix/share/sawmill/version/themes.

Resizing now chooses the direction to resize the window in by the
initial position of the pointer in relation to the window. The window
is divided into a 3x3 grid, the pointer must be in one of the outer
rectangles to resize in that direction

New commands select-workspace:X for X between
1 and 9

Support multiple depths, or layers, of windows

It's now possible to move the current workspace up or down the
list of all workspaces

New option -c COMMAND to sawmill-client; invokes
the named interactive function

When an app asks for no title and no border, give it what it
wants--use the new unframed window type

The maximize button works

Option to control placement of transient windows
(place-transient-mode)

Changing the frame style preserves the original window stacking
order

Added documentation strings for most built-in functions

Fix bug of evaluating both KeyPress and KeyRelease events

Fix bug of making the shape mask of unshaped client windows too
big

Fix bug where already-handled BadWindow errors were being reported

Fix bug where the window-ops-menu could be displayed from
one window but then affect a different window

Fix bug where click-to-focus doesn't work for new windows

Fix bug where deleting the last workspace selected the first, not
the new last workspace

Fix bug where changing a colormap when no window is focused
causes a segfault

Fix bug where iconifying a window may leave it in the clicked
state after it's uniconified

Fix Caps_Lock and Num_Lock modifiers interfering with bindings

Fix accessing X properties on 64-bit architectures

Fix bug where pointer may be left grabbed after moving a window

0.3a

Support the maximized GNOME window states

Where available, show documentation strings of commands in the
configurator

0.3

Added support for snapping to window edges when interactively
moving windows (move-snap-edges and move-snap-epsilon)

First attempt at handling a subset of the Motif and OpenLook
window hints

Removed the sloppy-focus variable, it's replaced by
focus-mode. This can currently be one of enter-exit
(normal focus follows pointer), enter-only ("sloppy" focus) or
click (click to focus)

When resolving pointer events, scan the keymap property of
the window under the pointer, not the focused window (as with keypress
events)

The sawmill-client program can now communicate inter-host,
since it uses X properties not raw sockets

New hook before-exit-hook, called immediately before
shutting down

Rewrote the GNOME support as a Lisp module

Placing windows interactively now works

Fixed the bug on Solaris where deleting windows could cause a
segmentation fault

0.2

Added a user-customization system, inspired by Emacs' customize
facility. Invoke this through the sawmill-ui program, or from
the Customize... entry in the main menu. All changes are stored
in the Lisp script ~/.sawmill-custom

Selected windows may now be raised
(raise-selected-windows)

It's possible to prevent the mouse pointer being warped to
selected windows (warp-to-selected-windows)

The brushed-metal and simple themes now define all
four standard frame types

Frame themes are now stored in a separate directory
(prefix/share/sawmill/version/lisp/themes) so that
the list of all available themes can be made automatically

The frame colors of the simple frame style can now be
customized (simple-normal-color and simple-active-color)

The sawmill-defaults.jl script enables GNOME compliance
unconditionally (since it has no ill-effects even if GNOME isn't being
used)

Transient windows can be given the same frames as normal windows
(decorate-transients)

Newly-displayed transient windows can be automatically given the
focus if their parent window is focused (transients-get-focus)

Any newly-displayed windows can be automatically given the input
focus (focus-windows-when-mapped)

The foreground, background and font
attributes of each frame part may now refer to a function

Fixed the window-move bug whereby the first motion event was
discarded

Fixed the bug where windows may be placed partially off the root
window, even if they needn't be

0.1

Colors

Sawfish provides a primitive type allowing colors to be represented.
Each color object allows a single color value to be named and passed
between Lisp functions.

colorp arg

Function

Returns t when arg is a member of the color type.

get-color name

Function

Returns the color object representing the color specified by the string
name. This is according to the standard X11 color specifiers,
either a named color from the rgb.txt database, or a string
defining the red, green and blue components of the color, either eight
or sixteen bits in hexadecimal, i.e. #RRGGBB or
#RRRRGGGGBBBB.

Signals an error if no known color has the name name.

get-color-rgb red green blue

Function

Return the color object representing the color with RGB components as
specified (each component ranging from 0 to 65535).

Given a color object, it's possible to find both the actual rgb values
defining the color and one of the names that X11 uses to refer to the
color.

color-rgb color

Function

Return a list of integers (redgreenblue) the
actual color values of the color represented by object COLOR. The
individual values range from 0 to 65535.

color-name color

Function

Return a string defining one of the X11 names used to specify the color
represented by the color object color. Note that this may well be
different to the name used when the color was originally allocated.

Where a color object is used to define the foreground color of a piece
of text, the default-foreground color provides the default value
used if no actual color is specified.

Images

The image type allows arbitrary 24-bit images to be manipulated by the
window manager. Images may be both loaded from files, and rendered
dynamically.

imagep arg

Function

Returns t when arg is a member of the image type.

make-imagefile-name

Function

Creates and returns an image object containing the image defined by the
contents of the file named file-name (a string). The
image-load-path directory provides the search path used while
trying to find a directory containing the file named file-name.

All common image formats will likely be able to be loaded. But PNG,
JPEG and XPM should always be supported.

Signals an error if file called file-name may be found, or if an
image may not be constructed from the file.

image-load-path

Variable

A list of directory names. This defines the search path used when
loading images.

make-sized-image width height &optional color

Function

Create and return a new image, of size width, height. If
color is defined it specifies the color of all pixels in the
image. If undefined, all pixels will be black.

Returns a cons-cell (width . height) defining the
dimensions of the image represented by image.

flip-image-horizontally image

Function

Flip the contents of image about the vertical axis.

flip-image-vertically image

Function

Flip the contents of image about the horizontal axis.

flip-image-diagonally image

Function

Flip the contents of image about an axis running from the
top-left corner to the bottom-right corner of the image.

As with many of the other types, arbitrary state may be associated with
image objects.

image-put image property value

Function

Set the property named property (a symbol) of image to
value.

image-get image property

Function

Return the property named property of image, or nil
if no such property exists.

The only predefined property is the symbol tiled, used when an
image is displayed in a window decoration. When set to a non-nil value
the image is not scaled to the size of the decoration (the default),
but is tiled across the decoration.

When images are scaled across border decorations the pixels that are
actually scaled are defined by the border of the image. The
border defines the outer rectangle of pixels that are left as-is, and
the inner rectangle which is scaled.

image-border image

Function

Returns a list of integers (leftrighttopbottom), the border of the image object image.

The number associated with each edge of the image defines the number of
pixels adjacent to that edge that will not be scaled.

set-image-border image left right top bottom

Function

Sets the border of image.

The shape of the image may also be specified, this defines which pixels
are treated as being transparent. Each image may define a single color
as marking transparent pixels.

image-shape-color image

Function

Return the color marking transparent pixels in image, or
nil if no such color has been specified.

set-image-shape-color image color

Function

Specify that color marks transparent pixels in image.

It's also possible to define color modifiers for each image.
These define the transformation applied to the value of each pixel when
it is displayed. Four different modifiers exist for each image, one for
each color component, and one for the image as a whole.

image-modifier image type

Function

Return the modifier defined by the symbol type of image, a
list of integers (gammabrightnesscontrast).
Each integer has a value between zero and 255 representing the weight
applied to the associated attribute when rendering the image.

The four types are red, green, blue and nil
(all colors).

set-image-modifier image type gamma brightness contrast

Function

Set the image modifier of image defined by type.

There are also several other functions manipulating images:

bevel-image image border upwards &optional bevel-percent

Function

Transform the edgemost pixels of image to give it a "bevelled"
effect. BORDER is an integer defining the width of the bevel. If
upwards is non-nil the bevel is raised, otherwise it is lowered.

If bevel-percent is defined it specifies the height or depth of
the drawn bevel. When undefined, the value of the parameter is taken
from the default-bevel-percent variable.

default-bevel-percent

Variable

Default height of drawn bevels, as a percentage.

clear-image image &optional color

Function

Set all pixels in image to color (or black if color
is undefined).

tile-image dest-image source-image

Function

Tiles source-image into dest-image, starting from the
upper-left corner, working outwards.

Cursors

Cursors define the shape and hot-spot of the mouse pointer's image. A
lisp type is provided for manipulating these objects.

cursorp arg

Function

Returns t if arg is a member of the cursor type.

get-cursor data

Function

Returns the cursor object representing the cursor defined by
data. If data is a symbol, it's replaced by its
cursor-shape property.

Possible data values are an integer representing a glyph in the
standard X11 cursor font, or a four-element vector.

If a vector the format is [imagemaskfgbg] where image and mask are the filenames of
standard X11 bitmaps, and fg and bg are colors (or names of
colors). All bitmap files are searched for using the
image-load-path variable.

recolor-cursor cursor fg bg

Function

Change the colors of the cursor object cursor to fg and
bg (either color objects or the names of colors).

default-cursor cursor

Function

Set the cursor object displayed in the root window, and in parts of
window frames that have no other cursor specified, to cursor.

So that the integer indices of glyphs in the X11 cursor font do not
have to be remembered, the cursor-shape properties of the
following symbols are automatically set:

Window Property Lists

Many window manager extensions need to be able to associate Lisp data
with individual windows. For example, the module handling iconification
needs to associate a boolean value with each window--whether that
window is iconified or not.

To solve this problem, Sawfish gives each window a property list. These
are exactly analogous to the property lists stored with each symbol
(see Property Lists);
they allow values to be associated with Lisp symbols, for a particular
window.

Note that these properties are different to the properties that X
stores with each window, since these properties are internal to the
window manager (see X Properties).

window-put window property value

Function

Set the lisp property named property (a symbol) associated with
window object window to value.

window-get window property

Function

Return the window property named property associated with the
window object window, or nil if no such property exists.

X Properties

The X window system associates properties with windows (these are
totally separate to the properties that sawfish associates with window
objects, see Window Property Lists). Most inter-client
communication is performed through manipulation of these properties.

All functions defined below, that operate on X properties, accept their
window parameter as either a window object (denoting the
associated client window), the numeric xid of a window, or the symbol
root denoting the root window.

Sawfish represents X atoms (both the names and data types of X
properties) as symbols. There is an exact correspondence between the
names of atoms and the name of the symbol representing them. For
example, the X atom STRING is represented by the lisp symbol
STRING.

Returns a list (typeformatdata) representing
the X property property of window. If no such property
exists, return nil.

type is the atom defining the type of the property. format
is an integer, either 8, 16 or 32, defining the number of bits in each
of the data items. data is an array, either a string for an 8-bit
format property, or a vector of integers otherwise.

If type is ATOM and format is 32, then data
will be a vector of symbols, representing the atoms read.

set-x-property window property data type format

Function

Set the X property property of window to the array
data, either a string or a vector of integers.

type is a symbol representing the atom defining the type of the
property; format is either 8, 16 or 32 defining the number of
bits in the data values.

If type is ATOM and format is 32, then any symbols
in data will be converted to their numeric X atoms.

The standard X property formats don't allow for an array of strings to
be stored, so these are often encoded as the strings concatenated,
separated by zero characters. These are usually called text
properties. Sawfish has two functions for manipulating them:

get-x-text-property window property

Function

Similar to get-x-property, but returns either nil or a
vector of strings.

set-x-text-property window property data

Function

Sets the X text property property of window to the array
of strings data.

It's also possible to detect when the value of any property associated
with a managed window changes, using the property-notify-hook.
See Standard Hooks.

Window Stacking

The stacking order of the display defines the order in which windows
are shown, from topmost to bottommost.

stacking-order

Function

Return a list of window objects defining the current stacking order of
all client windows, from top-most to bottom-most.

restack-windows list

Function

Restack all client windows specified in the list of window objects
list in the order they occur in the list (from top to bottom).
The stacking order of any unspecified windows isn't affected.

x-raise-window window

Function

Raise the client window associated with object window to the top
of the display.

Sawfish allows the stacking order to be managed as a sequence of
layers, with windows being assigned a particular depth within the
order. For any given window with depth d, it will be above all
windows with depth less than d, and below all windows with depth
greater than d. It may be above or below any other windows with
depth d.

The depth property of each window is used to store this depth. A
depth of zero is "normal", with negative depths stacked below, and
positive depths stacked above this normal level.

stacking-order-by-depth depth

Function

Similar to stacking-order, but only returns windows with depth
depth.

set-window-depth window depth

Function

Set the stacking depth of window to depth, then restacks
the windows to reflect this change.

window-on-top-p window

Function

Returns t if window is at the top of its stacking depth.

stack-window-below below above

Function

Change stacking order of window below so that it is immediately
below window above.

stack-window-above above below

Function

Change stacking order of window above so that it is immediately
above window below.

save-stacking-order &rest forms

Macro

Evaluate forms in an implicit progn, then restore the
original window stacking order, returning the value of the
progn.

For the following functions, when called interactively they all operate
on the window that received the current event, or alternatively the
currently focused window.

lower-window window

Command

Lower window to the bottom of its stacking depth.

raise-window window

Command

Raise window to the top of its stacking depth.

raise-lower-window window

Command

If window is the highest in its stacking level, lower it to the
bottom of this level, otherwise raise it to the top of its level.

Moving and Resizing Windows

As noted above (see Window Attributes), the
window-dimensions and window-position functions return
the current configuration of a window.

move-window-to window x y

Function

Move the top-left corner of the window frame of window to
(x, y).

resize-window-to window width height

Function

Set the dimensions of the client window associated with object
window to (width, height).

move-resize-window-to window x y width height

Function

A combination of the previous two functions.

resize-window-with-hints window cols rows &optional hints

Function

Resize the window associated with object window so that it has
cols columns and rows rows. The hints parameters is
either the size hints alist to use, or nil in which case the
window-size-hints function is used to retrieve the window's
hints.

Usually, however, it is left to the user to configure windows. The
following functions may be called interactively: their sole argument is
then either the window that received the current event or the currently
focused window.

move-window-interactively window

Command

Move window interactively using the mouse. Releasing any mouse
button places the window at its current position.

resize-window-interactively window

Command

Resize window interactively using the mouse. Releasing any mouse
button places the window at its current position.

Note that this function selects the edge or edges of the window to move
from the current position of the mouse when the resizing begins. The
window is divided into a three-by-three grid; the rectangle containing
the mouse pointer gives the direction to resize in. If the pointer is
in the central rectangle the bottom and right edges are moved.

move-selected-window

Command

Wait for the user to select a window using the mouse, then
interactively move that window.

resize-selected-window

Command

Wait for the user to select a window with the mouse, then interactively
resize that window.

The interactive move and resize behavior can be customized through the
following variables:

move-outline-mode

Variable

A symbol defining the visual method of interactively moving windows.
Current options include box for a wire-frame grid, and
opaque for full redisplay.

resize-outline-mode

Variable

A symbol defining the visual method of interactively resizing windows.
Current options include box for a wire-frame grid, and
opaque for full redisplay.

move-show-position

Variable

When non-nil, the current window position is shown in the center of the
screen.

resize-show-position

Variable

When non-nil, the window size is shown in the center of the screen.

move-snap-edges

Variable

When non-nil, the window position is "snapped" to edges of other
windows within close proximity.

Showing and Hiding Windows

Sawfish provides two low-level functions for withdrawing client windows
from the display. These are used to implement both virtual workspaces
(see Workspaces) and iconification (see Iconifying Windows).

hide-window window

Function

Prevent object window from being displayed.

show-window window

Function

Ensure that window (if it has been mapped, and is within the
screen boundary) is visible.

window-visible-p window

Function

Returns t if object window has not been hidden by the
hide-window function.

Iconifying Windows

X defines an iconic state for windows, often windows in this state are
displayed as small icons. Sawfish does not display these icons, instead
iconified windows are shown slightly differently in the menu of all
windows.

iconify-window window

Command

Iconify the window associated with object window.

uniconify-window window

Command

Return the window associated with window from its iconified state.

A window's iconic state may be tested through examination of its
iconified property--when t the window is iconified.

Customization

customization: setting variables to change the behavior of
existing features of the window manager, and,

extensibility: the ability to add entirely new features to
the window manager through the creation of new Lisp modules.

Obviously the first of these requires a lot less specialized knowledge
than the second. But even then, the user has to edit startup files
containing the Lisp forms setting the variables. To remove this need
for hand-editing, Sawfish has a specialized system allowing all
customizations to be made through a GUI, and then automatically
reloaded each time that the window manager is started.

customize &optional group

Command

Invoke the user-customization GUI. group defines the class of
customization variables to configure, or all classes if group is
undefined.

The sawfish-ui program can be used to invoke the GUI manually;
if GNOME is being used, then the GNOME Control Center can also be used
to customize certain classes.

In order to provide these customization options however, an extra
requirement is placed on the Lisp programmer. Instead of just using the
defvar special form to declare variables, the defcustom
macro must be used. This augments the variable with extra information
for the GUI, including such things as its required data type.

Customization options are organized into groups. Each group has a name
and contains a set of related options. Currently, it is not possible
for groups to contain sub-groups.

defgroup group real-name &rest keys

Macro

Declares a new customization group whose name is defined by the symbol
group. The string real-name is the title of the group as
seen by the user.

keys is a list, defining the properties of the group. The members
of the list are grouped into pairs of elements, the first element names
the property, the second defines its value. Currently the only property
is :widget, defining a function to create the group's UI widget.

This macro also creates an interactive function named
customize:group allowing the GUI to be invoked to
configure the new group.

defcustom variable value documentation &rest keys

Macro

The first three arguments are analogous to the defvar special
form, they declare a special variable stored in the symbol
variable, whose value is set to value if the variable is
currently unbound, with a documentation string documentation.

All other parameters are key-value pairs as with defgroup. The
possible pairs are as follows:

:group group

Specifies the customization group that this variable is a member of.

:type type

Specifies the required type of the variable. The current possibilities
are boolean, number, string, file-name,
program-name, font, color, frame-style,
keymap and (set symbols...).

The boolean type assures a value of either nil or
t, the set type allows the user to choose from one of the
symbols in the list.

:require feature

Denotes that the feature feature must be loaded if the variable
is set to a non-nil value by user customizations. This is
necessary because customization options are loaded on startup, possibly
before the modules that define them.

:allow-nil bool

Specifies whether the variable may be nil, instead of a member
of its actual type. This is only supported by the string,
set, font and color types.

:set function

Specifies that the variable must be set by calling function
instead of the default custom-set-variable. The function should
accept three arguments: (variablevalue &optional
require).

The usual action of this function is to translate the value into the
correct type, then call custom-set-variable. This translation is
necessary since many of the UI widgets accept strings representing more
complex types (i.e. a color's name, instead of the actual object)

:get function

Provides a function for reading the current value of the variable.
Should return a value that's acceptable to the UI widget associated
with the variable. Called with a single argument, the symbol containing
the variable.

:before-set function

:after-set function

Functions called both immediately before and after setting the value of
the variable. Called with a single parameter: the variable itself.

:range (min . max)

The allowed range for numeric variables. If min is nil the
the default minimum allowed value is zero; if max is nil
then the default maximum is unbounded.

Note that where necessary the types themselves define default
:set, :get and :widget values that may be
overridden by values in the defcustom call. Usually, however,
this will not be necessary.

Window Frames

Perhaps one of the most important features of a window manager is its
ability to decorate client windows, typically seen as an added border,
and then to allow the window to be manipulated through user input on
the border.

Sawfish provides an extremely flexible method of decorating windows,
the look and feel of the border may be specified completely. Also, no
limits are placed on which windows are given which borders, if
necessary a completely different border could be dynamically created
for each window!

Frame Basics

The frame of a client window is defined as all decorations added
by the window manager. Usually these decorations will be immediately
adjacent to the outer edges of the window, but there is no requirement
to use this model.

In Sawfish, each window frame is constructed from a list of frame
parts, conceptually rectangular objects with a specified position
relative to the edges of the client window. When shaped images are used
to define frame parts, they are still thought of as being rectangular,
just with some pixels missing from the display.

Each frame part has a list of attributes associated with it, these
include items defining the background of the part (i.e. a color or an
image), and items defining the foreground of the part (i.e. probably
some kind of text, with a color, font, etc...). Non-visual
attributes may also be defined, such as, for example, the keymap
mapping events occurring in the part to Lisp commands to execute
(see Keymaps).

So a window frame is defined in Lisp as a list of frame part
definitions (see Frame Part Definition). These frame parts are
added to the client window (in the order they are defined, so later
frame parts are above earlier parts at the same position), to produce
the entire window frame.

Frame Part Classes

Although one of the aims of Sawfish is to provide as much flexibility
as possible, this can sometimes be detrimental to the overall
experience. For example, it would be easier for the user if all themes
use consistent keymaps and cursor images in conceptually similar parts
of window frames. That is, it would be better if all close buttons had
the same mouse button bindings and the same mouse cursor displayed when
the pointer is over them.

To achieve this, Sawfish defines a number of classes of frame
parts, each with several default attributes. When defining a window
frame, the definitions of each part then specifies which class it is a
member of, and inherits the associated default attributes (provided
that it hasn't explicitly specified values for these attributes).

frame-part-classes

Variable

This variable is an association list, associating symbols naming frame
part classes with an association list of default attributes for that
class.

The names of the pre-defined classes are as follows, their meanings
should be self-explanatory:

Extra classes can be created by adding to frame-part-classes.
However, it's likely that more than one theme may need to use the same
class, and that the user may then wish to customize any extra keymaps
used. The def-frame-class macro should be used to add new
classes, since it handles these situations.

def-frame-class class alist-form &rest binding-forms ...

Macro

Creates a new frame part class named by the symbol CLASS.

The ALIST-FORM is evaluated to give an association list defining
attributes for the class. Each key-value pairs is only set if no
existing value exists for that key.

If binding-forms are given, they will be evaluated when no keymap
already exists for the class. A keymap will be created, and stored in
the variable named class-name. This variable may then be
used withing the binding-forms.

So to define a hypothetical shade-button class, the following
might be used:

Frame Part Definitions

Each frame part is defined as an association list (or alist), a list of
cons cells, the car of each cell defines the attribute, the cdr defines
the value given to that attribute. So, for example, the alist
((foo . 1) (bar . 2)) specifies two attributes: foo with
value 1, and bar with value 2. See Association Lists.

The attributes that may be defined are as follows:

(class . class)

Specifies the frame part class of the part.

(background . data)

(background . (normalfocusedhighlightedclicked))

Specifies the background of the part. May be a color, an image, or a
string naming a color. If a single element, then it is used for all
states of the part, otherwise if a list, then each of the four elements
defines the background for that particular state.

If an image is used it will be scaled to the size of the frame part,
unless it's tiled property is set, in which case it will be
tiled across the frame part.

(foreground . data)

(foreground . (normalfocusedhighlightedclicked))

Specifies a foreground color or image for the frame part, either for
all states, or for each individual state.

Unlike the background attribute, by default images are not
scaled when used to define the foreground of a frame part.

(scale-foreground . value)

When value is non-nil, the foreground image of the frame
part will be scaled to the size of the part.

(font . font)

(font . (normalfocusedhighlightedclicked))

Specifies the font(s) of the part.

(text . value)

Specifies the string to draw in the foreground of the frame part
(unless the foreground property is an image). Either a string,
or a function, that will be called each time that the part is
refreshed, that will return the string to draw.

(x-justify . value)

Defines the horizontal position of the foreground contents of the part
(i.e. the text or foreground image). May be one of the symbols
left, right or center, or a number. If a number it
defines the number of pixels from the left edge if positive, or the
right edge if negative.

(y-justify . value)

Similar to x-justify, but the accepted symbols are top,
bottom or center instead.

(renderer . function)

This attribute may be used instead of the background attribute.
When the part needs to be drawn function will be called with an
image in which to render the background, and the current state of the
part, a symbol focused, highlighted, clicked, or
nil (for the normal state).

(render-scale . value)

This attribute causes the size of the image used with the
renderer property to be reduced by a factor of value, an
integer.

(left-edge . value)

Defines the position of the left edge of the part, in relation to the
left edge of the client window.

(right-edge . value)

Defines the position of the right edge of the part, in relation to the
right edge of the client window.

(top-edge . value)

Defines the position of the top edge of the part, in relation to the
top edge of the client window.

(bottom-edge . value)

Defines the position of the bottom edge of the part, in relation to the
bottom edge of the client window.

(width . value)

Defines the width of the frame part.

(height . value)

Defines the height of the frame part.

(keymap . value)

Defines the keymap to use when evaluating events originating in this
frame part.

(cursor . cursor)

Defines the cursor to display when the mouse is in this part. May be
either a cursor object, or the argument to get-cursor to create
the required cursor object.

(removable . value)

When specified and value is non-nil, this frame part may
be removed from the frame without being detrimental to the overall
appearance of the frame. This is only important for button classes,
which may sometimes be removed at the request of the client window.

(below-client . value)

When specified and value is non-nil, then this frame part
will be displayed beneath the client window. The default action is for
frame parts to be stacked above the client window.

(hidden . value)

When specified and value is non-nil, don't display this
frame part.

The values specified for the background, foreground,
render-scale, font, left-edge, right-edge,
top-edge, bottom-edge, width, height,
cursor, below-client and hidden attributes may
actually be functions. In which case the function will be called (with
a single argument, the window object) when the frame is constructed,
the value returned will be used as the actual value of the attribute.

The coordinate system used for specifying the part's position is
relative to the window edge that the position is defined against.
Positive values count in from the window edge towards the center of the
window, while negative values count out from the edge, away from the
center of the window.

Consider the following example, a solid black title bar that is twenty
pixels high, directly above the client window:

The backquote operator is used since the definition is only mostly
constant, the comma operator inserts the value of the
window-name variable (a function giving the name of a window)
into the definition; see Backquoting).

This function is then used to dynamically specify the string drawn in
the foreground. The window manager will automatically refresh the
foreground of all frame parts of a window whenever any X property of
that window changes.

Given a framed window, and a particular frame part class, it is
possible to retrieve the values of individual attributes from the
complete list of definitions (including inherited or overrided
definitions).

frame-part-get window class attr

Function

Returns the value of the attribute attr for the frame part of
class class in the current frame of window.

Returns nil if no such attribute exists. If more than one frame
part of class class exists then the value will be taken from the
first part found.

Frame Functions

set-window-frame window frame-def

Function

Sets the frame of the client window associated with the object
window to that defined by the list of frame part definitions
frame-def. If the window is mapped the old frame will be
destroyed and a new frame constructed.

window-frame window

Function

Return the list of frame part definitions defining the frame associated
with window.

window-framed-p window

Function

Return t when window has been reparented to a frame
created by the window manager.

rebuild-frame window

Function

Recreates the window frame associated with window, from the
previously defined frame definition. All frame parts are reinitialized
and recalibrated.

window-frame-dimensions window

Function

Return a cons cell (width . height) defining the
dimensions of the frame associated with window. These will always
be greater than or equal to the dimensions of the client window.

If window is not framed, then this function returns the same
values as window-dimensions would.

window-frame-offset window

Function

Return a cons cell (x . y) defining the offset from
the origin of the client window associated with window to the
origin of its frame.

Frame Styles

Frame styles are used to encapsulate frames of the different types that
have a single visual appearance. Each frame style associates a name
with a function that creates a frame definition for a particular window
and frame type combination.

add-frame-style name function

Function

Defines a new frame style called name (a symbol). When a frame of
this style is required for a particular window, function is
called with two arguments, the window itself and a symbol defining the
frame type to create (see Frame Types).

If the frame style is unable to provide a frame definition of the
required type, it should return the symbol nil. In which case it
may subsequently be asked for a frame of a different type.

If no default frame style exists, the new style will be made the
default.

default-frame-style

Variable

A symbol naming the frame style to use for windows where no other style
is explicitly specified.

check-frame-availability name

Function

Returns t if a frame style called name exists. Will try to
load such a frame from the filing system if necessary.

set-window-frame-style window style &optional type from-user

Function

Sets the frame of window to the style named by the symbol
style. If type is defined then it names the frame type to
use, otherwise the default type for this window is used.

If from-user is non-nil then the user chose this frame style for
the window explicitly (i.e. it's not just the default choice for a new
window).

set-frame-for-window window &optional force type

Function

If window has no frame style associated with it, then chooses the
default value for this window, the value of default-frame-style.

If force is non-nil then the style is always re-chosen, even if
the window already has a chosen default style.

If type is non-nil it defines the frame type to give the window,
otherwise the current default for the window is used.

reframe-all-windows

Function

Forcibly reselect all window frame styles. Only windows with a user
specified style are not changed to the current defaults.

rebuild-frames-with-style style

Function

Call rebuild-frame on all windows that currently have a frame
defined by frame style style (a symbol)

reframe-windows-with-style style

Function

Completely recreate all window frames that are defined by the style
style.

Themes

Themes and frame styles are currently almost synonymous, the slight
difference being that themes provide a mechanism for loading frame
styles from the filing system as they are required. Although it is
possible that themes may include other user-interface settings in a
later version, at the moment it seems unlikely.

When a frame style is requested, if it is not already available (i.e.
if the add-frame-style function hasn't been called for that
style) then the window manager will attempt to load a theme of the same
name from the filing system.

Each theme is stored in a directory; this directory must have the same
name as the name of the theme itself. Within this directory there must
be a Lisp script named theme.jl or theme.jlc. This script
will be evaluated, it should provide a frame style of the same name as
the theme (by calling add-frame-style).

While the theme script is evaluating the image-load-path
variable is set to include the theme directory as its first element.
This ensures that any image files stored in the directory can be loaded
using the make-image function.

Since rep has no module system, any global variables defined within the
theme must be prefixed by the name of the theme to ensure their
uniqueness. For example, in the theme foo, a variable bar
would actually be called foo:bar.

In most cases however, rep's lexical scoping can be used to avoid
declaring any global variables or functions, the only usual exception
is when declaring customization options with defcustom; these
must be globally visible.

Since themes are generally passed around very casually, sawfish
evaluates all theme code in a very restricted environment; the idea
being that themes should only be able to affect the look of the window
manager. Despite this, it is still possible for malicious themes to
lock, and possibly crash, the window manager; in the first case sending
a SIGINT signal may unblock it. Hopefully themes are unable to
affect the rest of the user's environment, but there are no
guarantees...

theme-load-path

Variable

A list of directory names, provides the search path for locating theme
directories. By default this includes the user's theme directory and
the system theme directory.

Removing Frame Parts

It is often useful to be able to disable certain parts of a window's
frame. For example, a window may hint to the window manager that it
doesn't want a maximize button. Sawfish allows all parts of a
particular class to be disabled or enabled on a window by window basis.
However, not all frame styles will support this (it depends on the
frame part's removable property, Frame Part Definition).

remove-frame-class window class

Function

Disable all frame parts that are a member of class in
window where possible.

Workspaces

Popup Menus

Popup menus are one of the two main methods through which the user may
invoke Lisp code (the other is via keymaps, see Keymaps). The
popup-menu function is invoked with a list of menu item
definitions and the associated Lisp function to call for each item.
This starts a subprocess to display the menu, then at a later date the
chosen menu item is received and evaluated.

Each menu item is specified by a list, the first element of which is a
string providing the label for the menu item, the second element is a
function to be called if that item is selected by the user. If this
function has an interactive specification it will be invoked using the
call-command function, otherwise funcall will be used.
Alternatively the second element may be a lisp form to evaluate. So,
for example, a single-level menu could be defined by:

If the cdr of first element of any item is a symbol, then the rest of
the item is defined by the value of the named variable. If this value
is functional then the definition is found by calling the function.

This is the definition of Sawfish's root menu. We can see that four
submenus are created dynamically by dereferencing variables (in fact,
three of this variables contain functions) (workspace-menu,
window-menu, apps-menu and custom-menu).

The apps-menu variable can thus be used to redefine the
applications menu. The default definition is as follows:

The system function simply executes its single argument using
/bin/sh.

popup-menu spec

Function

Displays a menu defined by the list of item definitions spec.

popup-window-menu

Function

Display the menu listing all window operations.

popup-root-menu

Function

Display the main menu.

popup-apps-menu

Function

Displau the applications menu.

root-menu

Variable

Contains the root menu definition.

apps-menu

Variable

The variable containing the definition of the applications submenu of
the root menu.

Since the overhead of starting the menu subprocess may be noticeable on
some systems, it is possible to leave it running between menu requests.

menu-program-stays-running

Variable

This variable defines if, and for how long, the menu subprocess is
allowed to remain executing for after the last menu has completed. If
nil, the program is terminated immediately, if t it is
left running indefinitely, if an integer then the program will run for
that many seconds (unless another menu is displayed).

Events

Events refer to input events from X that the window manager receives,
either for the root window, the window frames it creates, or grabbed
from the client windows themselves. Each event induced by the mouse or
keyboard has a Lisp representation.

Each input event is represented by a cons cell containing two integers,
these integers encode the actual input event. The encoding is opaque;
the only way to access an event meaningfully is via the functions
provided.

eventp object

Function

This function returns t if its argument is an input event.

Each event has a name, a string. This string contains zero or more
modifier descriptions separated by hyphens, and then the name of the
key itself. The standard X modifier names are provided, as well as
three special modifiers <Meta>, <Alt> and <Hyper> that are
mapped to the keysyms of the same name.

The following table lists the possible modifier prefixes:

C

The control modifier

M

The meta modifier

A

The alt modifier

S

The shift modifier

H

The hyper modifier

Modk

The standard X modifiers, for k between 1 and 5

Buttonk

The k'th mouse button is currently pressed

Note that the M and A modifiers are virtual modifiers
assigned dynamically, according to the X server's xmodmap
configuration. The A virtual modifier is assigned to the X
modifier with either the <Alt_L> or <Alt_R> keysym assigned to
it. The M virtual modifier is assigned to the X modifier with
either <Meta_L> or <Meta_R> assigned to it. If either of these
two virtual modifiers would be unassigned it is set identically to the
other virtual modifier.

There are two special modifiers: the Any prefix matches any set
of modifiers; the Release modifier matches key-release events
instead of the default key-presses.

Generally keys have the same names as their X keysyms, there are
several specially defined keys:

SPC, TAB, RET, ESC, BS, DEL,
Up, Down, Left, Right.

Also, there are several pseudo-keys for describing mouse events:

Click1, Click2, Click3, Off, Move.

So, for example, a single click of the left mouse button with the
<Meta> key held would be described as M-Button1-Click1, while
pressing the <RET> key with <Shift> held would be described as
S-RET.

Functions are available to convert between the name of an event and the
actual event itself, and vice versa.

Commands

A command is a Lisp function which may be called interactively,
that is, either as a result of being bound to an input event.

Commands are defined in the same way as functions (using defun),
but the body forms of the command must contain an interactive
declaration. This marks that the function may be called interactively
and tells the call-command function how to compute the argument
values to apply to the command.

The interactive declaration looks like a call to the special form
interactive, in actual fact this special form always returns
nil and has no side-effects. The only effect of this form is to
show the call-command function that the function definition may
be called interactively. The second element of the declaration form
(after the interactive symbol) defines how the argument values
applied to the command are computed.

The structure of an interactive declaration, then, is:

(interactive [calling-spec])

When a command is defined this is how it includes the interactive
declaration:

The calling-spec form defines the argument values applied to the
command when it is called interactively, it may be one of,

nil or undefined (i.e. (interactive)); no arguments are
given to the command, this type of interactive declaration just shows
that the function may be called interactively.

A string; zero or more lines (each separated by a newline
character), each line defines how to compute one argument value. The
first one or two characters of each line is a prefix defining exactly
how to compute the argument, the rest of the line is an optional
argument which some prefixes may use.

The currently available prefixes are,

e

The event which caused this command to be invoked.

E

The event which caused this command, cooked into a string.

p

The prefix argument as a number, this will be 1 if no prefix argument
has been entered.

P

The raw prefix argument.

t

The symbol t.

%f

The window which currently has the input focus, or nil if no
window is focused.

%w

The result of calling the current-event-window function.

%W

The result of calling the current-event-window function, or if
this returns nil or root, the currently focused window.

A null line produces an argument value of nil.

Anything else; the form is evaluated and expected to return a list
of arguments to apply to the command.

When a command is to be invoked, the call-command function is
used. This builds a list of argument values to apply to the command
(using its interactive declaration) then calls the command.

commandpobject

Function

This function returns t if its argument may be called interactively.
If object is a function (i.e. a symbol or a lambda-expression) it
is a command if it contains an interactive declaration

The only other object which is a command is a function call form; the
use of these types of commands is discouraged but they can be useful
sometimes.

call-command command &optional prefix-arg

Function

This function calls the command command interactively. See the
documentation of commandp above for what constitutes a command.

If the prefix-argument is non-nil it defines the value of the
current-prefix-arg variable for this command, normally the value
of this variable would be taken from the global prefix-arg
variable.

Event Loop

The event loop reads all X events received on any of the windows that
Sawfish is aware off. Many of these events invoke hooks, as described
in Standard Hooks. Keyboard and pointer events are translated to
their Lisp equivalents (see Events) and then used to scan all
active keymaps for a binding. If a binding is found, the associated
command is invoked through the call-command function.

The active keymaps are determined as follows:

If the variable override-keymap is non-nil, then this is
the only keymap searched

Otherwise three keymaps are searched:

the keymap property of the currently "clicked" frame
part if there is one,

the keymap property of the currently focused window

the contents of the variable global-keymap.

Note that for ButtonRelease events, the frame part's keymap is
only searched if the pointer is actually within the frame part when the
release event occurs.

If no binding may be found in any of the active keymaps, then the
unbound-key-hook hook is called. This is an or type
hook--the first function that returns non-nil will terminate the hook
call.

lookup-event-binding event

Function

Perform the usual binding lookup for the event object object.
Returns the command found, or nil if no binding exists.

By default, both key-release events, and events that are bound to
modifier keys (e.g. <Control_L>), are ignored. However, this
behavior may be changed:

eval-modifier-events

Variable

When non-nil, key events bound to modifier keys are evaluated.

eval-key-release-events

Variable

When non-nil, key-release events are evaluated.

While a command is being evaluated, information about the event that
caused it may be found:

current-event

Function

Return the event which caused the current command to be invoked

current-event-string

Function

Returns the string which the current event would usually insert.

current-event-window

Function

Return the window that received the current event, or the symbol
root, or nil if no such window.

last-event

Function

Return the previous event which occurred.

proxy-current-event window &optional mask propagate

Function

Send the current X event to window, either a window object, a
numeric window id, or the symbol root. If a ButtonPress
event the pointer grab will be released first.

mask may be an integer defining the X event mask to pass to the
XSendEvent function. If not defined, a mask is chosen that would
usually be used to select the type of event being proxied.

allow-events mode

Function

This is a wrapper for the XAllowEvents function. The mode
parameter may be one of the following symbols: async-pointer,
async-keyboard, sync-pointer, sync-keyboard,
replay-pointer, replay-keyboard, async-both,
sync-both.

Events that have to be grabbed to be received (i.e. all bindings in the
global-keymap and the window-keymap) are grabbed
synchronously. This means that no more events will be received until
either the command returns, or allow-events is called.

This is normally not important, but if the command expects to receive
further events it must call allow-events. See the interactive
move and resize functions for an example.

forget-button-press

Function

Cause the next button press to be treated as a single click event, no
matter how soon it occurs after the prevous button-press event.

accept-x-input &optional mask

Function

Handle any X events received. If mask is non-nil then only events
matching this numeric value are handled (see the X header files for
details).

Display Functions

Draw an outline of a window of dimensions (width, height)
at position (x, y) relative to the root window.

mode is a symbol defining the type of outline drawn, currently it
may only be box for a 3x3 grid.

Use the erase-window-outline to erase the grid. Also note that
since these functions draw directly on the root window the server
should be grabbed until the outline is erased.

erase-window-outline mode x y width height

Function

Erase a previously drawn outline of a window of dimensions
(width, height) at position (x, y) relative to
the root window.

mode is a symbol defining the type of outline drawn, currently it
may only be box for a 3x3 grid.

display-message &optional text attributes

Function

Display the string text in a window on the screen. If text
is nil then any string previously displayed is removed. Returns
the numeric id of the window displaying the message, or nil if
no message is displayed.

attributes is an alist specifying how the string should be
displayed; each element of the list is a cons cell (attr .
value) associating an attribute attr (a symbol) with it's
value.

Possible attributes currently include:

font

The font to use

foreground

The color (or color name) to draw the text with

background

The color (or color name) to draw the background with

x-justify

The justification method for multi-line strings. One of the symbols
left, right, or center

spacing

The number of extra pixels of vertical spacing to leave between text
lines.

position

A cons cell defining the coordinates at which to display the message
window. The cell is (x . y). x and y are
integers or nil (for centered display). If negative they count
in from the left and bottom edges respectively.

Standard Hooks

Sawfish provides many hooks to allow extension of previously defined
functions. Also, many X events are exported to the Lisp environment via
the hooks mechanism. For more details on the hooks mechanism see
Normal Hooks.

As well as using the standard call-hook function, sawfish also
provides the call-window-hook function. This is used to invoke
hooks which refer to a single window. If the hook has a local value
defined in the window's property list then this value is used, before
the default value defined by the actual variable.

call-window-hook hook window &optional args hook-type

Function

Call hook for window with further arguments args. See
call-hook for a description of hook-type. Each function in
the hook is called with arguments (window . args).

The following table describes all standard hooks called by Sawfish, and
the arguments they are called with:

pre-command-hook

Called before each command is evaluated.

post-command-hook

Called after each command is evaluated.

unbound-key-hook

Called when an key or pointer event has been received which there is no
binding for.

before-add-window-hook

add-window-hook

Called with a single window when the window is first adopted by the
window manager. before-add-window-hook is called first, it
should only set properties of the window.

destroy-notify-hook

Called when the window is destroyed. Note that this may be called
asynchronously to the normal event loop. In general, the window manager
will attempt to call this hook as soon after it knows the window has
been destroyed as is possible.

map-notify-hook

unmap-notify-hook

reparent-notify-hook

enter-notify-hook

leave-notify-hook

focus-in-hook

focus-out-hook

shape-notify-hook

Called with a single window argument, analogous to the X events of the
same names.

Called before starting an interactive move or resize, with a single
argument: the window.

while-moving-hook

while-resizing-hook

Called while interactively moving or resizing the window passed as the
argument to the hook.

after-move-hook

after-resize-hook

Called after completion of an interactive move or resize. Called with
two arguments: the window, and a list of symbols defining how the
window was moved or resized.

gtkrc-changed-hook

When using the gtkrc module to load the current gtk style
parameters, this hook is called when the style changes.

enter-flipper-hook

leave-flipper-hook

When viewport edge-flipping is enabled, these hooks are called as the
pointer enters and leaves the pixel-wide border on the edge of the
screen. They're called with a single argument, one of the symbols
left, right, top, bottom defining the edge
in question.

Standard Window Properties

As described in an earlier section of this manual, each window has a
property list, which may be used to associate arbitrary lisp data with
symbolic keys (see Window Property Lists). The following table
documents a subset of the keys currently used.

ignored

When set, the window is ignored in many operations.

avoid

When set, the window will not be covered when maximizing, or when
placing using the first-fit or best-fit methods

workspaces

A list of integers defining the workspaces that the window is a member of, or
nil if the window is sticky.
See Workspaces.

Session Management

Sawfish has fully integrated support for the X session management
protocols. Also, this support is extensible to allow all Lisp modules
to save and reload their own window state.

There are two methods of doing this. If the module only wants to save
and restore the values of properties in each window's property list
(i.e. those values set via window-put), then the following
function may be used:

sm-add-saved-properties &rest properties

Function

Arrange for all symbols properties to be saved and loaded with
the session.

If a Lisp module chooses to use this method it may add a function to
the add-window-hook to act on the reloaded properties when the
session is reloaded.

For more complex window properties that can't be saved straight from
the window's plist two hooks are available:

sm-window-save-functions

Variable

A list of functions, each of which is called when the state of each
window is saved. Each function is called with a single argument (the
window) and should return a list of alist elements that will be saved
in the state file. (As such, only values with valid read syntaxes may
be included.)

sm-restore-window-hook

Variable

List of functions called when the state of a window is restored. Each
is called with arguments (windowalist), where
alist defines the state saved for the window.

Each function should look for the properties it saved, and then take
any action dependent on the values.

Frequently Asked Questions

Why is it now called Sawfish?

Because the old name (Sawmill) was already being used by another
company, who were in the process of registering it as a trademark.

The rename should be mostly painless, all old binaries still work for
the time being, but will be phased out over time. Where before you
would execute a program called sawmill*, replace it by
sawfish*. E.g. sawmill becomes sawfish, and
sawmill-client becomes sawfish-client.

Your ~/.sawmill directory will automatically be renamed
~/.sawfish unless it would overwrite an existing file. Both
~/.sawfishrc and ~/.sawmillrc will be checked currently
(though only one will be actually loaded).

My apologies for any inconvenience caused.

But why Sawfish, and not <insert your favourite
alternative>?

Well I had to choose something! And hopefully it satisfies the main
requirements:

There are no other computer-related users of the name (as checked
in April 2000,)

It's similar enough to the old name to hopefully carry some
recognition across,

It has no tenuous relationship to window-managing.

I installed Sawfish but it's not working! All I see when I
start X is the default stipple background: no programs, no menus, no
pager.

This is exactly what it's supposed to do. Sawfish is a window
manager and as such is not responsible for setting the background,
starting programs or displaying a pager--these can all be done using
separate applications (e.g. by using a desktop environment such as
GNOME).

The default menu binding is somewhat obscure; you must middle-click on
the background to bring up the menus. (If you have a two-button mouse,
try clicking both buttons simultaneously)

If, after reading this, you still think that sawfish isn't working,
please send mail describing the problem to the sawfish mailing list
sawmill@aarg.net

How do I add customizations?

There are several files controlling this:

~/.sawfishrc

Hand written lisp code, loaded at startup. This is where almost all
explicit customization should be done.

sawmill-defaults

This lisp library is only loaded if there's no .sawfishrc file.

~/.sawfish/custom

This stores customizations created by the configuration tool; it
shouldn't really be edited manually.

This file is loaded aftersawmill-defaults, but before.sawfishrc.

I created .sawfishrc, now things have changed?

If a ~/.sawfishrc file exists, it prevents
sawmill-defaults from being loaded. But it's
sawmill-defaults that loads some of the common window manager
features, so add the line

(require 'sawmill-defaults)

to your .sawfishrc file if you want to start with all
the standard features loaded.

What's this sawfish-client program?

This allows you to connect to a window manager process and evaluate
arbitrary Lisp forms. Do sawfish-client -? for more details
(sawfish-client - for a read-eval-print loop)

By default you can only connect from the host running the wm (through a
unix-domain socket). To enable the network based server, evaluate the
lisp form (server-net-init).

Note however that this connects through the X server, meaning that
anyone who can open windows on your display can also execute any Lisp
code on the host running the window manager (and by extension,
execute any program).

So don't run the net server with X access control disabled
(unless you're not connected to a network)

How do I bind a key to execute a shell command?

Bind a key to the run-shell-command command; remember to enter
the shell command you want to execute in the string entry in the
Edit binding dialog window.

How do I make clicking on a window raise the window?

Bind the event Button1-Click1 in the window-keymap to the
raise-window-and-pass-through-click command

Basically though, create a directory ~/.sawfish/themes/foo
where foo is the name of your theme. Then copy any images into
this directory and create a file theme.jl that will be loaded to
initialise the theme

The configuration tool will display the contents of a file called
README in the directory (but make it 80-column text, and only a
few lines)

Recent versions of sawfish include a program sawfish-themer that
allows simple themes to be created using a GTK+ interface. Ian McKellar
has created GimpMill:

GimpMill is a GIMP plugin written in Python using James Henstrige's
really cool Python GIMP bindings. It allows the construction of Sawmill
themes within The GIMP - extending the GIMP interface to allow theme
creation like the GAP extends it to allow animation creation.

GimpMill is available from <http://www.yakk.net/projects.gimpmill.html>

How do I port an Enlightenment theme to sawfish?

There's no automatic translation available. Get the images used in the
window border, then write a theme.jl file telling the window
manager how they are used to form a window frame

See the themes/brushed-metal directory for an example, and the
Info manual for the documentation

Are there any other themes available?

Thanks to those nice people at themes.org, there's now
<http://sawmill.themes.org/> for your theming pleasure

Why don't GTK themes work with sawfish?

There was a problem with older versions of the gtk-engines
package preventing engine based themes working with several interpreted
languages. Get the latest gtk-engines from
<ftp://ftp.gnome.org/>

Why don't you use GUILE?

Mainly because I'm lazy; I had already written rep, and therefore
understood it completely, whereas I have never used GUILE. Also, rep
has some features not available in GUILE (byte-code compilation,
autoloading, built-in event-loop, ...)

But before you flame me: yes I do think scheme is a more elegant
language

Will you add feature x?

Possibly. But only if it can be written in Lisp, or doesn't conflict
with the overall design aims.

These aims are to build a lightweight, generally applicable, set of
core window management functions, then write all high-level
functionality as Lisp extensions

Will you add background setting?

No. This can easily be done by a separate application (e.g. with the
GNOME hints, simply monitor property _WIN_WORKSPACE on the root
window).

Sawmill has an irc channel too! It's on EFNet, and called (of all
crazy things), #sawmill. So break out your irc clients, or hop on over
if you're already addicted. Theme, lisp, general sawmill, and most
other random discussion welcome.

If you need an EFNet server, check www.efnet.net for a listing.

Why does sawfish look weird/crash on Solaris?

Sawfish works stably on Solaris, but you may need to do two things:

Disable use of MIT-SHM by Imlib (run the program imlib_config,
the MIT-SHM option is on the Rendering page)

Recompile GTK+ using the --disable-xim option to configure

Why don't some windows ever get focused?

If you don't have the option `give focus to windows even when they
haven't asked for it' checked (group Focus/Advanced), then windows that
don't ask for focus don't get it.

Windows ask to receive focus by setting their WM_HINTS property
appropriately; for example if I xprop a gnome-terminal: