Documentation

Learn how to configure and master LuraWM

Contents

[Lura]

Overview

LuraWM is a minimal Wayland compositor forked from dwl. It follows the same suckless philosophy. Simple, fast, and easily extensible through patches. If you have ever used dwm on X11, you will feel at home here.

Dependencies

Required:

Package Purpose
libinput Input device handling
wayland Wayland protocol libraries
wlroots0.19 Compositor library
xkbcommon Keyboard layout handling
wayland-protocols Protocol XML files (compile-time only)
pkg-config Build dependency resolution (compile-time only)

Additional for XWayland support:

Package Purpose
libxcb X11 client library
libxcb-wm Window management helpers for XCB
xwayland X11 compatibility layer (runtime only)

On distributions with split packages (e.g. Debian, Fedora), install the -devel or -dev counterparts as well.

Building & Installing

git clone https://codeberg.org/Mandy/LuraWM
cd LuraWM
cp config.def.h config.h
# Edit config.h to your liking
sudo make install

This installs the lurawm binary to /usr/local/bin, the man page to /usr/local/share/man/man1, and a Wayland session desktop entry to /usr/local/share/wayland-sessions.

To change the install prefix, edit config.mk:

PREFIX = /usr

Enabling XWayland: Uncomment the XWayland flags in config.mk:

XWAYLAND = -DXWAYLAND
XLIBS = xcb xcb-icccm

To uninstall:

sudo make uninstall

Running LuraWM

LuraWM can be started directly from a TTY, or from within an existing Wayland or X11 session (useful for testing).

From a TTY:

lurawm

With a startup command (autostart.sh, status bar, etc.):

lurawm -s 'lurabar'

The -s command is run as a child process. LuraWM sends it SIGTERM at shutdown and waits for it to exit. This makes it suitable for launching service managers like s6, dinit, or systemd --user.

Note: The -s flag cannot set environment variables for the LuraWM session. Set any required variables (e.g. XDG_RUNTIME_DIR) before launching LuraWM.

Command-line flags:

Flag Description
-v Print version and exit
-d Enable full wlroots debug logging
-s <cmd> Run a startup command

From a display manager: LuraWM installs a lurawm.desktop file. Display managers that support Wayland sessions will pick it up automatically.

If you are using the lurawm.desktop file, you can add the -s flag to add a startup script to your session. For example:

[Desktop Entry]
Name=LuraWM
Comment=Lura's Window Manager
Exec=sh -c 'lurawm -s "$HOME/path/to/autostart.sh"'
Type=Application

Choosing Status Bars

There hasn't been a huge variety of bars tested on LuraWM. LuraBar is the status bar made for LuraWM to address the unreliability of other alternatives. It is forked from dwlb and is actively maintained for LuraWM.

Other than LuraBar, Waybar works well.
With more hopefully coming soon.

dwlb & somebar, which are status bars made for dwl, are both unmaintained projects and do not work on LuraWM well.. Or at all.

As of now, there isn't a patch for adding a bar to LuraWM like the bar patch from dwl's repository. And as of writing this, that patch has been barely maintained by it's maintainer, sewn.

If you would like to rewrite or port that patch over to LuraWM's patches repository, go ahead! Create an issue, a pull request, or contact a maintainer.

Configuration

There are no runtime configuration files, configuring is done by editing config.h and recompiling.

cp config.def.h config.h
# Edit config.h to your liking
sudo make clean install

The file config.def.h is the default configuration template. Copy it to config.h.

Colors are defined as 32-bit hex RGBA values using the COLOR() macro:

static const float rootcolor[]   = COLOR(0x222222ff);
static const float bordercolor[] = COLOR(0x444444ff); /* Inactive */
static const float focuscolor[]  = COLOR(0x555555ff); /* Active */
static const float urgentcolor[] = COLOR(0xff0000ff);

Other settings in config.h:

Variable Default Description
sloppyfocus 1 Focus follows mouse pointer
borderpx 1 Window border thickness in pixels
TAGCOUNT 9 Number of tags (max 31)
log_level WLR_ERROR Logging verbosity
repeat_rate 30 Key repeat rate (characters/sec)
repeat_delay 250 Delay before key repeat starts (ms)
MODKEY ALT Modifier key for all keybindings

To use the Super (Logo/Windows) key instead of Alt, change the define:

#define MODKEY WLR_MODIFIER_LOGO

Default Keybindings

The default MODKEY is Alt.
All keybindings below use Mod to mean whatever MODKEY is set to.

Window Management

Keybinding Action
Mod + Shift + Return Open terminal
Mod + p Open launcher
Mod + j Focus next window
Mod + k Focus previous window
Mod + Return Zoom — swap focused window with master
Mod + q Close focused window
Mod + e Toggle fullscreen
Mod + Shift + Space Toggle focused window floating

Layout Control

Keybinding Action
Mod + i Increase master count
Mod + d Decrease master count
Mod + h Shrink master area
Mod + l Grow master area
Mod + t Set layout: tile []=
Mod + f Set layout: floating ><>
Mod + m Set layout: monocle [M]
Mod + Space Toggle between current and previous layout

Tag Navigation

Keybinding Action
Mod + [1-9] View tag 1-9
Mod + Ctrl + [1-9] Toggle visibility of tag 1-9
Mod + Shift + [1-9] Move focused window to tag 1-9
Mod + Ctrl + Shift + [1-9] Toggle focused window on tag 1-9
Mod + 0 View all tags
Mod + Shift + 0 Apply all tags to focused window
Mod + Tab Toggle between last two tags

Monitor Control

Keybinding Action
Mod + , (comma) Focus monitor to the left
Mod + . (period) Focus monitor to the right
Mod + Shift + < Move window to monitor on the left
Mod + Shift + > Move window to monitor on the right

Session

Keybinding Action
Mod + Shift + q Quit LuraWM
Ctrl + Alt + Backspace Quit LuraWM (X11 legacy shortcut)
Ctrl + Alt + F[1-12] Switch to another TTY from 1-12

Mouse Bindings

Binding Action
Mod + Left Click Move window
Mod + Middle Click Toggle floating
Mod + Right Click Resize window

Layouts

LuraWM ships with three layouts.
The active layout is shown in the status bar area as its symbol, if you have a status bar like LuraBar which supports this.

Symbol Name Behaviour
[]= Tile Master-stack tiling. The master area takes a configurable fraction (mfact) of the screen. Stack windows share the rest equally.
><> Floating All windows float freely, positioned and sized by the user.
[M] Monocle The focused window takes the full screen. Other windows are hidden behind it.

You can adjust the master area ratio with Mod + h / Mod + l (5% by default), and add or remove windows from the master area with Mod + i / Mod + d.

Tags

Unlike traditional workspaces, tags are a bitmask. A window can belong to one or more tags simultaneously, and you can view one or more tags at the same time.

By default there are 9 tags, accessed via Mod + [1-9]. The maximum is 31 (defined by TAGCOUNT in config.h).

Sticky windows: To make a window visible on all tags, press Mod + Shift + 0 (assigns all tags). This is useful for always-visible terminals or music players.

Monitors

Multi-monitor configuration is handled via the monrules array in config.h. Each rule matches an output by name and specifies:

Field Description
name Output name (e.g. "eDP-1", "HDMI-A-1"). Use NULL for a catch-all default.
mfact Master area ratio (0.0 to 1.0). Default: 0.55
nmaster Number of windows in master area. Default: 1
scale Output scale factor for HiDPI. Default: 1
layout Default layout for this monitor
rotate/reflect Output transform (e.g. WL_OUTPUT_TRANSFORM_90)
x, y Position. Use (-1, -1) for auto-placement.

Example for a HiDPI laptop display:

{ "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },

To find your output names, run wlr-randr or check LuraWM debug output with lurawm -d.

Trackpad & Input

Trackpad and input settings are configured via libinput variables in config.h:

Variable Default Description
tap_to_click 1 Tap the trackpad to click
tap_and_drag 1 Tap-then-drag gesture
drag_lock 1 Continue drag after lifting finger briefly
natural_scrolling 0 Inverted scroll direction (macOS-style)
disable_while_typing 1 Disable trackpad while typing
left_handed 0 Swap left/right buttons
middle_button_emulation 0 Press left+right simultaneously for middle click
accel_profile ADAPTIVE Pointer acceleration. Use FLAT for no acceleration.
accel_speed 0.0 Pointer speed (-1.0 to 1.0)
scroll_method 2FG Two-finger scroll. Alternatives: EDGE, ON_BUTTON_DOWN, NO_SCROLL
click_method BUTTON_AREAS Click zones. Alternative: CLICKFINGER
button_map LRM 1/2/3 finger tap maps to left/right/middle. Alternative: LMR

Keyboard layouts are configured via XKB rules:

static const struct xkb_rule_names xkb_rules = {
    .options = NULL,
};

Examples:

.layout = "us,de" for US/German
.options = "ctrl:nocaps" to map Caps Lock to Ctrl, or .options = "grp:alt_shift_toggle" to toggle layouts with Alt + Shift.

Client Rules

Client rules match windows by app_id (or WM_CLASS for XWayland) and title, then apply settings automatically. Defined in the rules[] array:

static const Rule rules[] = {
    /* app_id           title  tags mask  isfloating  monitor */
    { "Gimp_EXAMPLE",   NULL,  0,         1,          -1 },
    { "firefox_EXAMPLE", NULL, 1 << 8,    0,          -1 },
};
Field Description
app_id Match by application ID. Use NULL to match any.
title Match by window title. Use NULL to match any.
tags mask Force window onto specific tags. 0 means use current tag. 1 << 8 means tag 9.
isfloating 1 to start floating, 0 for tiled.
monitor Force onto a monitor. -1 means current monitor.

To find an application's app_id, focus its window and check the status output, or use tools like wlr-randr and wlprop.

Patches

All patches are available in the patches repository.

IPC Patch

Enables inter-process communication between LuraWM and external programs. The IPC protocol is based on dwl-ipc-unstable-v2 and is primarily used by LuraBar and other bars to receive tag, layout, and window information directly from the compositor, rather than parsing stdout.

With IPC enabled, LuraBar can respond to tag clicks and display live compositor state without the stdin/stdout pipe mechanism.

Gaps Patch

Adds configurable inner and outer gaps between tiled windows. Gap sizes are set in config.h after the patch is applied.

To apply a patch:

patch -p1 < patchfile.patch

Tip: After applying a patch, always rebuild with sudo make clean install

Applying dwl Patches

Since LuraWM is a fork of dwl, many community patches from the dwl-patches repository can be ported with minimal effort.

Applying patches straight from dwl's patches repository is not recommended, but if you wish to, some hunks may fail. In that case, look at the .rej files and apply the changes manually. This applies to LuraWM patches too if they are unmaintained.

Status Bar Integration

LuraWM writes status information (tags, layout symbol, window title) to the stdout of the compositor, which is piped into the stdin of the -s command. This means any script that reads line-by-line from stdin can act as a status bar.

Using LuraBar:

lurawm -s 'lurabar'

Automatically detects IPC to handle tag clicks and live state updates.

Using a custom script:

lurawm -s 'your-bar-script'

Important: If your startup command does not consume stdin, you must close it explicitly, or LuraWM will block when the pipe buffer fills up:

lurawm -s 'foot --server <&-'

Inside a shell script, use exec <&- to close stdin for all subsequent commands.

Environment & Session

Wayland requires XDG_RUNTIME_DIR to be set. This is normally handled by your login manager or elogind/systemd-logind.

If you're launching without a session manager:

export XDG_RUNTIME_DIR=/tmp/xdg-runtime-$(id -u)
mkdir -p $XDG_RUNTIME_DIR
lurawm

Seat access: Depending on your setup, you may need to:

Java applications: Some Java AWT applications (e.g. Xilinx Vivado, IntelliJ) may not render correctly. Set this before launching:

export _JAVA_AWT_WM_NONREPARENTING=1

Troubleshooting

Screen sharing does not work

Wayland screen sharing requires xdg-desktop-portal-wlr and PipeWire. Make sure both are installed and running. Some applications also need the WAYLAND_DISPLAY and XDG_CURRENT_DESKTOP environment variables set.

XWayland applications look blurry on HiDPI

X11 applications are not aware of Wayland scaling. They render at 1x and the compositor scales them up. There is no general fix; some applications support GDK_SCALE or QT_SCALE_FACTOR.

No output / black screen after starting

Run lurawm -d for debug output. Common causes:

Borders do not change size

The borderpx variable in config.def.h may not visually change for higher values in the current release. This is a known issue tracked for the next release.

How do I restart LuraWM without losing my session?

You cannot. In the Wayland architecture, the compositor is the display server. Restarting it ends the session. Recompile and restart from a TTY.