Installation
Arch Linux (or an Arch-based distro) with Xorg is required.
Quick Install (Recommended)
The easiest way is via Linutil:
curl -fsSL https://christitus.com/linux | sh
In the TUI, press v to multi-select, then select dwm, rofi, bash prompt, and ghostty. Press Enter to install.

Manual Install
1. Dependencies
Build:
sudo pacman -S --needed base-devel libx11 libxft libxinerama imlib2 libxcb xcb-util freetype2 fontconfig
Xorg:
sudo pacman -S --needed xorg-server xorg-xinit xorg-xrandr xorg-xsetroot xorg-xset
Runtime:
sudo pacman -S --needed rofi picom dunst feh flameshot dex mate-polkit alsa-utils noto-fonts-emoji ttf-meslo-nerd
Terminal (pick one — ghostty is the default):
sudo pacman -S ghostty # or: alacritty, kitty
Status bar:
sudo pacman -S polybar
2. Clone and Build
git clone https://github.com/ChrisTitusTech/dwm-titus.git
cd dwm-titus
cp config.def.h config.h
make
sudo make install
3. Fonts
Polybar icon fonts are bundled in config/polybar/fonts/:
mkdir -p ~/.local/share/fonts
cp -r config/polybar/fonts/* ~/.local/share/fonts/
fc-cache -fv
Automated Installer
./install.sh
The script handles all dependency installation, font copying, and config placement.
Starting dwm
Display manager (SDDM, GDM, LightDM): log out and select dwm from the session list.
startx:
startx
The provided .xinitrc disables screen blanking, launches Polybar, and runs dwm.
Getting Started
After installing, the first thing to know: Super = the Windows key.
Press Super + / at any time to open the interactive keybind viewer.
Essential Actions
| Action | Keys |
|---|---|
| Open terminal | Super + X |
| App launcher (rofi) | Super + R |
| Close window | Super + Q |
| Power menu | Super + Ctrl + Q |
| Control Center | Super + F1 |
| Keybind viewer | Super + / |
Switching Tags (Workspaces)
Tags 1–9 act as workspaces. Use Super + a number to switch.
| Action | Keys |
|---|---|
| Switch to tag | Super + 1–9 |
| Move window to tag | Super + Shift + 1–9 |
| Show all tags | Super + 0 |
Layouts
Three layouts are available — switch between them instantly.
| Layout | Keys |
|---|---|
| Tiling (master + stack) | Super + T |
| Floating | Super + Shift + M |
| Fullscreen (monocle) | Super + M |
See Keybindings for the full reference.
Keybindings
Press Super + / inside dwm to open a live, searchable keybind viewer via rofi.
MODKEY = Super (Windows key) in the shipped config.h.
Bindings are defined in config/hotkeys.toml and reload instantly on save — no recompile needed.
Launchers
| Keys | Action |
|---|---|
Super + R | App launcher (rofi) |
Super + X | Terminal |
Super + E | File manager |
Super + B | Browser |
Super + / | Keybind viewer |
Super + F1 | Control Center |
Screenshots
| Keys | Action |
|---|---|
Super + P | Full screenshot |
Super + Shift + P | Screenshot selection → file |
Super + Ctrl + P | Screenshot selection → clipboard |
Web Apps
| Keys | Action |
|---|---|
Super + A | ChatGPT |
Super + Shift + A | Gemini |
Super + Shift + X | X/Twitter — new post |
Window Management
| Keys | Action |
|---|---|
Super + J | Focus next window |
Super + K | Focus previous window |
Super + Shift + J | Move window down in stack |
Super + Shift + K | Move window up in stack |
Super + Return | Promote window to master |
Super + Q | Close window |
Super + I | Add window to master area |
Super + D | Remove window from master area |
Super + H | Shrink master area |
Super + L | Expand master area |
Super + Shift + H | Increase window cfact size |
Super + Shift + L | Decrease window cfact size |
Super + Shift + O | Reset window cfact |
Layouts
| Keys | Action |
|---|---|
Super + T | Tiling layout |
Super + M | Fullscreen (monocle) |
Super + Space | Toggle floating for window |
Super + Shift + M | Toggle floating for window |
Super + Shift + Y | Fake fullscreen (bar stays) |
Super + Shift + B | Toggle bar visibility |
Tags (Workspaces)
| Keys | Action |
|---|---|
Super + 1–9 | Switch to tag |
Super + Ctrl + 1–9 | Also show tag alongside current |
Super + Shift + 1–9 | Move window to tag |
Super + Ctrl + Shift + 1–9 | Also show window on that tag |
Super + 0 | Show all tags |
Super + Tab | Previous tag |
Multi-Monitor
| Keys | Action |
|---|---|
Super + , | Focus left monitor |
Super + . | Focus right monitor |
Super + Shift + , | Send window to left monitor |
Super + Shift + . | Send window to right monitor |
Media Keys
| Keys | Action |
|---|---|
XF86AudioRaiseVolume | Volume up |
XF86AudioLowerVolume | Volume down |
XF86AudioMute | Mute toggle |
XF86MonBrightnessUp | Brightness up |
XF86MonBrightnessDown | Brightness down |
Session & Power
| Keys | Action |
|---|---|
Super + Ctrl + Q | Power menu |
Super + Shift + Q | Quit dwm |
Super + Ctrl + Shift + R | Reboot |
Super + Ctrl + Shift + S | Suspend |
Mouse
| Action | Function |
|---|---|
Super + Left drag | Move window |
Super + Middle click | Toggle floating |
Super + Right drag | Resize window |
Customizing Keybinds
Edit config/hotkeys.toml — changes take effect on save, no recompile required.
[vars]
terminal = "ghostty"
keys = [
{ mod="SUPER SHIFT", key="f", desc="Firefox", func="spawn", exec=["firefox"] },
]
See the comments in hotkeys.toml for a full list of func values and modifier syntax.
Configuration
dwm-titus uses two TOML config files that live-reload on save — no recompile needed for most changes.
| File | Purpose |
|---|---|
config/hotkeys.toml | All keybindings |
config/themes.toml | Colors, themes, border size |
For deeper changes (window rules, fonts, refresh rate), edit config.h and run make && sudo make install.
config.h Essentials
config.h is your personal copy of config.def.h. It is created automatically by make if it doesn’t exist.
$EDITOR config.h
make && sudo make install
Key Options
| Setting | Description |
|---|---|
refresh_rate | Match your monitor (default 60; set 120 for high-refresh) |
fonts[] | Font family and size used in the bar |
colors[] | Managed by themes.toml — rarely edit directly |
autostart[] | Programs launched on dwm start |
rules[] | Per-app window rules (floating, tag assignment, terminal flag) |
keys[] | Fallback static keybinds (prefer hotkeys.toml) |
MODKEY | Mod4Mask = Super, Mod1Mask = Alt |
Window Rules
Rules in config.h let you assign windows to specific tags or force float:
/* class instance title tags mask isfloating isterminal noswallow monitor */
{ "Gimp", NULL, NULL, 0, 1, 0, 0, -1 },
{ "Firefox", NULL, NULL, 1 << 1, 0, 0, -1, -1 },
hotkeys.toml — Live Keybinds
Add or change bindings without recompiling. Save the file and they apply instantly.
[vars]
terminal = "ghostty"
webapp = "webapp-launch"
keys = [
{ mod="SUPER", key="x", desc="Terminal", func="spawn", exec=["$terminal"] },
{ mod="SUPER SHIFT", key="f", desc="Firefox", func="spawn", exec=["firefox"] },
]
Modifier Syntax
Use space-separated modifiers: "SUPER", "SUPER SHIFT", "SUPER CTRL", "SUPER CTRL SHIFT".
Available Functions
func | Parameters | Description |
|---|---|---|
spawn | exec=[...] or cmd="..." | Run a program |
killclient | — | Close focused window |
zoom | — | Promote/demote master |
focusstack | i=1 or i=-1 | Focus next/prev window |
movestack | i=1 or i=-1 | Reorder in stack |
incnmaster | i=1 or i=-1 | Change master count |
setmfact | f=0.05 or f=-0.05 | Resize master area |
setcfact | f=0.25 / f=-0.25 / f=0.00 | Resize window slot |
setlayout | layout_idx=0/1/2 | 0=tile, 1=float, 2=monocle |
togglefloating | — | Float/tile window |
fullscreen | — | True fullscreen |
togglefakefullscreen | — | Fullscreen with bar |
togglebar | — | Show/hide bar |
focusmon | i=1 or i=-1 | Focus monitor |
tagmon | i=1 or i=-1 | Send window to monitor |
view | ui=-1 = all tags | Switch tag |
quit | — | Exit dwm |
Tag Bindings
Tag bindings auto-generate all four variants (switch, toggle-view, move, toggle-tag):
tag_keys = [
{ key="1", tag=0 },
{ key="2", tag=1 },
]
Notes on XDG Autostart
Recommend using Flatpak to install programs on startup:
flatpak install flathub io.github.flattool.Ignition
or you can create your own .desktop file in ~/.config/autostart/
set-refresh.desktop Example:
[Desktop Entry]
Type=Application
Exec=xrandr --output HDMI-0 --primary --mode 1920x1080 --pos 0x0 --rotate normal --rate 120 --output DP-0 --off --output DP-1 --off --output DP-2 --off --output DP-3 --off --output DP-4 --off --output DP-5 --off
Hidden=false
X-GNOME-Autostart-enabled=true
Name=Set Refresh
Theming
Themes are defined in config/themes.toml. Change the active theme and save — dwm, terminal, rofi, and polybar all update instantly. No restart needed.
[active]
theme = "nord" # ← change this line to switch themes
Available Themes
Dark
| Theme | Description |
|---|---|
nord | Arctic, cool blue palette (default) |
dracula | Purple-tinted dark theme |
gruvbox | Warm retro earth tones |
catppuccin | Mocha variant — soft pastels |
tokyonight | Deep blue-grey night theme |
onedark | Atom One Dark inspired |
solarized | Dark variant of Solarized |
rosepine | Muted rose/pine tones |
everforest | Muted green forest palette |
monochrome | Black and white minimal |
Light
| Theme | Description |
|---|---|
catppuccin-latte | Catppuccin light variant |
gruvbox-light | Warm light tones |
solarized-light | Classic Solarized light |
rosepine-dawn | Rose Pine dawn variant |
tokyonight-day | Tokyo Night day variant |
Border Size
[appearance]
borderpx = 1 # 0 = no border, 1 = thin (default), 2-3 = thicker
What Each Theme Controls
Each [theme.name] section sets colors for all components:
| Key | Applies To |
|---|---|
normfgcolor / normbgcolor / normbordercolor | Unfocused bar and windows |
selfgcolor / selbgcolor / selbordercolor | Focused window and active tag |
term_bg / term_fg / term_cursor | Terminal background, text, cursor |
term_color0–term_color15 | Full 16-color terminal palette |
ghostty_theme | Ghostty built-in theme name |
rofi_theme | Rofi .rasi theme (filename without extension) |
polybar_bg / polybar_fg / polybar_accent / polybar_urgent | Polybar colors |
dark_mode | GTK dark preference (true / false) |
Creating a Custom Theme
Add a new section to themes.toml:
[theme.mytheme]
normfgcolor = "#cdd6f4"
normbgcolor = "#1e1e2e"
normbordercolor = "#313244"
selfgcolor = "#cdd6f4"
selbgcolor = "#89b4fa"
selbordercolor = "#89b4fa"
term_bg = "#1e1e2e"
term_fg = "#cdd6f4"
term_cursor = "#f5e0dc"
# ... term_color0–15 ...
ghostty_theme = "Catppuccin Mocha"
rofi_theme = "sidetab-catppuccin"
polybar_bg = "#1e1e2e"
polybar_fg = "#cdd6f4"
polybar_bg_alt = "#313244"
polybar_fg_alt = "#a6adc8"
polybar_accent = "#89b4fa"
polybar_urgent = "#f38ba8"
dark_mode = true
Then set theme = "mytheme" under [active] and save.
Applying Themes via Control Center
Open the Control Center with Super + F1, navigate to Appearance → Select Theme, and pick from the list. The theme switches immediately.
Rofi Themes
Rofi theme files live in config/rofi/themes/. The active theme’s rofi_theme key selects which .rasi file is used.
Available rofi themes: nord, onedark, catppuccin, dracula, gruvbox, everforest, monochrome, rosepine, solarized, tokyonight.
Wallpapers
Place images in ~/Pictures/backgrounds/. Use Super + Shift + W to randomize, or set a specific one:
feh --bg-fill ~/Pictures/backgrounds/mywall.jpg
Control Center
The Control Center is a rofi-based menu providing system health, quick actions, appearance settings, and more.
Open: Super + F1 — or run dwm-controlcenter from a terminal.
Navigate with arrow keys or type to filter. Press Esc or ← to go back.
Modules
System Health
Runs a full dependency check and reports:
- Build tools (
cc,make) and required libraries - Xorg / Xlibre installation
- Runtime programs: rofi, picom, dunst, feh, flameshot, polybar
- Terminal emulators (ghostty, alacritty, kitty, st)
- Fonts: MesloLGS Nerd, Noto Color Emoji
- Running services: picom, dunst, polybar, NetworkManager
- Config paths:
.xinitrc, polybar dir, rofi dir, wallpaper folder
Selecting a failed item offers to run install.sh (auto-fix) or check-deps.sh (details).
Quick Actions
| Action | Description |
|---|---|
| Restart Picom | Kill and relaunch the compositor |
| Restart Dunst | Kill and relaunch the notification daemon |
| Restart Polybar | Relaunch using ~/.config/polybar/launch.sh |
| Reload Wallpaper | Randomize from ~/Pictures/backgrounds/ |
| Toggle Compositor | Start or stop picom |
| Restart NetworkManager | sudo systemctl restart NetworkManager |
| Run Dependency Check | Opens check-deps.sh in a terminal |
| Install Missing Deps | Runs install.sh in a terminal |
Appearance
| Action | Description |
|---|---|
| Select Theme | Pick from all themes defined in themes.toml |
| Randomize Wallpaper | Random image from ~/Pictures/backgrounds/ |
| Open Wallpaper Folder | Open folder in file manager |
| Edit Polybar Config | Open polybar config in $EDITOR |
| GTK Theme Settings | Launch nwg-look for GTK theming |
Keybind Viewer
Displays all bindings from hotkeys.toml in a searchable rofi list. Same as pressing Super + /.
Running from Terminal
dwm-controlcenter
The script auto-detects your terminal emulator (ghostty → alacritty → kitty → st → xterm) and uses the active rofi theme from ~/.config/rofi/themes/controlcenter.rasi.
Patches & Features
dwm-titus is a heavily patched build. Below is every addition on top of stock dwm.
Window Management Patches
Pertag
Each tag independently remembers its layout, master count, and master/stack sizing. Switching tags restores the previous layout for that tag.
Cfact
Assign per-window size weights within the stack area. Windows are no longer forced to equal height.
| Keys | Action |
|---|---|
Super + Shift + H | Grow this window’s slot |
Super + Shift + L | Shrink this window’s slot |
Super + Shift + O | Reset to equal sizing |
Movestack
Reorder windows within the stack without using the mouse.
| Keys | Action |
|---|---|
Super + Shift + J | Move window down |
Super + Shift + K | Move window up |
Window Swallowing
When a GUI application is launched from a terminal, it replaces the terminal in the layout. Closing the app brings the terminal back.
Controlled via window rules in config.h:
{ "ghostty", NULL, NULL, 0, 0, 1, 0, -1 }, /* isterminal = 1 */
Fullscreen (3-State)
Three fullscreen modes available:
| Mode | Keys | Description |
|---|---|---|
| True fullscreen | Super + M | Hides bar, takes full screen |
| Fake fullscreen | Super + Shift + Y | Looks fullscreen, bar still usable |
| Monocle layout | — | Single window view, bar visible |
Bar & EWMH
Polybar Integration
The built-in dwm bar is replaced by Polybar. dwm-titus feeds tag and window data to Polybar via EWMH atoms, keeping it fully informed.
Multi-monitor support: each monitor gets its own Polybar instance. The primary monitor hosts the system tray and EWMH tag reporting.
EWMH Compliance
Implements _NET_WM_STATE, _NET_CURRENT_DESKTOP, _NET_NUMBER_OF_DESKTOPS, and related atoms so external tools and taskbars work correctly.
Window Icons
Title bar icons via _NET_WM_ICON. Applications that set this atom display their icon in the bar.
Systray
A built-in system tray is compiled in. It is disabled by default when Polybar is running (to avoid duplication), but can be re-enabled in config.h.
Visual
Noborder
When only one window is visible on a tag, its border is automatically removed for a cleaner look. Borders return when a second window appears.
Cursor Warp
When focus moves to a different window or monitor (via keyboard), the mouse cursor warps to the center of the newly focused window.
Live Configuration
TOML Hotkeys (hotkeys.toml)
Keybindings are parsed from config/hotkeys.toml at runtime. Edit and save — bindings update without recompiling or restarting dwm.
TOML Themes (themes.toml)
Colors for dwm, terminal, rofi, and polybar are all sourced from config/themes.toml. Save the file to apply a new theme instantly across all apps.
Scripts & Utilities
| Script | Description |
|---|---|
dwm-controlcenter | Rofi-based control center (Super+F1) |
dwm-keybinds | Searchable keybind viewer (Super+/) |
dwm-screenshot | Wrapper for flameshot (full, gui, clip modes) |
theme-apply.sh | Applies active theme from themes.toml to all apps |
webapp-create | Creates a web app shortcut |
webapp-launch | Launches a URL as a standalone web app window |
autostart.sh | Runs programs on dwm start |
check-deps.sh | Checks all required dependencies |
active-audio | Displays active audio device in Polybar |
disable-powersaving | Disables DPMS and screen blanking |
Multi-Monitor
Xinerama support with per-monitor Polybar bars. Tags are independent per monitor. Windows can be moved between monitors with Super + Shift + ,/..
Troubleshooting
Run the dependency checker first — it covers most common issues:
bash scripts/check-deps.sh
Or use the Control Center → System Health.
dwm Won’t Start
Black screen / returns immediately to login:
- Verify Xorg:
pacman -Q xorg-server xorg-xinit - Check
.xinitrcexists and ends withexec dwm - Run
startxfrom a TTY to see error output in the terminal
dwm: cannot open display:
- You must launch dwm from a TTY, not an existing X session
- If using a display manager, ensure
dwm.desktopis in/usr/share/xsessions/
No Status Bar / Polybar Missing
- Install polybar:
sudo pacman -S polybar - Verify launch script:
ls ~/.config/polybar/launch.sh - Run manually:
~/.config/polybar/launch.sh - Check fonts:
fc-list | grep -i meslo
Missing icons in Polybar:
cp -r config/polybar/fonts/* ~/.local/share/fonts/
fc-cache -fv
Terminal Won’t Open (Super+X)
- Install a terminal:
sudo pacman -S ghostty - Or change the terminal in
config/hotkeys.toml:[vars] terminal = "alacritty"
Themes Not Applying
- Confirm
themes.tomlis at~/.config/dwm-titus/themes.toml - Check the
[active]section has a valid theme name - Manually trigger:
kill -USR1 $(pidof dwm) - Run
theme-apply.shdirectly to see any errors
Keybinds Not Working
- Check
config/hotkeys.tomlfor syntax errors — invalid TOML silently fails - Verify the key name is correct (use
xevto find X11 key names) - If a bind still doesn’t work, add it as a fallback in
config.hand recompile
Multi-Monitor Issues
- Tags not syncing across monitors: run
debug/debug_ewmh.sh - Polybar only on one monitor: check
~/.config/polybar/launch.shusesxrandrto detect monitors - Cursor doesn’t follow focus: verify cursor warp is enabled in
config.h(cursorwarp = 1)
NVIDIA / Suspend Issues
- Black screen on wake: run
scripts/nvidia-suspend-test.shto diagnose - DPMS/screensaver issues: run
scripts/disable-powersavingor add it to autostart
Picom / Compositor Artifacts
Restart picom via the Control Center (Quick Actions → Restart Picom) or:
pkill picom; picom -b
If artifacts persist, try disabling experimental backends in ~/.config/picom.conf.
Still Stuck?
- Open an issue: github.com/ChrisTitusTech/dwm-titus/issues
- Run the full check:
bash scripts/check-deps.sh