niri
A scrollable-tiling Wayland compositor.
Status
A lot of the essential functionality is implemented, plus some goodies on top. Feel free to give niri a try. Have your waybars and fuzzels ready: niri is not a complete desktop environment.
niri.mp4
Idea
Niri implements scrollable tiling, heavily inspired by PaperWM. Windows are arranged in columns on an infinite strip going to the right. Every column takes up a full monitor worth of height, divided among its windows.
With multiple monitors, every monitor has its own separate window strip. Windows can never "overflow" onto an adjacent monitor.
This is one of the reasons that prompted me to try writing my own compositor. PaperWM is a solid implementation, but, being a GNOME Shell extension, it has to work around Shell's global window coordinate space to prevent windows from overflowing.
Niri also has dynamic workspaces which work similar to GNOME Shell. Since windows go left-to-right horizontally, workspaces are arranged vertically. Every monitor has an independent set of workspaces, and there's always one empty workspace present all the way down.
Niri tries to preserve the workspace arrangement as much as possible upon disconnecting and connecting monitors. When a monitor disconnects, its workspaces will move to another monitor, but upon reconnection they will move back to the original monitor.
Building
For Fedora users, there's a COPR with built and packaged niri: https://copr.fedorainfracloud.org/coprs/yalter/niri/
First, install the dependencies for your distribution.
-
Ubuntu:
sudo apt-get install -y software-properties-common sudo add-apt-repository -y ppa:pipewire-debian/pipewire-upstream sudo apt-get update -y sudo apt-get install -y libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libpipewire-0.3-dev
-
Fedora:
sudo dnf install gcc libudev-devel libgbm-devel libxkbcommon-devel wayland-devel libinput-devel dbus-devel systemd-devel libseat-devel pipewire-devel clang
Next, build niri with cargo build --release
.
Installation
The recommended way to install and run niri is as a standalone desktop session. To do that, put files into the correct directories according to this table.
File | Destination |
---|---|
target/release/niri |
/usr/bin/ |
resources/niri-session |
/usr/bin/ |
resources/niri.desktop |
/usr/share/wayland-sessions/ |
resources/niri-portals.conf |
/usr/share/xdg-desktop-portal/ |
resources/niri.service |
/usr/lib/systemd/user/ |
resources/niri-shutdown.target |
/usr/lib/systemd/user/ |
Doing this will make niri appear in GDM and, presumably, other display managers.
Running
cargo run --release
Inside an existing desktop session, it will run in a window. On a TTY, it will run natively.
To exit when running on a TTY, press SuperShiftE.
Session
If you followed the recommended installation steps above, niri should appear in your display manager. Starting it from there will run niri as a desktop session.
The niri session will autostart apps through the systemd xdg-autostart target.
You can also autostart systemd services like mako by symlinking them into $HOME/.config/systemd/user/niri.service.wants/
.
A step-by-step process for this is explained on the wiki.
Niri also works with some parts of xdg-desktop-portal-gnome. In particular, it supports file choosers and monitor screencasting (e.g. to OBS).
Default Hotkeys
When running on a TTY, the Mod key is Super. When running in a window, the Mod key is Alt.
The general system is: if a hotkey switches somewhere, then adding Ctrl will move the focused window or column there.
Hotkey | Description |
---|---|
ModT | Spawn alacritty (terminal) |
ModD | Spawn fuzzel (application launcher) |
ModAltL | Spawn swaylock (screen locker) |
ModQ | Close the focused window |
ModH or Mod← | Focus the column to the left |
ModL or Mod→ | Focus the column to the right |
ModJ or Mod↓ | Focus the window below in a column |
ModK or Mod↑ | Focus the window above in a column |
ModCtrlH or ModCtrl← | Move the focused column to the left |
ModCtrlL or ModCtrl→ | Move the focused column to the right |
ModCtrlJ or ModCtrl↓ | Move the focused window below in a column |
ModCtrlK or ModCtrl↑ | Move the focused window above in a column |
ModShiftHJKL or ModShift←↓↑→ | Focus the monitor to the side |
ModCtrlShiftHJKL or ModCtrlShift←↓↑→ | Move the focused window to the monitor to the side |
ModU or ModPageDown | Switch to the workspace below |
ModI or ModPageUp | Switch to the workspace above |
ModCtrlU or ModCtrlPageDown | Move the focused window to the workspace below |
ModCtrlI or ModCtrlPageUp | Move the focused window to the workspace above |
Mod1–9 | Switch to a workspace by index |
ModCtrl1–9 | Move the focused window to a workspace by index |
ModShiftU or ModShiftPageDown | Move the focused workspace down |
ModShiftI or ModShiftPageUp | Move the focused workspace up |
Mod, | Consume the window to the right into the focused column |
Mod. | Expel the focused window into its own column |
ModR | Toggle between preset column widths |
ModF | Maximize column |
ModC | Center column within view |
Mod- | Decrease column width by 10% |
Mod= | Increase column width by 10% |
ModShift- | Decrease window height by 10% |
ModShift= | Increase window height by 10% |
ModShiftF | Toggle full-screen on the focused window |
PrtSc | Take an area screenshot. Select the area to screenshot with mouse, then press Space to save the screenshot, or Escape to cancel |
AltPrtSc | Take a screenshot of the focused window to clipboard and to ~/Pictures/Screenshots/ |
CtrlPrtSc | Take a screenshot of the focused monitor to clipboard and to ~/Pictures/Screenshots/ |
ModCtrlShiftT | Toggle debug tinting of rendered elements |
ModShiftE | Exit niri |
Configuration
Niri will load configuration from $XDG_CONFIG_HOME/.config/niri/config.kdl
or ~/.config/niri/config.kdl
.
If this fails, it will load the default configuration file.
Please use the default configuration file as the starting point for your custom configuration.
Niri will live-reload many of the configuration settings, like key binds or gaps, as you change the config file. Though, some settings are still missing live-reload support. Notably, output modes and positions will only apply when the output is reconnected.