Previous Table of Contents Next


Because SCWM has a full programming language as its configuration and extension mechanism, fewer features need to be included in the window manager as primitives. For example, users often like window controls that “toggle” some characteristic—whether the window is in front of other windows, or behind them, whether it is iconified, whether it is zoomed, and so on. Rather than include these functions as primitives, SCWM implements them in Scheme, using a higher-order function that captures the concept of a toggle. The following code appears in the (app scwm winops) module of the standard SCWM distribution (slightly edited here):

   (define (make-toggling-winop pred neg pos)
    (lambda* (#&optional (w (get-window)))
     (if w (if (pred w)
            (neg w)
            (pos w)))))

   (define toggle-raise
     (make-toggling-winop raised? lower-window raise-window))
   (define toggle-iconify
     (make-toggling-winop iconified? deiconify iconify))
   (define toggle-stick
     (make-toggling-winop sticky? unstick stick))

The function make-toggling-winop builds toggling commands. Its first argument should be a function that, when applied to a window, indicates whether the property being toggled is currently true. Its second argument should be a function that turns the toggle off, and its third should turn it back on. Given these three functions, make-toggling-winop returns a new function to toggle the given property, which can be bound to a key, menu item, or button. Using make-toggling-winop, the functions toggle-raise, toggle-iconify, and toggle-stick have trivial definitions.

Because SCWM uses a full-fledged language for configuration and extension, it needs fewer primitive procedures in its core and can express the operations it does provide in simpler terms—in this example, separating the notion of a toggle from the property being toggled.

To create SCWM, Stachowiak started with the source code for Robert Nation’s FVWM window manager and gradually replaced the original home-grown configuration language with Guile. Procedures such as window-position and bind-key are implemented in C and operate directly on the window manager’s internal data structures, whereas others such as %x and %y are defined in Scheme. Guile also allows C code to augment the Scheme type system with new data types; the SCWM examples shown previously illustrate how Scheme code may operate on instances of the window type.

Stachowiak describes his experiences replacing the built-in functions of FVWM with Guile equivalents:

Converting the built-ins themselves was relatively simple for most cases…. However, in doing the conversion, I have often made my Scheme procedures much simpler than the FVWM commands they emulate because the extra features of the FVWM commands could be done by using normal Scheme functionality. As an example, instead of making move-pointer-to (my equivalent of move-cursor) be able to move the pointer either absolutely or relatively, I added a procedure that gets the current pointer position and wrote the relative move version in Scheme using it. As another example, I wrote the Next, Prev, and WindowList command equivalents entirely in Scheme based on very simple primitives. Although a conversion could be done almost mechanically, it is a big win to give it deeper thought.1


1
Email posted to the Guile mailing list, September 1997.

Stachowiak also reports that the code to support the Guile-based configuration commands was typically two thirds to one half the length of the original code, mostly because Guile takes care of parsing on the applications behalf.2


2
Personal communication, October 1997.

SCWM is not only smaller than its predecessor, but also more powerful. FVWM does support user-defined functions that accept arguments, but there are no general control structures, data structures, or global variables. Given the design of FVWM, these are reasonable limitations; implementing a complete, general programming language would be a distraction from the main purpose of the program. However, because SCWM uses Guile, it requires no extra effort on the part of the SCWM developers to support all of these programming features. Guile relieves the programmer of the burden of language design and implementation.

4.4. Specializing Guile

To encourage customization, Guile provides extensive interfaces, allowing C code to interact with the Scheme world. C code can freely create, access, and mutate Scheme objects; C functions may call Scheme functions and vice versa; C code may add new types to the Scheme world and take advantage of Guile’s garbage collector.

After initialization, the application typically calls the appropriate Guile functions to introduce its extensions to Scheme. For example, here are the relevant portions of the SCSH’s initialization code:

     void
     main(int argc, char **argv)
     {
      gh_enter(argc, argv, scwm_main);
     }

     void
     scwm_main(int argc, char **argv)
     {
       …
       init_scwm_types();
       …
       init_scwm_procs();
       …
       HandleEvents();
       …
     }

As in the previous Guile shell example, control passes to scwm_main once initialization is complete. That function calls init_scwm_types to define the new types needed by SCWM, then init_scwm_procs to publish SCWM’s primitives to the Scheme interpreter, and finally HandleEvents, the main event loop of the window manager.


Previous Table of Contents Next