mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Compare commits
819 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf4e8cd233 | |||
| 34b05e8671 | |||
| d4e1b2231b | |||
| e81f356908 | |||
| 1013147ba3 | |||
| 38f388565f | |||
| f9ea905987 | |||
| 7a8355bb4d | |||
| 781edba45f | |||
| 6d62c26a0f | |||
| 5ea9092a49 | |||
| 43a2648e57 | |||
| ba129e98e3 | |||
| b9b4f31b6f | |||
| 5f3528a2ee | |||
| a5777b9473 | |||
| 6dc4f6a622 | |||
| 85d42db05d | |||
| d6db202a03 | |||
| 3a85e77518 | |||
| e0bf056ba3 | |||
| 39bdfece9a | |||
| 26a6e0cd98 | |||
| b12a56e4e6 | |||
| f6e1b3133e | |||
| dc93f1c1fd | |||
| a6febb86aa | |||
| 3b76cb7b3d | |||
| 271534e115 | |||
| af30cc8df6 | |||
| a003e01307 | |||
| 38df8d4f33 | |||
| 6d0505e684 | |||
| 8b4517a87b | |||
| c7a8c44a0d | |||
| 25c1c04349 | |||
| 36af02ad34 | |||
| a9f0f4d44f | |||
| e3101ced70 | |||
| ea438b21e9 | |||
| 42bd107795 | |||
| a2767041d9 | |||
| 5bda3041d0 | |||
| 54076b7632 | |||
| c9873a0885 | |||
| 7a6be2a923 | |||
| bba9ca1fa2 | |||
| af9ce53310 | |||
| 0044578681 | |||
| 0c09f2529b | |||
| 2fb993d221 | |||
| 67361f88fd | |||
| f74d83dcca | |||
| 055a94de3d | |||
| 52c579d556 | |||
| 5edd91d37b | |||
| 378a90e4b0 | |||
| 871cf4ba9a | |||
| f49ecc31c4 | |||
| 15b4acc17e | |||
| 43577f4d97 | |||
| 8fba696d8e | |||
| 2e3935d77d | |||
| 53b7c08363 | |||
| 76c3bb20ba | |||
| 91b6a111cf | |||
| 98a42c5557 | |||
| e19e1f0f10 | |||
| c0ddf3f9ff | |||
| 4ac4cb4a44 | |||
| 365274e5e2 | |||
| 672bf3e1ff | |||
| fefc0bc0a7 | |||
| 0b1a6c76ec | |||
| 485e667fec | |||
| 8f442dee06 | |||
| 9c09bc730f | |||
| 7b065f8618 | |||
| 60fbcd2329 | |||
| 5ac440a760 | |||
| 0e3d078a85 | |||
| 36efd6e3f9 | |||
| 30a9c6c31b | |||
| bc0a06226a | |||
| ed799f5afc | |||
| 007d35541d | |||
| e46a27351d | |||
| 56901eed5d | |||
| 48fe08caf4 | |||
| df00f0328e | |||
| d85eaf9799 | |||
| 25cbb739ae | |||
| 88339633b1 | |||
| 22e43193e0 | |||
| 7a2379ad35 | |||
| fe2c2eec29 | |||
| 746a7e81b7 | |||
| 51b6a495c5 | |||
| bb40a35ccf | |||
| 37c6412e80 | |||
| 19c8fca836 | |||
| 186e0b608a | |||
| ce501bca9e | |||
| 45e9bb769d | |||
| dfb3683187 | |||
| ce9ba00d54 | |||
| 37458d94b2 | |||
| 044f14f8f9 | |||
| 4c02f3bba4 | |||
| b55a80c641 | |||
| e0b0b04b44 | |||
| ed14e8da84 | |||
| e53f8527b0 | |||
| da3dc913a6 | |||
| f3f6e79eec | |||
| 83ec369536 | |||
| 97dfd2b1a0 | |||
| 730eab09fb | |||
| a23ce10311 | |||
| 2f18d8e328 | |||
| 7aec37f5c9 | |||
| 07080a0431 | |||
| aa47223c19 | |||
| 10a6d6ae45 | |||
| 7db864d203 | |||
| 8d7b22d1a8 | |||
| 0407ac5e4c | |||
| a18d24fc24 | |||
| 2bacc80c93 | |||
| c91638c12e | |||
| f8a0c9df2c | |||
| 6bab912383 | |||
| 3edb8fd906 | |||
| c9b1514d63 | |||
| 2066737024 | |||
| f918eabe6a | |||
| 0698f167e5 | |||
| 242ebf2945 | |||
| 9858599ac1 | |||
| abac28a65c | |||
| a7186a0441 | |||
| 1911cf3f55 | |||
| 09da884cd8 | |||
| 8ba57fcf25 | |||
| 126ca37d96 | |||
| e6bd60fbb1 | |||
| a605a3f016 | |||
| ef44adea69 | |||
| 7fdb918cd0 | |||
| 8347cc20dc | |||
| 51a176ec4a | |||
| d618daf6b9 | |||
| 357f9157cc | |||
| c4a759e620 | |||
| f369a0f810 | |||
| 71251a7003 | |||
| 2415346caa | |||
| 3f2b7e63ba | |||
| ae89cb6017 | |||
| b6fc4d0455 | |||
| d8265ad34e | |||
| 3b864dc104 | |||
| 15093221ed | |||
| ac7b3fbf19 | |||
| bb8eb377c7 | |||
| 6169c0312a | |||
| 2ae99224ab | |||
| 4f63e13385 | |||
| 46a8f81160 | |||
| 0d6843ea67 | |||
| 6d083ea497 | |||
| 7a42140d6c | |||
| eeb411bef5 | |||
| defd4c5c4d | |||
| 7227e64149 | |||
| c98537a2b0 | |||
| 9c103f1f1d | |||
| 2aff1ec71a | |||
| 3466fc0a66 | |||
| f917932b3e | |||
| 89b7423ee5 | |||
| a2efaf2816 | |||
| 5816691460 | |||
| 4b5e9e6cb0 | |||
| a8259b4cea | |||
| 9d3d7cb0e9 | |||
| 398bc78ea0 | |||
| caa6189448 | |||
| 86f57c2ec7 | |||
| 3cc67897af | |||
| a99489c6c0 | |||
| 0763c7e196 | |||
| fb5c5204e8 | |||
| d207cd385b | |||
| 99bf2df2b4 | |||
| 09be90f4e6 | |||
| dfc42b9d82 | |||
| e2b9838d89 | |||
| 816a0d479c | |||
| 84323d10a4 | |||
| b956f2775c | |||
| 9ff2f83db0 | |||
| 7a10f71ee5 | |||
| ea7add3563 | |||
| e9c6f08906 | |||
| 17343a6740 | |||
| 140d726cd3 | |||
| c37d3b3442 | |||
| 497f186422 | |||
| 3e31c134a6 | |||
| fe682938db | |||
| 6142922ca4 | |||
| 4b44fba14c | |||
| 57639ca84c | |||
| ec88aae77d | |||
| 6c9705dd4b | |||
| eb590c5346 | |||
| 02baad91ac | |||
| 68589cd5a1 | |||
| f2c690802b | |||
| 9d6037b94c | |||
| 7b4cf094ef | |||
| 446bc155ce | |||
| 3289324ce4 | |||
| 9fb02b9571 | |||
| 0e9496b01e | |||
| 82dabc21f3 | |||
| 39b3d62873 | |||
| af080a03cd | |||
| 5f117c61dc | |||
| cb857e32e4 | |||
| 199be26947 | |||
| d5c0c74d2c | |||
| 9bb292ec82 | |||
| a1ba6bcaa0 | |||
| fd389af6d8 | |||
| db09727b18 | |||
| c9d6478c3c | |||
| 758cca5432 | |||
| 78e3daf5f8 | |||
| a99a0b2492 | |||
| bfd42c74f4 | |||
| 501ea47128 | |||
| d2a1cf53b4 | |||
| 62d47d77d5 | |||
| 85cd64e830 | |||
| 55c14eebf2 | |||
| 3fe67549b4 | |||
| 1835b532d9 | |||
| e6d82d3ee3 | |||
| fae3a27641 | |||
| 31e76cf451 | |||
| b8a9be542f | |||
| 59de6918b3 | |||
| bd3d554389 | |||
| af1fca35bb | |||
| 9571d149b2 | |||
| 99358e36b3 | |||
| 8b878f355f | |||
| 395b6d9a4f | |||
| 25f24f668c | |||
| 929eaf0d69 | |||
| ce3103949f | |||
| ef60dd81d7 | |||
| 7671a5d833 | |||
| 3f09352067 | |||
| 5059cce886 | |||
| b20dd226c0 | |||
| acb69c3b4d | |||
| dbe0a9e293 | |||
| d3a79faeec | |||
| 21630ddb5e | |||
| 9e5e0c85bb | |||
| 5cd8040d1a | |||
| 86351938f2 | |||
| ee4c5e23ab | |||
| ffd6acc0aa | |||
| cee11dc329 | |||
| 59a42249a4 | |||
| 74b016202b | |||
| 6ab055a4b9 | |||
| 98bd9b7abb | |||
| f36e1c2ef2 | |||
| 2243615fe9 | |||
| 7884d3bfea | |||
| fdbc485d78 | |||
| 7e253d2687 | |||
| 15ba2ab300 | |||
| 37840a418a | |||
| 4a4c972ffb | |||
| ba933773ab | |||
| f1cca1a6ca | |||
| 763cd564e3 | |||
| 95eafba346 | |||
| df94662435 | |||
| 430b155929 | |||
| c359d24825 | |||
| e8da89a430 | |||
| feae8c15e6 | |||
| b49f7dcb4d | |||
| 60034a57ef | |||
| 2adbf33fb6 | |||
| 28cc84fbd1 | |||
| e10b968eb0 | |||
| 3b1bf34e21 | |||
| bd927b54e0 | |||
| 66d3a3bd82 | |||
| 36489f1daa | |||
| b2c34e7fe9 | |||
| dcc291d701 | |||
| 8d43efe4ac | |||
| 3bb7e60311 | |||
| d639eb0032 | |||
| d91499486e | |||
| f7106f9658 | |||
| 835490c59a | |||
| 5cde00f6c6 | |||
| 7dc015e16b | |||
| 0db48e2f1b | |||
| 7cfecf4b1b | |||
| 3142838e9e | |||
| 4534d37266 | |||
| ec5112d779 | |||
| c709696237 | |||
| b271409509 | |||
| 500dcca9b7 | |||
| 7210045b2a | |||
| ed20822ce9 | |||
| e88dfae46f | |||
| f95d5a82df | |||
| 7f72c358d5 | |||
| 0d4f0f00c0 | |||
| f2663c738c | |||
| c3609efb7a | |||
| fd1f43673c | |||
| 9d10def7e8 | |||
| e251ca7340 | |||
| 9a527cc571 | |||
| 39f52b7585 | |||
| b447b1f4de | |||
| 1a0fab05b6 | |||
| fbb399f01d | |||
| 6a80ec4704 | |||
| e8b158641b | |||
| 27a715aded | |||
| 926e63a5f3 | |||
| e879199880 | |||
| 5b6b6a5fe1 | |||
| e11af089aa | |||
| 5e549e1323 | |||
| 287480b541 | |||
| a022fedd51 | |||
| a4b8e100c0 | |||
| 62576796be | |||
| 31891e6642 | |||
| 392fc27de1 | |||
| 9e560e7e60 | |||
| cee2ec7ab7 | |||
| 8c4ebb00a1 | |||
| f6aa8c1793 | |||
| a5d58d670b | |||
| b4922086ce | |||
| fd3b1f2b6c | |||
| ee0e2c7f1b | |||
| 4f16be9e4d | |||
| 0f30306fe5 | |||
| 1c6037e612 | |||
| fed86fdb5d | |||
| 3e21585861 | |||
| 9f9c4a99af | |||
| b220cdbe7e | |||
| df219b5134 | |||
| 8cdabe8adf | |||
| 8737067af5 | |||
| 50a99f6356 | |||
| 993c5ce8af | |||
| 47dd338340 | |||
| 87b6c12625 | |||
| b351f6ff22 | |||
| 12817a682d | |||
| 88614c08fe | |||
| 4f5c8e745b | |||
| f30413a744 | |||
| 3b8ce12316 | |||
| 880386e563 | |||
| 266c6c3878 | |||
| 7b033aa7c6 | |||
| efd8372b20 | |||
| 74a30be10b | |||
| 1c521e4831 | |||
| eda43b2b93 | |||
| 593241d2f0 | |||
| 69627bdc64 | |||
| 3fa373c720 | |||
| 083a56c729 | |||
| 88fcf0c2a9 | |||
| 26618f8d50 | |||
| 9f205d465c | |||
| d6e736aaf0 | |||
| 36b28d9b96 | |||
| 66113d7d76 | |||
| aa2e8b402c | |||
| 311f3be5d8 | |||
| 70dcd229cf | |||
| 26fe4a489a | |||
| 2363cf48e7 | |||
| 848294c09b | |||
| 693d935538 | |||
| 16405b9b2b | |||
| 4719cc6d59 | |||
| 98b92d4db7 | |||
| 1bdded7a44 | |||
| 9bfe90dee1 | |||
| c153349c62 | |||
| 5b6b5536fd | |||
| bac22dfe9f | |||
| bca6545288 | |||
| b94a5db879 | |||
| 4a4dcb85ef | |||
| 7b70cb66bc | |||
| cd6522bcc6 | |||
| 8885233c7e | |||
| 7478784343 | |||
| dca187de37 | |||
| fe660a253b | |||
| ad49e5820a | |||
| 4c40e6ce06 | |||
| 44c9797844 | |||
| 652d2923bb | |||
| 85349ce475 | |||
| 92cc2b89f7 | |||
| 078383ea82 | |||
| d27d6a504d | |||
| ec5144feca | |||
| 05e0e44a77 | |||
| 108e88e211 | |||
| a693f64c41 | |||
| 5c0468d469 | |||
| f2b1fc66f2 | |||
| 22302bf224 | |||
| bb6663ebac | |||
| c6e98d5a96 | |||
| d077350ae4 | |||
| f01c840ebe | |||
| ca1500ae90 | |||
| d7f3ca00c7 | |||
| fd8140e091 | |||
| d94fbe9895 | |||
| 7816f20e6a | |||
| 0d3610416c | |||
| 377ad54016 | |||
| 9e794f358b | |||
| 4e17cbb9ea | |||
| 4c98b87486 | |||
| 5b753be213 | |||
| a605e7f622 | |||
| 513488f6b8 | |||
| 43ea4a172a | |||
| d47b59879a | |||
| ef80bcc834 | |||
| eb8bd3894a | |||
| 7e552333a9 | |||
| 213eafa203 | |||
| 7b18ff8870 | |||
| 5246e2ff25 | |||
| dde9214ae4 | |||
| 29b7a41692 | |||
| 216753678a | |||
| b9e67f6565 | |||
| 3a481b5250 | |||
| 20769b4c2f | |||
| 14ac2cff4c | |||
| fde627d955 | |||
| 6942ecc13a | |||
| 963ff14ed0 | |||
| 96a3ded2ec | |||
| a21196ec54 | |||
| 0b83d9932b | |||
| 6bd92ab926 | |||
| 02eccf7762 | |||
| 89cf276779 | |||
| bc701cd529 | |||
| bfd81fc290 | |||
| 0dd8e883b0 | |||
| c31b58e2c9 | |||
| b163045757 | |||
| 41e9ec1364 | |||
| 64544a5726 | |||
| d7d5a7f8f6 | |||
| a451f75917 | |||
| 1515410012 | |||
| 8f9e0d029c | |||
| 90f24da631 | |||
| df70140b36 | |||
| f90eb0cbe4 | |||
| 55e2ea0c3b | |||
| 1d883931b4 | |||
| b65fad09d8 | |||
| 09a559d3c9 | |||
| 9fc749f3d4 | |||
| f836d1c28a | |||
| 4f05a74aa8 | |||
| c30f522ef2 | |||
| 397e704d64 | |||
| acc9d3e409 | |||
| 0c59fc304c | |||
| abd7f1dce3 | |||
| 1d87da00b7 | |||
| 91515ac6dc | |||
| 7ec771f7ec | |||
| a42a5ac696 | |||
| b31c0359eb | |||
| 934e5a6033 | |||
| 690d635505 | |||
| a444efd0eb | |||
| c41f93a468 | |||
| 900da597e4 | |||
| d320833f40 | |||
| c384b2489f | |||
| ddcac86d1d | |||
| 734e3a6d3c | |||
| f18b1a7043 | |||
| 7d24ad23c2 | |||
| 691bc064bb | |||
| 553b1ba852 | |||
| d5592743cb | |||
| 019e75955d | |||
| 32ad545f84 | |||
| 4eddcef1be | |||
| 68776f1cee | |||
| a0e2a15c60 | |||
| 88c6778771 | |||
| 73f6d3366e | |||
| 48a4d5c8a3 | |||
| 6f2f7fa259 | |||
| 49ddf66c2f | |||
| a169e0335d | |||
| e412a0fc6b | |||
| fb5fedbf24 | |||
| 6b04b1e454 | |||
| 0c340ec5ea | |||
| 34679c75a4 | |||
| 1d3820a064 | |||
| 1c749f578c | |||
| 3a887a6e49 | |||
| beef2da628 | |||
| 9b4d73f13a | |||
| 0226d9aec2 | |||
| 902222675a | |||
| ec43493522 | |||
| baa0518912 | |||
| d665079b84 | |||
| f0d935dee1 | |||
| 314b82caa0 | |||
| 8f79139b78 | |||
| c5296b870a | |||
| 78697d1cea | |||
| 852da5714a | |||
| 4f79303811 | |||
| f294d527e1 | |||
| 54a1cd5069 | |||
| 748d90b443 | |||
| 128b01e049 | |||
| 788c9c6c54 | |||
| a10705fb20 | |||
| b01b8afa8c | |||
| acd4cb51aa | |||
| 5ebcae997e | |||
| 2511a98e8b | |||
| a7692d10c4 | |||
| c892f04c96 | |||
| 3aad5a39ea | |||
| 7f025da5b6 | |||
| 01285bdbbe | |||
| 8182484572 | |||
| 0584dd2f1e | |||
| bd559a2660 | |||
| b4add625b2 | |||
| 890bbff007 | |||
| b853d5b124 | |||
| 693e0e09f7 | |||
| d52356b131 | |||
| b11b995d03 | |||
| 99ba295082 | |||
| 8c2b5957eb | |||
| 4472164447 | |||
| a3cbe3514b | |||
| efa7c862a4 | |||
| 0df7a085de | |||
| 6ae51f287c | |||
| 36076d5279 | |||
| 427c4e3982 | |||
| 1632ce87a5 | |||
| c523c80598 | |||
| 0bd6df507b | |||
| 6e41220dbf | |||
| e05bc269e6 | |||
| d574341f1f | |||
| 481958f8f7 | |||
| 4094469d59 | |||
| 2261fcb631 | |||
| 279c8b6aa2 | |||
| e35c630c1d | |||
| d3047afa7f | |||
| a03783f54c | |||
| cbf0d6190d | |||
| 89c991b636 | |||
| bbbd35e9ef | |||
| c308be315d | |||
| d825e3125e | |||
| 64288de04e | |||
| fb4471e69d | |||
| 8be8694f5f | |||
| 60b78dc2cd | |||
| 80fe5a8167 | |||
| df58c49876 | |||
| 7dee2f6995 | |||
| 623687e59b | |||
| 5958d3be62 | |||
| 142e57450d | |||
| 80815a1591 | |||
| 8412bfb813 | |||
| a0f279691a | |||
| 92aeddb9fe | |||
| d7da88853b | |||
| 89678c7b1e | |||
| 098c826095 | |||
| befbdc3ae5 | |||
| dca0364f4c | |||
| 37771259d9 | |||
| 4618e4851c | |||
| b2ca280c49 | |||
| bf6995f759 | |||
| ab0cce7cb7 | |||
| 2e422fc026 | |||
| a2f9d132a0 | |||
| 1973b97cc2 | |||
| b3c6f0e661 | |||
| 6998b17f9e | |||
| ed9932d70d | |||
| a5f3b2a949 | |||
| 152ed59502 | |||
| 8e16be9e11 | |||
| 300701f44e | |||
| d1370622d8 | |||
| 0134166009 | |||
| ddb9084260 | |||
| 0224452cef | |||
| c17d4dc050 | |||
| 4e33f45522 | |||
| b16d7abb35 | |||
| 2f17a30157 | |||
| 0dbd14ebdc | |||
| 8b3d8ccb47 | |||
| f8ff2e4e28 | |||
| 044f0d41a5 | |||
| 4089bebd83 | |||
| d4787c75fd | |||
| 3bf0a57b82 | |||
| cc505ae49f | |||
| 2f6de136dd | |||
| da21b50137 | |||
| a38a5c529f | |||
| 44b5612697 | |||
| 0113292cf6 | |||
| 4741ab2e04 | |||
| 08fb9435fd | |||
| 793e92e9d6 | |||
| a7c57f4faf | |||
| 8409107a5b | |||
| 9089c3fb02 | |||
| 6c897d5201 | |||
| 6cb5135f34 | |||
| 44bf45794e | |||
| d6da9f47d8 | |||
| be05b66ac3 | |||
| d1998ae3fa | |||
| 3c2e1554c6 | |||
| 744955ba69 | |||
| 7af33f9e6a | |||
| 3c0705b0ae | |||
| 4ea4d2bd3b | |||
| 6c52077d92 | |||
| 73bf7b1730 | |||
| b394cb6379 | |||
| 60854e180e | |||
| 5b4750a009 | |||
| ad50dd21fe | |||
| 8b0cb0bb57 | |||
| a24a6e4e3c | |||
| 6fba4c371e | |||
| 27911431db | |||
| db6447ed79 | |||
| 99c0fabee6 | |||
| fc99724aba | |||
| 88fbc62b1d | |||
| e8027d571f | |||
| daaee43be3 | |||
| 0d71cb93af | |||
| e5e50e82d5 | |||
| 7e852124a5 | |||
| f66a49bc42 | |||
| baf78ccda2 | |||
| 31f0e66f45 | |||
| 28b78a563b | |||
| 2f380de73b | |||
| e3a9a39c9a | |||
| 1710bb78df | |||
| 3e13fc3e70 | |||
| befc399506 | |||
| 88116b9fb1 | |||
| 53e1c58cc5 | |||
| 4b9ecdd11d | |||
| e31e409ee8 | |||
| 5488aaf69f | |||
| 96e493d8b1 | |||
| e409453fbd | |||
| 309bf1348c | |||
| 76a5635298 | |||
| f4f2a1f6de | |||
| a440805ea1 | |||
| c359672bd2 | |||
| 38350935e6 | |||
| 421cd89a0f | |||
| 5ce3369aa6 | |||
| f38acfe988 | |||
| 965619d096 | |||
| 9f017e834c | |||
| 3c67b08488 | |||
| 4add755a4d | |||
| 56e249aee6 | |||
| 6a7c8fcfd5 | |||
| 14b1003c62 | |||
| 43a4bae010 | |||
| 9c205f77a2 | |||
| c2e4cfd832 | |||
| c008e1c5bc | |||
| 1aa60f0da3 | |||
| bd1fd8383c | |||
| aac54d0ea1 | |||
| 4fe718581b | |||
| 71842f07bd | |||
| f2bec1f82f | |||
| 10460191b9 | |||
| c5fffd6e2c | |||
| 951f63b6fd | |||
| e6d8932b3b | |||
| 70f96cca0a | |||
| 4e357e9659 | |||
| 1f8aed6732 | |||
| fa2bace3cd | |||
| 955039b5ea | |||
| 771ea1e815 | |||
| d38bfc4aff | |||
| fbb0054232 | |||
| 2d3c36edae | |||
| 8dcc41a54d | |||
| ba3d2e36c8 | |||
| b51047ffcc | |||
| b1c40a9079 | |||
| b014c267ae | |||
| 6b16cc52db | |||
| d35ad73e35 | |||
| 2a1af3d9ae | |||
| 82e30246c1 | |||
| bb3a05bb3f | |||
| 40fa82275c | |||
| 9824321fc9 | |||
| 27e607ab82 | |||
| a2b27b8790 | |||
| 396089ef0e | |||
| df98b5021d | |||
| 34ce6d0b02 | |||
| 7af937b08e | |||
| 8665003269 | |||
| 1e76716819 | |||
| 91a42fdf58 | |||
| 5ed5243be6 | |||
| 4560251e64 | |||
| 2020dca3e0 | |||
| 7fc2121454 | |||
| 8b84afbd38 | |||
| 305fc3b557 | |||
| 61f2ac01d7 | |||
| 39a9f55205 | |||
| 11f351dbeb | |||
| 815fa379ea | |||
| 4c480a1ea3 | |||
| fa4aa0e06d | |||
| e2a6374bf5 | |||
| dc14554053 | |||
| 985ca7b643 | |||
| 60624d64fa | |||
| 2935dae89e | |||
| 4c22c3285d | |||
| 93cee2994a | |||
| 9c7e8d04d2 | |||
| 1e6b8906e0 | |||
| 6c5b92e5c0 | |||
| 38c515e12e | |||
| c239937fac | |||
| bafa574784 | |||
| 199a5854a8 | |||
| a74a578198 | |||
| 7de752ec56 | |||
| 0a833171ac | |||
| 1a0612cbfd | |||
| fbbd3ba349 | |||
| 1028639186 | |||
| 0e5e764c78 | |||
| db1faecc95 | |||
| c2c415d2e8 | |||
| d193928f31 | |||
| 17861e0003 | |||
| 97fe964e00 | |||
| 9debb5db23 | |||
| 494b438151 | |||
| 010a236882 | |||
| 1951d2a9f2 |
@@ -1 +1,12 @@
|
|||||||
|
# LFS configuration for images from the wiki
|
||||||
*.png filter=lfs diff=lfs merge=lfs -text
|
*.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'
|
||||||
|
|||||||
@@ -9,9 +9,23 @@ assignees: ''
|
|||||||
|
|
||||||
<!-- Please describe the issue here at the top, then fill in the system information below. -->
|
<!-- Please describe the issue here at the top, then fill in the system information below. -->
|
||||||
|
|
||||||
|
<!-- Attaching your full niri config can help diagnose the problem. -->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If you have a problem with a specific app, please verify that it is running on Wayland, rather than X11. An easy way is to run xeyes and mouse over the app: xeyes will be able to "see" only X11 windows.
|
||||||
|
|
||||||
|
You can also check what process the window PID belongs to:
|
||||||
|
|
||||||
|
$ readlink /proc/$(niri msg --json pick-window | jq .pid)/exe
|
||||||
|
|
||||||
|
If this points to xwayland-satellite, then it's an X11 window.
|
||||||
|
|
||||||
|
Please report issues with X11 apps to xwayland-satellite instead of niri: https://github.com/Supreeeme/xwayland-satellite/issues
|
||||||
|
-->
|
||||||
|
|
||||||
### System Information
|
### System Information
|
||||||
|
|
||||||
<!-- Paste the output of `niri -V`, e.g. niri 0.1.0-beta.1 (v0.1.0-beta.1) -->
|
<!-- Paste the output of `niri -V`, e.g. niri 25.02 (b94a5db) -->
|
||||||
* niri version:
|
* niri version:
|
||||||
|
|
||||||
<!-- Write your distribution, e.g. Fedora 40 Silverblue -->
|
<!-- Write your distribution, e.g. Fedora 40 Silverblue -->
|
||||||
|
|||||||
@@ -2,3 +2,9 @@ contact_links:
|
|||||||
- name: Feature request
|
- name: Feature request
|
||||||
url: https://github.com/YaLTeR/niri/discussions/new?category=ideas
|
url: https://github.com/YaLTeR/niri/discussions/new?category=ideas
|
||||||
about: Ideas for new features and functionality (start a Discussion)
|
about: Ideas for new features and functionality (start a Discussion)
|
||||||
|
- name: Ask a question
|
||||||
|
url: https://github.com/YaLTeR/niri/discussions/new?category=q-a
|
||||||
|
about: Question about niri (start a Discussion)
|
||||||
|
- name: Matrix room
|
||||||
|
url: https://matrix.to/#/#niri:matrix.org
|
||||||
|
about: Chat about niri with other users
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "cargo"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
groups:
|
||||||
|
smithay:
|
||||||
|
patterns:
|
||||||
|
- "smithay"
|
||||||
|
- "smithay-drm-extras"
|
||||||
|
rust-dependencies:
|
||||||
|
update-types:
|
||||||
|
- "minor"
|
||||||
|
- "patch"
|
||||||
|
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
ignore:
|
||||||
|
- dependency-name: "Andrew-Chen-Wang/github-wiki-action"
|
||||||
+199
-68
@@ -8,23 +8,18 @@ on:
|
|||||||
- cron: '0 0 1 * *' # Monthly
|
- cron: '0 0 1 * *' # Monthly
|
||||||
|
|
||||||
env:
|
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:
|
jobs:
|
||||||
build:
|
test:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
matrix:
|
name: test
|
||||||
configuration: [debug, release]
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
include:
|
|
||||||
- configuration: release
|
|
||||||
release-flag: '--release'
|
|
||||||
|
|
||||||
name: test - ${{ matrix.configuration }}
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
container: ubuntu:23.10
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -33,49 +28,124 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
apt-get update -y
|
sudo apt-get update -y
|
||||||
apt-get install -y 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
|
sudo apt-get install -y ${{ env.DEPS_APT }}
|
||||||
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
with:
|
|
||||||
key: ${{ matrix.configuration }}
|
|
||||||
|
|
||||||
- name: Check (no default features)
|
- name: Build tests
|
||||||
run: cargo check ${{ matrix.release-flag }} --no-default-features
|
run: cargo test --no-run --all --exclude niri-visual-tests
|
||||||
|
|
||||||
- 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 }}
|
|
||||||
|
|
||||||
- name: Test
|
- 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 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
|
||||||
|
PROPTEST_MAX_SHRINK_ITERS: 200000
|
||||||
|
|
||||||
|
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: Build tests
|
||||||
|
run: cargo test --no-run --all --exclude niri-visual-tests --release
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: cargo test --all --exclude niri-visual-tests --release
|
||||||
|
|
||||||
visual-tests:
|
visual-tests:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
name: visual tests
|
name: visual tests
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
container: ubuntu:23.10
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -84,8 +154,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
apt-get update -y
|
sudo apt-get update -y
|
||||||
apt-get install -y 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 libadwaita-1-dev libdisplay-info-dev
|
sudo apt-get install -y ${{ env.DEPS_APT }} libadwaita-1-dev
|
||||||
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
@@ -98,9 +168,8 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
name: 'msrv - 1.77.0'
|
name: msrv
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
container: ubuntu:23.10
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -109,10 +178,10 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
apt-get update -y
|
sudo apt-get update -y
|
||||||
apt-get install -y 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 libadwaita-1-dev libdisplay-info-dev
|
sudo apt-get install -y ${{ env.DEPS_APT }} libadwaita-1-dev
|
||||||
|
|
||||||
- uses: dtolnay/rust-toolchain@1.77.0
|
- uses: dtolnay/rust-toolchain@1.80.1
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
@@ -123,8 +192,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
name: clippy
|
name: clippy
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
container: ubuntu:23.10
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -133,8 +201,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
apt-get update -y
|
sudo apt-get update -y
|
||||||
apt-get install -y 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 libadwaita-1-dev libdisplay-info-dev
|
sudo apt-get install -y ${{ env.DEPS_APT }} libadwaita-1-dev
|
||||||
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
@@ -146,7 +214,7 @@ jobs:
|
|||||||
run: cargo clippy --all --all-targets
|
run: cargo clippy --all --all-targets
|
||||||
|
|
||||||
rustfmt:
|
rustfmt:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -161,8 +229,8 @@ jobs:
|
|||||||
run: cargo fmt --all -- --check
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
fedora:
|
fedora:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
container: fedora:39
|
container: fedora:41
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -172,13 +240,54 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo dnf update -y
|
sudo dnf update -y
|
||||||
sudo dnf install -y cargo gcc libudev-devel libgbm-devel libxkbcommon-devel wayland-devel libinput-devel dbus-devel systemd-devel libseat-devel pipewire-devel pango-devel cairo-gobject-devel clang libadwaita-devel libdisplay-info-devel
|
sudo dnf install -y ${{ env.DEPS_DNF }} libadwaita-devel
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
- run: cargo build --all
|
- 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:
|
nix:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -197,38 +306,60 @@ jobs:
|
|||||||
|
|
||||||
publish-wiki:
|
publish-wiki:
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
needs: build
|
needs:
|
||||||
|
- publish-docs
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
lfs: true
|
lfs: true
|
||||||
show-progress: false
|
show-progress: false
|
||||||
- uses: Andrew-Chen-Wang/github-wiki-action@86138cbd6328b21d759e89ab6e6dd6a139b22270
|
|
||||||
|
|
||||||
rustdoc:
|
- uses: Andrew-Chen-Wang/github-wiki-action@b7e552d7cb0fa7f83e459012ffc6840fd87bcb83
|
||||||
needs: build
|
with:
|
||||||
|
path: docs/wiki/
|
||||||
|
|
||||||
|
publish-docs:
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
needs:
|
||||||
|
- test
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
lfs: true
|
||||||
show-progress: false
|
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
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
- name: Generate documentation
|
- name: Generate rustdoc documentation
|
||||||
run: cargo doc --no-deps -p niri-ipc
|
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
|
- name: Deploy documentation
|
||||||
if: github.ref == 'refs/heads/main'
|
if: github.ref == 'refs/heads/main'
|
||||||
uses: peaceiris/actions-gh-pages@v4
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
publish_dir: ./target/doc
|
publish_dir: ./publish
|
||||||
force_orphan: true
|
force_orphan: true
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
name: Prepare release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: 'Public version'
|
||||||
|
required: true
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
RUN_SLOW_TESTS: 1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prepare-release:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
show-progress: false
|
||||||
|
|
||||||
|
- name: Check for unreplaced "Since:" in the wiki
|
||||||
|
run: |
|
||||||
|
if grep --recursive 'Since: next release' wiki; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y 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 libadwaita-1-dev
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- name: Create vendored dependencies archive
|
||||||
|
run: |
|
||||||
|
mkdir .cargo
|
||||||
|
cargo vendor --locked > .cargo/config.toml
|
||||||
|
tar cJf niri-${{ github.event.inputs.version }}-vendored-dependencies.tar.xz vendor/
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cargo build --all --frozen --release
|
||||||
|
|
||||||
|
- name: Build tests
|
||||||
|
run: cargo test --no-run --all --frozen --release
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: cargo test --all --frozen --release -- --nocapture
|
||||||
|
|
||||||
|
- name: Draft release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
tag_name: v${{ github.event.inputs.version }}
|
||||||
|
files: niri-${{ github.event.inputs.version }}-vendored-dependencies.tar.xz
|
||||||
|
fail_on_unmatched_files: true
|
||||||
@@ -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
+1089
-1224
File diff suppressed because it is too large
Load Diff
+58
-44
@@ -1,32 +1,38 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["niri-visual-tests"]
|
members = [
|
||||||
|
"niri-config",
|
||||||
|
"niri-ipc",
|
||||||
|
"niri-visual-tests",
|
||||||
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.10"
|
version = "25.5.1"
|
||||||
description = "A scrollable-tiling Wayland compositor"
|
description = "A scrollable-tiling Wayland compositor"
|
||||||
authors = ["Ivan Molodetskikh <yalterz@gmail.com>"]
|
authors = ["Ivan Molodetskikh <yalterz@gmail.com>"]
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/YaLTeR/niri"
|
repository = "https://github.com/YaLTeR/niri"
|
||||||
rust-version = "1.77"
|
rust-version = "1.80.1"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = "1.0.93"
|
anyhow = "1.0.99"
|
||||||
bitflags = "2.6.0"
|
bitflags = "2.9.2"
|
||||||
clap = { version = "4.5.20", features = ["derive"] }
|
clap = { version = "4.5.45", features = ["derive"] }
|
||||||
k9 = "0.12.0"
|
insta = "1.43.1"
|
||||||
serde = { version = "1.0.214", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_json = "1.0.132"
|
serde_json = "1.0.143"
|
||||||
tracing = { version = "0.1.40", features = ["max_level_trace", "release_max_level_debug"] }
|
tracing = { version = "0.1.41", features = ["max_level_trace", "release_max_level_debug"] }
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||||
tracy-client = { version = "0.17.4", default-features = false }
|
tracy-client = { version = "0.18.2", default-features = false }
|
||||||
|
|
||||||
[workspace.dependencies.smithay]
|
[workspace.dependencies.smithay]
|
||||||
|
# version = "0.4.1"
|
||||||
git = "https://github.com/Smithay/smithay.git"
|
git = "https://github.com/Smithay/smithay.git"
|
||||||
# path = "../smithay"
|
# path = "../smithay"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[workspace.dependencies.smithay-drm-extras]
|
[workspace.dependencies.smithay-drm-extras]
|
||||||
|
# version = "0.1.0"
|
||||||
git = "https://github.com/Smithay/smithay.git"
|
git = "https://github.com/Smithay/smithay.git"
|
||||||
# path = "../smithay/smithay-drm-extras"
|
# path = "../smithay/smithay-drm-extras"
|
||||||
|
|
||||||
@@ -46,46 +52,47 @@ keywords = ["wayland", "compositor", "tiling", "smithay", "wm"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
arrayvec = "0.7.6"
|
arrayvec = "0.7.6"
|
||||||
async-channel = "2.3.1"
|
async-channel = "2.5.0"
|
||||||
async-io = { version = "1.13.0", optional = true }
|
async-io = { version = "2.5.0", optional = true }
|
||||||
atomic = "0.6.0"
|
atomic = "0.6.1"
|
||||||
bitflags.workspace = true
|
bitflags.workspace = true
|
||||||
bytemuck = { version = "1.19.0", features = ["derive"] }
|
bytemuck = { version = "1.23.2", features = ["derive"] }
|
||||||
calloop = { version = "0.14.1", features = ["executor", "futures-io"] }
|
calloop = { version = "0.14.3", features = ["executor", "futures-io", "signals"] }
|
||||||
clap = { workspace = true, features = ["string"] }
|
clap = { workspace = true, features = ["string"] }
|
||||||
directories = "5.0.1"
|
clap_complete = "4.5.57"
|
||||||
|
clap_complete_nushell = "4.5.8"
|
||||||
|
directories = "6.0.0"
|
||||||
drm-ffi = "0.9.0"
|
drm-ffi = "0.9.0"
|
||||||
fastrand = "2.2.0"
|
fastrand = "2.3.0"
|
||||||
futures-util = { version = "0.3.31", default-features = false, features = ["std", "io"] }
|
futures-util = { version = "0.3.31", default-features = false, features = ["std", "io"] }
|
||||||
git-version = "0.3.9"
|
git-version = "0.3.9"
|
||||||
glam = "0.29.2"
|
glam = "0.30.5"
|
||||||
input = { version = "0.9.1", features = ["libinput_1_21"] }
|
input = { version = "0.9.1", features = ["libinput_1_21"] }
|
||||||
keyframe = { version = "1.1.1", default-features = false }
|
keyframe = { version = "1.1.1", default-features = false }
|
||||||
libc = "0.2.162"
|
libc = "0.2.175"
|
||||||
libdisplay-info = "0.1.0"
|
libdisplay-info = "0.2.2"
|
||||||
log = { version = "0.4.22", features = ["max_level_trace", "release_max_level_debug"] }
|
log = { version = "0.4.27", features = ["max_level_trace", "release_max_level_debug"] }
|
||||||
niri-config = { version = "0.1.10", path = "niri-config" }
|
niri-config = { version = "25.5.1", path = "niri-config" }
|
||||||
niri-ipc = { version = "0.1.10", path = "niri-ipc", features = ["clap"] }
|
niri-ipc = { version = "25.5.1", path = "niri-ipc", features = ["clap"] }
|
||||||
notify-rust = { version = "~4.10.0", optional = true }
|
ordered-float = "5.0.0"
|
||||||
ordered-float = "4.5.0"
|
pango = { version = "0.20.12", features = ["v1_44"] }
|
||||||
pango = { version = "0.20.4", features = ["v1_44"] }
|
pangocairo = "0.20.10"
|
||||||
pangocairo = "0.20.4"
|
|
||||||
pipewire = { git = "https://gitlab.freedesktop.org/pipewire/pipewire-rs.git", optional = true, features = ["v0_3_33"] }
|
pipewire = { git = "https://gitlab.freedesktop.org/pipewire/pipewire-rs.git", optional = true, features = ["v0_3_33"] }
|
||||||
png = "0.17.14"
|
png = "0.17.16"
|
||||||
portable-atomic = { version = "1.9.0", default-features = false, features = ["float"] }
|
portable-atomic = { version = "1.11.1", default-features = false, features = ["float"] }
|
||||||
profiling = "1.0.16"
|
profiling = "1.0.17"
|
||||||
sd-notify = "0.4.3"
|
sd-notify = "0.4.5"
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
smithay-drm-extras.workspace = true
|
smithay-drm-extras.workspace = true
|
||||||
tracing-subscriber.workspace = true
|
tracing-subscriber.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
tracy-client.workspace = true
|
tracy-client.workspace = true
|
||||||
url = { version = "2.5.3", optional = true }
|
url = { version = "2.5.4", optional = true }
|
||||||
wayland-backend = "0.3.7"
|
wayland-backend = "0.3.11"
|
||||||
wayland-scanner = "0.31.5"
|
wayland-scanner = "0.31.7"
|
||||||
xcursor = "0.3.8"
|
xcursor = "0.3.10"
|
||||||
zbus = { version = "~3.15.2", optional = true }
|
zbus = { version = "5.9.0", optional = true }
|
||||||
|
|
||||||
[dependencies.smithay]
|
[dependencies.smithay]
|
||||||
workspace = true
|
workspace = true
|
||||||
@@ -107,15 +114,18 @@ features = [
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
approx = "0.5.1"
|
approx = "0.5.1"
|
||||||
k9.workspace = true
|
calloop-wayland-source = "0.4.0"
|
||||||
proptest = "1.5.0"
|
insta.workspace = true
|
||||||
proptest-derive = { version = "0.5.0", features = ["boxed_union"] }
|
proptest = "1.7.0"
|
||||||
xshell = "0.2.6"
|
proptest-derive = { version = "0.6.0", features = ["boxed_union"] }
|
||||||
|
rayon = "1.11.0"
|
||||||
|
wayland-client = "0.31.11"
|
||||||
|
xshell = "0.2.7"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["dbus", "systemd", "xdp-gnome-screencast"]
|
default = ["dbus", "systemd", "xdp-gnome-screencast"]
|
||||||
# Enables D-Bus support (serve various freedesktop and GNOME interfaces, power button handling).
|
# Enables D-Bus support (serve various freedesktop and GNOME interfaces, power button handling).
|
||||||
dbus = ["zbus", "async-io", "notify-rust", "url"]
|
dbus = ["dep:zbus", "dep:async-io", "dep:url"]
|
||||||
# Enables systemd integration (global environment, apps in transient scopes).
|
# Enables systemd integration (global environment, apps in transient scopes).
|
||||||
systemd = ["dbus"]
|
systemd = ["dbus"]
|
||||||
# Enables screencasting support through xdg-desktop-portal-gnome.
|
# Enables screencasting support through xdg-desktop-portal-gnome.
|
||||||
@@ -138,8 +148,12 @@ lto = "thin"
|
|||||||
# knuffel with chomsky generates a metric ton of debuginfo.
|
# knuffel with chomsky generates a metric ton of debuginfo.
|
||||||
debug = false
|
debug = false
|
||||||
|
|
||||||
|
[profile.dev.package]
|
||||||
|
insta.opt-level = 3
|
||||||
|
similar.opt-level = 3
|
||||||
|
|
||||||
[package.metadata.generate-rpm]
|
[package.metadata.generate-rpm]
|
||||||
version = "0.1.10"
|
version = "25.05.1"
|
||||||
assets = [
|
assets = [
|
||||||
{ source = "target/release/niri", dest = "/usr/bin/", mode = "755" },
|
{ source = "target/release/niri", dest = "/usr/bin/", mode = "755" },
|
||||||
{ source = "resources/niri-session", dest = "/usr/bin/", mode = "755" },
|
{ source = "resources/niri-session", dest = "/usr/bin/", mode = "755" },
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<h1 align="center">niri</h1>
|
<h1 align="center">niri</h1>
|
||||||
<p align="center">A scrollable-tiling Wayland compositor.</p>
|
<p align="center">A scrollable-tiling Wayland compositor.</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://matrix.to/#/#niri:matrix.org"><img alt="Matrix" src="https://img.shields.io/matrix/niri%3Amatrix.org?logo=matrix&label=matrix"></a>
|
<a href="https://matrix.to/#/#niri:matrix.org"><img alt="Matrix" src="https://img.shields.io/badge/matrix-%23niri-blue?logo=matrix"></a>
|
||||||
<a href="https://github.com/YaLTeR/niri/blob/main/LICENSE"><img alt="GitHub License" src="https://img.shields.io/github/license/YaLTeR/niri"></a>
|
<a href="https://github.com/YaLTeR/niri/blob/main/LICENSE"><img alt="GitHub License" src="https://img.shields.io/github/license/YaLTeR/niri"></a>
|
||||||
<a href="https://github.com/YaLTeR/niri/releases"><img alt="GitHub Release" src="https://img.shields.io/github/v/release/YaLTeR/niri?logo=github"></a>
|
<a href="https://github.com/YaLTeR/niri/releases"><img alt="GitHub Release" src="https://img.shields.io/github/v/release/YaLTeR/niri?logo=github"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<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 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 Showcase</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
@@ -28,14 +28,17 @@ When a monitor disconnects, its workspaces will move to another monitor, but upo
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Scrollable tiling
|
- Built from the ground up for scrollable tiling
|
||||||
- Dynamic 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
|
- Built-in screenshot UI
|
||||||
- Monitor and window screencasting through xdg-desktop-portal-gnome
|
- 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
|
- [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://yalter.github.io/niri/Tabs.html)
|
||||||
- Configurable layout: gaps, borders, struts, window sizes
|
- 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)
|
- [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
|
- Live-reloading config
|
||||||
|
|
||||||
@@ -43,11 +46,60 @@ 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
|
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
|
## Status
|
||||||
|
|
||||||
A lot of the essential functionality is implemented, plus some goodies on top.
|
Niri is stable for day-to-day use and does most things expected of a Wayland compositor.
|
||||||
Feel free to give niri a try: follow the instructions on the [Getting Started](https://github.com/YaLTeR/niri/wiki/Getting-Started) wiki page.
|
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://yalter.github.io/niri/Getting-Started.html) page.
|
||||||
Have your [waybar]s and [fuzzel]s ready: niri is not a complete desktop environment.
|
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:
|
||||||
|
|
||||||
|
- **Multi-monitor**: yes, a core part of the design from the very start. Mixed DPI works.
|
||||||
|
- **Fractional scaling**: yes, plus all niri UI stays pixel-perfect.
|
||||||
|
- **NVIDIA**: seems to work fine.
|
||||||
|
- **Floating windows**: yes, starting from niri 25.01.
|
||||||
|
- **Input devices**: niri supports tablets, touchpads, and touchscreens.
|
||||||
|
You can map the tablet to a specific monitor, or use [OpenTabletDriver].
|
||||||
|
We have touchpad gestures, but no touchscreen gestures yet.
|
||||||
|
- **Wlr protocols**: yes, we have most of the important ones like layer-shell, gamma-control, screencopy.
|
||||||
|
You can check on [wayland.app](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://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://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
|
## Inspiration
|
||||||
|
|
||||||
@@ -62,19 +114,25 @@ Here are some other projects which implement a similar workflow:
|
|||||||
|
|
||||||
- [PaperWM]: scrollable tiling on top of GNOME Shell.
|
- [PaperWM]: scrollable tiling on top of GNOME Shell.
|
||||||
- [karousel]: scrollable tiling on top of KDE.
|
- [karousel]: scrollable tiling on top of KDE.
|
||||||
- [papersway]: scrollable tiling on top of sway/i3.
|
- [scroll](https://github.com/dawsers/scroll) and [papersway]: scrollable tiling on top of sway/i3.
|
||||||
- [hyprscroller] and [hyprslidr]: scrollable tiling on top of Hyprland.
|
- [hyprscrolling] and [hyprslidr]: scrollable tiling on top of Hyprland.
|
||||||
- [PaperWM.spoon]: scrollable tiling on top of macOS.
|
- [PaperWM.spoon]: scrollable tiling on top of macOS.
|
||||||
|
|
||||||
## Contact
|
## 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
|
[PaperWM]: https://github.com/paperwm/PaperWM
|
||||||
[waybar]: https://github.com/Alexays/Waybar
|
[waybar]: https://github.com/Alexays/Waybar
|
||||||
[fuzzel]: https://codeberg.org/dnkl/fuzzel
|
[fuzzel]: https://codeberg.org/dnkl/fuzzel
|
||||||
|
[awesome-niri]: https://github.com/Vortriz/awesome-niri
|
||||||
[karousel]: https://github.com/peterfajdiga/karousel
|
[karousel]: https://github.com/peterfajdiga/karousel
|
||||||
[papersway]: https://spwhitton.name/tech/code/papersway/
|
[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
|
[hyprslidr]: https://gitlab.com/magus/hyprslidr
|
||||||
[PaperWM.spoon]: https://github.com/mogenson/PaperWM.spoon
|
[PaperWM.spoon]: https://github.com/mogenson/PaperWM.spoon
|
||||||
|
[Matrix channel]: https://matrix.to/#/#niri:matrix.org
|
||||||
|
[OpenTabletDriver]: https://opentabletdriver.net/
|
||||||
|
[gamescope]: https://github.com/ValveSoftware/gamescope
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
site
|
||||||
|
__pycache__
|
||||||
@@ -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
|
||||||
|
)
|
||||||
@@ -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>"
|
||||||
@@ -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
|
||||||
|
- Layer‐Shell Components: Layer‐Shell-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
|
||||||
@@ -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
@@ -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" },
|
||||||
|
]
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
### Electron applications
|
||||||
|
|
||||||
|
Electron-based applications can run directly on Wayland, but it's not the default.
|
||||||
|
|
||||||
|
For Electron > 28, you can set an environment variable:
|
||||||
|
```kdl
|
||||||
|
environment {
|
||||||
|
ELECTRON_OZONE_PLATFORM_HINT "auto"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For previous versions, you need to pass command-line flags to the target application:
|
||||||
|
```
|
||||||
|
--enable-features=UseOzonePlatform --ozone-platform-hint=auto
|
||||||
|
```
|
||||||
|
|
||||||
|
If the application has a [desktop entry](https://specifications.freedesktop.org/menu-spec/latest/menu-add-example.html), you can put the command-line arguments into the `Exec` section.
|
||||||
|
|
||||||
|
### VSCode
|
||||||
|
|
||||||
|
If you're having issues with some VSCode hotkeys, try starting `Xwayland` and setting the `DISPLAY=:0` environment variable for VSCode.
|
||||||
|
That is, still running VSCode with the Wayland backend, but with `DISPLAY` set to a running Xwayland instance.
|
||||||
|
Apparently, VSCode currently unconditionally queries the X server for a keymap.
|
||||||
|
|
||||||
|
### WezTerm
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Both of these issues seem to be fixed in the nightly build of WezTerm.
|
||||||
|
|
||||||
|
There's [a bug](https://github.com/wezterm/wezterm/issues/4708) in WezTerm that it waits for a zero-sized Wayland configure event, so its window never shows up in niri. To work around it, put this window rule in the niri config (included in the default config):
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
window-rule {
|
||||||
|
match app-id=r#"^org\.wezfurlong\.wezterm$"#
|
||||||
|
default-column-width {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This empty default column width lets WezTerm pick its own initial width which makes it show up properly.
|
||||||
|
|
||||||
|
There's [another bug](https://github.com/wezterm/wezterm/issues/6472) in WezTerm that causes it to choose a wrong size when it's in a tiled state, and prevent resizing it.
|
||||||
|
Niri puts windows in the tiled state with [`prefer-no-csd`](./Configuration:-Miscellaneous.md#prefer-no-csd).
|
||||||
|
So if you hit this problem, comment out `prefer-no-csd` in the niri config and restart WezTerm.
|
||||||
|
|
||||||
|
### Ghidra
|
||||||
|
|
||||||
|
Some Java apps like Ghidra can show up blank under xwayland-satellite.
|
||||||
|
To fix this, run them with the `_JAVA_AWT_WM_NONREPARENTING=1` environment variable.
|
||||||
|
|
||||||
|
### rofi-wayland
|
||||||
|
|
||||||
|
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.
|
||||||
|
Most of these can be avoided with Valve's [gamescope](https://github.com/ValveSoftware/gamescope), for example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gamescope -f -w 1920 -h 1080 -W 1920 -H 1080 --force-grab-cursor --backend sdl -- <game>
|
||||||
|
```
|
||||||
|
|
||||||
|
This command will run *<game>* in 1080p fullscreen—make sure to replace the width and height values to match your desired resolution.
|
||||||
|
`--force-grab-cursor` forces gamescope to use relative mouse movement which prevents the cursor from escaping the game's window on multi-monitor setups.
|
||||||
|
Note that `--backend sdl` is currently also required as gamescope's default Wayland backend doesn't lock the cursor properly (possibly related to https://github.com/ValveSoftware/gamescope/issues/1711).
|
||||||
|
|
||||||
|
Steam users should use gamescope through a game's [launch options](https://help.steampowered.com/en/faqs/view/7D01-D2DD-D75E-2955) by replacing the game executable with `%command%`.
|
||||||
|
Other game launchers such as [Lutris](https://lutris.net/) have their own ways of setting gamescope options.
|
||||||
|
|
||||||
|
Running X11-based games with this method doesn't require Xwayland as gamescope creates its own Xwayland server.
|
||||||
|
You can run Wayland-native games as well by passing `--expose-wayland` to gamescope, therefore eliminating X11 from the equation.
|
||||||
|
|
||||||
|
### Steam
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
window-rule {
|
||||||
|
match app-id="steam" title=r#"^notificationtoasts_\d+_desktop$"#
|
||||||
|
default-floating-position x=10 y=10 relative-to="bottom-right"
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -50,6 +50,10 @@ animations {
|
|||||||
duration-ms 200
|
duration-ms 200
|
||||||
curve "ease-out-quad"
|
curve "ease-out-quad"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
overview-open-close {
|
||||||
|
spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -159,7 +163,7 @@ animations {
|
|||||||
|
|
||||||
##### `custom-shader`
|
##### `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.
|
You can write a custom shader for drawing the window during an open animation.
|
||||||
|
|
||||||
@@ -219,7 +223,7 @@ animations {
|
|||||||
|
|
||||||
##### `custom-shader`
|
##### `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.
|
You can write a custom shader for drawing the window during a close animation.
|
||||||
|
|
||||||
@@ -315,7 +319,7 @@ animations {
|
|||||||
|
|
||||||
##### `custom-shader`
|
##### `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.
|
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
|
### Synchronized Animations
|
||||||
|
|
||||||
<sup>Since: 0.1.5</sup>
|
<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.
|
They are not meant for normal use.
|
||||||
|
|
||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
> These options are **not** covered by the [config breaking change policy](./Configuration:-Overview.md).
|
> 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.
|
> They can change or stop working at any point with little notice.
|
||||||
|
|
||||||
Here are all the options at a glance:
|
Here are all the options at a glance:
|
||||||
@@ -16,7 +16,9 @@ debug {
|
|||||||
enable-overlay-planes
|
enable-overlay-planes
|
||||||
disable-cursor-plane
|
disable-cursor-plane
|
||||||
disable-direct-scanout
|
disable-direct-scanout
|
||||||
|
restrict-primary-scanout-to-matching-format
|
||||||
render-drm-device "/dev/dri/renderD129"
|
render-drm-device "/dev/dri/renderD129"
|
||||||
|
force-pipewire-invalid-modifier
|
||||||
dbus-interfaces-in-non-session-instances
|
dbus-interfaces-in-non-session-instances
|
||||||
wait-for-frame-completion-before-queueing
|
wait-for-frame-completion-before-queueing
|
||||||
emulate-zero-presentation-time
|
emulate-zero-presentation-time
|
||||||
@@ -24,6 +26,11 @@ debug {
|
|||||||
disable-transactions
|
disable-transactions
|
||||||
keep-laptop-panel-on-when-lid-is-closed
|
keep-laptop-panel-on-when-lid-is-closed
|
||||||
disable-monitor-names
|
disable-monitor-names
|
||||||
|
strict-new-window-focus-policy
|
||||||
|
honor-xdg-activation-with-invalid-serial
|
||||||
|
skip-cursor-only-updates-during-vrr
|
||||||
|
deactivate-unfocused-windows
|
||||||
|
keep-max-bpc-unchanged
|
||||||
}
|
}
|
||||||
|
|
||||||
binds {
|
binds {
|
||||||
@@ -82,6 +89,20 @@ debug {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `restrict-primary-scanout-to-matching-format`
|
||||||
|
|
||||||
|
Restricts direct scanout to the primary plane to when the window buffer exactly matches the composition swapchain format.
|
||||||
|
|
||||||
|
This flag may prevent unexpected bandwidth changes when going between composition and scanout.
|
||||||
|
The plan is to make it default in the future, when we implement a way to tell the clients the composition swapchain format.
|
||||||
|
As is, it may prevent some clients (mpv on my machine) from scanning out to the primary plane.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
debug {
|
||||||
|
restrict-primary-scanout-to-matching-format
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### `render-drm-device`
|
### `render-drm-device`
|
||||||
|
|
||||||
Override the DRM device that niri will use for all rendering.
|
Override the DRM device that niri will use for all rendering.
|
||||||
@@ -94,6 +115,20 @@ debug {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `force-pipewire-invalid-modifier`
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
Forces PipeWire screencasting to use the invalid modifier, even when DRM offers more modifiers.
|
||||||
|
|
||||||
|
Useful for testing the invalid modifier code path that is hit by drivers that don't support modifiers.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
debug {
|
||||||
|
force-pipewire-invalid-modifier
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### `dbus-interfaces-in-non-session-instances`
|
### `dbus-interfaces-in-non-session-instances`
|
||||||
|
|
||||||
Make niri create its D-Bus interfaces even if it's not running as a `--session`.
|
Make niri create its D-Bus interfaces even if it's not running as a `--session`.
|
||||||
@@ -194,6 +229,87 @@ debug {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `strict-new-window-focus-policy`
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
Disables heuristic automatic focusing for new windows.
|
||||||
|
Only windows that activate themselves with a valid xdg-activation token will be focused.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
debug {
|
||||||
|
strict-new-window-focus-policy
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `honor-xdg-activation-with-invalid-serial`
|
||||||
|
|
||||||
|
<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.
|
||||||
|
|
||||||
|
By default, niri ignores xdg-activation tokens with invalid serials, to prevent windows from randomly stealing focus.
|
||||||
|
This debug flag makes niri honor such tokens, making the aforementioned widely-used apps get focus when clicking on their tray icon or notification.
|
||||||
|
|
||||||
|
Amusingly, clicking on a notification sends the app a perfectly valid activation token from the notification daemon, but these apps seem to simply ignore it.
|
||||||
|
Maybe in the future these apps/toolkits (Electron, Qt) are fixed, making this debug flag unnecessary.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
debug {
|
||||||
|
honor-xdg-activation-with-invalid-serial
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `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
|
### Key Bindings
|
||||||
|
|
||||||
These are not debug options, but rather key bindings.
|
These are not debug options, but rather key bindings.
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
### Overview
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
The `gestures` config section contains gesture settings.
|
||||||
|
For an overview of all niri gestures, see the [Gestures](./Gestures.md) wiki page.
|
||||||
|
|
||||||
|
Here's a quick glance at the available settings along with their default values.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
gestures {
|
||||||
|
dnd-edge-view-scroll {
|
||||||
|
trigger-width 30
|
||||||
|
delay-ms 100
|
||||||
|
max-speed 1500
|
||||||
|
}
|
||||||
|
|
||||||
|
dnd-edge-workspace-switch {
|
||||||
|
trigger-height 50
|
||||||
|
delay-ms 100
|
||||||
|
max-speed 1500
|
||||||
|
}
|
||||||
|
|
||||||
|
hot-corners {
|
||||||
|
// off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `dnd-edge-view-scroll`
|
||||||
|
|
||||||
|
Scroll the tiling view when moving the mouse cursor against a monitor edge during drag-and-drop (DnD).
|
||||||
|
Also works on a touchscreen.
|
||||||
|
|
||||||
|
This will work for regular drag-and-drop (e.g. dragging a file from a file manager), and for window interactive move when targeting the tiling layout.
|
||||||
|
|
||||||
|
The options are:
|
||||||
|
|
||||||
|
- `trigger-width`: 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 in logical pixels 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-view-scroll {
|
||||||
|
trigger-width 100
|
||||||
|
max-speed 3000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -17,11 +17,13 @@ input {
|
|||||||
// options "compose:ralt,ctrl:nocaps"
|
// options "compose:ralt,ctrl:nocaps"
|
||||||
// model ""
|
// model ""
|
||||||
// rules ""
|
// rules ""
|
||||||
|
// file "~/.config/keymap.xkb"
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeat-delay 600
|
// repeat-delay 600
|
||||||
// repeat-rate 25
|
// repeat-rate 25
|
||||||
// track-layout "global"
|
// track-layout "global"
|
||||||
|
numlock
|
||||||
}
|
}
|
||||||
|
|
||||||
touchpad {
|
touchpad {
|
||||||
@@ -29,12 +31,16 @@ input {
|
|||||||
tap
|
tap
|
||||||
// dwt
|
// dwt
|
||||||
// dwtp
|
// dwtp
|
||||||
|
// drag false
|
||||||
|
// drag-lock
|
||||||
natural-scroll
|
natural-scroll
|
||||||
// accel-speed 0.2
|
// accel-speed 0.2
|
||||||
// accel-profile "flat"
|
// accel-profile "flat"
|
||||||
// scroll-factor 1.0
|
// scroll-factor 1.0
|
||||||
|
// scroll-factor vertical=1.0 horizontal=-2.0
|
||||||
// scroll-method "two-finger"
|
// scroll-method "two-finger"
|
||||||
// scroll-button 273
|
// scroll-button 273
|
||||||
|
// scroll-button-lock
|
||||||
// tap-button-map "left-middle-right"
|
// tap-button-map "left-middle-right"
|
||||||
// click-method "clickfinger"
|
// click-method "clickfinger"
|
||||||
// left-handed
|
// left-handed
|
||||||
@@ -48,8 +54,10 @@ input {
|
|||||||
// accel-speed 0.2
|
// accel-speed 0.2
|
||||||
// accel-profile "flat"
|
// accel-profile "flat"
|
||||||
// scroll-factor 1.0
|
// scroll-factor 1.0
|
||||||
|
// scroll-factor vertical=1.0 horizontal=-2.0
|
||||||
// scroll-method "no-scroll"
|
// scroll-method "no-scroll"
|
||||||
// scroll-button 273
|
// scroll-button 273
|
||||||
|
// scroll-button-lock
|
||||||
// left-handed
|
// left-handed
|
||||||
// middle-emulation
|
// middle-emulation
|
||||||
}
|
}
|
||||||
@@ -61,6 +69,8 @@ input {
|
|||||||
// accel-profile "flat"
|
// accel-profile "flat"
|
||||||
// scroll-method "on-button-down"
|
// scroll-method "on-button-down"
|
||||||
// scroll-button 273
|
// scroll-button 273
|
||||||
|
// scroll-button-lock
|
||||||
|
// left-handed
|
||||||
// middle-emulation
|
// middle-emulation
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +81,7 @@ input {
|
|||||||
// accel-profile "flat"
|
// accel-profile "flat"
|
||||||
// scroll-method "on-button-down"
|
// scroll-method "on-button-down"
|
||||||
// scroll-button 273
|
// scroll-button 273
|
||||||
|
// scroll-button-lock
|
||||||
// left-handed
|
// left-handed
|
||||||
// middle-emulation
|
// middle-emulation
|
||||||
}
|
}
|
||||||
@@ -79,9 +90,11 @@ input {
|
|||||||
// off
|
// off
|
||||||
map-to-output "eDP-1"
|
map-to-output "eDP-1"
|
||||||
// left-handed
|
// left-handed
|
||||||
|
// calibration-matrix 1.0 0.0 0.0 0.0 1.0 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
touch {
|
touch {
|
||||||
|
// off
|
||||||
map-to-output "eDP-1"
|
map-to-output "eDP-1"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +102,9 @@ input {
|
|||||||
// warp-mouse-to-focus
|
// warp-mouse-to-focus
|
||||||
// focus-follows-mouse max-scroll-amount="0%"
|
// focus-follows-mouse max-scroll-amount="0%"
|
||||||
// workspace-auto-back-and-forth
|
// workspace-auto-back-and-forth
|
||||||
|
|
||||||
|
// mod-key "Super"
|
||||||
|
// mod-key-nested "Alt"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -112,6 +128,51 @@ input {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
>
|
||||||
|
> <sup>Since: 25.02</sup>
|
||||||
|
>
|
||||||
|
> Alternatively, you can directly set a path to a .xkb file containing an xkb keymap.
|
||||||
|
> This overrides all other xkb settings.
|
||||||
|
>
|
||||||
|
> ```kdl
|
||||||
|
> input {
|
||||||
|
> keyboard {
|
||||||
|
> xkb {
|
||||||
|
> file "~/.config/keymap.xkb"
|
||||||
|
> }
|
||||||
|
> }
|
||||||
|
> }
|
||||||
|
> ```
|
||||||
|
|
||||||
|
> [!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.
|
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.
|
You can control this with the `track-layout` option.
|
||||||
|
|
||||||
@@ -140,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
|
### Pointing Devices
|
||||||
|
|
||||||
Most settings for the pointing devices are passed directly to libinput.
|
Most settings for the pointing devices are passed directly to libinput.
|
||||||
@@ -158,6 +235,8 @@ 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`.
|
- `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.
|
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`: <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.
|
- `middle-emulation`: emulate a middle mouse click by pressing left and right mouse buttons at once.
|
||||||
|
|
||||||
Settings specific to `touchpad`s:
|
Settings specific to `touchpad`s:
|
||||||
@@ -165,6 +244,8 @@ Settings specific to `touchpad`s:
|
|||||||
- `tap`: tap-to-click.
|
- `tap`: tap-to-click.
|
||||||
- `dwt`: disable-when-typing.
|
- `dwt`: disable-when-typing.
|
||||||
- `dwtp`: disable-when-trackpointing.
|
- `dwtp`: disable-when-trackpointing.
|
||||||
|
- `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.
|
- `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).
|
- `click-method`: can be `button-areas` or `clickfinger`, changes the [click method](https://wayland.freedesktop.org/libinput/doc/latest/clickpad-softbuttons.html).
|
||||||
- `disabled-on-external-mouse`: do not send events while external pointer device is plugged in.
|
- `disabled-on-external-mouse`: do not send events while external pointer device is plugged in.
|
||||||
@@ -173,9 +254,11 @@ Settings specific to `touchpad` and `mouse`:
|
|||||||
|
|
||||||
- `scroll-factor`: <sup>Since: 0.1.10</sup> scales the scrolling speed by this value.
|
- `scroll-factor`: <sup>Since: 0.1.10</sup> scales the scrolling speed by this value.
|
||||||
|
|
||||||
Settings specific to `touchpad`, `mouse` and `tablet`:
|
<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`
|
||||||
|
|
||||||
- `left-handed`: if set, changes the device to left-handed mode.
|
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.
|
||||||
|
|
||||||
Tablets and touchscreens are absolute pointing devices that can be mapped to a specific output like so:
|
Tablets and touchscreens are absolute pointing devices that can be mapped to a specific output like so:
|
||||||
|
|
||||||
@@ -214,7 +297,7 @@ input {
|
|||||||
|
|
||||||
Makes the mouse warp to newly focused windows.
|
Makes the mouse warp to newly focused windows.
|
||||||
|
|
||||||
X and Y coordinates are computed separately, i.e. if moving the mouse only horizontally is enough to put it inside the newly focused window, then it will move only horizontally.
|
Does not make the cursor visible if it had been hidden.
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
input {
|
input {
|
||||||
@@ -222,6 +305,21 @@ 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: 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.
|
||||||
|
- `mode="center-xy-always"`: warps by both X and Y coordinates together, even if the mouse was already somewhere inside the newly focused window.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
input {
|
||||||
|
warp-mouse-to-focus mode="center-xy"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### `focus-follows-mouse`
|
#### `focus-follows-mouse`
|
||||||
|
|
||||||
Focuses windows and outputs automatically when moving the mouse over them.
|
Focuses windows and outputs automatically when moving the mouse over them.
|
||||||
@@ -262,3 +360,24 @@ input {
|
|||||||
workspace-auto-back-and-forth
|
workspace-auto-back-and-forth
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `mod-key`, `mod-key-nested`
|
||||||
|
|
||||||
|
<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`.
|
||||||
|
|
||||||
|
By default, `Mod` is equal to `Super` when running niri on a TTY, and to `Alt` when running niri as a nested winit window.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> There are a lot of default bindings with Mod, none of them "make it through" to the underlying window.
|
||||||
|
> You probably don't want to set `mod-key` to Ctrl or Shift, since Ctrl is commonly used for app hotkeys, and Shift is used for, well, regular typing.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Switch the mod keys around: use Alt normally, and Super inside a nested window.
|
||||||
|
input {
|
||||||
|
mod-key "Alt"
|
||||||
|
mod-key-nested "Super"
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -9,7 +9,9 @@ You can find documentation for various sections of the config on these wiki page
|
|||||||
* [`layout {}`](./Configuration:-Layout.md)
|
* [`layout {}`](./Configuration:-Layout.md)
|
||||||
* [top-level options](./Configuration:-Miscellaneous.md)
|
* [top-level options](./Configuration:-Miscellaneous.md)
|
||||||
* [`window-rule {}`](./Configuration:-Window-Rules.md)
|
* [`window-rule {}`](./Configuration:-Window-Rules.md)
|
||||||
|
* [`layer-rule {}`](./Configuration:-Layer-Rules.md)
|
||||||
* [`animations {}`](./Configuration:-Animations.md)
|
* [`animations {}`](./Configuration:-Animations.md)
|
||||||
|
* [`gestures {}`](./Configuration:-Gestures.md)
|
||||||
* [`debug {}`](./Configuration:-Debug-Options.md)
|
* [`debug {}`](./Configuration:-Debug-Options.md)
|
||||||
|
|
||||||
### Loading
|
### Loading
|
||||||
@@ -129,15 +131,12 @@ output "eDP-1" {
|
|||||||
### Defaults
|
### Defaults
|
||||||
|
|
||||||
Omitting most of the sections of the config file will leave you with the default values for that section.
|
Omitting most of the sections of the config file will leave you with the default values for that section.
|
||||||
A notable exception is `binds {}`: they do not get filled with defaults, so make sure you do not erase this section.
|
A notable exception is [`binds {}`](./Configuration:-Key-Bindings.md): they do not get filled with defaults, so make sure you do not erase this section.
|
||||||
|
|
||||||
### Breaking Change Policy
|
### Breaking Change Policy
|
||||||
|
|
||||||
Configuration backwards compatibility follows the Rust / Cargo semantic versioning standards.
|
As a rule, niri updates should not break existing config files.
|
||||||
A patch release (i.e. niri 0.1.3 to 0.1.4) must not cause a parse error on a config that worked on the previous version.
|
(For example, the default config from niri v0.1.0 still parses fine on v25.02 as I'm writing this.)
|
||||||
|
|
||||||
A minor release (i.e. niri 0.1.3 to 0.2.0) *can* cause previously valid config files to stop parsing.
|
|
||||||
When niri reaches 1.0, a major release (i.e. niri 1.0 to 2.0) will be required to break config backwards compatibility.
|
|
||||||
|
|
||||||
Exceptions can be made for parsing bugs.
|
Exceptions can be made for parsing bugs.
|
||||||
For example, niri used to accept multiple binds to the same key, but this was not intended and did not do anything (the first bind was always used).
|
For example, niri used to accept multiple binds to the same key, but this was not intended and did not do anything (the first bind was always used).
|
||||||
@@ -24,12 +24,15 @@ Valid modifiers are:
|
|||||||
- `Alt`;
|
- `Alt`;
|
||||||
- `Super` or `Win`;
|
- `Super` or `Win`;
|
||||||
- `ISO_Level3_Shift` or `Mod5`—this is the AltGr key on certain layouts;
|
- `ISO_Level3_Shift` or `Mod5`—this is the AltGr key on certain layouts;
|
||||||
|
- `ISO_Level5_Shift`: can be used with an xkb lv5 option like `lv5:caps_switch`;
|
||||||
- `Mod`.
|
- `Mod`.
|
||||||
|
|
||||||
`Mod` is a special modifier that is equal to `Super` when running niri on a TTY, and to `Alt` when running niri as a nested winit window.
|
`Mod` is a special modifier that is equal to `Super` when running niri on a TTY, and to `Alt` when running niri as a nested winit window.
|
||||||
This way, you can test niri in a window without causing too many conflicts with the host compositor's key bindings.
|
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.
|
For this reason, most of the default keys use the `Mod` modifier.
|
||||||
|
|
||||||
|
<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]
|
> [!TIP]
|
||||||
> To find an XKB name for a particular key, you may use a program like [`wev`](https://git.sr.ht/~sircmpwn/wev).
|
> To find an XKB name for a particular key, you may use a program like [`wev`](https://git.sr.ht/~sircmpwn/wev).
|
||||||
>
|
>
|
||||||
@@ -49,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.
|
> 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.
|
> 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><</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><</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).
|
<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`:
|
You can disable that for specific binds with `repeat=false`:
|
||||||
@@ -98,6 +110,65 @@ binds {
|
|||||||
Both mouse wheel and touchpad scroll binds will prevent applications from receiving any scroll events when their modifiers are held down.
|
Both mouse wheel and touchpad scroll binds will prevent applications from receiving any scroll events when their modifiers are held down.
|
||||||
For example, if you have a `Mod+WheelScrollDown` bind, then while holding `Mod`, all mouse wheel scrolling will be consumed by niri.
|
For example, if you have a `Mod+WheelScrollDown` bind, then while holding `Mod`, all mouse wheel scrolling will be consumed by niri.
|
||||||
|
|
||||||
|
### Mouse Click Bindings
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
You can bind mouse clicks using the following syntax.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
Mod+MouseLeft { close-window; }
|
||||||
|
Mod+MouseRight { close-window; }
|
||||||
|
Mod+MouseMiddle { close-window; }
|
||||||
|
Mod+MouseForward { close-window; }
|
||||||
|
Mod+MouseBack { close-window; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Mouse clicks operate on the window that was focused at the time of the click, not the window you're clicking.
|
||||||
|
|
||||||
|
Note that binding `Mod+MouseLeft` or `Mod+MouseRight` will override the corresponding gesture (moving or resizing the window).
|
||||||
|
|
||||||
|
### Custom Hotkey Overlay Titles
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
The hotkey overlay (the Important Hotkeys dialog) shows a hardcoded list of binds.
|
||||||
|
You can customize this list using the `hotkey-overlay-title` property.
|
||||||
|
|
||||||
|
To add a bind to the hotkey overlay, set the property to the title that you want to show:
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
Mod+Shift+S hotkey-overlay-title="Toggle Dark/Light Style" { spawn "some-script.sh"; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Binds with custom titles are listed after the hardcoded binds and before non-customized Spawn binds.
|
||||||
|
|
||||||
|
To remove a hardcoded bind from the hotkey overlay, set the property to null:
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
Mod+Q hotkey-overlay-title=null { close-window; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> When multiple key combinations are bound to the same action:
|
||||||
|
> - If any of the binds has a custom hotkey overlay title, niri will show that bind.
|
||||||
|
> - Otherwise, if any of the binds has a null title, niri will hide the bind.
|
||||||
|
> - Otherwise, niri will show the first key combination.
|
||||||
|
|
||||||
|
Custom titles support [Pango markup](https://docs.gtk.org/Pango/pango_markup.html):
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
Mod+Shift+S hotkey-overlay-title="<b>Toggle</b> <span foreground='red'>Dark</span>/Light Style" { spawn "some-script.sh"; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### Actions
|
### Actions
|
||||||
|
|
||||||
Every action that you can bind is also available for programmatic invocation via `niri msg action`.
|
Every action that you can bind is also available for programmatic invocation via `niri msg action`.
|
||||||
@@ -135,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
|
```kdl
|
||||||
binds {
|
binds {
|
||||||
@@ -178,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`
|
#### `quit`
|
||||||
|
|
||||||
Exit niri after showing a confirmation dialog to avoid accidentally triggering it.
|
Exit niri after showing a confirmation dialog to avoid accidentally triggering it.
|
||||||
@@ -232,3 +335,73 @@ Or, in scripts:
|
|||||||
```shell
|
```shell
|
||||||
niri msg action do-screen-transition --delay-ms 100
|
niri msg action do-screen-transition --delay-ms 100
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `toggle-window-rule-opacity`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Toggle the opacity window rule of the focused window.
|
||||||
|
This only has an effect if the window's opacity window rule is already set to semitransparent.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
Mod+O { toggle-window-rule-opacity; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `screenshot`, `screenshot-screen`, `screenshot-window`
|
||||||
|
|
||||||
|
Actions for taking screenshots.
|
||||||
|
|
||||||
|
- `screenshot`: opens the built-in interactive screenshot UI.
|
||||||
|
- `screenshot-screen`, `screenshow-window`: takes a screenshot of the focused screen or window respectively.
|
||||||
|
|
||||||
|
The screenshot is both stored to the clipboard and saved to disk, according to the [`screenshot-path` option](./Configuration:-Miscellaneous.md#screenshot-path).
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup> You can disable saving to disk for a specific bind with the `write-to-disk=false` property:
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
Ctrl+Print { screenshot-screen write-to-disk=false; }
|
||||||
|
Alt+Print { screenshot-window write-to-disk=false; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
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: 25.05</sup> You can hide the mouse pointer in screenshots with the `show-pointer=false` property:
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
// The pointer will be hidden by default
|
||||||
|
// (you can still show it by pressing P).
|
||||||
|
Print { screenshot show-pointer=false; }
|
||||||
|
|
||||||
|
// The pointer will be hidden on the screenshot.
|
||||||
|
Ctrl+Print { screenshot-screen show-pointer=false; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `toggle-keyboard-shortcuts-inhibit`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Applications such as remote-desktop clients and software KVM switches may request that niri stops processing its keyboard shortcuts so that they may, for example, forward the key presses as-is to a remote machine.
|
||||||
|
`toggle-keyboard-shortcuts-inhibit` is an escape hatch that toggles the inhibitor.
|
||||||
|
It's a good idea to bind it, so a buggy application can't hold your session hostage.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
Mod+Escape { toggle-keyboard-shortcuts-inhibit; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also make certain binds ignore inhibiting with the `allow-inhibiting=false` property.
|
||||||
|
They will always be handled by niri and never passed to the window.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
// This bind will always work, even when using a virtual machine.
|
||||||
|
Super+Alt+L allow-inhibiting=false { spawn "swaylock"; }
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
### Overview
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
Layer rules let you adjust behavior for individual layer-shell surfaces.
|
||||||
|
They have `match` and `exclude` directives that control which layer-shell surfaces the rule should apply to, and a number of properties that you can set.
|
||||||
|
|
||||||
|
Layer rules are processed and work very similarly to window rules, just with different matchers and properties.
|
||||||
|
Please read the [window rules wiki page](./Configuration:-Window-Rules.md) to learn how matching works.
|
||||||
|
|
||||||
|
Here are all matchers and properties that a layer rule could have:
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
layer-rule {
|
||||||
|
match namespace="waybar"
|
||||||
|
match at-startup=true
|
||||||
|
|
||||||
|
// Properties that apply continuously.
|
||||||
|
opacity 0.5
|
||||||
|
block-out-from "screencast"
|
||||||
|
// block-out-from "screen-capture"
|
||||||
|
|
||||||
|
shadow {
|
||||||
|
on
|
||||||
|
// off
|
||||||
|
softness 40
|
||||||
|
spread 5
|
||||||
|
offset x=0 y=5
|
||||||
|
draw-behind-window true
|
||||||
|
color "#00000064"
|
||||||
|
// inactive-color "#00000064"
|
||||||
|
}
|
||||||
|
|
||||||
|
geometry-corner-radius 12
|
||||||
|
place-within-backdrop true
|
||||||
|
baba-is-float true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Layer Surface Matching
|
||||||
|
|
||||||
|
Let's look at the matchers in more detail.
|
||||||
|
|
||||||
|
#### `namespace`
|
||||||
|
|
||||||
|
This is a regular expression that should match anywhere in the surface namespace.
|
||||||
|
You can read about the supported regular expression syntax [here](https://docs.rs/regex/latest/regex/#syntax).
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Match surfaces with namespace containing "waybar",
|
||||||
|
layer-rule {
|
||||||
|
match namespace="waybar"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can find the namespaces of all open layer-shell surfaces by running `niri msg layers`.
|
||||||
|
|
||||||
|
#### `at-startup`
|
||||||
|
|
||||||
|
Can be `true` or `false`.
|
||||||
|
Matches during the first 60 seconds after starting niri.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Show layer-shell surfaces with 0.5 opacity at niri startup, but not afterwards.
|
||||||
|
layer-rule {
|
||||||
|
match at-startup=true
|
||||||
|
|
||||||
|
opacity 0.5
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dynamic Properties
|
||||||
|
|
||||||
|
These properties apply continuously to open layer-shell surfaces.
|
||||||
|
|
||||||
|
#### `block-out-from`
|
||||||
|
|
||||||
|
You can block out surfaces from xdg-desktop-portal screencasts or all screen captures.
|
||||||
|
They will be replaced with solid black rectangles.
|
||||||
|
|
||||||
|
This can be useful for notifications.
|
||||||
|
|
||||||
|
The same caveats and instructions apply as for the [`block-out-from` window rule](./Configuration:-Window-Rules.md#block-out-from), so check the documentation there.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Block out mako notifications from screencasts.
|
||||||
|
layer-rule {
|
||||||
|
match namespace="^notifications$"
|
||||||
|
|
||||||
|
block-out-from "screencast"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `opacity`
|
||||||
|
|
||||||
|
Set the opacity of the surface.
|
||||||
|
`0.0` is fully transparent, `1.0` is fully opaque.
|
||||||
|
This is applied on top of the surface's own opacity, so semitransparent surfaces will become even more transparent.
|
||||||
|
|
||||||
|
Opacity is applied to every child of the layer-shell surface individually, so subsurfaces and pop-up menus will show window content behind them.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Make fuzzel semitransparent.
|
||||||
|
layer-rule {
|
||||||
|
match namespace="^launcher$"
|
||||||
|
|
||||||
|
opacity 0.95
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `shadow`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Override the shadow options for the surface.
|
||||||
|
|
||||||
|
These rules have the same options as the normal [`shadow` config in the layout section](./Configuration:-Layout.md#shadow), so check the documentation there.
|
||||||
|
|
||||||
|
Unlike window shadows, layer surface shadows always need to be enabled with a layer rule.
|
||||||
|
That is, enabling shadows in the layout config section won't automatically enable them for layer surfaces.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Layer surfaces have no way to tell niri about their *visual geometry*.
|
||||||
|
> For example, if a layer surface includes some invisible margins (like mako), niri has no way of knowing that, and will draw the shadow behind the entire surface, including the invisible margins.
|
||||||
|
>
|
||||||
|
> So to use niri shadows, you'll need to configure layer-shell clients to remove their own margins or shadows.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Add a shadow for fuzzel.
|
||||||
|
layer-rule {
|
||||||
|
match namespace="^launcher$"
|
||||||
|
|
||||||
|
shadow {
|
||||||
|
on
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fuzzel defaults to 10 px rounded corners.
|
||||||
|
geometry-corner-radius 10
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `geometry-corner-radius`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Set the corner radius of the surface.
|
||||||
|
|
||||||
|
This setting will only affect the shadow—it will round its corners to match the geometry corner radius.
|
||||||
|
|
||||||
|
```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
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -9,6 +9,9 @@ layout {
|
|||||||
gaps 16
|
gaps 16
|
||||||
center-focused-column "never"
|
center-focused-column "never"
|
||||||
always-center-single-column
|
always-center-single-column
|
||||||
|
empty-workspace-above-first
|
||||||
|
default-column-display "tabbed"
|
||||||
|
background-color "#003300"
|
||||||
|
|
||||||
preset-column-widths {
|
preset-column-widths {
|
||||||
proportion 0.33333
|
proportion 0.33333
|
||||||
@@ -29,8 +32,10 @@ layout {
|
|||||||
width 4
|
width 4
|
||||||
active-color "#7fc8ff"
|
active-color "#7fc8ff"
|
||||||
inactive-color "#505050"
|
inactive-color "#505050"
|
||||||
|
urgent-color "#9b0000"
|
||||||
// active-gradient from="#80c8ff" to="#bbddff" angle=45
|
// active-gradient from="#80c8ff" to="#bbddff" angle=45
|
||||||
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
|
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
|
||||||
|
// urgent-gradient from="#800" to="#a33" angle=45
|
||||||
}
|
}
|
||||||
|
|
||||||
border {
|
border {
|
||||||
@@ -38,8 +43,38 @@ layout {
|
|||||||
width 4
|
width 4
|
||||||
active-color "#ffc87f"
|
active-color "#ffc87f"
|
||||||
inactive-color "#505050"
|
inactive-color "#505050"
|
||||||
|
urgent-color "#9b0000"
|
||||||
// active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view"
|
// 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"
|
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" in="srgb-linear"
|
||||||
|
// urgent-gradient from="#800" to="#a33" angle=45
|
||||||
|
}
|
||||||
|
|
||||||
|
shadow {
|
||||||
|
// on
|
||||||
|
softness 30
|
||||||
|
spread 5
|
||||||
|
offset x=0 y=5
|
||||||
|
draw-behind-window true
|
||||||
|
color "#00000070"
|
||||||
|
// inactive-color "#00000054"
|
||||||
|
}
|
||||||
|
|
||||||
|
tab-indicator {
|
||||||
|
// off
|
||||||
|
hide-when-single-tab
|
||||||
|
place-within-column
|
||||||
|
gap 5
|
||||||
|
width 4
|
||||||
|
length total-proportion=1.0
|
||||||
|
position "right"
|
||||||
|
gaps-between-tabs 2
|
||||||
|
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 {
|
insert-hint {
|
||||||
@@ -100,6 +135,38 @@ layout {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `empty-workspace-above-first`
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
If set, niri will always add an empty workspace at the very start, in addition to the empty workspace at the very end.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
layout {
|
||||||
|
empty-workspace-above-first
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `default-column-display`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Sets the default display mode for new columns.
|
||||||
|
Can be `normal` or `tabbed`.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Make all new columns tabbed by default.
|
||||||
|
layout {
|
||||||
|
default-column-display "tabbed"
|
||||||
|
|
||||||
|
// You may also want to hide the tab indicator
|
||||||
|
// when there's only a single window in a column.
|
||||||
|
tab-indicator {
|
||||||
|
hide-when-single-tab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### `preset-column-widths`
|
### `preset-column-widths`
|
||||||
|
|
||||||
Set the widths that the `switch-preset-column-width` action (Mod+R) toggles between.
|
Set the widths that the `switch-preset-column-width` action (Mod+R) toggles between.
|
||||||
@@ -108,7 +175,7 @@ Set the widths that the `switch-preset-column-width` action (Mod+R) toggles betw
|
|||||||
For example, you can perfectly fit four windows sized `proportion 0.25` on an output, regardless of the gaps setting.
|
For example, you can perfectly fit four windows sized `proportion 0.25` on an output, regardless of the gaps setting.
|
||||||
The default preset widths are <sup>1</sup>⁄<sub>3</sub>, <sup>1</sup>⁄<sub>2</sub> and <sup>2</sup>⁄<sub>3</sub> of the output.
|
The default preset widths are <sup>1</sup>⁄<sub>3</sub>, <sup>1</sup>⁄<sub>2</sub> and <sup>2</sup>⁄<sub>3</sub> of the output.
|
||||||
|
|
||||||
`fixed` sets the width in logical pixels exactly.
|
`fixed` sets the window width in logical pixels exactly.
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
layout {
|
layout {
|
||||||
@@ -122,13 +189,6 @@ layout {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> Currently, due to an oversight, a preset `fixed` width does not take borders into account.
|
|
||||||
> I.e., preset `fixed 1000` with 4-wide borders will make the window 992 logical pixels wide.
|
|
||||||
> This may eventually be corrected.
|
|
||||||
>
|
|
||||||
> All other ways of using `fixed` (i.e. `default-column-width` or `set-column-width`) do take borders into account and give you the exact window width that you request.
|
|
||||||
|
|
||||||
### `default-column-width`
|
### `default-column-width`
|
||||||
|
|
||||||
Set the default width of the new windows.
|
Set the default width of the new windows.
|
||||||
@@ -155,9 +215,7 @@ layout {
|
|||||||
> `default-column-width {}` causes niri to send a (0, H) size in the initial configure request.
|
> `default-column-width {}` causes niri to send a (0, H) size in the initial configure request.
|
||||||
>
|
>
|
||||||
> This is a bit [unclearly defined](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/155) in the Wayland protocol, so some clients may misinterpret it.
|
> This is a bit [unclearly defined](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/155) in the Wayland protocol, so some clients may misinterpret it.
|
||||||
> In practice, the only problematic client I saw is [foot](https://codeberg.org/dnkl/foot/), which takes this as a request to have a literal zero width.
|
> Either way, `default-column-width {}` is most useful for specific windows, in form of a [window rule](./Configuration:-Window-Rules.md#default-column-width) with the same syntax.
|
||||||
>
|
|
||||||
> Either way, `default-column-width {}` is most useful for specific windows, in form of a [window rule](https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules) with the same syntax.
|
|
||||||
|
|
||||||
### `preset-window-heights`
|
### `preset-window-heights`
|
||||||
|
|
||||||
@@ -191,17 +249,17 @@ The difference is that the focus ring is drawn only around the active window, wh
|
|||||||
|
|
||||||
| Focus Ring | Border |
|
| Focus Ring | Border |
|
||||||
| ------------------------- | --------------------- |
|
| ------------------------- | --------------------- |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> By default, focus ring and border are rendered as a solid background rectangle behind windows.
|
> By default, focus ring and border are rendered as a solid background rectangle behind windows.
|
||||||
> That is, they will show up through semitransparent windows.
|
> That is, they will show up through semitransparent windows.
|
||||||
> This is because windows using client-side decorations can have an arbitrary shape.
|
> This is because windows using client-side decorations can have an arbitrary shape.
|
||||||
>
|
>
|
||||||
> If you don't like that, you should uncomment the `prefer-no-csd` setting at the [top level](./Configuration:-Miscellaneous.md) of the config.
|
> If you don't like that, you should uncomment the [`prefer-no-csd` setting](./Configuration:-Miscellaneous.md#prefer-no-csd) at the top level of the config.
|
||||||
> Niri will draw focus rings and borders *around* windows that agree to omit their client-side decorations.
|
> Niri will draw focus rings and borders *around* windows that agree to omit their client-side decorations.
|
||||||
>
|
>
|
||||||
> Alternatively, you can override this behavior with the `draw-border-with-background` [window rule](https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules).
|
> Alternatively, you can override this behavior with the [`draw-border-with-background` window rule](./Configuration:-Window-Rules.md#draw-border-with-background).
|
||||||
|
|
||||||
Focus ring and border have the following options.
|
Focus ring and border have the following options.
|
||||||
|
|
||||||
@@ -218,6 +276,9 @@ layout {
|
|||||||
active-color "#ffc87f"
|
active-color "#ffc87f"
|
||||||
inactive-color "#505050"
|
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"
|
// 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"
|
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" in="srgb-linear"
|
||||||
}
|
}
|
||||||
@@ -261,7 +322,7 @@ Similarly to colors, you can set `active-gradient` and `inactive-gradient`, whic
|
|||||||
|
|
||||||
Gradients are rendered the same as CSS [`linear-gradient(angle, from, to)`](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient).
|
Gradients are rendered the same as CSS [`linear-gradient(angle, from, to)`](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient).
|
||||||
The angle works the same as in `linear-gradient`, and is optional, defaulting to `180` (top-to-bottom gradient).
|
The angle works the same as in `linear-gradient`, and is optional, defaulting to `180` (top-to-bottom gradient).
|
||||||
You can use any CSS linear-gradient tool on the web to set these up, like [this one](https://www.css-gradient.com/).
|
You can use any CSS linear-gradient tool on the web to set these up, like [css-gradient.com](https://www.css-gradient.com/).
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
layout {
|
layout {
|
||||||
@@ -277,7 +338,7 @@ Here's a visual example:
|
|||||||
|
|
||||||
| Default | `relative-to="workspace-view"` |
|
| Default | `relative-to="workspace-view"` |
|
||||||
| -------------------------------- | --------------------------------------------------- |
|
| -------------------------------- | --------------------------------------------------- |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
layout {
|
layout {
|
||||||
@@ -299,7 +360,7 @@ Supported color spaces are:
|
|||||||
They are rendered the same as CSS.
|
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)`.
|
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)`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
layout {
|
layout {
|
||||||
@@ -309,6 +370,108 @@ layout {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `shadow`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Shadow rendered behind a window.
|
||||||
|
|
||||||
|
Set `on` to enable the shadow.
|
||||||
|
|
||||||
|
`softness` controls the shadow softness/size in logical pixels, same as [CSS box-shadow] *blur radius*.
|
||||||
|
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: 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.
|
||||||
|
|
||||||
|
Set `draw-behind-window` to `true` to make shadows draw behind the window rather than just around it.
|
||||||
|
Note that niri has no way of knowing about the CSD window corner 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.
|
||||||
|
|
||||||
|
`color` is the shadow color and opacity.
|
||||||
|
|
||||||
|
`inactive-color` lets you override the shadow color for inactive windows; by default, a more transparent `color` is used.
|
||||||
|
|
||||||
|
Shadow drawing will follow the window corner radius set with the [`geometry-corner-radius` window rule](./Configuration:-Window-Rules.md#geometry-corner-radius).
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Currently, shadow drawing only supports matching radius for all corners. If you set `geometry-corner-radius` to four values instead of one, the first (top-left) corner radius will be used for shadows.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Enable shadows.
|
||||||
|
layout {
|
||||||
|
shadow {
|
||||||
|
on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also ask windows to omit client-side decorations, so that
|
||||||
|
// they don't draw their own window shadows.
|
||||||
|
prefer-no-csd
|
||||||
|
```
|
||||||
|
|
||||||
|
[CSS box-shadow]: https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow
|
||||||
|
|
||||||
|
### `tab-indicator`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Controls the appearance of the tab indicator that appears next to columns in tabbed display mode.
|
||||||
|
|
||||||
|
Set `off` to hide the tab indicator.
|
||||||
|
|
||||||
|
Set `hide-when-single-tab` to hide the indicator for tabbed columns that only have a single window.
|
||||||
|
|
||||||
|
Set `place-within-column` to put the tab indicator "within" the column, rather than outside.
|
||||||
|
This will include it in column sizing and avoid overlaying adjacent columns.
|
||||||
|
|
||||||
|
`gap` sets the gap between the tab indicator and the window in logical pixels.
|
||||||
|
The gap can be negative, this will put the tab indicator on top of the window.
|
||||||
|
|
||||||
|
`width` sets the thickness of the indicator in logical pixels.
|
||||||
|
|
||||||
|
`length` controls the length of the indicator.
|
||||||
|
Set the `total-proportion` property to make tabs take up this much length relative to the window size.
|
||||||
|
By default, the tab indicator has length equal to half of the window size, or `length total-proportion=0.5`.
|
||||||
|
|
||||||
|
`position` sets the position of the tab indicator relative to the window.
|
||||||
|
It can be `left`, `right`, `top`, or `bottom`.
|
||||||
|
|
||||||
|
`gaps-between-tabs` controls the gap between individual tabs in logical pixels.
|
||||||
|
|
||||||
|
`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`, `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:
|
||||||
|
1. Colors from the `tab-indicator` window rule, if set.
|
||||||
|
1. Colors from the `tab-indicator` layout options, if set (you're here).
|
||||||
|
1. If neither are set, niri picks the color matching the window border or focus ring, whichever one is active.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Make the tab indicator wider and match the window height,
|
||||||
|
// also put it at the top and within the column.
|
||||||
|
layout {
|
||||||
|
tab-indicator {
|
||||||
|
width 8
|
||||||
|
gap 8
|
||||||
|
length total-proportion=1.0
|
||||||
|
position "top"
|
||||||
|
place-within-column
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### `insert-hint`
|
### `insert-hint`
|
||||||
|
|
||||||
<sup>Since: 0.1.10</sup>
|
<sup>Since: 0.1.10</sup>
|
||||||
@@ -353,7 +516,7 @@ layout {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
<sup>Since: 0.1.8</sup> You can use negative values.
|
<sup>Since: 0.1.8</sup> You can use negative values.
|
||||||
They will push the windows outwards, even outside the edges of the screen.
|
They will push the windows outwards, even outside the edges of the screen.
|
||||||
@@ -373,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).
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
This page documents all top-level options that don't otherwise have dedicated pages.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
|
||||||
|
|
||||||
|
environment {
|
||||||
|
QT_QPA_PLATFORM "wayland"
|
||||||
|
DISPLAY null
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor {
|
||||||
|
xcursor-theme "breeze_cursors"
|
||||||
|
xcursor-size 48
|
||||||
|
|
||||||
|
hide-when-typing
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `spawn-at-startup`
|
||||||
|
|
||||||
|
Add lines like this to spawn processes at niri startup.
|
||||||
|
|
||||||
|
`spawn-at-startup` accepts a path to the program binary as the first argument, followed by arguments to the program.
|
||||||
|
|
||||||
|
This option works the same way as the [`spawn` key binding action](./Configuration:-Key-Bindings.md#spawn), so please read about all its subtleties there.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
spawn-at-startup "waybar"
|
||||||
|
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.
|
||||||
|
|
||||||
|
If an application will specifically ask for CSD, the request will be honored.
|
||||||
|
Additionally, clients will be informed that they are tiled, removing some rounded corners.
|
||||||
|
|
||||||
|
With `prefer-no-csd` set, applications that negotiate server-side decorations through the xdg-decoration protocol will have focus ring and border drawn around them *without* a solid colored background.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Unlike most other options, changing `prefer-no-csd` will not entirely affect already running applications.
|
||||||
|
> It will make some windows rectangular, but won't remove the title bars.
|
||||||
|
> This mainly has to do with niri working around a [bug in SDL2](https://github.com/libsdl-org/SDL/issues/8173) that prevents SDL2 applications from starting.
|
||||||
|
>
|
||||||
|
> Restart applications after changing `prefer-no-csd` in the config to fully apply it.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
prefer-no-csd
|
||||||
|
```
|
||||||
|
|
||||||
|
### `screenshot-path`
|
||||||
|
|
||||||
|
Set the path where screenshots are saved.
|
||||||
|
A `~` at the front will be expanded to the home directory.
|
||||||
|
|
||||||
|
The path is formatted with `strftime(3)` to give you the screenshot date and time.
|
||||||
|
|
||||||
|
Niri will create the last folder of the path if it doesn't exist.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also set this option to `null` to disable saving screenshots to disk.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
screenshot-path null
|
||||||
|
```
|
||||||
|
|
||||||
|
### `environment`
|
||||||
|
|
||||||
|
Override environment variables for processes spawned by niri.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
environment {
|
||||||
|
// Set a variable like this:
|
||||||
|
// QT_QPA_PLATFORM "wayland"
|
||||||
|
|
||||||
|
// Remove a variable by using null as the value:
|
||||||
|
// DISPLAY null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `cursor`
|
||||||
|
|
||||||
|
Change the theme and size of the cursor as well as set the `XCURSOR_THEME` and `XCURSOR_SIZE` environment variables.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
cursor {
|
||||||
|
xcursor-theme "breeze_cursors"
|
||||||
|
xcursor-size 48
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `hide-when-typing`
|
||||||
|
|
||||||
|
<sup>Since: 0.1.10</sup>
|
||||||
|
|
||||||
|
If set, hides the cursor when pressing a key on the keyboard.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> This setting might interfere with games running in Wine in native Wayland mode that use mouselook, such as first-person games.
|
||||||
|
> If your character's point of view jumps down when you press a key and move the mouse simultaneously, try disabling this setting.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
cursor {
|
||||||
|
hide-when-typing
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `hide-after-inactive-ms`
|
||||||
|
|
||||||
|
<sup>Since: 0.1.10</sup>
|
||||||
|
|
||||||
|
If set, the cursor will automatically hide once this number of milliseconds passes since the last cursor movement.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
cursor {
|
||||||
|
// Hide the cursor after one second of inactivity.
|
||||||
|
hide-after-inactive-ms 1000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `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>
|
||||||
|
|
||||||
|
Clipboard settings.
|
||||||
|
|
||||||
|
Set the `disable-primary` flag to disable the primary clipboard (middle-click paste).
|
||||||
|
Toggling this flag will only apply to applications started afterward.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
clipboard {
|
||||||
|
disable-primary
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `hotkey-overlay`
|
||||||
|
|
||||||
|
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
|
||||||
|
hotkey-overlay {
|
||||||
|
skip-at-startup
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `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
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -39,3 +39,9 @@ There's no way to give a name to an already existing workspace, but you can simp
|
|||||||
|
|
||||||
<sup>Since: 0.1.9</sup> `open-on-output` can now use monitor manufacturer, model, and serial.
|
<sup>Since: 0.1.9</sup> `open-on-output` can now use monitor manufacturer, model, and serial.
|
||||||
Before, it could only use the connector name.
|
Before, it could only use the connector name.
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup> You can use `set-workspace-name` and `unset-workspace-name` actions to change workspace names dynamically.
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup> Named workspaces no longer update/forget their original output when opening a new window on them (unnamed workspaces will keep doing that).
|
||||||
|
This means that named workspaces "stick" to their original output in more cases, reflecting their more permanent nature.
|
||||||
|
Explicitly moving a named workspace to a different monitor will still update its original output.
|
||||||
@@ -13,7 +13,9 @@ output "eDP-1" {
|
|||||||
transform "90"
|
transform "90"
|
||||||
position x=1280 y=0
|
position x=1280 y=0
|
||||||
variable-refresh-rate // on-demand=true
|
variable-refresh-rate // on-demand=true
|
||||||
|
focus-at-startup
|
||||||
background-color "#003300"
|
background-color "#003300"
|
||||||
|
backdrop-color "#001100"
|
||||||
}
|
}
|
||||||
|
|
||||||
output "HDMI-A-1" {
|
output "HDMI-A-1" {
|
||||||
@@ -143,7 +145,7 @@ You can check whether an output supports VRR in `niri msg outputs`.
|
|||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> Some drivers have various issues with VRR.
|
> Some drivers have various issues with VRR.
|
||||||
>
|
>
|
||||||
> If the cursor moves at a low framerate with VRR, try setting the `disable-cursor-plane` [debug flag](./Configuration:-Debug-Options.md) and reconnecting the monitor.
|
> If the cursor moves at a low framerate with VRR, try setting the [`disable-cursor-plane` debug flag](./Configuration:-Debug-Options.md#disable-cursor-plane) and reconnecting the monitor.
|
||||||
>
|
>
|
||||||
> If a monitor is not detected as VRR-capable when it should, sometimes unplugging a different monitor fixes it.
|
> If a monitor is not detected as VRR-capable when it should, sometimes unplugging a different monitor fixes it.
|
||||||
>
|
>
|
||||||
@@ -164,17 +166,54 @@ output "HDMI-A-1" {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `focus-at-startup`
|
||||||
|
|
||||||
|
<sup>Since: 25.05</sup>
|
||||||
|
|
||||||
|
Focus this output by default when niri starts.
|
||||||
|
|
||||||
|
If multiple outputs with `focus-at-startup` are connected, they are prioritized in the order that they appear in the config.
|
||||||
|
|
||||||
|
When none of the connected outputs are explicitly `focus-at-startup`, niri will focus the first one sorted by name (same output sorting as used elsewhere in niri).
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Focus HDMI-A-1 by default.
|
||||||
|
output "HDMI-A-1" {
|
||||||
|
focus-at-startup
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...if HDMI-A-1 wasn't connected, focus DP-2 instead.
|
||||||
|
output "DP-2" {
|
||||||
|
focus-at-startup
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### `background-color`
|
### `background-color`
|
||||||
|
|
||||||
<sup>Since: 0.1.8</sup>
|
<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.
|
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
|
```kdl
|
||||||
output "HDMI-A-1" {
|
output "HDMI-A-1" {
|
||||||
background-color "#003300"
|
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"
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
This wiki page has moved to: [Introduction](./Configuration:-Introduction.md).
|
||||||
@@ -16,7 +16,7 @@ switch-events {
|
|||||||
```
|
```
|
||||||
|
|
||||||
The syntax is similar to key bindings.
|
The syntax is similar to key bindings.
|
||||||
Currently, only the `spawn` action are supported.
|
Currently, only the [`spawn` action](./Configuration:-Key-Bindings.md#spawn) are supported.
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> In contrast to key bindings, switch event bindings are *always* executed, even when the session is locked.
|
> In contrast to key bindings, switch event bindings are *always* executed, even when the session is locked.
|
||||||
@@ -33,14 +33,20 @@ window-rule {
|
|||||||
match is-active=true
|
match is-active=true
|
||||||
match is-focused=false
|
match is-focused=false
|
||||||
match is-active-in-column=true
|
match is-active-in-column=true
|
||||||
|
match is-floating=true
|
||||||
|
match is-window-cast-target=true
|
||||||
|
match is-urgent=true
|
||||||
match at-startup=true
|
match at-startup=true
|
||||||
|
|
||||||
// Properties that apply once upon window opening.
|
// Properties that apply once upon window opening.
|
||||||
default-column-width { proportion 0.75; }
|
default-column-width { proportion 0.75; }
|
||||||
|
default-window-height { fixed 500; }
|
||||||
open-on-output "Some Company CoolMonitor 1234"
|
open-on-output "Some Company CoolMonitor 1234"
|
||||||
open-on-workspace "chat"
|
open-on-workspace "chat"
|
||||||
open-maximized true
|
open-maximized true
|
||||||
open-fullscreen true
|
open-fullscreen true
|
||||||
|
open-floating true
|
||||||
|
open-focused false
|
||||||
|
|
||||||
// Properties that apply continuously.
|
// Properties that apply continuously.
|
||||||
draw-border-with-background false
|
draw-border-with-background false
|
||||||
@@ -48,6 +54,9 @@ window-rule {
|
|||||||
block-out-from "screencast"
|
block-out-from "screencast"
|
||||||
// block-out-from "screen-capture"
|
// block-out-from "screen-capture"
|
||||||
variable-refresh-rate true
|
variable-refresh-rate true
|
||||||
|
default-column-display "tabbed"
|
||||||
|
default-floating-position x=100 y=200 relative-to="bottom-left"
|
||||||
|
scroll-factor 0.75
|
||||||
|
|
||||||
focus-ring {
|
focus-ring {
|
||||||
// off
|
// off
|
||||||
@@ -55,16 +64,40 @@ window-rule {
|
|||||||
width 4
|
width 4
|
||||||
active-color "#7fc8ff"
|
active-color "#7fc8ff"
|
||||||
inactive-color "#505050"
|
inactive-color "#505050"
|
||||||
|
urgent-color "#9b0000"
|
||||||
// active-gradient from="#80c8ff" to="#bbddff" angle=45
|
// active-gradient from="#80c8ff" to="#bbddff" angle=45
|
||||||
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
|
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
|
||||||
|
// urgent-gradient from="#800" to="#a33" angle=45
|
||||||
}
|
}
|
||||||
|
|
||||||
border {
|
border {
|
||||||
// Same as focus-ring.
|
// Same as focus-ring.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shadow {
|
||||||
|
// on
|
||||||
|
off
|
||||||
|
softness 40
|
||||||
|
spread 5
|
||||||
|
offset x=0 y=5
|
||||||
|
draw-behind-window true
|
||||||
|
color "#00000064"
|
||||||
|
// inactive-color "#00000064"
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
geometry-corner-radius 12
|
||||||
clip-to-geometry true
|
clip-to-geometry true
|
||||||
|
tiled-state true
|
||||||
|
baba-is-float true
|
||||||
|
|
||||||
min-width 100
|
min-width 100
|
||||||
max-width 200
|
max-width 200
|
||||||
@@ -97,12 +130,12 @@ There can be multiple *matchers* in one directive, then the window should match
|
|||||||
```kdl
|
```kdl
|
||||||
window-rule {
|
window-rule {
|
||||||
// Match Firefox windows with Gmail in title.
|
// Match Firefox windows with Gmail in title.
|
||||||
match app-id="org.mozilla.firefox" title="Gmail"
|
match app-id="firefox" title="Gmail"
|
||||||
}
|
}
|
||||||
|
|
||||||
window-rule {
|
window-rule {
|
||||||
// Match Firefox, but only when it is active...
|
// Match Firefox, but only when it is active...
|
||||||
match app-id=r#"^org\.mozilla\.firefox$"# is-active=true
|
match app-id="firefox" is-active=true
|
||||||
|
|
||||||
// ...or match Telegram...
|
// ...or match Telegram...
|
||||||
match app-id=r#"^org\.telegram\.desktop$"#
|
match app-id=r#"^org\.telegram\.desktop$"#
|
||||||
@@ -189,12 +222,84 @@ Matches the window that is the "active" window in its column.
|
|||||||
Contrary to `is-active`, there is always one `is-active-in-column` window in each column.
|
Contrary to `is-active`, there is always one `is-active-in-column` window in each column.
|
||||||
It is the window that was last focused in the column, i.e. the one that will gain focus if this column is focused.
|
It is the window that was last focused in the column, i.e. the one that will gain focus if this column is focused.
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup> This rule will match `true` during the initial window opening.
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
window-rule {
|
window-rule {
|
||||||
match is-active-in-column=true
|
match is-active-in-column=true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `is-floating`
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
Can be `true` or `false`.
|
||||||
|
Matches floating windows.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> This matcher will apply only after the window is already open.
|
||||||
|
> This means that you cannot use it to change the window opening properties like `default-window-height` or `open-on-workspace`.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
window-rule {
|
||||||
|
match is-floating=true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `is-window-cast-target`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Can be `true` or `false`.
|
||||||
|
Matches `true` for windows that are target of an ongoing window screencast.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> This only matches individual-window screencasts.
|
||||||
|
> It will not match windows that happen to be visible in a monitor screencast, for example.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Indicate screencasted windows with red colors.
|
||||||
|
window-rule {
|
||||||
|
match is-window-cast-target=true
|
||||||
|
|
||||||
|
focus-ring {
|
||||||
|
active-color "#f38ba8"
|
||||||
|
inactive-color "#7d0d2d"
|
||||||
|
}
|
||||||
|
|
||||||
|
border {
|
||||||
|
inactive-color "#7d0d2d"
|
||||||
|
}
|
||||||
|
|
||||||
|
shadow {
|
||||||
|
color "#7d0d2d70"
|
||||||
|
}
|
||||||
|
|
||||||
|
tab-indicator {
|
||||||
|
active-color "#f38ba8"
|
||||||
|
inactive-color "#7d0d2d"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### `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`
|
#### `at-startup`
|
||||||
|
|
||||||
<sup>Since: 0.1.6</sup>
|
<sup>Since: 0.1.6</sup>
|
||||||
@@ -222,6 +327,8 @@ To be precise, they apply at the point when niri sends the initial configure req
|
|||||||
|
|
||||||
Set the default width for the new window.
|
Set the default width for the new window.
|
||||||
|
|
||||||
|
This works for floating windows too, despite the word "column" in the name.
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
// Give Blender and GIMP some guaranteed width on opening.
|
// Give Blender and GIMP some guaranteed width on opening.
|
||||||
window-rule {
|
window-rule {
|
||||||
@@ -235,6 +342,23 @@ window-rule {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `default-window-height`
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
Set the default height for the new window.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Open the Firefox picture-in-picture window as floating with 480×270 size.
|
||||||
|
window-rule {
|
||||||
|
match app-id="firefox$" title="^Picture-in-Picture$"
|
||||||
|
|
||||||
|
open-floating true
|
||||||
|
default-column-width { fixed 480; }
|
||||||
|
default-window-height { fixed 270; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### `open-on-output`
|
#### `open-on-output`
|
||||||
|
|
||||||
Make the window open on a specific output.
|
Make the window open on a specific output.
|
||||||
@@ -247,7 +371,7 @@ If the window opens on an output that is not currently focused, the window will
|
|||||||
// Open Firefox and Telegram (but not its Media Viewer)
|
// Open Firefox and Telegram (but not its Media Viewer)
|
||||||
// on a specific monitor.
|
// on a specific monitor.
|
||||||
window-rule {
|
window-rule {
|
||||||
match app-id=r#"^org\.mozilla\.firefox$"#
|
match app-id="firefox$"
|
||||||
match app-id=r#"^org\.telegram\.desktop$"#
|
match app-id=r#"^org\.telegram\.desktop$"#
|
||||||
exclude app-id=r#"^org\.telegram\.desktop$"# title="^Media viewer$"
|
exclude app-id=r#"^org\.telegram\.desktop$"# title="^Media viewer$"
|
||||||
|
|
||||||
@@ -286,7 +410,7 @@ Make the window open as a maximized column.
|
|||||||
```kdl
|
```kdl
|
||||||
// Maximize Firefox by default.
|
// Maximize Firefox by default.
|
||||||
window-rule {
|
window-rule {
|
||||||
match app-id=r#"^org\.mozilla\.firefox$"#
|
match app-id="firefox$"
|
||||||
|
|
||||||
open-maximized true
|
open-maximized true
|
||||||
}
|
}
|
||||||
@@ -313,6 +437,59 @@ window-rule {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `open-floating`
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
Make the window open in the floating layout.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Open the Firefox picture-in-picture window as floating.
|
||||||
|
window-rule {
|
||||||
|
match app-id="firefox$" title="^Picture-in-Picture$"
|
||||||
|
|
||||||
|
open-floating true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also set this to `false` to *prevent* a window from opening in the floating layout.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Open all windows in the tiling layout, overriding any auto-floating logic.
|
||||||
|
window-rule {
|
||||||
|
open-floating false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `open-focused`
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
Set this to `false` to prevent this window from being automatically focused upon opening.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Don't give focus to the GIMP startup splash screen.
|
||||||
|
window-rule {
|
||||||
|
match app-id="^gimp" title="^GIMP Startup$"
|
||||||
|
|
||||||
|
open-focused false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also set this to `true` to focus the window, even if normally it wouldn't get auto-focused.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Always focus the KeePassXC-Browser unlock dialog.
|
||||||
|
//
|
||||||
|
// This dialog opens parented to the KeePassXC window rather than the browser,
|
||||||
|
// so it doesn't get auto-focused by default.
|
||||||
|
window-rule {
|
||||||
|
match app-id=r#"^org\.keepassxc\.KeePassXC$"# title="^Unlock Database - KeePassXC$"
|
||||||
|
|
||||||
|
open-focused true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Dynamic Properties
|
### Dynamic Properties
|
||||||
|
|
||||||
These properties apply continuously to open windows.
|
These properties apply continuously to open windows.
|
||||||
@@ -323,6 +500,7 @@ You can block out windows from xdg-desktop-portal screencasts.
|
|||||||
They will be replaced with solid black rectangles.
|
They will be replaced with solid black rectangles.
|
||||||
|
|
||||||
This can be useful for password managers or messenger windows, etc.
|
This can be useful for password managers or messenger windows, etc.
|
||||||
|
For layer-shell notification pop-ups and the like, you can use a [`block-out-from` layer rule](./Configuration:-Layer-Rules.md#block-out-from).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -365,7 +543,7 @@ window-rule {
|
|||||||
> ```kdl
|
> ```kdl
|
||||||
> window-rule {
|
> window-rule {
|
||||||
> // Doesn't quite work! Try to block out the Gmail tab.
|
> // Doesn't quite work! Try to block out the Gmail tab.
|
||||||
> match app-id=r#"^org\.mozilla\.firefox$"# title="- Gmail "
|
> match app-id="firefox$" title="- Gmail "
|
||||||
>
|
>
|
||||||
> block-out-from "screencast"
|
> block-out-from "screencast"
|
||||||
> }
|
> }
|
||||||
@@ -388,6 +566,8 @@ Opacity is applied to every surface of the window individually, so subsurfaces a
|
|||||||
|
|
||||||
Also, focus ring and border with background will show through semitransparent windows (see `prefer-no-csd` and the `draw-border-with-background` window rule below).
|
Also, focus ring and border with background will show through semitransparent windows (see `prefer-no-csd` and the `draw-border-with-background` window rule below).
|
||||||
|
|
||||||
|
Opacity can be toggled on or off for a window using the [`toggle-window-rule-opacity`](./Configuration:-Key-Bindings.md#toggle-window-rule-opacity) action.
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
// Make inactive windows semitransparent.
|
// Make inactive windows semitransparent.
|
||||||
window-rule {
|
window-rule {
|
||||||
@@ -417,6 +597,96 @@ window-rule {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `default-column-display`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Set the default display mode for columns created from this window.
|
||||||
|
|
||||||
|
This is used any time a window goes into its own column.
|
||||||
|
For example:
|
||||||
|
- Opening a new window.
|
||||||
|
- Expelling a window into its own column.
|
||||||
|
- Moving a window from the floating layout to the tiling layout.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Make Evince windows open as tabbed columns.
|
||||||
|
window-rule {
|
||||||
|
match app-id="^evince$"
|
||||||
|
|
||||||
|
default-column-display "tabbed"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `default-floating-position`
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
Set the initial position for this window when it opens on, or moves to the floating layout.
|
||||||
|
|
||||||
|
Afterward, the window will remember its last floating position.
|
||||||
|
|
||||||
|
By default, new floating windows open at the center of the screen, and windows from the tiling layout open close to their visual screen position.
|
||||||
|
|
||||||
|
The position uses logical coordinates relative to the working area.
|
||||||
|
By default, they are relative to the top-left corner of the working area, but you can change this by setting `relative-to` to one of these values: `top-left`, `top-right`, `bottom-left`, `bottom-right`, `top`, `bottom`, `left`, or `right`.
|
||||||
|
|
||||||
|
For example, if you have a bar at the top, then `x=0 y=0` will put the top-left corner of the window directly below the bar.
|
||||||
|
If instead you write `x=0 y=0 relative-to="top-right"`, then the top-right corner of the window will align with the top-right corner of the workspace, also directly below the bar.
|
||||||
|
When only one side is specified (e.g. top) the window will align to the center of that side.
|
||||||
|
|
||||||
|
The coordinates change direction based on `relative-to`.
|
||||||
|
For example, by default (top-left), `x=100 y=200` will put the window 100 pixels to the right and 200 pixels down from the top-left corner.
|
||||||
|
If you use `x=100 y=200 relative-to="bottom-left"`, it will put the window 100 pixels to the right and 200 pixels *up* from the bottom-left corner.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Open the Firefox picture-in-picture window at the bottom-left corner of the screen
|
||||||
|
// with a small gap.
|
||||||
|
window-rule {
|
||||||
|
match app-id="firefox$" title="^Picture-in-Picture$"
|
||||||
|
|
||||||
|
default-floating-position x=32 y=32 relative-to="bottom-left"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use single-side `relative-to` to get a dropdown-like effect.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Example: a "dropdown" terminal.
|
||||||
|
window-rule {
|
||||||
|
// Match by "dropdown" app ID.
|
||||||
|
// You need to set this app ID when running your terminal, e.g.:
|
||||||
|
// spawn "alacritty" "--class" "dropdown"
|
||||||
|
match app-id="^dropdown$"
|
||||||
|
|
||||||
|
// Open it as floating.
|
||||||
|
open-floating true
|
||||||
|
// Anchor to the top edge of the screen.
|
||||||
|
default-floating-position x=0 y=0 relative-to="top"
|
||||||
|
// Half of the screen high.
|
||||||
|
default-window-height { proportion 0.5; }
|
||||||
|
// 80% of the screen wide.
|
||||||
|
default-column-width { proportion 0.8; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `scroll-factor`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Set a scroll factor for all scroll events sent to a window.
|
||||||
|
|
||||||
|
This will be multiplied with the scroll factor set for your input device in the [input section](./Configuration:-Input.md#pointing-devices).
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Make scrolling in Firefox a bit slower.
|
||||||
|
window-rule {
|
||||||
|
match app-id="firefox$"
|
||||||
|
|
||||||
|
scroll-factor 0.75
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### `draw-border-with-background`
|
#### `draw-border-with-background`
|
||||||
|
|
||||||
Override whether the border and the focus ring draw with a background.
|
Override whether the border and the focus ring draw with a background.
|
||||||
@@ -428,7 +698,7 @@ This property can be useful for rectangular windows that do not support the xdg-
|
|||||||
|
|
||||||
| With Background | Without Background |
|
| With Background | Without Background |
|
||||||
| ------------------------------------------------ | --------------------------------------------------- |
|
| ------------------------------------------------ | --------------------------------------------------- |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
window-rule {
|
window-rule {
|
||||||
@@ -442,7 +712,7 @@ window-rule {
|
|||||||
|
|
||||||
Override the focus ring and border options for the window.
|
Override the focus ring and border options for the window.
|
||||||
|
|
||||||
These rules have the same options as the normal focus ring and border config in the [layout](./Configuration:-Layout.md) section, so check the documentation there.
|
These rules have the same options as the normal [`focus-ring` and `border` config in the layout section](./Configuration:-Layout.md#focus-ring-and-border), so check the documentation there.
|
||||||
|
|
||||||
However, in addition to `off` to disable the border/focus ring, this window rule has an `on` flag that enables the border/focus ring for the window even if it was otherwise disabled.
|
However, in addition to `off` to disable the border/focus ring, this window rule has an `on` flag that enables the border/focus ring for the window even if it was otherwise disabled.
|
||||||
The `on` flag has precedence over the `off` flag, in case both are set.
|
The `on` flag has precedence over the `off` flag, in case both are set.
|
||||||
@@ -463,6 +733,47 @@ window-rule {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `shadow`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Override the shadow options for the window.
|
||||||
|
|
||||||
|
This rule has the same options as the normal [`shadow` config in the layout section](./Configuration:-Layout.md#shadow), so check the documentation there.
|
||||||
|
|
||||||
|
However, in addition to `on` to enable the shadow, this window rule has an `off` flag that disables the shadow for the window even if it was otherwise enabled.
|
||||||
|
The `on` flag has precedence over the `off` flag, in case both are set.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Turn on shadows for floating windows.
|
||||||
|
window-rule {
|
||||||
|
match is-floating=true
|
||||||
|
|
||||||
|
shadow {
|
||||||
|
on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `tab-indicator`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Override the tab indicator options for the window.
|
||||||
|
|
||||||
|
Options in this rule match the same options as the normal [`tab-indicator` config in the layout section](./Configuration:-Layout.md#tab-indicator), so check the documentation there.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Make KeePassXC tab have a dark red inactive color.
|
||||||
|
window-rule {
|
||||||
|
match app-id=r#"^org\.keepassxc\.KeePassXC$"#
|
||||||
|
|
||||||
|
tab-indicator {
|
||||||
|
inactive-color "darkred"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### `geometry-corner-radius`
|
#### `geometry-corner-radius`
|
||||||
|
|
||||||
<sup>Since: 0.1.6</sup>
|
<sup>Since: 0.1.6</sup>
|
||||||
@@ -470,7 +781,7 @@ window-rule {
|
|||||||
Set the corner radius of the window.
|
Set the corner radius of the window.
|
||||||
|
|
||||||
On its own, this setting will only affect the border and the focus ring—they will round their corners to match the geometry corner radius.
|
On its own, this setting will only affect the border and the focus ring—they will round their corners to match the geometry corner radius.
|
||||||
If you'd like to force-round the corners of the window itself, set `clip-to-geometry true` in addition to this setting.
|
If you'd like to force-round the corners of the window itself, set [`clip-to-geometry true`](#clip-to-geometry) in addition to this setting.
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
window-rule {
|
window-rule {
|
||||||
@@ -480,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:
|
The radius is set in logical pixels, and controls the radius of the window itself, that is, the inner radius of the border:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Instead of one radius, you can set four, for each corner.
|
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.
|
The order is the same as in CSS: top-left, top-right, bottom-right, bottom-left.
|
||||||
@@ -493,7 +804,7 @@ window-rule {
|
|||||||
|
|
||||||
This way, you can match GTK 3 applications which have square bottom corners:
|
This way, you can match GTK 3 applications which have square bottom corners:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### `clip-to-geometry`
|
#### `clip-to-geometry`
|
||||||
|
|
||||||
@@ -503,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`.
|
This will cut out any client-side window shadows, and also round window corners according to `geometry-corner-radius`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
window-rule {
|
window-rule {
|
||||||
@@ -511,9 +822,9 @@ window-rule {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Enable border, set `geometry-corner-radius` and `clip-to-geometry`, and you've got a classic setup:
|
Enable border, set [`geometry-corner-radius`](#geometry-corner-radius) and `clip-to-geometry`, and you've got a classic setup:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
prefer-no-csd
|
prefer-no-csd
|
||||||
@@ -534,6 +845,48 @@ window-rule {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `tiled-state`
|
||||||
|
|
||||||
|
<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.
|
||||||
|
Windows that snap their size to a grid (e.g. terminals like [foot](https://codeberg.org/dnkl/foot)) will usually disable this snapping when they are tiled.
|
||||||
|
|
||||||
|
By default, niri will set the tiled state to `true` together with [`prefer-no-csd`](./Configuration:-Miscellaneous.md#prefer-no-csd) in order to improve behavior for apps that don't support server-side decorations.
|
||||||
|
You can use this window rule to override this, for example to get rectangular windows with CSD.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Make tiled windows rectangular while using CSD.
|
||||||
|
window-rule {
|
||||||
|
match is-floating=false
|
||||||
|
|
||||||
|
tiled-state true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `baba-is-float`
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
Make your windows FLOAT up and down.
|
||||||
|
|
||||||
|
This is an April Fools' 2025 feature.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
window-rule {
|
||||||
|
match is-floating=true
|
||||||
|
|
||||||
|
baba-is-float true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<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
|
#### Size Overrides
|
||||||
|
|
||||||
You can amend the window's minimum and maximum size in logical pixels.
|
You can amend the window's minimum and maximum size in logical pixels.
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
> *Time, Dr. Freeman? Is it really that... time again?*
|
||||||
|
|
||||||
|
A compositor deals with one or more monitors on mostly fixed refresh cycles.
|
||||||
|
For example, a 170 Hz monitor can draw a frame every ~5.88 ms.
|
||||||
|
|
||||||
|
Most of the time, the compositor doesn't actually redraw the monitor: when nothing changes on screen (e.g. you're reading a document and aren't moving your cursor), it would be wasteful to wake up the GPU to composite the same image.
|
||||||
|
During an animation however, screen contents do change every frame.
|
||||||
|
Niri will generally start drawing the next frame as soon as the previous one shows up on screen.
|
||||||
|
|
||||||
|
Since the monitor refresh cycle is fixed in most cases (even with VRR, there's a maximum refresh rate), the compositor can predict when the next frame will show up on the monitor, and render ongoing animations for that exact moment in time.
|
||||||
|
This way, all animation frames are perfectly timed with no jitter, regardless of when exactly the rendering code had a chance to run.
|
||||||
|
For example, even if the compositor has to process new window events, delaying the rendering by a few ms, the animation timing will remain exactly aligned to the monitor refresh cycle.
|
||||||
|
|
||||||
|
There are hence several properties that a compositor wants from its timing system.
|
||||||
|
|
||||||
|
1. It should be possible to get the state of the animations at a specific time in the near future, for rendering a frame exactly timed to when the monitor will show it.
|
||||||
|
- This time override ability should be usable in tests to advance the time in a fully controlled fashion.
|
||||||
|
1. Animations in response to user actions should begin at the moment when the action happens.
|
||||||
|
For example, pressing a workspace switch key should start the animation at the instant when the user pressed the key (rather than, say, slightly in the future where we predicted the next monitor frame, which we had already rendered by now).
|
||||||
|
1. During the processing of a single action, querying the current time should return the exact same value.
|
||||||
|
Even if the processing finishes a few microseconds after it started, querying the time in the end should return the same thing.
|
||||||
|
This generally makes writing code much more sane; otherwise you'd need to for example avoid reading the position of some element twice in a row, since it could have moved by one pixel in-between, screwing with the logic.
|
||||||
|
Also, fetching the current system time [can be quite expensive](https://mastodon.online/@YaLTeR/109934977035721850) in terms of overhead.
|
||||||
|
1. It should be reasonably easy to implement an animation slow-down preference, so all animations can be slowed down or sped up by the same factor.
|
||||||
|
|
||||||
|
The solution in niri is a `LazyClock`, a clock that remembers one timestamp.
|
||||||
|
Initially, the timestamp is empty, so when you ask `LazyClock` for the current time, it will fetch and return the system time, and also remember it.
|
||||||
|
Subsequently, it will keep returning the same timestamp that it had remembered.
|
||||||
|
|
||||||
|
You can also clear the timestamp, then `LazyClock` will fetch the system time anew when it's needed.
|
||||||
|
In niri, the timestamp is cleared at the end of every event loop iteration, right before going to sleep waiting for new events.
|
||||||
|
This way, anything that happens next (like a user key press) will fetch and use the most up-to-date timestamp as soon as one is needed, but then the processing code will keep getting the exact same timestamp, since `LazyClock` stores it.
|
||||||
|
|
||||||
|
You can also just manually set the timestamp to a specific value.
|
||||||
|
This is how we render a frame for the predicted time of when the monitor will show it.
|
||||||
|
Also, this is used by tests: they simply always set the timestamp and never use the system time.
|
||||||
|
|
||||||
|
Finally, there's an `AdjustableClock` wrapper on top that provides the ability to control the slow-down rate by modifying the timestamps returned by the clock.
|
||||||
|
|
||||||
|
An important detail is that with rate changes, timestamps from the `AdjustableClock` will drift away and become unrelated to the system time.
|
||||||
|
However, our target timestamp (for rendering) comes from the system time, so the override works directly on the underlying `LazyClock`.
|
||||||
|
That is, overriding the timestamp and then querying the `AdjustableClock` will return a *different* timestamp that is correct and consistent with the adjustments made by `AdjustableClock`.
|
||||||
|
This is reflected in the API by naming the function `Clock::set_unadjusted()` (and there's also `Clock::now_unadjusted()` to get the raw timestamp).
|
||||||
|
|
||||||
|
The clock is shared among all animations in niri through passing around and storing a reference-counted pointer.
|
||||||
|
This way, overriding the time automatically applies to everything, whereas in tests we can use a separate clock per test so that they don't interfere with each other.
|
||||||
@@ -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.
|
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`.
|
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.
|
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:
|
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,
|
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.
|
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.
|
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.
|
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 the `spawn-at-startup` config option, 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`
|
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`
|
2. `mako` and `waybar` provide systemd units out of the box, so you can simply add them to the niri session:
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
ln -s /usr/lib/systemd/user/mako.service ~/.config/systemd/user/niri.service.wants/
|
systemctl --user add-wants niri.service mako.service
|
||||||
ln -s /usr/lib/systemd/user/waybar.service ~/.config/systemd/user/niri.service.wants/
|
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.
|
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]
|
[Unit]
|
||||||
PartOf=graphical-session.target
|
PartOf=graphical-session.target
|
||||||
After=graphical-session.target
|
After=graphical-session.target
|
||||||
@@ -37,15 +34,16 @@ In contrast to the `spawn-at-startup` config option, this lets you easily monito
|
|||||||
|
|
||||||
After editing `swaybg.service`, run `systemctl --user daemon-reload` so systemd picks up the changes in the file.
|
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]
|
[Unit]
|
||||||
PartOf=graphical-session.target
|
PartOf=graphical-session.target
|
||||||
After=graphical-session.target
|
After=graphical-session.target
|
||||||
@@ -56,20 +54,23 @@ In contrast to the `spawn-at-startup` config option, this lets you easily monito
|
|||||||
Restart=on-failure
|
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!
|
That's it!
|
||||||
Now these three utilities will be started together with the niri session and stopped when it exits.
|
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.
|
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
|
### 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:
|
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
|
systemd-run --user --scope tmux new-session
|
||||||
```
|
```
|
||||||
@@ -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).
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
### Overview
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup>
|
||||||
|
|
||||||
|
Floating windows in niri always show on top of the tiled windows.
|
||||||
|
The floating layout does not scroll.
|
||||||
|
Each workspace/monitor has its own floating layout, just like each workspace/monitor has its own tiling layout.
|
||||||
|
|
||||||
|
New windows will automatically float if they have a parent (e.g. dialogs) or if they are fixed size (e.g. splash screens).
|
||||||
|
To change a window between floating and tiling, you can use the `toggle-window-floating` bind or right click while dragging/moving the window.
|
||||||
|
You can also use the `open-floating true/false` window rule to either force a window to open as floating, or to disable the automatic floating logic.
|
||||||
|
|
||||||
|
Use `switch-focus-between-floating-and-tiling` to switch the focus between the two layouts.
|
||||||
|
When focused on the floating layout, binds (like `focus-column-right`) will operate on the floating window.
|
||||||
|
|
||||||
|
You can precisely position a floating window with a command like `niri msg action move-floating-window -x 100 -y 200`.
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
### Overview
|
||||||
|
|
||||||
|
There are several gestures in niri.
|
||||||
|
|
||||||
|
Also see the [gestures configuration](./Configuration:-Gestures.md) wiki page.
|
||||||
|
|
||||||
|
### Mouse
|
||||||
|
|
||||||
|
#### Interactive Move
|
||||||
|
|
||||||
|
<sup>Since: 0.1.10</sup>
|
||||||
|
|
||||||
|
You can move windows by holding <kbd>Mod</kbd> and the left mouse button.
|
||||||
|
|
||||||
|
You can customize the look of the window insertion preview in the [`insert-hint` layout config](./Configuration:-Layout.md#insert-hint).
|
||||||
|
|
||||||
|
<sup>Since: 25.01</sup> Right click while moving to toggle between floating and tiling layout to put the window into.
|
||||||
|
|
||||||
|
#### Interactive Resize
|
||||||
|
|
||||||
|
<sup>Since: 0.1.6</sup>
|
||||||
|
|
||||||
|
You can resize windows by holding <kbd>Mod</kbd> and the right mouse button.
|
||||||
|
|
||||||
|
#### Reset Window Height
|
||||||
|
|
||||||
|
<sup>Since: 0.1.6</sup>
|
||||||
|
|
||||||
|
If you double-click on a top or bottom tiled window resize edge, the window height will reset to automatic.
|
||||||
|
|
||||||
|
This works with both window-initiated resizes (when using client-side decorations), and niri-initiated <kbd>Mod</kbd> + right click resizes.
|
||||||
|
|
||||||
|
#### Toggle Full Width
|
||||||
|
|
||||||
|
<sup>Since: 0.1.6</sup>
|
||||||
|
|
||||||
|
If you double-click on a left or right tiled window resize edge, the column will expand to the full workspace width.
|
||||||
|
|
||||||
|
This works with both window-initiated resizes (when using client-side decorations), and niri-initiated <kbd>Mod</kbd> + right click resizes.
|
||||||
|
|
||||||
|
#### Horizontal View Movement
|
||||||
|
|
||||||
|
<sup>Since: 0.1.6</sup>
|
||||||
|
|
||||||
|
Move the view horizontally by holding <kbd>Mod</kbd> and the middle mouse button (or the wheel) and dragging the mouse horizontally.
|
||||||
|
|
||||||
|
#### Workspace Switch
|
||||||
|
|
||||||
|
<sup>Since: 0.1.7</sup>
|
||||||
|
|
||||||
|
Switch workspaces by holding <kbd>Mod</kbd> and the middle mouse button (or the wheel) and dragging the mouse vertically.
|
||||||
|
|
||||||
|
### Touchpad
|
||||||
|
|
||||||
|
#### Workspace Switch
|
||||||
|
|
||||||
|
Switch workspaces with three-finger vertical swipes.
|
||||||
|
|
||||||
|
#### Horizontal View Movement
|
||||||
|
|
||||||
|
Move the view horizontally with three-finger horizontal swipes.
|
||||||
|
|
||||||
|
### All Pointing Devices
|
||||||
|
|
||||||
|
#### Drag-and-Drop Edge View Scroll
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
The easiest way to get niri is to install one of the distribution packages.
|
The easiest way to get niri is to install one of the distribution packages.
|
||||||
Here are some of them: [Fedora COPR](https://copr.fedorainfracloud.org/coprs/yalter/niri/) and [nightly COPR](https://copr.fedorainfracloud.org/coprs/yalter/niri-git/) (which I maintain myself), [NixOS Flake](https://github.com/sodiboo/niri-flake), and some more from repology below.
|
Here are some of them: [Fedora COPR](https://copr.fedorainfracloud.org/coprs/yalter/niri/) and [nightly COPR](https://copr.fedorainfracloud.org/coprs/yalter/niri-git/) (which I maintain myself), [NixOS Flake](https://github.com/sodiboo/niri-flake), and some more from repology below.
|
||||||
See the [Building](#building) section if you'd like to compile niri yourself.
|
See the [Building](#building) section if you'd like to compile niri yourself and the [Packaging niri](./Packaging-niri.md) page if you want to package niri.
|
||||||
|
|
||||||
[](https://repology.org/project/niri/versions)
|
[](https://repology.org/project/niri/versions)
|
||||||
|
|
||||||
@@ -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).
|
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.
|
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.
|
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.
|
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
|
### 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).
|
NVIDIA GPUs can have problems running niri (for example, the screen remains black upon starting from a TTY).
|
||||||
Sometimes, the problems can be fixed.
|
Sometimes, the problems can be fixed.
|
||||||
You can try the following:
|
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:
|
Open the niri config file at `~/.config/niri/config.kdl` and put your `render` device path like this:
|
||||||
|
|
||||||
```
|
```kdl
|
||||||
debug {
|
debug {
|
||||||
render-drm-device "/dev/dri/renderD128"
|
render-drm-device "/dev/dri/renderD128"
|
||||||
}
|
}
|
||||||
@@ -70,7 +82,7 @@ Also, on Intel graphics, you may need a workaround described [here](https://nixo
|
|||||||
|
|
||||||
To run niri in a VM, make sure to enable 3D acceleration.
|
To run niri in a VM, make sure to enable 3D acceleration.
|
||||||
|
|
||||||
## Default Hotkeys
|
## Main Default Hotkeys
|
||||||
|
|
||||||
When running on a TTY, the Mod key is <kbd>Super</kbd>.
|
When running on a TTY, the Mod key is <kbd>Super</kbd>.
|
||||||
When running in a window, the Mod key is <kbd>Alt</kbd>.
|
When running in a window, the Mod key is <kbd>Alt</kbd>.
|
||||||
@@ -92,23 +104,20 @@ The general system is: if a hotkey switches somewhere, then adding <kbd>Ctrl</kb
|
|||||||
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>L</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>→</kbd> | Move the focused column to the right |
|
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>L</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>→</kbd> | Move the focused column to the right |
|
||||||
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>J</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>↓</kbd> | Move the focused window below in a column |
|
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>J</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>↓</kbd> | Move the focused window below in a column |
|
||||||
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>K</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>↑</kbd> | Move the focused window above in a column |
|
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>K</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>↑</kbd> | Move the focused window above in a column |
|
||||||
| <kbd>Mod</kbd><kbd>Home</kbd> and <kbd>Mod</kbd><kbd>End</kbd> | Focus the first or the last column |
|
|
||||||
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>Home</kbd> and <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>End</kbd> | Move the focused column to the very start or to the very end |
|
|
||||||
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>H</kbd><kbd>J</kbd><kbd>K</kbd><kbd>L</kbd> or <kbd>Mod</kbd><kbd>Shift</kbd><kbd>←</kbd><kbd>↓</kbd><kbd>↑</kbd><kbd>→</kbd> | Focus the monitor to the side |
|
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>H</kbd><kbd>J</kbd><kbd>K</kbd><kbd>L</kbd> or <kbd>Mod</kbd><kbd>Shift</kbd><kbd>←</kbd><kbd>↓</kbd><kbd>↑</kbd><kbd>→</kbd> | Focus the monitor to the side |
|
||||||
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>H</kbd><kbd>J</kbd><kbd>K</kbd><kbd>L</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>←</kbd><kbd>↓</kbd><kbd>↑</kbd><kbd>→</kbd> | Move the focused column to the monitor to the side |
|
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>H</kbd><kbd>J</kbd><kbd>K</kbd><kbd>L</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>←</kbd><kbd>↓</kbd><kbd>↑</kbd><kbd>→</kbd> | Move the focused column to the monitor to the side |
|
||||||
| <kbd>Mod</kbd><kbd>U</kbd> or <kbd>Mod</kbd><kbd>PageDown</kbd> | Switch to the workspace below |
|
| <kbd>Mod</kbd><kbd>U</kbd> or <kbd>Mod</kbd><kbd>PageDown</kbd> | Switch to the workspace below |
|
||||||
| <kbd>Mod</kbd><kbd>I</kbd> or <kbd>Mod</kbd><kbd>PageUp</kbd> | Switch to the workspace above |
|
| <kbd>Mod</kbd><kbd>I</kbd> or <kbd>Mod</kbd><kbd>PageUp</kbd> | Switch to the workspace above |
|
||||||
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>U</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>PageDown</kbd> | Move the focused column to the workspace below |
|
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>U</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>PageDown</kbd> | Move the focused column to the workspace below |
|
||||||
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>I</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>PageUp</kbd> | Move the focused column to the workspace above |
|
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>I</kbd> or <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>PageUp</kbd> | Move the focused column to the workspace above |
|
||||||
| <kbd>Mod</kbd><kbd>1</kbd>–<kbd>9</kbd> | Switch to a workspace by index |
|
|
||||||
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>1</kbd>–<kbd>9</kbd> | Move the focused column to a workspace by index |
|
|
||||||
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>U</kbd> or <kbd>Mod</kbd><kbd>Shift</kbd><kbd>PageDown</kbd> | Move the focused workspace down |
|
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>U</kbd> or <kbd>Mod</kbd><kbd>Shift</kbd><kbd>PageDown</kbd> | Move the focused workspace down |
|
||||||
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>I</kbd> or <kbd>Mod</kbd><kbd>Shift</kbd><kbd>PageUp</kbd> | Move the focused workspace up |
|
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>I</kbd> or <kbd>Mod</kbd><kbd>Shift</kbd><kbd>PageUp</kbd> | Move the focused workspace up |
|
||||||
| <kbd>Mod</kbd><kbd>,</kbd> | Consume the window to the right into the focused column |
|
| <kbd>Mod</kbd><kbd>,</kbd> | Consume the window to the right into the focused column |
|
||||||
| <kbd>Mod</kbd><kbd>.</kbd> | Expel the focused window into its own column |
|
| <kbd>Mod</kbd><kbd>.</kbd> | Expel the bottom window in the focused column into its own column |
|
||||||
| <kbd>Mod</kbd><kbd>[</kbd> | Consume or expel the focused window to the left |
|
| <kbd>Mod</kbd><kbd>[</kbd> | Consume or expel the focused window to the left |
|
||||||
| <kbd>Mod</kbd><kbd>]</kbd> | Consume or expel the focused window to the right |
|
| <kbd>Mod</kbd><kbd>]</kbd> | Consume or expel the focused window to the right |
|
||||||
| <kbd>Mod</kbd><kbd>R</kbd> | Toggle between preset column widths |
|
| <kbd>Mod</kbd><kbd>R</kbd> | Toggle between preset column widths |
|
||||||
|
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>R</kbd> | Toggle between preset column heights |
|
||||||
| <kbd>Mod</kbd><kbd>F</kbd> | Maximize column |
|
| <kbd>Mod</kbd><kbd>F</kbd> | Maximize column |
|
||||||
| <kbd>Mod</kbd><kbd>C</kbd> | Center column within view |
|
| <kbd>Mod</kbd><kbd>C</kbd> | Center column within view |
|
||||||
| <kbd>Mod</kbd><kbd>-</kbd> | Decrease column width by 10% |
|
| <kbd>Mod</kbd><kbd>-</kbd> | Decrease column width by 10% |
|
||||||
@@ -117,16 +126,18 @@ The general system is: if a hotkey switches somewhere, then adding <kbd>Ctrl</kb
|
|||||||
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>=</kbd> | Increase window height by 10% |
|
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>=</kbd> | Increase window height by 10% |
|
||||||
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>R</kbd> | Reset window height back to automatic |
|
| <kbd>Mod</kbd><kbd>Ctrl</kbd><kbd>R</kbd> | Reset window height back to automatic |
|
||||||
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>F</kbd> | Toggle full-screen on the focused window |
|
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>F</kbd> | Toggle full-screen on the focused window |
|
||||||
|
| <kbd>Mod</kbd><kbd>V</kbd> | Move the focused window between the floating and the tiling layout |
|
||||||
|
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>V</kbd> | Switch focus between the floating and the tiling layout |
|
||||||
| <kbd>PrtSc</kbd> | Take an area screenshot. Select the area to screenshot with mouse, then press Space to save the screenshot, or Escape to cancel |
|
| <kbd>PrtSc</kbd> | Take an area screenshot. Select the area to screenshot with mouse, then press Space to save the screenshot, or Escape to cancel |
|
||||||
| <kbd>Alt</kbd><kbd>PrtSc</kbd> | Take a screenshot of the focused window to clipboard and to `~/Pictures/Screenshots/` |
|
| <kbd>Alt</kbd><kbd>PrtSc</kbd> | Take a screenshot of the focused window to clipboard and to `~/Pictures/Screenshots/` |
|
||||||
| <kbd>Ctrl</kbd><kbd>PrtSc</kbd> | Take a screenshot of the focused monitor to clipboard and to `~/Pictures/Screenshots/` |
|
| <kbd>Ctrl</kbd><kbd>PrtSc</kbd> | Take a screenshot of the focused monitor to clipboard and to `~/Pictures/Screenshots/` |
|
||||||
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>E</kbd> | Exit niri |
|
| <kbd>Mod</kbd><kbd>Shift</kbd><kbd>E</kbd> or <kbd>Ctrl</kbd><kbd>Alt</kbd><kbd>Delete</kbd> | Exit niri |
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
First, install the dependencies for your distribution.
|
First, install the dependencies for your distribution.
|
||||||
|
|
||||||
- Ubuntu 23.10:
|
- Ubuntu 24.04:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo apt-get install -y 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
|
sudo apt-get install -y 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
|
||||||
@@ -157,34 +168,19 @@ 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:
|
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
|
nix run --impure github:guibou/nixGL -- ./results/bin/niri
|
||||||
```
|
```
|
||||||
|
|
||||||
### Packaging
|
|
||||||
|
|
||||||
The recommended way to package niri is so that it runs as a standalone desktop session.
|
|
||||||
To do that, put files into the correct directories according to this table.
|
|
||||||
|
|
||||||
| File | Destination |
|
|
||||||
| ---- | ----------- |
|
|
||||||
| `target/release/niri` | `/usr/bin/` |
|
|
||||||
| `resources/niri-session` | `/usr/bin/` |
|
|
||||||
| `resources/niri.desktop` | `/usr/share/wayland-sessions/` |
|
|
||||||
| `resources/niri-portals.conf` | `/usr/share/xdg-desktop-portal/` |
|
|
||||||
| `resources/niri.service` (systemd) | `/usr/lib/systemd/user/` |
|
|
||||||
| `resources/niri-shutdown.target` (systemd) | `/usr/lib/systemd/user/` |
|
|
||||||
| `resources/dinit/niri` (dinit) | `/usr/lib/dinit.d/user/` |
|
|
||||||
| `resources/dinit/niri-shutdown` (dinit) | `/usr/lib/dinit.d/user/` |
|
|
||||||
|
|
||||||
Doing this will make niri appear in GDM and other display managers.
|
|
||||||
|
|
||||||
### Manual Installation
|
### Manual Installation
|
||||||
|
|
||||||
If installing directly without a package, the recommended file destinations are slightly different.
|
If installing directly without a package, the recommended file destinations are slightly different.
|
||||||
In this case, put the files in the directories indicated in the table below.
|
In this case, put the files in the directories indicated in the table below.
|
||||||
These may vary depending on your distribution.
|
These may vary depending on your distribution.
|
||||||
|
|
||||||
|
Don't forget to make sure that the path to `niri` in niri.service is correct.
|
||||||
|
This defaults to `/usr/bin/niri`.
|
||||||
|
|
||||||
| File | Destination |
|
| File | Destination |
|
||||||
| ---- | ----------- |
|
| ---- | ----------- |
|
||||||
| `target/release/niri` | `/usr/local/bin/` |
|
| `target/release/niri` | `/usr/local/bin/` |
|
||||||
@@ -2,7 +2,7 @@ Since niri is not a complete desktop environment, you will very likely want to r
|
|||||||
|
|
||||||
### Notification Daemon
|
### Notification Daemon
|
||||||
|
|
||||||
Many apps need one. For example, [mako](https://github.com/emersion/mako) works well. Use [a systemd setup](./Example-systemd-Setup.md) or `spawn-at-startup`.
|
Many apps need one. For example, [mako](https://github.com/emersion/mako) works well. Use [a systemd setup](./Example-systemd-Setup.md) or [`spawn-at-startup`](./Configuration:-Miscellaneous.md#spawn-at-startup).
|
||||||
|
|
||||||
### Portals
|
### Portals
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ Portals **require** [running niri as a session](./Getting-Started.md), which mea
|
|||||||
* `xdg-desktop-portal-gnome`: required for screencasting support.
|
* `xdg-desktop-portal-gnome`: required for screencasting support.
|
||||||
* `gnome-keyring`: implements the Secret portal, required for certain apps to work.
|
* `gnome-keyring`: implements the Secret portal, required for certain apps to work.
|
||||||
|
|
||||||
Then systemd should start them on-demand automatically. These particular portals are configured in `niri-portals.conf` which [must be installed](https://github.com/YaLTeR/niri/wiki/Getting-Started#installation) in the correct location.
|
Then systemd should start them on-demand automatically. These particular portals are configured in `niri-portals.conf` which [must be installed](./Getting-Started.md#manual-installation) in the correct location.
|
||||||
|
|
||||||
Since we're using `xdg-desktop-portal-gnome`, Flatpak apps will read the GNOME UI settings. For example, to enable the dark style, run:
|
Since we're using `xdg-desktop-portal-gnome`, Flatpak apps will read the GNOME UI settings. For example, to enable the dark style, run:
|
||||||
|
|
||||||
@@ -22,9 +22,13 @@ Since we're using `xdg-desktop-portal-gnome`, Flatpak apps will read the GNOME U
|
|||||||
dconf write /org/gnome/desktop/interface/color-scheme '"prefer-dark"'
|
dconf write /org/gnome/desktop/interface/color-scheme '"prefer-dark"'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that if you're using the provided `resources/niri-portals.conf`, you also need to install the `nautilus` file manager in order for file chooser dialogues to work properly. This is necessary because xdg-desktop-portal-gnome uses nautilus as the file chooser by default starting from version 47.0.
|
||||||
|
|
||||||
|
If you do not want to install `nautilus` (say you use `nemo` instead), you can set `org.freedesktop.impl.portal.FileChooser=gtk;` in `niri-portals.conf` to use the GTK portal for file chooser dialogues.
|
||||||
|
|
||||||
### Authentication Agent
|
### Authentication Agent
|
||||||
|
|
||||||
Required when apps need to ask for root permissions. Something like `plasma-polkit-agent` works fine. Start it [with systemd](./Example-systemd-Setup.md) or with `spawn-at-startup`.
|
Required when apps need to ask for root permissions. Something like `plasma-polkit-agent` works fine. Start it [with systemd](./Example-systemd-Setup.md) or with [`spawn-at-startup`](./Configuration:-Miscellaneous.md#spawn-at-startup).
|
||||||
|
|
||||||
Note that to start `plasma-polkit-agent` with systemd on Fedora, you'll need to override its systemd service to add the correct dependency. Run:
|
Note that to start `plasma-polkit-agent` with systemd on Fedora, you'll need to override its systemd service to add the correct dependency. Run:
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
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.
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
### Overview
|
||||||
|
|
||||||
|
When building niri, check `Cargo.toml` for a list of build features.
|
||||||
|
For example, you can replace systemd integration with dinit integration using `cargo build --release --no-default-features --features dinit,dbus,xdp-gnome-screencast`.
|
||||||
|
The defaults however should work fine for most distributions.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Do NOT build with `--all-features`!
|
||||||
|
>
|
||||||
|
> Some features are meant only for development use.
|
||||||
|
> For example, one of the features enables collection of profiling data into a memory buffer that will grow indefinitely until you run out of memory.
|
||||||
|
|
||||||
|
The `niri-visual-tests` sub-crate/binary is development-only and should not be packaged.
|
||||||
|
|
||||||
|
The recommended way to package niri is so that it runs as a standalone desktop session.
|
||||||
|
To do that, put files into the correct directories according to this table.
|
||||||
|
|
||||||
|
| File | Destination |
|
||||||
|
| ---- | ----------- |
|
||||||
|
| `target/release/niri` | `/usr/bin/` |
|
||||||
|
| `resources/niri-session` | `/usr/bin/` |
|
||||||
|
| `resources/niri.desktop` | `/usr/share/wayland-sessions/` |
|
||||||
|
| `resources/niri-portals.conf` | `/usr/share/xdg-desktop-portal/` |
|
||||||
|
| `resources/niri.service` (systemd) | `/usr/lib/systemd/user/` |
|
||||||
|
| `resources/niri-shutdown.target` (systemd) | `/usr/lib/systemd/user/` |
|
||||||
|
| `resources/dinit/niri` (dinit) | `/usr/lib/dinit.d/user/` |
|
||||||
|
| `resources/dinit/niri-shutdown` (dinit) | `/usr/lib/dinit.d/user/` |
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ niri --version
|
||||||
|
niri 25.01 (e35c630)
|
||||||
|
```
|
||||||
|
|
||||||
|
When building in a packaging system, there's usually no repository, so the commit hash is unavailable and the version will show "unknown commit".
|
||||||
|
In this case, please set the commit hash manually:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ export NIRI_BUILD_COMMIT="e35c630"
|
||||||
|
...proceed to build niri
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also override the version string entirely, in this case please make sure the corresponding niri version stays intact:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ export NIRI_BUILD_VERSION_STRING="25.01-1 (e35c630)"
|
||||||
|
...proceed to build niri
|
||||||
|
```
|
||||||
|
|
||||||
|
Remember to set this variable for both `cargo build` and `cargo install` since the latter will rebuild niri if the environment changes.
|
||||||
|
|
||||||
|
### Panics
|
||||||
|
|
||||||
|
Good panic backtraces are required for diagnosing niri crashes.
|
||||||
|
Please use the `niri panic` command to test that your package produces good backtraces.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ niri panic
|
||||||
|
thread 'main' panicked at /builddir/build/BUILD/rust-1.83.0-build/rustc-1.83.0-src/library/core/src/time.rs:1142:31:
|
||||||
|
overflow when subtracting durations
|
||||||
|
stack backtrace:
|
||||||
|
0: rust_begin_unwind
|
||||||
|
at /builddir/build/BUILD/rust-1.83.0-build/rustc-1.83.0-src/library/std/src/panicking.rs:665:5
|
||||||
|
1: core::panicking::panic_fmt
|
||||||
|
at /builddir/build/BUILD/rust-1.83.0-build/rustc-1.83.0-src/library/core/src/panicking.rs:74:14
|
||||||
|
2: core::panicking::panic_display
|
||||||
|
at /builddir/build/BUILD/rust-1.83.0-build/rustc-1.83.0-src/library/core/src/panicking.rs:264:5
|
||||||
|
3: core::option::expect_failed
|
||||||
|
at /builddir/build/BUILD/rust-1.83.0-build/rustc-1.83.0-src/library/core/src/option.rs:2021:5
|
||||||
|
4: expect<core::time::Duration>
|
||||||
|
at /builddir/build/BUILD/rust-1.83.0-build/rustc-1.83.0-src/library/core/src/option.rs:933:21
|
||||||
|
5: sub
|
||||||
|
at /builddir/build/BUILD/rust-1.83.0-build/rustc-1.83.0-src/library/core/src/time.rs:1142:31
|
||||||
|
6: cause_panic
|
||||||
|
at /builddir/build/BUILD/niri-0.0.git.1699.279c8b6a-build/niri/src/utils/mod.rs:382:13
|
||||||
|
7: main
|
||||||
|
at /builddir/build/BUILD/niri-0.0.git.1699.279c8b6a-build/niri/src/main.rs:107:27
|
||||||
|
8: call_once<fn() -> core::result::Result<(), alloc::boxed::Box<dyn core::error::Error, alloc::alloc::Global>>, ()>
|
||||||
|
at /builddir/build/BUILD/rust-1.83.0-build/rustc-1.83.0-src/library/core/src/ops/function.rs:250:5
|
||||||
|
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
|
||||||
|
```
|
||||||
|
|
||||||
|
Important things to look for:
|
||||||
|
|
||||||
|
- The panic message is there: "overflow when subtracting durations".
|
||||||
|
- The backtrace goes all the way up to `main` and includes `cause_panic`.
|
||||||
|
- The backtrace includes the file and line number for `cause_panic`: `at /.../src/utils/mod.rs:382:13`.
|
||||||
|
|
||||||
|
If possible, please ensure that your niri package on its own has good panics, i.e. *without* installing debuginfo or other packages.
|
||||||
|
The user likely won't have debuginfo installed when their compositor first crashes, and we really want to be able to diagnose and fix all crashes right away.
|
||||||
|
|
||||||
|
### Rust dependencies
|
||||||
|
|
||||||
|
Every niri release comes with a vendored dependencies archive from `cargo vendor`.
|
||||||
|
You can use it to build the corresponding niri release completely offline.
|
||||||
|
|
||||||
|
If you don't want to use vendored dependencies, consider following the niri release's `Cargo.lock`.
|
||||||
|
It contains the exact dependency versions that I used when testing the release.
|
||||||
|
|
||||||
|
If you need to change the versions of some dependencies, pay extra attention to `smithay` and `smithay-drm-extras` commit hash.
|
||||||
|
These crates don't currently have regular stable releases, so niri uses git snapshots.
|
||||||
|
Upstream frequently has breaking changes (API and behavior), so you're strongly advised to use the exact commit hash from the niri release's `Cargo.lock`.
|
||||||
@@ -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.
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
### Overview
|
||||||
|
|
||||||
|
The primary screencasting interface that niri offers is through portals and pipewire.
|
||||||
|
It is supported by [OBS], Firefox, Chromium, Electron, Telegram, and other apps.
|
||||||
|
You can screencast both monitors and individual windows.
|
||||||
|
|
||||||
|
In order to use it, you need a working D-Bus session, pipewire, `xdg-desktop-portal-gnome`, and [running niri as a session](./Getting-Started.md) (i.e. through `niri-session` or from a display manager).
|
||||||
|
On widely used distros this should all "just work".
|
||||||
|
|
||||||
|
Alternatively, you can use tools that rely on the `wlr-screencopy` protocol, which niri also supports.
|
||||||
|
|
||||||
|
There are several features in niri designed for screencasting.
|
||||||
|
Let's take a look!
|
||||||
|
|
||||||
|
### Block out windows
|
||||||
|
|
||||||
|
You can block out specific windows from screencasts, replacing them with solid black rectangles.
|
||||||
|
This can be useful for password managers or messenger windows, etc.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This is controlled through the `block-out-from` window rule, for example:
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Block out password managers from screencasts.
|
||||||
|
window-rule {
|
||||||
|
match app-id=r#"^org\.keepassxc\.KeePassXC$"#
|
||||||
|
match app-id=r#"^org\.gnome\.World\.Secrets$"#
|
||||||
|
|
||||||
|
block-out-from "screencast"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can similarly block out layer surfaces, using a layer rule:
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Block out mako notifications from screencasts.
|
||||||
|
layer-rule {
|
||||||
|
match namespace="^notifications$"
|
||||||
|
|
||||||
|
block-out-from "screencast"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Check [the corresponding wiki section](./Configuration:-Window-Rules.md#block-out-from) for more details and examples.
|
||||||
|
|
||||||
|
### Dynamic screencast target
|
||||||
|
|
||||||
|
<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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
When you select it, it will start as an empty, transparent video stream.
|
||||||
|
Then, you can use the following binds to change what it shows:
|
||||||
|
|
||||||
|
- `set-dynamic-cast-window` to cast the focused window.
|
||||||
|
- `set-dynamic-cast-monitor` to cast the focused monitor.
|
||||||
|
- `clear-dynamic-cast-target` to go back to an empty stream.
|
||||||
|
|
||||||
|
You can also use these actions from the command line, for example to interactively pick which window to cast:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ 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).
|
||||||
|
|
||||||
|
### Indicate screencasted windows
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
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 targeted by dynamic screencasts.
|
||||||
|
However, it will not work for windows that just happen to be visible in a full-monitor screencast.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
// Indicate screencasted windows with red colors.
|
||||||
|
window-rule {
|
||||||
|
match is-window-cast-target=true
|
||||||
|
|
||||||
|
focus-ring {
|
||||||
|
active-color "#f38ba8"
|
||||||
|
inactive-color "#7d0d2d"
|
||||||
|
}
|
||||||
|
|
||||||
|
border {
|
||||||
|
inactive-color "#7d0d2d"
|
||||||
|
}
|
||||||
|
|
||||||
|
shadow {
|
||||||
|
color "#7d0d2d70"
|
||||||
|
}
|
||||||
|
|
||||||
|
tab-indicator {
|
||||||
|
active-color "#f38ba8"
|
||||||
|
inactive-color "#7d0d2d"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Windowed (fake/detached) fullscreen
|
||||||
|
|
||||||
|
<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.
|
||||||
|
|
||||||
|
The `toggle-windowed-fullscreen` bind helps with this.
|
||||||
|
It tells the app that it went fullscreen, while in reality leaving it as a normal window that you can resize and put wherever you want.
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
Mod+Ctrl+Shift+F { toggle-windowed-fullscreen; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep in mind that not all apps react to fullscreening, so it may sometimes look as if the bind did nothing.
|
||||||
|
|
||||||
|
Here's an example showing a windowed-fullscreen Google Slides [presentation](https://youtu.be/Kmz8ODolnDg), along with the presenter view and a meeting app:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[OBS]: https://obsproject.com/
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
### Overview
|
||||||
|
|
||||||
|
<sup>Since: 25.02</sup>
|
||||||
|
|
||||||
|
You can switch a column to present windows as tabs, rather than as vertical tiles.
|
||||||
|
All tabs in a column have the same window size, so this is useful to get more vertical space.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Use this bind to toggle a column between normal and tabbed display:
|
||||||
|
|
||||||
|
```kdl
|
||||||
|
binds {
|
||||||
|
Mod+W { toggle-column-tabbed-display; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
All other binds remain the same: switch tabs with `focus-window-down/up`, add or remove windows with `consume-window-into-column`/`expel-window-from-column`, and so on.
|
||||||
|
|
||||||
|
Unlike regular columns, tabbed columns can go full-screen with multiple windows.
|
||||||
|
|
||||||
|
### Tab indicator
|
||||||
|
|
||||||
|
Tabbed columns show a tab indicator on the side.
|
||||||
|
You can click on the indicator to switch tabs.
|
||||||
|
|
||||||
|
See the [`tab-indicator` section in the layout section](./Configuration:-Layout.md#tab-indicator) to configure it.
|
||||||
|
|
||||||
|
By default, the indicator draws "outside" the column, so it can overlay other windows or go off-screen.
|
||||||
|
The `place-within-column` flag puts the indicator "inside" the column, adjusting the window size to make space for it.
|
||||||
|
This is especially useful for thicker tab indicators, or when you have very small gaps.
|
||||||
|
|
||||||
|
| Default | `place-within-column` |
|
||||||
|
| --- | --- |
|
||||||
|
|  |  |
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
### Overview
|
||||||
|
|
||||||
|
Niri has dynamic workspaces that can move between monitors.
|
||||||
|
|
||||||
|
Each monitor contains an independent set of workspaces arranged vertically.
|
||||||
|
You can switch between workspaces on a monitor with `focus-workspace-down` and `focus-workspace-up`.
|
||||||
|
Empty workspaces "in the middle" automatically disappear when you switch away from them.
|
||||||
|
|
||||||
|
There's always one empty workspace at the end (at the bottom) of every monitor.
|
||||||
|
When you open a window on this empty workspace, a new empty workspace will immediately appear further below it.
|
||||||
|
|
||||||
|
You can move workspaces up and down on the monitor with `move-workspace-up/down`.
|
||||||
|
The way to put a window on a new workspace "in the middle" is to put it on the last (empty) workspace, then move the workspace up to where you need.
|
||||||
|
|
||||||
|
Here's a visual representation that shows two monitors and their workspaces.
|
||||||
|
The left monitor has three workspaces (two with windows, plus one empty), and the right monitor has two workspaces (one with windows, plus one empty).
|
||||||
|
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="./img/workspaces-dark.png">
|
||||||
|
<img alt="Two monitors. First with three workspaces, second with two workspaces." src="./img/workspaces-light.png">
|
||||||
|
</picture>
|
||||||
|
|
||||||
|
You can move a workspace to a different monitor using binds like `move-workspace-to-monitor-left/right/up/down` and `move-workspace-to-monitor-next/previous`.
|
||||||
|
|
||||||
|
When you disconnect a monitor, its workspaces will automatically move to a different monitor.
|
||||||
|
But, they will also "remember" their original monitor, so when you reconnect it, the workspaces will automatically move back to it.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> From other tiling WMs, you may be used to thinking about workspaces like this: "These are all of my workspaces. I can show workspace X on my first monitor, and workspace Y on my second monitor."
|
||||||
|
> In niri, instead, think like this: "My first monitor contains these workspaces, including X and Y, and my second monitor contains these other workspaces. I can switch my first monitor to workspace X or Y. I can move workspace Y to my second monitor to show it there."
|
||||||
|
|
||||||
|
### Addressing workspaces by index
|
||||||
|
|
||||||
|
Several actions in niri can address workspaces "by index": `focus-workspace 2`, `move-column-to-workspace 4`.
|
||||||
|
This index refers to whichever workspace *currently happens to be* at this position on the focused monitor.
|
||||||
|
So, `focus-workspace 2` will always put you on the second workspace of the monitor, whichever workspace that currently is.
|
||||||
|
|
||||||
|
This is an important distinction from WMs with static workspace systems.
|
||||||
|
In niri, workspaces *do not have indices on their own*.
|
||||||
|
If you take the first workspace and move it further down on the monitor, `focus-workspace 1` will now put you on a different workspace (the one that was below the first workspace before you moved it).
|
||||||
|
|
||||||
|
When you want to have a more permanent workspace in niri, you can create a [named workspace](./Configuration:-Named-Workspaces.md) in the config or via the `set-workspace-name` action.
|
||||||
|
You can refer to named workspaces by name, e.g. `focus-workspace "browser"`, and they won't disappear when they become empty.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> You can try to emulate static workspaces by creating workspaces named "one", "two", "three", ..., and binding keys to `focus-workspace "one"`, `focus-workspace "two"`, ...
|
||||||
|
> This can work to some extent, but it can become somewhat confusing, since you can still move these workspaces up and down and between monitors.
|
||||||
|
>
|
||||||
|
> If you're coming from a static workspace WM, I suggest *not* doing that, but instead trying the "niri way" with dynamic workspaces, focusing and moving up/down instead of by index.
|
||||||
|
> Thanks to scrollable tiling, you generally need fewer workspaces than on a traditional tiling WM.
|
||||||
|
|
||||||
|
### Example workflow
|
||||||
|
|
||||||
|
This is how I like to use workspaces.
|
||||||
|
|
||||||
|
I will usually have my browser on the topmost workspace, then one workspace per project (or a "thing") I'm working on.
|
||||||
|
On a single workspace I have 1–2 windows that fit inside a monitor that I switch between frequently, and maybe extra windows scrolled outside the view, usually either ones I need rarely, or temporary windows that I quickly close.
|
||||||
|
When I need another permanent window, I'll put it on a new workspace.
|
||||||
|
|
||||||
|
I actively move workspaces up and down as I'm working on things to make what I need accessible in one motion.
|
||||||
|
For example, I usually frequently switch between the browser and whatever I'm doing, so I always move whatever I'm currently doing to right below the browser, so a single `focus-workspace-up/down` gets me where I want.
|
||||||
@@ -1,23 +1,38 @@
|
|||||||
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.
|
However, there are multiple solutions to running X11 apps in niri.
|
||||||
|
|
||||||
## Using xwayland-satellite
|
## Using xwayland-satellite
|
||||||
|
|
||||||
[xwayland-satellite] is a new project that essentially implements rootless Xwayland in a separate application, without the host compositor's involvement.
|
[xwayland-satellite] implements rootless Xwayland in a separate application, without the host compositor's involvement.
|
||||||
While it is still somewhat experimental, it handles a lot of applications correctly, like Steam, games and Discord.
|
It makes X11 windows appear as normal windows, just like a native Xwayland integration.
|
||||||
|
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.
|
||||||
|
|
||||||
Build it according to instructions from its README, then run the `xwayland-satellite` binary.
|
> [!NOTE]
|
||||||
Now you can start X11 applications on the X11 DISPLAY that it provides:
|
> 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`.
|
||||||
|
Now you can start X11 applications on this X11 DISPLAY:
|
||||||
|
|
||||||
```
|
```
|
||||||
env DISPLAY=:0 flatpak run com.valvesoftware.Steam
|
env DISPLAY=:0 flatpak run com.valvesoftware.Steam
|
||||||
```
|
```
|
||||||
|
|
||||||
They will appear as normal windows.
|

|
||||||
|
|
||||||
You can also set `DISPLAY` by default for all apps by adding it to the `environment` section of the niri config:
|
You can also automatically run it at startup, and set `DISPLAY` by default for all apps by adding it to the [`environment`](./Configuration:-Miscellaneous.md#environment) section of the niri config:
|
||||||
|
|
||||||
```kdl
|
```kdl
|
||||||
|
spawn-at-startup "xwayland-satellite"
|
||||||
|
// Or, if you built it by hand:
|
||||||
|
// spawn-at-startup "~/path/to/code/target/release/xwayland-satellite"
|
||||||
|
|
||||||
environment {
|
environment {
|
||||||
DISPLAY ":0"
|
DISPLAY ":0"
|
||||||
}
|
}
|
||||||
@@ -25,10 +40,22 @@ environment {
|
|||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> If the `:0` DISPLAY is already taken (for example, by some other Xwayland server like `xwayland-run`), `xwayland-satellite` will try the next DISPLAY numbers in order: `:1`, `:2`, etc. and tell you which one it used in its output.
|
> If the `:0` DISPLAY is already taken (for example, by some other Xwayland server like `xwayland-run`), `xwayland-satellite` will try the next DISPLAY numbers in order: `:1`, `:2`, etc. and tell you which one it used in its output.
|
||||||
> Then, you will need to use that DISPLAY number for the `env` command or for the niri `environment` block.
|
> Then, you will need to use that DISPLAY number for the `env` command or for the niri [`environment`](./Configuration:-Miscellaneous.md#environment) section.
|
||||||
>
|
>
|
||||||
> You can also force a specific DISPLAY number like so: `xwayland-satellite :12` will start on `DISPLAY=:12`.
|
> You can also force a specific DISPLAY number like so: `xwayland-satellite :12` will start on `DISPLAY=:12`.
|
||||||
|
|
||||||
|
## Using the labwc Wayland compositor
|
||||||
|
|
||||||
|
[Labwc](https://github.com/labwc/labwc) is a traditional stacking Wayland compositor with Xwayland.
|
||||||
|
You can run it as a window, then run X11 apps inside.
|
||||||
|
|
||||||
|
1. Install labwc from your distribution packages.
|
||||||
|
1. Run it inside niri with the `labwc` command.
|
||||||
|
It will open as a new window.
|
||||||
|
1. Run an X11 application on the X11 DISPLAY that it provides, e.g. `env DISPLAY=:0 glxgears`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Directly running Xwayland in rootful mode
|
## Directly running Xwayland in rootful mode
|
||||||
|
|
||||||
This method involves invoking XWayland directly and running it as its own window, it also requires an extra X11 window manager running inside it.
|
This method involves invoking XWayland directly and running it as its own window, it also requires an extra X11 window manager running inside it.
|
||||||
@@ -2,15 +2,22 @@
|
|||||||
* [Getting Started](./Getting-Started.md)
|
* [Getting Started](./Getting-Started.md)
|
||||||
* [Example systemd Setup](./Example-systemd-Setup.md)
|
* [Example systemd Setup](./Example-systemd-Setup.md)
|
||||||
* [Important Software](./Important-Software.md)
|
* [Important Software](./Important-Software.md)
|
||||||
|
* [Workspaces](./Workspaces.md)
|
||||||
|
* [Floating Windows](./Floating-Windows.md)
|
||||||
|
* [Tabs](./Tabs.md)
|
||||||
|
* [Overview](./Overview.md)
|
||||||
|
* [Screencasting](./Screencasting.md)
|
||||||
* [Layer‐Shell Components](./Layer%E2%80%90Shell-Components.md)
|
* [Layer‐Shell Components](./Layer%E2%80%90Shell-Components.md)
|
||||||
* [IPC, `niri msg`](./IPC.md)
|
* [IPC, `niri msg`](./IPC.md)
|
||||||
* [VSCode, Chromium, WezTerm](./Application-Issues.md)
|
* [Application-Specific Issues](./Application-Issues.md)
|
||||||
|
* [Nvidia](./Nvidia.md)
|
||||||
* [Xwayland](./Xwayland.md)
|
* [Xwayland](./Xwayland.md)
|
||||||
* [Gestures](./Gestures.md)
|
* [Gestures](./Gestures.md)
|
||||||
|
* [Packaging niri](./Packaging-niri.md)
|
||||||
* [FAQ](./FAQ.md)
|
* [FAQ](./FAQ.md)
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
* [Overview](./Configuration:-Overview.md)
|
* [Introduction](./Configuration:-Introduction.md)
|
||||||
* [Input](./Configuration:-Input.md)
|
* [Input](./Configuration:-Input.md)
|
||||||
* [Outputs](./Configuration:-Outputs.md)
|
* [Outputs](./Configuration:-Outputs.md)
|
||||||
* [Key Bindings](./Configuration:-Key-Bindings.md)
|
* [Key Bindings](./Configuration:-Key-Bindings.md)
|
||||||
@@ -19,11 +26,15 @@
|
|||||||
* [Named Workspaces](./Configuration:-Named-Workspaces.md)
|
* [Named Workspaces](./Configuration:-Named-Workspaces.md)
|
||||||
* [Miscellaneous](./Configuration:-Miscellaneous.md)
|
* [Miscellaneous](./Configuration:-Miscellaneous.md)
|
||||||
* [Window Rules](./Configuration:-Window-Rules.md)
|
* [Window Rules](./Configuration:-Window-Rules.md)
|
||||||
|
* [Layer Rules](./Configuration:-Layer-Rules.md)
|
||||||
* [Animations](./Configuration:-Animations.md)
|
* [Animations](./Configuration:-Animations.md)
|
||||||
|
* [Gestures](./Configuration:-Gestures.md)
|
||||||
* [Debug Options](./Configuration:-Debug-Options.md)
|
* [Debug Options](./Configuration:-Debug-Options.md)
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
* [Design Principles](./Design-Principles.md)
|
* [Design Principles](./Development:-Design-Principles.md)
|
||||||
* [Developing niri](./Developing-niri.md)
|
* [Developing niri](./Development:-Developing-niri.md)
|
||||||
* [Fractional Layout](./Fractional-Layout.md)
|
* [Documenting niri](./Development:-Documenting-niri.md)
|
||||||
* [Redraw Loop](./Redraw-Loop.md)
|
* [Fractional Layout](./Development:-Fractional-Layout.md)
|
||||||
|
* [Redraw Loop](./Development:-Redraw-Loop.md)
|
||||||
|
* [Animation Timing](./Development:-Animation-Timing.md)
|
||||||
@@ -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 |
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1dcaa6ece8e8287081332604270fa17a66561e0d81fd190d665005b6359c0eac
|
||||||
|
size 559823
|
||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 23 KiB |
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e387b2551923ebcf9a21e2e485c55195c817d64a3198bc8d38ee0808046b7a44
|
||||||
|
size 16825
|
||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:bf088a6b2a4ba2f38b711a5057251a702f55d6c8fcbc8310d39ad4c75a2a0d38
|
||||||
|
size 17357
|
||||||
Generated
+6
-22
@@ -1,27 +1,12 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"nix-filter": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1710156097,
|
|
||||||
"narHash": "sha256-1Wvk8UP7PXdf8bCCaEoMnOT1qe5/Duqgj+rL8sRQsSM=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "nix-filter",
|
|
||||||
"rev": "3342559a24e85fc164b295c3444e8a139924675b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "nix-filter",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1726365531,
|
"lastModified": 1752077645,
|
||||||
"narHash": "sha256-luAKNxWZ+ZN0kaHchx1OdLQ71n81Y31ryNPWP1YRDZc=",
|
"narHash": "sha256-HM791ZQtXV93xtCY+ZxG1REzhQenSQO020cu6rHtAPk=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "9299cdf978e15f448cf82667b0ffdd480b44ee48",
|
"rev": "be9e214982e20b8310878ac2baa063a961c1bdf6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -33,7 +18,6 @@
|
|||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nix-filter": "nix-filter",
|
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"rust-overlay": "rust-overlay"
|
"rust-overlay": "rust-overlay"
|
||||||
}
|
}
|
||||||
@@ -45,11 +29,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1727663505,
|
"lastModified": 1752374969,
|
||||||
"narHash": "sha256-83j/GrHsx8GFUcQofKh+PRPz6pz8sxAsZyT/HCNdey8=",
|
"narHash": "sha256-Ky3ynEkJXih7mvWyt9DWoiSiZGqPeHLU1tlBU4b0mcc=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "c2099c6c7599ea1980151b8b6247a8f93e1806ee",
|
"rev": "75fb000638e6d0f57cb1e8b7a4550cbdd8c76f1d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
nix-filter.url = "github:numtide/nix-filter";
|
|
||||||
|
|
||||||
# NOTE: This is not necessary for end users
|
# NOTE: This is not necessary for end users
|
||||||
# You can omit it with `inputs.rust-overlay.follows = ""`
|
# You can omit it with `inputs.rust-overlay.follows = ""`
|
||||||
@@ -18,7 +17,6 @@
|
|||||||
{
|
{
|
||||||
self,
|
self,
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
nix-filter,
|
|
||||||
rust-overlay,
|
rust-overlay,
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
@@ -26,21 +24,20 @@
|
|||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
cairo,
|
cairo,
|
||||||
clang,
|
|
||||||
dbus,
|
dbus,
|
||||||
libGL,
|
libGL,
|
||||||
libclang,
|
|
||||||
libdisplay-info,
|
libdisplay-info,
|
||||||
libinput,
|
libinput,
|
||||||
seatd,
|
seatd,
|
||||||
libxkbcommon,
|
libxkbcommon,
|
||||||
mesa,
|
libgbm,
|
||||||
pango,
|
pango,
|
||||||
pipewire,
|
pipewire,
|
||||||
pkg-config,
|
pkg-config,
|
||||||
rustPlatform,
|
rustPlatform,
|
||||||
systemd,
|
systemd,
|
||||||
wayland,
|
wayland,
|
||||||
|
installShellFiles,
|
||||||
withDbus ? true,
|
withDbus ? true,
|
||||||
withSystemd ? true,
|
withSystemd ? true,
|
||||||
withScreencastSupport ? true,
|
withScreencastSupport ? true,
|
||||||
@@ -51,16 +48,16 @@
|
|||||||
pname = "niri";
|
pname = "niri";
|
||||||
version = self.shortRev or self.dirtyShortRev or "unknown";
|
version = self.shortRev or self.dirtyShortRev or "unknown";
|
||||||
|
|
||||||
src = nix-filter.lib.filter {
|
src = lib.fileset.toSource {
|
||||||
root = self;
|
root = ./.;
|
||||||
include = [
|
fileset = lib.fileset.unions [
|
||||||
"niri-config"
|
./niri-config
|
||||||
"niri-ipc"
|
./niri-ipc
|
||||||
"niri-visual-tests"
|
./niri-visual-tests
|
||||||
"resources"
|
./resources
|
||||||
"src"
|
./src
|
||||||
./Cargo.lock
|
|
||||||
./Cargo.toml
|
./Cargo.toml
|
||||||
|
./Cargo.lock
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,8 +76,9 @@
|
|||||||
strictDeps = true;
|
strictDeps = true;
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
clang
|
rustPlatform.bindgenHook
|
||||||
pkg-config
|
pkg-config
|
||||||
|
installShellFiles
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs =
|
buildInputs =
|
||||||
@@ -92,7 +90,7 @@
|
|||||||
libinput
|
libinput
|
||||||
seatd
|
seatd
|
||||||
libxkbcommon
|
libxkbcommon
|
||||||
mesa # libgbm
|
libgbm
|
||||||
pango
|
pango
|
||||||
wayland
|
wayland
|
||||||
]
|
]
|
||||||
@@ -108,8 +106,28 @@
|
|||||||
++ lib.optional withSystemd "systemd";
|
++ lib.optional withSystemd "systemd";
|
||||||
buildNoDefaultFeatures = true;
|
buildNoDefaultFeatures = true;
|
||||||
|
|
||||||
|
# ever since this commit:
|
||||||
|
# https://github.com/YaLTeR/niri/commit/771ea1e81557ffe7af9cbdbec161601575b64d81
|
||||||
|
# niri now runs an actual instance of the real compositor (with a mock backend) during tests
|
||||||
|
# and thus creates a real socket file in the runtime dir.
|
||||||
|
# this is fine for our build, we just need to make sure it has a directory to write to.
|
||||||
|
preCheck = ''
|
||||||
|
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 =
|
postInstall =
|
||||||
''
|
''
|
||||||
|
installShellCompletion --cmd niri \
|
||||||
|
--bash <($out/bin/niri completions bash) \
|
||||||
|
--fish <($out/bin/niri completions fish) \
|
||||||
|
--zsh <($out/bin/niri completions zsh)
|
||||||
|
|
||||||
install -Dm644 resources/niri.desktop -t $out/share/wayland-sessions
|
install -Dm644 resources/niri.desktop -t $out/share/wayland-sessions
|
||||||
install -Dm644 resources/niri-portals.conf -t $out/share/xdg-desktop-portal
|
install -Dm644 resources/niri-portals.conf -t $out/share/xdg-desktop-portal
|
||||||
''
|
''
|
||||||
@@ -119,8 +137,6 @@
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
env = {
|
env = {
|
||||||
LIBCLANG_PATH = lib.getLib libclang + "/lib";
|
|
||||||
|
|
||||||
# Force linking with libEGL and libwayland-client
|
# Force linking with libEGL and libwayland-client
|
||||||
# so they can be discovered by `dlopen()`
|
# so they can be discovered by `dlopen()`
|
||||||
RUSTFLAGS = toString (
|
RUSTFLAGS = toString (
|
||||||
@@ -191,7 +207,7 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
pkgs.clang
|
pkgs.rustPlatform.bindgenHook
|
||||||
pkgs.pkg-config
|
pkgs.pkg-config
|
||||||
pkgs.wrapGAppsHook4 # For `niri-visual-tests`
|
pkgs.wrapGAppsHook4 # For `niri-visual-tests`
|
||||||
];
|
];
|
||||||
@@ -201,8 +217,6 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
env = {
|
env = {
|
||||||
inherit (niri) LIBCLANG_PATH;
|
|
||||||
|
|
||||||
# WARN: Do not overwrite this variable in your shell!
|
# WARN: Do not overwrite this variable in your shell!
|
||||||
# It is required for `dlopen()` to work on some libraries; see the comment
|
# It is required for `dlopen()` to work on some libraries; see the comment
|
||||||
# in the package expression
|
# in the package expression
|
||||||
|
|||||||
@@ -9,16 +9,15 @@ repository.workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags.workspace = true
|
bitflags.workspace = true
|
||||||
csscolorparser = "0.7.0"
|
csscolorparser = "0.7.2"
|
||||||
knuffel = "3.2.0"
|
knuffel = "3.2.0"
|
||||||
miette = "5.10.0"
|
miette = { version = "5.10.0", features = ["fancy-no-backtrace"] }
|
||||||
niri-ipc = { version = "0.1.10", path = "../niri-ipc" }
|
niri-ipc = { version = "25.5.1", path = "../niri-ipc" }
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
smithay = { workspace = true, features = ["backend_libinput"] }
|
smithay = { workspace = true, features = ["backend_libinput"] }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
tracy-client.workspace = true
|
tracy-client.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
k9.workspace = true
|
insta.workspace = true
|
||||||
miette = { version = "5.10.0", features = ["fancy"] }
|
|
||||||
pretty_assertions = "1.4.1"
|
pretty_assertions = "1.4.1"
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
use crate::{BlockOutFrom, CornerRadius, RegexEq, ShadowRule};
|
||||||
|
|
||||||
|
#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)]
|
||||||
|
pub struct LayerRule {
|
||||||
|
#[knuffel(children(name = "match"))]
|
||||||
|
pub matches: Vec<Match>,
|
||||||
|
#[knuffel(children(name = "exclude"))]
|
||||||
|
pub excludes: Vec<Match>,
|
||||||
|
|
||||||
|
#[knuffel(child, unwrap(argument))]
|
||||||
|
pub opacity: Option<f32>,
|
||||||
|
#[knuffel(child, unwrap(argument))]
|
||||||
|
pub block_out_from: Option<BlockOutFrom>,
|
||||||
|
#[knuffel(child, default)]
|
||||||
|
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)]
|
||||||
|
pub struct Match {
|
||||||
|
#[knuffel(property, str)]
|
||||||
|
pub namespace: Option<RegexEq>,
|
||||||
|
#[knuffel(property)]
|
||||||
|
pub at_startup: Option<bool>,
|
||||||
|
}
|
||||||
+2710
-375
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
/// `Regex` that implements `PartialEq` by its string form.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct RegexEq(pub Regex);
|
||||||
|
|
||||||
|
impl PartialEq for RegexEq {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.0.as_str() == other.0.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for RegexEq {}
|
||||||
|
|
||||||
|
impl FromStr for RegexEq {
|
||||||
|
type Err = <Regex as FromStr>::Err;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Regex::from_str(s).map(Self)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ fn extract_kdl_from_file(file_contents: &str, filename: &str) -> Vec<KdlCodeBloc
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wiki_docs_parses() {
|
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)
|
let code_blocks = fs::read_dir(wiki_dir)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -95,8 +95,7 @@ fn wiki_docs_parses() {
|
|||||||
}
|
}
|
||||||
} else if must_fail {
|
} else if must_fail {
|
||||||
errors.push(format!(
|
errors.push(format!(
|
||||||
"Expected error parsing wiki KDL code block at {}:{}",
|
"Expected error parsing wiki KDL code block at {filename}:{line_number}",
|
||||||
filename, line_number
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ readme = "README.md"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { workspace = true, optional = true }
|
clap = { workspace = true, optional = true }
|
||||||
schemars = { version = "0.8.21", optional = true }
|
schemars = { version = "1.0.4", optional = true }
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -12,5 +12,5 @@ Use an exact version requirement to avoid breaking changes:
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
niri-ipc = "=0.1.10"
|
niri-ipc = "=25.5.1"
|
||||||
```
|
```
|
||||||
|
|||||||
+631
-13
@@ -1,8 +1,23 @@
|
|||||||
//! Types for communicating with niri via IPC.
|
//! Types for communicating with niri via IPC.
|
||||||
//!
|
//!
|
||||||
//! After connecting to the niri socket, you can send a single [`Request`] and receive a single
|
//! After connecting to the niri socket, you can send [`Request`]s. Niri will process them one by
|
||||||
//! [`Reply`], which is a `Result` wrapping a [`Response`]. If you requested an event stream, you
|
//! one, in order, and to each request it will respond with a single [`Reply`], which is a `Result`
|
||||||
//! can keep reading [`Event`]s from the socket after the response.
|
//! 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,
|
//! 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,
|
//! 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
|
//! 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.
|
//! 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`].
|
//! 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.
|
//! on a single line each.
|
||||||
//!
|
//!
|
||||||
//! ## Backwards compatibility
|
//! ## Backwards compatibility
|
||||||
@@ -24,7 +41,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ```toml
|
//! ```toml
|
||||||
//! [dependencies]
|
//! [dependencies]
|
||||||
//! niri-ipc = "=0.1.10"
|
//! niri-ipc = "=25.5.1"
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Features
|
//! ## Features
|
||||||
@@ -55,12 +72,18 @@ pub enum Request {
|
|||||||
Workspaces,
|
Workspaces,
|
||||||
/// Request information about open windows.
|
/// Request information about open windows.
|
||||||
Windows,
|
Windows,
|
||||||
|
/// Request information about layer-shell surfaces.
|
||||||
|
Layers,
|
||||||
/// Request information about the configured keyboard layouts.
|
/// Request information about the configured keyboard layouts.
|
||||||
KeyboardLayouts,
|
KeyboardLayouts,
|
||||||
/// Request information about the focused output.
|
/// Request information about the focused output.
|
||||||
FocusedOutput,
|
FocusedOutput,
|
||||||
/// Request information about the focused window.
|
/// Request information about the focused window.
|
||||||
FocusedWindow,
|
FocusedWindow,
|
||||||
|
/// Request picking a window and get its information.
|
||||||
|
PickWindow,
|
||||||
|
/// Request picking a color from the screen.
|
||||||
|
PickColor,
|
||||||
/// Perform an action.
|
/// Perform an action.
|
||||||
Action(Action),
|
Action(Action),
|
||||||
/// Change output configuration temporarily.
|
/// Change output configuration temporarily.
|
||||||
@@ -91,6 +114,8 @@ pub enum Request {
|
|||||||
EventStream,
|
EventStream,
|
||||||
/// Respond with an error (for testing error handling).
|
/// Respond with an error (for testing error handling).
|
||||||
ReturnError,
|
ReturnError,
|
||||||
|
/// Request information about the overview.
|
||||||
|
OverviewState,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reply from niri to client.
|
/// Reply from niri to client.
|
||||||
@@ -119,14 +144,38 @@ pub enum Response {
|
|||||||
Workspaces(Vec<Workspace>),
|
Workspaces(Vec<Workspace>),
|
||||||
/// Information about open windows.
|
/// Information about open windows.
|
||||||
Windows(Vec<Window>),
|
Windows(Vec<Window>),
|
||||||
|
/// Information about layer-shell surfaces.
|
||||||
|
Layers(Vec<LayerSurface>),
|
||||||
/// Information about the keyboard layout.
|
/// Information about the keyboard layout.
|
||||||
KeyboardLayouts(KeyboardLayouts),
|
KeyboardLayouts(KeyboardLayouts),
|
||||||
/// Information about the focused output.
|
/// Information about the focused output.
|
||||||
FocusedOutput(Option<Output>),
|
FocusedOutput(Option<Output>),
|
||||||
/// Information about the focused window.
|
/// Information about the focused window.
|
||||||
FocusedWindow(Option<Window>),
|
FocusedWindow(Option<Window>),
|
||||||
|
/// Information about the picked window.
|
||||||
|
PickedWindow(Option<Window>),
|
||||||
|
/// Information about the picked color.
|
||||||
|
PickedColor(Option<PickedColor>),
|
||||||
/// Output configuration change result.
|
/// Output configuration change result.
|
||||||
OutputConfigChanged(OutputConfigChanged),
|
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.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||||
|
pub struct PickedColor {
|
||||||
|
/// Color values as red, green, blue, each ranging from 0.0 to 1.0.
|
||||||
|
pub rgb: [f64; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Actions that niri can perform.
|
/// Actions that niri can perform.
|
||||||
@@ -154,6 +203,12 @@ pub enum Action {
|
|||||||
#[cfg_attr(feature = "clap", arg(last = true, required = true))]
|
#[cfg_attr(feature = "clap", arg(last = true, required = true))]
|
||||||
command: Vec<String>,
|
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.
|
/// Do a screen transition.
|
||||||
DoScreenTransition {
|
DoScreenTransition {
|
||||||
/// Delay in milliseconds for the screen to freeze before starting the transition.
|
/// Delay in milliseconds for the screen to freeze before starting the transition.
|
||||||
@@ -161,9 +216,23 @@ pub enum Action {
|
|||||||
delay_ms: Option<u16>,
|
delay_ms: Option<u16>,
|
||||||
},
|
},
|
||||||
/// Open the screenshot UI.
|
/// Open the screenshot UI.
|
||||||
Screenshot {},
|
Screenshot {
|
||||||
|
/// Whether to show the mouse pointer by default in the screenshot UI.
|
||||||
|
#[cfg_attr(feature = "clap", arg(short = 'p', long, action = clap::ArgAction::Set, default_value_t = true))]
|
||||||
|
show_pointer: bool,
|
||||||
|
},
|
||||||
/// Screenshot the focused screen.
|
/// Screenshot the focused screen.
|
||||||
ScreenshotScreen {},
|
ScreenshotScreen {
|
||||||
|
/// Write the screenshot to disk in addition to putting it in your clipboard.
|
||||||
|
///
|
||||||
|
/// The screenshot is saved according to the `screenshot-path` config setting.
|
||||||
|
#[cfg_attr(feature = "clap", arg(short = 'd', long, action = clap::ArgAction::Set, default_value_t = true))]
|
||||||
|
write_to_disk: bool,
|
||||||
|
|
||||||
|
/// Whether to include the mouse pointer in the screenshot.
|
||||||
|
#[cfg_attr(feature = "clap", arg(short = 'p', long, action = clap::ArgAction::Set, default_value_t = true))]
|
||||||
|
show_pointer: bool,
|
||||||
|
},
|
||||||
/// Screenshot a window.
|
/// Screenshot a window.
|
||||||
#[cfg_attr(feature = "clap", clap(about = "Screenshot the focused window"))]
|
#[cfg_attr(feature = "clap", clap(about = "Screenshot the focused window"))]
|
||||||
ScreenshotWindow {
|
ScreenshotWindow {
|
||||||
@@ -172,7 +241,14 @@ pub enum Action {
|
|||||||
/// If `None`, uses the focused window.
|
/// If `None`, uses the focused window.
|
||||||
#[cfg_attr(feature = "clap", arg(long))]
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
id: Option<u64>,
|
id: Option<u64>,
|
||||||
|
/// Write the screenshot to disk in addition to putting it in your clipboard.
|
||||||
|
///
|
||||||
|
/// The screenshot is saved according to the `screenshot-path` config setting.
|
||||||
|
#[cfg_attr(feature = "clap", arg(short = 'd', long, action = clap::ArgAction::Set, default_value_t = true))]
|
||||||
|
write_to_disk: bool,
|
||||||
},
|
},
|
||||||
|
/// Enable or disable the keyboard shortcuts inhibitor (if any) for the focused surface.
|
||||||
|
ToggleKeyboardShortcutsInhibit {},
|
||||||
/// Close a window.
|
/// Close a window.
|
||||||
#[cfg_attr(feature = "clap", clap(about = "Close the focused window"))]
|
#[cfg_attr(feature = "clap", clap(about = "Close the focused window"))]
|
||||||
CloseWindow {
|
CloseWindow {
|
||||||
@@ -194,12 +270,34 @@ pub enum Action {
|
|||||||
#[cfg_attr(feature = "clap", arg(long))]
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
id: Option<u64>,
|
id: Option<u64>,
|
||||||
},
|
},
|
||||||
|
/// Toggle windowed (fake) fullscreen on a window.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Toggle windowed (fake) fullscreen on the focused window")
|
||||||
|
)]
|
||||||
|
ToggleWindowedFullscreen {
|
||||||
|
/// Id of the window to toggle windowed fullscreen of.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
},
|
||||||
/// Focus a window by id.
|
/// Focus a window by id.
|
||||||
FocusWindow {
|
FocusWindow {
|
||||||
/// Id of the window to focus.
|
/// Id of the window to focus.
|
||||||
#[cfg_attr(feature = "clap", arg(long))]
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
id: u64,
|
id: u64,
|
||||||
},
|
},
|
||||||
|
/// Focus a window in the focused column by index.
|
||||||
|
FocusWindowInColumn {
|
||||||
|
/// Index of the window in the column.
|
||||||
|
///
|
||||||
|
/// The index starts from 1 for the topmost window.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
index: u8,
|
||||||
|
},
|
||||||
|
/// Focus the previously focused window.
|
||||||
|
FocusWindowPrevious {},
|
||||||
/// Focus the column to the left.
|
/// Focus the column to the left.
|
||||||
FocusColumnLeft {},
|
FocusColumnLeft {},
|
||||||
/// Focus the column to the right.
|
/// Focus the column to the right.
|
||||||
@@ -212,6 +310,14 @@ pub enum Action {
|
|||||||
FocusColumnRightOrFirst {},
|
FocusColumnRightOrFirst {},
|
||||||
/// Focus the next column to the left, looping if at start.
|
/// Focus the next column to the left, looping if at start.
|
||||||
FocusColumnLeftOrLast {},
|
FocusColumnLeftOrLast {},
|
||||||
|
/// Focus a column by index.
|
||||||
|
FocusColumn {
|
||||||
|
/// Index of the column to focus.
|
||||||
|
///
|
||||||
|
/// The index starts from 1 for the first column.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
index: usize,
|
||||||
|
},
|
||||||
/// Focus the window or the monitor above.
|
/// Focus the window or the monitor above.
|
||||||
FocusWindowOrMonitorUp {},
|
FocusWindowOrMonitorUp {},
|
||||||
/// Focus the window or the monitor below.
|
/// Focus the window or the monitor below.
|
||||||
@@ -232,10 +338,18 @@ pub enum Action {
|
|||||||
FocusWindowUpOrColumnLeft {},
|
FocusWindowUpOrColumnLeft {},
|
||||||
/// Focus the window above or the column to the right.
|
/// Focus the window above or the column to the right.
|
||||||
FocusWindowUpOrColumnRight {},
|
FocusWindowUpOrColumnRight {},
|
||||||
/// Focus the window or the workspace above.
|
/// Focus the window or the workspace below.
|
||||||
FocusWindowOrWorkspaceDown {},
|
FocusWindowOrWorkspaceDown {},
|
||||||
/// Focus the window or the workspace above.
|
/// Focus the window or the workspace above.
|
||||||
FocusWindowOrWorkspaceUp {},
|
FocusWindowOrWorkspaceUp {},
|
||||||
|
/// Focus the topmost window.
|
||||||
|
FocusWindowTop {},
|
||||||
|
/// Focus the bottommost window.
|
||||||
|
FocusWindowBottom {},
|
||||||
|
/// Focus the window below or the topmost window.
|
||||||
|
FocusWindowDownOrTop {},
|
||||||
|
/// Focus the window above or the bottommost window.
|
||||||
|
FocusWindowUpOrBottom {},
|
||||||
/// Move the focused column to the left.
|
/// Move the focused column to the left.
|
||||||
MoveColumnLeft {},
|
MoveColumnLeft {},
|
||||||
/// Move the focused column to the right.
|
/// Move the focused column to the right.
|
||||||
@@ -248,6 +362,14 @@ pub enum Action {
|
|||||||
MoveColumnLeftOrToMonitorLeft {},
|
MoveColumnLeftOrToMonitorLeft {},
|
||||||
/// Move the focused column to the right or to the monitor to the right.
|
/// Move the focused column to the right or to the monitor to the right.
|
||||||
MoveColumnRightOrToMonitorRight {},
|
MoveColumnRightOrToMonitorRight {},
|
||||||
|
/// Move the focused column to a specific index on its workspace.
|
||||||
|
MoveColumnToIndex {
|
||||||
|
/// New index for the column.
|
||||||
|
///
|
||||||
|
/// The index starts from 1 for the first column.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
index: usize,
|
||||||
|
},
|
||||||
/// Move the focused window down in a column.
|
/// Move the focused window down in a column.
|
||||||
MoveWindowDown {},
|
MoveWindowDown {},
|
||||||
/// Move the focused window up in a column.
|
/// Move the focused window up in a column.
|
||||||
@@ -284,8 +406,34 @@ pub enum Action {
|
|||||||
ConsumeWindowIntoColumn {},
|
ConsumeWindowIntoColumn {},
|
||||||
/// Expel the focused window from the column.
|
/// Expel the focused window from the column.
|
||||||
ExpelWindowFromColumn {},
|
ExpelWindowFromColumn {},
|
||||||
|
/// Swap focused window with one to the right.
|
||||||
|
SwapWindowRight {},
|
||||||
|
/// Swap focused window with one to the left.
|
||||||
|
SwapWindowLeft {},
|
||||||
|
/// Toggle the focused column between normal and tabbed display.
|
||||||
|
ToggleColumnTabbedDisplay {},
|
||||||
|
/// Set the display mode of the focused column.
|
||||||
|
SetColumnDisplay {
|
||||||
|
/// Display mode to set.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
display: ColumnDisplay,
|
||||||
|
},
|
||||||
/// Center the focused column on the screen.
|
/// Center the focused column on the screen.
|
||||||
CenterColumn {},
|
CenterColumn {},
|
||||||
|
/// Center a window on the screen.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Center the focused window on the screen")
|
||||||
|
)]
|
||||||
|
CenterWindow {
|
||||||
|
/// Id of the window to center.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
},
|
||||||
|
/// Center all fully visible columns on the screen.
|
||||||
|
CenterVisibleColumns {},
|
||||||
/// Focus the workspace below.
|
/// Focus the workspace below.
|
||||||
FocusWorkspaceDown {},
|
FocusWorkspaceDown {},
|
||||||
/// Focus the workspace above.
|
/// Focus the workspace above.
|
||||||
@@ -317,21 +465,94 @@ pub enum Action {
|
|||||||
/// Reference (index or name) of the workspace to move the window to.
|
/// Reference (index or name) of the workspace to move the window to.
|
||||||
#[cfg_attr(feature = "clap", arg())]
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
reference: WorkspaceReferenceArg,
|
reference: WorkspaceReferenceArg,
|
||||||
|
|
||||||
|
/// Whether the focus should follow the moved window.
|
||||||
|
///
|
||||||
|
/// If `true` (the default) and the window to move is focused, the focus will follow the
|
||||||
|
/// window 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 below.
|
/// 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.
|
/// 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).
|
/// Move the focused column to a workspace by reference (index or name).
|
||||||
MoveColumnToWorkspace {
|
MoveColumnToWorkspace {
|
||||||
/// Reference (index or name) of the workspace to move the column to.
|
/// Reference (index or name) of the workspace to move the column to.
|
||||||
#[cfg_attr(feature = "clap", arg())]
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
reference: WorkspaceReferenceArg,
|
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.
|
/// Move the focused workspace down.
|
||||||
MoveWorkspaceDown {},
|
MoveWorkspaceDown {},
|
||||||
/// Move the focused workspace up.
|
/// Move the focused workspace up.
|
||||||
MoveWorkspaceUp {},
|
MoveWorkspaceUp {},
|
||||||
|
/// Move a workspace to a specific index on its monitor.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Move the focused workspace to a specific index on its monitor")
|
||||||
|
)]
|
||||||
|
MoveWorkspaceToIndex {
|
||||||
|
/// New index for the workspace.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
index: usize,
|
||||||
|
|
||||||
|
/// Reference (index or name) of the workspace to move.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused workspace.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
reference: Option<WorkspaceReferenceArg>,
|
||||||
|
},
|
||||||
|
/// Set the name of a workspace.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Set the name of the focused workspace")
|
||||||
|
)]
|
||||||
|
SetWorkspaceName {
|
||||||
|
/// New name for the workspace.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
name: String,
|
||||||
|
|
||||||
|
/// Reference (index or name) of the workspace to name.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused workspace.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
workspace: Option<WorkspaceReferenceArg>,
|
||||||
|
},
|
||||||
|
/// Unset the name of a workspace.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Unset the name of the focused workspace")
|
||||||
|
)]
|
||||||
|
UnsetWorkspaceName {
|
||||||
|
/// Reference (index or name) of the workspace to unname.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused workspace.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
reference: Option<WorkspaceReferenceArg>,
|
||||||
|
},
|
||||||
/// Focus the monitor to the left.
|
/// Focus the monitor to the left.
|
||||||
FocusMonitorLeft {},
|
FocusMonitorLeft {},
|
||||||
/// Focus the monitor to the right.
|
/// Focus the monitor to the right.
|
||||||
@@ -340,6 +561,16 @@ pub enum Action {
|
|||||||
FocusMonitorDown {},
|
FocusMonitorDown {},
|
||||||
/// Focus the monitor above.
|
/// Focus the monitor above.
|
||||||
FocusMonitorUp {},
|
FocusMonitorUp {},
|
||||||
|
/// Focus the previous monitor.
|
||||||
|
FocusMonitorPrevious {},
|
||||||
|
/// Focus the next monitor.
|
||||||
|
FocusMonitorNext {},
|
||||||
|
/// Focus a monitor by name.
|
||||||
|
FocusMonitor {
|
||||||
|
/// Name of the output to focus.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
output: String,
|
||||||
|
},
|
||||||
/// Move the focused window to the monitor to the left.
|
/// Move the focused window to the monitor to the left.
|
||||||
MoveWindowToMonitorLeft {},
|
MoveWindowToMonitorLeft {},
|
||||||
/// Move the focused window to the monitor to the right.
|
/// Move the focused window to the monitor to the right.
|
||||||
@@ -348,6 +579,26 @@ pub enum Action {
|
|||||||
MoveWindowToMonitorDown {},
|
MoveWindowToMonitorDown {},
|
||||||
/// Move the focused window to the monitor above.
|
/// Move the focused window to the monitor above.
|
||||||
MoveWindowToMonitorUp {},
|
MoveWindowToMonitorUp {},
|
||||||
|
/// Move the focused window to the previous monitor.
|
||||||
|
MoveWindowToMonitorPrevious {},
|
||||||
|
/// Move the focused window to the next monitor.
|
||||||
|
MoveWindowToMonitorNext {},
|
||||||
|
/// Move a window to a specific monitor.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Move the focused window to a specific monitor")
|
||||||
|
)]
|
||||||
|
MoveWindowToMonitor {
|
||||||
|
/// Id of the window to move.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
|
||||||
|
/// The target output name.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
output: String,
|
||||||
|
},
|
||||||
/// Move the focused column to the monitor to the left.
|
/// Move the focused column to the monitor to the left.
|
||||||
MoveColumnToMonitorLeft {},
|
MoveColumnToMonitorLeft {},
|
||||||
/// Move the focused column to the monitor to the right.
|
/// Move the focused column to the monitor to the right.
|
||||||
@@ -356,6 +607,32 @@ pub enum Action {
|
|||||||
MoveColumnToMonitorDown {},
|
MoveColumnToMonitorDown {},
|
||||||
/// Move the focused column to the monitor above.
|
/// Move the focused column to the monitor above.
|
||||||
MoveColumnToMonitorUp {},
|
MoveColumnToMonitorUp {},
|
||||||
|
/// Move the focused column to the previous monitor.
|
||||||
|
MoveColumnToMonitorPrevious {},
|
||||||
|
/// Move the focused column to the next monitor.
|
||||||
|
MoveColumnToMonitorNext {},
|
||||||
|
/// Move the focused column to a specific monitor.
|
||||||
|
MoveColumnToMonitor {
|
||||||
|
/// The target output name.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
output: String,
|
||||||
|
},
|
||||||
|
/// Change the width of a window.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Change the width of the focused window")
|
||||||
|
)]
|
||||||
|
SetWindowWidth {
|
||||||
|
/// Id of the window whose width to set.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
|
||||||
|
/// How to change the width.
|
||||||
|
#[cfg_attr(feature = "clap", arg(allow_hyphen_values = true))]
|
||||||
|
change: SizeChange,
|
||||||
|
},
|
||||||
/// Change the height of a window.
|
/// Change the height of a window.
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "clap",
|
feature = "clap",
|
||||||
@@ -369,7 +646,7 @@ pub enum Action {
|
|||||||
id: Option<u64>,
|
id: Option<u64>,
|
||||||
|
|
||||||
/// How to change the height.
|
/// How to change the height.
|
||||||
#[cfg_attr(feature = "clap", arg())]
|
#[cfg_attr(feature = "clap", arg(allow_hyphen_values = true))]
|
||||||
change: SizeChange,
|
change: SizeChange,
|
||||||
},
|
},
|
||||||
/// Reset the height of a window back to automatic.
|
/// Reset the height of a window back to automatic.
|
||||||
@@ -386,6 +663,14 @@ pub enum Action {
|
|||||||
},
|
},
|
||||||
/// Switch between preset column widths.
|
/// Switch between preset column widths.
|
||||||
SwitchPresetColumnWidth {},
|
SwitchPresetColumnWidth {},
|
||||||
|
/// Switch between preset window widths.
|
||||||
|
SwitchPresetWindowWidth {
|
||||||
|
/// Id of the window whose width to switch.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
},
|
||||||
/// Switch between preset window heights.
|
/// Switch between preset window heights.
|
||||||
SwitchPresetWindowHeight {
|
SwitchPresetWindowHeight {
|
||||||
/// Id of the window whose height to switch.
|
/// Id of the window whose height to switch.
|
||||||
@@ -399,9 +684,11 @@ pub enum Action {
|
|||||||
/// Change the width of the focused column.
|
/// Change the width of the focused column.
|
||||||
SetColumnWidth {
|
SetColumnWidth {
|
||||||
/// How to change the width.
|
/// How to change the width.
|
||||||
#[cfg_attr(feature = "clap", arg())]
|
#[cfg_attr(feature = "clap", arg(allow_hyphen_values = true))]
|
||||||
change: SizeChange,
|
change: SizeChange,
|
||||||
},
|
},
|
||||||
|
/// Expand the focused column to space not taken up by other fully visible columns.
|
||||||
|
ExpandColumnToAvailableWidth {},
|
||||||
/// Switch between keyboard layouts.
|
/// Switch between keyboard layouts.
|
||||||
SwitchLayout {
|
SwitchLayout {
|
||||||
/// Layout to switch to.
|
/// Layout to switch to.
|
||||||
@@ -418,12 +705,152 @@ pub enum Action {
|
|||||||
MoveWorkspaceToMonitorDown {},
|
MoveWorkspaceToMonitorDown {},
|
||||||
/// Move the focused workspace to the monitor above.
|
/// Move the focused workspace to the monitor above.
|
||||||
MoveWorkspaceToMonitorUp {},
|
MoveWorkspaceToMonitorUp {},
|
||||||
|
/// Move the focused workspace to the previous monitor.
|
||||||
|
MoveWorkspaceToMonitorPrevious {},
|
||||||
|
/// Move the focused workspace to the next monitor.
|
||||||
|
MoveWorkspaceToMonitorNext {},
|
||||||
|
/// Move a workspace to a specific monitor.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Move the focused workspace to a specific monitor")
|
||||||
|
)]
|
||||||
|
MoveWorkspaceToMonitor {
|
||||||
|
/// The target output name.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
output: String,
|
||||||
|
|
||||||
|
// Reference (index or name) of the workspace to move.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused workspace.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
reference: Option<WorkspaceReferenceArg>,
|
||||||
|
},
|
||||||
/// Toggle a debug tint on windows.
|
/// Toggle a debug tint on windows.
|
||||||
ToggleDebugTint {},
|
ToggleDebugTint {},
|
||||||
/// Toggle visualization of render element opaque regions.
|
/// Toggle visualization of render element opaque regions.
|
||||||
DebugToggleOpaqueRegions {},
|
DebugToggleOpaqueRegions {},
|
||||||
/// Toggle visualization of output damage.
|
/// Toggle visualization of output damage.
|
||||||
DebugToggleDamage {},
|
DebugToggleDamage {},
|
||||||
|
/// Move the focused window between the floating and the tiling layout.
|
||||||
|
ToggleWindowFloating {
|
||||||
|
/// Id of the window to move.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
},
|
||||||
|
/// Move the focused window to the floating layout.
|
||||||
|
MoveWindowToFloating {
|
||||||
|
/// Id of the window to move.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
},
|
||||||
|
/// Move the focused window to the tiling layout.
|
||||||
|
MoveWindowToTiling {
|
||||||
|
/// Id of the window to move.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
},
|
||||||
|
/// Switches focus to the floating layout.
|
||||||
|
FocusFloating {},
|
||||||
|
/// Switches focus to the tiling layout.
|
||||||
|
FocusTiling {},
|
||||||
|
/// Toggles the focus between the floating and the tiling layout.
|
||||||
|
SwitchFocusBetweenFloatingAndTiling {},
|
||||||
|
/// Move a floating window on screen.
|
||||||
|
#[cfg_attr(feature = "clap", clap(about = "Move the floating window on screen"))]
|
||||||
|
MoveFloatingWindow {
|
||||||
|
/// Id of the window to move.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
|
||||||
|
/// How to change the X position.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
arg(short, long, default_value = "+0", allow_negative_numbers = true)
|
||||||
|
)]
|
||||||
|
x: PositionChange,
|
||||||
|
|
||||||
|
/// How to change the Y position.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
arg(short, long, default_value = "+0", allow_negative_numbers = true)
|
||||||
|
)]
|
||||||
|
y: PositionChange,
|
||||||
|
},
|
||||||
|
/// Toggle the opacity of a window.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Toggle the opacity of the focused window")
|
||||||
|
)]
|
||||||
|
ToggleWindowRuleOpacity {
|
||||||
|
/// Id of the window.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
},
|
||||||
|
/// Set the dynamic cast target to a window.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Set the dynamic cast target to the focused window")
|
||||||
|
)]
|
||||||
|
SetDynamicCastWindow {
|
||||||
|
/// Id of the window to target.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused window.
|
||||||
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
|
id: Option<u64>,
|
||||||
|
},
|
||||||
|
/// Set the dynamic cast target to a monitor.
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "clap",
|
||||||
|
clap(about = "Set the dynamic cast target to the focused monitor")
|
||||||
|
)]
|
||||||
|
SetDynamicCastMonitor {
|
||||||
|
/// Name of the output to target.
|
||||||
|
///
|
||||||
|
/// If `None`, uses the focused output.
|
||||||
|
#[cfg_attr(feature = "clap", arg())]
|
||||||
|
output: Option<String>,
|
||||||
|
},
|
||||||
|
/// 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.
|
/// Change in window or column size.
|
||||||
@@ -440,6 +867,16 @@ pub enum SizeChange {
|
|||||||
AdjustProportion(f64),
|
AdjustProportion(f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Change in floating window position.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||||
|
pub enum PositionChange {
|
||||||
|
/// Set the position in logical pixels.
|
||||||
|
SetFixed(f64),
|
||||||
|
/// Add or subtract to the current position in logical pixels.
|
||||||
|
AdjustFixed(f64),
|
||||||
|
}
|
||||||
|
|
||||||
/// Workspace reference (id, index or name) to operate on.
|
/// Workspace reference (id, index or name) to operate on.
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||||
@@ -460,6 +897,18 @@ pub enum LayoutSwitchTarget {
|
|||||||
Next,
|
Next,
|
||||||
/// The previous configured layout.
|
/// The previous configured layout.
|
||||||
Prev,
|
Prev,
|
||||||
|
/// The specific layout by index.
|
||||||
|
Index(u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// How windows display in a column.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||||
|
pub enum ColumnDisplay {
|
||||||
|
/// Windows are tiled vertically across the working area height.
|
||||||
|
Normal,
|
||||||
|
/// Windows are in tabs.
|
||||||
|
Tabbed,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Output actions that niri can perform.
|
/// Output actions that niri can perform.
|
||||||
@@ -695,12 +1144,71 @@ pub struct Window {
|
|||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
/// Application ID, if set.
|
/// Application ID, if set.
|
||||||
pub app_id: Option<String>,
|
pub app_id: Option<String>,
|
||||||
|
/// Process ID that created the Wayland connection for this window, if known.
|
||||||
|
///
|
||||||
|
/// Currently, windows created by xdg-desktop-portal-gnome will have a `None` PID, but this may
|
||||||
|
/// change in the future.
|
||||||
|
pub pid: Option<i32>,
|
||||||
/// Id of the workspace this window is on, if any.
|
/// Id of the workspace this window is on, if any.
|
||||||
pub workspace_id: Option<u64>,
|
pub workspace_id: Option<u64>,
|
||||||
/// Whether this window is currently focused.
|
/// Whether this window is currently focused.
|
||||||
///
|
///
|
||||||
/// There can be either one focused window or zero (e.g. when a layer-shell surface has focus).
|
/// There can be either one focused window or zero (e.g. when a layer-shell surface has focus).
|
||||||
pub is_focused: bool,
|
pub is_focused: bool,
|
||||||
|
/// Whether this window is currently floating.
|
||||||
|
///
|
||||||
|
/// 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.
|
/// Output configuration change result.
|
||||||
@@ -740,6 +1248,8 @@ pub struct Workspace {
|
|||||||
///
|
///
|
||||||
/// Can be `None` if no outputs are currently connected.
|
/// Can be `None` if no outputs are currently connected.
|
||||||
pub output: Option<String>,
|
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.
|
/// Whether the workspace is currently active on its output.
|
||||||
///
|
///
|
||||||
/// Every output has one active workspace, the one that is currently visible on that output.
|
/// Every output has one active workspace, the one that is currently visible on that output.
|
||||||
@@ -762,6 +1272,46 @@ pub struct KeyboardLayouts {
|
|||||||
pub current_idx: u8,
|
pub current_idx: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A layer-shell layer.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||||
|
pub enum Layer {
|
||||||
|
/// The background layer.
|
||||||
|
Background,
|
||||||
|
/// The bottom layer.
|
||||||
|
Bottom,
|
||||||
|
/// The top layer.
|
||||||
|
Top,
|
||||||
|
/// The overlay layer.
|
||||||
|
Overlay,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Keyboard interactivity modes for a layer-shell surface.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||||
|
pub enum LayerSurfaceKeyboardInteractivity {
|
||||||
|
/// Surface cannot receive keyboard focus.
|
||||||
|
None,
|
||||||
|
/// Surface receives keyboard focus whenever possible.
|
||||||
|
Exclusive,
|
||||||
|
/// Surface receives keyboard focus on demand, e.g. when clicked.
|
||||||
|
OnDemand,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A layer-shell surface.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||||
|
pub struct LayerSurface {
|
||||||
|
/// Namespace provided by the layer-shell client.
|
||||||
|
pub namespace: String,
|
||||||
|
/// Name of the output the surface is on.
|
||||||
|
pub output: String,
|
||||||
|
/// Layer that the surface is on.
|
||||||
|
pub layer: Layer,
|
||||||
|
/// The surface's keyboard interactivity mode.
|
||||||
|
pub keyboard_interactivity: LayerSurfaceKeyboardInteractivity,
|
||||||
|
}
|
||||||
|
|
||||||
/// A compositor event.
|
/// A compositor event.
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||||
@@ -774,6 +1324,13 @@ pub enum Event {
|
|||||||
/// workspaces are missing from here, then they were deleted.
|
/// workspaces are missing from here, then they were deleted.
|
||||||
workspaces: Vec<Workspace>,
|
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.
|
/// A workspace was activated on an output.
|
||||||
///
|
///
|
||||||
/// This doesn't always mean the workspace became focused, just that it's now the active
|
/// This doesn't always mean the workspace became focused, just that it's now the active
|
||||||
@@ -821,6 +1378,18 @@ pub enum Event {
|
|||||||
/// Id of the newly focused window, or `None` if no window is now focused.
|
/// Id of the newly focused window, or `None` if no window is now focused.
|
||||||
id: Option<u64>,
|
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.
|
/// The configured keyboard layouts have changed.
|
||||||
KeyboardLayoutsChanged {
|
KeyboardLayoutsChanged {
|
||||||
/// The new keyboard layout configuration.
|
/// The new keyboard layout configuration.
|
||||||
@@ -831,6 +1400,21 @@ pub enum Event {
|
|||||||
/// Index of the newly active layout.
|
/// Index of the newly active layout.
|
||||||
idx: u8,
|
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 {
|
impl FromStr for WorkspaceReferenceArg {
|
||||||
@@ -891,6 +1475,25 @@ impl FromStr for SizeChange {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for PositionChange {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let value = s;
|
||||||
|
match value.bytes().next() {
|
||||||
|
Some(b'-' | b'+') => {
|
||||||
|
let value = value.parse().map_err(|_| "error parsing value")?;
|
||||||
|
Ok(Self::AdjustFixed(value))
|
||||||
|
}
|
||||||
|
Some(_) => {
|
||||||
|
let value = value.parse().map_err(|_| "error parsing value")?;
|
||||||
|
Ok(Self::SetFixed(value))
|
||||||
|
}
|
||||||
|
None => Err("value is missing"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for LayoutSwitchTarget {
|
impl FromStr for LayoutSwitchTarget {
|
||||||
type Err = &'static str;
|
type Err = &'static str;
|
||||||
|
|
||||||
@@ -898,7 +1501,22 @@ impl FromStr for LayoutSwitchTarget {
|
|||||||
match s {
|
match s {
|
||||||
"next" => Ok(Self::Next),
|
"next" => Ok(Self::Next),
|
||||||
"prev" => Ok(Self::Prev),
|
"prev" => Ok(Self::Prev),
|
||||||
_ => Err(r#"invalid layout action, can be "next" or "prev""#),
|
other => match other.parse() {
|
||||||
|
Ok(layout) => Ok(Self::Index(layout)),
|
||||||
|
_ => Err(r#"invalid layout action, can be "next", "prev" or a layout index"#),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for ColumnDisplay {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"normal" => Ok(Self::Normal),
|
||||||
|
"tabbed" => Ok(Self::Tabbed),
|
||||||
|
_ => Err(r#"invalid column display, can be "normal" or "tabbed""#),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-18
@@ -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
|
/// This struct is used to communicate with the niri IPC server. It handles the socket connection
|
||||||
/// and serialization/deserialization of messages.
|
/// and serialization/deserialization of messages.
|
||||||
pub struct Socket {
|
pub struct Socket {
|
||||||
stream: UnixStream,
|
stream: BufReader<UnixStream>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Socket {
|
impl Socket {
|
||||||
@@ -37,6 +37,7 @@ impl Socket {
|
|||||||
/// Connects to the niri IPC socket at the given path.
|
/// Connects to the niri IPC socket at the given path.
|
||||||
pub fn connect_to(path: impl AsRef<Path>) -> io::Result<Self> {
|
pub fn connect_to(path: impl AsRef<Path>) -> io::Result<Self> {
|
||||||
let stream = UnixStream::connect(path.as_ref())?;
|
let stream = UnixStream::connect(path.as_ref())?;
|
||||||
|
let stream = BufReader::new(stream);
|
||||||
Ok(Self { stream })
|
Ok(Self { stream })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,31 +48,54 @@ impl Socket {
|
|||||||
/// * `Ok(Ok(response))`: successful [`Response`](crate::Response) from niri
|
/// * `Ok(Ok(response))`: successful [`Response`](crate::Response) from niri
|
||||||
/// * `Ok(Err(message))`: error message from niri
|
/// * `Ok(Err(message))`: error message from niri
|
||||||
/// * `Err(error)`: error communicating with niri
|
/// * `Err(error)`: error communicating with niri
|
||||||
///
|
pub fn send(&mut self, request: Request) -> io::Result<Reply> {
|
||||||
/// 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;
|
|
||||||
|
|
||||||
let mut buf = serde_json::to_string(&request).unwrap();
|
let mut buf = serde_json::to_string(&request).unwrap();
|
||||||
stream.write_all(buf.as_bytes())?;
|
buf.push('\n');
|
||||||
stream.shutdown(Shutdown::Write)?;
|
self.stream.get_mut().write_all(buf.as_bytes())?;
|
||||||
|
|
||||||
let mut reader = BufReader::new(stream);
|
|
||||||
|
|
||||||
buf.clear();
|
buf.clear();
|
||||||
reader.read_line(&mut buf)?;
|
self.stream.read_line(&mut buf)?;
|
||||||
|
|
||||||
let reply = serde_json::from_str(&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();
|
buf.clear();
|
||||||
reader.read_line(&mut buf)?;
|
stream.read_line(&mut buf)?;
|
||||||
let event = serde_json::from_str(&buf)?;
|
let event = serde_json::from_str(&buf)?;
|
||||||
Ok(event)
|
Ok(event)
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok((reply, events))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ pub struct EventStreamState {
|
|||||||
|
|
||||||
/// State of the keyboard layouts.
|
/// State of the keyboard layouts.
|
||||||
pub keyboard_layouts: KeyboardLayoutsState,
|
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.
|
/// The workspaces state communicated over the event stream.
|
||||||
@@ -63,12 +69,28 @@ pub struct KeyboardLayoutsState {
|
|||||||
pub keyboard_layouts: Option<KeyboardLayouts>,
|
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 {
|
impl EventStreamStatePart for EventStreamState {
|
||||||
fn replicate(&self) -> Vec<Event> {
|
fn replicate(&self) -> Vec<Event> {
|
||||||
let mut events = Vec::new();
|
let mut events = Vec::new();
|
||||||
events.extend(self.workspaces.replicate());
|
events.extend(self.workspaces.replicate());
|
||||||
events.extend(self.windows.replicate());
|
events.extend(self.windows.replicate());
|
||||||
events.extend(self.keyboard_layouts.replicate());
|
events.extend(self.keyboard_layouts.replicate());
|
||||||
|
events.extend(self.overview.replicate());
|
||||||
|
events.extend(self.config.replicate());
|
||||||
events
|
events
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +98,8 @@ impl EventStreamStatePart for EventStreamState {
|
|||||||
let event = self.workspaces.apply(event)?;
|
let event = self.workspaces.apply(event)?;
|
||||||
let event = self.windows.apply(event)?;
|
let event = self.windows.apply(event)?;
|
||||||
let event = self.keyboard_layouts.apply(event)?;
|
let event = self.keyboard_layouts.apply(event)?;
|
||||||
|
let event = self.overview.apply(event)?;
|
||||||
|
let event = self.config.apply(event)?;
|
||||||
Some(event)
|
Some(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,6 +115,13 @@ impl EventStreamStatePart for WorkspacesState {
|
|||||||
Event::WorkspacesChanged { workspaces } => {
|
Event::WorkspacesChanged { workspaces } => {
|
||||||
self.workspaces = workspaces.into_iter().map(|ws| (ws.id, ws)).collect();
|
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 } => {
|
Event::WorkspaceActivated { id, focused } => {
|
||||||
let ws = self.workspaces.get(&id);
|
let ws = self.workspaces.get(&id);
|
||||||
let ws = ws.expect("activated workspace was missing from the map");
|
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;
|
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),
|
event => return Some(event),
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@@ -192,3 +238,39 @@ impl EventStreamStatePart for KeyboardLayoutsState {
|
|||||||
None
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ edition.workspace = true
|
|||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
adw = { version = "0.7.1", package = "libadwaita", features = ["v1_4"] }
|
adw = { version = "0.7.2", package = "libadwaita", features = ["v1_4"] }
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
gtk = { version = "0.9.3", package = "gtk4", features = ["v4_12"] }
|
gtk = { version = "0.9.7", package = "gtk4", features = ["v4_12"] }
|
||||||
niri = { version = "0.1.10", path = ".." }
|
niri = { version = "25.5.1", path = ".." }
|
||||||
niri-config = { version = "0.1.10", path = "../niri-config" }
|
niri-config = { version = "25.5.1", path = "../niri-config" }
|
||||||
smithay.workspace = true
|
smithay.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
tracing-subscriber.workspace = true
|
tracing-subscriber.workspace = true
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
use std::f32::consts::{FRAC_PI_2, PI};
|
use std::f32::consts::{FRAC_PI_2, PI};
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use niri::animation::ANIMATION_SLOWDOWN;
|
|
||||||
use niri::render_helpers::border::BorderRenderElement;
|
use niri::render_helpers::border::BorderRenderElement;
|
||||||
use niri_config::{Color, CornerRadius, GradientInterpolation};
|
use niri_config::{Color, CornerRadius, GradientInterpolation};
|
||||||
use smithay::backend::renderer::element::RenderElement;
|
use smithay::backend::renderer::element::RenderElement;
|
||||||
use smithay::backend::renderer::gles::GlesRenderer;
|
use smithay::backend::renderer::gles::GlesRenderer;
|
||||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
use smithay::utils::{Physical, Point, Rectangle, Size};
|
||||||
|
|
||||||
use super::TestCase;
|
use super::{Args, TestCase};
|
||||||
|
|
||||||
pub struct GradientAngle {
|
pub struct GradientAngle {
|
||||||
angle: f32,
|
angle: f32,
|
||||||
@@ -17,7 +15,7 @@ pub struct GradientAngle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GradientAngle {
|
impl GradientAngle {
|
||||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
pub fn new(_args: Args) -> Self {
|
||||||
Self {
|
Self {
|
||||||
angle: 0.,
|
angle: 0.,
|
||||||
prev_time: Duration::ZERO,
|
prev_time: Duration::ZERO,
|
||||||
@@ -31,20 +29,13 @@ impl TestCase for GradientAngle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn advance_animations(&mut self, current_time: Duration) {
|
fn advance_animations(&mut self, current_time: Duration) {
|
||||||
let mut delta = if self.prev_time.is_zero() {
|
let delta = if self.prev_time.is_zero() {
|
||||||
Duration::ZERO
|
Duration::ZERO
|
||||||
} else {
|
} else {
|
||||||
current_time.saturating_sub(self.prev_time)
|
current_time.saturating_sub(self.prev_time)
|
||||||
};
|
};
|
||||||
self.prev_time = current_time;
|
self.prev_time = current_time;
|
||||||
|
|
||||||
let slowdown = ANIMATION_SLOWDOWN.load(Ordering::SeqCst);
|
|
||||||
if slowdown == 0. {
|
|
||||||
delta = Duration::ZERO
|
|
||||||
} else {
|
|
||||||
delta = delta.div_f64(slowdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.angle += delta.as_secs_f32() * PI;
|
self.angle += delta.as_secs_f32() * PI;
|
||||||
|
|
||||||
if self.angle >= PI * 2. {
|
if self.angle >= PI * 2. {
|
||||||
@@ -59,19 +50,20 @@ impl TestCase for GradientAngle {
|
|||||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||||
let (a, b) = (size.w / 4, size.h / 4);
|
let (a, b) = (size.w / 4, size.h / 4);
|
||||||
let size = (size.w - a * 2, size.h - b * 2);
|
let size = (size.w - a * 2, size.h - b * 2);
|
||||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
let area = Rectangle::new(Point::from((a, b)), Size::from(size)).to_f64();
|
||||||
|
|
||||||
[BorderRenderElement::new(
|
[BorderRenderElement::new(
|
||||||
area.size,
|
area.size,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
GradientInterpolation::default(),
|
GradientInterpolation::default(),
|
||||||
Color::new_unpremul(1., 0., 0., 1.),
|
Color::new_unpremul(1., 0., 0., 1.),
|
||||||
Color::new_unpremul(0., 1., 0., 1.),
|
Color::new_unpremul(0., 1., 0., 1.),
|
||||||
self.angle - FRAC_PI_2,
|
self.angle - FRAC_PI_2,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
0.,
|
0.,
|
||||||
CornerRadius::default(),
|
CornerRadius::default(),
|
||||||
1.,
|
1.,
|
||||||
|
1.,
|
||||||
)
|
)
|
||||||
.with_location(area.loc)]
|
.with_location(area.loc)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
use std::f32::consts::{FRAC_PI_4, PI};
|
use std::f32::consts::{FRAC_PI_4, PI};
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use niri::animation::ANIMATION_SLOWDOWN;
|
|
||||||
use niri::layout::focus_ring::FocusRing;
|
use niri::layout::focus_ring::FocusRing;
|
||||||
use niri::render_helpers::border::BorderRenderElement;
|
use niri::render_helpers::border::BorderRenderElement;
|
||||||
use niri_config::{Color, CornerRadius, FloatOrInt, GradientInterpolation};
|
use niri_config::{Color, CornerRadius, FloatOrInt, GradientInterpolation};
|
||||||
use smithay::backend::renderer::element::RenderElement;
|
use smithay::backend::renderer::element::RenderElement;
|
||||||
use smithay::backend::renderer::gles::GlesRenderer;
|
use smithay::backend::renderer::gles::GlesRenderer;
|
||||||
use smithay::utils::{Logical, Physical, Point, Rectangle, Size};
|
use smithay::utils::{Physical, Point, Rectangle, Size};
|
||||||
|
|
||||||
use super::TestCase;
|
use super::{Args, TestCase};
|
||||||
|
|
||||||
pub struct GradientArea {
|
pub struct GradientArea {
|
||||||
progress: f32,
|
progress: f32,
|
||||||
@@ -19,14 +17,16 @@ pub struct GradientArea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GradientArea {
|
impl GradientArea {
|
||||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
pub fn new(_args: Args) -> Self {
|
||||||
let border = FocusRing::new(niri_config::FocusRing {
|
let border = FocusRing::new(niri_config::FocusRing {
|
||||||
off: false,
|
off: false,
|
||||||
width: FloatOrInt(1.),
|
width: FloatOrInt(1.),
|
||||||
active_color: Color::from_rgba8_unpremul(255, 255, 255, 128),
|
active_color: Color::from_rgba8_unpremul(255, 255, 255, 128),
|
||||||
inactive_color: Color::default(),
|
inactive_color: Color::default(),
|
||||||
|
urgent_color: Color::default(),
|
||||||
active_gradient: None,
|
active_gradient: None,
|
||||||
inactive_gradient: None,
|
inactive_gradient: None,
|
||||||
|
urgent_gradient: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@@ -43,20 +43,13 @@ impl TestCase for GradientArea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn advance_animations(&mut self, current_time: Duration) {
|
fn advance_animations(&mut self, current_time: Duration) {
|
||||||
let mut delta = if self.prev_time.is_zero() {
|
let delta = if self.prev_time.is_zero() {
|
||||||
Duration::ZERO
|
Duration::ZERO
|
||||||
} else {
|
} else {
|
||||||
current_time.saturating_sub(self.prev_time)
|
current_time.saturating_sub(self.prev_time)
|
||||||
};
|
};
|
||||||
self.prev_time = current_time;
|
self.prev_time = current_time;
|
||||||
|
|
||||||
let slowdown = ANIMATION_SLOWDOWN.load(Ordering::SeqCst);
|
|
||||||
if slowdown == 0. {
|
|
||||||
delta = Duration::ZERO
|
|
||||||
} else {
|
|
||||||
delta = delta.div_f64(slowdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.progress += delta.as_secs_f32() * PI;
|
self.progress += delta.as_secs_f32() * PI;
|
||||||
|
|
||||||
if self.progress >= PI * 2. {
|
if self.progress >= PI * 2. {
|
||||||
@@ -74,8 +67,8 @@ impl TestCase for GradientArea {
|
|||||||
let f = (self.progress.sin() + 1.) / 2.;
|
let f = (self.progress.sin() + 1.) / 2.;
|
||||||
|
|
||||||
let (a, b) = (size.w / 4, size.h / 4);
|
let (a, b) = (size.w / 4, size.h / 4);
|
||||||
let rect_size = (size.w - a * 2, size.h - b * 2);
|
let rect_size = Size::from((size.w - a * 2, size.h - b * 2));
|
||||||
let area = Rectangle::from_loc_and_size((a, b), rect_size).to_f64();
|
let area = Rectangle::new(Point::from((a, b)), rect_size).to_f64();
|
||||||
|
|
||||||
let g_size = Size::from((
|
let g_size = Size::from((
|
||||||
(size.w as f32 / 8. + size.w as f32 / 8. * 7. * f).round() as i32,
|
(size.w as f32 / 8. + size.w as f32 / 8. * 7. * f).round() as i32,
|
||||||
@@ -83,16 +76,18 @@ impl TestCase for GradientArea {
|
|||||||
));
|
));
|
||||||
let g_loc = Point::from(((size.w - g_size.w) / 2, (size.h - g_size.h) / 2)).to_f64();
|
let g_loc = Point::from(((size.w - g_size.w) / 2, (size.h - g_size.h) / 2)).to_f64();
|
||||||
let g_size = g_size.to_f64();
|
let g_size = g_size.to_f64();
|
||||||
let mut g_area = Rectangle::from_loc_and_size(g_loc, g_size);
|
let mut g_area = Rectangle::new(g_loc, g_size);
|
||||||
g_area.loc -= area.loc;
|
g_area.loc -= area.loc;
|
||||||
|
|
||||||
self.border.update_render_elements(
|
self.border.update_render_elements(
|
||||||
g_size,
|
g_size,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
Rectangle::default(),
|
Rectangle::default(),
|
||||||
CornerRadius::default(),
|
CornerRadius::default(),
|
||||||
1.,
|
1.,
|
||||||
|
1.,
|
||||||
);
|
);
|
||||||
rv.extend(
|
rv.extend(
|
||||||
self.border
|
self.border
|
||||||
@@ -108,10 +103,11 @@ impl TestCase for GradientArea {
|
|||||||
Color::new_unpremul(1., 0., 0., 1.),
|
Color::new_unpremul(1., 0., 0., 1.),
|
||||||
Color::new_unpremul(0., 1., 0., 1.),
|
Color::new_unpremul(0., 1., 0., 1.),
|
||||||
FRAC_PI_4,
|
FRAC_PI_4,
|
||||||
Rectangle::from_loc_and_size((0, 0), rect_size).to_f64(),
|
Rectangle::from_size(rect_size).to_f64(),
|
||||||
0.,
|
0.,
|
||||||
CornerRadius::default(),
|
CornerRadius::default(),
|
||||||
1.,
|
1.,
|
||||||
|
1.,
|
||||||
)
|
)
|
||||||
.with_location(area.loc)]
|
.with_location(area.loc)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ use niri_config::{
|
|||||||
};
|
};
|
||||||
use smithay::backend::renderer::element::RenderElement;
|
use smithay::backend::renderer::element::RenderElement;
|
||||||
use smithay::backend::renderer::gles::GlesRenderer;
|
use smithay::backend::renderer::gles::GlesRenderer;
|
||||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
use smithay::utils::{Physical, Point, Rectangle, Size};
|
||||||
|
|
||||||
use super::TestCase;
|
use super::{Args, TestCase};
|
||||||
|
|
||||||
pub struct GradientOklab {
|
pub struct GradientOklab {
|
||||||
gradient_format: GradientInterpolation,
|
gradient_format: GradientInterpolation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GradientOklab {
|
impl GradientOklab {
|
||||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
pub fn new(_args: Args) -> Self {
|
||||||
Self {
|
Self {
|
||||||
gradient_format: GradientInterpolation {
|
gradient_format: GradientInterpolation {
|
||||||
color_space: GradientColorSpace::Oklab,
|
color_space: GradientColorSpace::Oklab,
|
||||||
@@ -31,19 +31,20 @@ impl TestCase for GradientOklab {
|
|||||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||||
let (a, b) = (size.w / 6, size.h / 3);
|
let (a, b) = (size.w / 6, size.h / 3);
|
||||||
let size = (size.w - a * 2, size.h - b * 2);
|
let size = (size.w - a * 2, size.h - b * 2);
|
||||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
let area = Rectangle::new(Point::from((a, b)), Size::from(size)).to_f64();
|
||||||
|
|
||||||
[BorderRenderElement::new(
|
[BorderRenderElement::new(
|
||||||
area.size,
|
area.size,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
self.gradient_format,
|
self.gradient_format,
|
||||||
Color::new_unpremul(1., 0., 0., 1.),
|
Color::new_unpremul(1., 0., 0., 1.),
|
||||||
Color::new_unpremul(0., 1., 0., 1.),
|
Color::new_unpremul(0., 1., 0., 1.),
|
||||||
0.,
|
0.,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
0.,
|
0.,
|
||||||
CornerRadius::default(),
|
CornerRadius::default(),
|
||||||
1.,
|
1.,
|
||||||
|
1.,
|
||||||
)
|
)
|
||||||
.with_location(area.loc)]
|
.with_location(area.loc)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
@@ -2,16 +2,16 @@ use niri::render_helpers::border::BorderRenderElement;
|
|||||||
use niri_config::{Color, CornerRadius, GradientColorSpace, GradientInterpolation};
|
use niri_config::{Color, CornerRadius, GradientColorSpace, GradientInterpolation};
|
||||||
use smithay::backend::renderer::element::RenderElement;
|
use smithay::backend::renderer::element::RenderElement;
|
||||||
use smithay::backend::renderer::gles::GlesRenderer;
|
use smithay::backend::renderer::gles::GlesRenderer;
|
||||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
use smithay::utils::{Physical, Point, Rectangle, Size};
|
||||||
|
|
||||||
use super::TestCase;
|
use super::{Args, TestCase};
|
||||||
|
|
||||||
pub struct GradientOklabAlpha {
|
pub struct GradientOklabAlpha {
|
||||||
gradient_format: GradientInterpolation,
|
gradient_format: GradientInterpolation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GradientOklabAlpha {
|
impl GradientOklabAlpha {
|
||||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
pub fn new(_args: Args) -> Self {
|
||||||
Self {
|
Self {
|
||||||
gradient_format: GradientInterpolation {
|
gradient_format: GradientInterpolation {
|
||||||
color_space: GradientColorSpace::Oklab,
|
color_space: GradientColorSpace::Oklab,
|
||||||
@@ -29,19 +29,20 @@ impl TestCase for GradientOklabAlpha {
|
|||||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||||
let (a, b) = (size.w / 6, size.h / 3);
|
let (a, b) = (size.w / 6, size.h / 3);
|
||||||
let size = (size.w - a * 2, size.h - b * 2);
|
let size = (size.w - a * 2, size.h - b * 2);
|
||||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
let area = Rectangle::new(Point::from((a, b)), Size::from(size)).to_f64();
|
||||||
|
|
||||||
[BorderRenderElement::new(
|
[BorderRenderElement::new(
|
||||||
area.size,
|
area.size,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
self.gradient_format,
|
self.gradient_format,
|
||||||
Color::new_unpremul(1., 0., 0., 1.),
|
Color::new_unpremul(1., 0., 0., 1.),
|
||||||
Color::new_unpremul(0., 1., 0., 0.),
|
Color::new_unpremul(0., 1., 0., 0.),
|
||||||
0.,
|
0.,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
0.,
|
0.,
|
||||||
CornerRadius::default(),
|
CornerRadius::default(),
|
||||||
1.,
|
1.,
|
||||||
|
1.,
|
||||||
)
|
)
|
||||||
.with_location(area.loc)]
|
.with_location(area.loc)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ use niri_config::{
|
|||||||
};
|
};
|
||||||
use smithay::backend::renderer::element::RenderElement;
|
use smithay::backend::renderer::element::RenderElement;
|
||||||
use smithay::backend::renderer::gles::GlesRenderer;
|
use smithay::backend::renderer::gles::GlesRenderer;
|
||||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
use smithay::utils::{Physical, Point, Rectangle, Size};
|
||||||
|
|
||||||
use super::TestCase;
|
use super::{Args, TestCase};
|
||||||
|
|
||||||
pub struct GradientOklchAlpha {
|
pub struct GradientOklchAlpha {
|
||||||
gradient_format: GradientInterpolation,
|
gradient_format: GradientInterpolation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GradientOklchAlpha {
|
impl GradientOklchAlpha {
|
||||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
pub fn new(_args: Args) -> Self {
|
||||||
Self {
|
Self {
|
||||||
gradient_format: GradientInterpolation {
|
gradient_format: GradientInterpolation {
|
||||||
color_space: GradientColorSpace::Oklch,
|
color_space: GradientColorSpace::Oklch,
|
||||||
@@ -31,19 +31,20 @@ impl TestCase for GradientOklchAlpha {
|
|||||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||||
let (a, b) = (size.w / 6, size.h / 3);
|
let (a, b) = (size.w / 6, size.h / 3);
|
||||||
let size = (size.w - a * 2, size.h - b * 2);
|
let size = (size.w - a * 2, size.h - b * 2);
|
||||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
let area = Rectangle::new(Point::from((a, b)), Size::from(size)).to_f64();
|
||||||
|
|
||||||
[BorderRenderElement::new(
|
[BorderRenderElement::new(
|
||||||
area.size,
|
area.size,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
self.gradient_format,
|
self.gradient_format,
|
||||||
Color::new_unpremul(1., 0., 0., 1.),
|
Color::new_unpremul(1., 0., 0., 1.),
|
||||||
Color::new_unpremul(0., 1., 0., 0.),
|
Color::new_unpremul(0., 1., 0., 0.),
|
||||||
0.,
|
0.,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
0.,
|
0.,
|
||||||
CornerRadius::default(),
|
CornerRadius::default(),
|
||||||
1.,
|
1.,
|
||||||
|
1.,
|
||||||
)
|
)
|
||||||
.with_location(area.loc)]
|
.with_location(area.loc)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ use niri_config::{
|
|||||||
};
|
};
|
||||||
use smithay::backend::renderer::element::RenderElement;
|
use smithay::backend::renderer::element::RenderElement;
|
||||||
use smithay::backend::renderer::gles::GlesRenderer;
|
use smithay::backend::renderer::gles::GlesRenderer;
|
||||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
use smithay::utils::{Physical, Point, Rectangle, Size};
|
||||||
|
|
||||||
use super::TestCase;
|
use super::{Args, TestCase};
|
||||||
|
|
||||||
pub struct GradientOklchDecreasing {
|
pub struct GradientOklchDecreasing {
|
||||||
gradient_format: GradientInterpolation,
|
gradient_format: GradientInterpolation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GradientOklchDecreasing {
|
impl GradientOklchDecreasing {
|
||||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
pub fn new(_args: Args) -> Self {
|
||||||
Self {
|
Self {
|
||||||
gradient_format: GradientInterpolation {
|
gradient_format: GradientInterpolation {
|
||||||
color_space: GradientColorSpace::Oklch,
|
color_space: GradientColorSpace::Oklch,
|
||||||
@@ -31,19 +31,20 @@ impl TestCase for GradientOklchDecreasing {
|
|||||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||||
let (a, b) = (size.w / 6, size.h / 3);
|
let (a, b) = (size.w / 6, size.h / 3);
|
||||||
let size = (size.w - a * 2, size.h - b * 2);
|
let size = (size.w - a * 2, size.h - b * 2);
|
||||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
let area = Rectangle::new(Point::from((a, b)), Size::from(size)).to_f64();
|
||||||
|
|
||||||
[BorderRenderElement::new(
|
[BorderRenderElement::new(
|
||||||
area.size,
|
area.size,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
self.gradient_format,
|
self.gradient_format,
|
||||||
Color::new_unpremul(1., 0., 0., 1.),
|
Color::new_unpremul(1., 0., 0., 1.),
|
||||||
Color::new_unpremul(0., 1., 0., 1.),
|
Color::new_unpremul(0., 1., 0., 1.),
|
||||||
0.,
|
0.,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
0.,
|
0.,
|
||||||
CornerRadius::default(),
|
CornerRadius::default(),
|
||||||
1.,
|
1.,
|
||||||
|
1.,
|
||||||
)
|
)
|
||||||
.with_location(area.loc)]
|
.with_location(area.loc)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ use niri_config::{
|
|||||||
};
|
};
|
||||||
use smithay::backend::renderer::element::RenderElement;
|
use smithay::backend::renderer::element::RenderElement;
|
||||||
use smithay::backend::renderer::gles::GlesRenderer;
|
use smithay::backend::renderer::gles::GlesRenderer;
|
||||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
use smithay::utils::{Physical, Point, Rectangle, Size};
|
||||||
|
|
||||||
use super::TestCase;
|
use super::{Args, TestCase};
|
||||||
|
|
||||||
pub struct GradientOklchIncreasing {
|
pub struct GradientOklchIncreasing {
|
||||||
gradient_format: GradientInterpolation,
|
gradient_format: GradientInterpolation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GradientOklchIncreasing {
|
impl GradientOklchIncreasing {
|
||||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
pub fn new(_args: Args) -> Self {
|
||||||
Self {
|
Self {
|
||||||
gradient_format: GradientInterpolation {
|
gradient_format: GradientInterpolation {
|
||||||
color_space: GradientColorSpace::Oklch,
|
color_space: GradientColorSpace::Oklch,
|
||||||
@@ -31,19 +31,20 @@ impl TestCase for GradientOklchIncreasing {
|
|||||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||||
let (a, b) = (size.w / 6, size.h / 3);
|
let (a, b) = (size.w / 6, size.h / 3);
|
||||||
let size = (size.w - a * 2, size.h - b * 2);
|
let size = (size.w - a * 2, size.h - b * 2);
|
||||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
let area = Rectangle::new(Point::from((a, b)), Size::from(size)).to_f64();
|
||||||
|
|
||||||
[BorderRenderElement::new(
|
[BorderRenderElement::new(
|
||||||
area.size,
|
area.size,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
self.gradient_format,
|
self.gradient_format,
|
||||||
Color::new_unpremul(1., 0., 0., 1.),
|
Color::new_unpremul(1., 0., 0., 1.),
|
||||||
Color::new_unpremul(0., 1., 0., 1.),
|
Color::new_unpremul(0., 1., 0., 1.),
|
||||||
0.,
|
0.,
|
||||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
Rectangle::from_size(area.size),
|
||||||
0.,
|
0.,
|
||||||
CornerRadius::default(),
|
CornerRadius::default(),
|
||||||
1.,
|
1.,
|
||||||
|
1.,
|
||||||
)
|
)
|
||||||
.with_location(area.loc)]
|
.with_location(area.loc)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user