Documentation
Learn how to configure and master LuraWM
Contents
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.
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:
- Add yourself to the
videoandinputgroups, or - Use
elogind/systemd-logindwith polkit installed, or - Add yourself to the
seatgroup and enable/startseatd
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:
- Missing seat access (see Environment & Session)
- Wrong wlroots version (must be 0.19.x)
- GPU driver not loaded or incompatible
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.