Table of Contents

Layout Engines

A "layout engine" or ILayoutEngine in Whim is responsible for arranging windows in a workspace. Each workspace has a single active layout engine, and can cycle through different layout engines.

There are two different types of layout engines:

  • proxy layout engines
  • leaf layout engines

Proxy layout engines wrap other engines, and can be used to modify the behavior of other engines. For example, the Gaps plugin will add gaps between windows - normally layout engines won't leave gaps between windows.

Leaf layout engines are the lowest level layout engines, and are responsible for actually arranging windows.

Available layout engines

Engine TL;DR
FocusLayoutEngine One window at a time
SliceLayoutEngine Awesome/dwm-style dynamic tiling (primary/stack, multi-column, etc.)
TreeLayoutEngine i3-style dynamic tiling (arbitrary grids)

FocusLayoutEngine

FocusLayoutEngine is a layout engine that displays one window at a time:

To focus the window in the specified direction, call FocusWindowInDirection(Direction, IWindow).

To reorder windows, calling SwapWindowInDirection(Direction, IWindow) will swap the current window with the window in the specified direction. This will not change the focused window.

Windows which are not focused are minimized to the taskbar.

FocusLayoutEngine demo

SliceLayoutEngine

SliceLayoutEngine is an Awesome/dwm-style layout engine, which arranges following a deterministic algorithm filling a grid configured in the config file.

Each SliceLayoutEngine is divided into a number of IAreas. There are three types of IAreas:

  • ParentArea: An area that can have any IArea implementation as a child
  • SliceArea: An ordered area that can have any IWindow as a child. There can be multiple SliceAreas in a SliceLayoutEngine, and they are ordered by the Order property/parameter.
  • OverflowArea: An area that can have any infinite number of IWindows as a child. There can be only one OverflowArea in a SliceLayoutEngine - any additional OverflowAreas will be ignored. If no OverflowArea is specified, the SliceLayoutEngine will replace the last SliceArea with an OverflowArea.

OverflowAreas are implicitly the last ordered area in the layout engine, in comparison to all SliceAreas. Internally, SliceLayoutEngine stores a list of IWindows. Each IArea corresponds to a "slice" of the IWindow list.

Defining SliceLayoutEngines

The SliceLayouts contains methods to create a few common layouts:

  • primary/stack (master/stack)
  • multi-column layout
  • three-column layout, with the middle column being the primary
context.WorkspaceManager.CreateLayoutEngines = () => new CreateLeafLayoutEngine[]
{
    (id) => SliceLayouts.CreatePrimaryStackLayout(context, sliceLayoutPlugin, id),
    (id) => SliceLayouts.CreateMultiColumnLayout(context, sliceLayoutPlugin, id, 1, 2, 0),
    (id) => CustomLayouts.CreateSecondaryPrimaryLayout(context, sliceLayoutPlugin, id)
}

Arbitrary layouts can be created by nesting areas:

context.WorkspaceManager.CreateLayoutEngines = () => new CreateLeafLayoutEngine[]
{
    (id) => new SliceLayoutEngine(
        context,
        sliceLayoutPlugin,
        id,
        new ParentArea(
            isRow: true,
            (0.5, new OverflowArea()),
            (0.5, new SliceArea(order: 0, maxChildren: 2))
        )
    ) { Name = "Overflow on left" }
};

SliceLayoutEngine requires the SliceLayoutPlugin to be added to the IPluginManager instance:

SliceLayoutPlugin sliceLayoutPlugin = new(context);
context.PluginManager.AddPlugin(sliceLayoutPlugin);

SliceLayoutEngine demo

TreeLayoutEngine

TreeLayoutEngine is a layout that allows users to create arbitrary grid layouts, similar to i3. Unlike SliceLayoutEngine, windows can can be added in any location at runtime.

TreeLayoutEngine requires the TreeLayoutPlugin to be added to the IPluginManager instance:

TreeLayoutPlugin treeLayoutPlugin = new(context);
context.PluginManager.AddPlugin(treeLayoutPlugin);

TreeLayoutEngine demo