github YaLTeR/niri v0.1.8

latest releases: v0.1.10, v0.1.9
3 months ago

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.

Today is a special day. Niri is one year old! 🥳

┌ (main) ~/s/r/niri
└─ git show --format='commit %H%nCommitDate: %cd%n%n    %s' --no-patch ad3c3f8
commit ad3c3f8cefd38d2bf26b466d8e34eccde3bca443
CommitDate: Thu Aug 10 14:49:38 2023 +0400

    Init from smallvil

We've come a long way since then! I am very happy with how niri is shaping up. I am especially grateful to 45 (!) contributors who have volunteered their time to improve something in the compositor over the year.

We also managed to amass more than 3000 stars, and almost 400 people in our comfy Matrix room!

Nevertheless, there's plenty to be done. Without further ado, here are the improvements from the last release.

Note

Packagers: niri now requires pango >= 1.44 and rust >= 1.77.

Gradient border color spaces

A big thanks to @CaliOn2 for overhauling gradient rendering in niri, adding support for interpolation color spaces! You can now set gradient borders to draw not just in srgb, but also in srgb-linear, oklab and oklch, the latter with support for {shorter,longer,increasing,decreasing} hue.

Which means that you can now have beautiful rainbow gradient borders:

layout {
    border {
        active-gradient from="red" to="orange" angle=45 in="oklch longer hue"
    }
}

As usual, niri gradients are rendered the same way as CSS linear-gradient(), so you can use any browser tool to configure them.

Additionally, @my4ng debugged and fixed gradients rendering with a sharp edge on NVIDIA, and I fixed gradient rendering being reversed at angle=90.

Screenshot UI pointer toggle

You can now toggle mouse pointer visibility in the screenshot UI by pressing P. I added a new help panel to remind you of this, and to explain how to capture the screenshot.

niri-screenshot-ui-panel.mp4

Also, the screenshot UI now fades in. (As usual, you can disable this animation if you don't like it.) Finally, I fixed some minor regressions with area selection that were introduced in the fractional scaling refactor.

Key repeat for binds

Thanks to @salman-farooq-sh, niri now has key repeat for all binds. This is especially useful for binds that control volume and brightness. Or for having some fun by spawning a ton of windows.

niri-key-repeat.mp4

You can disable key repeat for specific binds using the new repeat=false property:

binds {
    // Disable key repeat for this bind.
    Mod+T repeat=false { spawn "alacritty"; }
}

Focus-follows-mouse improvements

Being a scrollable-tiling compositor, niri faces some unique design challenges for otherwise commonplace functionality. One particularly annoying example was unwanted view movement caused by focus-follows-mouse.

When using niri, you will frequently have windows partially off-screen. With focus-follows-mouse, moving the cursor over such a window would focus it and scroll it into view. This is especially problematic if you have two monitors side-by-side, and just want to move the mouse to the other monitor.

To figure out the solution, I outlined all problems and possible solutions in a GitHub discussion. Some very productive brainstorming followed, and a solution emerged: a view scroll threshold for focus-follows-mouse.

In the config, you can now set a property on focus-follows-mouse:

input {
    focus-follows-mouse max-scroll-amount="0%"
}

This number controls how much scrolling is allowed to happen for focus-follows-mouse to trigger. With 0% (the new suggested default), focus-follows-mouse will only focus a window if it does not cause any scrolling. You can also set this to bigger values, e.g. 10% will restrict it to when the view scrolls no more than 10% of the screen width.

niri-focus-follows-mouse-threshold.mp4

I've personally been avoiding focus-follows-mouse in niri in the past precisely because of the undesired scrolling, but max-scroll-amount="0%" had pretty much solved that problem, so since then I've been using it just fine.

This release has another fix to focus-follows-mouse: when using the always-centered mode, it will no longer cause rapid window scrolling. The issue was the way the logic interacted with pointer focus update suppression during animations.

wlr-output-management

@gmorer implemented the wlr-output-management protocol, which means that you can now use third-party tools like kanshi or wdisplays to configure the outputs in niri.

Checking display settings in wdisplays

Keep in mind that changes applied this way are transient and are not automatically saved into your niri configuration, just like the niri msg output command.

wlr-screencopy version 3

Niri had supported wlr-screencopy version 1 since v0.1.3. This was enough for screenshot tools like grim, but not for screen recording tools. This was an intentional choice, as the screen recording parts of this protocol are quite complex, and need a very different implementation from the existing PipeWire screencasting.

For this release, @my4ng dived in and implemented it! Now, niri supports wlr-screencopy version 3 and you can use tools like wf-recorder and wl-mirror.

niri-wf-recorder.mp4

As a bonus, I found and fixed a bug in region capture with a fractional scale.

Negative struts

@salman-farooq-sh implemented a small change to allow strut config values to go negative. It's not obvious at first why this is needed (why would you want windows to peek outside the screen bounds?), but actually, this is an elegant solution for having smaller outer gaps than inner gaps.

In niri, one of the design principles is that opening a new window never causes existing windows to resize. Turns out, this restriction prevents differentiating horizontal inner and outer gaps. Imagine inner gaps = 10 and outer gaps = 0. A single 50%-wide window should then take exactly 50% of the screen. But then, opening a second window introduces an inner gap, so now the first window must occupy (50% minus a half gap), requiring a resize!

Negative struts work around this problem. All gap values remain equal, but you can use left and right strut values equal to negative gap size to "push" the "outer" gaps off-screen. Visually, this looks the same as having no outer gaps, while not causing any unintended window resizes.

Inner gaps without outer gaps in niri

layout {
    gaps 16

    struts {
        left -16
        right -16
        top -16
        bottom -16
    }
}

PipeWire screencast fixes

I implemented the full DMA-BUF modifier negotiation procedure for PipeWire screencasts (when using xdg-desktop-portal-gnome). As an immediate benefit, it makes screencasting work on NVIDIA. It should also fix GStreamer-based screen recording tools like Kooha, however, I have not been able to get this to work just yet. Perhaps it'll start working with the next PipeWire release? We'll see.

Wiki configuration snippet tests

This is not directly related to running niri, but is very cool nonetheless! @Suyashtnt implemented a test that verifies that every single config example on the wiki successfully parses. Combined with the fact that every single config option has an example code block, we should be very much set to catch any unintentional config parsing regressions.

Nightly COPR

With some help from @my4ng, I set up a COPR with automatic git niri builds: https://copr.fedorainfracloud.org/coprs/yalter/niri-git

Turns out, this is quite easy, and involves adding a special template .spec file into the repository, and setting up a webhook so GitHub can tell COPR to trigger a build when the main branch is updated.

If you run Fedora, you can use this new COPR to stay more up-to-date with niri development.

Other improvements in this release

  • Implemented on-demand keyboard focus mode for layer-shell surfaces, which is used by some newer bar applications.
  • Added focus-window-or-monitor-{up,down} actions (thanks @TheAngusMcFire).
  • Added move-column-left-or-to-monitor-left and move-column-right-or-to-monitor-right actions (thanks @brainlessbitch).
  • Added a middle-emulation flag to touchpad, mouse, and trackpoint settings.
  • Added a background-color option to outputs that sets the color of the default niri solid background. You can use this if you don't want to run any third-party background tools. Thanks @anant-357!
  • Added Mod3/ISO_Level5_Shift modifier support to key bindings (thanks @jpeeler).
  • Enabled sub-pixel glyph positioning for better kerning in niri panels.
  • Added a profile-with-tracy-ondemand build feature that produces a build with on-demand Tracy profiler integration, which you can run as your main compositor and only attach the profiler when needed.
  • VRR state (whether VRR is on or off for an output) is now correctly restored upon TTY switch into niri.
  • Fixed view scroll animation sometimes restarting on switching focus when the target view position does not change.
  • Fixed a rare crash that could happen when reconnecting monitors with a KVM switch.
  • Removed the enable-color-transformations-capability debug config flag. Keep in mind that changes to debug options are not considered breaking changes.
  • Powered-off monitors no longer turn on upon connecting a new monitor. This is a workaround for some monitors that reconnect themselves upon powering off, which made it impossible to power them off. Thanks @it-a-me!
  • @olistrik added optional JSON schema generation to the niri-ipc crate using schemars.
  • Updated Smithay:
    • Fixed Chromium getting stuck after attempting to drag-and-drop text in a tab.
    • Fixed fullscreen Xwayland windows freezing the screen on some NVIDIA setups.
    • Fixed lock screen surface viewporter support (used for fractional scaling).
    • Fixed primary plane selection on some devices where the same primary plane can be used on different CRTCs.
    • Fixed cursor plane selection on some drivers that have multiple cursor planes per CRTC.

Don't miss a new niri release

NewReleases is sending notifications on new releases.