Configuration

Configuration Files

The configuration of Chamferwm is managed through a Python script. The provided configuration script defines the necessary classes and routines for layout management and overall behaviour of the window manager. For basic customization, user may want to edit the default configuration script to (re)define key bindings and add calls to launch applications and such. More advanced configuration might enhance the window management through provided callbacks, set up shaders to customize visuals and introduce other means to alter the behaviour and provide features.

By default Chamferwm will look for the configuration in following locations:

~/.config/chamfer/config.py
~/.chamfer/config.py
/usr/share/chamfer/config/config.py

The path to the configuration script can also be given with --config=[path], which will override any previously found files.

In the official setup, a default configuration script has been installed to /usr/share/chamfer/config/ as a starting point for customization. User may want to copy this file to the previously listed locations in order to start editing. Currently any modification will require a restart of the window managar to take effect.

Warning

While the configuration API is still unstable, and new features are being added, default configuration will be subject to minor changes.

Changing shortcuts

Some typical operations have already been assigned a key combination in the provided default configuration. The bound operations are listed under Key(Enum) class, where an identifier has been given to each of them. The corresponding lines to define the actual key combinations can be found futher below, under a callback chamfer.Backend.OnSetupKeys(). For each binding, one finds

self.BindKey(symbol, mask, keyId)

Here symbol is the keysym code for the desired key. A list of symbols can be found inside a header file /usr/include/X11/keysymdef.h, for example. mask defines the modifier mask for the key combination. Possible modifiers are:

  • chamfer.MOD_MASK_SHIFT

  • chamfer.MOD_MASK_CONTROL

  • chamfer.MOD_MASK_LOCK

  • chamfer.MOD_MASK_ANY

  • chamfer.MOD_MASK_1

  • chamfer.MOD_MASK_2

  • chamfer.MOD_MASK_3

  • chamfer.MOD_MASK_4

  • chamfer.MOD_MASK_5

Run xmodmap -pm to find out which key each of the mask corresponds to on your system. The last argument keyId is the identifier defined under previously mentioned Key(Enum). The identifier will be used to map a key press to an operation written in chamfer.Backend.OnKeyPress() and chamfer.Backend.OnKeyRelease().

In order to change the key binding for launching a terminal emulator for example, one should look for a self explanatory definition LAUNCH_TERMINAL, and the corresponding BindKey() entry, for which the parameters should be changed.

Launching Applications

Setting up an application launcher in case of Chamferwm consists of two steps: 1) defining the key binding and 2) adding callback functionality (corresponding the key binding) to start the said application. In this example we set up a hotkey to launch a web browser.

1. Application hotkey. First step is to bind the key which we want to launch the browser. Our choice of key combination in this example is Super+1. We add the following line under callback chamfer.Backend.OnSetupKeys() already found in the default configuration as a method of Backend class:

self.BindKey(ord('1'),chamfer.MOD_MASK_4,Key.LAUNCH_BROWSER.value)

Here chamfer.MOD_MASK_4 corresponds the modifier mask of the Super key. The last parameter takes our custom identifier of the hot key we are in process of defining. The identifier will be passed on to the key press callback chamfer.Backend.OnKeyPress() and it should be uniquely defined somewhere. We may define it using enum.Enum and enum.auto() so that it automatically receives an incremented unique value. In our default configuration we add:

class Key(Enum):
        ...
        LAUNCH_BROWSER = auto()
        ...

2. Launch procedure. We launch the application using psutil module's psutil.Popen() function. Under chamfer.Backend.OnKeyPress() callback we add a branch for our newly defined key identifier, in which we start our browser process:

elif keyId == Key.LAUNCH_BROWSER.value:
        psutil.Popen(["firefox"],stdout=None,stderr=None);

Note that it is possible to configure applications to launch on start up while the window manager is being initialized. In this case simply put psutil.Popen() somewhere in the global scope.

Any other functionality can be added similarly. Instead of calling psutil.Popen() to launch a browser, any other routine can be written in place of this. Writing routines in Python inside the same configuration file eliminates the need for smaller separate utility scripts often placed to complement to configuration file itself.

Python API

Warning

Chamferwm is work in progress, and the configuration API is subject to breaking changes. The default configuration file config.py may also undergo additions and minor refactoring.

class chamfer.Container

The workspace in Chamferwm is arranged in containers. Containers are a construct to hold either a client window or a set of child containers. The concept of a child container comes from a hierarchial approach: at the base of the tree, there exists a root container which is split into one or more child containers. The child containers may in turn be further split into child containers, or alternatively hold a single instance of a client window.

_images/chamfer-tree.svg

Container tree.

_images/chamfer-layout.svg

Possible corresponding window arrangement.

The Container class is a user implemented interface to define callbacks related to creation and initialization of the container and client window, and to handle events that might arise during window management.

OnSetupContainer()

Called to setup the container before it is created. One should setup minSize, maxSize and floatingMode here, if necessary.

OnSetupClient()

Called to setup the client before it is created. Can be especially used to assign the initial shaders vertexShader, geometryShader and fragmentShader.

OnParent()

Called to assign a parent for the container. The parent is assigned by returning the Container instance of the desired parent. Most of the time OnParent() is called upon creation of a new container, as it needs to be put into a parent container. In the default sample configuration, the parent of the operand will be the parent of the current focus (retrieved using chamfer.Backend.GetFocus()), resulting in the new container being placed next to the current focus.

OnCreate()

Called once the client has been created and mapped to the display. Typically the newly created client can now be focused by calling Focus().

OnFullscreen(toggle)

Called to request permission to enter or exit fullscreen mode for this container depending on the value of toggle. The implementation should return true on permission granted, and false for permission denied. In addition, one may assign a different set of shaders that may better benefit the fullscreen mode, and perform other operations related to the preparations for the transition.

OnStack(toggle)

Called whenever containers under this container are stacked or unstacked, denoted by toggle.

OnFocus()

Called to request permission for focus, and to allow for any routines before it. This call may be a result of calling Focus(), or a client spontaneously requesting it. Returning true assigns the focus on this container.

OnPropertyChange(propId)

Called every time a client property has changed. This may refer to window title etc., given by propId, which will have one of the values from property.

GetNext()

Get the next sibling container in the parent container.

GetPrev()

Get the previous sibling container in the parent container.

GetParent()

Retrieve the parent container.

GetFocus()

Get the focused container of the parent container. This will be one of the child containers of the operand.

GetTiledFocus()

Get the most recently focused tiled container. Successive calls on the return objects, for example container.GetTiledFocus().GetTiledFocus()..., will retrieve the second most recent, third most recent and so on container.

GetFloatFocus()

Get the most recently focused floating container.

GetAdjacent()

reserved

MoveNext()

Swap this and the next sibling container.

MovePrev()

Swap this and the previous sibling container.

Move(container)

Move this container under to a new parent, container.

Focus()

Focus the container. If the container is in another workspace, a workspace switch will occur. Changing workspaces is also possible by focusing the root container of the target workspace.

Kill()

Close the client and kill the container.

ShiftLayout(layout)

Shift the container layout to a new layout indicated by layout. Most prominently used to transition between vertical and horizontal container splittings. May also be used to force some of the changed container parameters to take effect, such as changes to canvasOffset etc., whicn for performance reasons will not result in an automatic update.

SetFullscreen(toggle)

Move this container to a fullscreen mode, or back to normal depending on the value of toggle (true, false).

SetStacked(toggle)

Toggle container stacking inside this container. If layout is equal to chamfer.layout.VSPLIT, the containers will be tabbed, and can be cycled horizontally. Otherwise, the containers are stacked, and are vertically cycled.

SetFloating(toggle)

Toggle between tiled and floating modes.

IsFloating()

Returns true if this is a floating container.

IsAlive()

Returns true if the container still exists, i.e. it has not been removed. Use of a removed container will raise an exception.

name

Name label of the container. Workspaces are identified by their root container name label.

canvasOffset

Tiled container position offset. This is a tuple of two values between 0 and 1 for horizontal and vertical directions, indicating the position offset of the container in the units of full screen widths/heights. A value of zero implies no offset, while a value of 1 displaces the container one full screen width or height. As an example, a value of (-0.1,0) implies a displacement of 10% of the screen width to the left.

canvasExtent

Tiled container size extension. See canvasOffset for details. In this case, a value of (-0.1,0) would imply a contraction of 10% of the screen width towards the left side of the container. Likewise (0,0.2) expands the container vertically 20% of the screen height downwards.

margin

A tuple of two values, one for horizontal and vertical screen dimensions. A positive non-zero value will apply a gap between the containers in order to give the compositor space to render the decorations around the client windows. The units are in full screen widths (and widths only, to preserve the aspect). Setting margin = (0.015,0.015) would inset the container by 1.5% of the screen width horizontally and vertically.

size

A tuple of two values for the size of the container and space reserved in horizontal and vertical screen direction. The units are widths and heights of the parent container: for instance, a value of (0.7,1) reserves 70% of the total horizontal and 100% of the vertical space given by the parent. If only one container exists, the value will always be (1,1). The value is automatically updated as the surrounding layout changes. For example, the first container will have a size of (1,1). Creating a second container will split the space in half, giving both containers a size (0.5,1) (in case of vertical splitting). User may then adjust the size of one of the containers to (0.7,1), which will automatically assign the other container a size (0.3,1).

minSize

Minimum size that the container may shrink to while making space for other containers. A tuple of two values, one for the each dimension of the screen. The units are widths and heights of the full screen. minSize of (0.3,0) will always keep the container width at least 30% of the full screen width, while (1,0) will make the container always occupy the full width of the screen. In case the space within the parent container runs out, containers will automatically start overlapping each other in a stacking manner.

maxSize

Maximum size that the container may expand to when there is space available. See minSize for details.

fullscreen

Read only fullscreen status: true if this container is in fullscreen mode, false otherwise.

stacked

Read only container stacking status: true if containers inside this container are stacked.

titleBar

Title bar placement for this container, see titleBar.

shaderFlags

User supplied value that will be passed on to the shaders as a push constant. See shaderFlag for the list of bit flags automatically managed by Chamferwm. Note that all bits below USER_BIT are reserved for use by Chamferwm.

wm_name

Current title of the client window. Read only.

wm_class

Current class name of the client window. Read only.

vertexShader

File name of the vertex shader to be used to render this client. The name of the file will be matched to the files found in the shader lookup directories. Default vertexShader = "default_vertex.spv".

geometryShader

File name of the geometry shader. See vertexShader for details.

fragmentShader

File name of the geometry shader. See vertexShader for details.

layout

Current tiling layout of the container. One of the values from chamfer.layout. Layout transitions are handled by calling ShiftLayout() with the desired new layout. By default, the container will be created in chamfer.layout.VSPLIT mode.

floatingMode

Determine in which mode (tiled or floating) the client shall be created. See floatingMode for possible values. Default = AUTOMATIC.

class chamfer.layout(enum.Enum)

Possible values of layout and the layout parameter of ShiftLayout(), dictating the splitting mode of the container.

VSPLIT

Implies a vertically split container. Containers will be placed in a horizontal row.

HSPLIT

Implies a horizontally split container. Containers will be placed in a vertical column.

class chamfer.floatingMode(enum.Enum)

Possible values of floatingMode, dictating the mode in which the client shall be created.

AUTOMATIC

Whether the client will be created in a floating or tiled mode will be determined automatically from its client attributes.

ALWAYS

The client is always created in floating mode, regardless of its client attributes.

NEVER

The client is always created in a tiled container, regardless of its client attributes.

class chamfer.property

Various client property identifiers.

NAME

Client window title.

CLASS

Client window class name.

class chamfer.titleBar

Title bar placement. By default the title bars are placed on top of the client.

NONE

Hide title bar

LEFT

Title bar placed at the left border of client

TOP

Title bar placed at the left border of client

RIGHT

Title bar placed at the left border of client

BOTTOM

Title bar placed at the left border of client

class chamfer.Backend

A user implemented interface to define routines for various window management related events. Moreover, Backend provides methods for ...

OnSetupKeys(debug)

Called as soon as the backend is initialized. Ideal for setting up the keybindings for example. debug will tell if testing backend (not a real window manager) was created.

OnCreateContainer()

Called to request a new instance of Container. The implementation is expected to return an instance of this class.

OnKeyPress(keyId)

Called to report a press of a key that was mapped with either Backend.BindKey() or Backend.MapKey(). keyId is the user chosen identifier for the reported key.

OnKeyRelease(keyId)

Called to report a release of a key. See Backend.OnKeyPress().

OnTimer()

reserved

OnExit()

Called when user quits the window manager.

GetFocus()

Get the currently focused container chamfer.Container.

GetRoot(name=None)

Get the root container chamfer.Container. If name is specified, return the root container belonging to that workspace. Otherwise return the root of the currently focused container. If workspace does not exist, it will be created.

BindKey(symbol, mask, keyId)

Bind key symbol with modifier mask. The key combination will be exclusive to Chamferwm, and won't be reported to any of the clients. Whenever the bound key is pressed, chamfer.Backend.OnKeyPress() with keyId is called. Likewise, chamfer.Backend.OnKeyRelease() is called when the pressed key is released.

MapKey(symbol, mask, keyId)

Unlike chamfer.Backend.BindKey(), mapped keys are not exclusive to Chamferwm, and not reported until chamfer.Backend.GrabKeyboard() is called. See chamfer.Backend.GrabKeyboard() for details.

GrabKeyboard(enable)

Once keyboard is grabbed, keys mapped using chamfer.Backend.MapKey() besides the other key bindings are reported. During this, no key input whatsoever will be reported to the clients. GrabKeyboard method is useful for implementing functionality such as task switcher, which could be operating for as long as some modifier key is being held down.

chamfer.BindBackend(backend)

Bind your instance of Backend class implementation, assigned by a call to BindBackend(). Should be done during initialization.

chamfer.backend

Bound backend class object used by Chamferwm. Read only attribute.

class chamfer.shaderFlag(enum.Enum)

Bit flags for the shader push constant, accessible with shaderFlags.

FOCUS

Client focus bit, set automatically by Chamferwm.

FLOATING

Floating client bit, set automatically by Chamferwm.

STACKED

Stacked client bit, set automatically by Chamferwm.

USER_BIT

First bit reserved for user defined flags.

class chamfer.Compositor

A user implemented interface to define routines for various compositing related events.

deviceIndex

GPU to use by its index. By default the first device in the list of enumerated GPUs will be used. May be overriden by command line arguments.

debugLayers

Enable Vulkan debug layers. May be overriden by command line arguments.

scissoring

Enable or disable scissoring optimizations. By default the optimization is enabled. If during compositing missing regions or flickering occur, the scissoring optimization can be disabled. The option --no-scissoring forces this false.

hostMemoryImport

Host shared memory import support.

unredirOnFullscreen

Disable compositor while on fullscreen (not implemented).

enableAnimation

Enable or disable transition and movement animations. Enabled by default.

animationDuration

Total duration of the transition and movement animations. Default 0.3 seconds.

fontName

Font face to use for title bars.

fontSize

Title bar font size in points.

chamfer.BindCompositor(compositor)

Bind your instance of Compositor class implementation. Should be done during initialization.

chamfer.compositor

Bound compositor class object used by Chamferwm, assigned by a call to BindCompositor(). Read only attribute.