Skip to content

Releases: YaLTeR/niri

v0.1.5

20 Apr 13:55
Compare
Choose a tag to compare

Niri is a scrollable-tiling Wayland compositor. Windows are arranged in columns on an infinite strip going to the right. Opening a new window never causes existing windows to resize.

This time I decided to update the demo video in the README. Here's the new video if you're curious:

demo.mp4

Now let's go over the improvements from the last release.

More animations

A big focus in this release was on animations. I've animated many more actions: window movement, resizing, and closing. Each of these was challenging to implement in its own way, but I'm quite happy with the end result.

niri-new-anims.mp4

Naturally, all animations work well with windows blocked out from screencasts.

As usual, you can disable or configure individual animations if you prefer. Find instructions on the wiki page.

While working on these animations, I fixed a few minor issues with view positioning. So niri now works better even with animations disabled.

Spring animation improvements

Spring animations are now more robust: values and durations are clamped more aggressively where it makes sense. For example, a bouncy window opening animation will become fully opaque upon reaching the full window size, and won't become transparent again during the following bounces.

niri-open-anim-clamp.mp4

Also, when using slowdown, the touchpad gesture velocity is now scaled by the slowdown factor, making the animation smoother.

Variable refresh rate

Niri now has basic variable refresh rate (VRR) support. You can enable it by setting a variable-refresh-rate flag in the output config. Check the wiki for an example and caveats.

Additionally, niri msg outputs now shows whether VRR is supported and enabled.

IPC improvements

niri msg received a few quality-of-life improvements thanks to @sodiboo:

  • Added niri msg version that shows the running niri compositor version and the niri CLI version. They are the same binary, so their versions should match, but they can briefly go out of sync after a niri update.
  • When niri msg receives an error from the compositor, it will now check if the compositor and the CLI versions match, and if not, print a message reminding you that you may need to restart niri.
  • Added niri msg request-error that will always result in an error from the compositor. This can aid in script development to check that your error handling works right.

Other improvements in this release

  • Added an allow-when-locked=true flag for spawn key bindings that makes them work when the session is locked. Check the wiki for an example.
  • Previous view position is now restored upon unfullscreening a window.
  • The SIGPIPE handler is now set to default in niri msg to prevent panic backtraces from showing up when stdout is closed.
  • The mouse cursor is now hidden upon touchscreen interaction.
  • Corrected some DRM leasing behavior to fix crashes when DRM leasing is unavailable and better handle hotplugging.
  • Added an ease-out-quad easing curve.
  • Fixed warp-mouse-to-focus not triggering when a window is closed by unmapping its buffer.
  • Fixed the horizontal touchpad gesture redrawing continuously rather than only on touchpad events.
  • Fixed overdamped spring instability being able to crash the compositor.
  • Added a microphone mute example bind to the default config.

v0.1.4

30 Mar 11:09
Compare
Choose a tag to compare

Before we begin: downgrade xz to v5.4. Done? Good, let's get to the release.

Niri is a scrollable-tiling Wayland compositor. Windows are arranged in columns on an infinite strip going to the right. Opening a new window never causes existing windows to resize.

Here are the improvements from the last release.

Block out windows from screencasts

You can now instruct niri to block out certain windows from screencasts with a window rule. This can be useful for apps like password managers or messengers that you don't want to accidentally show during meetings or streams.

Screenshot showing a visible Secrets window and an OBS window screencasting the screen where there's a black rectangle instead of the Secrets window.

The compositor (niri in this case) is the perfect place for this functionality since it is solely responsible for the video frames sent to displays and screencast clients like OBS. Plus, the compositor has the entire window tree, and can selectively block out individual windows while retaining correct layered compositing.

This blocking out also seamlessly works with the built-in screenshot UI. You can capture a screenshot with interactive area selection while seeing all windows normally, and on a screencast, this entire process, including the interactive selection UI, will have the windows correctly blocked out.

block-out-from.mp4

Unfortunately, this kind of tight integration is not possible with third-party screenshot annotation/preview tools. To avoid accidentally showing windows even when using third-party screenshot tools, niri provides a more aggressive mode that blocks out the window from all screen capture tools, not just xdg-desktop-portal screencasts.

Dynamic window rules

Window rules, introduced in the last release, let you adjust behavior for individual windows. For this release, I did the necessary refactors to support dynamic window rules that apply continuously to open windows.

The main example of course is the rule to block out windows from screencasts (described above), but you can also override whether borders draw with a solid background, change the window size limits and adjust window opacity.

As an example, you can replicate the "inactive windows become semitransparent" effect:

window-rule {
    match is-active=false
    opacity 0.9
}

Screenshot showing three apps, the middle one focused, and the ones on the side are semitransparent.

Check out the window rules wiki page for a complete list of properties that you can set.

By the way, I also added a little niri msg focused-window IPC command that shows you the title and app ID of the focused window, to aid in writing rule matchers.

Warp mouse to focus & focus follows mouse

Two popular features among tiling WMs, now in niri.

Warp mouse to focus, implemented by @FluxTape (thanks!), will automatically move the mouse into windows as you focus them. Focus follows mouse on the other hand will automatically focus windows under the cursor as you move it around.

These two actually work very well together, give it a try!

niri-warp-mouse-focus-follows.mp4

Mouse and touchpad scroll bindings

It is now possible to bind mouse wheel and touchpad scrolls to perform actions or spawn commands. Mouse scrolling activates every wheel "tick", whereas touchpad scrolling emulates scroll "ticks" based on finger distance traveled.

Additionally, you can now set a cooldown for binds to avoid triggering them too often with scrolling.

binds {
    Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
    Mod+WheelScrollUp   cooldown-ms=150 { focus-workspace-up; }

    Mod+TouchpadScrollDown { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02+"; }
    Mod+TouchpadScrollUp   { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02-"; }
}

Check the wiki page for more details.

wlr-gamma-control

Niri now implements the wlr-gamma-control protocol that is required for "Night Light" tools like wlsunset and gammastep. Thanks @phuhl for working on this!

Note

As it turns out, setting the gamma is pretty slow, at least on my system. I suggest using wlsunset because it only sets the gamma when it needs to change, rather than, say, every few seconds unconditionally.

xdg-desktop-portal-gnome 46.0

I implemented more of the Mutter D-Bus interface to support xdg-desktop-portal-gnome 46.0 with its new screencast monitor selector with visual positions:

Screenshot of the new monitor selector in xdg-desktop-portal-gnome 46.0.

Documentation

As you've noticed, I've been linking the wiki pages a lot. The reason for this is that over the past week I went through the entire config and wrote detailed documentation and examples for every single option.

Check out all this documentation here on the wiki: https://github.com/YaLTeR/niri/wiki/Configuration:-Overview

A major benefit of this is that it allowed me to declutter the default config by removing some of the less important things and instead linking the wiki. This will improve the experience for people trying out niri as they no longer need to sift through the entire window rule and animation examples.

If you find a mistake, feel free to open a pull request against the wiki/ folder of the repository.

Also, shoutouts to great reference-style docs @sodiboo had been writing for the nix flake: https://github.com/sodiboo/niri-flake/blob/main/docs.md#programsnirisettings

Other improvements in this release

  • When opening and closing a window without switching focus in between (think various dialogs and temporary windows), niri focuses the previous window since that's where you came from. Now, when this happens, niri will also restore the view position, which makes the behavior more natural and less annoying.
  • Fixed wp-viewporter bugs in Smithay (thanks @cmeissl). Particularly, this prevented Chromium and Electron applications from accepting mouse input after resizing.
  • Added more information to niri msg outputs (logical output position, size, scale, transform, and current and preferred mode flags).
  • Added a click-method input setting for touchpads (thanks @uetcis).
  • Added a workspace-auto-back-and-forth setting that causes switching to the same workspace by index twice to switch back to the previous workspace (thanks @FluxTape).
  • Added support for ISO_Level3_Shift / Mod5 modifier (thanks @Trundle).
  • Added a once-per-second fallback timer that sends frame callbacks to off-screen windows, which fixes issues with vsynced games in gamescope.
  • The last folder in the screenshot path is now automatically created if it doesn't exist.
  • Corrected pointer location reported to lock screen surfaces.
  • Fixed niri crashing when a screencast is attempted after failing to initialize PipeWire.
    • If on your system PipeWire is not started automatically, you need to make sure that it is started before niri for niri to have screencast support.
  • Fixed a crash that could happen when stopping the same screencast session twice with the right timing.
  • Relaxed checks for DRM render nodes, which in theory allows niri to run on more devices with split DRM display/render nodes (various ARM boards like Raspberry Pi).
  • Made the EGL wl-display extension optional on the TTY which makes niri work on some NVIDIA GPUs where it didn't before.
  • Niri now tries to reduce the max bits-per-channel output property to 8 which may result in more monitor configurations working.
  • Fixed building on musl.
  • Fixed mouse scrolling inside nested niri window sometimes being too slow.
  • Fixed hardcoding us as the keyboard layout when it is missing from the config (turns out libxkbcommon handles that one for us).

v0.1.3

09 Mar 11:12
Compare
Choose a tag to compare

Niri is a scrollable-tiling Wayland compositor. Windows are arranged in columns on an infinite strip going to the right. Opening a new window never causes existing windows to resize.

Here are the improvements from the last release.

Note

Packagers: if you're not using systemd and the niri-session script, you may need to change your niri startup command to niri --session. Please read below on the changes for environments without systemd.

Also, please consider including the wp-viewporter revert: 40cec34 to fix a mouse input bug with Chromium and Electron apps.

Touchpad gestures

I grew annoyed enough with the lack of a horizontal touchpad gesture in niri, so I spent several days working on the gestures. I tried three different horizontal gesture behaviors, and the one I landed on does a fairly good job of moving the windows where you intended.

I also made many overall improvements to both the vertical and the horizontal gestures to make them feel very good. They are now inertial, meaning that a short flick is enough to take you to the next workspace, as the gesture will account for the speed of your fingers. Vertical gesture has rubberbanding at the edges, indicating that you can't go any further. Finally, both gestures use spring animations when releasing fingers, which feel natural as they also take the finger speed into account. If you swipe with enough force, you'll even get a small bounce at the edge!

touchpad-gestures.mp4

Thanks goes to the maintainers of libadwaita since that's where I copied lots of the code and numeric values from.

Spring animations

As part of the gesture work, niri now supports spring animations. These are physics-based animations that are especially well suited for gestures, but feel good on their own too. Based on the spring configuration, they can optionally give small bounces and oscillations.

I made three of the four default animations to use springs. If you had custom animation settings in your config, comment them out to give springs a try! Also, check the default config for a more detailed explanation and examples on how to set up spring animations.

config-error-bounce.mp4

Touch support

@cmeissl added basic touchscreen support to niri. Thanks!

Dramatic reenactment (this laptop doesn't have a touchscreen).

Gradient borders

Focus ring and borders can now use a linear gradient instead of a solid color!

image

This is how you can set it up:

layout {
    border {
        active-gradient from="#f38ba8" to="#f9e2af" angle=45 relative-to="workspace-view"
        inactive-gradient from="#585b70" to="#7f849c" angle=45 relative-to="workspace-view"
    }
}

Colors can use several CSS-like notations, and the gradient itself is rendered like CSS linear-gradient(angle, from, to). You can use some CSS gradient generator, like this one, to get a gradient you like, then copy the values into the niri config.

Also, gradients can be relative to windows individually (the default), or to the whole view of the workspace. It's easier to explain visually:

Default relative-to="workspace-view"
image image

By the way, regular colors can also now be written with CSS-like notations. The old four-number way is now deprecated.

// catppuccin-mocha Sapphire
active-color "#74c7ec"
// catppuccin-mocha Surface2
inactive-color "#585b70"

wlr-screencopy

While niri supports xdg-desktop-portal screencasting and has a built-in screenshot UI, these are not very well suited for taking programmatic screenshots (and the current screenshot portal API isn't very good either). So, in this release, niri implements wlr-screencopy version 1 (not 3). Now you can take screenshots with grim.

Screen recording tools based on wlr-screencopy will need version 3, so they won't work for now. (The screencast portal is better for this anyway; for example, it leaves frame pacing entirely to the compositor, where it belongs.) Version 1 should be sufficient for any screenshot tool; if a screenshot tool complains that it needs version 3 then it likely needs a simple patch to avoid requesting version 3 if unavailable.

Like other security-sensitive protocols, wlr-screencopy is not available to sandboxed clients with a security context (such as Flatpaks).


Finally, all three of my outputs on a single screenshot.

Thanks to @sodiboo for implementing wlr-screencopy support!

Frame timing fixes

I fixed several issues in the presentation time handling and frame callback tracking logic.

  • Frame callbacks were sometimes sent ~1 frame later than they should've been, meaning that clients had much less time to render.
  • With specific timing it was possible for frame callbacks to stop getting sent to certain surfaces, causing a window to stop redrawing until something else updates the screen.
  • Zero presentation time from DRM (which can happen on some drivers) sometimes resulted in a panic.

Stricter config validation

Due to the ease of use in knuffel, the KDL parsing library we use in niri, some nodes technically accepted multiple children, despite only expecting one. Specifically, default-column-width {} and binds. Also, you could write multiple binds to the same key combination, which is similarly not supported.

This has been fixed to cause a config validation error. While technically a config-breaking change, it's more of a bug fix, since before all these extra nodes that you could write were ignored. Therefore I considered it fine to include in a minor niri version bump.

Thanks @sodiboo for implementing this validation!

Refactored window creation flow

I reworked the window creation flow and tracking of unmapped windows in niri to make it more robust and less "all over the place". As part of this:

  • With borders enabled, default-column-width {} (unset, the app picks its own) caused the app to shrink a bit right after it appeared. This wasn't really noticeable, but it resulted in a smaller window size than what the app wanted. It is now fixed.
  • Corrected default-column-width { fixed N; } similarly not taking borders into account, resulting in a smaller window than the specified N.
  • Added support for apps requesting a specific fullscreen monitor before they first appear (mpv --fs-screen=N will now work).
  • Added open-maximized true window rule.
  • Added open-fullscreen true/false window rule. Setting it to true will fullscreen the window upon opening, and setting it to false will deny the window from fullscreening upon opening.
    • Some windows can request fullscreen after they are initially configured, but before they are first shown on screen. In this case open-fullscreen false will not work, because these window rules apply at the initial configure. So far I only saw mpv --fs do this, so it's not a big problem (you can just remove the mpv flag).

Systemd scopes

When niri runs applications it will now put them into transient systemd scopes. One concrete benefit is that when an application uses too much RAM and systemd-oomd kills it, niri won't go down alongside the app, so the rest of your session will stay intact.

Many other tools (like Flatpak, tmux, or systemd itself) already do this for the commands they spawn, so niri joins this established practice.

β”Œ ~
└─ systemctl --user status
● sparklingbrook
    State: running
    Units: 444 loaded (incl. loaded aliases)
     Jobs: 0 queued
   Failed: 0 units
    Since: Mon 2024-03-04 10:25:20 +04; 4 days ago
  systemd: 254.9-1.fc39
   CGroup: /user.slice/user-1000.slice/user@1000.service
           β”œβ”€app.slice
           β”‚ β”œβ”€app-niri-alacritty-1672431.scope
           β”‚ β”‚ β”œβ”€1672431 alacritty
           β”‚ β”‚ β”œβ”€1672446 /usr/bin/fish
           β”‚ β”‚ └─1672578 systemctl --user status --no-pager
           β”‚ β”œβ”€app-niri-fuzzel-1672466.scope
           β”‚ β”‚ └─1672468 /var/home/yalter/stuff/blender-4.0.2-linux-x64/blender
<...>
           β”œβ”€session.slice
           β”‚ β”œβ”€niri.service
           β”‚ β”‚ └─1663138 /usr/bin/niri --session
<...>

Also, since the niri.service scope now only contains niri itself, I have moved it into session.slice, a slice for important services such as the compositor.

Running without systemd

I've made it easier to run niri in environments without systemd.

  • Added a new, enabled by default, feature systemd which gates calls to the systemd D-Bus API. Currently, this includes starting transient scopes and systemctl import-environment.
  • Niri now sets XDG_CURRENT_DESKTOP and XDG_SESSION_TYPE in the main binary, rather than in the niri-session script.
  • Added a niri --session flag for running niri as the main session instance, which means that it will import environment variables globally into systemd and D-Bus, and start D-Bus services. This flag replaces auto-detection based on the presence of the NOTIFY_SOCKET...
Read more

v0.1.2

17 Feb 05:33
Compare
Choose a tag to compare

Thanks everyone for 1000 stars! πŸ₯³

Niri is a scrollable-tiling Wayland compositor. Windows are arranged in columns on an infinite strip going to the right. Opening a new window never causes existing windows to resize.

Here are the improvements from the last release.

Note

Packagers: niri now requires libinput >= 1.21.

The new niri-visual-tests subcrate is development-only and should not be packaged. If you do cargo test --workspace, make sure to exclude it: cargo test --workspace --exclude niri-visual-tests, as it brings extra native dependencies.

Window opening animations

Windows now appear with an animation! Existing windows to the right move away, and the new window fades in, avoiding sudden visual jumps. All happening quickly enough to hopefully not be distracting.

niri-open-anims-release.mp4

More animations are coming, but they need time and work to implement right.

Animation settings

If you prefer reduced motion, or on the contrary if you want more animation, you can now set this up in a new animations config section. There's a flag to turn off, and a setting to adjust speed for all animations at once, as well as settings for every individual animation should you need it.

These settings replace the now-removed animation-slowdown debug flag.

Idle protocols

Niri now implements the ext-idle-notify and idle-inhibit pair of Wayland protocols. This allows tools like swayidle to work, and clients like mpv to pause them from working while you're watching videos.

As a bonus, I also implemented the org.freedesktop.ScreenSaver D-Bus interface for idle inhibiting, used by xdg-desktop-portal-gtk. This was necessary to make Flatpak Firefox correctly inhibit the idle state, and in general covers more applications.

Invoke actions via IPC

As the first expansion to the niri msg command, you can now invoke any bindable action with niri msg action do-something. That is, if you can bind something like Mod+F { maximize-column; }, then you can also call it programmatically with niri msg action maximize-column.

Turns out, one thing IPC actions are pretty convenient for is scripting video demos, like the one above!

Also, niri now has a way to report errors back to the IPC client, instead of leaving it in the dark for requests that don't otherwise need a response.

Window rules (the beginnings thereof)

You can now set some (at the moment, two) settings on a per-window basis. You can match or exclude windows from a rule with regular expressions on app-id and window title, similarly to other compositors. See the default config for a detailed explanation.

The settings you can currently set are default-column-width and open-on-output. Most notably, this lets you work around WezTerm's initial configure bug:

window-rule {
    // This regexp is intentionally made as specific as possible.
    // You can get away with app-id="wezterm" if you want.
    match app-id=r#"^org\.wezfurlong\.wezterm$"#

    default-column-width {}
}

More rules, including dynamically updating ones, are coming, after some refactors.

Better focus stealing prevention

To minimize your distraction, niri prevents new windows from taking focus while you're in a fullscreen application (I've had enough games ruined by a sudden Steam chat message). In this release, niri will additionally track when a newly opened window is a dialog from a particular existing window, and put that dialog to the immediate right from its parent window. The dialog will get focus only if the parent window was focused.

This change both prevents some random client from a different monitor/workspace from taking focus with a sudden dialog (looking at you, syncthing-gtk), and lets dialogs originating from fullscreen windows take focus as expected, bypassing the normal fullscreen focus stealing prevention.

Improved filtering in the hotkey overlay

The hotkey overlay shows a hardcoded set of binds that I deemed "most important". Included are the spawn actions, because binds like "spawn terminal" and "spawn application launcher" are definitely up there in the importance list.

However, not all commands you might want to spawn are that important, and with a lot of binds, the list could get polluted with many entries like XF86AudioRaiseVolume. Filtering based on program name doesn't sound very robust, so, instead, now the hotkey overlay will only show spawn binds with Mod or Super in the hotkey.

Additionally, out of multiple spawn binds to the same command, only the first one will show up in the hotkey overlay, which is consistent with all other hotkeys.

Before After
Hotkey overlay before the change. Hotkey overlay after the change.

Other improvements

  • Fixed a crash with some monitors with weird EDID data, and fixed inability to light up some monitors by filtering out interlaced modes.
  • Implemented DRM leasing. This lets you use VR applications and headsets with niri. Thanks @Supreeeme for working on this!
  • Added consume-or-expel-window-{left,right} actions that either expel the focused window into its own column, or consume a singular focused window into a column. These act as an alternative to the existing consume and expel commands, and are not bound to any keys by default. Thanks @exoticorn for implementing them!
  • Added a dwtp flag to touchpad settings for disable-when-trackpointing.
  • Added trackpoint input settings. Thanks @okvik for implementing them!
  • Added a way to bind / IPC-invoke quit while skipping the "Are you sure you want to exit niri?" dialog: Mod+Shift+E { quit skip-confirmation=true; }.
  • You can no longer spawn multiple lockscreen clients at once (more relevant now with swayidle).
  • Fixed binds like Super+Q not working (you had to spell it out as Mod+Super+Q).
  • Changed the default swaylock bind from Mod+Alt+L to Super+Alt+L to fix a collision with the Mod+L bind when running niri as a window (not sure how I missed this in testing). You don't usually want to "lock the screen" of a nested niri anyway.
  • Monitors powered off with DPMS will now light up upon switching the TTY back to niri.
  • The NIRI_SOCKET environment variable is now exported into the systemd and D-Bus session, which lets systemd units run niri msg. For example, this allows you to run swayidle as a systemd service.
  • Fixed a Smithay bug which mistakenly sent primary-selection to wlr-data-control v1 clients, causing them to crash (thanks @kchibisov).
  • Fixed border using focus ring's default values instead of its own.
  • Fixed omitting the layout config section resulting in gaps 0 instead of the default gaps 16.
  • Fixed target monitor not getting focus when pressing move-column-to-monitor-* on an empty source monitor.

v0.1.1

03 Feb 10:12
Compare
Choose a tag to compare

Better fresh install workflow

Niri will now create a config file if it's not present, filling it with the default config contents. It will notify about this with a new message.

  • Before, on a fresh install:

    Config parse error.

  • After, on a fresh install:

    Notification about a config being created.

wlr-foreign-toplevel-management

I've implemented the wlr-foreign-toplevel-management protocol used by taskbars like the wlr/taskbar Waybar module or sfwbar, and by some other clients like fcitx5.

Niri with two taskbars showing several open windows.

Output rotation

You can now rotate and flip outputs with a new setting:

output "eDP-1" {
    // The rotations are counter-clockwise:
    transform "90"
}

Thanks @axtloss for implementing this and to @cmeissl for fixing various Smithay issues that had come up with transforms!

Other improvements in this release

  • Keyboard LEDs (Num Lock, Caps Lock, Scroll Lock) will now light up. Thanks @cmeissl!
  • Added move-workspace-to-monitor-{left,right,up,down} actions that move the entire workspace to a different monitor. They are not bound to any key by default (yet?). Thanks @Trundle for implementing this!
  • Fixed semitransparent border and focus ring colors.
  • Fixed natural-scroll not being respected for the touchpad workspace switch gesture.
  • Fixed windows being unable to open in fullscreen mode right away.
  • Monitor screencasts will now stop on monitor size changes. In the future it may be possible to resize the stream on the go but we don't do that yet, so just stop them to avoid wrong video frames.
  • Fixed building on Rust 1.72.0.
  • Made backend initialization errors more detailed.
  • Fixed a panic when closing niri running as a nested window during a screen redraw.

v0.1.0

27 Jan 10:42
Compare
Choose a tag to compare

Here it is. The first real release, after five months of work. Let's do a recap for the occasion.

This is niri, a scrollable-tiling Wayland compositor inspired by PaperWM. Windows are tiled on an infinite horizontal strip that scrolls left and right. They don't "overflow" onto adjacent monitors. Opening a new window never resizes existing ones.

Niri showing some windows.

Despite this being the first release with plenty of things left to do, niri already packs a good number of features.

  • All the basics. It's a Wayland compositor, it shows windows, runs on a TTY, works with multiple monitors and mixed-GPU systems, supports HiDPI.

  • Dynamic workspaces like in GNOME, but per-monitor. Workspaces also remember which monitor they were on across monitor disconnects and reconnects.

  • Some of the important desktop component protocols like wlr-layer-shell and ext-session-lock.

  • A built-in screenshot UI. Press PrtSc, select a rectangle on a frozen screen, and press Space to copy the image to the clipboard and save to a file. Or screenshot one window with AltPrtSc.

    Niri with the screenshot UI open.

  • Screencasting support through xdg-desktop-portal-gnome. Works with OBS, browsers, and others.

    Niri screencasting to OBS, Firefox, Chromium.

  • Fully live-reloading config.

  • Configurable layout: things like gaps, borders, struts, window sizes.

    Niri showing large struts and gaps.

If you want to see niri in action, here's a video demo from the README.

niri.mp4

It's also worth mentioning that:

  • NVIDIA GPU systems might have rendering issues.
  • Xwayland in rootless mode is not supported. However, you can use its excellent rootful mode with niri. Games and X11 apps work just fine for the most part.

If you'd like to give niri a try, check the README for building and running instructions. There are also a few community-maintained packages:

Finally, we have a Matrix room. Feel free to drop by with a message.

Changes since v0.1.0-beta.1

  • Fixed config live-reload on NixOS configurations which change the config file symlink but leave the mtime constant (thanks @sodiboo).
  • Fixed most cases of niri failing to light up monitors after a TTY switch (thanks @cmeissl).
  • Fixed xdg-desktop-portal-gnome not updating the screencast monitor list upon monitor disconnection / reconnection (niri wasn't notifying it about changes).
  • Fixed large windows with large CSD shadows getting cut on screenshots and screencasts.
  • Fixed output config changes being ignored if done when on a different TTY.
  • Fixed popups not showing up when an IME is active (for now as a workaround by disabling popup grabs when an IME is active).
  • Slightly improved cursor rendering performance by avoiding CPU->GPU->CPU transfers (thanks @cmeissl).
  • Slightly increased the precision of the default column widths in the default config. This should get one pixel back for the β…“ column width on most monitors.
  • xdg-desktop-portal screencasts will now receive the optional logical monitor size which some apps require.
  • xdg-desktop-portal screenshots will now get an error instead of a broken screenshot for multi-monitor configurations (it needs to be implemented, see #117). This does not affect the screenshot UI.
  • Fixed screenshot UI not showing up if the cursor ended up outside all monitors.

v0.1.0-beta.1

20 Jan 06:08
Compare
Choose a tag to compare

I've made a ton of improvements since the last alpha tag. I am now happy enough with the feature set to make the first proper release. So, this is a beta tag, and 0.1.0 should follow several days later.

Note

Packagers: niri now depends on pangocairo.

IPC, output list

I've implemented the beginnings of IPC, and a new niri msg outputs subcommand that will list all connected monitors and their available modes. Finally, you no longer need to dig in niri's debug output to find this information.

β”Œ ~
└─ niri msg outputs
Output "eDP-1" (Unknown - Unknown - eDP-1)
  Current mode: 2560x1600 @ 165.004 Hz
  Physical size: 340x210 mm
  Available modes:
    2560x1600@165.004
    2560x1600@60.002
    2560x1600@120.028
    2560x1600@96.030
    2560x1600@72.005
    2560x1600@60.001
    1920x1200@165.004
    1920x1080@165.004
    1600x1200@165.004
    1680x1050@165.004
    1280x1024@165.004
    1440x900@165.004
    1280x800@165.004
    1280x720@165.004
    1024x768@165.004
    800x600@165.004
    640x480@165.004

Output settings improvements

All output settings (scale, position, mode, on/off) are now live-reloaded without having to replug the monitors.

Additionally, monitors are now always repositioned from scratch on every change, with preference given to monitors with explicitly-configured positions. Practically this means that your monitor positions will be consistent regardless of the order they are connected in (especially relevant at startup where the order is random).

More libinput settings, live-reload

  • Added touchpad accel-profile, dwt, tap-button-map settings.
  • Added mouse natural-scroll, accel-speed, accel-profile settings.
  • Added live-reload for all libinput settings.

This should cover most of the important libinput settings. These are relatively straightforward to add, so feel free to open a PR if you need some libinput setting that is still missing.

Hotkey help overlay

I've added Pango for text rendering, which unlocks a ton of useful features. One of them is the new Important Hotkeys list that shows up at startup and helps you learn your way around niri.

Important hotkeys overlay.

The list of actions to show is hardcoded, but the actual hotkeys come from the current config, so you will see the keys that you had configured. The bind to display this overlay is show-hotkey-overlay.

More overlays

I've added two more overlays using text rendering. One shows up when there's an error in your config:

Config error overlay.

And the second one prompts for a confirmation when pressing the exit bind:

Exit confirmation dialog.

Wayland popup grabs

Niri now correctly implements popup grabs. Practically, this means that:

  • You can now dismiss popups by clicking anywhere on screen, including layer-shell popups like the ones from sfwbar.
  • You can now navigate the layer-shell popups with the keyboard.
  • Popups with grabs will be dismissed when focusing a different window (or in the case of layer-shell, a different monitor), and unfocused windows will be denied popup grabs.

Client-side decoration fixes

By default (without the prefer-no-csd setting), niri wants clients to use client-side decorations. Turns out that SDL2 has a bug (already fixed but not released) in its xdg-decoration protocol implementation that prevents windows from showing up when the compositor insists on CSD.

To make all apps work properly, niri will now hide the xdg-decoration protocol from the clients when it wants client-side decorations, and only show it when prefer-no-csd is set.

DOSBox-X with CSD.

Improved security

Niri now implements the security-context Wayland protocol which lets it hide a number of sensitive protocols from sandboxed clients. This protocol is used by Flatpak, so now Flatpak apps can no longer steal your clipboard through wlr-data-control, as an example.

β”Œ ~
└─ wl-copy 'My secret clipboard contents!'
β”Œ ~
└─ flatpak run --command=bash --filesystem=home org.gnome.Adwaita1.Demo
[πŸ“¦ org.gnome.Adwaita1.Demo ~]$ wl-paste
Error: A required Wayland protocol (zwlr_data_control_manager_v1 version 1) is not supported by the compositor
[πŸ“¦ org.gnome.Adwaita1.Demo ~]$
exit
β”Œ ~ 1
└─ wl-paste
My secret clipboard contents!

More improvements in this release

  • Added move-column-to-workspace* and move-column-to-monitor* binds that operate on columns, as opposed to the existing move-window-to-* binds. I believe this behavior makes more sense, so I changed the default binds to the new column ones.
  • Added a center-focused-column layout setting that can be set to never (the default), always (always center the focused column) and on-overflow, which will center the focused column when it doesn't fit together with the previously focused column. Thanks @tversteeg for working on this feature.
  • Layer-shell surfaces are now properly notified of output removal, which for example fixes mako breaking when disconnecting a monitor that it was displaying a notification on.
  • Fixed mouse clicks on layer-shell surfaces activating the windows below them.
  • Fixed screencast session restore picking the wrong monitor. This is especially relevant in Chromium where session restore is part of the normal screencast workflow.
  • Fixed screencast taking a while to startup if there are no new frames rendered by the compositor.
  • Laptop displays will now show up as "Built-in display" in the xdp-gnome monitor selection dialog.
  • Fixed niri not redrawing the screen upon changing focus. Usually this isn't a problem because windows redraw in response to changing focus, but it became more visible with popup grabs.
  • Niri will now watch the config file path even if the config did not exist, or failed to parse at startup. This is especially relevant for new niri users which don't have a config yet. You can create a config after running niri for the first time, and it will now live-load it without having to restart.
  • Added a niri panic subcommand that triggers a panic, which you can use to check that you have built / packaged niri with enough debuginfo to produce useful crash backtraces.
  • Documented the debug settings in the default config file.
  • Fixed windows receiving events that look like they left all outputs when consuming them into a column.
  • Fixed windows receiving events that look like they left all outputs when replugging monitors.
  • Fixed a crash that could happen when a window is closed during a workspace switch transition.
  • Fixed a crash that could happen if workspaces are transferred back to their original monitor that was connected during a workspace switch transition.
  • Updated Smithay, the Wayland compositor building library that underlies niri, which brought some fixes:
    • The cursor plane will now work in more cases. If you needed the disable-cursor-plane setting, you might no longer need it.
    • Fixes to graphical glitches on nouveau and possibly other configurations.
    • Fixes to a deadlock when using an IME with certain clients.

Caution

This is an beta tag. There may be breaking changes leading to the release.

Please check the README for building and installation instructions. Also, if you're on Fedora, I've got a COPR. NixOS users, check out https://github.com/sodiboo/niri-flake.

v0.1.0-alpha.3

07 Jan 14:19
Compare
Choose a tag to compare

Config breaking change

Settings for focus-ring, preset-column-widths, default-column-width, gaps, struts moved into a new layout { } node.

layout {
    focus-ring { /* ... */ }
    preset-column-widths { /* ... */ }
    default-column-width { /* ... */ }
    gaps 8
    struts { /* ... */ }
}

Multi-GPU support

Monitors plugged into secondary GPUs will now light up and work. This is particularly important for hybrid laptops with an integrated and a discrete GPU, where for example a monitor may "plug into" the dGPU while the primary device is the iGPU.

Additionally, direct scan-out will now work in more cases across GPUs (i.e. a dGPU client on an iGPU monitor).

image

Niri uses the default GPU for rendering, the same as any other GL client. You can force niri to use a different GPU with a new debug setting which works similarly to the WLR_RENDER_DRM_DEVICE environment variable from wlroots:

debug {
    render-drm-device "/dev/dri/renderD129"
}

Borders

You can now add borders to windows with a new setting:

layout {
    border {
        // The settings are the same as for the focus ring.
        // If you enable the border, you probably want to disable the focus ring.
        // off
        width 4
        active-color 255 200 127 255
        inactive-color 80 80 80 255
    }
}

In contrast to the focus ring, borders are always visible, even on unfocused windows.

image

Fullscreen backdrop

Fullscreen windows smaller than the monitor now have a monitor-sized black backdrop, as expected by xdg-shell. This makes all fullscreen windows consistent in how they look, while keeping the PaperWM-like property that they mostly behave like a regular column that you can scroll out of view if you want.

image

More improvements in this release

  • Added a focus-column-{first,last} actions that focus the leftmost/rightmost column on the workspace, bound to ModHome/End by default.
  • Added a move-column-to-{first,last} actions that move the focused column to the leftmost/rightmost position on the workspace, bound to ModCtrlHome/End by default.
  • Added an input { disable-power-key-handling } config flag to prevent niri from taking over the power button handling (which makes it sleep instead of power off). You can use this flag if you configure the power button elsewhere, i.e. in logind.conf.
  • Windows on unfocused monitors now always display as unfocused.
  • When prefer-no-csd is unset (the default), niri is now more insistent on client-side decorations. This makes the alacritty 0.13 use CSD in this case for example.
  • Added a debug { disable-cursor-plane } config flag if you're having cursor rendering issues.
  • Enabled EGL support for clients in the winit backend (when running niri as a nested window). On Fedora with recent Mesa this makes it so you can run GL clients inside nested niri again.
  • The toggle-debug-tint action, bound to ModCtrlShiftT by default, will now redraw the screen immediately.

Caution

This is an alpha tag. There are known bugs and missing features. Don't be surprised if there's a breaking config change in the future.

Please check the README for building and installation instructions. Also, if you're on Fedora, I've got a COPR. NixOS users, check out https://github.com/sodiboo/niri-flake.

v0.1.0-alpha.2

23 Dec 07:10
Compare
Choose a tag to compare

Several important additions have landed since alpha.1.

Implemented the relative-pointer and pointer-constraints protocols

These protocols allow apps to lock or confine the mouse pointer within their window. In particular, Xwayland makes use of these protocols to make 3D games with mouse look "just work"!

mouse-look.mp4

Other examples include Blender and virtual machines.

blender-warp.mp4

Implemented popup unconstraining

Popups will no longer open partially off-screen. Niri will also try to position popups within the application's window horizontally so that if a window is fully on-screen, the popup will also be fully visible.

Fractal screenshot with open emoji popup

Added a struts option

This one allows you to add a kind of "outer gaps" if you like those layouts. Also, left and right struts will make windows to the sides always partially visible, which can help with mouse-only navigation.

Screenshot from 2023-12-23 10-21-20

More improvements in this release

  • New windows can no longer steal focus from a fullscreen window. All it took was a Syncthing dialog interrupting my Hollow Knight boss battle.
  • Tablets will now match their target monitor's aspect ratio (works the same way as in GNOME Shell).
  • Tablets can no longer move the cursor outside of their target monitor's bounds.
  • Tablets will no longer send wl_pointer events (as they shouldn't), which makes them work correctly with GTK 4 apps.
  • Added a niri validate subcommand that will check if your config parses successfully.
  • Added a way to disable an output with an off config flag.
  • Added focus-window-or-workspace-up/down and move-window-up-or-to-workspace-up/down bind commands that do a workspace switch when the focus is at the end of a window column (not bound to anything by default). This way you can avoid an extra set of workspace switch binds. Thanks @rabidpug for adding this.
  • Keyboard config is now live-reloaded, including the XKB options.
  • Fixed screen not immediately redrawing in some cases, most notably when a layer-shell surface shows a popup.
  • Allegedly, high-resolution scroll wheel mice should now work after a Smithay update, but I don't have one so I don't know for sure.

This is an alpha tag. There are known bugs and missing features. Don't be surprised if there's a breaking config change in the future.

Please check the README for building and installation instructions. Also, if you're on Fedora, I've got a COPR.

v0.1.0-alpha.1

26 Nov 16:28
Compare
Choose a tag to compare

A good chunk of functionality is implemented. I've been daily driving niri for at least two months now. I feel like it's a good point to make the first tag.

Make no mistake, this is an alpha tag. There are known bugs and missing features. Don't be surprised if there's a breaking config change in the future. But, depending on your needs and preferences, it may already be good enough for daily use.

Please check the README for building and installation instructions. Also, if you're on Fedora, I've got a COPR.

For people following along, I recommend sticking to the main branch rather than freezing on this release.

niri.mp4