A scrollable-tiling Wayland compositor. https://matrix.to/#/#niri:matrix.org
Find a file
Bernardo Kuri 5ea9092a49
Add per-axis scroll speed config for input devices (#2109)
* Add per-axis scroll speed config for input devices.

Accepts negative values to inverse scroll direction.

Properly complements/overrides global `scroll-direction` setting.

Includes docs and tests.

* Update per-axis scroll factor implementation after testing

- Refined configuration structure in niri-config
- Updated input handling to use per-axis scroll factors
- Added comprehensive test snapshots
- Updated documentation with per-axis examples

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Simplify per-axis scroll factor implementation per review feedback

- Make documentation concise and clear
- Remove unnecessary comments and test helper functions
- Use inline snapshots for tests
- Rename get_factors() to h_v_factors() for clarity
- Remove unnecessary .clone() calls (ScrollFactor is Copy)
- Reduce test count to essential cases only
- Fix comment about window factor override behavior

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove unnecessary ScrollFactor::new() helper function

The maintainer prefers minimal code, so removing this helper and
constructing ScrollFactor directly in tests.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix scroll factor behavior - all settings now multiply with window factor

Per maintainer feedback, both combined and per-axis scroll settings
should multiply with the window-specific scroll factor, not override it.
This ensures consistent behavior regardless of configuration method.

Also removed the now-unused has_per_axis_override() method.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Final cleanup: remove redundant comments and unused snapshot files

- Removed unused snapshot files (now using inline snapshots)
- Removed redundant inline comments in tests
- Simplified test descriptions to be more concise

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Convert scroll factor parsing tests to use assert_debug_snapshot

Updates parse_scroll_factor_combined, parse_scroll_factor_split, and
parse_scroll_factor_partial tests to use assert_debug_snapshot instead
of manual assert_eq comparisons, as requested in PR review.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Convert to inline snapshots as requested

- Convert all scroll factor parsing tests to use inline snapshots instead of external files
- Remove external snapshot files to keep test directory clean
- All tests still pass with inline snapshot assertions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix missed assert_eq in parse_scroll_factor_mixed test

Converts the remaining assert_eq calls to assert_debug_snapshot
with inline snapshots in the mixed syntax test function.
Also fixes raw string delimiters from ### to #.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Convert scroll_factor_h_v_factors test to use assert_debug_snapshot

Makes all scroll factor tests consistent by using snapshots instead
of assert_eq for better maintainability.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fixes

---------

Co-authored-by: Bernardo Kuri <github@bkuri.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-19 05:51:32 +00:00
.github ci: Add some blank lines 2025-08-17 18:10:41 +03:00
docs Add per-axis scroll speed config for input devices (#2109) 2025-08-19 05:51:32 +00:00
niri-config Add per-axis scroll speed config for input devices (#2109) 2025-08-19 05:51:32 +00:00
niri-ipc Add ConfigLoaded event to IPC, option to disable built-in notification (#1829) 2025-08-17 09:28:24 +03:00
niri-visual-tests layout: Remove by-ref animation_snapshot() getter 2025-08-14 15:58:59 +03:00
resources Update all remaining links to the new wiki 2025-08-18 20:09:30 +03:00
src Add per-axis scroll speed config for input devices (#2109) 2025-08-19 05:51:32 +00:00
.gitattributes Stop including broken LFS files in source tarball 2025-05-17 04:29:46 -07:00
.gitignore Add Nix Flake (#77) 2024-01-10 22:43:46 -08:00
Cargo.lock Update dependencies 2025-08-11 09:12:42 +03:00
Cargo.toml Update dependencies 2025-08-11 09:12:42 +03:00
clippy.toml Deal with Clippy warnings 2024-07-28 11:41:09 +03:00
CONTRIBUTING.md Update all remaining links to the new wiki 2025-08-18 20:09:30 +03:00
flake.lock nix: update flake inputs 2025-07-15 15:55:45 +03:00
flake.nix flake: skip tests that require a valid EGL display (#2244) 2025-08-16 06:08:58 +00:00
LICENSE Add LICENSE 2023-08-10 14:50:51 +04:00
niri.spec.rpkg rpkg: Fix wiki path 2025-08-17 18:09:33 +03:00
README.md readme: use links to docs instead of gh wiki 2025-08-17 22:35:47 +03:00
rustfmt.toml Add rustfmt.toml and reformat 2023-08-10 14:49:38 +04:00
typos.toml Fix typos (#429) 2024-06-09 10:50:22 +00:00

niri

A scrollable-tiling Wayland compositor.

Matrix GitHub License GitHub Release

Getting Started | Configuration | Setup Showcase

niri with a few windows open

About

Windows are arranged in columns on an infinite strip going to the right. Opening a new window never causes existing windows to resize.

Every monitor has its own separate window strip. Windows can never "overflow" onto an adjacent monitor.

Workspaces are dynamic and arranged vertically. Every monitor has an independent set of workspaces, and there's always one empty workspace present all the way down.

The workspace arrangement is preserved across disconnecting and connecting monitors where it makes sense. When a monitor disconnects, its workspaces will move to another monitor, but upon reconnection they will move back to the original monitor.

Features

Video Demo

bce834b0-f205-434e-a027-b373495f9729

Also check out this video from Brodie Robertson that showcases a lot of the niri functionality: Niri Is My New Favorite Wayland Compositor

Status

Niri is stable for day-to-day use and does most things expected of a Wayland compositor. Many people are daily-driving niri, and are happy to help in our Matrix channel.

Give it a try! Follow the instructions on the Getting Started page. Have your waybars and fuzzels ready: niri is not a complete desktop environment.

Here are some points you may have questions about:

  • Multi-monitor: yes, a core part of the design from the very start. Mixed DPI works.
  • Fractional scaling: yes, plus all niri UI stays pixel-perfect.
  • NVIDIA: seems to work fine.
  • Floating windows: yes, starting from niri 25.01.
  • Input devices: niri supports tablets, touchpads, and touchscreens. You can map the tablet to a specific monitor, or use OpenTabletDriver. We have touchpad gestures, but no touchscreen gestures yet.
  • Wlr protocols: yes, we have most of the important ones like layer-shell, gamma-control, screencopy. You can check on wayland.app at the bottom of each protocol's page.
  • Performance: while I run niri on beefy machines, I try to stay conscious of performance. I've seen someone use it fine on an Eee PC 900 from 2008, of all things.
  • Xwayland: no built-in support, but xwayland-satellite is easy to set up and works very well.
    • Steam and games, including Proton: work perfectly through xwayland-satellite.
    • JetBrains IDEs, Ghidra: work well through xwayland-satellite.
    • Discord and other Electron apps: work well through xwayland-satellite.
    • Chromium and VSCode: work perfectly natively on Wayland with the right flags.
    • X11 apps that want to position windows or bars at specific screen coordinates: won't work well; you can run them in a nested compositor like labwc or rootful Xwayland.
    • Display scaling (integer or fractional) keeps X11 apps crisp, but you need the latest xwayland-satellite. For games, you can run them in gamescope at native resolution, even with display scaling.

Media

niri: Making a Wayland compositor in Rust · December 2024

My talk from the 2024 Moscow RustCon about niri, and how I do randomized property testing and profiling, and measure input latency. The talk is in Russian, but I prepared full English subtitles that you can find in YouTube's subtitle language selector.

An interview with Ivan, the developer behind Niri · June 2025

An interview by a German tech podcast Das Triumvirat (in English). We talk about niri development and history, and my experience building and maintaining niri.

A tour of the niri scrolling-tiling Wayland compositor · July 2025

An LWN article with a nice overview and introduction to niri.

Contributing

If you'd like to help with niri, there are plenty of both coding- and non-coding-related ways to do so. See CONTRIBUTING.md for an overview.

Inspiration

Niri is heavily inspired by PaperWM which implements scrollable tiling on top of GNOME Shell.

One of the reasons that prompted me to try writing my own compositor is being able to properly separate the monitors. Being a GNOME Shell extension, PaperWM has to work against Shell's global window coordinate space to prevent windows from overflowing.

Tile Scrollably Elsewhere

Here are some other projects which implement a similar workflow:

Contact

Our main communication channel is a Matrix chat, feel free to join and ask a question: https://matrix.to/#/#niri:matrix.org

We also have a community Discord server: https://discord.gg/vT8Sfjy7sx