Compare commits

...

279 Commits

Author SHA1 Message Date
Ivan Molodetskikh bf4e8cd233 wip look into Keyboard/PointerTarget
Decided not to pursue this for now. The idea was to extract input handling from
input/mod.rs into the respective modules, plus get rid of manual cursor shape
resetting, but there are some roadblocks:

- The pointer is locked when those methods are called, meaning you can't get
  the current location (have to store from enter/motion) and, more crucially,
  can't set grabs—we need this for the Overview.
- Gesture begin/end is handled at the Wayland object level, meaning
  PointerTargets get to deal with "improper" events themselves, reducing their
  utility. cosmic-comp spawns an idle callback for this which seems awkward and
  is asking for problems.
- We're not actually removing much code at all, only adding more code for the
  blanket wrappers and such.
2025-08-20 20:36:36 +03:00
Ivan Molodetskikh 34b05e8671 Rename spawn-at-startup-sh => spawn-sh-at-startup
Makes a bit more sense
2025-08-20 15:10:05 +03:00
Ivan Molodetskikh d4e1b2231b default-config: Mark orca as allow-when-locked
Consistent with GNOME. Move down so allow-when-locked explanation is above.
2025-08-20 14:48:54 +03:00
Ivan Molodetskikh e81f356908 Add spawn-sh, spawn-at-startup-sh
Our top 10 most confusing config moments
2025-08-20 14:43:50 +03:00
Ivan Molodetskikh 1013147ba3 CI: Move feature combinations off the docs critical path
Make docs deploy faster. Also don't build --release separately, it's covered by
the randomized-tests job.
2025-08-19 19:31:03 +03:00
Ivan Molodetskikh 38f388565f Update dependencies 2025-08-19 19:17:54 +03:00
Ivan Molodetskikh f9ea905987 Update Smithay and fix two unused upscale() calls
Uh oh. I can't come up with an easy way to test these, so let's just hope that
before they were broken and now they work fine?..
2025-08-19 19:08:53 +03:00
Ivan Molodetskikh 7a8355bb4d README: Link awesome-niri 2025-08-19 10:40:52 +03:00
Ivan Molodetskikh 781edba45f wiki/Getting-Started: Mention DEs and shells 2025-08-19 10:40:52 +03:00
Kent Daleng 6d62c26a0f configure section permalinks 2025-08-19 10:20:01 +03:00
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
Ivan Molodetskikh 43a2648e57 wiki/FAQ: Add spaces for search to work
"pinned" doesn't find anything otherwise
2025-08-18 20:45:38 +03:00
Ivan Molodetskikh ba129e98e3 wiki/FAQ: Mention Bitwarden 2025-08-18 20:26:07 +03:00
Ivan Molodetskikh b9b4f31b6f Update all remaining links to the new wiki 2025-08-18 20:09:30 +03:00
Ivan Molodetskikh 5f3528a2ee wiki/FAQ: Mention always on top windows 2025-08-18 20:05:27 +03:00
Ivan Molodetskikh a5777b9473 wiki/Application-Issues: Mention Zen dmabuf screencasting 2025-08-18 20:01:55 +03:00
Ivan Molodetskikh 6dc4f6a622 wiki: Improve home page 2025-08-18 09:53:42 +03:00
Ivan Molodetskikh 85d42db05d wiki/FAQ: Mention blur 2025-08-18 09:49:00 +03:00
Kent Daleng d6db202a03 wiki/docs: rename index.md to README.md 2025-08-18 09:42:27 +03:00
Ivan Molodetskikh 3a85e77518 wiki: Minor logo update 2025-08-17 23:00:38 +03:00
Kent Daleng e0bf056ba3 docs: location-agnostic index page (#2256)
* Update index.md

a simple suggestion for a location-agnostic index page

* Update docs/wiki/index.md

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-17 19:41:17 +00:00
Kent Daleng 39bdfece9a readme: use links to docs instead of gh wiki
(i'm obsessed with making pull requests right in the browser)
2025-08-17 22:35:47 +03:00
Ivan Molodetskikh 26a6e0cd98 ci: Add some blank lines 2025-08-17 18:10:41 +03:00
Ivan Molodetskikh b12a56e4e6 rpkg: Fix wiki path 2025-08-17 18:09:33 +03:00
Ivan Molodetskikh f6e1b3133e ci: Add missing perm 2025-08-17 17:19:05 +03:00
Kent Daleng dc93f1c1fd github wiki replacement / mkdocs-docs (#2147)
* Add wiki based on mkdocs

* wording fixes

* fix github bg color on narrow

* Fix left sidebar section headers being bigger than pages

* fix hover accent

* fix list rendering on fractional layout

* fix videos

* fix automatic full links

* remove redundant commented css

* improve dark mode contrast

* update pygments for better child node coloring

* update logo

* remove blank lines

* add systemd language hint

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-17 17:05:41 +03:00
Ivan Molodetskikh a6febb86aa tty: Remove warning when rendering with inactive device 2025-08-17 11:29:33 +03:00
Matej Cotman 3b76cb7b3d Add FreeBSD CI (#2072)
* feat(ci): add FreeBSD job

* Update .github/workflows/ci.yml

* fix(workflow): remove 10m timeout for freebsd job, put it back later if there is an actual reason

* feat(workflow): enable cache on freebsd job

* feat(workflow): add custom CARGO_HOME for freebsd job

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* clean-up

* test cache

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-17 11:12:47 +03:00
Horu 271534e115 Add ConfigLoaded event to IPC, option to disable built-in notification (#1829)
* feat: config reload ipc event

* cleanups

* Rename and move the new config option

* rename to ConfigLoaded and emit at connection

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-17 09:28:24 +03:00
yrkv af30cc8df6 niri-ipc: Add window positions and sizes (#1265)
* Add window sizes and positions to the IPC

* basic fixes

* report window_loc instead of window pos

* clean ups

* make scrolling indices 1-based

* add printing to niri msg windows

* don't include render offset in floating tile pos

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-16 11:42:08 +03:00
Ivan Molodetskikh a003e01307 README: Link Discord 2025-08-16 09:09:44 +03:00
Cole Helbling 38df8d4f33 flake: skip tests that require a valid EGL display (#2244)
* flake: skip tests that require a valid EGL display

Otherwise:

    niri> failures:
    niri>
    niri> ---- tests::animations::clientside_height_change_doesnt_animate stdout ----
    niri>
    niri> thread 'tests::animations::clientside_height_change_doesnt_animate' panicked at src/tests/animations.rs:87:54:
    niri> called `Result::unwrap()` on an `Err` value: error creating EGL display
    niri>
    niri> Caused by:
    niri>     Unable to obtain a valid EGL Display.
    niri> note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    niri>
    niri> ---- tests::animations::height_resize_animates_next_y stdout ----
    niri>
    niri> thread 'tests::animations::height_resize_animates_next_y' panicked at src/tests/animations.rs:87:54:
    niri> called `Result::unwrap()` on an `Err` value: error creating EGL display
    niri>
    niri> Caused by:
    niri>     Unable to obtain a valid EGL Display.
    niri>
    niri>
    niri> failures:
    niri>     tests::animations::clientside_height_change_doesnt_animate
    niri>     tests::animations::height_resize_animates_next_y
    niri>
    niri> test result: FAILED. 147 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.45s

* flake: skip all animations tests, present and future

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* fixup: typo

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-16 06:08:58 +00:00
Ivan Molodetskikh 6d0505e684 watcher: Refactor tests to not use threads
Fixes flakiness, removes unnecessary waiting.
2025-08-15 08:09:25 +03:00
Ivan Molodetskikh 8b4517a87b watcher: Mark tests as ignored
Until someone figures out how to fix the flakiness. See
https://github.com/YaLTeR/niri/issues/2226
2025-08-14 21:38:45 +03:00
Ivan Molodetskikh c7a8c44a0d niri.spec.rpkg: Add mesa-libEGL to build requirements
Needed for the client-server animation tests.

Signed-off-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-14 20:29:27 +03:00
Ivan Molodetskikh 25c1c04349 layout: Offset ongoing column X move anims for non-animated resizes 2025-08-14 15:58:59 +03:00
Ivan Molodetskikh 36af02ad34 layout/tests: Add two width resize tests with the same issue as just fixed 2025-08-14 15:58:59 +03:00
Ivan Molodetskikh a9f0f4d44f layout/scrolling: Normalize column X move anim from 1 to 0
Will be needed for offsetting to fix the resize cancel issue.
2025-08-14 15:58:59 +03:00
Ivan Molodetskikh e3101ced70 layout: Offset Y animations for non-animated resizes 2025-08-14 15:58:59 +03:00
Ivan Molodetskikh ea438b21e9 layout/tests: Add column resize animation tests 2025-08-14 15:58:59 +03:00
Ivan Molodetskikh 42bd107795 layout/tests: Add CompleteAnimations op 2025-08-14 15:58:59 +03:00
Ivan Molodetskikh a2767041d9 layout/tests: Support forced test window size 2025-08-14 15:58:59 +03:00
Ivan Molodetskikh 5bda3041d0 layout/tests: Support animation snapshot
Only the size is needed in these tests; needed for testing animation progress.
2025-08-14 15:58:59 +03:00
Ivan Molodetskikh 54076b7632 layout/tests: Extract check_ops_on_layout() 2025-08-14 15:58:59 +03:00
Ivan Molodetskikh c9873a0885 layout: Remove by-ref animation_snapshot() getter
It was used in only one place, and that place was due for an update to use the
cached data.
2025-08-14 15:58:59 +03:00
Ivan Molodetskikh 7a6be2a923 Add basic client-server resize animation tests 2025-08-14 15:58:59 +03:00
Ivan Molodetskikh bba9ca1fa2 headless: Add a renderer
To be used for animation tests that need animation snapshots.

The renderer is optional to avoid creating it thousands of times in tests when
it's not needed, plus it can deadlock in mesa apparently.
2025-08-14 15:58:59 +03:00
Christian Meissl af9ce53310 use ScanoutCandidate kind for surfaces
this allows to get direct scan-out on surfaces again
2025-08-13 11:39:12 +03:00
Ivan Molodetskikh 0044578681 Fix new lifetime warnings 2025-08-11 09:39:28 +03:00
Ivan Molodetskikh 0c09f2529b Update dependencies 2025-08-11 09:12:42 +03:00
Ivan Molodetskikh 2fb993d221 Bump Smithay (xkbcommon wvkbd fix) 2025-08-11 09:07:13 +03:00
vanderlokken 67361f88fd Add the LoadConfigFile action (#2163)
* Add the `LoadConfigFile` action

* fixes

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-09 12:20:08 +00:00
BB f74d83dcca niri-config: add keep-max-bpc-unchanged option (#2195)
* niri-config: add disable-set-bpc option
setting bpc to 8 bricks some OLED displays driven by amdgpu

* change to keep-max-bpc-unchanged and add to wiki

* fmt

* Update wiki/Configuration:-Debug-Options.md

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-07 11:06:11 -07:00
Ivan Molodetskikh 055a94de3d Reload libinput settings when trackball, tablet and touch change
Somehow missed this before.
2025-08-07 17:15:30 +03:00
sodiboo 52c579d556 fix hot reloading /etc/niri/config.kdl (#1907)
* refactor config load logic, and properly watch the system config path

* move config creation to niri-config, and make the errors a bit nicer

notably, "error creating config" is now a cause for "error loading
config", instead of it being one error and then "error loading config:
no such file or directory". also, failure to load a config is now
printed as an error level diagnostic (because it is indeed an error, not
just a warning you can shrug off)

* refactor watcher tests; add some new ones

now they check for the file contents too! and i added some tests for
ConfigPath::Regular, including a messy one with many symlink swaps

* fixes

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-08-05 06:27:28 -07:00
Ivan Molodetskikh 5edd91d37b pw_utils: Add Tracy span to queue_after_sync() 2025-08-04 16:01:11 +02:00
Ivan Molodetskikh 378a90e4b0 pw_utils: Set sequence in buffer meta header
Useful for debugging.
2025-08-04 16:01:11 +02:00
Ivan Molodetskikh 871cf4ba9a pw_utils: Remove commented-out unused buffer props 2025-08-04 16:01:11 +02:00
Ivan Molodetskikh f49ecc31c4 pw_utils: Wait for frame completion before queueing
Without explicit sync, we have no way to signal the PipeWire consumer when the
rendering is done. So, wait until it's done before giving it the frame.

This should fix flickering screencasts on NVIDIA.
2025-08-04 14:36:34 +02:00
Ivan Molodetskikh 15b4acc17e pw_utils: Fill dmabuf strides and offsets at add_buffer()
As far as I understand, these don't change.
2025-08-04 14:36:34 +02:00
Ivan Molodetskikh 43577f4d97 pw_utils: Store LoopHandle 2025-08-04 14:36:34 +02:00
Ivan Molodetskikh 8fba696d8e pw_utils: Switch to using raw pw_buffers
We're gonna need to store these in the future, and the lifetime on the pw-rs
Buffer prevents us from easily doing that. Besides, we'll need access to
metadata which pw-rs doesn't expose yet.
2025-08-04 14:36:34 +02:00
Ivan Molodetskikh 2e3935d77d pw_utils: Extract shared state to CastInner 2025-08-04 14:36:34 +02:00
Ivan Molodetskikh 53b7c08363 pw_utils: Unmark CastState as pub 2025-08-04 14:36:34 +02:00
Ivan Molodetskikh 76c3bb20ba pw_utils: Add clarifying comments on maxsize and size 2025-08-04 14:36:34 +02:00
Ivan Molodetskikh 91b6a111cf Upgrade dependencies
Leave gtk-rs for now as it bumped MSRV to 1.83.
2025-07-31 19:39:12 +02:00
Ivan Molodetskikh 98a42c5557 Update Smithay (clipboard client exit nil fix, input region bottom-right fix) 2025-07-31 19:39:12 +02:00
Ivan Molodetskikh e19e1f0f10 signals: Gate on target_os = "linux"
Hopefully fixes build on FreeBSD.
2025-07-31 14:57:46 +03:00
Ivan Molodetskikh c0ddf3f9ff signals: Reduce fn visibility 2025-07-31 14:50:39 +03:00
Ivan Molodetskikh 4ac4cb4a44 xwayland: Make abstract socket optional and Linux-only
Hopefully fixes build on FreeBSD.
2025-07-31 14:35:35 +03:00
Ivan Molodetskikh 365274e5e2 default-config: Add a bind to toggle orca (screen reader)
Signed-off-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-07-31 13:02:54 +02:00
Ivan Molodetskikh 672bf3e1ff Implement org.fd.a11y KeyboardMonitor
Makes Orca work with niri:
- keyboard watching and announcing everywhere (not just GTK 3 windows)
- grabs for the Orca modifier (with double-press to pass through) and keystrokes
2025-07-31 13:02:54 +02:00
Ivan Molodetskikh fefc0bc0a7 README: Link LWN article 2025-07-18 23:28:49 +03:00
zimward 0b1a6c76ec ci/alpine: switch to container to not rely on overloaded alpine gitlab 2025-07-18 12:10:47 -07:00
sodiboo 485e667fec block signals early: now handled correctly with tracy ondemand 2025-07-18 11:41:17 -07:00
sodiboo 8f442dee06 refactor signal handling, and clear sigmask before spawning 2025-07-18 11:41:17 -07:00
ジムワルド 9c09bc730f ci: add musl/alpine build (#2065)
* ci: add musl build

* Update .github/workflows/ci.yml

* Update .github/workflows/ci.yml

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-07-17 20:05:36 +00:00
Ivan Molodetskikh 7b065f8618 wiki/Nvidia: Mention screencast flickering fix 2025-07-16 11:57:55 +03:00
hecate cantus 60fbcd2329 Add Nvidia.md leaf file, add links in sidebar & getting started (#2029)
* Add Nvidia.md leaf file, add links in sidebar & getting started

* squash review-commits from gh to one commit

* heap reuse ratio from 1 => 0 to match currently shipped solution

* Update wiki/Nvidia.md

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-07-16 06:06:07 +00:00
Ivan Molodetskikh 5ac440a760 Mention localectl in the docs 2025-07-15 18:38:00 +03:00
Ivan Molodetskikh 0e3d078a85 Implement fetching xkb options from org.freedesktop.locale1 2025-07-15 18:19:11 +03:00
Bloxx12 36efd6e3f9 nix: update flake inputs 2025-07-15 15:55:45 +03:00
Bloxx12 30a9c6c31b nix: replace nix-filter with lib.fileset
Co-authored-by: sodiboo <git@sodi.boo>
2025-07-15 15:55:45 +03:00
Ivan Molodetskikh bc0a06226a niri-session: Also unset DISPLAY
We set it now for xwayland-satellite integration.
2025-07-15 15:54:50 +03:00
sodiboo ed799f5afc revert nushell completion for flake.nix 2025-07-15 14:32:45 +03:00
Ivan Molodetskikh 007d35541d README: Mention Contributing 2025-07-15 10:45:54 +03:00
Ivan Molodetskikh e46a27351d README: Move Media higher up 2025-07-15 10:40:45 +03:00
Ivan Molodetskikh 56901eed5d Print when exiting by signal
Doesn't appear to work at the moment?
2025-07-14 14:58:27 +03:00
Ivan Molodetskikh 48fe08caf4 CONTRIBUTING.md: Mention testing in writing PRs 2025-07-14 14:57:44 +03:00
Horu df00f0328e Register org.freedesktop.ScreenSaver at /ScreenSaver 2025-07-14 14:56:11 +03:00
Ivan Molodetskikh d85eaf9799 Fix LockedHint locked condition 2025-07-14 14:39:57 +03:00
peelz 25cbb739ae Set logind LockedHint on lock/unlock (#1763)
* Set logind LockedHint on lock/unlock

* fixup! Set logind LockedHint on lock/unlock

- use warn!() instead of error!()
- extract dbus call into a separate method

* fixup! Set logind LockedHint on lock/unlock

- Update LockedHint in refresh_and_flush_clients

* fixup! Set logind LockedHint on lock/unlock

woops

* fixup! Set logind LockedHint on lock/unlock

- only call SetLockedHint if niri was run with `--session`

* fixes

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-07-14 11:34:10 +00:00
Vladimir-csp 88339633b1 Detect external session management
This should make `uwsm start niri.desktop` possible like with other compositors.
2025-07-14 13:20:30 +03:00
sodiboo 22e43193e0 handle SIGINT, SIGTERM, SIGHUP 2025-07-14 13:16:10 +03:00
sodiboo 7a2379ad35 don't use smithay::reexports for calloop::EventLoop 2025-07-14 13:16:10 +03:00
Ivan Molodetskikh fe2c2eec29 Add CONTRIBUTING.md 2025-07-14 12:04:36 +03:00
Artrix 746a7e81b7 Add nushell completion support (#2009)
* Add nushell completion support

Adds `clap_complete_nushell` crate and implements it into the `niri
completions` command.

* Add nushell to flake.nix autocompletions

* Convert to `TryFrom`

* Fix linting errors

* Move types down

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-07-14 06:29:26 +00:00
abmantis 51b6a495c5 Simplify pointer handling in constraint check
Minor change so that `get_pointer()` (which has a lock) does not get
called twice. Also moved the call to `current_location()` to the scope
where it is needed.
2025-07-14 06:48:56 +03:00
Ivan Molodetskikh bb40a35ccf wiki/Xwayland: Link FAQ entry with reasons 2025-07-13 17:46:47 +03:00
Ivan Molodetskikh 37c6412e80 wiki/FAQ: Mention reasons for not integrating Xwayland 2025-07-13 17:44:07 +03:00
Sharun 19c8fca836 feat: add hint to disable "Important Hotkeys" in the default config file (#1881)
* feat: add hint to disable "Important Hotkeys" in the default config file

* Update resources/default-config.kdl

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-07-13 11:29:27 +00:00
Lin Xianyi 186e0b608a Fix docs for FocusWindowOrWorkspaceDown
Typo fix for the doc comment
2025-07-13 14:11:17 +03:00
Ivan Molodetskikh ce501bca9e tests: Add layer-shell scaffolding and an overflow test 2025-07-13 12:59:01 +03:00
Ivan Molodetskikh 45e9bb769d Update deps & Smithay (layer-shell overflows fix) 2025-07-13 12:58:52 +03:00
Ivan Molodetskikh dfb3683187 Fix new Clippy warnings 2025-07-13 12:54:03 +03:00
Ivan Molodetskikh ce9ba00d54 Implement ext-workspace 2025-07-13 11:43:59 +03:00
Ivan Molodetskikh 37458d94b2 Bump xcursor version in Cargo.toml too 2025-06-24 21:52:04 +03:00
Ivan Molodetskikh 044f14f8f9 Update xcursor (fixes regression in last update) 2025-06-24 21:47:39 +03:00
Ivan Molodetskikh 4c02f3bba4 Update dependencies 2025-06-23 16:12:45 +03:00
Ivan Molodetskikh b55a80c641 Update Smithay 2025-06-23 16:12:45 +03:00
Nikolay Yakimov e0b0b04b44 Expose libinput Button Scrolling Button Lock Enabled property 2025-06-19 05:05:47 -07:00
Baily ed14e8da84 Fix typos (#1822)
* Fix: Correct typo in xwayland module and update documentation

This commit includes several improvements:

1.  **Code Fix (clippy):**
    - I corrected a typo in `src/utils/xwayland/mod.rs` from `OFlags::WRONGLY` to `OFlags::WRONLY`. This was identified by `clippy` during the build process.

2.  **Documentation Updates:**
    - **README.md**:
        - I clarified the sentence about finding help in the Matrix channel to be more inviting for new users.
        - I corrected a future date typo in the Media section for an interview (June 2025 to June 2024).
    - **wiki/Getting-Started.md**:
        - I changed the Russian month "мая" to "May" in an example output for better international readability.
        - I improved keybinding notation for monitor focus/move keys (e.g., Mod+Shift+H / J / K / L) to avoid ambiguity.
        - I updated `apt-get` to `apt` in Ubuntu dependency installation commands for modern practice.

No new typos were found by `typos-cli` in this pass.

* Revert README&GS.md to previous version

* Apply rustfmt

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2025-06-18 08:49:47 +03:00
Nicolaos Skimas e53f8527b0 Add backlight adjustment keys to default config (#1824)
* Support backlight adjustment keys in default config

* Update resources/default-config.kdl

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-06-17 06:37:00 +00:00
Ivan Molodetskikh da3dc913a6 README: Link a new video and podcast 2025-06-16 14:59:08 +03:00
Ivan Molodetskikh f3f6e79eec Return app ids with ".desktop" appended to Shell.Introspect
This isn't the correct solution, but it seems to work often enough for window
icons in the screencast dialog.
2025-06-13 09:55:08 +03:00
Ivan Molodetskikh 83ec369536 layout/scrolling: Take unfullscreen view offset unconditionally
It might get set and unset all while the view is frozen with a gesture.
2025-06-13 08:54:59 +03:00
Ivan Molodetskikh 97dfd2b1a0 screenshot_ui: Move selection with a second touch too 2025-06-12 21:17:25 +03:00
Anselm Schüler 730eab09fb default-config.kdl: add repeat=false to close-window 2025-06-12 07:25:31 -07:00
Ivan Molodetskikh a23ce10311 screenshot_ui: Move selection when holding Space 2025-06-12 15:24:49 +03:00
Ivan Molodetskikh 2f18d8e328 Implement move-column/window-to-monitor actions for the screenshot UI 2025-06-12 08:56:52 +03:00
Ivan Molodetskikh 7aec37f5c9 Extract output_left/right/up/down/previous/next_of() 2025-06-11 21:09:55 +03:00
Andrew Davis 07080a0431 Clamp colors to valid values when parsing config
The oklch color space often creates weird values when parsed by csscolorparser.
clamping the output to values between 0 and 1 should fix inconsistent color handling
on borders.
2025-06-11 02:40:36 -07:00
Ivan Molodetskikh aa47223c19 Upgrade deps and Smithay (cursor-shape v2) 2025-06-11 10:21:17 +03:00
Illia Ostapyshyn 10a6d6ae45 Expand screenshot UI to handle move-X-or-to-workspace/monitor-X (#1669)
* Expand screenshot UI to handle more moving actions

Currently, screenshot UI handles MoveColumn{Left,Right} and
MoveWindow{Up,Down} which move the screenshot selection as if it were a
floating window.  Expand this to include MoveColumn*OrToMonitor* and
MoveWindow*OrToWorkspace* and adjust their logic to move the screenshot
selection.

* Update src/input/mod.rs

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-06-11 06:28:03 +00:00
Nathan 7db864d203 Update Example-systemd-Setup.md to use add-wants (#1710)
Instead of hard-linked locations tried to reword to simplify for both XDG-compliance and/or non-compliance. Additionally, replace 'ln ...' references with "add-wants" from systemctl. This advantage is that it creates all the right directories and the only thing the user needs to worry about later is possibly removing a symlink manually.
2025-06-11 06:18:26 +00:00
sashomasho 8d7b22d1a8 Add deactivate-unfocused-windows debug flag (#1706)
* force xdg deactivation on invisable workspaces

This debug option provides a workaround for many Chromium-based chat
applications that fail to show notifications when they're active in
a workspace that's not currently visible and don't have keyboard focus

Signed-off-by: Alex Yosifov <sashomasho@gmail.com>

* fixes

---------

Signed-off-by: Alex Yosifov <sashomasho@gmail.com>
Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-06-11 06:05:14 +00:00
Ivan Molodetskikh 0407ac5e4c Ignore lock surfaces from unrelated clients
gtklock doesn't mind the fact that it got denied the lock, and just creates a
new lock surface anyway. And we happily replace the running lock with it.
2025-06-10 17:03:32 +03:00
Ivan Molodetskikh a18d24fc24 Don't forget to update insta snapshots 2025-06-09 16:13:40 +03:00
Ivan Molodetskikh 2bacc80c93 default-config: Make sample gradients more obvious 2025-06-09 14:40:31 +03:00
Ivan Molodetskikh c91638c12e default-config: Clarify focus-ring inactive-color 2025-06-09 14:27:50 +03:00
Ivan Molodetskikh f8a0c9df2c default-config: Clarify that input settings are not defaults 2025-06-09 14:25:30 +03:00
Ivan Molodetskikh 6bab912383 Accept FloatOrInt for input accel_speed, animation slowdown
Technically cfg-breaking due to introducing min/max limits at parse time, but
values outside these limits were invalid anyway, so maybe it's fine?
2025-06-09 14:04:56 +03:00
Ivan Molodetskikh 3edb8fd906 layout/scrolling: Take parent area into account for popup unconstraining 2025-06-09 13:52:18 +03:00
Ivan Molodetskikh c9b1514d63 layout/scrolling: Store parent_area in ScrollingSpace 2025-06-09 13:43:28 +03:00
Ivan Molodetskikh 2066737024 layout/scrolling: Inline popup_target_rect up to ScrollingSpace 2025-06-09 13:39:55 +03:00
Ivan Molodetskikh f918eabe6a Implement xwayland-satellite integration 2025-06-07 13:12:50 -07:00
Ivan Molodetskikh 0698f167e5 Update generate-rpm version 2025-06-07 23:03:01 +03:00
Ivan Molodetskikh 242ebf2945 wiki: Add Since to hide-not-bound 2025-06-05 11:42:32 +03:00
Ivan Molodetskikh 9858599ac1 Round lock surface size, rather than floor
There's no problem with 1 px overflow here, while 1 px underflow shows up as a
border.
2025-06-04 09:40:22 +03:00
Kent Daleng abac28a65c add option to hide unbound actions in hotkey overlay (#1618)
* add option to hide unbound actions in hotkey overlay

* fix config test, add some docs

* Add kdl language hint

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* Improve docs

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* hide_unbound -> hide_not_bound

* forgot to rename in wiki

* filter actions before calling format

* use any instead of contains

* retain instead of filter

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-06-03 20:31:18 +03:00
Gwen a7186a0441 Add debug option to skip cursor-only updates while VRR is active (#1616)
* Add debug option to skip cursor-only updates while VRR is active

* Update niri-config/src/lib.rs

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* Update src/backend/tty.rs

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* Update wiki/Configuration:-Debug-Options.md

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* Update Configuration:-Debug-Options.md

* Update tty.rs

* Update lib.rs

* Update Configuration:-Debug-Options.md

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-06-03 15:56:21 +00:00
Ivan Molodetskikh 1911cf3f55 wiki/Xwayland: Remove the scary "experimental" word from xwl-s 2025-06-01 19:22:17 +03:00
Ivan Molodetskikh 09da884cd8 README: Update Configuration link 2025-06-01 09:56:28 +03:00
Ivan Molodetskikh 8ba57fcf25 Bump version to 25.05.1 2025-05-25 08:45:41 +03:00
Ivan Molodetskikh 126ca37d96 Rename Un/Set/ToggleUrgent to Un/Set/ToggleWindowUrgent
Overlooked this when reviewing. This change is not cfg-breaking (since you
can't bind these directly), but it does break calling these actions through
IPC. I don't imagine they are widely used though, and the original PR author
who also implemented urgency for bars said he didn't use these actions either.
2025-05-25 08:43:27 +03:00
Ivan Molodetskikh e6bd60fbb1 wiki: Remove note about numlock issue
It's been fixed.
2025-05-25 08:36:33 +03:00
Ivan Molodetskikh a605a3f016 Account for hidden pointer in move_cursor() 2025-05-23 23:08:51 +03:00
Ivan Molodetskikh ef44adea69 Set pointer contents straight to nothing when disabling pointer 2025-05-23 23:08:51 +03:00
Duncan Overbruck 7fdb918cd0 input: do not revert fully invisible cursor to hidden (#1650)
* input: do not force redraw to hide an already hidden cursor

* more

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-05-23 05:24:24 +00:00
Ivan Molodetskikh 8347cc20dc Update Smithay (pen tilt, num lock, keymap spam) 2025-05-22 18:05:17 +03:00
alex-huff 51a176ec4a layer-shell: only reset 'initial_configure_sent' for mapped surfaces 2025-05-22 08:02:56 -07:00
alex-huff d618daf6b9 layer-shell: don't dismiss popups because of unmapped layer surfaces
Fixes #1640
2025-05-22 07:55:29 -07:00
Ivan Molodetskikh 357f9157cc wiki/packaging: Mention RUN_SLOW_TESTS 2025-05-22 11:37:09 +03:00
Ivan Molodetskikh c4a759e620 wiki/packaging: Document limiting test threads 2025-05-22 11:35:12 +03:00
Ivan Molodetskikh f369a0f810 input: Add missing check for output under 2025-05-22 08:55:01 +03:00
Ivan Molodetskikh 71251a7003 input: Add missing redraws on urgency actions
The layout urgent colors update even without window rule changes.
2025-05-21 19:50:13 +03:00
alex-huff 2415346caa layer-shell: properly handle re-map
According to the zwlr_layer_surface_v1 documentation: Unmapping a
layer_surface means that the surface cannot be shown by the compositor
until it is explicitly mapped again. The layer_surface returns to the
state it had right after layer_shell.get_layer_surface. The client can
re-map the surface by performing a commit without any buffer attached,
waiting for a configure event and handling it as usual.

Before this commit, no configure event was sent when a client performed
a commit without any buffer attached.
2025-05-21 07:25:22 -07:00
Ivan Molodetskikh 3f2b7e63ba Improve comment in on-demand layer-shell keyboard alive check 2025-05-19 09:18:07 +03:00
Ivan Molodetskikh ae89cb6017 Update README.md 2025-05-17 15:59:05 +03:00
Ivan Molodetskikh b6fc4d0455 wiki/Overview: Link the new video 2025-05-17 14:38:24 +03:00
Federico Ceratto d8265ad34e Stop including broken LFS files in source tarball 2025-05-17 04:29:46 -07:00
Ivan Molodetskikh 3b864dc104 Bump version to 25.05 2025-05-17 13:50:36 +03:00
Ivan Molodetskikh 15093221ed wiki/Overview: Update wording 2025-05-17 13:44:55 +03:00
Ivan Molodetskikh ac7b3fbf19 wiki: Link to issue in numlock
https://github.com/YaLTeR/niri/issues/1501
2025-05-17 07:58:52 +03:00
Ivan Molodetskikh bb8eb377c7 Update dependencies more carefully
No winit deadlock in this update.
2025-05-16 22:54:37 +03:00
Ivan Molodetskikh 6169c0312a Revert "Update dependencies"
Something is causing winit deadlock on nested niri exit.

This reverts commit 2ae99224ab.

This reverts commit 0d6843ea67.
2025-05-16 22:53:54 +03:00
Ivan Molodetskikh 2ae99224ab Update dependencies 2025-05-16 22:29:09 +03:00
Ivan Molodetskikh 4f63e13385 Deal with new Clippy warnings 2025-05-16 22:21:14 +03:00
Ivan Molodetskikh 46a8f81160 ipc/client: Make compositor version check for JSON parsing errors
These can happen when adding new fields to returned structs.
2025-05-15 09:08:53 +03:00
Ivan Molodetskikh 0d6843ea67 Update dependencies 2025-05-13 17:13:35 +03:00
Ivan Molodetskikh 6d083ea497 layout: Fix workspace swipe to same workspace forgetting previous id
This manifested much more prominently in the overview.
2025-05-13 08:17:15 +03:00
Ivan Molodetskikh 7a42140d6c dependabot: Change to weekly
Let's see if this fixes it missing from the GitHub UI.
2025-05-12 20:05:33 +03:00
Ivan Molodetskikh eeb411bef5 wiki: Add Since for touchpad drag 2025-05-12 20:05:10 +03:00
Ivan Molodetskikh defd4c5c4d Add center-visible-columns action 2025-05-12 14:13:51 +03:00
dependabot[bot] 7227e64149 build(deps): bump clap in the rust-dependencies group
Bumps the rust-dependencies group with 1 update: [clap](https://github.com/clap-rs/clap).


Updates `clap` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.37...clap_complete-v4.5.38)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.38
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-12 02:58:56 -07:00
Ivan Molodetskikh c98537a2b0 Implement baba-is-float for layers 2025-05-12 09:10:59 +03:00
Ivan Molodetskikh 9c103f1f1d Add missing "to" in comment 2025-05-12 08:26:39 +03:00
Ivan Molodetskikh 2aff1ec71a ipc/socket: Support multiple requests 2025-05-11 21:51:26 -07:00
Jon Heinritz 3466fc0a66 ipc: document the new socket behavior 2025-05-11 21:51:26 -07:00
Jon Heinritz f917932b3e ipc: support long living sockets 2025-05-11 21:51:26 -07:00
Ivan Molodetskikh 89b7423ee5 Print urgent status in niri msg windows 2025-05-10 23:43:00 +03:00
Ivan Molodetskikh a2efaf2816 Add is-urgent window rule matcher 2025-05-10 22:49:55 +03:00
Ivan Molodetskikh 5816691460 Add urgent color support to tab indicators 2025-05-10 22:42:45 +03:00
Ivan Molodetskikh 4b5e9e6cb0 wiki: Document urgent-color 2025-05-10 22:42:45 +03:00
Duncan Overbruck a8259b4cea add WindowUrgencyChanged ipc event 2025-05-10 12:14:41 -07:00
Duncan Overbruck 9d3d7cb0e9 add {toggle,set,unset}-urgent cli actions 2025-05-10 12:14:41 -07:00
Duncan Overbruck 398bc78ea0 add urgent border color and gradient 2025-05-10 12:14:41 -07:00
Duncan Overbruck caa6189448 add workspace urgency ipc event 2025-05-10 12:14:41 -07:00
Duncan Overbruck 86f57c2ec7 add window urgency through xdg-activation-v1
urgency is done through activation requests without a serial from a
previous interaction.

https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/150
2025-05-10 12:14:41 -07:00
Charlie Le 3cc67897af Implement IPC for the overview state (#1526)
* Implement IPC for the overview state

* Update Overview IPC to maintain naming consistency, renamed OverviewToggled to be more clear, simplify overview state request on the server, consolidate ipc refresh

* Fix Overview is_open in IPC client

* Change opened to is_open

* Update niri-ipc/src/lib.rs

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* Update niri-ipc/src/state.rs

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* Update src/ipc/client.rs

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* Update src/ipc/client.rs

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>

* Add overview state to EventStreamStatePart replicate and apply

* Fix formatting

* Rename Overview to OverviewState

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-05-09 18:01:01 +03:00
dependabot[bot] a99489c6c0 build(deps): bump clap_complete in the rust-dependencies group
Bumps the rust-dependencies group with 1 update: [clap_complete](https://github.com/clap-rs/clap).


Updates `clap_complete` from 4.5.49 to 4.5.50
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.49...clap_complete-v4.5.50)

---
updated-dependencies:
- dependency-name: clap_complete
  dependency-version: 4.5.50
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-09 07:38:04 -07:00
Ivan Molodetskikh 0763c7e196 Add a clickable button to capture the screenshot
Allows tablet-, touch- and mouse-only confirmation.
2025-05-09 15:42:23 +03:00
Ivan Molodetskikh fb5c5204e8 Extract confirm_screenshot() 2025-05-09 15:41:57 +03:00
Ivan Molodetskikh d207cd385b screenshot_ui: Refactor mouse down + touch slot state 2025-05-09 15:10:00 +03:00
Ivan Molodetskikh 99bf2df2b4 Silence new zvariant De/SerializeDict deprecations
Questionable exercise converting to serde with much more boilerplate, and
breaking compat with older zvariant versions. Plus maybe this will be
undeprecated back.
2025-05-09 10:35:16 +03:00
Ivan Molodetskikh 09be90f4e6 Add touch selection support to the screenshot UI 2025-05-09 10:28:20 +03:00
Ivan Molodetskikh dfc42b9d82 Split ScreenshotUi::pointer_down() and up() 2025-05-09 10:28:20 +03:00
Ivan Molodetskikh e2b9838d89 Extract evt.slot() 2025-05-09 10:28:20 +03:00
Ivan Molodetskikh 816a0d479c Rename touch_location to pos 2025-05-09 10:28:20 +03:00
Ivan Molodetskikh 84323d10a4 Support tablet input for screenshot UI selection 2025-05-09 10:28:20 +03:00
Ivan Molodetskikh b956f2775c Use early return 2025-05-09 10:28:20 +03:00
Ivan Molodetskikh 9ff2f83db0 Simplify ScreenshotUi::pointer_button() 2025-05-09 10:28:20 +03:00
James Sully 7a10f71ee5 refactor(main): eliminate a mut from config load code in main
I think this makes for marginally better readability, since you don't
have to wonder whether config_errored is set anywhere else. It's also
slightly terser.
2025-05-09 00:25:54 -07:00
James Sully ea7add3563 fix: don't try to create a default config at path that exists
Currently this bug has no actual consequences, we just continue silently
on AlreadyExists in main()
(this line: https://github.com/YaLTeR/niri/blob/e9c6f08906143c3fec1ad1301d538bef4cbc1978/src/main.rs#L151).

This commit just eliminates the redundant attempt.
2025-05-08 21:52:39 -07:00
Ivan Molodetskikh e9c6f08906 Add a resize transaction client-server test 2025-05-07 22:59:57 +03:00
Ivan Molodetskikh 17343a6740 wiki: Fix Until note location 2025-05-06 17:42:14 +03:00
Ivan Molodetskikh 140d726cd3 wiki: Clarify that layers within backdrop ignore input 2025-05-06 17:40:52 +03:00
Ivan Molodetskikh c37d3b3442 wiki: Link to output backdrop-color from overview {} 2025-05-06 17:34:40 +03:00
Ivan Molodetskikh 497f186422 Add layout background-color setting 2025-05-06 17:34:40 +03:00
Ivan Molodetskikh 3e31c134a6 Implement place-within-backdrop layer rule 2025-05-06 17:34:40 +03:00
Ivan Molodetskikh fe682938db Simplify exclusive focus on layer check 2025-05-06 17:34:40 +03:00
Ivan Molodetskikh 6142922ca4 wiki: Mention Overview behavior on layer-shell page 2025-05-06 17:34:40 +03:00
Ivan Molodetskikh 4b44fba14c wiki: Clarify FAQ question about border with background 2025-05-06 17:34:40 +03:00
dependabot[bot] 57639ca84c build(deps): bump the rust-dependencies group across 1 directory with 3 updates
Bumps the rust-dependencies group with 3 updates in the / directory: [clap_complete](https://github.com/clap-rs/clap), [glam](https://github.com/bitshifter/glam-rs) and [zbus](https://github.com/dbus2/zbus).


Updates `clap_complete` from 4.5.48 to 4.5.49
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.48...clap_complete-v4.5.49)

Updates `glam` from 0.30.2 to 0.30.3
- [Changelog](https://github.com/bitshifter/glam-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bitshifter/glam-rs/compare/0.30.2...0.30.3)

Updates `zbus` from 5.5.0 to 5.6.0
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zbus-5.5.0...zbus-5.6.0)

---
updated-dependencies:
- dependency-name: clap_complete
  dependency-version: 4.5.49
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: glam
  dependency-version: 0.30.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: zbus
  dependency-version: 5.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-06 01:38:03 -07:00
Ivan Molodetskikh ec88aae77d wiki: Add Since to numlock 2025-05-05 20:29:55 +03:00
Ivan Molodetskikh 6c9705dd4b layout/scrolling: Update view offset on config update
Fix always-centering not applied right away. No other changes intended.
2025-05-01 21:37:34 +03:00
Aberter Yan eb590c5346 Implement --focus for MoveColumnToWorkspace/Up/Down 2025-05-01 11:06:34 -07:00
Ivan Molodetskikh 02baad91ac wiki: Clarify how key bindings are resolved 2025-05-01 16:28:28 +03:00
Ivan Molodetskikh 68589cd5a1 wiki: Remove "experimental" from custom shaders
They've been around for a while.
2025-05-01 11:19:38 +03:00
Ivan Molodetskikh f2c690802b Adjust the workspace shadow defaults some more 2025-05-01 11:04:47 +03:00
Ivan Molodetskikh 9d6037b94c Normalize workspace shadows to 1080 px tall screen, adjust defaults
Workspace gaps are dependent on screen size, so it makes sense to make shadows
depend on the screen size to, to avoid them filling more or less of the gap.
2025-05-01 10:33:53 +03:00
Ivan Molodetskikh 7b4cf094ef Draw workspace shadows behind all workspaces 2025-05-01 10:10:11 +03:00
Ivan Molodetskikh 446bc155ce Add workspace-shadow {} config to overview {} 2025-05-01 09:45:38 +03:00
Ivan Molodetskikh 3289324ce4 wiki: Use subheadings for overview settings 2025-05-01 09:36:39 +03:00
Ivan Molodetskikh 9fb02b9571 layout: Fix DnD scroll not stopping when interactive moving unfullscreen to floating 2025-04-30 20:32:56 +03:00
erdii 0e9496b01e chore(wiki): document numlock setting
Co-Authored-By: Ivan Molodetskikh <yalterz@gmail.com>
Signed-off-by: erdii <me@erdii.engineering>
2025-04-30 09:54:19 -07:00
erdii 82dabc21f3 feat: implement support to enable numlock at startup
Signed-off-by: erdii <me@erdii.engineering>
2025-04-30 09:54:19 -07:00
erdii 39b3d62873 chore: bump smithay 2025-04-30 09:54:19 -07:00
dependabot[bot] af080a03cd build(deps): bump the rust-dependencies group with 3 updates
Bumps the rust-dependencies group with 3 updates: [wayland-backend](https://github.com/smithay/wayland-rs), [insta](https://github.com/mitsuhiko/insta) and [wayland-client](https://github.com/smithay/wayland-rs).


Updates `wayland-backend` from 0.3.9 to 0.3.10
- [Release notes](https://github.com/smithay/wayland-rs/releases)
- [Changelog](https://github.com/Smithay/wayland-rs/blob/master/historical_changelog.md)
- [Commits](https://github.com/smithay/wayland-rs/commits)

Updates `insta` from 1.43.0 to 1.43.1
- [Release notes](https://github.com/mitsuhiko/insta/releases)
- [Changelog](https://github.com/mitsuhiko/insta/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mitsuhiko/insta/compare/1.43.0...1.43.1)

Updates `wayland-client` from 0.31.9 to 0.31.10
- [Release notes](https://github.com/smithay/wayland-rs/releases)
- [Changelog](https://github.com/Smithay/wayland-rs/blob/master/historical_changelog.md)
- [Commits](https://github.com/smithay/wayland-rs/commits)

---
updated-dependencies:
- dependency-name: wayland-backend
  dependency-version: 0.3.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: insta
  dependency-version: 1.43.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: wayland-client
  dependency-version: 0.31.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-30 01:46:05 -07:00
Ivan Molodetskikh 5f117c61dc animation/spring: Guard against numerical instability 2025-04-29 10:51:53 +03:00
Christian Meissl cb857e32e4 Bump Smithay and others
Presentation subsurface fix, popup unconstrain resize fix, cursor shape fix, refactors.
2025-04-29 08:53:25 +03:00
dependabot[bot] 199be26947 build(deps): bump the rust-dependencies group across 1 directory with 5 updates
Bumps the rust-dependencies group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.97` | `1.0.98` |
| [clap](https://github.com/clap-rs/clap) | `4.5.34` | `4.5.37` |
| [glam](https://github.com/bitshifter/glam-rs) | `0.30.1` | `0.30.2` |
| [libc](https://github.com/rust-lang/libc) | `0.2.171` | `0.2.172` |
| [insta](https://github.com/mitsuhiko/insta) | `1.42.2` | `1.43.0` |



Updates `anyhow` from 1.0.97 to 1.0.98
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.97...1.0.98)

Updates `clap` from 4.5.34 to 4.5.37
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.34...clap_complete-v4.5.37)

Updates `glam` from 0.30.1 to 0.30.2
- [Changelog](https://github.com/bitshifter/glam-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bitshifter/glam-rs/compare/0.30.1...0.30.2)

Updates `libc` from 0.2.171 to 0.2.172
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.172/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.171...0.2.172)

Updates `insta` from 1.42.2 to 1.43.0
- [Release notes](https://github.com/mitsuhiko/insta/releases)
- [Changelog](https://github.com/mitsuhiko/insta/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mitsuhiko/insta/compare/1.42.2...1.43.0)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-version: 1.0.98
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: clap
  dependency-version: 4.5.37
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: glam
  dependency-version: 0.30.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: libc
  dependency-version: 0.2.172
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: insta
  dependency-version: 1.43.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-28 22:35:11 -07:00
Ivan Molodetskikh d5c0c74d2c Fix hot corners preventing focus even when disabled 2025-04-29 08:24:45 +03:00
Ivan Molodetskikh 9bb292ec82 default-config: Set repeat=off for the Overview bind 2025-04-28 12:05:55 +03:00
Ivan Molodetskikh a1ba6bcaa0 wiki: Update backdrop-color examples 2025-04-28 09:32:44 +03:00
Ivan Molodetskikh fd389af6d8 Add backdrop-color setting to overview {} 2025-04-28 09:14:43 +03:00
Ivan Molodetskikh db09727b18 Replace Smithay's SolidColor elements with ours
Must've forgotten about these back when I replaced others.
2025-04-28 09:05:55 +03:00
Ivan Molodetskikh c9d6478c3c wiki: Rename Configuration: Overview page to Introduction 2025-04-28 07:54:02 +03:00
bogdanov 758cca5432 Fix pointer hiding so that it is no longer annoying (#1426)
* replace `pointer_hidden` with `pointer_visiblity`

* disable hidden pointer after content underneath has changed

* fixes

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
2025-04-27 06:25:36 +00:00
Ivan Molodetskikh 78e3daf5f8 overview: Activate window upon dropping from interactive move 2025-04-26 13:29:36 +03:00
Mitchel Stewart a99a0b2492 Steam Black Screen system-composer 2025-04-26 00:38:48 -07:00
Ivan Molodetskikh bfd42c74f4 layout/tab_indicator: Fix negative gap
Regressed in a recent commit that added max1.
2025-04-26 09:25:31 +03:00
Ivan Molodetskikh 501ea47128 wiki/Overview: Mention backdrop-color 2025-04-25 17:56:17 +03:00
Ivan Molodetskikh d2a1cf53b4 Fix panic when interactively moving to invisible workspace
Introduced in the interactive move between workspaces commit.
2025-04-25 16:55:36 +03:00
Ivan Molodetskikh 62d47d77d5 wiki: Document backdrop-color and overview-open-close animation 2025-04-25 15:29:42 +03:00
Ivan Molodetskikh 85cd64e830 Document the Overview and other new things 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 55c14eebf2 hotkey_overlay: Show the ToggleOverview bind 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 3fe67549b4 default-config: Bind Mod+O to toggle-overview 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 1835b532d9 Implement interactive move to a new workspace above/between 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh e6d82d3ee3 Implement top-left hot corner to toggle the Overview
Compared to third-party implementations such as waycorner:

- It works during interactive window move (no surfaces receive pointer
  focus in this case, so this cannot work through layer-shell).
- It works during drag-and-drop.
- It disables itself over fullscreen windows.
- It does not prevent direct scanout.
2025-04-25 02:00:18 -07:00
Ivan Molodetskikh fae3a27641 Implement DnD hold to activate window or workspace 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 31e76cf451 overview: Add DnD up/down scrolling 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh b8a9be542f overview: Add touchscreen gestures 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 59de6918b3 overview: Add two-finger touchpad scroll 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh bd3d554389 overview: Add hardcoded mouse scroll binds 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh af1fca35bb Implement an Overview 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 9571d149b2 Render workspaces separately with gaps between
This design makes more sense spatially, and is required for the
Overview. Gaps also make it clear how clipping windows to workspace
bounds works.

Background and bottom layer-shell surfaces get duplicated for each
workspace, while top and overlay stay "on top".
2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 99358e36b3 layout/monitor: Extract activate_workspace_with_anim_config() 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 8b878f355f Put interactively moved window on top of background and bottom layer popups 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 395b6d9a4f layout: Extract interactive_moved_window_under() and add output check
Fixes interactively moved window getting input on every output rather
than just its own.
2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 25f24f668c Extract mapped_hit_data() 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 929eaf0d69 Pass target workspace to view offset grab 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh ce3103949f layout/scrolling: Support view offset anim during gesture
Brings back moving the newly active window into focus upon interactive
move dragging out.
2025-04-25 02:00:18 -07:00
Ivan Molodetskikh ef60dd81d7 layout/monitor: Cache scale, view_size, working_area 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 7671a5d833 layout/monitor: Don't consider workspace switch in active_tile_visual_rectangle()
This only did something when in the middle of a touchpad gesture, and it
didn't really make sense for that edge case.
2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 3f09352067 layout/monitor: Extract add_workspace_at() 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 5059cce886 Add with_alpha() to shader and shadow element 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh b20dd226c0 layout: Move insert hint from ScrollingSpace to Monitor 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh acb69c3b4d layout: Return floating and scrolling elems separately from Workspace 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh dbe0a9e293 layout/tab_indicator: Use round_max1 where appropriate 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh d3a79faeec layout/monitor: Extract workspace_render_idx() 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 21630ddb5e layout/monitor: Extract workspaces_render_geo() 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 9e5e0c85bb Simplify condition 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 5cd8040d1a Extract is_layout_obscured_under() 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 86351938f2 Put the top layer above bottom and background layer popups
Makes it consistent with how window popups are below the top layer, also
will make more sense for the overview.
2025-04-25 02:00:18 -07:00
Ivan Molodetskikh ee4c5e23ab Reformat scroll factor computation 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh ffd6acc0aa layout/monitor: Extract WorkspaceSwitchGesture::min_max() 2025-04-25 02:00:18 -07:00
Ivan Molodetskikh cee11dc329 layout/monitor: Keep track of workspace switch gesture start idx
Fixes jump when "catching" an animation with a gesture.
2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 59a42249a4 Remove cancellation from swipe gestures
It only worked for workspace switch, and even there it was more confusing than
helpful.
2025-04-25 02:00:18 -07:00
172 changed files with 15585 additions and 2976 deletions
+11
View File
@@ -1 +1,12 @@
# LFS configuration for images from the wiki
*.png filter=lfs diff=lfs merge=lfs -text
# Exclude LFS-tracked files from the tarball
/wiki/img/ export-ignore
# exclude .gitattributes itself from the tarball
.gitattributes export-ignore
# tip: can be tested using
# git archive --format=tar.gz --output=source.tar.gz HEAD && \
# tar tfvz source.tar.gz | grep -e '.png' -e '.gitattributes'
+2 -2
View File
@@ -3,7 +3,7 @@ updates:
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "daily"
interval: "weekly"
groups:
smithay:
patterns:
@@ -17,6 +17,6 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
interval: "weekly"
ignore:
- dependency-name: "Andrew-Chen-Wang/github-wiki-action"
+140 -54
View File
@@ -8,23 +8,17 @@ on:
- cron: '0 0 1 * *' # Monthly
env:
RUN_SLOW_TESTS: 1
DEPS_APT: curl gcc clang libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libpipewire-0.3-dev libpango1.0-dev libdisplay-info-dev
DEPS_DNF: cargo gcc clang libudev-devel libgbm-devel libxkbcommon-devel wayland-devel libinput-devel dbus-devel systemd-devel libseat-devel pipewire-devel pango-devel cairo-gobject-devel libdisplay-info-devel
DEPS_APK: cargo clang-libclang eudev-dev glib-dev libdisplay-info-dev libinput-dev libseat-dev libxkbcommon-dev mesa-dev pango-dev pipewire-dev tar
DEPS_PKG: git curl rust llvm pkgconf pixman libudev-devd libdisplay-info seatd libinput libxkbcommon pipewire mesa-libs cairo devel/glib20 gettext-runtime harfbuzz pango
jobs:
build:
test:
strategy:
fail-fast: false
matrix:
configuration: [debug, release]
include:
- configuration: release
release-flag: '--release'
name: test - ${{ matrix.configuration }}
name: test
runs-on: ubuntu-24.04
steps:
@@ -40,46 +34,87 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.configuration }}
- name: Check (no default features)
run: cargo check ${{ matrix.release-flag }} --no-default-features
- name: Check (just dbus)
run: cargo check ${{ matrix.release-flag }} --no-default-features --features dbus
- name: Check (just systemd)
run: cargo check ${{ matrix.release-flag }} --no-default-features --features systemd
- name: Check (just dinit)
run: cargo check ${{ matrix.release-flag }} --no-default-features --features dinit
- name: Check (just xdp-gnome-screencast)
run: cargo check ${{ matrix.release-flag }} --no-default-features --features xdp-gnome-screencast
- name: Check
run: cargo check ${{ matrix.release-flag }}
- name: Build (with profiling)
run: cargo build ${{ matrix.release-flag }} --features profile-with-tracy
- name: Build tests
run: cargo test --no-run --all --exclude niri-visual-tests ${{ matrix.release-flag }}
run: cargo test --no-run --all --exclude niri-visual-tests
- name: Test
run: cargo test --all --exclude niri-visual-tests ${{ matrix.release-flag }} -- --nocapture
run: cargo test --all --exclude niri-visual-tests -- --nocapture
build:
strategy:
fail-fast: false
name: check feature combinations
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
show-progress: false
- name: Install dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y ${{ env.DEPS_APT }}
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Check (no default features)
run: cargo check --no-default-features
- name: Check (just dbus)
run: cargo check --no-default-features --features dbus
- name: Check (just systemd)
run: cargo check --no-default-features --features systemd
- name: Check (just dinit)
run: cargo check --no-default-features --features dinit
- name: Check (just xdp-gnome-screencast)
run: cargo check --no-default-features --features xdp-gnome-screencast
- name: Check
run: cargo check
- name: Build (with profiling)
run: cargo build --features profile-with-tracy
build-musl:
strategy:
fail-fast: false
name: alpine musl
runs-on: ubuntu-24.04
container: alpine:3
steps:
- uses: actions/checkout@v4
with:
show-progress: false
- name: Install Deps
run: apk add --no-cache ${{ env.DEPS_APK }}
- uses: Swatinem/rust-cache@v2
- name: Build
run: cargo build --no-default-features --features dbus,xdp-gnome-screencast
# Job that runs randomized tests for a longer period of time.
# Also runs normal slow tests.
randomized-tests:
strategy:
fail-fast: false
name: randomized tests
name: randomized and slow tests
runs-on: ubuntu-24.04
env:
RUST_BACKTRACE: 1
RUN_SLOW_TESTS: 1
PROPTEST_CASES: 200000
PROPTEST_MAX_LOCAL_REJECTS: 200000
PROPTEST_MAX_GLOBAL_REJECTS: 200000
@@ -210,6 +245,47 @@ jobs:
- uses: Swatinem/rust-cache@v2
- run: cargo build --all
freebsd:
runs-on: ubuntu-24.04
env:
CARGO_HOME: /home/runner/work/niri/niri/cargo-home
steps:
- uses: actions/checkout@v4
with:
show-progress: false
# Required for the rust-cache action to work.
- uses: dtolnay/rust-toolchain@stable
# FIXME: doesn't seem to cache the builds, only the downloads for some unknown reason.
- uses: Swatinem/rust-cache@v2
with:
cache-all-crates: true
# Remove man-db triggers to speed up Ubuntu upgrade by a minute or two during vmactions/freebsd-vm action run.
- run: |
sudo rm /var/lib/dpkg/info/man-db.*
- name: Build
uses: vmactions/freebsd-vm@966989c456d41351f095a421f60e71342d3bce41 # v1.2.1
with:
prepare: |
pkg update -f
pkg install -y ${{ env.DEPS_PKG }}
run: |
curl -o patch-pipewire_init 'https://cgit.freebsd.org/ports/plain/x11-wm/niri/files/patch-pipewire_init?id=f3f7e555b06d9a87d63c047ce3e82e936a11f2fe'
export CARGO_HOME="$PWD/cargo-home"
cargo fetch
( cd $CARGO_HOME/git/checkouts/pipewire-rs-*/*/; patch -p2 < $CARGO_HOME/../patch-pipewire_init; )
cargo build \
--offline \
--no-default-features --features dbus,xdp-gnome-screencast
nix:
runs-on: ubuntu-24.04
steps:
@@ -228,21 +304,10 @@ jobs:
- run: nix flake check
continue-on-error: true
check-links:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
show-progress: false
- uses: lycheeverse/lychee-action@v2.0.2 # later versions break fragment checks. don't bump until this is fixed: https://github.com/lycheeverse/lychee/issues/1574
with:
args: --offline --include-fragments 'wiki/*.md'
publish-wiki:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs:
- build
- check-links
- publish-docs
permissions:
contents: write
runs-on: ubuntu-24.04
@@ -251,29 +316,50 @@ jobs:
with:
lfs: true
show-progress: false
- uses: Andrew-Chen-Wang/github-wiki-action@b7e552d7cb0fa7f83e459012ffc6840fd87bcb83
rustdoc:
needs: build
- uses: Andrew-Chen-Wang/github-wiki-action@b7e552d7cb0fa7f83e459012ffc6840fd87bcb83
with:
path: docs/wiki/
publish-docs:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs:
- test
permissions:
contents: write
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
lfs: true
show-progress: false
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
- name: Install the project
run: uv sync --locked --all-extras --dev
working-directory: docs/
- name: Generate niri documentation
run: uv run mkdocs build
working-directory: docs/
- uses: dtolnay/rust-toolchain@stable
- name: Generate documentation
- name: Generate rustdoc documentation
run: cargo doc --no-deps -p niri-ipc
- run: cp ./resources/rustdoc-index.html ./target/doc/index.html
- run: mkdir -p publish/niri_ipc
- run: cp -r ./target/doc/* ./publish/
- run: cp -r ./docs/site/* ./publish/
- name: Deploy documentation
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./target/doc
publish_dir: ./publish
force_orphan: true
+96
View File
@@ -0,0 +1,96 @@
# Contributing to niri
Thanks for your interest in niri!
The project has grown quite a bit, and we could use all help that we can.
Make sure to join our Matrix chat if you have any questions or want to discuss anything: https://matrix.to/#/#niri:matrix.org
## Issues and discussions
This is a good way to help many new and existing users without programming knowledge.
- Answer and help people in GitHub issues and discussions.
- Check and point out duplicate issues.
- Check for issues that are likely application bugs (and not niri bugs).
- Ask or try to reproduce on another non-Smithay-based compositor (sway, KDE/KWin, GNOME/Mutter). If the issue reproduces, it's likely an application bug.
- Ask or try to reproduce on another *Smithay-based* compositor ([cosmic-comp], [anvil]). If the issue reproduces only on Smithay compositors, it may be a Smithay bug.
- Make sure you're testing the Wayland version of the app on all compositors. Apps may silently use X11 when an X11 `$DISPLAY` is available.
- Problems with X11 apps should be reported to [xwayland-satellite]. When testing xwayland-satellite on different compositors, make sure you use xwayland-satellite's `$DISPLAY` (rather than another compositor's built-in Xwayland `$DISPLAY`).
- After testing, mention where you could and couldn't reproduce, as well as the exact steps to reproduce if the issue is missing them.
- Try to reproduce the issue on your own system and write if you could or couldn't reproduce it.
- Upvote issues with a thumbs up reaction as you like.
- Ideas and feature requests from new users should go to Discussions.
If your issue is a duplicate, or not a niri issue (application bug, hardware problem, configuration problem), then please close it.
## Reviewing and testing pull requests
With the growing popularity, the volume of pull requests is honestly more than I can manage myself in my free time.
I would really appreciate help with testing and reviewing them.
### Testing
Pick a pull request you like, then build it and give it a go.
The [Developing niri wiki page](https://yalter.github.io/niri/Development:-Developing-niri) has guidance on running niri test builds.
Be really thorough with your testing.
We're striving for polished features in niri, so point out any issues and bugs, even small ones like animation jank.
- Think of weird edge cases or unexpected interactions and try them to see that they work reasonably.
- Try to break the feature and check that it behaves well.
- Where applicable, try different input devices: keyboard, mouse, trackpad, tablet, touchscreen.
- Watch out for any new performance drops.
For bug fixes, first make sure you can reproduce the bug, then do the same steps in the PR test build, and verify that the bug is fixed.
Be similarly thorough: test any similar or related edge cases to verify that the fix doesn't introduce any new problems.
Write your findings in the pull request: any issues you found, or if everything worked well.
Re-test after the author updates the code to see that your issues were fixed.
Don't hesitate to test even if someone else already did; very frequently different people will stumble upon different problems.
### Reviewing
Reviewing pull requests is something I need the most help with since there are a lot of them, and it's quite time-consuming.
Anyone with code accepted into niri is welcome, but this is not a requirement; even if you aren't familiar with Rust you may find some logic problems.
Pick a pull request, then review its code.
- Check that everything looks good, check various conditions for edge cases.
- See if there are any scenarios the author forgot to handle.
- Check that the code fits well into the rest of niri, follows its design and code style.
- I understand this is vague. The idea is: look at the surrounding code and at similar modules (e.g. when implementing a new protocol, check other protocol implementations), and try to follow the style and structure.
- Check for unrelated changes that may be better split into their own pull request.
- Check that the wiki had been updated if necessary (for example, new config options were documented with examples, and have a correct Since annotation).
Point out everything you find as review comments (don't forget to submit the review).
Be constructive and respectful; some people may be new to programming and Rust.
As the author addresses the comments and issues, check the code again to see that the problems were fixed.
If everything looks good, say that, so I know someone has reviewed the PR.
As with testing, don't hesitate to look through and comment even if someone else already had.
Extra pairs of eyes catch more problems.
## Writing pull requests
When creating pull requests, please keep the following in mind.
- Make sure new features align with niri's design directions. Ideally, there should be an existing issue or discussion where we settled on that solution.
- Keep pull requests focused on a single feature or bug fix with no unrelated changes.
- Try to split your changes into small, self-contained commits. Every commit should build and pass tests. This makes it much easier to review your PR, and bisect for regressions in the future.
- When addressing PR comments, try to squash the changes straight into the relevant commits.
- In some cases when the requested changes are big/unclear, you can leave them as separate commits on top, but please squash and otherwise clean up the history when the changes are finalized.
- To update the main branch, please rebase instead of merging. Try to force-push the main update rebase separately from other changes, this way it's easy to skip during review since it's usually not interesting.
- When working on bigger features, I usually start with a big messy commit, then gradually split out smaller self-contained changes from it as the code gets into shape.
- [git-rebase.io](https://git-rebase.io/) is a helpful guide for splitting commits and cleaning up history in git.
- When you address a review comment, mark it as resolved.
- Remember to [run tests](https://yalter.github.io/niri/Development:-Developing-niri#tests) and format the code with `cargo +nightly fmt --all`.
- For new layout actions, remember to add them to the randomized tests. For weird Wayland handling, adding client-server tests in `src/tests/` could be very useful.
- Test your changes by hand thoroughly, including for edge cases and weird interactions. See the Testing section above for some tips.
- Remember to document new config options on the wiki.
- When opening a pull request, ensure "Allow edits from maintainers" is enabled, so I can make final tweaks before merging.
[cosmic-comp]: https://github.com/pop-os/cosmic-comp
[anvil]: https://github.com/Smithay/smithay/tree/master/anvil
[xwayland-satellite]: https://github.com/Supreeeme/xwayland-satellite
Generated
+752 -603
View File
File diff suppressed because it is too large Load Diff
+31 -30
View File
@@ -6,7 +6,7 @@ members = [
]
[workspace.package]
version = "25.2.0"
version = "25.5.1"
description = "A scrollable-tiling Wayland compositor"
authors = ["Ivan Molodetskikh <yalterz@gmail.com>"]
license = "GPL-3.0-or-later"
@@ -15,15 +15,15 @@ repository = "https://github.com/YaLTeR/niri"
rust-version = "1.80.1"
[workspace.dependencies]
anyhow = "1.0.97"
bitflags = "2.9.0"
clap = { version = "4.5.34", features = ["derive"] }
insta = "1.42.2"
anyhow = "1.0.99"
bitflags = "2.9.2"
clap = { version = "4.5.45", features = ["derive"] }
insta = "1.43.1"
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
serde_json = "1.0.143"
tracing = { version = "0.1.41", features = ["max_level_trace", "release_max_level_debug"] }
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
tracy-client = { version = "0.18.0", default-features = false }
tracy-client = { version = "0.18.2", default-features = false }
[workspace.dependencies.smithay]
# version = "0.4.1"
@@ -52,34 +52,35 @@ keywords = ["wayland", "compositor", "tiling", "smithay", "wm"]
[dependencies]
anyhow.workspace = true
arrayvec = "0.7.6"
async-channel = "2.3.1"
async-io = { version = "2.4.0", optional = true }
atomic = "0.6.0"
async-channel = "2.5.0"
async-io = { version = "2.5.0", optional = true }
atomic = "0.6.1"
bitflags.workspace = true
bytemuck = { version = "1.22.0", features = ["derive"] }
calloop = { version = "0.14.2", features = ["executor", "futures-io"] }
bytemuck = { version = "1.23.2", features = ["derive"] }
calloop = { version = "0.14.3", features = ["executor", "futures-io", "signals"] }
clap = { workspace = true, features = ["string"] }
clap_complete = "4.5.47"
clap_complete = "4.5.57"
clap_complete_nushell = "4.5.8"
directories = "6.0.0"
drm-ffi = "0.9.0"
fastrand = "2.3.0"
futures-util = { version = "0.3.31", default-features = false, features = ["std", "io"] }
git-version = "0.3.9"
glam = "0.30.1"
glam = "0.30.5"
input = { version = "0.9.1", features = ["libinput_1_21"] }
keyframe = { version = "1.1.1", default-features = false }
libc = "0.2.171"
libc = "0.2.175"
libdisplay-info = "0.2.2"
log = { version = "0.4.27", features = ["max_level_trace", "release_max_level_debug"] }
niri-config = { version = "25.2.0", path = "niri-config" }
niri-ipc = { version = "25.2.0", path = "niri-ipc", features = ["clap"] }
niri-config = { version = "25.5.1", path = "niri-config" }
niri-ipc = { version = "25.5.1", path = "niri-ipc", features = ["clap"] }
ordered-float = "5.0.0"
pango = { version = "0.20.9", features = ["v1_44"] }
pangocairo = "0.20.7"
pango = { version = "0.20.12", features = ["v1_44"] }
pangocairo = "0.20.10"
pipewire = { git = "https://gitlab.freedesktop.org/pipewire/pipewire-rs.git", optional = true, features = ["v0_3_33"] }
png = "0.17.16"
portable-atomic = { version = "1.11.0", default-features = false, features = ["float"] }
profiling = "1.0.16"
portable-atomic = { version = "1.11.1", default-features = false, features = ["float"] }
profiling = "1.0.17"
sd-notify = "0.4.5"
serde.workspace = true
serde_json.workspace = true
@@ -88,10 +89,10 @@ tracing-subscriber.workspace = true
tracing.workspace = true
tracy-client.workspace = true
url = { version = "2.5.4", optional = true }
wayland-backend = "0.3.8"
wayland-scanner = "0.31.6"
xcursor = "0.3.8"
zbus = { version = "5.5.0", optional = true }
wayland-backend = "0.3.11"
wayland-scanner = "0.31.7"
xcursor = "0.3.10"
zbus = { version = "5.9.0", optional = true }
[dependencies.smithay]
workspace = true
@@ -115,10 +116,10 @@ features = [
approx = "0.5.1"
calloop-wayland-source = "0.4.0"
insta.workspace = true
proptest = "1.6.0"
proptest-derive = { version = "0.5.1", features = ["boxed_union"] }
rayon = "1.10.0"
wayland-client = "0.31.8"
proptest = "1.7.0"
proptest-derive = { version = "0.6.0", features = ["boxed_union"] }
rayon = "1.11.0"
wayland-client = "0.31.11"
xshell = "0.2.7"
[features]
@@ -152,7 +153,7 @@ insta.opt-level = 3
similar.opt-level = 3
[package.metadata.generate-rpm]
version = "25.02"
version = "25.05.1"
assets = [
{ source = "target/release/niri", dest = "/usr/bin/", mode = "755" },
{ source = "resources/niri-session", dest = "/usr/bin/", mode = "755" },
+43 -21
View File
@@ -7,10 +7,10 @@
</p>
<p align="center">
<a href="https://github.com/YaLTeR/niri/wiki/Getting-Started">Getting Started</a> | <a href="https://github.com/YaLTeR/niri/wiki/Configuration:-Overview">Configuration</a> | <a href="https://github.com/YaLTeR/niri/discussions/325">Setup&nbsp;Showcase</a>
<a href="https://yalter.github.io/niri/Getting-Started.html">Getting Started</a> | <a href="https://yalter.github.io/niri/Configuration%3A-Introduction.html">Configuration</a> | <a href="https://github.com/YaLTeR/niri/discussions/325">Setup&nbsp;Showcase</a>
</p>
![niri with a few windows open](https://github.com/user-attachments/assets/d142e57d-a25d-4ddb-ab46-311417458211)
![niri with a few windows open](https://github.com/user-attachments/assets/535e6530-2f44-4b84-a883-1240a3eee6e9)
## About
@@ -29,14 +29,16 @@ When a monitor disconnects, its workspaces will move to another monitor, but upo
## Features
- Built from the ground up for scrollable tiling
- [Dynamic workspaces](https://github.com/YaLTeR/niri/wiki/Workspaces) like in GNOME
- [Dynamic workspaces](https://yalter.github.io/niri/Workspaces.html) like in GNOME
- An [Overview](https://github.com/user-attachments/assets/379a5d1f-acdb-4c11-b36c-e85fd91f0995) that zooms out workspaces and windows
- Built-in screenshot UI
- Monitor and window screencasting through xdg-desktop-portal-gnome
- You can [block out](https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules#block-out-from) sensitive windows from screencasts
- You can [block out](https://yalter.github.io/niri/Configuration%3A-Window-Rules.html#block-out-from) sensitive windows from screencasts
- [Dynamic cast target](https://yalter.github.io/niri/Screencasting.html#dynamic-screencast-target) that can change what it shows on the go
- [Touchpad](https://github.com/YaLTeR/niri/assets/1794388/946a910e-9bec-4cd1-a923-4a9421707515) and [mouse](https://github.com/YaLTeR/niri/assets/1794388/8464e65d-4bf2-44fa-8c8e-5883355bd000) gestures
- Group windows into [tabs](https://github.com/YaLTeR/niri/wiki/Tabs)
- Group windows into [tabs](https://yalter.github.io/niri/Tabs.html)
- Configurable layout: gaps, borders, struts, window sizes
- [Gradient borders](https://github.com/YaLTeR/niri/wiki/Configuration:-Layout#gradients) with Oklab and Oklch support
- [Gradient borders](https://yalter.github.io/niri/Configuration%3A-Layout.html#gradients) with Oklab and Oklch support
- [Animations](https://github.com/YaLTeR/niri/assets/1794388/ce178da2-af9e-4c51-876f-8709c241d95e) with support for [custom shaders](https://github.com/YaLTeR/niri/assets/1794388/27a238d6-0a22-4692-b794-30dc7a626fad)
- Live-reloading config
@@ -44,14 +46,17 @@ When a monitor disconnects, its workspaces will move to another monitor, but upo
https://github.com/YaLTeR/niri/assets/1794388/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](https://youtu.be/DeYx2exm04M)
## 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](https://github.com/YaLTeR/niri/wiki/Getting-Started) wiki page.
Follow the instructions on the [Getting Started](https://yalter.github.io/niri/Getting-Started.html) page.
Have your [waybar]s and [fuzzel]s ready: niri is not a complete desktop environment.
Also check out [awesome-niri], a list of niri-related links and projects.
Here are some points you may have questions about:
@@ -66,15 +71,36 @@ We have touchpad gestures, but no touchscreen gestures yet.
You can check on [wayland.app](https://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](https://github.com/YaLTeR/niri/wiki/Xwayland#using-xwayland-satellite) and works very well.
- **Xwayland**: no built-in support, but xwayland-satellite is [easy to set up](https://yalter.github.io/niri/Xwayland.html#using-xwayland-satellite) 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](https://github.com/YaLTeR/niri/wiki/Xwayland#using-the-labwc-wayland-compositor) or [rootful Xwayland](https://github.com/YaLTeR/niri/wiki/Xwayland#directly-running-xwayland-in-rootful-mode).
- Display scaling (integer or fractional) will make X11 apps look blurry; this needs to be supported in xwayland-satellite.
- 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](https://yalter.github.io/niri/Xwayland.html#using-the-labwc-wayland-compositor) or [rootful Xwayland](https://yalter.github.io/niri/Xwayland.html#directly-running-xwayland-in-rootful-mode).
- 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](https://youtu.be/Kmz8ODolnDg?list=PLRdS-n5seLRqrmWDQY4KDqtRMfIwU0U3T) · *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](https://www.trommelspeicher.de/podcast/special_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](https://lwn.net/Articles/1025866/) · *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](https://github.com/YaLTeR/niri/blob/main/CONTRIBUTING.md) for an overview.
## Inspiration
Niri is heavily inspired by [PaperWM] which implements scrollable tiling on top of GNOME Shell.
@@ -88,27 +114,23 @@ Here are some other projects which implement a similar workflow:
- [PaperWM]: scrollable tiling on top of GNOME Shell.
- [karousel]: scrollable tiling on top of KDE.
- [papersway]: scrollable tiling on top of sway/i3.
- [hyprscroller] and [hyprslidr]: scrollable tiling on top of Hyprland.
- [scroll](https://github.com/dawsers/scroll) and [papersway]: scrollable tiling on top of sway/i3.
- [hyprscrolling] and [hyprslidr]: scrollable tiling on top of Hyprland.
- [PaperWM.spoon]: scrollable tiling on top of macOS.
## Media
[niri: Making a Wayland compositor in Rust](https://youtu.be/Kmz8ODolnDg?list=PLRdS-n5seLRqrmWDQY4KDqtRMfIwU0U3T)
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.
## Contact
We have a Matrix chat, feel free to join and ask a question: https://matrix.to/#/#niri:matrix.org
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
[PaperWM]: https://github.com/paperwm/PaperWM
[waybar]: https://github.com/Alexays/Waybar
[fuzzel]: https://codeberg.org/dnkl/fuzzel
[awesome-niri]: https://github.com/Vortriz/awesome-niri
[karousel]: https://github.com/peterfajdiga/karousel
[papersway]: https://spwhitton.name/tech/code/papersway/
[hyprscroller]: https://github.com/dawsers/hyprscroller
[hyprscrolling]: https://github.com/hyprwm/hyprland-plugins/tree/main/hyprscrolling
[hyprslidr]: https://gitlab.com/magus/hyprslidr
[PaperWM.spoon]: https://github.com/mogenson/PaperWM.spoon
[Matrix channel]: https://matrix.to/#/#niri:matrix.org
+2
View File
@@ -0,0 +1,2 @@
site
__pycache__
+19
View File
@@ -0,0 +1,19 @@
from __future__ import annotations
import re
# todo: this could be done generically, so that any
# ```language,annotation,anything-else
# is reduced to
# ```language
# which is what's supported by mkdocs/pygments
# also note: mkdocs provides ways to highlight lines, add line numbers
# but these are added as
# ```language linenums="1"
# and not split by comma
def on_page_markdown(
markdown: str, *, page, config, files
):
return re.sub(
r",must-fail",
'', markdown, flags = re.I | re.M
)
+44
View File
@@ -0,0 +1,44 @@
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
from __future__ import annotations
import re
from re import Match
def on_page_markdown(
markdown: str, *, page, config, files
):
def replace(match: Match):
matches = match.groups()
preposition, version = matches[0], matches[1]
return _badge_for_version(preposition, version)
return re.sub(
r"<sup>(Until|Since): (.*?)</sup>",
replace, markdown, flags = re.I | re.M
)
def _badge_for_version(preposition: str, version: str):
if version == "next release":
# we might fail to make real links to release notes on other cases too, but for now this is the one i've found
return f"<span class=\"badge\">{preposition}: {version}</span>"
else:
path = f"https://github.com/YaLTeR/niri/releases/tag/v{version}"
return f"<span class=\"badge\">[{preposition}: {version}]({path})</span>"
+109
View File
@@ -0,0 +1,109 @@
site_name: niri
docs_dir: wiki
site_url: https://yalter.github.io/niri
repo_url: https://github.com/YaLTeR/niri
edit_uri: edit/main/docs/wiki/
use_directory_urls: false
theme:
name: material
logo: _assets/icons/logo.svg
favicon: _assets/icons/logo.svg
features:
- navigation.instant
- search.suggest
- content.code.copy
- content.action.edit
palette:
- media: "(prefers-color-scheme)"
primary: custom
toggle:
icon: material/brightness-auto
name: Switch to light mode
- media: "(prefers-color-scheme: light)"
primary: custom
scheme: default
toggle:
icon: material/brightness-7
name: Switch to dark mode
- media: "(prefers-color-scheme: dark)"
primary: custom
scheme: slate
toggle:
icon: material/brightness-4
name: Switch to system preference
markdown_extensions:
- github-callouts
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.magiclink
- pymdownx.snippets
- pymdownx.superfences
- pymdownx.keys
- toc:
permalink: '#'
plugins:
- search
hooks:
- hooks/shortcodes.py
- hooks/remove-must-fail.py
extra_css:
- _assets/stylesheets/niri.css
strict: true
validation:
nav:
omitted_files: warn
not_found: warn
absolute_links: relative_to_docs
links:
not_found: warn
anchors: warn
absolute_links: relative_to_docs
unrecognized_links: warn
not_in_nav: |
_Sidebar.md
Configuration:-Overview.md
README.md
# ah, wouldn't it be nice if we could autogenerate this with wiki/_Sidebar.md
nav:
- Usage:
- Getting Started: Getting-Started.md
- Example systemd Setup: Example-systemd-Setup.md
- Important Software: Important-Software.md
- Workspaces: Workspaces.md
- Floating Windows: Floating-Windows.md
- Tabs: Tabs.md
- Overview: Overview.md
- Screencasting: Screencasting.md
- LayerShell Components: LayerShell-Components.md
- IPC, niri msg: IPC.md
- Application-Specific Issues: Application-Issues.md
- Nvidia: Nvidia.md
- Xwayland: Xwayland.md
- Gestures: Gestures.md
- Packaging niri: Packaging-niri.md
- FAQ: FAQ.md
- Configuration:
- Introduction: Configuration:-Introduction.md
- Input: Configuration:-Input.md
- Outputs: Configuration:-Outputs.md
- Key Bindings: Configuration:-Key-Bindings.md
- Switch Events: Configuration:-Switch-Events.md
- Layout: Configuration:-Layout.md
- Named Workspaces: Configuration:-Named-Workspaces.md
- Miscellaneous: Configuration:-Miscellaneous.md
- Window Rules: Configuration:-Window-Rules.md
- Layer Rules: Configuration:-Layer-Rules.md
- Animations: Configuration:-Animations.md
- Gestures: Configuration:-Gestures.md
- Debug Options: Configuration:-Debug-Options.md
- Development:
- Design Principles: Development:-Design-Principles.md
- Developing niri: Development:-Developing-niri.md
- Documenting niri: Development:-Documenting-niri.md
- Fractional Layout: Development:-Fractional-Layout.md
- Redraw Loop: Development:-Redraw-Loop.md
- Animation Timing: Development:-Animation-Timing.md
+14
View File
@@ -0,0 +1,14 @@
[project]
name = "niri-docs"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
"markdown-callouts>=0.4.0",
"mkdocs-material>=9.6.15",
"pygments",
]
# for KDL highlighting support
# TODO: use the official pygments package once https://github.com/pygments/pygments/pull/2936 is merged
[tool.uv.sources]
pygments = { git = "https://github.com/chinatsu/pygments", rev = "0f0b0d4da2839e1285881389155bb4605a0a6dc4" }
Generated
+511
View File
@@ -0,0 +1,511 @@
version = 1
revision = 3
requires-python = ">=3.10"
[[package]]
name = "babel"
version = "2.17.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" },
]
[[package]]
name = "backrefs"
version = "5.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/eb/a7/312f673df6a79003279e1f55619abbe7daebbb87c17c976ddc0345c04c7b/backrefs-5.9.tar.gz", hash = "sha256:808548cb708d66b82ee231f962cb36faaf4f2baab032f2fbb783e9c2fdddaa59", size = 5765857, upload-time = "2025-06-22T19:34:13.97Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/19/4d/798dc1f30468134906575156c089c492cf79b5a5fd373f07fe26c4d046bf/backrefs-5.9-py310-none-any.whl", hash = "sha256:db8e8ba0e9de81fcd635f440deab5ae5f2591b54ac1ebe0550a2ca063488cd9f", size = 380267, upload-time = "2025-06-22T19:34:05.252Z" },
{ url = "https://files.pythonhosted.org/packages/55/07/f0b3375bf0d06014e9787797e6b7cc02b38ac9ff9726ccfe834d94e9991e/backrefs-5.9-py311-none-any.whl", hash = "sha256:6907635edebbe9b2dc3de3a2befff44d74f30a4562adbb8b36f21252ea19c5cf", size = 392072, upload-time = "2025-06-22T19:34:06.743Z" },
{ url = "https://files.pythonhosted.org/packages/9d/12/4f345407259dd60a0997107758ba3f221cf89a9b5a0f8ed5b961aef97253/backrefs-5.9-py312-none-any.whl", hash = "sha256:7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa", size = 397947, upload-time = "2025-06-22T19:34:08.172Z" },
{ url = "https://files.pythonhosted.org/packages/10/bf/fa31834dc27a7f05e5290eae47c82690edc3a7b37d58f7fb35a1bdbf355b/backrefs-5.9-py313-none-any.whl", hash = "sha256:cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b", size = 399843, upload-time = "2025-06-22T19:34:09.68Z" },
{ url = "https://files.pythonhosted.org/packages/fc/24/b29af34b2c9c41645a9f4ff117bae860291780d73880f449e0b5d948c070/backrefs-5.9-py314-none-any.whl", hash = "sha256:df5e169836cc8acb5e440ebae9aad4bf9d15e226d3bad049cf3f6a5c20cc8dc9", size = 411762, upload-time = "2025-06-22T19:34:11.037Z" },
{ url = "https://files.pythonhosted.org/packages/41/ff/392bff89415399a979be4a65357a41d92729ae8580a66073d8ec8d810f98/backrefs-5.9-py39-none-any.whl", hash = "sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60", size = 380265, upload-time = "2025-06-22T19:34:12.405Z" },
]
[[package]]
name = "certifi"
version = "2025.7.14"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b3/76/52c535bcebe74590f296d6c77c86dabf761c41980e1347a2422e4aa2ae41/certifi-2025.7.14.tar.gz", hash = "sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995", size = 163981, upload-time = "2025-07-14T03:29:28.449Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/4f/52/34c6cf5bb9285074dc3531c437b3919e825d976fde097a7a73f79e726d03/certifi-2025.7.14-py3-none-any.whl", hash = "sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2", size = 162722, upload-time = "2025-07-14T03:29:26.863Z" },
]
[[package]]
name = "charset-normalizer"
version = "3.4.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/95/28/9901804da60055b406e1a1c5ba7aac1276fb77f1dde635aabfc7fd84b8ab/charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", size = 201818, upload-time = "2025-05-02T08:31:46.725Z" },
{ url = "https://files.pythonhosted.org/packages/d9/9b/892a8c8af9110935e5adcbb06d9c6fe741b6bb02608c6513983048ba1a18/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", size = 144649, upload-time = "2025-05-02T08:31:48.889Z" },
{ url = "https://files.pythonhosted.org/packages/7b/a5/4179abd063ff6414223575e008593861d62abfc22455b5d1a44995b7c101/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", size = 155045, upload-time = "2025-05-02T08:31:50.757Z" },
{ url = "https://files.pythonhosted.org/packages/3b/95/bc08c7dfeddd26b4be8c8287b9bb055716f31077c8b0ea1cd09553794665/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", size = 147356, upload-time = "2025-05-02T08:31:52.634Z" },
{ url = "https://files.pythonhosted.org/packages/a8/2d/7a5b635aa65284bf3eab7653e8b4151ab420ecbae918d3e359d1947b4d61/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", size = 149471, upload-time = "2025-05-02T08:31:56.207Z" },
{ url = "https://files.pythonhosted.org/packages/ae/38/51fc6ac74251fd331a8cfdb7ec57beba8c23fd5493f1050f71c87ef77ed0/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", size = 151317, upload-time = "2025-05-02T08:31:57.613Z" },
{ url = "https://files.pythonhosted.org/packages/b7/17/edee1e32215ee6e9e46c3e482645b46575a44a2d72c7dfd49e49f60ce6bf/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", size = 146368, upload-time = "2025-05-02T08:31:59.468Z" },
{ url = "https://files.pythonhosted.org/packages/26/2c/ea3e66f2b5f21fd00b2825c94cafb8c326ea6240cd80a91eb09e4a285830/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", size = 154491, upload-time = "2025-05-02T08:32:01.219Z" },
{ url = "https://files.pythonhosted.org/packages/52/47/7be7fa972422ad062e909fd62460d45c3ef4c141805b7078dbab15904ff7/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", size = 157695, upload-time = "2025-05-02T08:32:03.045Z" },
{ url = "https://files.pythonhosted.org/packages/2f/42/9f02c194da282b2b340f28e5fb60762de1151387a36842a92b533685c61e/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", size = 154849, upload-time = "2025-05-02T08:32:04.651Z" },
{ url = "https://files.pythonhosted.org/packages/67/44/89cacd6628f31fb0b63201a618049be4be2a7435a31b55b5eb1c3674547a/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", size = 150091, upload-time = "2025-05-02T08:32:06.719Z" },
{ url = "https://files.pythonhosted.org/packages/1f/79/4b8da9f712bc079c0f16b6d67b099b0b8d808c2292c937f267d816ec5ecc/charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", size = 98445, upload-time = "2025-05-02T08:32:08.66Z" },
{ url = "https://files.pythonhosted.org/packages/7d/d7/96970afb4fb66497a40761cdf7bd4f6fca0fc7bafde3a84f836c1f57a926/charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", size = 105782, upload-time = "2025-05-02T08:32:10.46Z" },
{ url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", size = 198794, upload-time = "2025-05-02T08:32:11.945Z" },
{ url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", size = 142846, upload-time = "2025-05-02T08:32:13.946Z" },
{ url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", size = 153350, upload-time = "2025-05-02T08:32:15.873Z" },
{ url = "https://files.pythonhosted.org/packages/df/68/a576b31b694d07b53807269d05ec3f6f1093e9545e8607121995ba7a8313/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", size = 145657, upload-time = "2025-05-02T08:32:17.283Z" },
{ url = "https://files.pythonhosted.org/packages/92/9b/ad67f03d74554bed3aefd56fe836e1623a50780f7c998d00ca128924a499/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f", size = 147260, upload-time = "2025-05-02T08:32:18.807Z" },
{ url = "https://files.pythonhosted.org/packages/a6/e6/8aebae25e328160b20e31a7e9929b1578bbdc7f42e66f46595a432f8539e/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", size = 149164, upload-time = "2025-05-02T08:32:20.333Z" },
{ url = "https://files.pythonhosted.org/packages/8b/f2/b3c2f07dbcc248805f10e67a0262c93308cfa149a4cd3d1fe01f593e5fd2/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", size = 144571, upload-time = "2025-05-02T08:32:21.86Z" },
{ url = "https://files.pythonhosted.org/packages/60/5b/c3f3a94bc345bc211622ea59b4bed9ae63c00920e2e8f11824aa5708e8b7/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", size = 151952, upload-time = "2025-05-02T08:32:23.434Z" },
{ url = "https://files.pythonhosted.org/packages/e2/4d/ff460c8b474122334c2fa394a3f99a04cf11c646da895f81402ae54f5c42/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", size = 155959, upload-time = "2025-05-02T08:32:24.993Z" },
{ url = "https://files.pythonhosted.org/packages/a2/2b/b964c6a2fda88611a1fe3d4c400d39c66a42d6c169c924818c848f922415/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", size = 153030, upload-time = "2025-05-02T08:32:26.435Z" },
{ url = "https://files.pythonhosted.org/packages/59/2e/d3b9811db26a5ebf444bc0fa4f4be5aa6d76fc6e1c0fd537b16c14e849b6/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", size = 148015, upload-time = "2025-05-02T08:32:28.376Z" },
{ url = "https://files.pythonhosted.org/packages/90/07/c5fd7c11eafd561bb51220d600a788f1c8d77c5eef37ee49454cc5c35575/charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", size = 98106, upload-time = "2025-05-02T08:32:30.281Z" },
{ url = "https://files.pythonhosted.org/packages/a8/05/5e33dbef7e2f773d672b6d79f10ec633d4a71cd96db6673625838a4fd532/charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", size = 105402, upload-time = "2025-05-02T08:32:32.191Z" },
{ url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936, upload-time = "2025-05-02T08:32:33.712Z" },
{ url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790, upload-time = "2025-05-02T08:32:35.768Z" },
{ url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924, upload-time = "2025-05-02T08:32:37.284Z" },
{ url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626, upload-time = "2025-05-02T08:32:38.803Z" },
{ url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567, upload-time = "2025-05-02T08:32:40.251Z" },
{ url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957, upload-time = "2025-05-02T08:32:41.705Z" },
{ url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408, upload-time = "2025-05-02T08:32:43.709Z" },
{ url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399, upload-time = "2025-05-02T08:32:46.197Z" },
{ url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815, upload-time = "2025-05-02T08:32:48.105Z" },
{ url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537, upload-time = "2025-05-02T08:32:49.719Z" },
{ url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565, upload-time = "2025-05-02T08:32:51.404Z" },
{ url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357, upload-time = "2025-05-02T08:32:53.079Z" },
{ url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776, upload-time = "2025-05-02T08:32:54.573Z" },
{ url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" },
{ url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" },
{ url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" },
{ url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" },
{ url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" },
{ url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" },
{ url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" },
{ url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" },
{ url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" },
{ url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" },
{ url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" },
{ url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" },
{ url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" },
{ url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" },
]
[[package]]
name = "click"
version = "8.2.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" },
]
[[package]]
name = "colorama"
version = "0.4.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
]
[[package]]
name = "ghp-import"
version = "2.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "python-dateutil" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943, upload-time = "2022-05-02T15:47:16.11Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" },
]
[[package]]
name = "idna"
version = "3.10"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
]
[[package]]
name = "jinja2"
version = "3.1.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markupsafe" },
]
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
]
[[package]]
name = "markdown"
version = "3.8.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d7/c2/4ab49206c17f75cb08d6311171f2d65798988db4360c4d1485bd0eedd67c/markdown-3.8.2.tar.gz", hash = "sha256:247b9a70dd12e27f67431ce62523e675b866d254f900c4fe75ce3dda62237c45", size = 362071, upload-time = "2025-06-19T17:12:44.483Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/96/2b/34cc11786bc00d0f04d0f5fdc3a2b1ae0b6239eef72d3d345805f9ad92a1/markdown-3.8.2-py3-none-any.whl", hash = "sha256:5c83764dbd4e00bdd94d85a19b8d55ccca20fe35b2e678a1422b380324dd5f24", size = 106827, upload-time = "2025-06-19T17:12:42.994Z" },
]
[[package]]
name = "markdown-callouts"
version = "0.4.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markdown" },
]
sdist = { url = "https://files.pythonhosted.org/packages/87/73/ae5aa379f6f7fea9d0bf4cba888f9a31d451d90f80033ae60ae3045770d5/markdown_callouts-0.4.0.tar.gz", hash = "sha256:7ed2c90486967058a73a547781121983839522d67041ae52c4979616f1b2b746", size = 9768, upload-time = "2024-01-22T23:18:18.513Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1d/b5/7b0a0a52c82bfccd830af2a8cc8add1c5bc932e0204922434954a631dd51/markdown_callouts-0.4.0-py3-none-any.whl", hash = "sha256:ed0da38f29158d93116a0d0c6ecaf9df90b37e0d989b5337d678ee6e6d6550b7", size = 7108, upload-time = "2024-01-22T23:18:17.465Z" },
]
[[package]]
name = "markupsafe"
version = "3.0.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357, upload-time = "2024-10-18T15:20:51.44Z" },
{ url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", size = 12393, upload-time = "2024-10-18T15:20:52.426Z" },
{ url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", size = 21732, upload-time = "2024-10-18T15:20:53.578Z" },
{ url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", size = 20866, upload-time = "2024-10-18T15:20:55.06Z" },
{ url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", size = 20964, upload-time = "2024-10-18T15:20:55.906Z" },
{ url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", size = 21977, upload-time = "2024-10-18T15:20:57.189Z" },
{ url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", size = 21366, upload-time = "2024-10-18T15:20:58.235Z" },
{ url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", size = 21091, upload-time = "2024-10-18T15:20:59.235Z" },
{ url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50", size = 15065, upload-time = "2024-10-18T15:21:00.307Z" },
{ url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", size = 15514, upload-time = "2024-10-18T15:21:01.122Z" },
{ url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353, upload-time = "2024-10-18T15:21:02.187Z" },
{ url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392, upload-time = "2024-10-18T15:21:02.941Z" },
{ url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984, upload-time = "2024-10-18T15:21:03.953Z" },
{ url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120, upload-time = "2024-10-18T15:21:06.495Z" },
{ url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032, upload-time = "2024-10-18T15:21:07.295Z" },
{ url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057, upload-time = "2024-10-18T15:21:08.073Z" },
{ url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359, upload-time = "2024-10-18T15:21:09.318Z" },
{ url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306, upload-time = "2024-10-18T15:21:10.185Z" },
{ url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094, upload-time = "2024-10-18T15:21:11.005Z" },
{ url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521, upload-time = "2024-10-18T15:21:12.911Z" },
{ url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" },
{ url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" },
{ url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" },
{ url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" },
{ url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" },
{ url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" },
{ url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" },
{ url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" },
{ url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" },
{ url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" },
{ url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" },
{ url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" },
{ url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" },
{ url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" },
{ url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" },
{ url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" },
{ url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" },
{ url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" },
{ url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" },
{ url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" },
{ url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" },
{ url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" },
{ url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" },
{ url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" },
{ url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" },
{ url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" },
{ url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" },
{ url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" },
{ url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" },
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" },
]
[[package]]
name = "mergedeep"
version = "1.3.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661, upload-time = "2021-02-05T18:55:30.623Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" },
]
[[package]]
name = "mkdocs"
version = "1.6.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
{ name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "ghp-import" },
{ name = "jinja2" },
{ name = "markdown" },
{ name = "markupsafe" },
{ name = "mergedeep" },
{ name = "mkdocs-get-deps" },
{ name = "packaging" },
{ name = "pathspec" },
{ name = "pyyaml" },
{ name = "pyyaml-env-tag" },
{ name = "watchdog" },
]
sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159, upload-time = "2024-08-30T12:24:06.899Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451, upload-time = "2024-08-30T12:24:05.054Z" },
]
[[package]]
name = "mkdocs-get-deps"
version = "0.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mergedeep" },
{ name = "platformdirs" },
{ name = "pyyaml" },
]
sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239, upload-time = "2023-11-20T17:51:09.981Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521, upload-time = "2023-11-20T17:51:08.587Z" },
]
[[package]]
name = "mkdocs-material"
version = "9.6.15"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "babel" },
{ name = "backrefs" },
{ name = "colorama" },
{ name = "jinja2" },
{ name = "markdown" },
{ name = "mkdocs" },
{ name = "mkdocs-material-extensions" },
{ name = "paginate" },
{ name = "pygments" },
{ name = "pymdown-extensions" },
{ name = "requests" },
]
sdist = { url = "https://files.pythonhosted.org/packages/95/c1/f804ba2db2ddc2183e900befe7dad64339a34fa935034e1ab405289d0a97/mkdocs_material-9.6.15.tar.gz", hash = "sha256:64adf8fa8dba1a17905b6aee1894a5aafd966d4aeb44a11088519b0f5ca4f1b5", size = 3951836, upload-time = "2025-07-01T10:14:15.671Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1d/30/dda19f0495a9096b64b6b3c07c4bfcff1c76ee0fc521086d53593f18b4c0/mkdocs_material-9.6.15-py3-none-any.whl", hash = "sha256:ac969c94d4fe5eb7c924b6d2f43d7db41159ea91553d18a9afc4780c34f2717a", size = 8716840, upload-time = "2025-07-01T10:14:13.18Z" },
]
[[package]]
name = "mkdocs-material-extensions"
version = "1.3.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847, upload-time = "2023-11-22T19:09:45.208Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728, upload-time = "2023-11-22T19:09:43.465Z" },
]
[[package]]
name = "niri-docs"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "markdown-callouts" },
{ name = "mkdocs-material" },
{ name = "pygments" },
]
[package.metadata]
requires-dist = [
{ name = "markdown-callouts", specifier = ">=0.4.0" },
{ name = "mkdocs-material", specifier = ">=9.6.15" },
{ name = "pygments", git = "https://github.com/chinatsu/pygments?rev=0f0b0d4da2839e1285881389155bb4605a0a6dc4" },
]
[[package]]
name = "packaging"
version = "25.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
]
[[package]]
name = "paginate"
version = "0.5.7"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252, upload-time = "2024-08-25T14:17:24.139Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746, upload-time = "2024-08-25T14:17:22.55Z" },
]
[[package]]
name = "pathspec"
version = "0.12.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" },
]
[[package]]
name = "platformdirs"
version = "4.3.8"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" },
]
[[package]]
name = "pygments"
version = "2.19.2"
source = { git = "https://github.com/chinatsu/pygments?rev=0f0b0d4da2839e1285881389155bb4605a0a6dc4#0f0b0d4da2839e1285881389155bb4605a0a6dc4" }
[[package]]
name = "pymdown-extensions"
version = "10.16"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markdown" },
{ name = "pyyaml" },
]
sdist = { url = "https://files.pythonhosted.org/packages/1a/0a/c06b542ac108bfc73200677309cd9188a3a01b127a63f20cadc18d873d88/pymdown_extensions-10.16.tar.gz", hash = "sha256:71dac4fca63fabeffd3eb9038b756161a33ec6e8d230853d3cecf562155ab3de", size = 853197, upload-time = "2025-06-21T17:56:36.974Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/98/d4/10bb14004d3c792811e05e21b5e5dcae805aacb739bd12a0540967b99592/pymdown_extensions-10.16-py3-none-any.whl", hash = "sha256:f5dd064a4db588cb2d95229fc4ee63a1b16cc8b4d0e6145c0899ed8723da1df2", size = 266143, upload-time = "2025-06-21T17:56:35.356Z" },
]
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
]
[[package]]
name = "pyyaml"
version = "6.0.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199, upload-time = "2024-08-06T20:31:40.178Z" },
{ url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758, upload-time = "2024-08-06T20:31:42.173Z" },
{ url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463, upload-time = "2024-08-06T20:31:44.263Z" },
{ url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280, upload-time = "2024-08-06T20:31:50.199Z" },
{ url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239, upload-time = "2024-08-06T20:31:52.292Z" },
{ url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802, upload-time = "2024-08-06T20:31:53.836Z" },
{ url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527, upload-time = "2024-08-06T20:31:55.565Z" },
{ url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052, upload-time = "2024-08-06T20:31:56.914Z" },
{ url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774, upload-time = "2024-08-06T20:31:58.304Z" },
{ url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" },
{ url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" },
{ url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" },
{ url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" },
{ url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" },
{ url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" },
{ url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" },
{ url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" },
{ url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" },
{ url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" },
{ url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" },
{ url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" },
{ url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" },
{ url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" },
{ url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" },
{ url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" },
{ url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" },
{ url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" },
{ url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" },
{ url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" },
{ url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" },
{ url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" },
{ url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" },
{ url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" },
{ url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" },
{ url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" },
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" },
]
[[package]]
name = "pyyaml-env-tag"
version = "1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyyaml" },
]
sdist = { url = "https://files.pythonhosted.org/packages/eb/2e/79c822141bfd05a853236b504869ebc6b70159afc570e1d5a20641782eaa/pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff", size = 5737, upload-time = "2025-05-13T15:24:01.64Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04", size = 4722, upload-time = "2025-05-13T15:23:59.629Z" },
]
[[package]]
name = "requests"
version = "2.32.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "charset-normalizer" },
{ name = "idna" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" },
]
[[package]]
name = "six"
version = "1.17.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
]
[[package]]
name = "urllib3"
version = "2.5.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" },
]
[[package]]
name = "watchdog"
version = "6.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0c/56/90994d789c61df619bfc5ce2ecdabd5eeff564e1eb47512bd01b5e019569/watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26", size = 96390, upload-time = "2024-11-01T14:06:24.793Z" },
{ url = "https://files.pythonhosted.org/packages/55/46/9a67ee697342ddf3c6daa97e3a587a56d6c4052f881ed926a849fcf7371c/watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112", size = 88389, upload-time = "2024-11-01T14:06:27.112Z" },
{ url = "https://files.pythonhosted.org/packages/44/65/91b0985747c52064d8701e1075eb96f8c40a79df889e59a399453adfb882/watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3", size = 89020, upload-time = "2024-11-01T14:06:29.876Z" },
{ url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" },
{ url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" },
{ url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" },
{ url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471, upload-time = "2024-11-01T14:06:37.745Z" },
{ url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449, upload-time = "2024-11-01T14:06:39.748Z" },
{ url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054, upload-time = "2024-11-01T14:06:41.009Z" },
{ url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" },
{ url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" },
{ url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" },
{ url = "https://files.pythonhosted.org/packages/30/ad/d17b5d42e28a8b91f8ed01cb949da092827afb9995d4559fd448d0472763/watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881", size = 87902, upload-time = "2024-11-01T14:06:53.119Z" },
{ url = "https://files.pythonhosted.org/packages/5c/ca/c3649991d140ff6ab67bfc85ab42b165ead119c9e12211e08089d763ece5/watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11", size = 88380, upload-time = "2024-11-01T14:06:55.19Z" },
{ url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" },
{ url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" },
{ url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" },
{ url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" },
{ url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" },
{ url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" },
{ url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" },
{ url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" },
{ url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" },
{ url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" },
]
@@ -52,6 +52,11 @@ To fix this, run them with the `_JAVA_AWT_WM_NONREPARENTING=1` environment varia
There's a bug in rofi-wayland that prevents it from accepting keyboard input on niri with errors in the output.
It's been fixed in rofi, but [the fix had not been released yet](https://github.com/davatorium/rofi/discussions/2008).
### Zen Browser
For some reason, DMABUF screencasts are disabled in the Zen Browser, so screencasting doesn't work out of the box on niri.
To fix it, open `about:config` and set `widget.dmabuf.force-enabled` to `true`.
### Fullscreen games
Some video games, both Linux-native and on Wine, have various issues when using non-stacking desktop environments.
@@ -77,6 +82,8 @@ On some systems, Steam will show a fully black window.
To fix this, navigate to Settings -> Interface (via Steam's tray icon, or by blindly finding the Steam menu at the top left of the window), then **disable** GPU accelerated rendering in web views.
Restart Steam and it should now work fine.
If you do not want to disable GPU accelerated rendering you can instead try to pass the launch argument `-system-composer` instead.
Steam notifications don't run through the standard notification daemon and show up as floating windows in the center of the screen.
You can move them to a more convenient location by adding a window rule in your niri config:
@@ -50,6 +50,10 @@ animations {
duration-ms 200
curve "ease-out-quad"
}
overview-open-close {
spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
}
}
```
@@ -159,7 +163,7 @@ animations {
##### `custom-shader`
<sup>Since: 0.1.6, experimental</sup>
<sup>Since: 0.1.6</sup>
You can write a custom shader for drawing the window during an open animation.
@@ -219,7 +223,7 @@ animations {
##### `custom-shader`
<sup>Since: 0.1.6, experimental</sup>
<sup>Since: 0.1.6</sup>
You can write a custom shader for drawing the window during a close animation.
@@ -315,7 +319,7 @@ animations {
##### `custom-shader`
<sup>Since: 0.1.6, experimental</sup>
<sup>Since: 0.1.6</sup>
You can write a custom shader for drawing the window during a resize animation.
@@ -374,6 +378,20 @@ animations {
}
```
#### `overview-open-close`
<sup>Since: 25.05</sup>
The open/close zoom animation of the [Overview](./Overview.md).
```kdl
animations {
overview-open-close {
spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
}
}
```
### Synchronized Animations
<sup>Since: 0.1.5</sup>
@@ -4,7 +4,7 @@ Niri has several options that are only useful for debugging, or are experimental
They are not meant for normal use.
> [!CAUTION]
> These options are **not** covered by the [config breaking change policy](./Configuration:-Overview.md#breaking-change-policy).
> These options are **not** covered by the [config breaking change policy](./Configuration:-Introduction.md#breaking-change-policy).
> They can change or stop working at any point with little notice.
Here are all the options at a glance:
@@ -21,14 +21,16 @@ debug {
force-pipewire-invalid-modifier
dbus-interfaces-in-non-session-instances
wait-for-frame-completion-before-queueing
wait-for-frame-completion-in-pipewire
emulate-zero-presentation-time
disable-resize-throttling
disable-transactions
keep-laptop-panel-on-when-lid-is-closed
disable-monitor-names
strict-new-window-focus-policy
honor-xdg-activation-with-invalid-serial
honor-xdg-activation-with-invalid-serial
skip-cursor-only-updates-during-vrr
deactivate-unfocused-windows
keep-max-bpc-unchanged
}
binds {
@@ -153,22 +155,6 @@ debug {
}
```
### `wait-for-frame-completion-in-pipewire`
<sup>Since: next release</sup>
Wait until every screencast frame is done rendering before handing it over to PipeWire.
Sometimes helps on NVIDIA to prevent glitched frames when screencasting.
This debug flag will eventually be removed once we handle this properly (via explicit sync in PipeWire).
```kdl
debug {
wait-for-frame-completion-in-pipewire
}
```
### `emulate-zero-presentation-time`
Emulate zero (unknown) presentation time returned from DRM.
@@ -258,7 +244,7 @@ debug {
### `honor-xdg-activation-with-invalid-serial`
<sup>Since: next release</sup>
<sup>Since: 25.05</sup>
Widely-used clients such as Discord and Telegram make fresh xdg-activation tokens upon clicking on their tray icon or on their notification.
Most of the time, these fresh tokens will have invalid serials, because the app needs to be focused to get a valid serial, and if the user clicks on a tray icon or a notification, it is usually because the app *isn't* focused, and the user wants to focus it.
@@ -275,6 +261,55 @@ debug {
}
```
### `skip-cursor-only-updates-during-vrr`
<sup>Since: next release</sup>
Skips redrawing the screen from cursor input while variable refresh rate is active.
Useful for games where the cursor isn't drawn internally to prevent erratic VRR shifts in response to cursor movement.
Note that the current implementation has some issues, for example when there's nothing redrawing the screen (like a game), the rendering will appear to completely freeze (since cursor movements won't cause redraws).
```kdl
debug {
skip-cursor-only-updates-during-vrr
}
```
### `deactivate-unfocused-windows`
<sup>Since: next release</sup>
Some clients (notably, Chromium- and Electron-based, like Teams or Slack) erroneously use the Activated xdg window state instead of keyboard focus for things like deciding whether to send notifications for new messages, or for picking where to show an IME popup.
Niri keeps the Activated state on unfocused workspaces and invisible tabbed windows (to reduce unwanted animations), surfacing bugs in these applications.
Set this debug flag to work around these problems.
It will cause niri to drop the Activated state for all unfocused windows.
```kdl
debug {
deactivate-unfocused-windows
}
```
### `keep-max-bpc-unchanged`
<sup>Since: next release</sup>
When connecting monitors, niri sets their max bpc to 8 in order to reduce display bandwidth and to potentially allow more monitors to be connected at once.
Restricting bpc to 8 is not a problem since we don't support HDR or color management yet and can't really make use of higher bpc.
Apparently, setting max bpc to 8 breaks some displays driven by AMDGPU.
If this happens to you, set this debug flag, which will prevent niri from changing max bpc.
AMDGPU bug report: https://gitlab.freedesktop.org/drm/amd/-/issues/4487.
```kdl
debug {
keep-max-bpc-unchanged
}
```
### Key Bindings
These are not debug options, but rather key bindings.
@@ -14,6 +14,16 @@ gestures {
delay-ms 100
max-speed 1500
}
dnd-edge-workspace-switch {
trigger-height 50
delay-ms 100
max-speed 1500
}
hot-corners {
// off
}
}
```
@@ -41,3 +51,46 @@ gestures {
}
}
```
### `dnd-edge-workspace-switch`
<sup>Since: 25.05</sup>
Scroll the workspaces up/down when moving the mouse cursor against a monitor edge during drag-and-drop (DnD) while in the overview.
Also works on a touchscreen.
The options are:
- `trigger-height`: size of the area near the monitor edge that will trigger the scrolling, in logical pixels.
- `delay-ms`: delay in milliseconds before the scrolling starts.
Avoids unwanted scrolling when dragging things across monitors.
- `max-speed`: maximum scrolling speed; 1500 corresponds to one screen height per second.
The scrolling speed increases linearly as you move your mouse cursor from `trigger-width` to the very edge of the monitor.
```kdl
gestures {
// Increase the trigger area and maximum speed.
dnd-edge-workspace-switch {
trigger-height 100
max-speed 3000
}
}
```
### `hot-corners`
<sup>Since: 25.05</sup>
Put your mouse at the very top-left corner of a monitor to toggle the overview.
Also works during drag-and-dropping something.
`off` disables the hot corners.
```kdl
// Disable the hot corners.
gestures {
hot-corners {
off
}
}
```
@@ -23,6 +23,7 @@ input {
// repeat-delay 600
// repeat-rate 25
// track-layout "global"
numlock
}
touchpad {
@@ -36,8 +37,10 @@ input {
// accel-speed 0.2
// accel-profile "flat"
// scroll-factor 1.0
// scroll-factor vertical=1.0 horizontal=-2.0
// scroll-method "two-finger"
// scroll-button 273
// scroll-button-lock
// tap-button-map "left-middle-right"
// click-method "clickfinger"
// left-handed
@@ -51,8 +54,10 @@ input {
// accel-speed 0.2
// accel-profile "flat"
// scroll-factor 1.0
// scroll-factor vertical=1.0 horizontal=-2.0
// scroll-method "no-scroll"
// scroll-button 273
// scroll-button-lock
// left-handed
// middle-emulation
}
@@ -64,6 +69,7 @@ input {
// accel-profile "flat"
// scroll-method "on-button-down"
// scroll-button 273
// scroll-button-lock
// left-handed
// middle-emulation
}
@@ -75,6 +81,7 @@ input {
// accel-profile "flat"
// scroll-method "on-button-down"
// scroll-button 273
// scroll-button-lock
// left-handed
// middle-emulation
}
@@ -138,6 +145,34 @@ input {
> }
> ```
> [!NOTE]
>
> <sup>Since: next release</sup>
>
> If the `xkb` section is empty (like it is by default), niri will fetch xkb settings from systemd-localed at `org.freedesktop.locale1` over D-Bus.
> This way, for example, system installers can dynamically set the niri keyboard layout.
> You can see this layout in `localectl` and change it with `localectl set-x11-keymap`, for example:
>
> ```sh
> $ localectl set-x11-keymap "us" "" "colemak_dh_ortho" "compose:ralt,ctrl:nocaps"
> $ localectl
> System Locale: LANG=en_US.UTF-8
> LC_NUMERIC=ru_RU.UTF-8
> LC_TIME=ru_RU.UTF-8
> LC_MONETARY=ru_RU.UTF-8
> LC_PAPER=ru_RU.UTF-8
> LC_MEASUREMENT=ru_RU.UTF-8
> VC Keymap: us-colemak_dh_ortho
> X11 Layout: us
> X11 Variant: colemak_dh_ortho
> X11 Options: compose:ralt,ctrl:nocaps
> ```
>
> By default, `localectl` will set the TTY keymap to the closest match of the XKB keymap.
> You can prevent that with a `--no-convert` flag, for example: `localectl set-x11-keymap --no-convert "us,ru"`.
>
> These settings are picked up by some other programs too, like GDM.
When using multiple layouts, niri can remember the current layout globally (the default) or per-window.
You can control this with the `track-layout` option.
@@ -166,6 +201,22 @@ input {
}
```
#### Num Lock
<sup>Since: 25.05</sup>
Set the `numlock` flag to turn on Num Lock automatically at startup.
You might want to disable (comment out) `numlock` if you're using a laptop with a keyboard that overlays Num Lock keys on top of regular keys.
```kdl
input {
keyboard {
numlock
}
}
```
### Pointing Devices
Most settings for the pointing devices are passed directly to libinput.
@@ -184,6 +235,7 @@ A few settings are common between `touchpad`, `mouse`, `trackpoint`, and `trackb
- `scroll-method`: when to generate scroll events instead of pointer motion events, can be `no-scroll`, `two-finger`, `edge`, or `on-button-down`.
The default and supported methods vary depending on the device type.
- `scroll-button`: <sup>Since: 0.1.10</sup> the button code used for the `on-button-down` scroll method. You can find it in `libinput debug-events`.
- `scroll-button-lock`: <sup>Since: next release</sup> when enabled, the button does not need to be held down. Pressing once engages scrolling, pressing a second time disengages it, and double click acts as single click of the the underlying button.
- `left-handed`: if set, changes the device to left-handed mode.
- `middle-emulation`: emulate a middle mouse click by pressing left and right mouse buttons at once.
@@ -192,7 +244,7 @@ Settings specific to `touchpad`s:
- `tap`: tap-to-click.
- `dwt`: disable-when-typing.
- `dwtp`: disable-when-trackpointing.
- `drag`: can be `true` or `false`, controls if tap-and-drag is enabled.
- `drag`: <sup>Since: 25.05</sup> can be `true` or `false`, controls if tap-and-drag is enabled.
- `drag-lock`: <sup>Since: 25.02</sup> if set, lifting the finger off for a short time while dragging will not drop the dragged item. See the [libinput documentation](https://wayland.freedesktop.org/libinput/doc/latest/tapping.html#tap-and-drag).
- `tap-button-map`: can be `left-right-middle` or `left-middle-right`, controls which button corresponds to a two-finger tap and a three-finger tap.
- `click-method`: can be `button-areas` or `clickfinger`, changes the [click method](https://wayland.freedesktop.org/libinput/doc/latest/clickpad-softbuttons.html).
@@ -202,6 +254,8 @@ Settings specific to `touchpad` and `mouse`:
- `scroll-factor`: <sup>Since: 0.1.10</sup> scales the scrolling speed by this value.
<sup>Since: next release</sup> You can also override horizontal and vertical scroll factor separately like so: `scroll-factor horizontal=2.0 vertical=-1.0`
Settings specific to `tablet`s:
- `calibration-matrix`: <sup>Since: 25.02</sup> set to six floating point numbers to change the calibration matrix. See the [`LIBINPUT_CALIBRATION_MATRIX` documentation](https://wayland.freedesktop.org/libinput/doc/latest/device-configuration-via-udev.html) for examples.
@@ -254,7 +308,7 @@ input {
By default, the cursor warps *separately* horizontally and vertically.
I.e. if moving the mouse only horizontally is enough to put it inside the newly focused window, then the mouse will move only horizontally, and not vertically.
<sup>Since: next release</sup> You can customize this with the `mode` property.
<sup>Since: 25.05</sup> You can customize this with the `mode` property.
- `mode="center-xy"`: warps by both X and Y coordinates together.
So if the mouse was anywhere outside the newly focused window, it will warp to the center of the window.
@@ -309,7 +363,7 @@ input {
#### `mod-key`, `mod-key-nested`
<sup>Since: next release</sup>
<sup>Since: 25.05</sup>
Customize the `Mod` key for [key bindings](./Configuration:-Key-Bindings.md).
Only valid modifiers are allowed, e.g. `Super`, `Alt`, `Mod3`, `Mod5`, `Ctrl`, `Shift`.
@@ -31,7 +31,7 @@ Valid modifiers are:
This way, you can test niri in a window without causing too many conflicts with the host compositor's key bindings.
For this reason, most of the default keys use the `Mod` modifier.
<sup>Since: next release</sup> You can customize the `Mod` key [in the `input` section of the config](./Configuration:-Input.md#mod-key-mod-key-nested).
<sup>Since: 25.05</sup> You can customize the `Mod` key [in the `input` section of the config](./Configuration:-Input.md#mod-key-mod-key-nested).
> [!TIP]
> To find an XKB name for a particular key, you may use a program like [`wev`](https://git.sr.ht/~sircmpwn/wev).
@@ -52,6 +52,15 @@ For this reason, most of the default keys use the `Mod` modifier.
>
> Here, look at `sym: Left` and `sym: Right`: these are the key names.
> I was pressing the left and the right arrow in this example.
>
> Keep in mind that binding shifted keys requires spelling out Shift and the unshifted version of the key, according to your XKB layout.
> For example, on the US QWERTY layout, <kbd>&lt;</kbd> is on <kbd>Shift</kbd> + <kbd>,</kbd>, so to bind it, you spell out something like `Mod+Shift+Comma`.
>
> As another example, if you've configured the French [BÉPO](https://en.wikipedia.org/wiki/B%C3%89PO) XKB layout, your <kbd>&lt;</kbd> is on <kbd>AltGr</kbd> + <kbd>«</kbd>.
> <kbd>AltGr</kbd> is `ISO_Level3_Shift`, or equivalently `Mod5`, so to bind it, you spell out something like `Mod+Mod5+guillemotleft`.
>
> When resolving latin keys, niri will search for the *first* configured XKB layout that has the latin key.
> So for example with US QWERTY and RU layouts configured, US QWERTY will be used for latin binds.
<sup>Since: 0.1.8</sup> Binds will repeat by default (i.e. holding down a bind will make it trigger repeatedly).
You can disable that for specific binds with `repeat=false`:
@@ -197,7 +206,8 @@ binds {
> }
> ```
Currently, niri *does not* use a shell to run commands, which means that you need to manually separate arguments.
For `spawn`, niri *does not* use a shell to run commands, which means that you need to manually separate arguments.
See [`spawn-sh`](#spawn-sh) below for an action that uses a shell.
```kdl
binds {
@@ -240,6 +250,37 @@ binds {
}
```
#### `spawn-sh`
<sup>Since: next release</sup>
Run a command through the shell.
The argument is a single string that is passed verbatim to `sh`.
You can use shell variables, pipelines, `~` expansion, and everything else as expected.
```kdl
binds {
// Works with spawn-sh: all arguments in the same string.
Mod+D { spawn-sh "alacritty -e /usr/bin/fish"; }
// Works with spawn-sh: shell variable ($MAIN_OUTPUT), ~ expansion.
Mod+T { spawn-sh "grim -o $MAIN_OUTPUT ~/screenshot.png"; }
// Works with spawn-sh: process substitution.
Mod+Q { spawn-sh "notify-send clipboard \"$(wl-paste)\""; }
// Works with spawn-sh: multiple commands.
Super+Alt+S { spawn-sh "pkill orca || exec orca"; }
}
```
`spawn-sh "some command"` is equivalent to `spawn "sh" "-c" "some command"`—it's just a less confusing shorthand.
Keep in mind that going through the shell incurs a tiny performance penalty compared to directly `spawn`ing some binary.
Using `sh` is hardcoded, consistent with other compositors.
If you want a different shell, write it out using `spawn`, e.g. `spawn "fish" "-c" "some fish command"`.
#### `quit`
Exit niri after showing a confirmation dialog to avoid accidentally triggering it.
@@ -328,7 +369,7 @@ binds {
In the interactive screenshot UI, pressing <kbd>Ctrl</kbd><kbd>C</kbd> will copy the screenshot to the clipboard without writing it to disk.
<sup>Since: next release</sup> You can hide the mouse pointer in screenshots with the `show-pointer=false` property:
<sup>Since: 25.05</sup> You can hide the mouse pointer in screenshots with the `show-pointer=false` property:
```kdl
binds {
@@ -32,6 +32,8 @@ layer-rule {
}
geometry-corner-radius 12
place-within-backdrop true
baba-is-float true
}
```
@@ -129,7 +131,7 @@ That is, enabling shadows in the layout config section won't automatically enabl
// Add a shadow for fuzzel.
layer-rule {
match namespace="^launcher$"
shadow {
on
}
@@ -149,6 +151,43 @@ This setting will only affect the shadow—it will round its corners to match th
```kdl
layer-rule {
match namespace="^launcher$"
geometry-corner-radius 12
}
```
#### `place-within-backdrop`
<sup>Since: 25.05</sup>
Set to `true` to place the surface into the backdrop visible in the [Overview](./Overview.md) and between workspaces.
This will only work for *background* layer surfaces that ignore exclusive zones (typical for wallpaper tools).
Layers within the backdrop will ignore all input.
```kdl
// Put swaybg inside the overview backdrop.
layer-rule {
match namespace="^wallpaper$"
place-within-backdrop true
}
```
#### `baba-is-float`
<sup>Since: 25.05</sup>
Make your layer surfaces FLOAT up and down.
This is a natural extension of the [April Fools' 2025 feature](./Configuration:-Window-Rules.md#baba-is-float).
```kdl
// Make fuzzel FLOAT.
layer-rule {
match namespace="^launcher$"
baba-is-float true
}
```
@@ -11,6 +11,7 @@ layout {
always-center-single-column
empty-workspace-above-first
default-column-display "tabbed"
background-color "#003300"
preset-column-widths {
proportion 0.33333
@@ -31,8 +32,10 @@ layout {
width 4
active-color "#7fc8ff"
inactive-color "#505050"
urgent-color "#9b0000"
// active-gradient from="#80c8ff" to="#bbddff" angle=45
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
// urgent-gradient from="#800" to="#a33" angle=45
}
border {
@@ -40,8 +43,10 @@ layout {
width 4
active-color "#ffc87f"
inactive-color "#505050"
urgent-color "#9b0000"
// active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view"
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" in="srgb-linear"
// urgent-gradient from="#800" to="#a33" angle=45
}
shadow {
@@ -66,8 +71,10 @@ layout {
corner-radius 8
active-color "red"
inactive-color "gray"
urgent-color "blue"
// active-gradient from="#80c8ff" to="#bbddff" angle=45
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
// urgent-gradient from="#800" to="#a33" angle=45
}
insert-hint {
@@ -242,7 +249,7 @@ The difference is that the focus ring is drawn only around the active window, wh
| Focus Ring | Border |
| ------------------------- | --------------------- |
| ![](./img/focus-ring.png) | ![](./img/border.png) |
| ![Screenshot showing a focused image in the center row using focus ring](./img/focus-ring.png) | ![Screenshot showing a focused image in the center row using border, while top and bottom windows have the inactive color](./img/border.png) |
> [!TIP]
> By default, focus ring and border are rendered as a solid background rectangle behind windows.
@@ -269,6 +276,9 @@ layout {
active-color "#ffc87f"
inactive-color "#505050"
// Color of the border around windows that request your attention.
urgent-color "#9b0000"
// active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view"
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" in="srgb-linear"
}
@@ -328,7 +338,7 @@ Here's a visual example:
| Default | `relative-to="workspace-view"` |
| -------------------------------- | --------------------------------------------------- |
| ![](./img/gradients-default.png) | ![](./img/gradients-relative-to-workspace-view.png) |
| ![Screenshot displaying 4 windows, each with individual gradient borders](./img/gradients-default.png) | ![Screenshot displaying 4 windows, with a shared gradient across their borders](./img/gradients-relative-to-workspace-view.png) |
```kdl
layout {
@@ -350,7 +360,7 @@ Supported color spaces are:
They are rendered the same as CSS.
For example, `active-gradient from="#f00f" to="#0f05" angle=45 in="oklch longer hue"` will look the same as CSS `linear-gradient(45deg in oklch longer hue, #f00f, #0f05)`.
![](./img/gradients-oklch.png)
![Screenshot showing a window with a border using a gradient in the oklch color space](./img/gradients-oklch.png)
```kdl
layout {
@@ -372,7 +382,7 @@ Set `on` to enable the shadow.
Setting `softness 0` will give you hard shadows.
`spread` is the distance to expand the window rectangle in logical pixels, same as CSS box-shadow spread.
<sup>Since: next release</sup> Spread can be negative.
<sup>Since: 25.05</sup> Spread can be negative.
`offset` moves the shadow relative to the window in logical pixels, same as CSS box-shadow offset.
For example, `offset x=2 y=2` will move the shadow 2 logical pixels downwards and to the right.
@@ -440,7 +450,7 @@ It can be `left`, `right`, `top`, or `bottom`.
`corner-radius` sets the rounded corner radius for tabs in the indicator in logical pixels.
When `gaps-between-tabs` is zero, only the first and the last tabs have rounded corners, otherwise all tabs do.
`active-color`, `inactive-color`, `active-gradient`, `inactive-gradient` let you override the colors for the tabs.
`active-color`, `inactive-color`, `urgent-color`, `active-gradient`, `inactive-gradient`, `urgent-gradient` let you override the colors for the tabs.
They have the same semantics as the border and focus ring colors and gradients.
Tab colors are picked in this order:
@@ -506,7 +516,7 @@ layout {
}
```
![](./img/struts.png)
![A screenshot illustrating the effects of struts, as explained in the second paragraph in this section](./img/struts.png)
<sup>Since: 0.1.8</sup> You can use negative values.
They will push the windows outwards, even outside the edges of the screen.
@@ -526,3 +536,18 @@ layout {
}
}
```
### `background-color`
<sup>Since: 25.05</sup>
Set the default background color that niri draws for workspaces.
This is visible when you're not using any background tools like swaybg.
```kdl
layout {
background-color "#003300"
}
```
You can also set the color per-output [in the output config](./Configuration:-Outputs.md#background-color).
@@ -1,5 +1,3 @@
### Overview
This page documents all top-level options that don't otherwise have dedicated pages.
Here are all of these options at a glance:
@@ -7,6 +5,7 @@ Here are all of these options at a glance:
```kdl
spawn-at-startup "waybar"
spawn-at-startup "alacritty"
spawn-sh-at-startup "qs -c ~/source/qs/MyAwesomeShell"
prefer-no-csd
@@ -25,12 +24,35 @@ cursor {
hide-after-inactive-ms 1000
}
overview {
zoom 0.5
backdrop-color "#262626"
workspace-shadow {
// off
softness 40
spread 10
offset x=0 y=10
color "#00000050"
}
}
xwayland-satellite {
// off
path "xwayland-satellite"
}
clipboard {
disable-primary
}
hotkey-overlay {
skip-at-startup
hide-not-bound
}
config-notification {
disable-failed
}
```
@@ -50,6 +72,22 @@ spawn-at-startup "alacritty"
Note that running niri as a systemd session supports xdg-desktop-autostart out of the box, which may be more convenient to use.
Thanks to this, apps that you configured to autostart in GNOME will also "just work" in niri, without any manual `spawn-at-startup` configuration.
### `spawn-sh-at-startup`
<sup>Since: next release</sup>
Add lines like this to run shell commands at niri startup.
The argument is a single string that is passed verbatim to `sh`.
You can use shell variables, pipelines, `~` expansion and everything else as expected.
See detailed description in the docs for the [`spawn-sh` key binding action](./Configuration:-Key-Bindings.md#spawn-sh).
```kdl
// Pass all arguments in the same string.
spawn-sh-at-startup "qs -c ~/source/qs/MyAwesomeShell"
```
### `prefer-no-csd`
This flag will make niri ask the applications to omit their client-side decorations.
@@ -143,6 +181,80 @@ cursor {
}
```
### `overview`
<sup>Since: 25.05</sup>
Settings for the [Overview](./Overview.md).
#### `zoom`
Control how much the workspaces zoom out in the overview.
`zoom` ranges from 0 to 0.75 where lower values make everything smaller.
```kdl
// Make workspaces four times smaller than normal in the overview.
overview {
zoom 0.25
}
```
#### `backdrop-color`
Set the backdrop color behind workspaces in the overview.
The backdrop is also visible between workspaces when switching.
The alpha channel for this color will be ignored.
```kdl
// Make the backdrop light.
overview {
backdrop-color "#777777"
}
```
You can also set the color per-output [in the output config](./Configuration:-Outputs.md#backdrop-color).
#### `workspace-shadow`
Control the shadow behind workspaces visible in the overview.
Settings here mirror the normal [`shadow` config in the layout section](./Configuration:-Layout.md#shadow), so check the documentation there.
Workspace shadows are configured for a workspace size normalized to 1080 pixels tall, then zoomed out together with the workspace.
Practically, this means that you'll want bigger spread, offset, and softness compared to window shadows.
```kdl
// Disable workspace shadows in the overview.
overview {
workspace-shadow {
off
}
}
```
### `xwayland-satellite`
<sup>Since: next release</sup>
Settings for integration with [xwayland-satellite](https://github.com/Supreeeme/xwayland-satellite).
When a recent enough xwayland-satellite is detected, niri will create the X11 sockets and set `DISPLAY`, then automatically spawn `xwayland-satellite` when an X11 client tries to connect.
If Xwayland dies, niri will keep watching the X11 socket and restart `xwayland-satellite` as needed.
This is very similar to how built-in Xwayland works in other compositors.
`off` disables the integration: niri won't create an X11 socket and won't set the `DISPLAY` environment variable.
`path` sets the path to the `xwayland-satellite` binary.
By default, it's just `xwayland-satellite`, so it's looked up like any other non-absolute program name.
```kdl
// Use a custom build of xwayland-satellite.
xwayland-satellite {
path "~/source/rs/xwayland-satellite/target/release/xwayland-satellite"
}
```
### `clipboard`
<sup>Since: 25.02</sup>
@@ -162,6 +274,8 @@ clipboard {
Settings for the "Important Hotkeys" overlay.
#### `skip-at-startup`
Set the `skip-at-startup` flag if you don't want to see the hotkey help at niri startup.
```kdl
@@ -170,4 +284,32 @@ hotkey-overlay {
}
```
#### `hide-not-bound`
<sup>Since: next release</sup>
By default, niri will show the most important actions even if they aren't bound to any key, to prevent confusion.
Set the `hide-not-bound` flag if you want to hide all actions not bound to any key.
```kdl
hotkey-overlay {
hide-not-bound
}
```
You can customize which binds the hotkey overlay shows using the [`hotkey-overlay-title` property](./Configuration:-Key-Bindings.md#custom-hotkey-overlay-titles).
### `config-notification`
<sup>Since: next release</sup>
Settings for the config created/failed notification.
Set the `disable-failed` flag to disable the "Failed to parse the config file" notification.
For example, if you have a custom one.
```kdl
config-notification {
disable-failed
}
```
@@ -15,6 +15,7 @@ output "eDP-1" {
variable-refresh-rate // on-demand=true
focus-at-startup
background-color "#003300"
backdrop-color "#001100"
}
output "HDMI-A-1" {
@@ -167,7 +168,7 @@ output "HDMI-A-1" {
### `focus-at-startup`
<sup>Since: next release</sup>
<sup>Since: 25.05</sup>
Focus this output by default when niri starts.
@@ -191,13 +192,28 @@ output "DP-2" {
<sup>Since: 0.1.8</sup>
Set the background color that niri draws for this output.
Set the background color that niri draws for workspaces on this output.
This is visible when you're not using any background tools like swaybg.
The alpha channel for this color will be ignored.
<sup>Until: 25.05</sup> The alpha channel for this color will be ignored.
```kdl
output "HDMI-A-1" {
background-color "#003300"
}
```
### `backdrop-color`
<sup>Since: 25.05</sup>
Set the backdrop color that niri draws for this output.
This is visible between workspaces or in the overview.
The alpha channel for this color will be ignored.
```kdl
output "HDMI-A-1" {
backdrop-color "#001100"
}
```
+1
View File
@@ -0,0 +1 @@
This wiki page has moved to: [Introduction](./Configuration:-Introduction.md).
@@ -35,6 +35,7 @@ window-rule {
match is-active-in-column=true
match is-floating=true
match is-window-cast-target=true
match is-urgent=true
match at-startup=true
// Properties that apply once upon window opening.
@@ -63,8 +64,10 @@ window-rule {
width 4
active-color "#7fc8ff"
inactive-color "#505050"
urgent-color "#9b0000"
// active-gradient from="#80c8ff" to="#bbddff" angle=45
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
// urgent-gradient from="#800" to="#a33" angle=45
}
border {
@@ -85,8 +88,10 @@ window-rule {
tab-indicator {
active-color "red"
inactive-color "gray"
urgent-color "blue"
// active-gradient from="#80c8ff" to="#bbddff" angle=45
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
// urgent-gradient from="#800" to="#a33" angle=45
}
geometry-corner-radius 12
@@ -280,7 +285,20 @@ window-rule {
Example:
![](https://github.com/user-attachments/assets/375b381e-3a87-4e94-8676-44404971d893)
![A screenshot showing that only the is-window-cast-target=true windows receive the special border colors](https://github.com/user-attachments/assets/375b381e-3a87-4e94-8676-44404971d893)
#### `is-urgent`
<sup>Since: 25.05</sup>
Can be `true` or `false`.
Matches windows that request the user's attention.
```kdl
window-rule {
match is-urgent=true
}
```
#### `at-startup`
@@ -680,7 +698,7 @@ This property can be useful for rectangular windows that do not support the xdg-
| With Background | Without Background |
| ------------------------------------------------ | --------------------------------------------------- |
| ![](./img/simple-egl-border-with-background.png) | ![](./img/simple-egl-border-without-background.png) |
| ![A screenshot displaying a window with draw-border-with-background set to true](./img/simple-egl-border-with-background.png) | ![A screenshot displaying a window with draw-border-with-background set to false](./img/simple-egl-border-without-background.png) |
```kdl
window-rule {
@@ -773,7 +791,7 @@ window-rule {
The radius is set in logical pixels, and controls the radius of the window itself, that is, the inner radius of the border:
![](./img/geometry-corner-radius.png)
![A screenshot showing a window with every corner rounded](./img/geometry-corner-radius.png)
Instead of one radius, you can set four, for each corner.
The order is the same as in CSS: top-left, top-right, bottom-right, bottom-left.
@@ -786,7 +804,7 @@ window-rule {
This way, you can match GTK 3 applications which have square bottom corners:
![](./img/different-corner-radius.png)
![A screenshot showing a window with only the top corners rounded](./img/different-corner-radius.png)
#### `clip-to-geometry`
@@ -796,7 +814,7 @@ Clips the window to its visual geometry.
This will cut out any client-side window shadows, and also round window corners according to `geometry-corner-radius`.
![](./img/clip-to-geometry.png)
![A screenshot showing a window with rounded corners, clipped to the visual geometry](./img/clip-to-geometry.png)
```kdl
window-rule {
@@ -806,7 +824,7 @@ window-rule {
Enable border, set [`geometry-corner-radius`](#geometry-corner-radius) and `clip-to-geometry`, and you've got a classic setup:
![](./img/border-radius-clip.png)
![A screenshot showing a window with rounded corners, and a border](./img/border-radius-clip.png)
```kdl
prefer-no-csd
@@ -829,7 +847,7 @@ window-rule {
#### `tiled-state`
<sup>Since: next release</sup>
<sup>Since: 25.05</sup>
Informs the window that it is tiled.
Usually, windows will react by becoming rectangular and hiding their client-side shadows.
@@ -863,8 +881,12 @@ window-rule {
}
```
<video controls src="https://github.com/user-attachments/assets/3f4cb1a4-40b2-4766-98b7-eec014c19509">
https://github.com/user-attachments/assets/3f4cb1a4-40b2-4766-98b7-eec014c19509
</video>
#### Size Overrides
You can amend the window's minimum and maximum size in logical pixels.
@@ -0,0 +1,85 @@
niri's documentation files are found in `docs/wiki/` and should be viewable and browsable in at least three systems:
- The GitHub repo's markdown file preview
- [The GitHub repo's wiki](https://github.com/YaLTeR/niri/wiki)
- [The documentation site](https://yalter.github.io/niri/)
## The GitHub repo's wiki
This is generated with the `publish-wiki` job in `.github/workflows/ci.yml`.
In order to have this job run as expected in your fork, you'll need to enable the wiki feature in your repo's settings on GitHub.
This could be useful as a contributor to verify that the wiki generates the way you expect it to.
## The documentation site
The documentation site is generated with [mkdocs](https://www.mkdocs.org/).
The configuration files are found in `docs/`.
To set up and run the documentation site locally, it is recommended to use [uv](https://docs.astral.sh/uv/).
### Serving the site locally with uv
In the `docs/` subdirectory:
- `uv sync`
- `uv run mkdocs serve`
The documentation site should now be available on http://127.0.0.1:8000/niri/
Changes made to the documentation while the development server is running will cause an automatic page refresh in the browser.
> [!TIP]
> Images may not be visible, as they are stored on Git LFS.
> If this is the case, run `git lfs pull`.
## Elements
Elements such as links, admonitions, images, and snippets should work as expected in markdown file previews on GitHub, the GitHub repo's wiki, and in the documentation site.
### Links
Links should in all cases be relative (e.g. `./FAQ.md`), unless it's an external one.
Links should have anchors if they are meant to lead the user to a specific section on a page (e.g. `./Getting-Started.md#nvidia`).
> [!TIP]
> mkdocs will terminate if relative links lead to non-existing documents or non-existing anchors.
> This means that the CI pipeline will fail when building documentation, as will `mkdocs serve` locally.
### Admonitions
> [!IMPORTANT]
> This is an important distinction from other `mkdocs`-based documentation you might have encountered.
Admonitions, or alerts should be written [the way GitHub defines them](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts).
The above admonition is written like this:
```
> [!IMPORTANT]
> This is an important distinction from other `mkdocs`-based documentation you might have encountered.
```
### Images
Images should have relative links to resources in `docs/wiki/img/`, and should contain sensible alt-text.
### Videos
For compatibility with both mkdocs and GitHub Wiki, videos need to be wrapped in a `<video>` tag (displayed by mkdocs) and have the video link again as fallback text (displayed by GitHub Wiki) padded with blank lines.
```html
<video controls src="https://github.com/user-attachments/assets/379a5d1f-acdb-4c11-b36c-e85fd91f0995">
https://github.com/user-attachments/assets/379a5d1f-acdb-4c11-b36c-e85fd91f0995
</video>
```
### Snippets
Configuration and code snippets in general should be annotated with a language.
If the language used in the snippet is KDL, open the code block like this:
```md
```kdl
```
@@ -25,6 +25,7 @@ The way it's handled in niri is:
It's important to understand that they remain fractional numbers in the logical space, but these numbers correspond to an integer number of pixels in the physical space.
The rounding looks something like: `(logical_size * scale).round() / scale`.
Whenever a workspace moves to an output with a different scale (or the output scale changes), all sizes are re-rounded from their original configured values to align with the new physical space.
2. The view offset and individual column/tile render offsets are *not* rounded to physical pixels, but:
3. `tiles_with_render_positions()` rounds tile positions to physical pixels as it returns them,
4. Custom shaders like opening, closing and resizing windows, are also careful to keep positions and sizes rounded to the physical pixels.
@@ -2,26 +2,23 @@ When starting niri from a display manager like GDM, or otherwise through the `ni
This provides the necessary systemd integration to run programs like `mako` and services like `xdg-desktop-portal` bound to the graphical session.
Here's an example on how you might set up [`mako`](https://github.com/emersion/mako), [`waybar`](https://github.com/Alexays/Waybar), [`swaybg`](https://github.com/swaywm/swaybg) and [`swayidle`](https://github.com/swaywm/swayidle) to run as systemd services with niri.
In contrast to [`spawn-at-startup`](./Configuration:-Miscellaneous.md#spawn-at-startup), this lets you easily monitor their status and output, and restart or reload them.
Unlike [`spawn-at-startup`](./Configuration:-Miscellaneous.md#spawn-at-startup), this lets you easily monitor their status and output, and restart or reload them.
1. Install them, i.e. `sudo dnf install mako waybar swaybg swayidle`
2. Create a `niri.service.wants` folder: `mkdir -p ~/.config/systemd/user/niri.service.wants`
This is a special systemd folder.
Any services linked there will be started together with `niri.service` (which is a systemd unit used by niri when running as a session).
3. `mako` and `waybar` provide systemd units out of the box, so you can simply symlink them into the `niri.service.wants` folder:
2. `mako` and `waybar` provide systemd units out of the box, so you can simply add them to the niri session:
```
ln -s /usr/lib/systemd/user/mako.service ~/.config/systemd/user/niri.service.wants/
ln -s /usr/lib/systemd/user/waybar.service ~/.config/systemd/user/niri.service.wants/
systemctl --user add-wants niri.service mako.service
systemctl --user add-wants niri.service waybar.service
```
4. `swaybg` does not provide a systemd unit, since you need to pass the background image as a command-line argument.
This will create links in `~/.config/systemd/user/niri.service.wants/`, a special systemd folder for services that need to start together with `niri.service`.
3. `swaybg` does not provide a systemd unit, since you need to pass the background image as a command-line argument.
So we will make our own.
Put the following into `~/.config/systemd/user/swaybg.service`:
Create `~/.config/systemd/user/swaybg.service` with the following contents:
```
```systemd
[Unit]
PartOf=graphical-session.target
After=graphical-session.target
@@ -37,15 +34,16 @@ In contrast to [`spawn-at-startup`](./Configuration:-Miscellaneous.md#spawn-at-s
After editing `swaybg.service`, run `systemctl --user daemon-reload` so systemd picks up the changes in the file.
Now, also symlink this to `niri.service.wants`:
Now, add it to the niri session:
```
ln -s ~/.config/systemd/user/swaybg.service ~/.config/systemd/user/niri.service.wants/
systemctl --user add-wants niri.service swaybg.service
```
5. `swayidle` similarly does not provide a service so we will also make our own. Put the following into `~/.config/systemd/user/swayidle.service`:
4. `swayidle` similarly does not provide a service, so we will also make our own.
Create `~/.config/systemd/user/swayidle.service` with the following contents:
```
```systemd
[Unit]
PartOf=graphical-session.target
After=graphical-session.target
@@ -56,20 +54,23 @@ In contrast to [`spawn-at-startup`](./Configuration:-Miscellaneous.md#spawn-at-s
Restart=on-failure
```
Then, run `systemctl --user daemon-reload` and symlink this file to `niri.service.wants`:
Then, run `systemctl --user daemon-reload` and add it to the niri session:
```
ln -s ~/.config/systemd/user/swayidle.service ~/.config/systemd/user/niri.service.wants/
systemctl --user add-wants niri.service swayidle.service
```
That's it!
Now these three utilities will be started together with the niri session and stopped when it exits.
You can also restart them with a command like `systemctl --user restart waybar.service`, for example after editing their config files.
To remove a service from niri startup, remove its symbolic link from `~/.config/systemd/user/niri.service.wants/`.
Then, run `systemctl --user daemon-reload`.
### Running Programs Across Logout
When running niri as a session, exiting it (logging out) will kill all programs that you've started within. However, sometimes you want a program, like `tmux`, `dtach` or similar, to persist in this case. To do this, run it in a transient systemd scope:
```
systemd-run --user --scope tmux new-session
```
```
+85
View File
@@ -0,0 +1,85 @@
### How to disable client-side decorations/make windows rectangular?
Uncomment the [`prefer-no-csd` setting](./Configuration:-Miscellaneous.md#prefer-no-csd) at the top level of the config, and then restart your apps.
Then niri will ask windows to omit client-side decorations, and also inform them that they are being tiled (which makes some windows rectangular, even if they cannot omit the decorations).
Note that currently this will prevent edge window resize handles from showing up.
You can still resize windows by holding <kbd>Mod</kbd> and the right mouse button.
### Why are transparent windows tinted? / Why is the border/focus ring showing up through semitransparent windows?
Uncomment the [`prefer-no-csd` setting](./Configuration:-Miscellaneous.md#prefer-no-csd) at the top level of the config, and then restart your apps.
Niri will draw focus rings and borders *around* windows that agree to omit their client-side decorations.
By default, focus ring and border are rendered as a solid background rectangle behind windows.
That is, they will show up through semitransparent windows.
This is because windows using client-side decorations can have an arbitrary shape.
You can also override this behavior with the [`draw-border-with-background` window rule](./Configuration:-Window-Rules.md#draw-border-with-background).
### How to enable rounded corners for all windows?
Put this window rule in your config:
```kdl
window-rule {
geometry-corner-radius 12
clip-to-geometry true
}
```
For more information, check the [`geometry-corner-radius` window rule](./Configuration:-Window-Rules.md#geometry-corner-radius).
### How to hide the "Important Hotkeys" pop-up at the start?
Put this into your config:
```kdl
hotkey-overlay {
skip-at-startup
}
```
### How to run X11 apps like Steam or Discord?
To run X11 apps, you can use [xwayland-satellite](https://github.com/Supreeeme/xwayland-satellite).
Check [the Xwayland wiki page](./Xwayland.md) for instructions.
Keep in mind that you can run many Electron apps such as VSCode natively on Wayland by passing the right flags, e.g. `code --ozone-platform-hint=auto`
### Why doesn't niri integrate Xwayland like other compositors?
A combination of factors:
- Integrating Xwayland is quite a bit of work, as the compositor needs to implement parts of an X11 window manager.
- You need to appease the X11 ideas of windowing, whereas for niri I want to have the best code for Wayland.
- niri doesn't have a good global coordinate system required by X11.
- You tend to get an endless stream of X11 bugs that take further time and effort away from other tasks.
- There aren't actually that many X11-only clients nowadays, and xwayland-satellite takes perfect care of most of those.
- niri isn't a Big Serious Desktop Environment which Must Support All Use Cases (and is Backed By Some Corporation).
All in all, the situation works out in favor of avoiding Xwayland integration.
Also, in the next release niri will have seamless built-in xwayland-satellite integration, that will solve the big rough edge of having to set it up manually.
Besides, I wouldn't be too surprised if, down the road, xwayland-satellite becomes the standard way of integrating Xwayland into new compositors, since it takes on the bulk of the annoying work, and isolates the compositor from misbehaving clients.
### Can I enable blur behind semitransparent windows?
Not yet, follow/upvote [this issue](https://github.com/YaLTeR/niri/issues/54).
There's also [a PR](https://github.com/YaLTeR/niri/pull/1634) adding blur to niri which you can build and run manually.
Keep in mind that it's an experimental implementation that may have problems and performance concerns.
### Can I make a window sticky / pinned / always on top / appear on all workspaces?
Not yet, follow/upvote [this issue](https://github.com/YaLTeR/niri/issues/932).
You can emulate this with a script that uses the niri IPC.
For example, [nirius](https://git.sr.ht/~tsdh/nirius) seems to have this feature (`toggle-follow-mode`).
### How do I make the Bitwarden window in Firefox open as floating?
Firefox seems to first open the Bitwarden window with a generic Firefox title, and only later change the window title to Bitwarden, so you can't effectively target it with an `open-floating` window rule.
You'll need to use a script, for example [this one](https://github.com/YaLTeR/niri/discussions/1599) or other ones (search niri issues and discussions for Bitwarden).
@@ -68,3 +68,26 @@ Move the view horizontally with three-finger horizontal swipes.
Scroll the tiling view when moving the mouse cursor against a monitor edge during drag-and-drop (DnD).
Also works on a touchscreen.
#### Drag-and-Drop Edge Workspace Switch
<sup>Since: 25.05</sup>
Scroll the workspaces up/down when moving the mouse cursor against a monitor edge during drag-and-drop (DnD) while in the overview.
Also works on a touchscreen.
#### Drag-and-Drop Hold to Activate
<sup>Since: 25.05</sup>
While drag-and-dropping, hold your mouse over a window to activate it.
This will bring a floating window to the top for example.
In the overview, you can also hold the mouse over a workspace to switch to it.
#### Hot Corner to Toggle the Overview
<sup>Since: 25.05</sup>
Put your mouse at the very top-left corner of a monitor to toggle the overview.
Also works during drag-and-dropping something.
@@ -17,12 +17,24 @@ Then it will open as a window, where you can give it a try.
Note that this windowed mode is mainly meant for development, so it is a bit buggy (in particular, there are issues with hotkeys).
Next, see the [list of important software](./Important-Software.md) required for normal desktop use, like a notification daemon and portals.
Also, check the [configuration overview](./Configuration:-Overview.md) page to get started configuring niri.
Also, check the [configuration introduction](./Configuration:-Introduction.md) page to get started configuring niri.
There you can find links to other pages containing thorough documentation and examples for all options.
Finally, the [Xwayland](./Xwayland.md) page explains how to run X11 applications on niri.
### Desktop environments
Some desktop environments and shells work with niri and can give a more out-of-the-box experience:
- [LXQt](https://lxqt-project.org/) officially supports niri, see [their wiki](https://github.com/lxqt/lxqt/wiki/ConfigWaylandSettings#general) for details on setting it up.
- Many [XFCE](https://www.xfce.org/) components work on Wayland, including niri. See [their wiki](https://wiki.xfce.org/releng/wayland_roadmap#component_specific_status) for details.
- There are complete desktop shells based on Quickshell that support niri, for example [DankMaterialShell](https://github.com/AvengeMedia/DankMaterialShell) and [Noctalia](https://github.com/noctalia-dev/noctalia-shell).
- You can run a [COSMIC](https://system76.com/cosmic/) session with niri using [cosmic-ext-extra-sessions](https://github.com/Drakulix/cosmic-ext-extra-sessions).
### NVIDIA
The NVIDIA drivers currently have an issue with high VRAM usage due to a heap reuse quirk.
You're recommended to apply a manual fix documented [here](./Nvidia.md) if you run niri on an NVIDIA GPU.
NVIDIA GPUs can have problems running niri (for example, the screen remains black upon starting from a TTY).
Sometimes, the problems can be fixed.
You can try the following:
@@ -50,7 +62,7 @@ You will likely have one `render` device and two `card` devices.
Open the niri config file at `~/.config/niri/config.kdl` and put your `render` device path like this:
```
```kdl
debug {
render-drm-device "/dev/dri/renderD128"
}
@@ -156,7 +168,7 @@ We have a community-maintained flake which provides a devshell with required dep
If you're not on NixOS, you may need [NixGL](https://github.com/nix-community/nixGL) to run the resulting binary:
```
```sh
nix run --impure github:guibou/nixGL -- ./results/bin/niri
```
View File
@@ -2,3 +2,4 @@ Things to keep in mind with layer-shell components (bars, launchers, etc.):
1. When a full-screen window is active and covers the entire screen, it will render above the top layer, and it will be prioritized for keyboard focus. If your launcher uses the top layer, and you try to run it while looking at a full-screen window, it won't show up. Only the overlay layer will show up on top of full-screen windows.
1. Components on the bottom and background layers will receive *on-demand* keyboard focus as expected. However, they will only receive *exclusive* keyboard focus when there are no windows on the workspace.
1. When opening the [Overview](./Overview.md), components on the bottom and background layers will zoom out and remain on the workspaces, while the top and overlay layers remain on top of the Overview. So, if you want the bar to remain on top, put it on the *top* layer.
+55
View File
@@ -0,0 +1,55 @@
### High VRAM usage fix
Presently, there is a quirk in the NVIDIA drivers that affects niri's VRAM usage (the driver does not properly release VRAM back into the pool). Niri *should* use on the order of 100 MiB of VRAM (as checked in [nvtop](https://github.com/Syllo/nvtop)); if you see anywhere close to 1 GiB of VRAM in use, you are likely hitting this issue (heap not returning freed buffers to the driver).
Luckily, you can mitigate this by configuring the NVIDIA drivers with a per-process application profile as follows:
* `sudo mkdir -p /etc/nvidia/nvidia-application-profiles-rc.d` to make the config dir if it does not exist (it most likely does not if you are reading this)
* write the following JSON blob to set the `GLVidHeapReuseRatio` config value for the `niri` process into the file `/etc/nvidia/nvidia-application-profiles-rc.d/50-limit-free-buffer-pool-in-wayland-compositors.json`:
```json
{
"rules": [
{
"pattern": {
"feature": "procname",
"matches": "niri"
},
"profile": "Limit Free Buffer Pool On Wayland Compositors"
}
],
"profiles": [
{
"name": "Limit Free Buffer Pool On Wayland Compositors",
"settings": [
{
"key": "GLVidHeapReuseRatio",
"value": 0
}
]
}
]
}
```
(The file in `/etc/nvidia/nvidia-application-profiles-rc.d/` can be named anything, and does not actually need an extension).
Restart niri after writing the config file to apply the change.
The upstream issue that this solution was pulled from is [here](https://github.com/NVIDIA/egl-wayland/issues/126#issuecomment-2379945259). There is a (slim) chance that NVIDIA updates their built-in application profiles to apply this to niri automatically; it is unlikely that the underlying heuristic will see a proper fix.
The fix shipped in the driver at the time of writing uses a value of 0, while the initial config posted by an Nvidia engineer approximately a year prior used a value of 1.
### Screencast flickering fix
<sup>Until: next release</sup>
If you have screencast glitches or flickering on NVIDIA, set this in the niri config:
```kdl,must-fail
debug {
wait-for-frame-completion-in-pipewire
}
```
This will become unnecessary once niri supports explicit sync for PipeWire screencasts: https://github.com/YaLTeR/niri/issues/1432
+116
View File
@@ -0,0 +1,116 @@
### Overview
<sup>Since: 25.05</sup>
The Overview is a zoomed-out view of your workspaces and windows.
It lets you see what's going on at a glance, navigate, and drag windows around.
<video controls src="https://github.com/user-attachments/assets/379a5d1f-acdb-4c11-b36c-e85fd91f0995">
https://github.com/user-attachments/assets/379a5d1f-acdb-4c11-b36c-e85fd91f0995
</video>
Open it with the `toggle-overview` bind, via the top-left hot corner, or using a touchpad four-finger swipe up.
While in the overview, all keyboard shortcuts keep working, while pointing devices get easier:
- Mouse: left click and drag windows to move them, right click and drag to scroll workspaces left/right, scroll to switch workspaces (no holding Mod required).
- Touchpad: two-finger scrolling that matches the normal three-finger gestures.
- Touchscreen: one-finger scrolling, or one-finger long press to move a window.
> [!TIP]
> The overview needs to draw a background under every workspace.
> So, layer-shell surfaces work this way: the *background* and *bottom* layers zoom out together with the workspaces, while the *top* and *overlay* layers remain on top of the overview.
>
> Put your bar on the *top* layer.
Drag-and-drop will scroll the workspaces up/down in the overview, and will activate a workspace when holding it for a moment.
Combined with the hot corner, this lets you do a mouse-only DnD across workspaces.
<video controls src="https://github.com/user-attachments/assets/5f09c5b7-ff40-462b-8b9c-f1b8073a2cbb">
https://github.com/user-attachments/assets/5f09c5b7-ff40-462b-8b9c-f1b8073a2cbb
</video>
You can also drag-and-drop a window to a new workspace above, below, or between existing workspaces.
<video controls src="https://github.com/user-attachments/assets/b76d5349-aa20-4889-ab90-0a51554c789d">
https://github.com/user-attachments/assets/b76d5349-aa20-4889-ab90-0a51554c789d
</video>
### Configuration
See the full documentation for the `overview {}` section [here](./Configuration:-Miscellaneous.md#overview).
You can set the zoom-out level like this:
```kdl
// Make workspaces four times smaller than normal in the overview.
overview {
zoom 0.25
}
```
To change the color behind the workspaces, use the `backdrop-color` setting:
```kdl
// Make the backdrop light.
overview {
backdrop-color "#777777"
}
```
You can also disable the hot corner:
```kdl
// Disable the hot corners.
gestures {
hot-corners {
off
}
}
```
### Backdrop customization
Apart from setting a custom backdrop color like described above, you can also put a layer-shell wallpaper into the backdrop with a [layer rule](./Configuration:-Layer-Rules.md#place-within-backdrop), for example:
```kdl
// Put swaybg inside the overview backdrop.
layer-rule {
match namespace="^wallpaper$"
place-within-backdrop true
}
```
This will only work for *background* layer surfaces that ignore exclusive zones (typical for wallpaper tools).
You can run two different wallpaper tools (like swaybg and swww), one for the backdrop and one for the normal workspace background.
This way you could set the backdrop one to a blurred version of the wallpaper for a nice effect.
You can also combine this with a transparent background color if you don't like the wallpaper moving together with workspaces:
```kdl
// Make the wallpaper stationary, rather than moving with workspaces.
layer-rule {
// This is for swaybg; change for other wallpaper tools.
// Find the right namespace by running niri msg layers.
match namespace="^wallpaper$"
place-within-backdrop true
}
// Set transparent workspace background color.
layout {
background-color "transparent"
}
// Optionally, disable the workspace shadows in the overview.
overview {
workspace-shadow {
off
}
}
```
@@ -28,6 +28,22 @@ To do that, put files into the correct directories according to this table.
Doing this will make niri appear in GDM and other display managers.
### Running tests
A bulk of our tests spawn niri compositor instances and test Wayland clients.
This does not require a graphical session, however due to test parallelism, it can run into file descriptor limits on high core count systems.
If you run into this problem, you may need to limit not just the Rust test harness thread count, but also the Rayon thread count, since some niri tests use internal Rayon threading:
```
$ export RAYON_NUM_THREADS=2
...proceed to run cargo test, perhaps with --test-threads=2
```
Don't forget to exclude the development-only `niri-visual-tests` crate when running tests.
You may also want to set the `RUN_SLOW_TESTS=1` environment variable to run the slower tests.
### Version string
The niri version string includes its version and commit hash:
+15
View File
@@ -0,0 +1,15 @@
Welcome to the niri documentation!
Feel free to look through usage and [Getting started](./Getting-Started.md).
If you're looking for ways to configure niri, check out the [introduction to configuration](./Configuration:-Introduction.md).
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](https://github.com/YaLTeR/niri/blob/main/CONTRIBUTING.md) for an overview.
If you're not already here, check out our new wiki website! https://yalter.github.io/niri/
---
The documentation is open to contribution, see [Documenting niri](./Development:-Documenting-niri.md).
Please discuss bigger changes in [our Matrix room](https://matrix.to/#/#niri:matrix.org) first!
The wiki is generated from files in the `docs/wiki/` folder of the repository, so you can open a pull request modifying it there.
@@ -46,7 +46,7 @@ Check [the corresponding wiki section](./Configuration:-Window-Rules.md#block-ou
### Dynamic screencast target
<sup>Since: next release</sup>
<sup>Since: 25.05</sup>
Niri provides a special screencast stream that you can change dynamically.
It shows up as "niri Dynamic Cast Target" in the screencast window dialog.
@@ -66,8 +66,12 @@ You can also use these actions from the command line, for example to interactive
$ niri msg action set-dynamic-cast-window --id $(niri msg --json pick-window | jq .id)
```
<video controls src="https://github.com/user-attachments/assets/c617a9d6-7d5e-4f1f-b8cc-9301182d9634">
https://github.com/user-attachments/assets/c617a9d6-7d5e-4f1f-b8cc-9301182d9634
</video>
If the cast target disappears (e.g. the target window closes), the stream goes back to empty.
All dynamic casts share the same target, but new ones start out empty until the next time you change it (to avoid surprises and sharing something sensitive by mistake).
@@ -76,10 +80,10 @@ All dynamic casts share the same target, but new ones start out empty until the
<sup>Since: 25.02</sup>
The [`is-window-cast-target=true` window rule](./Configuration:-Window-Rules.md#is-window-cast-target) matches windows targetted by an ongoing window screencast.
The [`is-window-cast-target=true` window rule](./Configuration:-Window-Rules.md#is-window-cast-target) matches windows targeted by an ongoing window screencast.
You use it with a special border color to clearly indicate screencasted windows.
This also works for windows targetted by dynamic screencasts.
This also works for windows targeted by dynamic screencasts.
However, it will not work for windows that just happen to be visible in a full-monitor screencast.
```kdl
@@ -113,7 +117,7 @@ Example:
### Windowed (fake/detached) fullscreen
<sup>Since: next release</sup>
<sup>Since: 25.05</sup>
When screencasting browser-based presentations like Google Slides, you usually want to hide the browser UI, which requires making the browser fullscreen.
This is not always convenient, for example if you have an ultrawide monitor, or just want to leave the browser as a smaller window, without taking up an entire monitor.
+1 -1
View File
@@ -32,4 +32,4 @@ This is especially useful for thicker tab indicators, or when you have very smal
| Default | `place-within-column` |
| --- | --- |
| ![](https://github.com/user-attachments/assets/c2f51f50-3d87-403a-8beb-cbbe5ec5c880) | ![](https://github.com/user-attachments/assets/f1797cd0-d518-4be6-95b4-3540523c4370) |
| ![A screenshot showing 4 windows, with the middle column being focused. The tab indicator overflows onto the left column](https://github.com/user-attachments/assets/c2f51f50-3d87-403a-8beb-cbbe5ec5c880) | ![A screenshot showing 4 windows, with the middle column being focused. The tab indicator is contained within its respective column](https://github.com/user-attachments/assets/f1797cd0-d518-4be6-95b4-3540523c4370) |
+11 -2
View File
@@ -1,11 +1,20 @@
X11 is very cursed, so built-in Xwayland support is not planned at the moment.
X11 is very cursed, so built-in Xwayland support [is not planned at the moment](./FAQ.md#why-doesnt-niri-integrate-xwayland-like-other-compositors).
However, there are multiple solutions to running X11 apps in niri.
## Using xwayland-satellite
[xwayland-satellite] implements rootless Xwayland in a separate application, without the host compositor's involvement.
It makes X11 windows appear as normal windows, just like a native Xwayland integration.
While it is still somewhat experimental, it handles a lot of applications correctly, like Steam, games and Discord.
xwayland-satellite works well with most applications: Steam, games, Discord, even more exotic things like Ardour with wine Windows VST plugins.
However, X11 apps that want to position windows or bars at specific screen coordinates won't behave correctly.
> [!NOTE]
> In the next release, niri will have [built-in xwayland-satellite integration](./Configuration:-Miscellaneous.md#xwayland-satellite).
> You can try it by installing git versions of both niri and xwayland-satellite.
> With no further configuration, niri will create X11 sockets, then when an X11 client connects, automatically start xwayland-satellite.
>
> This matches how other compositors run Xwayland (but in niri's case, it's xwayland-satellite rather than Xwayland itself).
> It also makes X11 apps work fine in `spawn-at-startup` and in XDG autostart.
Install it from your package manager, or build it according to instructions from its README, then run the `xwayland-satellite` binary.
Look for a log message like: `Connected to Xwayland on :0`.
+4 -1
View File
@@ -5,17 +5,19 @@
* [Workspaces](./Workspaces.md)
* [Floating Windows](./Floating-Windows.md)
* [Tabs](./Tabs.md)
* [Overview](./Overview.md)
* [Screencasting](./Screencasting.md)
* [LayerShell Components](./Layer%E2%80%90Shell-Components.md)
* [IPC, `niri msg`](./IPC.md)
* [Application-Specific Issues](./Application-Issues.md)
* [Nvidia](./Nvidia.md)
* [Xwayland](./Xwayland.md)
* [Gestures](./Gestures.md)
* [Packaging niri](./Packaging-niri.md)
* [FAQ](./FAQ.md)
## Configuration
* [Overview](./Configuration:-Overview.md)
* [Introduction](./Configuration:-Introduction.md)
* [Input](./Configuration:-Input.md)
* [Outputs](./Configuration:-Outputs.md)
* [Key Bindings](./Configuration:-Key-Bindings.md)
@@ -32,6 +34,7 @@
## Development
* [Design Principles](./Development:-Design-Principles.md)
* [Developing niri](./Development:-Developing-niri.md)
* [Documenting niri](./Development:-Documenting-niri.md)
* [Fractional Layout](./Development:-Fractional-Layout.md)
* [Redraw Loop](./Development:-Redraw-Loop.md)
* [Animation Timing](./Development:-Animation-Timing.md)
+405
View File
@@ -0,0 +1,405 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="512"
height="512.00006"
viewBox="0 0 135.46667 135.46668"
version="1.1"
id="svg1"
sodipodi:docname="icon.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:zoom="0.8030909"
inkscape:cx="26.14897"
inkscape:cy="535.43129"
inkscape:window-width="2528"
inkscape:window-height="1408"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="g71" />
<defs
id="defs1">
<filter
style="color-interpolation-filters:sRGB"
id="filter21"
x="-0.35129357"
y="-0.93287114"
width="1.7025871"
height="2.8657423">
<feGaussianBlur
stdDeviation="5.0792937"
id="feGaussianBlur21" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter22"
x="-0.42891072"
y="-0.64938287"
width="1.8578214"
height="2.2987657">
<feGaussianBlur
stdDeviation="6.5904956"
id="feGaussianBlur22" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter23"
x="-0.41511482"
y="-0.64325018"
width="1.8302296"
height="2.2865004">
<feGaussianBlur
stdDeviation="7.8584288"
id="feGaussianBlur23" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter24"
x="-0.36140346"
y="-0.92623631"
width="1.7228069"
height="2.8524726">
<feGaussianBlur
stdDeviation="5.269127"
id="feGaussianBlur24" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter27"
x="-0.17576354"
y="-0.83601771"
width="1.3515271"
height="2.6720354">
<feGaussianBlur
stdDeviation="4.753432"
id="feGaussianBlur26" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter52"
x="-0.33025388"
y="-1.0968854"
width="1.6605078"
height="3.1937708">
<feGaussianBlur
stdDeviation="4.2575558"
id="feGaussianBlur52" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter53"
x="-0.34014132"
y="-1.0243618"
width="1.6802826"
height="3.0487236">
<feGaussianBlur
stdDeviation="4.3187927"
id="feGaussianBlur54" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter55"
x="-0.33171227"
y="-1.0929411"
width="1.6634245"
height="3.1858823">
<feGaussianBlur
stdDeviation="4.4263355"
id="feGaussianBlur55" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter56"
x="-0.34596671"
y="-0.98818076"
width="1.6919334"
height="2.9763615">
<feGaussianBlur
stdDeviation="4.9267071"
id="feGaussianBlur56" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter57"
x="-0.50604737"
y="-0.53225252"
width="2.0120947"
height="2.064505">
<feGaussianBlur
stdDeviation="5.8261111"
id="feGaussianBlur57" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter58"
x="-0.32130078"
y="-1.1307663"
width="1.6426016"
height="3.2615325">
<feGaussianBlur
stdDeviation="4.2390405"
id="feGaussianBlur58" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter59"
x="-0.4030115"
y="-0.71156066"
width="1.806023"
height="2.4231213">
<feGaussianBlur
stdDeviation="4.4950086"
id="feGaussianBlur59" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter60"
x="-0.1759294"
y="-1.0177407"
width="1.3518588"
height="3.0354814">
<feGaussianBlur
stdDeviation="4.8003951"
id="feGaussianBlur60" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter70"
x="-0.43159762"
y="-0.3122953"
width="1.8631952"
height="1.6245906">
<feGaussianBlur
stdDeviation="18.461288"
id="feGaussianBlur70" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter72"
x="-0.43271319"
y="-0.31310251"
width="1.8654264"
height="1.626205">
<feGaussianBlur
stdDeviation="18.509006"
id="feGaussianBlur72" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter1"
x="-0.45705071"
y="-0.57220236"
width="1.9141014"
height="2.1444047">
<feGaussianBlur
stdDeviation="8.5810337"
id="feGaussianBlur1" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter2"
x="-0.545201"
y="-0.88686217"
width="2.090402"
height="2.7737243">
<feGaussianBlur
stdDeviation="4.3199889"
id="feGaussianBlur2" />
</filter>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 452.78682,224.36663 q -8.98432,0 -12.80266,-4.94138 -3.59373,-5.16598 -4.26757,-12.80265 -0.67381,-7.86128 -0.67381,-15.72256 0,-11.90423 -3.36913,-19.09168 -3.36912,-7.41207 -11.90421,-7.41207 -7.63667,0 -11.2304,7.41207 -3.59373,7.18745 -3.59373,19.09168 0,7.86128 -0.67384,15.49795 -0.44921,7.63667 -4.04294,12.80266 -3.59373,4.94137 -13.02726,4.94137 -6.96286,0 -11.67961,-5.16598 -4.49217,-5.16599 -6.96285,-13.47648 -2.47068,-8.3105 -3.59373,-17.96864 -0.89842,-9.65815 -0.89842,-18.64247 0,-8.98432 0.89842,-18.41785 0.89844,-9.43354 3.14452,-17.51943 2.47068,-8.08588 6.96285,-13.02726 4.49215,-4.94138 11.67961,-4.94138 12.80266,0 15.94715,11.67962 2.69531,-2.9199 8.53512,-5.39059 6.0644,-2.6953 13.70107,-2.6953 17.29484,0 28.30063,8.75971 11.00577,8.75972 15.94715,24.25767 5.16599,15.27334 4.94139,35.48806 0,10.33197 -2.02147,18.86707 -1.79687,8.3105 -6.51365,13.47648 -4.49215,4.94138 -12.80263,4.94138 z"
id="path5" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath5">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 452.78682,224.36663 q -8.98432,0 -12.80266,-4.94138 -3.59373,-5.16598 -4.26757,-12.80265 -0.67381,-7.86128 -0.67381,-15.72256 0,-11.90423 -3.36913,-19.09168 -3.36912,-7.41207 -11.90421,-7.41207 -7.63667,0 -11.2304,7.41207 -3.59373,7.18745 -3.59373,19.09168 0,7.86128 -0.67384,15.49795 -0.44921,7.63667 -4.04294,12.80266 -3.59373,4.94137 -13.02726,4.94137 -6.96286,0 -11.67961,-5.16598 -4.49217,-5.16599 -6.96285,-13.47648 -2.47068,-8.3105 -3.59373,-17.96864 -0.89842,-9.65815 -0.89842,-18.64247 0,-8.98432 0.89842,-18.41785 0.89844,-9.43354 3.14452,-17.51943 2.47068,-8.08588 6.96285,-13.02726 4.49215,-4.94138 11.67961,-4.94138 12.80266,0 15.94715,11.67962 2.69531,-2.9199 8.53512,-5.39059 6.0644,-2.6953 13.70107,-2.6953 17.29484,0 28.30063,8.75971 11.00577,8.75972 15.94715,24.25767 5.16599,15.27334 4.94139,35.48806 0,10.33197 -2.02147,18.86707 -1.79687,8.3105 -6.51365,13.47648 -4.49215,4.94138 -12.80263,4.94138 z"
id="path8" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath8">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 452.78682,224.36663 q -8.98432,0 -12.80266,-4.94138 -3.59373,-5.16598 -4.26757,-12.80265 -0.67381,-7.86128 -0.67381,-15.72256 0,-11.90423 -3.36913,-19.09168 -3.36912,-7.41207 -11.90421,-7.41207 -7.63667,0 -11.2304,7.41207 -3.59373,7.18745 -3.59373,19.09168 0,7.86128 -0.67384,15.49795 -0.44921,7.63667 -4.04294,12.80266 -3.59373,4.94137 -13.02726,4.94137 -6.96286,0 -11.67961,-5.16598 -4.49217,-5.16599 -6.96285,-13.47648 -2.47068,-8.3105 -3.59373,-17.96864 -0.89842,-9.65815 -0.89842,-18.64247 0,-8.98432 0.89842,-18.41785 0.89844,-9.43354 3.14452,-17.51943 2.47068,-8.08588 6.96285,-13.02726 4.49215,-4.94138 11.67961,-4.94138 12.80266,0 15.94715,11.67962 2.69531,-2.9199 8.53512,-5.39059 6.0644,-2.6953 13.70107,-2.6953 17.29484,0 28.30063,8.75971 11.00577,8.75972 15.94715,24.25767 5.16599,15.27334 4.94139,35.48806 0,10.33197 -2.02147,18.86707 -1.79687,8.3105 -6.51365,13.47648 -4.49215,4.94138 -12.80263,4.94138 z"
id="path11" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath11">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 452.78682,224.36663 q -8.98432,0 -12.80266,-4.94138 -3.59373,-5.16598 -4.26757,-12.80265 -0.67381,-7.86128 -0.67381,-15.72256 0,-11.90423 -3.36913,-19.09168 -3.36912,-7.41207 -11.90421,-7.41207 -7.63667,0 -11.2304,7.41207 -3.59373,7.18745 -3.59373,19.09168 0,7.86128 -0.67384,15.49795 -0.44921,7.63667 -4.04294,12.80266 -3.59373,4.94137 -13.02726,4.94137 -6.96286,0 -11.67961,-5.16598 -4.49217,-5.16599 -6.96285,-13.47648 -2.47068,-8.3105 -3.59373,-17.96864 -0.89842,-9.65815 -0.89842,-18.64247 0,-8.98432 0.89842,-18.41785 0.89844,-9.43354 3.14452,-17.51943 2.47068,-8.08588 6.96285,-13.02726 4.49215,-4.94138 11.67961,-4.94138 12.80266,0 15.94715,11.67962 2.69531,-2.9199 8.53512,-5.39059 6.0644,-2.6953 13.70107,-2.6953 17.29484,0 28.30063,8.75971 11.00577,8.75972 15.94715,24.25767 5.16599,15.27334 4.94139,35.48806 0,10.33197 -2.02147,18.86707 -1.79687,8.3105 -6.51365,13.47648 -4.49215,4.94138 -12.80263,4.94138 z"
id="path12" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath12">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 452.78682,224.36663 q -8.98432,0 -12.80266,-4.94138 -3.59373,-5.16598 -4.26757,-12.80265 -0.67381,-7.86128 -0.67381,-15.72256 0,-11.90423 -3.36913,-19.09168 -3.36912,-7.41207 -11.90421,-7.41207 -7.63667,0 -11.2304,7.41207 -3.59373,7.18745 -3.59373,19.09168 0,7.86128 -0.67384,15.49795 -0.44921,7.63667 -4.04294,12.80266 -3.59373,4.94137 -13.02726,4.94137 -6.96286,0 -11.67961,-5.16598 -4.49217,-5.16599 -6.96285,-13.47648 -2.47068,-8.3105 -3.59373,-17.96864 -0.89842,-9.65815 -0.89842,-18.64247 0,-8.98432 0.89842,-18.41785 0.89844,-9.43354 3.14452,-17.51943 2.47068,-8.08588 6.96285,-13.02726 4.49215,-4.94138 11.67961,-4.94138 12.80266,0 15.94715,11.67962 2.69531,-2.9199 8.53512,-5.39059 6.0644,-2.6953 13.70107,-2.6953 17.29484,0 28.30063,8.75971 11.00577,8.75972 15.94715,24.25767 5.16599,15.27334 4.94139,35.48806 0,10.33197 -2.02147,18.86707 -1.79687,8.3105 -6.51365,13.47648 -4.49215,4.94138 -12.80263,4.94138 z"
id="path14" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath15">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 511.63431,224.36663 q -8.98433,0 -13.47647,-5.16598 -4.26755,-5.16599 -5.83981,-15.72256 -1.34765,-10.78119 -1.57226,-27.62679 0,-16.8456 1.34763,-27.62678 1.57226,-10.78119 6.06444,-15.72256 4.49214,-5.16599 13.47647,-5.16599 8.98432,0 13.25187,5.16599 4.49217,4.94137 6.06443,15.72256 1.57223,10.78118 1.57223,27.62678 0.22461,16.8456 -1.34762,27.62679 -1.57226,10.55657 -6.06444,15.72256 -4.49215,5.16598 -13.47647,5.16598 z"
id="path16" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath17">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 681.32926,224.3022 q -8.98433,0 -13.47647,-5.16597 -4.26755,-5.16599 -5.83981,-15.72257 -1.34765,-10.78118 -1.57226,-27.62678 0,-16.8456 1.34763,-27.62678 1.57226,-10.78119 6.06444,-15.72257 4.49214,-5.16598 13.47647,-5.16598 8.98432,0 13.25187,5.16598 4.49217,4.94138 6.06443,15.72257 1.57223,10.78118 1.57223,27.62678 0.22461,16.8456 -1.34762,27.62678 -1.57226,10.55658 -6.06444,15.72257 -4.49215,5.16597 -13.47647,5.16597 z"
id="path17" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath18">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 573.177,224.36663 q -7.63667,0 -12.57805,-4.94138 -4.71678,-5.16598 -7.18746,-13.70108 -2.47068,-8.53511 -3.36913,-19.5409 -0.89842,-11.00579 -0.89842,-22.68541 0,-7.86128 0.22461,-15.94717 0.44921,-8.31049 2.24607,-15.27334 2.02147,-6.96285 6.51362,-11.2304 4.71678,-4.49216 13.25187,-4.49216 6.06443,0 11.00582,2.9199 4.94136,2.6953 6.28901,8.3105 5.16599,-4.71677 13.02727,-6.73824 8.08587,-2.24608 16.62099,-2.24608 7.18746,0 14.59952,3.59373 7.41207,3.36912 12.57803,9.43353 5.16599,6.06442 5.16599,13.70109 0,6.51363 -4.94136,12.35344 -4.71678,5.83981 -13.4765,5.83981 -3.81831,0 -6.28901,-0.89843 -2.47068,-1.12304 -4.71676,-2.02147 -2.2461,-0.89844 -5.39059,-0.89844 -8.31051,0 -15.27337,6.73824 -6.73822,6.51364 -6.73822,17.74404 0,5.8398 -0.44921,12.80265 -0.22463,6.73824 -2.02147,13.02727 -1.57226,6.28902 -5.83983,10.33196 -4.26754,3.81834 -12.35342,3.81834 z"
id="path19" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath19">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 573.177,224.36663 q -7.63667,0 -12.57805,-4.94138 -4.71678,-5.16598 -7.18746,-13.70108 -2.47068,-8.53511 -3.36913,-19.5409 -0.89842,-11.00579 -0.89842,-22.68541 0,-7.86128 0.22461,-15.94717 0.44921,-8.31049 2.24607,-15.27334 2.02147,-6.96285 6.51362,-11.2304 4.71678,-4.49216 13.25187,-4.49216 6.06443,0 11.00582,2.9199 4.94136,2.6953 6.28901,8.3105 5.16599,-4.71677 13.02727,-6.73824 8.08587,-2.24608 16.62099,-2.24608 7.18746,0 14.59952,3.59373 7.41207,3.36912 12.57803,9.43353 5.16599,6.06442 5.16599,13.70109 0,6.51363 -4.94136,12.35344 -4.71678,5.83981 -13.4765,5.83981 -3.81831,0 -6.28901,-0.89843 -2.47068,-1.12304 -4.71676,-2.02147 -2.2461,-0.89844 -5.39059,-0.89844 -8.31051,0 -15.27337,6.73824 -6.73822,6.51364 -6.73822,17.74404 0,5.8398 -0.44921,12.80265 -0.22463,6.73824 -2.02147,13.02727 -1.57226,6.28902 -5.83983,10.33196 -4.26754,3.81834 -12.35342,3.81834 z"
id="path20" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath20">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 573.177,224.36663 q -7.63667,0 -12.57805,-4.94138 -4.71678,-5.16598 -7.18746,-13.70108 -2.47068,-8.53511 -3.36913,-19.5409 -0.89842,-11.00579 -0.89842,-22.68541 0,-7.86128 0.22461,-15.94717 0.44921,-8.31049 2.24607,-15.27334 2.02147,-6.96285 6.51362,-11.2304 4.71678,-4.49216 13.25187,-4.49216 6.06443,0 11.00582,2.9199 4.94136,2.6953 6.28901,8.3105 5.16599,-4.71677 13.02727,-6.73824 8.08587,-2.24608 16.62099,-2.24608 7.18746,0 14.59952,3.59373 7.41207,3.36912 12.57803,9.43353 5.16599,6.06442 5.16599,13.70109 0,6.51363 -4.94136,12.35344 -4.71678,5.83981 -13.4765,5.83981 -3.81831,0 -6.28901,-0.89843 -2.47068,-1.12304 -4.71676,-2.02147 -2.2461,-0.89844 -5.39059,-0.89844 -8.31051,0 -15.27337,6.73824 -6.73822,6.51364 -6.73822,17.74404 0,5.8398 -0.44921,12.80265 -0.22463,6.73824 -2.02147,13.02727 -1.57226,6.28902 -5.83983,10.33196 -4.26754,3.81834 -12.35342,3.81834 z"
id="path21" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath21">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 573.177,224.36663 q -7.63667,0 -12.57805,-4.94138 -4.71678,-5.16598 -7.18746,-13.70108 -2.47068,-8.53511 -3.36913,-19.5409 -0.89842,-11.00579 -0.89842,-22.68541 0,-7.86128 0.22461,-15.94717 0.44921,-8.31049 2.24607,-15.27334 2.02147,-6.96285 6.51362,-11.2304 4.71678,-4.49216 13.25187,-4.49216 6.06443,0 11.00582,2.9199 4.94136,2.6953 6.28901,8.3105 5.16599,-4.71677 13.02727,-6.73824 8.08587,-2.24608 16.62099,-2.24608 7.18746,0 14.59952,3.59373 7.41207,3.36912 12.57803,9.43353 5.16599,6.06442 5.16599,13.70109 0,6.51363 -4.94136,12.35344 -4.71678,5.83981 -13.4765,5.83981 -3.81831,0 -6.28901,-0.89843 -2.47068,-1.12304 -4.71676,-2.02147 -2.2461,-0.89844 -5.39059,-0.89844 -8.31051,0 -15.27337,6.73824 -6.73822,6.51364 -6.73822,17.74404 0,5.8398 -0.44921,12.80265 -0.22463,6.73824 -2.02147,13.02727 -1.57226,6.28902 -5.83983,10.33196 -4.26754,3.81834 -12.35342,3.81834 z"
id="path22" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath23">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 681.43807,224.36663 q -8.98432,0 -13.47647,-5.16598 -4.26757,-5.16599 -5.83983,-15.72256 -1.34763,-10.78119 -1.57226,-27.62679 0,-16.8456 1.34765,-27.62678 1.57226,-10.78119 6.06444,-15.72256 4.49215,-5.16599 13.47647,-5.16599 8.98432,0 13.25187,5.16599 4.49215,4.94137 6.06441,15.72256 1.57226,10.78118 1.57226,27.62678 0.2246,16.8456 -1.34766,27.62679 -1.57223,10.55657 -6.06441,15.72256 -4.49215,5.16598 -13.47647,5.16598 z"
id="path25" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath25">
<path
style="font-size:224.608px;line-height:393.415px;font-family:'Cherry Bomb One';-inkscape-font-specification:'Cherry Bomb One';letter-spacing:0px;fill:#259eb4;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 681.43807,224.36663 q -8.98432,0 -13.47647,-5.16598 -4.26757,-5.16599 -5.83983,-15.72256 -1.34763,-10.78119 -1.57226,-27.62679 0,-16.8456 1.34765,-27.62678 1.57226,-10.78119 6.06444,-15.72256 4.49215,-5.16599 13.47647,-5.16599 8.98432,0 13.25187,5.16599 4.49215,4.94137 6.06441,15.72256 1.57226,10.78118 1.57226,27.62678 0.2246,16.8456 -1.34766,27.62679 -1.57223,10.55657 -6.06441,15.72256 -4.49215,5.16598 -13.47647,5.16598 z"
id="path26" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath34">
<path
id="path35"
style="fill:#259eb4;fill-opacity:1;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 169.33334,220.13334 c 0,8.46667 -4.23334,16.93333 -33.86667,16.93333 -29.63333,0 -33.86667,-8.46666 -33.86667,-16.93333 0,-12.7 8.46667,-21.16667 33.86667,-21.16667 25.4,0 33.86667,8.46667 33.86667,21.16667 z" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath35">
<path
id="path36"
style="fill:#259eb4;fill-opacity:1;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 715.91343,141.3418 c 0,8.46667 -4.23334,16.93332 -33.86667,16.93332 -29.63333,0 -33.86667,-8.46665 -33.86667,-16.93332 0,-12.7 8.46667,-21.16668 33.86667,-21.16668 25.4,0 33.86667,8.46668 33.86667,21.16668 z" />
</clipPath>
<filter
style="color-interpolation-filters:sRGB"
id="filter61"
x="-0.43233622"
y="-0.31282974"
width="1.8646724"
height="1.6256595">
<feGaussianBlur
stdDeviation="18.492881"
id="feGaussianBlur61" />
</filter>
</defs>
<g
id="layer1"
transform="translate(255.60477,-19.034522)">
<g
id="g71"
transform="matrix(0.53845513,0,0,0.53845513,-260.51955,13.25883)"
inkscape:label="ICON">
<g
id="g4"
inkscape:label="OUTLINE">
<path
id="path1"
style="display:inline;fill:#2d2d2d;fill-opacity:1;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 131.35535,193.41317 c -8.42529,0.21555 -17.07195,1.23898 -24.70899,5.03516 -6.56852,3.28887 -11.780948,9.56904 -13.037575,16.89416 -1.12503,5.50318 -0.847502,11.50687 1.819693,16.54193 2.619641,4.74577 7.282642,8.08459 12.343352,9.82958 7.20278,2.70364 14.97875,3.20323 22.59699,3.46523 7.89843,0.20478 15.85819,-0.17121 23.61105,-1.76836 5.63625,-1.25422 11.31076,-3.51115 15.35105,-7.77992 3.29144,-3.52234 5.05422,-8.32066 5.11255,-13.1185 0.31661,-6.70741 -1.69285,-13.72981 -6.39837,-18.65616 -4.18578,-4.5464 -10.04779,-7.11576 -15.95626,-8.569 -6.77112,-1.66654 -13.79057,-1.92415 -20.73349,-1.87412 z" />
<path
id="path4"
style="display:inline;mix-blend-mode:normal;fill:#2d2d2d;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;stroke-opacity:1;paint-order:stroke fill markers"
d="m 98.902224,36.772549 c -6.995893,0.126233 -13.62619,4.553849 -16.638172,10.834978 -3.470673,6.368967 -4.476788,13.68672 -5.225527,20.799337 -1.546324,15.903589 -0.51861,31.905986 -1.354082,47.842876 -0.544064,12.91133 -1.490643,25.96714 0.724426,38.77934 1.594594,9.15149 5.382372,18.1514 11.945332,24.8552 5.649973,5.83947 12.892719,10.17523 20.761639,12.23377 4.29395,0.94959 9.28733,-0.57303 11.73776,-4.36606 2.38164,-3.59662 2.34796,-8.32076 0.82613,-12.24486 -1.20789,-3.11502 -2.64307,-6.14315 -3.64842,-9.33584 -1.12185,-3.39459 -1.94228,-6.99797 -2.3869,-10.47882 -0.55748,-4.05967 -0.49766,-8.22945 -0.15435,-12.24032 0.58298,-6.27022 1.46357,-12.5645 3.39036,-18.57849 0.79153,-2.26867 1.52928,-4.64049 3.02766,-6.55814 5.54574,0.77098 10.63142,3.47347 15.10865,6.73077 1.80507,1.34294 3.49258,2.79574 5.00233,4.33482 4.14952,4.21383 7.69916,9.25861 9.14438,15.0671 1.23316,4.77068 1.46924,9.85005 0.41871,14.67703 -1.02032,4.50982 -3.25363,8.60065 -5.45452,12.62181 -1.87577,3.646 -3.05511,7.8744 -2.17051,11.96837 0.96209,4.20638 4.82507,7.5927 9.1658,7.8093 4.52117,0.38592 8.79301,-1.6188 12.64582,-3.75368 9.91038,-5.51624 17.57193,-14.7796 21.44242,-25.41236 3.56981,-9.82442 4.74142,-20.45137 3.89537,-30.84701 -1.23706,-11.29301 -6.03879,-21.87272 -12.00583,-31.42104 -8.7119,-13.884894 -20.08721,-25.908588 -32.38582,-36.666079 -9.92644,-8.582365 -20.62052,-16.394651 -32.3549,-22.32888 -4.66406,-2.261816 -9.65523,-4.278849 -14.913576,-4.33312 -0.18139,0.0033 -0.36279,0.0067 -0.54418,0.01 z" />
</g>
<g
id="g26"
clip-path="none"
style="display:inline"
inkscape:label="STUB">
<path
id="path2"
style="fill:#259eb4;fill-opacity:1;stroke-width:2.11667;stroke-linecap:square;paint-order:stroke fill markers"
d="m 169.33334,220.13334 c 0,8.46667 -4.23334,16.93333 -33.86667,16.93333 -29.63333,0 -33.86667,-8.46666 -33.86667,-16.93333 0,-12.7 8.46667,-21.16667 33.86667,-21.16667 25.4,0 33.86667,8.46667 33.86667,21.16667 z" />
<path
style="mix-blend-mode:normal;fill:#92cfda;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.292;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;filter:url(#filter27)"
d="m 649.45734,133.81724 c 0.30861,-0.52382 1.24567,-1.10943 2.25778,-1.9344 0.71834,-0.58551 1.60294,-1.1585 2.689,-1.71704 1.33566,-0.68692 2.82604,-1.27591 4.41873,-1.81477 0.91309,-0.30893 1.90318,-0.61043 2.97552,-0.89949 2.75909,-0.74374 5.93213,-1.36936 9.45117,-1.81993 3.4485,-0.44153 7.02191,-0.68799 10.54487,-0.74159 0.11888,-0.002 0.23758,-0.003 0.35611,-0.005 3.42087,-0.0395 6.87572,0.10105 10.20745,0.42751 3.52675,0.34557 6.72,0.8799 9.50577,1.55294 1.13268,0.27365 2.17777,0.56526 3.14025,0.86932 1.5536,0.49082 3.01719,1.0374 4.3387,1.68661 1.10269,0.54172 2.00605,1.10621 2.74422,1.69041 1.03948,0.82267 1.92442,1.4682 2.24848,1.99812 -0.19311,-0.57592 -0.56732,-1.6128 -1.44388,-2.71822 -0.62575,-0.78911 -1.46647,-2.06647 -2.53663,-2.85214 -1.27528,-0.93627 -2.69843,-2.19648 -4.28815,-2.8662 -0.98885,-0.41658 -2.24548,-1.23914 -3.41727,-1.59811 -2.87657,-0.88121 -5.61102,-1.58246 -9.24402,-2.0046 -3.43498,-0.39913 -7.78163,-0.93367 -11.29835,-0.89735 -0.12203,0.001 -0.24424,0.003 -0.36663,0.005 -3.62086,0.0519 -8.29298,0.61115 -11.8461,1.12441 -3.62258,0.5233 -6.54204,1.50557 -9.38537,2.45693 -1.10746,0.37055 -2.4353,1.22472 -3.37108,1.64065 -1.62494,0.72224 -2.75555,1.66679 -4.03455,2.65099 -1.04655,0.80534 -1.65707,2.24134 -2.25723,3.03279 -0.84139,1.10955 -1.24261,2.1654 -1.41747,2.7334 z"
id="path24"
transform="translate(-546.58009,78.791545)"
clip-path="url(#clipPath35)"
sodipodi:nodetypes="csssssccssssscsssssccssssscc" />
<path
style="mix-blend-mode:normal;fill:#134f5a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.292;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter60)"
d="m 102.62873,226.09888 c 0.21837,0.59119 0.61147,1.63901 1.62645,2.90953 0.71917,0.90024 1.67343,1.81283 2.88011,2.66136 0.63885,0.44924 1.326,0.86437 2.04583,1.23422 1.73607,0.89199 3.88794,1.6902 6.44451,2.35832 3.15978,0.82576 6.73316,1.3998 10.52375,1.74639 2.77174,0.25344 5.543,0.37487 8.21345,0.40382 1.03453,0.0112 2.07172,0.008 3.10774,-0.0105 3.80268,-0.0675 7.55355,-0.33754 11.05616,-0.82447 3.61058,-0.50195 6.89851,-1.22612 9.69476,-2.17075 0.18263,-0.0617 0.36305,-0.1243 0.54123,-0.1878 2.50252,-0.89183 4.82056,-2.11237 6.51802,-3.52561 0.94359,-0.78561 1.6151,-1.56242 2.06492,-2.2946 0.63371,-1.03151 0.74175,-1.832 0.76927,-2.29791 -0.27946,0.40619 -0.77594,0.89664 -1.67451,1.38662 -0.63117,0.34418 -1.42595,0.67135 -2.41953,0.98728 -1.84319,0.58607 -3.98976,1.02107 -6.42445,1.47239 -0.16947,0.0314 -0.34092,0.0627 -0.51435,0.094 -2.66528,0.48001 -5.74678,0.9266 -9.18723,1.27047 -3.33185,0.33301 -6.89061,0.55814 -10.52391,0.6262 -0.98784,0.0185 -1.97654,0.0253 -2.96263,0.0197 -2.54936,-0.0146 -5.17908,-0.11853 -7.80849,-0.31818 -3.6162,-0.27458 -6.92286,-0.70577 -9.89494,-1.23993 -2.40547,-0.43232 -4.36461,-0.8899 -6.04479,-1.31771 -0.70208,-0.17876 -1.35634,-0.34389 -2.02406,-0.52251 -1.24448,-0.33289 -2.31304,-0.65483 -3.26912,-1.01993 -1.3453,-0.51373 -2.22471,-1.029 -2.73819,-1.44035 z"
id="path59"
clip-path="url(#clipPath34)" />
</g>
<path
style="display:inline;mix-blend-mode:normal;fill:#3ba8bc;fill-opacity:1;stroke:none;stroke-width:2.11667;stroke-linecap:square;stroke-opacity:1;paint-order:stroke fill markers"
d="m 101.6,42.333334 c 16.93334,0 84.66667,50.800005 84.66667,93.133336 0,28.57209 -13.39181,41.07402 -25.11117,46.54433 -8.87807,4.14406 -11.33775,-1.382 -6.3999,-9.88879 3.31767,-5.71559 6.11107,-12.63293 6.11107,-19.72221 0,-12.7 -4.23333,-21.16666 -12.7,-29.63333 -8.46667,-8.46667 -19.34216,-12.70001 -25.4,-12.7 -8.46666,1e-5 -12.7,24.8856 -12.7,38.1 0,10.52973 3.14292,20.01182 6.30176,26.88277 2.97912,6.48004 0.48516,10.93086 -6.19604,8.47352 -7.29956,-2.68477 -16.052373,-7.98293 -21.272388,-18.42296 -8.466666,-16.93333 -4.233333,-41.3022 -4.233333,-63.5 0,-33.866665 -7e-6,-59.266666 16.933331,-59.266666 z"
id="path3"
inkscape:label="FLAME" />
<path
style="display:inline;mix-blend-mode:normal;fill:#3ba8bc;fill-opacity:0.151125;stroke:none;stroke-width:2.11667;stroke-linecap:square;stroke-opacity:1;paint-order:stroke fill markers;filter:url(#filter70)"
d="m 101.6,42.333334 c 16.93334,0 84.66667,50.800005 84.66667,93.133336 0,28.57209 -13.39181,41.07402 -25.11117,46.54433 -8.87807,4.14406 -11.33775,-1.382 -6.3999,-9.88879 3.31767,-5.71559 6.11107,-12.63293 6.11107,-19.72221 0,-12.7 -4.23333,-21.16666 -12.7,-29.63333 -8.46667,-8.46667 -19.34216,-12.70001 -25.4,-12.7 -8.46666,1e-5 -12.7,24.8856 -12.7,38.1 0,10.52973 3.14292,20.01182 6.30176,26.88277 2.97912,6.48004 0.48516,10.93086 -6.19604,8.47352 -7.29956,-2.68477 -16.052373,-7.98293 -21.272388,-18.42296 -8.466666,-16.93333 -4.233333,-41.3022 -4.233333,-63.5 0,-33.866665 -7e-6,-59.266666 16.933331,-59.266666 z"
id="path67"
inkscape:label="GLOW" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 30 KiB

+60
View File
@@ -0,0 +1,60 @@
:root > * {
--md-primary-fg-color: #1e97b5;
--md-primary-fg-color--dark: color-mix(in srgb, var(--md-primary-fg-color), black 20%);
--md-accent-fg-color: var(--md-primary-fg-color--dark);
}
.md-logo > img {
background-color: white;
border-radius: 8px;
}
@media (prefers-color-scheme: dark) {
:root > * {
--md-primary-fg-color: #167188;
--md-accent-fg-color: #1e97b5;
--md-typeset-a-color: color-mix(in srgb, var(--md-accent-fg-color), white 30%);
}
.md-logo > img {
background-color: #eee;
}
}
.md-nav--primary .md-nav__title {
box-shadow: none;
}
@media screen and (min-width: 76.25em) {
.md-nav__title {
display: none;
}
}
@media screen and (min-width: 76.25em) {
.md-main {
min-height: 100vh;
}
}
.md-nav__link--active {
font-weight: bold;
}
.highlight .gp, .highlight .go {
user-select: none;
}
.md-source-file__fact {
visibility: hidden;
}
.badge {
font-size: 0.85em;
box-shadow: 0 0 0 1px inset var(--md-accent-fg-color--transparent);
padding: 0.2rem 0.3rem;
}
.md-typeset table:not([class]) td {
padding: .5em 1.25em;
}

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Generated
+6 -22
View File
@@ -1,27 +1,12 @@
{
"nodes": {
"nix-filter": {
"locked": {
"lastModified": 1731533336,
"narHash": "sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms=",
"owner": "numtide",
"repo": "nix-filter",
"rev": "f7653272fd234696ae94229839a99b73c9ab7de0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "nix-filter",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1742707865,
"narHash": "sha256-RVQQZy38O3Zb8yoRJhuFgWo/iDIDj0hEdRTVfhOtzRk=",
"lastModified": 1752077645,
"narHash": "sha256-HM791ZQtXV93xtCY+ZxG1REzhQenSQO020cu6rHtAPk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "dd613136ee91f67e5dba3f3f41ac99ae89c5406b",
"rev": "be9e214982e20b8310878ac2baa063a961c1bdf6",
"type": "github"
},
"original": {
@@ -33,7 +18,6 @@
},
"root": {
"inputs": {
"nix-filter": "nix-filter",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
@@ -45,11 +29,11 @@
]
},
"locked": {
"lastModified": 1742697269,
"narHash": "sha256-Lpp0XyAtIl1oGJzNmTiTGLhTkcUjwSkEb0gOiNzYFGM=",
"lastModified": 1752374969,
"narHash": "sha256-Ky3ynEkJXih7mvWyt9DWoiSiZGqPeHLU1tlBU4b0mcc=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "01973c84732f9275c50c5f075dd1f54cc04b3316",
"rev": "75fb000638e6d0f57cb1e8b7a4550cbdd8c76f1d",
"type": "github"
},
"original": {
+15 -11
View File
@@ -4,7 +4,6 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
nix-filter.url = "github:numtide/nix-filter";
# NOTE: This is not necessary for end users
# You can omit it with `inputs.rust-overlay.follows = ""`
@@ -18,7 +17,6 @@
{
self,
nixpkgs,
nix-filter,
rust-overlay,
}:
let
@@ -50,16 +48,16 @@
pname = "niri";
version = self.shortRev or self.dirtyShortRev or "unknown";
src = nix-filter.lib.filter {
root = self;
include = [
"niri-config"
"niri-ipc"
"niri-visual-tests"
"resources"
"src"
./Cargo.lock
src = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions [
./niri-config
./niri-ipc
./niri-visual-tests
./resources
./src
./Cargo.toml
./Cargo.lock
];
};
@@ -117,6 +115,12 @@
export XDG_RUNTIME_DIR="$(mktemp -d)"
'';
checkFlags = [
# These tests require the ability to access a "valid EGL Display", but that won't work
# inside the Nix sandbox
"--skip=tests::animations"
];
postInstall =
''
installShellCompletion --cmd niri \
+2 -2
View File
@@ -9,10 +9,10 @@ repository.workspace = true
[dependencies]
bitflags.workspace = true
csscolorparser = "0.7.0"
csscolorparser = "0.7.2"
knuffel = "3.2.0"
miette = { version = "5.10.0", features = ["fancy-no-backtrace"] }
niri-ipc = { version = "25.2.0", path = "../niri-ipc" }
niri-ipc = { version = "25.5.1", path = "../niri-ipc" }
regex = "1.11.1"
smithay = { workspace = true, features = ["backend_libinput"] }
tracing.workspace = true
+4
View File
@@ -15,6 +15,10 @@ pub struct LayerRule {
pub shadow: ShadowRule,
#[knuffel(child)]
pub geometry_corner_radius: Option<CornerRadius>,
#[knuffel(child, unwrap(argument))]
pub place_within_backdrop: Option<bool>,
#[knuffel(child, unwrap(argument))]
pub baba_is_float: Option<bool>,
}
#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)]
+847 -52
View File
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -56,7 +56,7 @@ fn extract_kdl_from_file(file_contents: &str, filename: &str) -> Vec<KdlCodeBloc
#[test]
fn wiki_docs_parses() {
let wiki_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../wiki");
let wiki_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../docs/wiki");
let code_blocks = fs::read_dir(wiki_dir)
.unwrap()
@@ -95,8 +95,7 @@ fn wiki_docs_parses() {
}
} else if must_fail {
errors.push(format!(
"Expected error parsing wiki KDL code block at {}:{}",
filename, line_number
"Expected error parsing wiki KDL code block at {filename}:{line_number}",
));
}
}
+1 -1
View File
@@ -13,7 +13,7 @@ readme = "README.md"
[dependencies]
clap = { workspace = true, optional = true }
schemars = { version = "0.8.22", optional = true }
schemars = { version = "1.0.4", optional = true }
serde.workspace = true
serde_json.workspace = true
+1 -1
View File
@@ -12,5 +12,5 @@ Use an exact version requirement to avoid breaking changes:
```toml
[dependencies]
niri-ipc = "=25.2.0"
niri-ipc = "=25.5.1"
```
+181 -8
View File
@@ -1,8 +1,23 @@
//! Types for communicating with niri via IPC.
//!
//! After connecting to the niri socket, you can send a single [`Request`] and receive a single
//! [`Reply`], which is a `Result` wrapping a [`Response`]. If you requested an event stream, you
//! can keep reading [`Event`]s from the socket after the response.
//! After connecting to the niri socket, you can send [`Request`]s. Niri will process them one by
//! one, in order, and to each request it will respond with a single [`Reply`], which is a `Result`
//! wrapping a [`Response`].
//!
//! If you send a [`Request::EventStream`], niri will *stop* reading subsequent [`Request`]s, and
//! will start continuously writing compositor [`Event`]s to the socket. If you'd like to read an
//! event stream and write more requests at the same time, you need to use two IPC sockets.
//!
//! <div class="warning">
//!
//! Requests are *always* processed separately. Time passes between requests, even when sending
//! multiple requests to the socket at once. For example, sending [`Request::Workspaces`] and
//! [`Request::Windows`] together may not return consistent results (e.g. a window may open on a
//! new workspace in-between the two responses). This goes for actions too: sending
//! [`Action::FocusWindow`] and <code>[Action::CloseWindow] { id: None }</code> together may close
//! the wrong window because a different window got focused in-between these requests.
//!
//! </div>
//!
//! You can use the [`socket::Socket`] helper if you're fine with blocking communication. However,
//! it is a fairly simple helper, so if you need async, or if you're using a different language,
@@ -12,7 +27,9 @@
//! 2. Connect to the socket and write a JSON-formatted [`Request`] on a single line. You can follow
//! up with a line break and a flush, or just flush and shutdown the write end of the socket.
//! 3. Niri will respond with a single line JSON-formatted [`Reply`].
//! 4. If you requested an event stream, niri will keep responding with JSON-formatted [`Event`]s,
//! 4. You can keep writing [`Request`]s, each on a single line, and read [`Reply`]s, also each on a
//! separate line.
//! 5. After you request an event stream, niri will keep responding with JSON-formatted [`Event`]s,
//! on a single line each.
//!
//! ## Backwards compatibility
@@ -24,7 +41,7 @@
//!
//! ```toml
//! [dependencies]
//! niri-ipc = "=25.2.0"
//! niri-ipc = "=25.5.1"
//! ```
//!
//! ## Features
@@ -97,6 +114,8 @@ pub enum Request {
EventStream,
/// Respond with an error (for testing error handling).
ReturnError,
/// Request information about the overview.
OverviewState,
}
/// Reply from niri to client.
@@ -139,6 +158,16 @@ pub enum Response {
PickedColor(Option<PickedColor>),
/// Output configuration change result.
OutputConfigChanged(OutputConfigChanged),
/// Information about the overview.
OverviewState(Overview),
}
/// Overview information.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
pub struct Overview {
/// Whether the overview is currently open.
pub is_open: bool,
}
/// Color picked from the screen.
@@ -174,6 +203,12 @@ pub enum Action {
#[cfg_attr(feature = "clap", arg(last = true, required = true))]
command: Vec<String>,
},
/// Spawn a command through the shell.
SpawnSh {
/// Command to run.
#[cfg_attr(feature = "clap", arg(last = true, required = true))]
command: String,
},
/// Do a screen transition.
DoScreenTransition {
/// Delay in milliseconds for the screen to freeze before starting the transition.
@@ -303,7 +338,7 @@ pub enum Action {
FocusWindowUpOrColumnLeft {},
/// Focus the window above or the column to the right.
FocusWindowUpOrColumnRight {},
/// Focus the window or the workspace above.
/// Focus the window or the workspace below.
FocusWindowOrWorkspaceDown {},
/// Focus the window or the workspace above.
FocusWindowOrWorkspaceUp {},
@@ -397,6 +432,8 @@ pub enum Action {
#[cfg_attr(feature = "clap", arg(long))]
id: Option<u64>,
},
/// Center all fully visible columns on the screen.
CenterVisibleColumns {},
/// Focus the workspace below.
FocusWorkspaceDown {},
/// Focus the workspace above.
@@ -438,14 +475,35 @@ pub enum Action {
focus: bool,
},
/// Move the focused column to the workspace below.
MoveColumnToWorkspaceDown {},
MoveColumnToWorkspaceDown {
/// Whether the focus should follow the target workspace.
///
/// If `true` (the default), the focus will follow the column to the new workspace. If
/// `false`, the focus will remain on the original workspace.
#[cfg_attr(feature = "clap", arg(long, action = clap::ArgAction::Set, default_value_t = true))]
focus: bool,
},
/// Move the focused column to the workspace above.
MoveColumnToWorkspaceUp {},
MoveColumnToWorkspaceUp {
/// Whether the focus should follow the target workspace.
///
/// If `true` (the default), the focus will follow the column to the new workspace. If
/// `false`, the focus will remain on the original workspace.
#[cfg_attr(feature = "clap", arg(long, action = clap::ArgAction::Set, default_value_t = true))]
focus: bool,
},
/// Move the focused column to a workspace by reference (index or name).
MoveColumnToWorkspace {
/// Reference (index or name) of the workspace to move the column to.
#[cfg_attr(feature = "clap", arg())]
reference: WorkspaceReferenceArg,
/// Whether the focus should follow the target workspace.
///
/// If `true` (the default), the focus will follow the column to the new workspace. If
/// `false`, the focus will remain on the original workspace.
#[cfg_attr(feature = "clap", arg(long, action = clap::ArgAction::Set, default_value_t = true))]
focus: bool,
},
/// Move the focused workspace down.
MoveWorkspaceDown {},
@@ -764,6 +822,35 @@ pub enum Action {
},
/// Clear the dynamic cast target, making it show nothing.
ClearDynamicCastTarget {},
/// Toggle (open/close) the Overview.
ToggleOverview {},
/// Open the Overview.
OpenOverview {},
/// Close the Overview.
CloseOverview {},
/// Toggle urgent status of a window.
ToggleWindowUrgent {
/// Id of the window to toggle urgent.
#[cfg_attr(feature = "clap", arg(long))]
id: u64,
},
/// Set urgent status of a window.
SetWindowUrgent {
/// Id of the window to set urgent.
#[cfg_attr(feature = "clap", arg(long))]
id: u64,
},
/// Unset urgent status of a window.
UnsetWindowUrgent {
/// Id of the window to unset urgent.
#[cfg_attr(feature = "clap", arg(long))]
id: u64,
},
/// Reload the config file.
///
/// Can be useful for scripts changing the config file, to avoid waiting the small duration for
/// niri's config file watcher to notice the changes.
LoadConfigFile {},
}
/// Change in window or column size.
@@ -1072,6 +1159,56 @@ pub struct Window {
///
/// If the window isn't floating then it is in the tiling layout.
pub is_floating: bool,
/// Whether this window requests your attention.
pub is_urgent: bool,
/// Position- and size-related properties of the window.
pub layout: WindowLayout,
}
/// Position- and size-related properties of a [`Window`].
///
/// Optional properties will be unset for some windows, do not rely on them being present. Whether
/// some optional properties are present or absent for certain window types may change across niri
/// releases.
///
/// All sizes and positions are in *logical pixels* unless stated otherwise. Logical sizes may be
/// fractional. For example, at 1.25 monitor scale, a 2-physical-pixel-wide window border is 1.6
/// logical pixels wide.
///
/// This struct contains positions and sizes both for full tiles ([`Self::tile_size`],
/// [`Self::tile_pos_in_workspace_view`]) and the window geometry ([`Self::window_size`],
/// [`Self::window_offset_in_tile`]). For visual displays, use the tile properties, as they
/// correspond to what the user visually considers "window". The window properties on the other
/// hand are mainly useful when you need to know the underlying Wayland window sizes, e.g. for
/// application debugging.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
pub struct WindowLayout {
/// Location of a tiled window within a workspace: (column index, tile index in column).
///
/// The indices are 1-based, i.e. the leftmost column is at index 1 and the topmost tile in a
/// column is at index 1. This is consistent with [`Action::FocusColumn`] and
/// [`Action::FocusWindowInColumn`].
pub pos_in_scrolling_layout: Option<(usize, usize)>,
/// Size of the tile this window is in, including decorations like borders.
pub tile_size: (f64, f64),
/// Size of the window's visual geometry itself.
///
/// Does not include niri decorations like borders.
///
/// Currently, Wayland toplevel windows can only be integer-sized in logical pixels, even
/// though it doesn't necessarily align to physical pixels.
pub window_size: (i32, i32),
/// Tile position within the current view of the workspace.
///
/// This is the same "workspace view" as in gradients' `relative-to` in the niri config.
pub tile_pos_in_workspace_view: Option<(f64, f64)>,
/// Location of the window's visual geometry within its tile.
///
/// This includes things like border sizes. For fullscreened fixed-size windows this includes
/// the distance from the corner of the black backdrop to the corner of the (centered) window
/// contents.
pub window_offset_in_tile: (f64, f64),
}
/// Output configuration change result.
@@ -1111,6 +1248,8 @@ pub struct Workspace {
///
/// Can be `None` if no outputs are currently connected.
pub output: Option<String>,
/// Whether the workspace currently has an urgent window in its output.
pub is_urgent: bool,
/// Whether the workspace is currently active on its output.
///
/// Every output has one active workspace, the one that is currently visible on that output.
@@ -1185,6 +1324,13 @@ pub enum Event {
/// workspaces are missing from here, then they were deleted.
workspaces: Vec<Workspace>,
},
/// The workspace urgency changed.
WorkspaceUrgencyChanged {
/// Id of the workspace.
id: u64,
/// Whether this workspace has an urgent window.
urgent: bool,
},
/// A workspace was activated on an output.
///
/// This doesn't always mean the workspace became focused, just that it's now the active
@@ -1232,6 +1378,18 @@ pub enum Event {
/// Id of the newly focused window, or `None` if no window is now focused.
id: Option<u64>,
},
/// Window urgency changed.
WindowUrgencyChanged {
/// Id of the window.
id: u64,
/// The new urgency state of the window.
urgent: bool,
},
/// The layout of one or more windows has changed.
WindowLayoutsChanged {
/// Pairs consisting of a window id and new layout information for the window.
changes: Vec<(u64, WindowLayout)>,
},
/// The configured keyboard layouts have changed.
KeyboardLayoutsChanged {
/// The new keyboard layout configuration.
@@ -1242,6 +1400,21 @@ pub enum Event {
/// Index of the newly active layout.
idx: u8,
},
/// The overview was opened or closed.
OverviewOpenedOrClosed {
/// The new state of the overview.
is_open: bool,
},
/// The configuration was reloaded.
///
/// You will always receive this event when connecting to the event stream, indicating the last
/// config load attempt.
ConfigLoaded {
/// Whether the loading failed.
///
/// For example, the config file couldn't be parsed.
failed: bool,
},
}
impl FromStr for WorkspaceReferenceArg {
+42 -18
View File
@@ -16,7 +16,7 @@ pub const SOCKET_PATH_ENV: &str = "NIRI_SOCKET";
/// This struct is used to communicate with the niri IPC server. It handles the socket connection
/// and serialization/deserialization of messages.
pub struct Socket {
stream: UnixStream,
stream: BufReader<UnixStream>,
}
impl Socket {
@@ -37,6 +37,7 @@ impl Socket {
/// Connects to the niri IPC socket at the given path.
pub fn connect_to(path: impl AsRef<Path>) -> io::Result<Self> {
let stream = UnixStream::connect(path.as_ref())?;
let stream = BufReader::new(stream);
Ok(Self { stream })
}
@@ -47,31 +48,54 @@ impl Socket {
/// * `Ok(Ok(response))`: successful [`Response`](crate::Response) from niri
/// * `Ok(Err(message))`: error message from niri
/// * `Err(error)`: error communicating with niri
///
/// This method also returns a blocking function that you can call to keep reading [`Event`]s
/// after requesting an [`EventStream`][Request::EventStream]. This function is not useful
/// otherwise.
pub fn send(self, request: Request) -> io::Result<(Reply, impl FnMut() -> io::Result<Event>)> {
let Self { mut stream } = self;
pub fn send(&mut self, request: Request) -> io::Result<Reply> {
let mut buf = serde_json::to_string(&request).unwrap();
stream.write_all(buf.as_bytes())?;
stream.shutdown(Shutdown::Write)?;
let mut reader = BufReader::new(stream);
buf.push('\n');
self.stream.get_mut().write_all(buf.as_bytes())?;
buf.clear();
reader.read_line(&mut buf)?;
self.stream.read_line(&mut buf)?;
let reply = serde_json::from_str(&buf)?;
Ok(reply)
}
let events = move || {
/// Starts reading event stream [`Event`]s from the socket.
///
/// The returned function will block until the next [`Event`] arrives, then return it.
///
/// Use this only after requesting an [`EventStream`][Request::EventStream].
///
/// # Examples
///
/// ```no_run
/// use niri_ipc::{Request, Response};
/// use niri_ipc::socket::Socket;
///
/// fn main() -> std::io::Result<()> {
/// let mut socket = Socket::connect()?;
///
/// let reply = socket.send(Request::EventStream)?;
/// if matches!(reply, Ok(Response::Handled)) {
/// let mut read_event = socket.read_events();
/// while let Ok(event) = read_event() {
/// println!("Received event: {event:?}");
/// }
/// }
///
/// Ok(())
/// }
/// ```
pub fn read_events(self) -> impl FnMut() -> io::Result<Event> {
let Self { mut stream } = self;
let _ = stream.get_mut().shutdown(Shutdown::Write);
let mut buf = String::new();
move || {
buf.clear();
reader.read_line(&mut buf)?;
stream.read_line(&mut buf)?;
let event = serde_json::from_str(&buf)?;
Ok(event)
};
Ok((reply, events))
}
}
}
+82
View File
@@ -40,6 +40,12 @@ pub struct EventStreamState {
/// State of the keyboard layouts.
pub keyboard_layouts: KeyboardLayoutsState,
/// State of the overview.
pub overview: OverviewState,
/// State of the config.
pub config: ConfigState,
}
/// The workspaces state communicated over the event stream.
@@ -63,12 +69,28 @@ pub struct KeyboardLayoutsState {
pub keyboard_layouts: Option<KeyboardLayouts>,
}
/// The overview state communicated over the event stream.
#[derive(Debug, Default)]
pub struct OverviewState {
/// Whether the overview is currently open.
pub is_open: bool,
}
/// The config state communicated over the event stream.
#[derive(Debug, Default)]
pub struct ConfigState {
/// Whether the last config load attempt had failed.
pub failed: bool,
}
impl EventStreamStatePart for EventStreamState {
fn replicate(&self) -> Vec<Event> {
let mut events = Vec::new();
events.extend(self.workspaces.replicate());
events.extend(self.windows.replicate());
events.extend(self.keyboard_layouts.replicate());
events.extend(self.overview.replicate());
events.extend(self.config.replicate());
events
}
@@ -76,6 +98,8 @@ impl EventStreamStatePart for EventStreamState {
let event = self.workspaces.apply(event)?;
let event = self.windows.apply(event)?;
let event = self.keyboard_layouts.apply(event)?;
let event = self.overview.apply(event)?;
let event = self.config.apply(event)?;
Some(event)
}
}
@@ -91,6 +115,13 @@ impl EventStreamStatePart for WorkspacesState {
Event::WorkspacesChanged { workspaces } => {
self.workspaces = workspaces.into_iter().map(|ws| (ws.id, ws)).collect();
}
Event::WorkspaceUrgencyChanged { id, urgent } => {
for ws in self.workspaces.values_mut() {
if ws.id == id {
ws.is_urgent = urgent;
}
}
}
Event::WorkspaceActivated { id, focused } => {
let ws = self.workspaces.get(&id);
let ws = ws.expect("activated workspace was missing from the map");
@@ -162,6 +193,21 @@ impl EventStreamStatePart for WindowsState {
win.is_focused = Some(win.id) == id;
}
}
Event::WindowUrgencyChanged { id, urgent } => {
for win in self.windows.values_mut() {
if win.id == id {
win.is_urgent = urgent;
break;
}
}
}
Event::WindowLayoutsChanged { changes } => {
for (id, update) in changes {
let win = self.windows.get_mut(&id);
let win = win.expect("changed window was missing from the map");
win.layout = update;
}
}
event => return Some(event),
}
None
@@ -192,3 +238,39 @@ impl EventStreamStatePart for KeyboardLayoutsState {
None
}
}
impl EventStreamStatePart for OverviewState {
fn replicate(&self) -> Vec<Event> {
vec![Event::OverviewOpenedOrClosed {
is_open: self.is_open,
}]
}
fn apply(&mut self, event: Event) -> Option<Event> {
match event {
Event::OverviewOpenedOrClosed { is_open } => {
self.is_open = is_open;
}
event => return Some(event),
}
None
}
}
impl EventStreamStatePart for ConfigState {
fn replicate(&self) -> Vec<Event> {
vec![Event::ConfigLoaded {
failed: self.failed,
}]
}
fn apply(&mut self, event: Event) -> Option<Event> {
match event {
Event::ConfigLoaded { failed } => {
self.failed = failed;
}
event => return Some(event),
}
None
}
}
+3 -3
View File
@@ -10,9 +10,9 @@ repository.workspace = true
[dependencies]
adw = { version = "0.7.2", package = "libadwaita", features = ["v1_4"] }
anyhow.workspace = true
gtk = { version = "0.9.6", package = "gtk4", features = ["v4_12"] }
niri = { version = "25.2.0", path = ".." }
niri-config = { version = "25.2.0", path = "../niri-config" }
gtk = { version = "0.9.7", package = "gtk4", features = ["v4_12"] }
niri = { version = "25.5.1", path = ".." }
niri-config = { version = "25.5.1", path = "../niri-config" }
smithay.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
@@ -23,8 +23,10 @@ impl GradientArea {
width: FloatOrInt(1.),
active_color: Color::from_rgba8_unpremul(255, 255, 255, 128),
inactive_color: Color::default(),
urgent_color: Color::default(),
active_gradient: None,
inactive_gradient: None,
urgent_gradient: None,
});
Self {
@@ -81,6 +83,7 @@ impl TestCase for GradientArea {
g_size,
true,
true,
false,
Rectangle::default(),
CornerRadius::default(),
1.,
+4
View File
@@ -36,6 +36,7 @@ impl Layout {
subpixel: Subpixel::Unknown,
make: String::new(),
model: String::new(),
serial_number: String::new(),
},
);
let mode = Some(Mode {
@@ -60,8 +61,10 @@ impl Layout {
width: FloatOrInt(4.),
active_color: Color::from_rgba8_unpremul(255, 163, 72, 255),
inactive_color: Color::from_rgba8_unpremul(50, 50, 50, 255),
urgent_color: Color::from_rgba8_unpremul(155, 0, 0, 255),
active_gradient: None,
inactive_gradient: None,
urgent_gradient: None,
},
..Default::default()
};
@@ -266,6 +269,7 @@ impl TestCase for Layout {
.monitor_for_output(&self.output)
.unwrap()
.render_elements(renderer, RenderTarget::Output, true)
.flat_map(|(_, iter)| iter)
.map(|elem| Box::new(elem) as _)
.collect()
}
+4 -4
View File
@@ -255,10 +255,6 @@ impl LayoutElement for TestWindow {
&EMPTY
}
fn animation_snapshot(&self) -> Option<&LayoutElementRenderSnapshot> {
None
}
fn take_animation_snapshot(&mut self) -> Option<LayoutElementRenderSnapshot> {
None
}
@@ -272,4 +268,8 @@ impl LayoutElement for TestWindow {
fn interactive_resize_data(&self) -> Option<InteractiveResizeData> {
None
}
fn is_urgent(&self) -> bool {
false
}
}
+3 -1
View File
@@ -76,6 +76,8 @@ BuildRequires: pango-devel
BuildRequires: cairo-gobject-devel
# Needed for pipewire-rs
BuildRequires: clang
# Needed for some tests with a surfaceless EGL renderer
BuildRequires: mesa-libEGL
Requires: mesa-dri-drivers
Requires: mesa-libEGL
@@ -136,7 +138,7 @@ install -Dm644 -t %{buildroot}%{_userunitdir} ./resources/niri-shutdown.target
%license LICENSE
%doc README.md
%doc resources/default-config.kdl
%doc wiki
%doc docs/wiki
%{_bindir}/niri
%{_bindir}/niri-session
%{_datadir}/wayland-sessions/niri.desktop
+55 -15
View File
@@ -1,11 +1,11 @@
// This config is in the KDL format: https://kdl.dev
// "/-" comments out the following node.
// Check the wiki for a full description of the configuration:
// https://github.com/YaLTeR/niri/wiki/Configuration:-Overview
// https://yalter.github.io/niri/Configuration:-Introduction
// Input device configuration.
// Find the full list of options on the wiki:
// https://github.com/YaLTeR/niri/wiki/Configuration:-Input
// https://yalter.github.io/niri/Configuration:-Input
input {
keyboard {
xkb {
@@ -15,11 +15,19 @@ input {
// For example:
// layout "us,ru"
// options "grp:win_space_toggle,compose:ralt,ctrl:nocaps"
// If this section is empty, niri will fetch xkb settings
// from org.freedesktop.locale1. You can control these using
// localectl set-x11-keymap.
}
// Enable numlock on startup, omitting this setting disables it.
numlock
}
// Next sections include libinput settings.
// Omitting settings disables them, or leaves them at their default values.
// All commented-out settings here are examples, not defaults.
touchpad {
// off
tap
@@ -49,6 +57,7 @@ input {
// accel-profile "flat"
// scroll-method "on-button-down"
// scroll-button 273
// scroll-button-lock
// middle-emulation
}
@@ -64,7 +73,7 @@ input {
// by running `niri msg outputs` while inside a niri instance.
// The built-in laptop monitor is usually called "eDP-1".
// Find more information on the wiki:
// https://github.com/YaLTeR/niri/wiki/Configuration:-Outputs
// https://yalter.github.io/niri/Configuration:-Outputs
// Remember to uncomment the node by removing "/-"!
/-output "eDP-1" {
// Uncomment this line to disable this output.
@@ -99,7 +108,7 @@ input {
// Settings that influence how windows are positioned and sized.
// Find more information on the wiki:
// https://github.com/YaLTeR/niri/wiki/Configuration:-Layout
// https://yalter.github.io/niri/Configuration:-Layout
layout {
// Set gaps around windows in logical pixels.
gaps 16
@@ -161,6 +170,9 @@ layout {
active-color "#7fc8ff"
// Color of the ring on inactive monitors.
//
// The focus ring only draws around the active window, so the only place
// where you can see its inactive-color is on other monitors.
inactive-color "#505050"
// You can also use gradients. They take precedence over solid colors.
@@ -170,7 +182,7 @@ layout {
// You can use any CSS linear-gradient tool on the web to set these up.
// Changing the color space is also supported, check the wiki for more info.
//
// active-gradient from="#80c8ff" to="#bbddff" angle=45
// active-gradient from="#80c8ff" to="#c7ff7f" angle=45
// You can also color the gradient relative to the entire view
// of the workspace, rather than relative to just the window itself.
@@ -189,7 +201,14 @@ layout {
active-color "#ffc87f"
inactive-color "#505050"
// active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view"
// Color of the border around windows that request your attention.
urgent-color "#9b0000"
// Gradients can use a few different interpolation color spaces.
// For example, this is a pastel rainbow gradient via in="oklch longer hue".
//
// active-gradient from="#e5989b" to="#ffb4a2" angle=45 relative-to="workspace-view" in="oklch longer hue"
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
}
@@ -205,13 +224,13 @@ layout {
// radius. It has to assume that windows have square corners, leading to
// shadow artifacts inside the CSD rounded corners. This setting fixes
// those artifacts.
//
//
// However, instead you may want to set prefer-no-csd and/or
// geometry-corner-radius. Then, niri will know the corner radius and
// draw the shadow correctly, without having to draw it behind the
// window. These will also remove client-side shadows if the window
// draws any.
//
//
// draw-behind-window true
// You can change how shadows look. The values below are in logical
@@ -251,6 +270,14 @@ layout {
// This line starts waybar, a commonly used bar for Wayland compositors.
spawn-at-startup "waybar"
// To run a shell command (with variables, pipes, etc.), use spawn-sh-at-startup:
// spawn-sh-at-startup "qs -c ~/source/qs/MyAwesomeShell"
hotkey-overlay {
// Uncomment this line to disable the "Important Hotkeys" pop-up at startup.
// skip-at-startup
}
// Uncomment this line to ask the clients to omit their client-side decorations if possible.
// If the client will specifically ask for CSD, the request will be honored.
// Additionally, clients will be informed that they are tiled, removing some client-side rounded corners.
@@ -268,7 +295,7 @@ screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
// Animation settings.
// The wiki explains how to configure individual animations:
// https://github.com/YaLTeR/niri/wiki/Configuration:-Animations
// https://yalter.github.io/niri/Configuration:-Animations
animations {
// Uncomment to turn off all animations.
// off
@@ -279,7 +306,7 @@ animations {
// Window rules let you adjust behavior for individual windows.
// Find more information on the wiki:
// https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules
// https://yalter.github.io/niri/Configuration:-Window-Rules
// Work around WezTerm's initial configure bug
// by setting an empty default-column-width.
@@ -339,10 +366,6 @@ binds {
Mod+D hotkey-overlay-title="Run an Application: fuzzel" { spawn "fuzzel"; }
Super+Alt+L hotkey-overlay-title="Lock the Screen: swaylock" { spawn "swaylock"; }
// You can also use a shell. Do this if you need pipes, multiple commands, etc.
// Note: the entire command goes as a single argument in the end.
// Mod+T { spawn "bash" "-c" "notify-send hello && exec alacritty"; }
// Example volume keys mappings for PipeWire & WirePlumber.
// The allow-when-locked=true property makes them work even when the session is locked.
XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"; }
@@ -350,7 +373,21 @@ binds {
XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; }
XF86AudioMicMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; }
Mod+Q { close-window; }
// Example brightness key mappings for brightnessctl.
XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; }
XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; }
// Use spawn-sh to run a shell command. Do this if you need pipes, multiple commands, etc.
// Note: the entire command goes as a single argument. It's passed verbatim to `sh -c`.
// For example, this is a standard bind to toggle the screen reader (orca).
Super+Alt+S allow-when-locked=true hotkey-overlay-title=null { spawn-sh "pkill orca || exec orca"; }
// 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; }
Mod+Q repeat=false { close-window; }
Mod+Left { focus-column-left; }
Mod+Down { focus-window-down; }
@@ -514,6 +551,9 @@ binds {
Mod+C { center-column; }
// Center all fully visible columns on screen.
Mod+Ctrl+C { center-visible-columns; }
// Finer width adjustments.
// This command can also:
// * set width in pixels: "1000"
+11 -1
View File
@@ -1,5 +1,15 @@
#!/bin/sh
# Detect if being run as a user service, which implies external session management,
# exec compositor directly
if [ -n "${MANAGERPID:-}" ] && [ "${SYSTEMD_EXEC_PID:-}" = "$$" ]; then
case "$(ps -p "$MANAGERPID" -o cmd=)" in
*systemd*--user*)
exec niri --session
;;
esac
fi
if [ -n "$SHELL" ] &&
grep -q "$SHELL" /etc/shells &&
! (echo "$SHELL" | grep -q "false") &&
@@ -40,7 +50,7 @@ if hash systemctl >/dev/null 2>&1; then
systemctl --user start --job-mode=replace-irreversibly niri-shutdown.target
# Unset environment that we've set.
systemctl --user unset-environment WAYLAND_DISPLAY XDG_SESSION_TYPE XDG_CURRENT_DESKTOP NIRI_SOCKET
systemctl --user unset-environment WAYLAND_DISPLAY DISPLAY XDG_SESSION_TYPE XDG_CURRENT_DESKTOP NIRI_SOCKET
elif hash dinitctl >/dev/null 2>&1; then
# Check that the user dinit daemon is running
if ! pgrep -u "$(id -u)" dinit >/dev/null 2>&1; then
+19
View File
@@ -94,6 +94,12 @@ impl Spring {
x1 = (self.to - y0 + m * x0) / m;
y1 = self.oscillate(x1);
// Overdamped springs have some numerical stability issues...
if !y1.is_finite() {
return Duration::from_secs_f64(x0);
}
i += 1;
}
@@ -187,4 +193,17 @@ mod tests {
let _ = spring.clamped_duration();
let _ = spring.value_at(Duration::ZERO);
}
#[test]
fn overdamped_spring_duration_panic() {
let spring = Spring {
from: 0.,
to: 1.,
initial_velocity: 0.,
params: SpringParams::new(6., 1200., 0.0001),
};
let _ = spring.duration();
let _ = spring.clamped_duration();
let _ = spring.value_at(Duration::ZERO);
}
}
+30 -3
View File
@@ -1,13 +1,16 @@
//! Headless backend for tests.
//!
//! This can eventually grow into a more complete backend if needed, but for now it's missing some
//! crucial parts like rendering.
//! crucial parts like dmabufs.
use std::mem;
use std::sync::{Arc, Mutex};
use anyhow::Context as _;
use niri_config::OutputName;
use smithay::backend::allocator::dmabuf::Dmabuf;
use smithay::backend::egl::native::EGLSurfacelessDisplay;
use smithay::backend::egl::{EGLContext, EGLDisplay};
use smithay::backend::renderer::element::RenderElementStates;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::output::{Mode, Output, PhysicalProperties, Subpixel};
@@ -17,21 +20,44 @@ use smithay::wayland::presentation::Refresh;
use super::{IpcOutputMap, OutputId, RenderResult};
use crate::niri::{Niri, RedrawState};
use crate::render_helpers::{resources, shaders};
use crate::utils::{get_monotonic_time, logical_output};
pub struct Headless {
renderer: Option<GlesRenderer>,
ipc_outputs: Arc<Mutex<IpcOutputMap>>,
}
impl Headless {
pub fn new() -> Self {
Self {
renderer: None,
ipc_outputs: Default::default(),
}
}
pub fn init(&mut self, _niri: &mut Niri) {}
pub fn add_renderer(&mut self) -> anyhow::Result<()> {
if self.renderer.is_some() {
error!("add_renderer: renderer must not already exist");
return Ok(());
}
let mut renderer = unsafe {
let display =
EGLDisplay::new(EGLSurfacelessDisplay).context("error creating EGL display")?;
let context = EGLContext::new(&display).context("error creating EGL context")?;
GlesRenderer::new(context).context("error creating renderer")?
};
resources::init(&mut renderer);
shaders::init(&mut renderer);
self.renderer = Some(renderer);
Ok(())
}
pub fn add_output(&mut self, niri: &mut Niri, n: u8, size: (u16, u16)) {
let connector = format!("headless-{n}");
let make = "niri".to_string();
@@ -45,6 +71,7 @@ impl Headless {
subpixel: Subpixel::Unknown,
make: make.clone(),
model: model.clone(),
serial_number: serial.clone(),
},
);
@@ -93,9 +120,9 @@ impl Headless {
pub fn with_primary_renderer<T>(
&mut self,
_f: impl FnOnce(&mut GlesRenderer) -> T,
f: impl FnOnce(&mut GlesRenderer) -> T,
) -> Option<T> {
None
self.renderer.as_mut().map(f)
}
pub fn render(&mut self, niri: &mut Niri, output: &Output) -> RenderResult {
+1
View File
@@ -20,6 +20,7 @@ pub use winit::Winit;
pub mod headless;
pub use headless::Headless;
#[allow(clippy::large_enum_variant)]
pub enum Backend {
Tty(Tty),
Winit(Winit),
+27 -11
View File
@@ -19,6 +19,7 @@ use smithay::backend::allocator::format::FormatSet;
use smithay::backend::allocator::gbm::{GbmAllocator, GbmBufferFlags, GbmDevice};
use smithay::backend::allocator::Fourcc;
use smithay::backend::drm::compositor::{DrmCompositor, FrameFlags, PrimaryPlaneElement};
use smithay::backend::drm::exporter::gbm::GbmFramebufferExporter;
use smithay::backend::drm::{
DrmDevice, DrmDeviceFd, DrmEvent, DrmEventMetadata, DrmEventTime, DrmNode, NodeType, VrrSupport,
};
@@ -114,7 +115,7 @@ pub type TtyRendererError<'render> = <TtyRenderer<'render> as RendererSuper>::Er
type GbmDrmCompositor = DrmCompositor<
GbmAllocator<DrmDeviceFd>,
GbmDevice<DrmDeviceFd>,
GbmFramebufferExporter<DrmDeviceFd>,
(OutputPresentationFeedback, Duration),
DrmDeviceFd,
>;
@@ -315,11 +316,11 @@ impl Tty {
let mut node_path = String::new();
if let Some(path) = primary_render_node.dev_path() {
write!(node_path, "{:?}", path).unwrap();
write!(node_path, "{path:?}").unwrap();
} else {
write!(node_path, "{}", primary_render_node).unwrap();
write!(node_path, "{primary_render_node}").unwrap();
}
info!("using as the render node: {}", node_path);
info!("using as the render node: {node_path}");
Ok(Self {
config,
@@ -856,10 +857,13 @@ impl Tty {
}
debug!("picking mode: {mode:?}");
// We only use 8888 RGB formats, so set max bpc to 8 to allow more types of links to run.
match set_max_bpc(&device.drm, connector.handle(), 8) {
Ok(bpc) => debug!("set max bpc to {bpc}"),
Err(err) => debug!("error setting max bpc: {err:?}"),
if !niri.config.borrow().debug.keep_max_bpc_unchanged {
// We only use 8888 RGB formats, so set max bpc to 8 to allow more types of links to
// run.
match set_max_bpc(&device.drm, connector.handle(), 8) {
Ok(bpc) => debug!("set max bpc to {bpc}"),
Err(err) => debug!("error setting max bpc: {err:?}"),
}
}
let mut gamma_props = GammaProps::new(&device.drm, crtc)
@@ -919,6 +923,11 @@ impl Tty {
subpixel: connector.subpixel().into(),
model: output_name.model.as_deref().unwrap_or("Unknown").to_owned(),
make: output_name.make.as_deref().unwrap_or("Unknown").to_owned(),
serial_number: output_name
.serial
.as_deref()
.unwrap_or("Unknown")
.to_owned(),
},
);
@@ -971,7 +980,7 @@ impl Tty {
surface,
None,
allocator.clone(),
device.gbm.clone(),
GbmFramebufferExporter::new(device.gbm.clone(), device.render_node.into()),
SUPPORTED_COLOR_FORMATS,
// This is only used to pick a good internal format, so it can use the surface's render
// formats, even though we only ever render on the primary GPU.
@@ -1001,7 +1010,7 @@ impl Tty {
surface,
None,
allocator,
device.gbm.clone(),
GbmFramebufferExporter::new(device.gbm.clone(), device.render_node.into()),
SUPPORTED_COLOR_FORMATS,
render_formats,
device.drm.cursor_size(),
@@ -1373,7 +1382,8 @@ impl Tty {
span.emit_text(&surface.name.connector);
if !device.drm.is_active() {
warn!("device is inactive");
// This branch hits any time we try to render while the user had switched to a
// different VT, so don't print anything here.
return rv;
}
@@ -1421,6 +1431,12 @@ impl Tty {
if debug.disable_cursor_plane {
flags.remove(FrameFlags::ALLOW_CURSOR_PLANE_SCANOUT);
}
if debug.skip_cursor_only_updates_during_vrr {
let output_state = niri.output_state.get(output).unwrap();
if output_state.frame_clock.vrr() {
flags.insert(FrameFlags::SKIP_CURSOR_ONLY_UPDATES);
}
}
flags
};
+1
View File
@@ -49,6 +49,7 @@ impl Winit {
subpixel: Subpixel::Unknown,
make: "Smithay".into(),
model: "Winit".into(),
serial_number: "Unknown".into(),
},
);

Some files were not shown because too many files have changed in this diff Show More