A program such as a status bar has to follow the window manager, and so far it could only ask: komorebi on Windows and on macOS sends notifications for that. The daemon now keeps subscribers, each a Unix socket in its data directory that a program listens on, and after each event and each message it handles, it connects to every subscriber and writes the event or the message with the state after it. A subscriber can ask to be sent only what changed the state; a window that is shown and a new subscription are always sent, so a subscriber has the state as soon as it subscribes. A subscriber that cannot be connected to is dropped with its socket file and not tried again, and a stopping daemon closes an empty connection to each one. komorebic gains subscribe-socket and unsubscribe-socket, and komorebi-client subscribe and subscribe_with_options, which bind the socket and subscribe. The tests subscribe through real sockets against the fake desktop: a shown window is sent with the state that has it, a subscriber that filters is not sent a question that changed nothing, and one that is gone is dropped.
komorebi for KDE
A tiling window manager for KDE Plasma on Wayland, in the family of komorebi for Windows and komorebi for Mac. The daemon decides where each window goes, and KWin, the window manager of Plasma, does the moving and the drawing.
Running it locally
nix develop
cargo run --bin komorebi --locked -- --version
cargo run --bin komorebi --locked -- --log-level debug
cargo run --bin komorebi --locked -- --fake-backend
Inside a Plasma Wayland session, komorebi loads a script into KWin, reads the
monitors and the windows that are open, tiles them, and tiles the windows again
whenever one opens, closes, takes the focus, is minimized or comes back, until
it is stopped with Ctrl-C. It needs KWin 6.8 or newer;
docs/dev/PLATFORM.md has what it expects of the
session. Outside a Plasma session it exits with an error that says what is
missing. --fake-backend runs the window manager against an in-memory desktop
with one monitor and no windows instead.
While it runs, the daemon takes messages on a Unix socket, komorebi.sock in
$XDG_RUNTIME_DIR/komorebi (the local data directory when there is no runtime
directory): a message can ask for the state of the window manager, ask which
monitor, workspace or container has the focus, retile every monitor, or stop
the daemon. komorebi-client writes them, and komorebic,
the command line, is how a person sends them. komorebic start runs the
komorebi on the PATH, and passes it what follows a --. In a Plasma
session:
cargo build --locked
export PATH="$PWD/target/debug:$PATH"
komorebic start
komorebic state
komorebic stop
komorebic start -- --fake-backend tries the daemon and komorebic without a
compositor, against the in-memory desktop.
nix develop provides the Rust toolchain that rust-toolchain.toml
selects, a nightly rustfmt, and the tools just check and the flake's checks
use. With direnv, the .envrc does it on
cd. On Linux, nix run .#komorebi -- --version builds and runs the daemon
without a checkout of the toolchain.
Crates
komorebi: the daemon, and the library behind it. The library has the vocabulary the window manager is written in (core), theBackendtrait through which it reaches a compositor and the in-memory desktop the tests use (backend), the backend that reaches KWin through a script it runs (kwin), the model of what it tiles (monitor,workspace,container,window), the window manager that keeps the model (window_manager), loads it from the backend (desktop) and changes it when the compositor reports an event (window_manager_event,window_manager_event_listener,process_event), theRingthat holds monitors, workspaces and containers, and the lists in which some elements are locked in place. It answers the messages on the daemon's socket (core::SocketMessage,process_command), shows its state (state), and sends its subscribers a notification of each event and message it handles (notify_subscribers).komorebi-client: a library that sends messages to the daemon, reads its answers, subscribes to its notifications, and re-exports the types they are made of.komorebic: the command line. A subcommand that asks something of the daemon is one message on its socket;start,log,data-directory,completionsand the hiddendocgenwork without the daemon.version: the version string every binary reports.
The layouts, which turn a work area and a number of containers into a rectangle
for each, are komorebi-layouts from komorebi,
a git dependency at the revision Cargo.toml pins.
Checks
just check runs the formatting check, clippy with warnings denied, the tests,
rustdoc with warnings denied, and the type check and tests of the bridge (no
package.json: tsc and node come from the dev shell), inside nix develop.
nix flake check runs the same checks as derivations, plus cargo deny, the
TOML and Nix formatting, and the tests under cargo nextest, on Linux and on an
Apple silicon Mac. On Linux it also boots every VM test, which needs KVM. A Mac
runs the tests against the fake desktop, since KWin only exists on Linux.
nix fmt formats every file the checks look at.
The VM tests boot NixOS with Plasma and run a real KWin. just vm NAME runs
one; docs/dev/vm-tests.md has the details, including
how to run them on a Mac.
How it fits together
The daemon decides where every window goes and asks the compositor to put it
there. Everything it needs from the compositor is behind one trait, Backend,
so the window manager logic runs against a real compositor and against an
in-memory fake desktop alike. docs/dev/ARCHITECTURE.md
describes the trait and where each of its rules is enforced.
On KDE Plasma the backend is in two parts. A script that komorebi loads into KWin, the bridge, reports what KWin sees over the session bus, and carries out the commands it is given as the answer to a call it holds open. The daemon keeps a table of the windows and monitors from those reports, answers the window manager's questions from it, and turns each report into an event for the window manager. If KWin restarts, the daemon loads the bridge into the new one.
The window manager models the desktop as monitors, each with a ring of workspaces, each with a ring of containers, each with a ring of windows. A workspace's layout gives each of its containers a tile of the monitor's work area, and every window of a container is moved onto its tile. At startup the window manager loads the monitors and the windows that are open from the backend and tiles them; after that it changes the model when the compositor reports that a window was shown, closed, focused, minimized or restored, and tiles the workspace in front again.
Everything else reaches the daemon as a message on its socket: one JSON
SocketMessage per line, handled one at a time with the window manager
locked. A message that asks a question is answered on the same connection.
A program such as a status bar can subscribe to the daemon's notifications: it listens on a socket of its own, and after each event and each message, the daemon connects to it and writes the event or the message with the state of the window manager.
Documentation
The user guide starts at docs/index.md, and
docs/cli has a page for every komorebic subcommand, which
just docgen writes from the subcommands' help.
cargo doc --workspace --no-deps --open builds the API documentation.
CONTRIBUTING.md says how to work on the code.
docs/dev/ARCHITECTURE.md describes the model,
docs/dev/DESIGN.md says why it is built that way,
docs/dev/PLATFORM.md what it needs from KDE Plasma,
and docs/dev/vm-tests.md how the VM tests work.
License
komorebi for KDE is under the Komorebi License. Contributions
are accepted under the terms in CONTRIBUTING.md.