After a few years of constantly hearing about how cool Niri is, today I finally caved and decided to give it a try (aaah, the miracles of peer pressure).

I was initially hesitant because in my experience tiling window managers (ackshually on Wayland they are compositors, but you get the gist) have a tendency to be useful for very narrow use cases, while the giant hype around them (cough hyperland cough) tends to just focus on flashy animations. Not that I mind aesthetics, but I'd also like to use my computer for pursuing somewhat productive activities.

The last time I played with a tiling window manager was a couple of years ago (see Setting up Sway on a new machine). I was generally pleased with how easy and nice it was to configure Sway, but in reality I didn't end up daily driving it on my Arch machine, KDE took that throne in the end. The thing is: while the idea of tiling managers is pretty neat, the practical usability tends to suffer the moment you exit from a world where the only thing I do on this computer is write code all day. Doing any kind of creative work with many floating windows tends to negate the benefits of automatically tiling windows.

Which is why on my first day trying out Niri I was positevely surprised..

Premise

I will not be covering how to install Niri since it's already well covered on their wiki: https://github.com/niri-wm/niri/wiki/Getting-Started#quick-start.

Note that this article is not for the faint of heart. It's targeted at the tinkerers and makers, at the people that seek a more intimate connection with the machine. If you want something a little bit more reassuring, I'd recommend to stay away from Niri. Maybe have a read at A handbook for a sweet life on Linux instead, where I cover how to get a cozy comforting Desktop experience via Gnome and KDE!

Note: skip to the end of the article if you want to see a few screengrabs!

Nice UX by default

The first thing I really liked is that in the Getting Started guide they suggest you to install Niri together with DankMaterialShell.

DankMaterialShell (DMS for short) is an app that covers the same ground as waybar or other menu bars. It's a Wayland desktop shell built with Quickshell (which itself is built in QtQuick). It provides a really smooth out-of-the-box top-bar GUI experience for folks that want to tinker gently, preferring to start out with something already polished and usable. This means you'll immediately get a list of useful widgets, from battery level to WiFi, bluetooth, et cetera.

And don't be afraid, DMS is also heavily customizable, so you don't have to live with its default look forever. Personally, I was genuinely impressed by being able to quickly arrange the position of my displays using just DMS, second after I had installed it. Its notification widget looks clean and polished, and I found the clipboard history widget also pretty useful, especially since it's also searchable.

I guess all of this praise is less about Niri and more about DMS, and arguably (I guess) I could have reached the exact same setup with Sway. However, I probably would have never discovered DMS if it wasn't linked in the Getting Started docs of Niri, so there's that.

Let me say out loud then: congrats on the Niri project for choosing to recommend another project to help you bootstrap a working desktop setup from day 1. Sometimes developers tend to forget about UX, and if you're looking for a tiling window manager, you'll definitely need something like DMS to fill the usability void left by Niri (et friends).

Current look of the laptop screen, you can see DMS at the top. The wallpaper comes from KDE.


Configuration language

Now, let's get into Niri. Niri is configured using KDL, which I personally find very readable and easy to follow. And cute too.

For what I could see on my first day, the default config.kdl is well commented (which is good for grepping) and easy to hack on.

For example, it took me very little time to figure out that to make the Emacs windows partially transparent and with a gentle blur, I just needed to add this entry:

window-rule {
    match app-id="^emacs"
    opacity 0.9 

    background-effect {
        blur true
    }
}

Those few lines read very well, imho. It's a really nice feeling when you feel empowered by a config file instead of finding it daunting (Nix anyone?).

Essential navigation

To move between windows, you simply use the MOD key (CMD or whatever branded key your keyboard has) + the arrow keys. Because each Niri workspace is infinitely scrollable horizontally, and you can have infinite workspaces aligned vertically, you'll have 4 directions where you can focus:

Mod+Right { focus-column-right; }
Mod+Left  { focus-column-left; }
Mod+Down  { focus-window-down; }
Mod+Up    { focus-window-up; }

To move a window itself to a specific direction, you can just add the Ctrl key to the previous set of keybindings:

Mod+Ctrl+Left  { move-column-left; }
Mod+Ctrl+Down  { move-window-down; }
Mod+Ctrl+Up    { move-window-up; }
Mod+Ctrl+Right { move-column-right; }

To move a window and toggle it between being tiled horizontally and vertically, you can use Mod+[ and Mod+] :

    // The following binds move the focused window in and out of a column.
    // If the window is alone, they will consume it into the nearby column to the side.
    // If the window is already in a column, they will expel it out.
    Mod+BracketLeft  { consume-or-expel-window-left; }
    Mod+BracketRight { consume-or-expel-window-right; }

To look at all of your workspaces, use Mod+O. From the overview, you can use your arrows to move between workspaces. To toggle off the overview you can just press Mod+O again:

// Open/close the Overview: a zoomed-out view of workspaces and windows.
// You can also move the mouse into the top-left hot corner,
// or do a four-finger swipe up on a touchpad.
Mod+O repeat=false { toggle-overview; }

To close a window just use Mod+Q:

Mod+Q repeat=false { close-window; }

With these basic shortcuts under your hands, and because you can also still use the mouse to resize or move windows, you already have everything you need to start daily driving Niri!

More advanced usage

Once you're past the basics, you might feel like reaching for more.

For example: minimizing/maximizing a window. There's several ways to "make the focused window bigger".
Here's the main 3 I found:

Mod+F { maximize-column; }
Mod+Shift+F { fullscreen-window; }
Mod+M { maximize-window-to-edges; }

Of all of them, I would describe Mod+Shift+F as "Zen Mode", since everything else outside your window will disappear (top bar included). Mod+M will remove gaps between the window and the top bar, while Mod+F will just increase the width of the window to fit the current screen.

Another thing that can be useful is to resize your windows without reaching for the mouse. These are the default bindings for it:

Mod+Minus { set-column-width "-10%"; }
Mod+Equal { set-column-width "+10%"; }

I immediately added my two custom shortcuts here since with my split keyboard they felt much better under my fingers:

// Ergonomics: here I just use my right pinky up/down
Mod+P { set-column-width "+5%"; }
Mod+Semicolon { set-column-width "-5%"; }

Another handy shortcut is Mod+R, which lets you change the width of all windows currently displayed. The way it works is that you basically tell Niri which ratios to use. In my case I added a 0.8 to the defaults:

preset-column-widths {
    // Proportion sets the width as a fraction of the output width, taking gaps into account.
    // For example, you can perfectly fit four windows sized "proportion 0.25" on an output.
    // The default preset widths are 1/3, 1/2 and 2/3 of the output.
    proportion 0.33333
    proportion 0.5
    proportion 0.66667
    proportion 0.8

    // [..redacted..]
}

Then, pressing Mod+R will toggle between those ratios for your windows (4 in my case).

Finally, you might find useful some light aesthetic changes I did to remove the highlighted border on focused windows (which I felt was a bit clunky). I enabled drop shadows instead. Here's a diff showing these and a few other minor tweaks:

diff --git a/arch-linux/niri/config.kdl b/arch-linux/niri/config.kdl
index fdbfb78..6883dfc 100644
--- a/arch-linux/niri/config.kdl
+++ b/arch-linux/niri/config.kdl
@@ -111,7 +111,7 @@ input {
 // https://niri-wm.github.io/niri/Configuration:-Layout
 layout {
     // Set gaps around windows in logical pixels.
-    gaps 16
+    gaps 8
 
     // When to center a column when changing focus, options are:
     // - "never", default behavior, focusing an off-screen column will keep at the left
@@ -156,7 +156,7 @@ layout {
     // You can change how the focus ring looks.
     focus-ring {
         // Uncomment this line to disable the focus ring.
-        // off
+        off
 
         // How many logical pixels the ring extends out from the windows.
         width 4
@@ -215,7 +215,7 @@ layout {
     // You can enable drop shadows for windows.
     shadow {
         // Uncomment the next line to enable shadows.
-        // on
+        on
 
         // By default, the shadow draws only around its window, and not behind it.
         // Uncomment this setting to make the shadow draw behind its window.
@@ -231,7 +231,7 @@ layout {
         // window. These will also remove client-side shadows if the window
         // draws any.
         //
-        // draw-behind-window true
+        draw-behind-window true
 
         // You can change how shadows look. The values below are in logical
         // pixels and match the CSS box-shadow properties.

Launcher

Hot take: I like the application launcher that comes with DMS (maybe because it's similar to the one in KDE?). So instead of using the default Mod+D keybinding to run fuzzel, I tweaked to run DMS. This meant going from this:

Mod+D hotkey-overlay-title="Run an Application: fuzzel" { spawn "fuzzel"; }

..to this:

Mod+D hotkey-overlay-title="Open the DMS launcher" { spawn-sh "dms ipc call widget openWith launcherButton all"; }

I haven't yet used fuzzel at all, so my preferenced might change over time :)

Screenshots

Screengrabs are another pretty damn useful thing to have from day 1, if you can.
I was happy to note that I could add the usual "macOS-like" keyboard shortcut for quick screengrabs:

Mod+Shift+3 { screenshot-window; }
Mod+Shift+4 { screenshot; }
Mod+Shift+5 { screenshot-screen; } // This one is not really like macOS, but it's still useful!

Lock screen + Fingerprint sensor

I was also extremely pleased to notice that the lock screen used by Dank Material Shell natively supports the fingerprint sensor that ships with my Framework laptop 13". To lock the screen via DMS using a shortcut, I added this:

Mod+Shift+Semicolon hotkey-overlay-title="Lock the Screen: DMS" { spawn-sh "dms ipc call lock lock"; }

Epilogue

For now, that's all that I know! I'll see how my experience with Niri progresses with time and I'll update this post as needed.

Current look

To add some eye candy to this post, I've attached below a few screenshots of my current setup.

My main (ultrawide) desktop, showing 2 windows side-by-side


My main (ultrawide) desktop, showing 3 windows (the last one partially off-screen)


An example of a blurred semi-transparent window (Alacritty)


DMS Settings app


DMS launcher


Further reading/watching