Welcome, Guest! Log In | Create Account

DesignDocs/Tiling

Tiling

There are numerous different methods for producing a tiled layout in a window manager; PLWM should be flexible enough to support any of them the user wishes to use.

Algorithms and Examples

Static Frames

I'm pretty sure Ion uses this; basically, the screen is initially one large frame, or a preset layout of frames, where each frame can then either be deleted or subdivided manually into as many smaller frames as the user wishes. Each frame can be subdivided either horizontally or vertically into any number of arbitrarily-sized sub-frames. PLWM already has this method, to an extent, in the panes.py module and the PLPWM example WM.

Dynamic Tiling

WMII and Awesome are the best examples of this type of tiling I can think of. Two windows never occupy the same tile, and when new windows are opened, a new tile is automatically created for each of them.

In WMII's method, windows are sorted into columns; columns can be created and deleted by the user, and each column can either stack all of its windows within the column, (default) only display one, (max) or display one and have the titlebars of the others in place of where they normally would be. (stack)

Awesome exhibits several different algorithms for window placement, including some which do not qualify as tiling. (for instance, the 'floating' layout and the 'focus' layout) Some of its more interesting tiling layouts include 'spiral', where the newest tile is divided in such a way that the new tile follows a spiral pattern, and the 'fair' layouts, where the WM attempts to organize windows into the smallest number of rows and columns possible.


PLWM

In my opinion, PLWM should provide basic tiling that is flexible enough for any of these algorithms to be implemented. (I'll most likely be implementing the WMII-style column layout first, since I'm most fond of that one)

Generalization of Layout

In dealing with window layout in a window manager, there are two distinct forms of window layouts: user-directed (the user creates the tiles into which they wish to arrange their windows) and dynamic/automatic. (the window manager automatically makes decisions about the layout of the windows)

'Containers' are a way to combine these two strategies. To implement dynamic or automatic layout, we set the LayoutPolicy for a given Container. The LayoutPolicy determines how children in that Container will be laid out. Several types of policies should be available; see below for a list.

To define a user-directed tiled layout, the user will start with one full-screen Container, and split it and its children as many times in either direction as they wish; each split creates 2 or more child Containers within the one being split (the parent); these new containers then define the areas into which windows will be arranged. The parent Container should normally have a LayoutPolicy set which allows the user to adjust the relative sizes of its children, although this need not be the case. (For a fully user-directed layout, set the layout policy on all Containers which don't contain child Containers to some variant of 'full', 'tabbed' or 'stacked', and set ones which do contain child Containers to 'sash')

Containers also have a 'static' property, determining whether or not they should automatically close when their last child is closed. For a fully user-directed layout, 'static' should be set to True, so that all the Containers defined by the user stay open unless explicitly closed.

Integration With Views

Using a Container class as the basis for all layout also simplifies a unified View implementation. By representing each workspace with a full-screen Container, we can put all loading and saving of layout information into the Container and LayoutPolicy classes. Also, since you can set the LayoutPolicy of a Container to 'floating', standard floating-window workspaces can be represented with a single Container with a floating LayoutPolicy; simple, non-tiling window managers will use only this method.

Container Layout Policies

  • floating (use 'normal' WIMP layout style; each window can be moved and resized individually, and is not automatically laid out)
  • horizontal (column) (show all children at once, starting out equally sized)
  • vertical (row)
  • vertical stack (see the max, stack, and default layouts in WMII)
  • horizontal stack
  • tabs on top
  • tabs on bottom
  • tabs on left
  • tabs on right
  • fair tiling (vertical first)
  • fair tiling (horizontal first)
  • full
  • horizontal sash (same as 'horizontal', but the border between each pair of adjacent children is a draggable 'sash', allowing the children to be resized)
  • vertical sash (same as 'horizontal sash', but vertical; like 'vertical' with sashes.)

Implementation

A basic implementation is available in Bazaar at http://development.g33xnexus.com/bzr/plwm/tiling. To check out the source, run the following command: (after installing Bazaar)

bzr branch http://development.g33xnexus.com/bzr/plwm/tiling plwm-tiling

This implementation comes with an example window manager, which can be found example/tilewm.py. It has a couple of useful keys:

  • Mod4 + Return: Open a terminal.
  • Mod4 + L: Lock the screen with xscreensaver.
  • Control + Mod4 + Q: Quit the window manager.
  • Shift + Mod4 + C: Close the current window.
  • Control + Mod4 + C: Kill the current client.
  • Mod4 + Left: Focus the previous screen.
  • Mod4 + Right: Focus the next screene.
  • Mod4 + Up: Focus the next window on the current screen.
  • Mod4 + Down: Focus the previous window on the current screen.
  • Any + F5: Set the root Container's layout policy to floating.
  • Any + F6: Set the root Container's layout policy to horizontal.
  • Any + F7: Set the root Container's layout policy to vertical.
  • Any + F8: Set the root Container's layout policy to vertical stack.

Attachments