diff --git a/Cargo.lock b/Cargo.lock index 536cd82..8cf2d85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,18 +10,18 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] [[package]] name = "android_system_properties" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" dependencies = [ "libc", ] @@ -40,13 +40,13 @@ checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -77,8 +77,8 @@ dependencies = [ [[package]] name = "bread-theme" -version = "0.7.2" -source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.7.2#30517f161724132cdeb658c04cf5e490be07ee73" +version = "0.7.4" +source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.7.4#fcba3760387e2523edb71350f8efea3bc851b21e" dependencies = [ "dirs", "gtk4", @@ -108,7 +108,7 @@ dependencies = [ "gtk4", "relm4", "serde", - "thiserror 2.0.18", + "thiserror 2.0.20", "tokio", "toml 0.8.23", "tracing", @@ -126,7 +126,7 @@ dependencies = [ "serde", "serde_json", "smithay-client-toolkit", - "thiserror 2.0.18", + "thiserror 2.0.20", "tiny-skia", "toml 0.8.23", "tracing", @@ -155,22 +155,22 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytemuck" -version = "1.25.1" +version = "1.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5" +checksum = "fc0e56a716f1e132ff6bf4bdac1c944a3fcdc1cae65f70a4a2a1ac3b401d2d1f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -229,9 +229,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.3.0" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8" +checksum = "509591b7bcd67f4ef775afad7662703b4935daaa6ec0e5605cfb1090b32a2b6d" dependencies = [ "find-msvc-tools", "shlex", @@ -370,11 +370,11 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.3", ] [[package]] @@ -398,9 +398,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" [[package]] name = "flate2" @@ -426,9 +426,9 @@ dependencies = [ [[package]] name = "font-types" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad67eced03f5504d9cbd3a879b5958b5c54d4e5fd794361c6eb21b05fb703411" +checksum = "75382bc7392ef10aad10935f92fc3db36d2d4dad0e5d96d8d65e04f89a07ec39" dependencies = [ "bytemuck", ] @@ -467,9 +467,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88cf1f829d945f548cf8fec32c61b1f202b6d93b45848602fc02af4b12ad218" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" dependencies = [ "futures-channel", "futures-core", @@ -482,9 +482,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", "futures-sink", @@ -492,15 +492,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-executor" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" dependencies = [ "futures-core", "futures-task", @@ -509,38 +509,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-macro" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "futures-sink" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-channel", "futures-core", @@ -623,15 +623,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasip2", "wasm-bindgen", ] @@ -695,7 +694,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -814,7 +813,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -896,9 +895,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.103" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" dependencies = [ "cfg-if", "futures-util", @@ -913,9 +912,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libm" @@ -925,9 +924,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.18" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a" dependencies = [ "libc", ] @@ -1089,9 +1088,9 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" [[package]] name = "png" @@ -1131,42 +1130,42 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quick-xml" -version = "0.39.4" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rangemap" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" +checksum = "a611d15b50743feb4c76b7d03edcb0e64f399c26961e4efe6975bc398be6aa3d" [[package]] name = "read-fonts" @@ -1192,9 +1191,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -1238,7 +1237,7 @@ checksum = "36c9dbf50a60c82375e66b61d522c936b187a11b25c0a42e91c516326ad24a4f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1318,9 +1317,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -1328,29 +1327,29 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -1455,7 +1454,7 @@ dependencies = [ "memmap2", "pkg-config", "rustix", - "thiserror 2.0.18", + "thiserror 2.0.20", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -1522,6 +1521,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sys-locale" version = "0.3.2" @@ -1540,7 +1550,7 @@ dependencies = [ "cfg-expr", "heck", "pkg-config", - "toml 1.1.3+spec-1.1.0", + "toml 1.1.4+spec-1.1.0", "version-compare", ] @@ -1561,11 +1571,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl 2.0.20", ] [[package]] @@ -1576,18 +1586,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -1642,9 +1652,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.53.0" +version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d988bcd52dbe076d3d46903332f58c912b87a2c49b1428419a5845154762ffee" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ "bytes", "libc", @@ -1658,13 +1668,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -1681,9 +1691,9 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.3+spec-1.1.0" +version = "1.1.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" dependencies = [ "indexmap", "serde_core", @@ -1740,9 +1750,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.2+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ "winnow 1.0.4", ] @@ -1779,7 +1789,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1905,20 +1915,11 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasip2" -version = "1.0.4+wasi-0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasm-bindgen" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" dependencies = [ "cfg-if", "once_cell", @@ -1929,9 +1930,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1939,31 +1940,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" dependencies = [ "unicode-ident", ] [[package]] name = "wayland-backend" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" +checksum = "38a91b4eaddff87b1cd1074985e3713da4af2c49742d1b356b2c01670a67a078" dependencies = [ "cc", "downcast-rs", @@ -1974,9 +1975,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.14" +version = "0.31.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" +checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073" dependencies = [ "bitflags", "rustix", @@ -2059,9 +2060,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.10" +version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" +checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0" dependencies = [ "proc-macro2", "quick-xml", @@ -2098,7 +2099,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2109,7 +2110,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -2229,17 +2230,11 @@ dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - [[package]] name = "xcursor" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" +checksum = "163b33ed8786455e2fa5d72f554057ce3f3182425434f756cd39c99839d88e23" [[package]] name = "xkbcommon" diff --git a/Cargo.toml b/Cargo.toml index 7402de6..ca9ac0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["breadlock-ui", "breadlock", "breadgreet"] resolver = "2" [workspace.dependencies] -bread-theme = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.2" } +bread-theme = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.4" } bread-utils = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.2" } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/breadgreet/src/main.rs b/breadgreet/src/main.rs index 231c26f..1633d43 100644 --- a/breadgreet/src/main.rs +++ b/breadgreet/src/main.rs @@ -146,6 +146,7 @@ impl SimpleComponent for App { spawn_greetd_actor(cmd_rx, sender.clone()); theme::apply(); + bread_theme::gtk::bind_window_auto(&root); spawn_clock_ticker(sender.clone()); let model = App { diff --git a/breadlock-ui/src/theme.rs b/breadlock-ui/src/theme.rs index 364c3d0..282ef41 100644 --- a/breadlock-ui/src/theme.rs +++ b/breadlock-ui/src/theme.rs @@ -1,4 +1,4 @@ -pub use bread_theme::{ink_on, load_palette, Palette}; +pub use bread_theme::{ink_on, load_palette, load_palette_for, Palette}; /// Parse a `#rrggbb` hex colour. Falls back to opaque black on malformed input /// (palette slots are always produced by [`bread_theme`], which guarantees diff --git a/breadlock/src/input/keyboard.rs b/breadlock/src/input/keyboard.rs index 0add42b..c90d229 100644 --- a/breadlock/src/input/keyboard.rs +++ b/breadlock/src/input/keyboard.rs @@ -140,8 +140,9 @@ impl KeyboardHandler for AppState { impl AppState { fn handle_key(&mut self, qh: &QueueHandle, event: KeyEvent) { // Ignore all input while a PAM check is in flight so a fast second - // Enter can't race the first attempt. - if self.auth_state == AuthState::Checking { + // Enter can't race the first attempt, and while the unlock fade is + // playing (auth already succeeded; surfaces stay up until it ends). + if self.auth_state == AuthState::Checking || self.unlocking.is_some() { return; } diff --git a/breadlock/src/main.rs b/breadlock/src/main.rs index 18cd008..dde44f7 100644 --- a/breadlock/src/main.rs +++ b/breadlock/src/main.rs @@ -156,12 +156,13 @@ fn run_lock() { let auth_tx = auth::register(&loop_handle, move |state: &mut AppState, result| { match result { Ok(()) => { - tracing::info!("authenticated, unlocking"); - if let Some(lock) = state.session_lock.take() { - lock.unlock(); - bread_events::emit_unlocked(); + // Keep the lock surfaces up and fade the overlay out. + // Compositor unlock() runs only after UNLOCK_MS — dying + // mid-fade is fail-secure (session stays locked). + tracing::info!("authenticated, fading out"); + if state.unlocking.is_none() { + state.unlocking = Some(std::time::Instant::now()); } - state.exit = true; } Err(err) => { match err { @@ -217,6 +218,9 @@ fn run_lock() { password: zeroize::Zeroizing::new(String::with_capacity(128)), auth_state: AuthState::Idle, auth_tx, + appear_started: None, + unlocking: None, + anim_timer_armed: false, exit: false, }; @@ -272,7 +276,13 @@ fn run_lock() { let mut consecutive_errors = 0u32; while !app_state.exit { match event_loop.dispatch(Duration::from_millis(250), &mut app_state) { - Ok(()) => consecutive_errors = 0, + Ok(()) => { + consecutive_errors = 0; + // Backup if the 16ms anim timer failed to register: the + // 250ms dispatch timeout (or the 1s clock tick) still + // completes a finished unlock fade. + app_state.complete_unlock_if_ready(); + } Err(err) => { consecutive_errors += 1; tracing::error!( diff --git a/breadlock/src/render.rs b/breadlock/src/render.rs index 37796dc..acc7bc9 100644 --- a/breadlock/src/render.rs +++ b/breadlock/src/render.rs @@ -9,8 +9,20 @@ use crate::background::Background; use breadlock_ui::painter::{rounded_rect, tokens, TextRenderer}; use breadlock_ui::theme::tiny_skia_color; +use std::time::Instant; use tiny_skia::{Color, Paint, Pixmap}; +/// Lock-appear duration: overlay fades in and eases up from below rest. +pub const APPEAR_MS: u64 = 450; +/// Unlock-fade duration: overlay fades out with a slight upward drift. +pub const UNLOCK_MS: u64 = 400; +/// Redraw cadence while an animation is in flight (~60 Hz). +pub const ANIM_FRAME_MS: u64 = 16; + +const APPEAR_SLIDE_PX: f32 = 28.0; +const UNLOCK_DRIFT_PX: f32 = 20.0; +const DIM_ALPHA: f32 = 0.28; + pub struct FrameInputs<'a> { pub width: u32, pub height: u32, @@ -23,6 +35,40 @@ pub struct FrameInputs<'a> { /// shake in v1 — just a color/status-text indicator. pub failed: bool, pub status_text: Option<&'a str>, + /// Raw 0..1 lock-appear progress (pre-ease). 1 is rest pose. + pub appear_t: f32, + /// Raw 0..1 unlock-fade progress (pre-ease). 0 when not unlocking. + pub unlock_t: f32, +} + +/// Ease-out cubic. `t` is clamped to 0..1. +pub fn ease_out_cubic(t: f32) -> f32 { + let t = t.clamp(0.0, 1.0); + let inv = 1.0 - t; + 1.0 - inv * inv * inv +} + +/// Linear 0..1 progress since `started` over `duration_ms`. +pub fn unit_progress(started: Instant, duration_ms: u64) -> f32 { + let dur = duration_ms as f32 / 1000.0; + if dur <= 0.0 { + return 1.0; + } + (started.elapsed().as_secs_f32() / dur).clamp(0.0, 1.0) +} + +/// Overlay alpha and y-offset (positive is down) from raw 0..1 progress. +pub fn overlay_motion(appear_t: f32, unlock_t: f32) -> (f32, f32) { + let appear = ease_out_cubic(appear_t); + let unlock = ease_out_cubic(unlock_t); + let alpha = (appear * (1.0 - unlock)).clamp(0.0, 1.0); + let y = APPEAR_SLIDE_PX * (1.0 - appear) - UNLOCK_DRIFT_PX * unlock; + (alpha, y) +} + +fn faded(mut color: Color, alpha: f32) -> Color { + color.apply_opacity(alpha); + color } /// Composes one frame. Returns `None` only if `width`/`height` are degenerate @@ -31,11 +77,28 @@ pub fn compose(text: &mut TextRenderer, inputs: &FrameInputs) -> Option let mut pixmap = Pixmap::new(inputs.width, inputs.height)?; inputs.background.paint(&mut pixmap); + let (alpha, y_off) = overlay_motion(inputs.appear_t, inputs.unlock_t); + if alpha <= 0.0 { + return Some(pixmap); + } + let (w, h) = (inputs.width as f32, inputs.height as f32); - let surface_color = tiny_skia_color(&inputs.palette.color0); - let accent_color = tiny_skia_color(&inputs.palette.color4); - let on_surface = tiny_skia_color(breadlock_ui::theme::ink_on(&inputs.palette.color0)); - let red_color = tiny_skia_color(&inputs.palette.color1); + let surface_color = faded(tiny_skia_color(&inputs.palette.color0), alpha); + let accent_color = faded(tiny_skia_color(&inputs.palette.color4), alpha); + let on_surface = faded( + tiny_skia_color(breadlock_ui::theme::ink_on(&inputs.palette.color0)), + alpha, + ); + let red_color = faded(tiny_skia_color(&inputs.palette.color1), alpha); + + // Translucent veil over the (static) wallpaper — fades with the chrome. + if let Some(rect) = tiny_skia::Rect::from_xywh(0.0, 0.0, w, h) { + let mut paint = Paint::default(); + paint.set_color( + Color::from_rgba(0.0, 0.0, 0.0, DIM_ALPHA * alpha).unwrap_or(Color::TRANSPARENT), + ); + pixmap.fill_rect(rect, &paint, tiny_skia::Transform::identity(), None); + } // Clock, large, centered in the upper third. let clock_size = 64.0; @@ -45,16 +108,16 @@ pub fn compose(text: &mut TextRenderer, inputs: &FrameInputs) -> Option inputs.clock_text, inputs.font_family, clock_size, - Color::WHITE, + faded(Color::WHITE, alpha), (w - clock_w) / 2.0, - h * 0.28, + h * 0.28 + y_off, ); // Password pill, centered; turns red while showing a failed attempt. let pill_w = 280.0_f32.min(w - tokens::SPACE_XL as f32 * 2.0); let pill_h = 48.0; let pill_x = (w - pill_w) / 2.0; - let pill_y = h * 0.5; + let pill_y = h * 0.5 + y_off; if let Some(path) = rounded_rect( pill_x, @@ -97,7 +160,7 @@ pub fn compose(text: &mut TextRenderer, inputs: &FrameInputs) -> Option { let mut paint = Paint::default(); paint.set_color(if inputs.failed { - Color::WHITE + faded(Color::WHITE, alpha) } else { accent_color }); @@ -172,8 +235,38 @@ mod tests { password_len: 0, failed: false, status_text: None, + appear_t: 1.0, + unlock_t: 0.0, }; let pixmap = compose(&mut text, &inputs).unwrap(); assert_eq!((pixmap.width(), pixmap.height()), (400, 300)); } + + #[test] + fn ease_out_cubic_bounds_and_shape() { + assert_eq!(ease_out_cubic(0.0), 0.0); + assert_eq!(ease_out_cubic(1.0), 1.0); + assert_eq!(ease_out_cubic(-1.0), 0.0); + assert_eq!(ease_out_cubic(2.0), 1.0); + // Ease-out sits above the linear diagonal in the middle of the curve. + assert!(ease_out_cubic(0.5) > 0.5); + } + + #[test] + fn overlay_motion_appear_starts_below_and_fades_in() { + let (a0, y0) = overlay_motion(0.0, 0.0); + assert_eq!(a0, 0.0); + assert!(y0 > 0.0, "clock/pill should start below rest, got y={y0}"); + + let (a1, y1) = overlay_motion(1.0, 0.0); + assert_eq!(a1, 1.0); + assert_eq!(y1, 0.0); + } + + #[test] + fn overlay_motion_unlock_fades_out_and_drifts_up() { + let (a, y) = overlay_motion(1.0, 1.0); + assert_eq!(a, 0.0); + assert!(y < 0.0, "unlock should drift up from rest, got y={y}"); + } } diff --git a/breadlock/src/state.rs b/breadlock/src/state.rs index 8726cc9..4fd5dd6 100644 --- a/breadlock/src/state.rs +++ b/breadlock/src/state.rs @@ -8,7 +8,7 @@ use smithay_client_toolkit::registry_handlers; use smithay_client_toolkit::seat::SeatState; use smithay_client_toolkit::session_lock::{SessionLock, SessionLockState, SessionLockSurface}; use smithay_client_toolkit::shm::{Shm, ShmHandler}; -use std::time::Duration; +use std::time::{Duration, Instant}; use wayland_client::protocol::{wl_keyboard, wl_output, wl_shm}; use wayland_client::{Connection, QueueHandle}; @@ -75,6 +75,17 @@ pub struct AppState { pub auth_state: AuthState, pub auth_tx: Sender, + /// First-frame timestamp for the lock-appear animation. `None` until + /// the first non-degenerate redraw so the fade starts when the surface + /// is actually visible, not when the process starts. + pub appear_started: Option, + /// Set on PAM success. While `Some`, lock surfaces stay up and the + /// overlay fades out; compositor `unlock()` happens only after the + /// fade completes. Dying mid-fade leaves the session locked (fail-secure). + pub unlocking: Option, + /// True while a ~16ms animation timer is registered on the event loop. + pub anim_timer_armed: bool, + pub exit: bool, } @@ -93,28 +104,45 @@ impl AppState { return; } + if self.appear_started.is_none() { + self.appear_started = Some(Instant::now()); + } + let clock_text = chrono::Local::now() .format(&self.config.appearance.clock.format) .to_string(); let status_text = match self.auth_state { AuthState::Checking => Some("Checking…".to_string()), AuthState::Failed => Some("Wrong password".to_string()), - AuthState::ConfigError => { - Some("PAM config error — check logs (breadlock service not set up correctly)".to_string()) - } + AuthState::ConfigError => Some( + "PAM config error — check logs (breadlock service not set up correctly)" + .to_string(), + ), AuthState::Idle => None, }; + let appear_t = self + .appear_started + .map(|t| render::unit_progress(t, render::APPEAR_MS)) + .unwrap_or(0.0); + let unlock_t = self + .unlocking + .map(|t| render::unit_progress(t, render::UNLOCK_MS)) + .unwrap_or(0.0); + + let output_palette = self.palette_for_surface(surface); let inputs = render::FrameInputs { width, height, background: &self.background, - palette: &self.palette, + palette: &output_palette, font_family: &self.config.appearance.font.family, clock_text: &clock_text, password_len: self.password.len(), failed: matches!(self.auth_state, AuthState::Failed | AuthState::ConfigError), status_text: status_text.as_deref(), + appear_t, + unlock_t, }; let Some(pixmap) = render::compose(&mut self.text_renderer, &inputs) else { @@ -149,6 +177,18 @@ impl AppState { .damage_buffer(0, 0, width as i32, height as i32); surface.wl_surface().commit(); buffer.destroy(); + + self.arm_anim_if_needed(qh); + } + + fn palette_for_surface(&self, surface: &SessionLockSurface) -> breadlock_ui::theme::Palette { + self.surfaces + .iter() + .find(|s| s.surface.wl_surface() == surface.wl_surface()) + .and_then(|s| self.output_state.info(&s.output)) + .and_then(|info| info.name) + .map(|name| breadlock_ui::theme::load_palette_for(&name)) + .unwrap_or_else(|| self.palette.clone()) } /// Redraws every currently-configured surface — used for the clock tick @@ -162,6 +202,73 @@ impl AppState { for (surface, width, height) in surfaces { self.redraw_surface(qh, &surface, width, height); } + self.complete_unlock_if_ready(); + } + + fn appear_in_progress(&self) -> bool { + self.appear_started + .map(|t| t.elapsed() < Duration::from_millis(render::APPEAR_MS)) + .unwrap_or(true) + } + + fn unlock_in_progress(&self) -> bool { + self.unlocking + .map(|t| t.elapsed() < Duration::from_millis(render::UNLOCK_MS)) + .unwrap_or(false) + } + + fn anim_in_progress(&self) -> bool { + self.unlocking.is_some() || self.appear_in_progress() + } + + /// Keep requesting frames while appear or unlock-fade is running. + fn arm_anim_if_needed(&mut self, qh: &QueueHandle) { + if self.anim_timer_armed || !self.anim_in_progress() { + return; + } + self.anim_timer_armed = true; + let qh = qh.clone(); + if self + .loop_handle + .insert_source( + Timer::from_duration(Duration::from_millis(render::ANIM_FRAME_MS)), + move |_, _, state| state.tick_animation(&qh), + ) + .is_err() + { + tracing::error!("failed to arm lock animation timer"); + self.anim_timer_armed = false; + } + } + + fn tick_animation(&mut self, qh: &QueueHandle) -> TimeoutAction { + self.redraw_all(qh); + if self.unlocking.is_some() && !self.unlock_in_progress() { + self.anim_timer_armed = false; + TimeoutAction::Drop + } else if self.anim_in_progress() { + TimeoutAction::ToDuration(Duration::from_millis(render::ANIM_FRAME_MS)) + } else { + self.anim_timer_armed = false; + TimeoutAction::Drop + } + } + + /// After the unlock fade reaches t==1, send compositor `unlock` and + /// exit. Not called until then — dying mid-fade stays locked. + pub fn complete_unlock_if_ready(&mut self) { + let Some(started) = self.unlocking else { + return; + }; + if started.elapsed() < Duration::from_millis(render::UNLOCK_MS) { + return; + } + if let Some(lock) = self.session_lock.take() { + tracing::info!("unlock fade complete"); + lock.unlock(); + crate::bread_events::emit_unlocked(); + } + self.exit = true; } /// After a failed attempt, clears the "wrong password" state (and