
A StumpWM module for defining dual-monitor window layouts per group
I spent way longer than I'd like to admit getting one defcommand to do "make a group, split both monitors top/bottom, launch emacs + firefox + two terminals into the correct frames every time." The annoying part I eventually realized is that run-shell-command is async, so focus frame, launch app, focus next frame, launch next app just lands everything in whichever frame was focused last.
My fix was to register a *new-window-hook*, match each new window by a substring of its WM_CLASS, and pull-window it into the right frame as it appears. Hook removes itself when all the expected windows have shown up. Once that was working I had a ~50-line blob I didn't want to copy-paste for every project, so I pulled it out into a small module: layout-groups.
It exposes one macro, define-layout-group, which takes a command name, a group title, a layout preset, and a list of (slot class-substring launcher) tuples, and expands into a defcommand that does the group/split/hook/launch sequence for you. So a writing setup becomes one form:
(define-layout-group writing "Writing" :tri-2-head-v-r
(:left "emacs" "emacsclient -c -a emacs ~/notes")
(:right-top "firefox" "firefox --no-remote -P writing")
(:right-bottom "zathura" "zathura ~/refs/handbook.pdf"))
(define-key *root-map* (kbd "W") "writing")
Re-running the command after the group exists just switches to it instead of re-splitting.
Comes with 9 presets covering dual/tri/quad layouts across two monitors in every split direction. README has the WM_CLASS gotchas you only learn the hard way (firefox --no-remote -P is the big one; without it the second firefox invocation just opens a tab and no window event ever fires for the hook to catch).
Repo: https://github.com/licjon/stumpwm-layout-groups
Caveats: presets are hardcoded to exactly 2 heads. Module lives in the :stumpwm package directly because (:use :stumpwm) doesn't import the internals you actually need (find-group, head-frames, vsplit, etc.).