From 59876fd134e5bcc78a41258d1cbe9b2c5be2dbd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domen=20Ko=C5=BEar?= Date: Mon, 6 Jul 2026 18:05:32 -0600 Subject: [PATCH 1/3] Store the passphrase in a zeroizing buffer instead of a TextEdit Feed keystrokes directly into a zeroize::Zeroizing and draw a masked view, rather than an egui TextEdit whose retained widget state and undo history keep the plaintext around after the dialog closes. Move the value into the SecretString on submit (no clone; the buffer is zeroized on drop). Tests drive the field with synthetic input events since the masked view is no longer an accessible widget. --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/main.rs | 90 +++++++++++++++++++++++++++++++---------------------- 3 files changed, 55 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acabcf0..cca9e0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2224,10 +2224,10 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" name = "pinentry-egui" version = "0.1.2" dependencies = [ - "accesskit", "eframe", "egui_kittest", "secrecy", + "zeroize", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2ba81ad..150f82a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,11 +14,11 @@ exclude = ["CLAUDE.md"] [dependencies] eframe = { version = "0.33", default-features = false, features = ["default_fonts", "glow", "wayland", "x11"] } secrecy = "0.10" +zeroize = "1" [dev-dependencies] eframe = { version = "0.33", features = ["accesskit"] } egui_kittest = "0.33" -accesskit = "0.21" [profile.release] strip = true diff --git a/src/main.rs b/src/main.rs index 985d324..2c849d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ use std::sync::mpsc; use eframe::egui; use secrecy::{ExposeSecret, SecretString}; +use zeroize::Zeroizing; fn percent_decode(s: &str) -> String { let bytes = s.as_bytes(); @@ -48,9 +49,11 @@ struct PinentryState { #[derive(Default)] struct PinDialogState { - password: String, + // Keystrokes are appended here directly (never through an egui `TextEdit`, + // whose retained widget state and undo history would keep the plaintext), and + // the buffer is zeroized on drop. Moved into the `SecretString` on submit. + password: Zeroizing, submitted: Option, // Some(true) = OK, Some(false) = Cancel - focus_set: bool, } fn pin_dialog_ui( @@ -89,20 +92,34 @@ fn pin_dialog_ui( }; ui.label(prompt); ui.add_space(4.0); - let response = ui.add_sized( - [ui.available_width(), 28.0], - egui::TextEdit::singleline(&mut dialog.password) - .password(true) - .hint_text("Enter passphrase") - .font(egui::TextStyle::Body), - ); - if !dialog.focus_set { - dialog.focus_set = true; - response.request_focus(); - } - if response.lost_focus() - && ui.input(|i| i.key_pressed(egui::Key::Enter)) - { + + // Feed keystrokes straight into the zeroizing buffer instead of an + // egui `TextEdit`, so the plaintext never enters egui's retained + // widget state or undo history. Only a masked view is drawn. + ui.input(|input| { + for event in &input.events { + match event { + egui::Event::Text(text) | egui::Event::Paste(text) => { + dialog.password.push_str(text); + } + egui::Event::Key { + key: egui::Key::Backspace, + pressed: true, + .. + } => { + dialog.password.pop(); + } + _ => {} + } + } + }); + let dots = "\u{2022}".repeat(dialog.password.chars().count()); + egui::Frame::group(ui.style()).show(ui, |ui| { + ui.set_min_width(ui.available_width()); + ui.add(egui::Label::new(egui::RichText::new(dots).monospace())); + }); + + if ui.input(|i| i.key_pressed(egui::Key::Enter)) { dialog.submitted = Some(true); } ui.add_space(12.0); @@ -158,10 +175,10 @@ impl eframe::App for PinDialog { if let Some(ok) = self.dialog.submitted.take() { if ok { if self.want_pin { - let _ = self.tx.send(DialogResult::Pin(SecretString::from( - self.dialog.password.clone(), - ))); - self.dialog.password.clear(); + // Move the inner String out (leaving an empty one) into the + // secret, which zeroizes it in turn. + let value = std::mem::take(&mut *self.dialog.password); + let _ = self.tx.send(DialogResult::Pin(SecretString::from(value))); } else { let _ = self.tx.send(DialogResult::Confirmed); } @@ -322,7 +339,7 @@ fn main() { #[cfg(test)] mod tests { use super::*; - use egui_kittest::kittest::{Queryable, NodeT}; + use egui_kittest::kittest::Queryable; use egui_kittest::Harness; struct TestState { @@ -350,29 +367,30 @@ mod tests { ) } + // The custom masked field is not an accessible widget, so drive it with + // synthetic input events and assert on the resulting buffer/state. #[test] - fn test_password_field_gets_focus() { - let mut harness = make_harness("Enter your GPG passphrase", true); + fn test_type_password() { + let mut harness = make_harness("Enter passphrase", true); harness.run(); - let ti = harness.get_by_role(accesskit::Role::PasswordInput); - println!("focused: {}, value: {:?}", ti.is_focused(), ti.accesskit_node().value()); - assert!(ti.is_focused(), "password field should be auto-focused"); + harness.event(egui::Event::Text("secret123".into())); + harness.run(); + + assert_eq!(harness.state().dialog.password.as_str(), "secret123"); } #[test] - fn test_type_password() { + fn test_backspace_removes_last_char() { let mut harness = make_harness("Enter passphrase", true); harness.run(); - let ti = harness.get_by_role(accesskit::Role::PasswordInput); - assert!(ti.is_focused()); - - ti.type_text("secret123"); + harness.event(egui::Event::Text("abc".into())); + harness.run(); + harness.key_press(egui::Key::Backspace); harness.run(); - println!("password: {:?}", harness.state().dialog.password); - assert_eq!(harness.state().dialog.password, "secret123"); + assert_eq!(harness.state().dialog.password.as_str(), "ab"); } #[test] @@ -380,15 +398,13 @@ mod tests { let mut harness = make_harness("Enter passphrase", true); harness.run(); - let ti = harness.get_by_role(accesskit::Role::PasswordInput); - ti.type_text("mypass"); + harness.event(egui::Event::Text("mypass".into())); harness.run(); - harness.key_press(egui::Key::Enter); harness.run(); - println!("submitted: {:?}, password: {:?}", harness.state().dialog.submitted, harness.state().dialog.password); assert_eq!(harness.state().dialog.submitted, Some(true)); + assert_eq!(harness.state().dialog.password.as_str(), "mypass"); } From 47f526bfc05741d2b4c6f44102b2dbba98478e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domen=20Ko=C5=BEar?= Date: Tue, 7 Jul 2026 10:03:26 -0600 Subject: [PATCH 2/3] Render on the CPU with winit + softbuffer instead of eframe/glow Replace the eframe/glow (OpenGL) backend with a pure-CPU pipeline: winit for windowing, egui_software_backend to rasterize egui frames on the CPU, and softbuffer to present them. No GPU, OpenGL, or Vulkan is required, so the dialog runs on machines without working GL drivers. - Bump egui, egui-winit, and egui_kittest to the 0.34 line (pinned by egui_software_backend 0.0.3, which pins egui 0.34 / winit 0.30). - Drive one process-wide winit EventLoop with run_app_on_demand so a single gpg-agent connection can show several GETPIN/CONFIRM dialogs. - Keep the Assuan protocol layer, the zeroizing masked passphrase buffer, and the show_dialog(state, want_pin) signature unchanged. - Port the egui_kittest UI tests to the 0.34 API. --- Cargo.lock | 2680 ++++++++------------------------------------------- Cargo.toml | 21 +- src/main.rs | 377 ++++++-- 3 files changed, 729 insertions(+), 2349 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cca9e0a..952a17a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,110 +20,23 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "accesskit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99" - -[[package]] -name = "accesskit_atspi_common" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "890d241cf51fc784f0ac5ac34dfc847421f8d39da6c7c91a0fcc987db62a8267" -dependencies = [ - "accesskit", - "accesskit_consumer 0.31.0", - "atspi-common", - "serde", - "thiserror 1.0.69", - "zvariant", -] - -[[package]] -name = "accesskit_consumer" -version = "0.30.1" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd06f5fea9819250fffd4debf926709f3593ac22f8c1541a2573e5ee0ca01cd" +checksum = "d3b7f7f85a7e5f68090000ed7622545829afd484d210358702ae4cb97dd0c320" dependencies = [ - "accesskit", - "hashbrown 0.15.5", + "uuid", ] [[package]] name = "accesskit_consumer" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db81010a6895d8707f9072e6ce98070579b43b717193d2614014abd5cb17dd43" -dependencies = [ - "accesskit", - "hashbrown 0.15.5", -] - -[[package]] -name = "accesskit_macos" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0089e5c0ac0ca281e13ea374773898d9354cc28d15af9f0f7394d44a495b575" -dependencies = [ - "accesskit", - "accesskit_consumer 0.31.0", - "hashbrown 0.15.5", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "accesskit_unix" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301e55b39cfc15d9c48943ce5f572204a551646700d0e8efa424585f94fec528" -dependencies = [ - "accesskit", - "accesskit_atspi_common", - "async-channel", - "async-executor", - "async-task", - "atspi", - "futures-lite", - "futures-util", - "serde", - "zbus", -] - -[[package]] -name = "accesskit_windows" -version = "0.29.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d63dd5041e49c363d83f5419a896ecb074d309c414036f616dc0b04faca971" -dependencies = [ - "accesskit", - "accesskit_consumer 0.31.0", - "hashbrown 0.15.5", - "static_assertions", - "windows 0.61.3", - "windows-core 0.61.2", -] - -[[package]] -name = "accesskit_winit" -version = "0.29.2" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cfabe59d0eaca7412bfb1f70198dd31e3b0496fee7e15b066f9c36a1a140a0" +checksum = "53cf47daed85312e763fbf85ceca136e0d7abc68e0a7e12abe11f48172bc3b10" dependencies = [ "accesskit", - "accesskit_macos", - "accesskit_unix", - "accesskit_windows", - "raw-window-handle", - "winit", + "hashbrown", ] -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "ahash" version = "0.8.12" @@ -155,7 +68,7 @@ dependencies = [ "ndk-context", "ndk-sys", "num_enum", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -164,35 +77,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "arboard" -version = "3.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" -dependencies = [ - "clipboard-win", - "image", - "log", - "objc2 0.6.3", - "objc2-app-kit 0.3.2", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation 0.3.2", - "parking_lot", - "percent-encoding", - "windows-sys 0.60.2", - "x11rb", -] - [[package]] name = "arrayref" version = "0.3.9" @@ -211,223 +95,18 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" -[[package]] -name = "ash" -version = "0.38.0+1.3.281" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" -dependencies = [ - "libloading", -] - -[[package]] -name = "async-broadcast" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-channel" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-executor" -version = "1.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "pin-project-lite", - "slab", -] - -[[package]] -name = "async-io" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" -dependencies = [ - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix 1.1.3", - "slab", - "windows-sys 0.61.2", -] - -[[package]] -name = "async-lock" -version = "3.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-process" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" -dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix 1.1.3", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-signal" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix 1.1.3", - "signal-hook-registry", - "slab", - "windows-sys 0.61.2", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - -[[package]] -name = "async-trait" -version = "0.1.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "atspi" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83247582e7508838caf5f316c00791eee0e15c0bf743e6880585b867e16815c" -dependencies = [ - "atspi-common", - "atspi-connection", - "atspi-proxies", -] - -[[package]] -name = "atspi-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33dfc05e7cdf90988a197803bf24f5788f94f7c94a69efa95683e8ffe76cfdfb" -dependencies = [ - "enumflags2", - "serde", - "static_assertions", - "zbus", - "zbus-lockstep", - "zbus-lockstep-macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "atspi-connection" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4193d51303d8332304056ae0004714256b46b6635a5c556109b319c0d3784938" -dependencies = [ - "atspi-common", - "atspi-proxies", - "futures-lite", - "zbus", -] - -[[package]] -name = "atspi-proxies" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2eebcb9e7e76f26d0bcfd6f0295e1cd1e6f33bedbc5698a971db8dc43d7751c" -dependencies = [ - "atspi-common", - "serde", - "zbus", -] - [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "bit-set" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" - [[package]] name = "bitflags" version = "1.3.2" @@ -440,12 +119,6 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - [[package]] name = "block2" version = "0.5.1" @@ -455,19 +128,6 @@ dependencies = [ "objc2 0.5.2", ] -[[package]] -name = "blocking" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" -dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", -] - [[package]] name = "bumpalo" version = "3.19.1" @@ -494,12 +154,6 @@ dependencies = [ "syn", ] -[[package]] -name = "byteorder-lite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" - [[package]] name = "bytes" version = "1.11.1" @@ -517,20 +171,7 @@ dependencies = [ "polling", "rustix 0.38.44", "slab", - "thiserror 1.0.69", -] - -[[package]] -name = "calloop" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" -dependencies = [ - "bitflags 2.11.0", - "polling", - "rustix 1.1.3", - "slab", - "tracing", + "thiserror", ] [[package]] @@ -539,24 +180,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ - "calloop 0.13.0", + "calloop", "rustix 0.38.44", "wayland-backend", "wayland-client", ] -[[package]] -name = "calloop-wayland-source" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" -dependencies = [ - "calloop 0.14.4", - "rustix 1.1.3", - "wayland-backend", - "wayland-client", -] - [[package]] name = "cc" version = "1.2.56" @@ -588,32 +217,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] -name = "cgl" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" -dependencies = [ - "libc", -] - -[[package]] -name = "clipboard-win" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" -dependencies = [ - "error-code", -] - -[[package]] -name = "codespan-reporting" -version = "0.12.0" +name = "color" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +checksum = "2ec7c5eb7a16992b1904d76c517d170ab353b0e0b3d5a0c81a8a0cd1037893cf" dependencies = [ - "serde", - "termcolor", - "unicode-width", + "bytemuck", ] [[package]] @@ -636,20 +245,21 @@ dependencies = [ ] [[package]] -name = "core-foundation" -version = "0.9.4" +name = "constify" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "c3efe35846d8965e78e0e246153416055964610dc2b67ba0e162624dc44fc719" dependencies = [ - "core-foundation-sys", - "libc", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "core-foundation" -version = "0.10.1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -668,8 +278,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", + "core-foundation", + "core-graphics-types", "foreign-types", "libc", ] @@ -681,42 +291,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", + "core-foundation", "libc", ] [[package]] -name = "core-graphics-types" -version = "0.2.0" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" -dependencies = [ - "bitflags 2.11.0", - "core-foundation 0.10.1", - "libc", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "crc32fast" -version = "1.5.0" +name = "ctor" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +checksum = "83cf0d42651b16c6dfe68685716d18480d18a9c39c62d76e8cf3eb6ed5d8bcbf" dependencies = [ - "cfg-if", + "dtor", ] -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - [[package]] name = "cursor-icon" version = "1.2.0" @@ -736,18 +329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "objc2 0.6.4", ] [[package]] @@ -759,15 +341,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "document-features" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" -dependencies = [ - "litrs", -] - [[package]] name = "downcast-rs" version = "1.2.1" @@ -781,55 +354,66 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" [[package]] -name = "ecolor" -version = "0.33.3" +name = "drm" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71ddb8ac7643d1dba1bb02110e804406dd459a838efcb14011ced10556711a8e" +checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" dependencies = [ + "bitflags 2.11.0", "bytemuck", - "emath", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 0.38.44", ] [[package]] -name = "eframe" -version = "0.33.3" +name = "drm-ffi" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457481173e6db5ca9fa2be93a58df8f4c7be639587aeb4853b526c6cf87db4e6" +checksum = "51a91c9b32ac4e8105dec255e849e0d66e27d7c34d184364fb93e469db08f690" +dependencies = [ + "drm-sys", + "rustix 1.1.3", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8e1361066d91f5ffccff060a3c3be9c3ecde15be2959c1937595f7a82a9f8" +dependencies = [ + "libc", + "linux-raw-sys 0.9.4", +] + +[[package]] +name = "dtor" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf234dd1594d6dd434a8fb8cada51ddbbc593e40e4a01556a0b31c62da2775b" + +[[package]] +name = "ecolor" +version = "0.34.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a05fbfa222ffb51989d5ccf33e5f7aebfcf96c5023413856b0c3618a7f79896e" dependencies = [ - "ahash", "bytemuck", - "document-features", - "egui", - "egui-wgpu", - "egui-winit", - "egui_glow", - "glow", - "glutin", - "glutin-winit", - "image", - "js-sys", - "log", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", - "parking_lot", - "percent-encoding", - "profiling", - "raw-window-handle", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "web-time", - "windows-sys 0.61.2", - "winit", + "emath", ] [[package]] name = "egui" -version = "0.33.3" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9b567d356674e9a5121ed3fedfb0a7c31e059fe71f6972b691bcd0bfc284e3" +checksum = "42112be0ae157289312b92b3dfaf20e911b5a3c4c65d4aab0e7c47fbc0ce16e3" dependencies = [ "accesskit", "ahash", @@ -843,134 +427,87 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "egui-wgpu" -version = "0.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4d209971c84b2352a06174abdba701af1e552ce56b144d96f2bd50a3c91236" -dependencies = [ - "ahash", - "bytemuck", - "document-features", - "egui", - "epaint", - "log", - "profiling", - "thiserror 2.0.18", - "type-map", - "web-time", - "wgpu", - "winit", -] - [[package]] name = "egui-winit" -version = "0.33.3" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec6687e5bb551702f4ad10ac428bab12acf9d53047ebb1082d4a0ed8c6251a29" +checksum = "967c5b323625d46d46a59b5daba3fef742248d27693cc18972458619858c4239" dependencies = [ - "accesskit_winit", - "arboard", "bytemuck", "egui", "log", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-ui-kit", + "objc2 0.6.4", + "objc2-foundation 0.3.2", + "objc2-ui-kit 0.3.2", "profiling", "raw-window-handle", - "smithay-clipboard", "web-time", - "webbrowser", - "winit", -] - -[[package]] -name = "egui_glow" -version = "0.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6420863ea1d90e750f75075231a260030ad8a9f30a7cef82cdc966492dc4c4eb" -dependencies = [ - "bytemuck", - "egui", - "glow", - "log", - "memoffset", - "profiling", - "wasm-bindgen", - "web-sys", "winit", ] [[package]] name = "egui_kittest" -version = "0.33.3" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43afb5f968dfa9e6c8f5e609ab9039e11a2c4af79a326f4cb1b99cf6875cb6a0" +checksum = "1077ec995dbc754f22afcca9bbab1329071737d749a953e7b430d9b825d40c32" dependencies = [ "egui", "kittest", + "serde", + "toml", ] [[package]] -name = "emath" -version = "0.33.3" +name = "egui_software_backend" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "491bdf728bf25ddd9ad60d4cf1c48588fa82c013a2440b91aa7fc43e34a07c32" +checksum = "b8ca3a47168e93a5cca79b7cb830817acaf07ebc1f8756aa368a6b2d6250f6ae" dependencies = [ "bytemuck", + "constify", + "egui", + "egui-winit", + "softbuffer", + "strength_reduce", + "winit", ] [[package]] -name = "endi" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" - -[[package]] -name = "enumflags2" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.12" +name = "emath" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +checksum = "b53f0d33a479321da6b0caa71366c9f67e8a2c149762d90bdc0d16e601ee8ecb" dependencies = [ - "proc-macro2", - "quote", - "syn", + "bytemuck", ] [[package]] name = "epaint" -version = "0.33.3" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "009d0dd3c2163823a0abdb899451ecbc78798dec545ee91b43aff1fa790bab62" +checksum = "6675898a291ec212fc3df04f537d177fce8496120244590e6359dcaa4c25da79" dependencies = [ - "ab_glyph", "ahash", "bytemuck", "ecolor", "emath", "epaint_default_fonts", + "font-types", "log", "nohash-hasher", "parking_lot", "profiling", + "self_cell", + "skrifa", + "smallvec", + "vello_cpu", ] [[package]] name = "epaint_default_fonts" -version = "0.33.3" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fbe202b6578d3d56428fa185cdf114a05e49da05f477b3c7f0fbb221f1862" +checksum = "f8970033a4282a7bcf899b38b5ed3a58b732fe093d03785d58648515d8d309da" [[package]] name = "equivalent" @@ -989,30 +526,12 @@ dependencies = [ ] [[package]] -name = "error-code" -version = "3.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" - -[[package]] -name = "event-listener" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" +name = "euclid" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" dependencies = [ - "event-listener", - "pin-project-lite", + "num-traits", ] [[package]] @@ -1022,32 +541,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "fax" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" -dependencies = [ - "fax_derive", -] - -[[package]] -name = "fax_derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "fdeflate" -version = "0.3.7" +name = "fearless_simd" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +checksum = "8fb2907d1f08b2b316b9223ced5b0e89d87028ba8deae9764741dba8ff7f3903" dependencies = [ - "simd-adler32", + "bytemuck", ] [[package]] @@ -1056,27 +555,20 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "flate2" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "foldhash" -version = "0.1.5" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] -name = "foldhash" -version = "0.2.0" +name = "font-types" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +checksum = "5b38ad915f6dadd993ced50848a8291a543bd41ca62bc10740d5e64e2ab4cfd7" +dependencies = [ + "bytemuck", +] [[package]] name = "foreign-types" @@ -1105,51 +597,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "futures-task" version = "0.3.31" @@ -1163,7 +616,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", - "futures-macro", "futures-task", "pin-project-lite", "pin-utils", @@ -1177,7 +629,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix 1.1.3", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -1193,387 +645,92 @@ dependencies = [ ] [[package]] -name = "gl_generator" -version = "0.14.0" +name = "hashbrown" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ - "khronos_api", - "log", - "xml-rs", + "foldhash", ] [[package]] -name = "glow" -version = "0.16.0" +name = "hermit-abi" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] -name = "glutin" -version = "0.32.3" +name = "indexmap" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ - "bitflags 2.11.0", - "cfg_aliases", - "cgl", - "dispatch2", - "glutin_egl_sys", - "glutin_glx_sys", - "glutin_wgl_sys", - "libloading", - "objc2 0.6.3", - "objc2-app-kit 0.3.2", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "once_cell", - "raw-window-handle", - "wayland-sys", - "windows-sys 0.52.0", - "x11-dl", + "equivalent", + "hashbrown", ] [[package]] -name = "glutin-winit" -version = "0.5.0" +name = "jni" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ - "cfg_aliases", - "glutin", - "raw-window-handle", - "winit", + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", ] [[package]] -name = "glutin_egl_sys" -version = "0.7.1" +name = "jni-sys" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" -dependencies = [ - "gl_generator", - "windows-sys 0.52.0", -] +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] -name = "glutin_glx_sys" -version = "0.6.1" +name = "jobserver" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "gl_generator", - "x11-dl", + "getrandom", + "libc", ] [[package]] -name = "glutin_wgl_sys" -version = "0.6.1" +name = "js-sys" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ - "gl_generator", + "once_cell", + "wasm-bindgen", ] [[package]] -name = "gpu-alloc" -version = "0.6.0" +name = "kittest" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +checksum = "90ceaa75eb0036a32b6b9833962eb18137449e9817e2e586006471925b727fd5" dependencies = [ - "bitflags 2.11.0", - "gpu-alloc-types", + "accesskit", + "accesskit_consumer", ] [[package]] -name = "gpu-alloc-types" -version = "0.3.0" +name = "kurbo" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +checksum = "4b60dfc32f652b926df6192e55525b16d186c69d47876c3ead4da5cc9f8450e2" dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "gpu-allocator" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" -dependencies = [ - "log", - "presser", - "thiserror 1.0.69", - "windows 0.58.0", -] - -[[package]] -name = "gpu-descriptor" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" -dependencies = [ - "bitflags 2.11.0", - "gpu-descriptor-types", - "hashbrown 0.15.5", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "num-traits", - "zerocopy", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "foldhash 0.2.0", -] - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "icu_collections" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" - -[[package]] -name = "icu_properties" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" - -[[package]] -name = "icu_provider" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", + "arrayvec", + "euclid", + "polycool", "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "image" -version = "0.25.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" -dependencies = [ - "bytemuck", - "byteorder-lite", - "moxcms", - "num-traits", - "png", - "tiff", -] - -[[package]] -name = "indexmap" -version = "2.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" -dependencies = [ - "equivalent", - "hashbrown 0.16.1", -] - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.85" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "khronos-egl" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" -dependencies = [ - "libc", - "libloading", - "pkg-config", -] - -[[package]] -name = "khronos_api" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" - -[[package]] -name = "kittest" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fd6dd2cce251a360101038acb9334e3a50cd38cd02fefddbf28aa975f043c8" -dependencies = [ - "accesskit", - "accesskit_consumer 0.30.1", - "parking_lot", ] [[package]] @@ -1589,15 +746,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link 0.2.1", + "windows-link", ] -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - [[package]] name = "libredox" version = "0.1.12" @@ -1610,28 +761,28 @@ dependencies = [ ] [[package]] -name = "linux-raw-sys" -version = "0.4.15" +name = "linebender_resource_handle" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] -name = "litemap" -version = "0.8.1" +name = "linux-raw-sys" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] -name = "litrs" -version = "1.0.0" +name = "linux-raw-sys" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "lock_api" @@ -1648,15 +799,6 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - [[package]] name = "memchr" version = "2.8.0" @@ -1672,76 +814,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "metal" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" -dependencies = [ - "bitflags 2.11.0", - "block", - "core-graphics-types 0.2.0", - "foreign-types", - "log", - "objc", - "paste", -] - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "moxcms" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" -dependencies = [ - "num-traits", - "pxfm", -] - -[[package]] -name = "naga" -version = "27.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" -dependencies = [ - "arrayvec", - "bit-set", - "bitflags 2.11.0", - "cfg-if", - "cfg_aliases", - "codespan-reporting", - "half", - "hashbrown 0.16.1", - "hexf-parse", - "indexmap", - "libm", - "log", - "num-traits", - "once_cell", - "rustc-hash 1.1.0", - "spirv", - "thiserror 2.0.18", - "unicode-ident", -] - [[package]] name = "ndk" version = "0.9.0" @@ -1754,7 +826,7 @@ dependencies = [ "ndk-sys", "num_enum", "raw-window-handle", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -1772,19 +844,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.11.0", - "cfg-if", - "cfg_aliases", - "libc", - "memoffset", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -1798,7 +857,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -1823,15 +881,6 @@ dependencies = [ "syn", ] -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - [[package]] name = "objc-sys" version = "0.3.5" @@ -1850,9 +899,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] @@ -1870,20 +919,7 @@ dependencies = [ "objc2-core-data", "objc2-core-image", "objc2-foundation 0.2.2", - "objc2-quartz-core", -] - -[[package]] -name = "objc2-app-kit" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" -dependencies = [ - "bitflags 2.11.0", - "objc2 0.6.3", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation 0.3.2", + "objc2-quartz-core 0.2.2", ] [[package]] @@ -1930,7 +966,7 @@ checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.11.0", "dispatch2", - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -1941,7 +977,7 @@ checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.11.0", "dispatch2", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-io-surface", ] @@ -1996,7 +1032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -2007,7 +1043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -2019,7 +1055,7 @@ checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" dependencies = [ "block2", "objc2 0.5.2", - "objc2-app-kit 0.2.2", + "objc2-app-kit", "objc2-foundation 0.2.2", ] @@ -2048,6 +1084,18 @@ dependencies = [ "objc2-metal", ] +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + [[package]] name = "objc2-symbols" version = "0.2.2" @@ -2073,12 +1121,24 @@ dependencies = [ "objc2-core-location", "objc2-foundation 0.2.2", "objc2-link-presentation", - "objc2-quartz-core", + "objc2-quartz-core 0.2.2", "objc2-symbols", "objc2-uniform-type-identifiers", "objc2-user-notifications", ] +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + [[package]] name = "objc2-uniform-type-identifiers" version = "0.2.2" @@ -2119,25 +1179,6 @@ dependencies = [ "libredox", ] -[[package]] -name = "ordered-float" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - [[package]] name = "owned_ttf_parser" version = "0.25.1" @@ -2147,12 +1188,6 @@ dependencies = [ "ttf-parser", ] -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - [[package]] name = "parking_lot" version = "0.12.5" @@ -2173,14 +1208,21 @@ dependencies = [ "libc", "redox_syscall 0.5.18", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] -name = "paste" -version = "1.0.15" +name = "peniko" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "839c8299360d2e998bdb106dc0a6cd71dcc5f4df51df1b620361bf50e283cca6" +dependencies = [ + "bytemuck", + "color", + "kurbo", + "linebender_resource_handle", + "smallvec", +] [[package]] name = "percent-encoding" @@ -2224,42 +1266,23 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" name = "pinentry-egui" version = "0.1.2" dependencies = [ - "eframe", + "bytemuck", + "egui", + "egui-winit", "egui_kittest", + "egui_software_backend", "secrecy", + "softbuffer", + "winit", "zeroize", ] -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - [[package]] name = "pkg-config" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "png" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" -dependencies = [ - "bitflags 2.11.0", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - [[package]] name = "polling" version = "3.11.0" @@ -2275,35 +1298,14 @@ dependencies = [ ] [[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "portable-atomic-util" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "potential_utf" -version = "0.1.4" +name = "polycool" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "50596ddc09eb5ad5f75cacd40209568e66df71baf86e1499a0e99c4cff12a5a6" dependencies = [ - "zerovec", + "arrayvec", ] -[[package]] -name = "presser" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" - [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -2328,31 +1330,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" -[[package]] -name = "pxfm" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" -dependencies = [ - "num-traits", -] - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - -[[package]] -name = "quick-xml" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "quick-xml" version = "0.38.4" @@ -2377,18 +1354,22 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "range-alloc" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" - [[package]] name = "raw-window-handle" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "read-fonts" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" +dependencies = [ + "bytemuck", + "font-types", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -2416,24 +1397,6 @@ dependencies = [ "bitflags 2.11.0", ] -[[package]] -name = "renderdoc-sys" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - [[package]] name = "rustix" version = "0.38.44" @@ -2496,7 +1459,7 @@ dependencies = [ "ab_glyph", "log", "memmap2", - "smithay-client-toolkit 0.19.2", + "smithay-client-toolkit", "tiny-skia", ] @@ -2509,6 +1472,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "self_cell" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" + [[package]] name = "serde" version = "1.0.228" @@ -2540,14 +1509,12 @@ dependencies = [ ] [[package]] -name = "serde_repr" -version = "0.1.20" +name = "serde_spanned" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ - "proc-macro2", - "quote", - "syn", + "serde_core", ] [[package]] @@ -2557,36 +1524,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "signal-hook-registry" -version = "1.4.8" +name = "skrifa" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" dependencies = [ - "errno", - "libc", + "bytemuck", + "read-fonts", ] -[[package]] -name = "simd-adler32" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" - [[package]] name = "slab" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" -[[package]] -name = "slotmap" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" -dependencies = [ - "version_check", -] - [[package]] name = "smallvec" version = "1.15.1" @@ -2600,62 +1552,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ "bitflags 2.11.0", - "calloop 0.13.0", - "calloop-wayland-source 0.3.0", + "calloop", + "calloop-wayland-source", "cursor-icon", "libc", "log", "memmap2", "rustix 0.38.44", - "thiserror 1.0.69", - "wayland-backend", - "wayland-client", - "wayland-csd-frame", - "wayland-cursor", - "wayland-protocols", - "wayland-protocols-wlr", - "wayland-scanner", - "xkeysym", -] - -[[package]] -name = "smithay-client-toolkit" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" -dependencies = [ - "bitflags 2.11.0", - "calloop 0.14.4", - "calloop-wayland-source 0.4.1", - "cursor-icon", - "libc", - "log", - "memmap2", - "rustix 1.1.3", - "thiserror 2.0.18", + "thiserror", "wayland-backend", "wayland-client", "wayland-csd-frame", "wayland-cursor", "wayland-protocols", - "wayland-protocols-experimental", - "wayland-protocols-misc", "wayland-protocols-wlr", "wayland-scanner", "xkeysym", ] -[[package]] -name = "smithay-clipboard" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" -dependencies = [ - "libc", - "smithay-client-toolkit 0.20.0", - "wayland-backend", -] - [[package]] name = "smol_str" version = "0.2.2" @@ -2666,25 +1580,42 @@ dependencies = [ ] [[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" +name = "softbuffer" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" dependencies = [ - "bitflags 2.11.0", + "as-raw-xcb-connection", + "bytemuck", + "drm", + "fastrand", + "js-sys", + "memmap2", + "ndk", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", + "raw-window-handle", + "redox_syscall 0.5.18", + "rustix 1.1.3", + "tiny-xlib", + "tracing", + "wasm-bindgen", + "wayland-backend", + "wayland-client", + "wayland-sys", + "web-sys", + "windows-sys 0.61.2", + "x11rb", ] [[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "static_assertions" -version = "1.1.0" +name = "strength_reduce" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" [[package]] name = "strict-num" @@ -2703,55 +1634,13 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tempfile" -version = "3.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" -dependencies = [ - "fastrand", - "getrandom", - "once_cell", - "rustix 1.1.3", - "windows-sys 0.52.0", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl", ] [[package]] @@ -2765,31 +1654,6 @@ dependencies = [ "syn", ] -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tiff" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" -dependencies = [ - "fax", - "flate2", - "half", - "quick-error", - "weezl", - "zune-jpeg", -] - [[package]] name = "tiny-skia" version = "0.11.4" @@ -2816,13 +1680,29 @@ dependencies = [ ] [[package]] -name = "tinystr" -version = "0.8.2" +name = "tiny-xlib" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90a0ca3ee6a69f2ad28fd11621a4c3f03b371f366be500b64df260c4ffbafb4" +dependencies = [ + "as-raw-xcb-connection", + "ctor", + "libloading", + "pkg-config", + "tracing", +] + +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ - "displaydoc", - "zerovec", + "serde_core", + "serde_spanned", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.3", ] [[package]] @@ -2834,6 +1714,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.23.10+spec-1.0.0" @@ -2841,18 +1730,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ "indexmap", - "toml_datetime", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", - "winnow", + "winnow 0.7.14", ] [[package]] name = "toml_parser" -version = "1.0.8+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow", + "winnow 1.0.3", ] [[package]] @@ -2861,31 +1750,15 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ - "log", "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tracing-core" version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] [[package]] name = "ttf-parser" @@ -2893,26 +1766,6 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" -[[package]] -name = "type-map" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" -dependencies = [ - "rustc-hash 2.1.1", -] - -[[package]] -name = "uds_windows" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" -dependencies = [ - "memoffset", - "tempfile", - "winapi", -] - [[package]] name = "unicode-ident" version = "1.0.23" @@ -2926,38 +1779,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] -name = "unicode-width" -version = "0.2.2" +name = "uuid" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" [[package]] -name = "url" -version = "2.5.8" +name = "vello_common" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +checksum = "1bd1a4c633ce09e7d713df1a6e036644a125e15e0c169cfb5180ddf5836ca04b" dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", + "bytemuck", + "fearless_simd", + "hashbrown", + "log", + "peniko", + "skrifa", + "smallvec", ] [[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.20.0" +name = "vello_cpu" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +checksum = "0162bfe48aabf6a9fdcd401b628c7d9f260c2cbabb343c70a65feba6f7849edc" dependencies = [ - "js-sys", - "serde_core", - "wasm-bindgen", + "bytemuck", + "hashbrown", + "vello_common", ] [[package]] @@ -3104,476 +1954,89 @@ dependencies = [ "wayland-scanner", ] -[[package]] -name = "wayland-protocols-experimental" -version = "20250721.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-misc" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791c58fdeec5406aa37169dd815327d1e47f334219b523444bc26d70ceb4c34e" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - [[package]] name = "wayland-protocols-plasma" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-wlr" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" -dependencies = [ - "proc-macro2", - "quick-xml 0.38.4", - "quote", -] - -[[package]] -name = "wayland-sys" -version = "0.31.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" -dependencies = [ - "dlib", - "log", - "once_cell", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.85" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webbrowser" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f00bb839c1cf1e3036066614cbdcd035ecf215206691ea646aa3c60a24f68f2" -dependencies = [ - "core-foundation 0.10.1", - "jni", - "log", - "ndk-context", - "objc2 0.6.3", - "objc2-foundation 0.3.2", - "url", - "web-sys", -] - -[[package]] -name = "weezl" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" - -[[package]] -name = "wgpu" -version = "27.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" -dependencies = [ - "arrayvec", - "bitflags 2.11.0", - "cfg-if", - "cfg_aliases", - "document-features", - "hashbrown 0.16.1", - "js-sys", - "log", - "naga", - "parking_lot", - "portable-atomic", - "profiling", - "raw-window-handle", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "27.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7" -dependencies = [ - "arrayvec", - "bit-set", - "bit-vec", - "bitflags 2.11.0", - "bytemuck", - "cfg_aliases", - "document-features", - "hashbrown 0.16.1", - "indexmap", - "log", - "naga", - "once_cell", - "parking_lot", - "portable-atomic", - "profiling", - "raw-window-handle", - "rustc-hash 1.1.0", - "smallvec", - "thiserror 2.0.18", - "wgpu-core-deps-apple", - "wgpu-core-deps-emscripten", - "wgpu-core-deps-windows-linux-android", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core-deps-apple" -version = "27.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-emscripten" -version = "27.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-windows-linux-android" -version = "27.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-hal" -version = "27.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b21cb61c57ee198bc4aff71aeadff4cbb80b927beb912506af9c780d64313ce" -dependencies = [ - "android_system_properties", - "arrayvec", - "ash", - "bit-set", - "bitflags 2.11.0", - "block", - "bytemuck", - "cfg-if", - "cfg_aliases", - "core-graphics-types 0.2.0", - "glow", - "glutin_wgl_sys", - "gpu-alloc", - "gpu-allocator", - "gpu-descriptor", - "hashbrown 0.16.1", - "js-sys", - "khronos-egl", - "libc", - "libloading", - "log", - "metal", - "naga", - "ndk-sys", - "objc", - "once_cell", - "ordered-float", - "parking_lot", - "portable-atomic", - "portable-atomic-util", - "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "smallvec", - "thiserror 2.0.18", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "windows 0.58.0", - "windows-core 0.58.0", -] - -[[package]] -name = "wgpu-types" -version = "27.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" -dependencies = [ - "bitflags 2.11.0", - "bytemuck", - "js-sys", - "log", - "thiserror 2.0.18", - "web-sys", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" -dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections", - "windows-core 0.61.2", - "windows-future", - "windows-link 0.1.3", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", -] - -[[package]] -name = "windows-core" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement 0.58.0", - "windows-interface 0.58.0", - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement 0.60.2", - "windows-interface 0.59.3", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading", -] - -[[package]] -name = "windows-implement" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" dependencies = [ - "proc-macro2", - "quote", - "syn", + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", ] [[package]] -name = "windows-interface" -version = "0.58.0" +name = "wayland-protocols-wlr" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" dependencies = [ - "proc-macro2", - "quote", - "syn", + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", ] [[package]] -name = "windows-interface" -version = "0.59.3" +name = "wayland-scanner" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" dependencies = [ "proc-macro2", + "quick-xml", "quote", - "syn", ] [[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-numerics" -version = "0.2.0" +name = "wayland-sys" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", + "dlib", + "log", + "once_cell", + "pkg-config", ] [[package]] -name = "windows-result" -version = "0.2.0" +name = "web-sys" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ - "windows-targets 0.52.6", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "windows-result" -version = "0.3.4" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ - "windows-link 0.1.3", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "windows-strings" -version = "0.1.0" +name = "winapi-util" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", + "windows-sys 0.61.2", ] [[package]] -name = "windows-strings" -version = "0.4.2" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" @@ -3602,22 +2065,13 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - [[package]] name = "windows-sys" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -3644,39 +2098,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link 0.2.1", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -3689,12 +2117,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -3707,12 +2129,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -3725,24 +2141,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -3755,12 +2159,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -3773,12 +2171,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -3791,12 +2183,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -3809,17 +2195,11 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winit" -version = "0.30.12" +version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" dependencies = [ "ahash", "android-activity", @@ -3827,10 +2207,10 @@ dependencies = [ "bitflags 2.11.0", "block2", "bytemuck", - "calloop 0.13.0", + "calloop", "cfg_aliases", "concurrent-queue", - "core-foundation 0.9.4", + "core-foundation", "core-graphics", "cursor-icon", "dpi", @@ -3839,9 +2219,9 @@ dependencies = [ "memmap2", "ndk", "objc2 0.5.2", - "objc2-app-kit 0.2.2", + "objc2-app-kit", "objc2-foundation 0.2.2", - "objc2-ui-kit", + "objc2-ui-kit 0.2.2", "orbclient", "percent-encoding", "pin-project", @@ -3849,7 +2229,7 @@ dependencies = [ "redox_syscall 0.4.1", "rustix 0.38.44", "sctk-adwaita", - "smithay-client-toolkit 0.19.2", + "smithay-client-toolkit", "smol_str", "tracing", "unicode-segmentation", @@ -3877,16 +2257,16 @@ dependencies = [ ] [[package]] -name = "wit-bindgen" -version = "0.51.0" +name = "winnow" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" [[package]] -name = "writeable" -version = "0.6.2" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "x11-dl" @@ -3945,133 +2325,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" -[[package]] -name = "xml-rs" -version = "0.8.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" - -[[package]] -name = "yoke" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zbus" -version = "5.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91" -dependencies = [ - "async-broadcast", - "async-executor", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "enumflags2", - "event-listener", - "futures-core", - "futures-lite", - "hex", - "nix", - "ordered-stream", - "serde", - "serde_repr", - "tracing", - "uds_windows", - "uuid", - "windows-sys 0.61.2", - "winnow", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus-lockstep" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e96e38ded30eeab90b6ba88cb888d70aef4e7489b6cd212c5e5b5ec38045b6" -dependencies = [ - "zbus_xml", - "zvariant", -] - -[[package]] -name = "zbus-lockstep-macros" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6821851fa840b708b4cbbaf6241868cabc85a2dc22f426361b0292bfc0b836" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "zbus-lockstep", - "zbus_xml", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "5.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb94821ca8a87ca9c298b5d1cbd80e2a8b67115d99f6e4551ac49e42b6a314" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", - "zbus_names", - "zvariant", - "zvariant_utils", -] - -[[package]] -name = "zbus_names" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" -dependencies = [ - "serde", - "static_assertions", - "winnow", - "zvariant", -] - -[[package]] -name = "zbus_xml" -version = "5.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589e9a02bfafb9754bb2340a9e3b38f389772684c63d9637e76b1870377bec29" -dependencies = [ - "quick-xml 0.36.2", - "serde", - "static_assertions", - "zbus_names", - "zvariant", -] - [[package]] name = "zerocopy" version = "0.8.39" @@ -4092,117 +2345,8 @@ dependencies = [ "syn", ] -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "zeroize" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - -[[package]] -name = "zerotrie" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zune-core" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" - -[[package]] -name = "zune-jpeg" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" -dependencies = [ - "zune-core", -] - -[[package]] -name = "zvariant" -version = "5.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2be61892e4f2b1772727be11630a62664a1826b62efa43a6fe7449521cb8744c" -dependencies = [ - "endi", - "enumflags2", - "serde", - "winnow", - "zvariant_derive", - "zvariant_utils", -] - -[[package]] -name = "zvariant_derive" -version = "5.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da58575a1b2b20766513b1ec59d8e2e68db2745379f961f86650655e862d2006" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", - "zvariant_utils", -] - -[[package]] -name = "zvariant_utils" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "syn", - "winnow", -] diff --git a/Cargo.toml b/Cargo.toml index 150f82a..8f6728d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,13 +12,28 @@ readme = "README.md" exclude = ["CLAUDE.md"] [dependencies] -eframe = { version = "0.33", default-features = false, features = ["default_fonts", "glow", "wayland", "x11"] } secrecy = "0.10" +# The passphrase buffer is wiped on drop rather than merely freed, so a +# cancelled or submitted value does not linger in process memory. zeroize = "1" +# egui triple: these three MUST stay together on the 0.34 line. The CPU software +# backend (egui_software_backend) is the linchpin: its latest release pins egui +# 0.34, which pins egui-winit 0.34 and winit 0.30. +egui = { version = "=0.34.3", default-features = false, features = ["default_fonts"] } +egui-winit = { version = "=0.34.3", default-features = false, features = ["wayland", "x11"] } +egui_software_backend = "=0.0.3" + +# Windowing + pure-CPU presentation. No GPU/OpenGL/Vulkan in the tree: the UI is +# rasterized on the CPU by egui_software_backend and blitted with softbuffer. +winit = "=0.30.13" +softbuffer = "=0.4.8" +bytemuck = "1.25" + [dev-dependencies] -eframe = { version = "0.33", features = ["accesskit"] } -egui_kittest = "0.33" +# Headless UI tests: drive pin_dialog_ui with synthetic input events and assert +# on the resulting state, no window required. Pinned to the egui 0.34 line. +egui_kittest = "=0.34.0" [profile.release] strip = true diff --git a/src/main.rs b/src/main.rs index 2c849d8..9caaf17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,16 @@ +use std::cell::RefCell; use std::io::{self, BufRead, Write}; +use std::num::NonZeroU32; use std::process; -use std::sync::mpsc; +use std::rc::Rc; -use eframe::egui; +use egui_software_backend::{BufferMutRef, ColorFieldOrder, EguiSoftwareRender}; use secrecy::{ExposeSecret, SecretString}; +use winit::application::ApplicationHandler; +use winit::event::WindowEvent; +use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; +use winit::platform::run_on_demand::EventLoopExtRunOnDemand; +use winit::window::{Window, WindowId}; use zeroize::Zeroizing; fn percent_decode(s: &str) -> String { @@ -47,15 +54,32 @@ struct PinentryState { error: String, } -#[derive(Default)] struct PinDialogState { - // Keystrokes are appended here directly (never through an egui `TextEdit`, - // whose retained widget state and undo history would keep the plaintext), and - // the buffer is zeroized on drop. Moved into the `SecretString` on submit. + /// Backing store for the passphrase. Keystrokes are appended here directly + /// (never through an egui `TextEdit`), and it is zeroized on drop, so the + /// secret is not copied into egui's retained widget/undo state and is wiped + /// from memory when the dialog ends. Emptied into the result on submit. password: Zeroizing, - submitted: Option, // Some(true) = OK, Some(false) = Cancel + /// Some(true) = OK, Some(false) = Cancel. + submitted: Option, +} + +impl Default for PinDialogState { + fn default() -> Self { + PinDialogState { + // Reserve up front so ordinary typing does not reallocate (which + // would leave un-zeroized copies of the partial secret behind). + password: Zeroizing::new(String::with_capacity(256)), + submitted: None, + } + } } +/// Lays out the dialog's widgets into `ui` and records the user's action. +/// +/// Kept separate from the event loop so it can be driven headlessly in tests +/// (via egui_kittest): feed input events, run a frame, and read back the +/// resulting password / submitted flag without opening a window. fn pin_dialog_ui( ui: &mut egui::Ui, pin_state: &PinentryState, @@ -63,15 +87,6 @@ fn pin_dialog_ui( want_pin: bool, ) { ui.vertical_centered(|ui| { - // Make text field stroke more visible - let visuals = ui.visuals_mut(); - visuals.widgets.inactive.bg_stroke = - egui::Stroke::new(1.0, egui::Color32::from_gray(140)); - visuals.widgets.hovered.bg_stroke = - egui::Stroke::new(1.5, egui::Color32::from_gray(180)); - visuals.selection.stroke = - egui::Stroke::new(2.0, egui::Color32::from_rgb(100, 150, 255)); - ui.add_space(8.0); if !pin_state.error.is_empty() { @@ -90,10 +105,8 @@ fn pin_dialog_ui( } else { &pin_state.prompt }; - ui.label(prompt); - ui.add_space(4.0); - // Feed keystrokes straight into the zeroizing buffer instead of an + // Feed keystrokes straight into our zeroizing buffer instead of an // egui `TextEdit`, so the plaintext never enters egui's retained // widget state or undo history. Only a masked view is drawn. ui.input(|input| { @@ -113,15 +126,18 @@ fn pin_dialog_ui( } } }); - let dots = "\u{2022}".repeat(dialog.password.chars().count()); - egui::Frame::group(ui.style()).show(ui, |ui| { - ui.set_min_width(ui.available_width()); - ui.add(egui::Label::new(egui::RichText::new(dots).monospace())); - }); - if ui.input(|i| i.key_pressed(egui::Key::Enter)) { - dialog.submitted = Some(true); - } + ui.label(prompt); + ui.add_space(4.0); + let dots = "\u{2022}".repeat(dialog.password.chars().count()); + egui::Frame::group(ui.style()) + .inner_margin(egui::Margin::symmetric(6, 4)) + .show(ui, |ui| { + ui.set_min_width(240.0); + ui.add( + egui::Label::new(egui::RichText::new(dots).monospace()).selectable(false), + ); + }); ui.add_space(12.0); } @@ -145,6 +161,15 @@ fn pin_dialog_ui( } }); }); + + // Enter submits, Escape cancels. Read from the global input rather than a + // focused widget, since there is no `TextEdit` to own focus. + if ui.input(|i| i.key_pressed(egui::Key::Enter)) { + dialog.submitted = Some(true); + } + if ui.input(|i| i.key_pressed(egui::Key::Escape)) { + dialog.submitted = Some(false); + } } enum DialogResult { @@ -153,76 +178,259 @@ enum DialogResult { Cancelled, } -struct PinDialog { +type SbSurface = softbuffer::Surface, Rc>; + +thread_local! { + /// winit permits only one event loop per process (and a *failed* creation + /// still counts), so we keep one alive per thread and reuse it across + /// dialogs. This lets one gpg-agent connection drive several + /// `GETPIN`/`CONFIRM` prompts instead of failing with "EventLoop can't be + /// recreated". Access only from the thread that first created it — the main + /// thread, which is where winit requires the loop to run. + static EVENT_LOOP: RefCell>> = const { RefCell::new(None) }; +} + +/// Builds one egui frame, mutating `dialog` in response to input. +/// +/// `run` is used rather than the newer `run_ui` for API stability across the +/// egui 0.34 line; the deprecation is intentional. +#[allow(deprecated)] +fn build_frame( + egui_ctx: &egui::Context, + raw_input: egui::RawInput, + pin_state: &PinentryState, + dialog: &mut PinDialogState, + want_pin: bool, +) -> egui::FullOutput { + egui_ctx.run(raw_input, |ctx| { + egui::CentralPanel::default().show(ctx, |ui| { + pin_dialog_ui(ui, pin_state, dialog, want_pin); + }); + }) +} + +struct App { pin_state: PinentryState, dialog: PinDialogState, want_pin: bool, - tx: mpsc::Sender, + + egui_ctx: egui::Context, + sw_render: EguiSoftwareRender, + + window: Option>, + surface: Option, + egui_state: Option, + + result: Option, + error: Option, } -impl eframe::App for PinDialog { - fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - if ctx.input(|i| i.key_pressed(egui::Key::Escape)) { - let _ = self.tx.send(DialogResult::Cancelled); - ctx.send_viewport_cmd(egui::ViewportCommand::Close); - return; +impl App { + fn new(pin_state: PinentryState, want_pin: bool) -> Self { + App { + pin_state, + dialog: PinDialogState::default(), + want_pin, + egui_ctx: egui::Context::default(), + // softbuffer wants 0x00RRGGBB (BGRA byte order on little-endian). + sw_render: EguiSoftwareRender::new(ColorFieldOrder::Bgra), + window: None, + surface: None, + egui_state: None, + result: None, + error: None, } + } - egui::CentralPanel::default().show(ctx, |ui| { - pin_dialog_ui(ui, &self.pin_state, &mut self.dialog, self.want_pin); - }); + fn fail(&mut self, elwt: &ActiveEventLoop, err: String) { + self.error = Some(err); + elwt.exit(); + } + + fn redraw(&mut self, elwt: &ActiveEventLoop, window: &Rc) { + let Some(state) = self.egui_state.as_mut() else { + return; + }; + let raw_input = state.take_egui_input(window); + + let full = build_frame( + &self.egui_ctx, + raw_input, + &self.pin_state, + &mut self.dialog, + self.want_pin, + ); + state.handle_platform_output(window, full.platform_output); if let Some(ok) = self.dialog.submitted.take() { - if ok { + self.result = Some(if ok { if self.want_pin { - // Move the inner String out (leaving an empty one) into the - // secret, which zeroizes it in turn. - let value = std::mem::take(&mut *self.dialog.password); - let _ = self.tx.send(DialogResult::Pin(SecretString::from(value))); + // Move the inner String out (leaving the Zeroizing wrapper + // holding an empty one) into the secret, which zeroizes it in + // turn. + DialogResult::Pin(SecretString::new( + std::mem::take(&mut *self.dialog.password).into(), + )) } else { - let _ = self.tx.send(DialogResult::Confirmed); + DialogResult::Confirmed } } else { - let _ = self.tx.send(DialogResult::Cancelled); + DialogResult::Cancelled + }); + elwt.exit(); + return; + } + + let clipped = self.egui_ctx.tessellate(full.shapes, full.pixels_per_point); + if let Err(e) = self.present_frame( + &clipped, + &full.textures_delta, + full.pixels_per_point, + window, + ) { + self.fail(elwt, e); + } + } + + /// Rasterizes `clipped` into the softbuffer surface and presents it. + fn present_frame( + &mut self, + clipped: &[egui::ClippedPrimitive], + textures_delta: &egui::TexturesDelta, + pixels_per_point: f32, + window: &Rc, + ) -> Result<(), String> { + let size = window.inner_size(); + let (Some(w), Some(h)) = (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) else { + return Ok(()); + }; + let surface = self + .surface + .as_mut() + .ok_or_else(|| "surface not initialized".to_string())?; + surface.resize(w, h).map_err(|e| e.to_string())?; + let mut buffer = surface.buffer_mut().map_err(|e| e.to_string())?; + buffer.fill(0); + { + let pixels: &mut [[u8; 4]] = bytemuck::cast_slice_mut(&mut buffer); + let mut bref = BufferMutRef::new(pixels, size.width as usize, size.height as usize); + self.sw_render + .render(&mut bref, clipped, textures_delta, pixels_per_point); + } + buffer.present().map_err(|e| e.to_string())?; + Ok(()) + } +} + +impl ApplicationHandler for App { + fn resumed(&mut self, elwt: &ActiveEventLoop) { + // Modal: only redraw in response to input, not continuously. + elwt.set_control_flow(ControlFlow::Wait); + if self.window.is_some() { + return; + } + let title = if self.pin_state.title.is_empty() { + "pinentry-egui" + } else { + &self.pin_state.title + }; + let attrs = Window::default_attributes() + .with_title(title) + .with_inner_size(winit::dpi::LogicalSize::new(400.0, 200.0)) + .with_resizable(false); + let window = match elwt.create_window(attrs) { + Ok(w) => Rc::new(w), + Err(e) => { + self.fail(elwt, e.to_string()); + return; + } + }; + + let context = match softbuffer::Context::new(window.clone()) { + Ok(c) => c, + Err(e) => { + self.fail(elwt, e.to_string()); + return; + } + }; + let surface = match softbuffer::Surface::new(&context, window.clone()) { + Ok(s) => s, + Err(e) => { + self.fail(elwt, e.to_string()); + return; + } + }; + + let egui_state = egui_winit::State::new( + self.egui_ctx.clone(), + egui::ViewportId::ROOT, + &*window, + Some(window.scale_factor() as f32), + None, + None, + ); + + self.surface = Some(surface); + self.egui_state = Some(egui_state); + self.window = Some(window.clone()); + window.request_redraw(); + } + + fn window_event(&mut self, elwt: &ActiveEventLoop, _id: WindowId, event: WindowEvent) { + let Some(window) = self.window.clone() else { + return; + }; + + if let Some(state) = self.egui_state.as_mut() { + let response = state.on_window_event(&window, &event); + if response.repaint { + window.request_redraw(); } - ctx.send_viewport_cmd(egui::ViewportCommand::Close); + } + + match event { + WindowEvent::CloseRequested => { + self.result = Some(DialogResult::Cancelled); + elwt.exit(); + } + WindowEvent::RedrawRequested => self.redraw(elwt, &window), + _ => {} } } } +/// Shows the dialog described by `state` and returns its outcome. +/// +/// Reuses one process-wide event loop via `run_app_on_demand`, so it can be +/// called repeatedly across `GETPIN`/`CONFIRM` commands on one connection. Must +/// be called from the main thread (winit requirement) — the Assuan loop is. fn show_dialog(state: PinentryState, want_pin: bool) -> DialogResult { - let title = if state.title.is_empty() { - "pinentry-egui".to_string() - } else { - state.title.clone() - }; - - let (tx, rx) = mpsc::channel(); - - let options = eframe::NativeOptions { - viewport: egui::ViewportBuilder::default() - .with_title(&title) - .with_inner_size([400.0, 200.0]) - .with_resizable(false), - ..Default::default() - }; - - if let Err(e) = eframe::run_native( - &title, - options, - Box::new(move |_cc| { - Ok(Box::new(PinDialog { - pin_state: state, - dialog: PinDialogState::default(), - want_pin, - tx, - })) - }), - ) { - eprintln!("eframe error: {}", e); + match run_dialog(state, want_pin) { + Ok(result) => result, + Err(e) => { + eprintln!("pinentry-egui error: {}", e); + DialogResult::Cancelled + } } +} + +fn run_dialog(state: PinentryState, want_pin: bool) -> Result { + EVENT_LOOP.with_borrow_mut(|slot| { + if slot.is_none() { + *slot = Some(EventLoop::new().map_err(|e| e.to_string())?); + } + let event_loop = slot.as_mut().expect("event loop initialized above"); - rx.try_recv().unwrap_or(DialogResult::Cancelled) + let mut app = App::new(state, want_pin); + event_loop + .run_app_on_demand(&mut app) + .map_err(|e| e.to_string())?; + + if let Some(err) = app.error.take() { + return Err(err); + } + Ok(app.result.take().unwrap_or(DialogResult::Cancelled)) + }) } fn respond(out: &mut impl Write, msg: &str) { @@ -348,6 +556,8 @@ mod tests { want_pin: bool, } + /// A kittest harness that drives [`pin_dialog_ui`] for `desc`, with an empty + /// password and no submission to start. fn make_harness(desc: &str, want_pin: bool) -> Harness<'static, TestState> { let state = TestState { pin_state: PinentryState { @@ -367,8 +577,6 @@ mod tests { ) } - // The custom masked field is not an accessible widget, so drive it with - // synthetic input events and assert on the resulting buffer/state. #[test] fn test_type_password() { let mut harness = make_harness("Enter passphrase", true); @@ -378,6 +586,8 @@ mod tests { harness.run(); assert_eq!(harness.state().dialog.password.as_str(), "secret123"); + // Typing alone does not submit. + assert_eq!(harness.state().dialog.submitted, None); } #[test] @@ -404,9 +614,20 @@ mod tests { harness.run(); assert_eq!(harness.state().dialog.submitted, Some(true)); + // The typed value is preserved for the caller to take. assert_eq!(harness.state().dialog.password.as_str(), "mypass"); } + #[test] + fn test_escape_cancels() { + let mut harness = make_harness("Enter passphrase", true); + harness.run(); + + harness.key_press(egui::Key::Escape); + harness.run(); + + assert_eq!(harness.state().dialog.submitted, Some(false)); + } #[test] fn test_ok_button_submits() { From 1aef2ae9a6cc0ea20cffca143439af2f203568c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domen=20Ko=C5=BEar?= Date: Tue, 7 Jul 2026 10:10:19 -0600 Subject: [PATCH 3/3] Add an opt-in `x11` feature: X11 windowing backend and keyboard grab The default build stays Wayland-only and links no libX11. Enabling `x11` turns on winit's X11 backend and adds an XGrabKeyboard anti-snoop grab (Drop-guarded, retry-until-viewable, no-op off X11), covering every dialog window. --- Cargo.lock | 5 +-- Cargo.toml | 33 ++++++++++++-- src/grab.rs | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 32 ++++++++++++++ 4 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 src/grab.rs diff --git a/Cargo.lock b/Cargo.lock index 952a17a..37dfee6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -463,13 +463,9 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8ca3a47168e93a5cca79b7cb830817acaf07ebc1f8756aa368a6b2d6250f6ae" dependencies = [ - "bytemuck", "constify", "egui", - "egui-winit", - "softbuffer", "strength_reduce", - "winit", ] [[package]] @@ -1274,6 +1270,7 @@ dependencies = [ "secrecy", "softbuffer", "winit", + "x11-dl", "zeroize", ] diff --git a/Cargo.toml b/Cargo.toml index 8f6728d..585505a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,16 +20,43 @@ zeroize = "1" # egui triple: these three MUST stay together on the 0.34 line. The CPU software # backend (egui_software_backend) is the linchpin: its latest release pins egui # 0.34, which pins egui-winit 0.34 and winit 0.30. +# +# Everything below is Wayland-only by default. X11 support (winit's X11 backend +# and its libX11 loader) is off unless the `x11` feature turns it on, so an +# X11-free default build genuinely links no X11 code. egui = { version = "=0.34.3", default-features = false, features = ["default_fonts"] } -egui-winit = { version = "=0.34.3", default-features = false, features = ["wayland", "x11"] } -egui_software_backend = "=0.0.3" +egui-winit = { version = "=0.34.3", default-features = false, features = ["wayland"] } +# Only the core CPU rasterizer, not its bundled winit/softbuffer glue: that glue +# pulls `winit` with default features (which include X11), which would drag +# `x11-dl` into every build. We drive winit/softbuffer ourselves below and use +# only `BufferMutRef`/`ColorFieldOrder`/`EguiSoftwareRender`, all core types. +egui_software_backend = { version = "=0.0.3", default-features = false, features = ["std"] } # Windowing + pure-CPU presentation. No GPU/OpenGL/Vulkan in the tree: the UI is # rasterized on the CPU by egui_software_backend and blitted with softbuffer. -winit = "=0.30.13" +# winit's default features include `x11`; we opt out of them and re-enable only +# the Wayland set, so no libX11 is linked unless `x11` adds `winit/x11`. +winit = { version = "=0.30.13", default-features = false, features = [ + "rwh_06", + "wayland", + "wayland-dlopen", + "wayland-csd-adwaita", +] } softbuffer = "=0.4.8" bytemuck = "1.25" +# X11 keyboard grab (anti-keylogging). dlopens libX11 at runtime. Optional and +# Linux-only: pulled in exclusively by the `x11` feature. +[target.'cfg(target_os = "linux")'.dependencies] +x11-dl = { version = "2.21", optional = true } + +[features] +# Opt-in X11 keyboard grab. OFF by default so the default build stays Wayland- +# only and links no X11 code. Enabling it: (1) links the libX11 grab (x11-dl), +# and (2) turns on winit's X11 windowing backend (via winit + egui-winit) so the +# grab has a real X11 window to hold. +x11 = ["dep:x11-dl", "winit/x11", "egui-winit/x11"] + [dev-dependencies] # Headless UI tests: drive pin_dialog_ui with synthetic input events and assert # on the resulting state, no window required. Pinned to the egui 0.34 line. diff --git a/src/grab.rs b/src/grab.rs new file mode 100644 index 0000000..a16d956 --- /dev/null +++ b/src/grab.rs @@ -0,0 +1,121 @@ +//! Keyboard grab for the dialog window. +//! +//! On X11, [`try_grab`] calls `XGrabKeyboard` so that every `KeyPress`/`KeyRelease` +//! is delivered exclusively to the dialog while it is open, defeating other X +//! clients that would otherwise snoop keystrokes through the normal event path. +//! The returned [`KeyboardGrab`] releases the grab in its `Drop`, so the ungrab +//! runs on every exit path (normal return, early return, panic unwind); the X +//! server also auto-releases if the connection closes. +//! +//! On Wayland, macOS, and Windows the compositor already isolates input between +//! clients and offers no equivalent client-side global grab, so [`try_grab`] +//! reports [`GrabAttempt::NotApplicable`] and the dialog runs ungrabbed. +//! +//! This is not a complete anti-keylogger: a privileged local process can still +//! read the input devices directly or use raw-input extensions. It defeats +//! ordinary event-based snoopers on a shared X display. +//! +//! The whole module is compiled only under the opt-in `x11` feature; the +//! default build contains no grab code and links no libX11 loader. + +/// Outcome of a single attempt to grab the keyboard. +pub(crate) enum GrabAttempt { + /// The grab succeeded. Hold the guard for the dialog's lifetime. Boxed + /// because the guard keeps the whole libX11 function table alive. + Grabbed(Box), + /// No grab applies here (Wayland, a non-Linux platform, or libX11 missing). + /// Stop trying. + NotApplicable, + /// This is an X11 window but the grab did not take yet — typically because + /// the window is not viewable at the moment. Retry on a later frame. + Retry, +} + +#[cfg(target_os = "linux")] +pub(crate) use linux::{try_grab, KeyboardGrab}; + +#[cfg(not(target_os = "linux"))] +pub(crate) use other::{try_grab, KeyboardGrab}; + +#[cfg(target_os = "linux")] +mod linux { + use super::GrabAttempt; + use winit::raw_window_handle::{ + HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle, + }; + use winit::window::Window; + use x11_dl::xlib; + + /// An active X11 keyboard grab. Releasing happens in [`Drop`]. + pub(crate) struct KeyboardGrab { + xlib: xlib::Xlib, + display: *mut xlib::Display, + } + + impl Drop for KeyboardGrab { + fn drop(&mut self) { + // Safety: `display` is winit's live Xlib connection for the window we + // grabbed, used only here on the event-loop (main) thread. + unsafe { + (self.xlib.XUngrabKeyboard)(self.display, xlib::CurrentTime); + (self.xlib.XFlush)(self.display); + } + } + } + + pub(crate) fn try_grab(window: &Window) -> GrabAttempt { + // Only an X11 (Xlib) window has a display+window we can grab. winit's X11 + // backend hands out Xlib handles; Wayland yields Wayland handles (no grab). + let (display, xid) = match ( + window.display_handle().map(|h| h.as_raw()), + window.window_handle().map(|h| h.as_raw()), + ) { + (Ok(RawDisplayHandle::Xlib(d)), Ok(RawWindowHandle::Xlib(w))) => match d.display { + Some(ptr) => (ptr.as_ptr().cast::(), w.window), + None => return GrabAttempt::NotApplicable, + }, + _ => return GrabAttempt::NotApplicable, + }; + + // dlopen libX11 to get the function table; the grab targets winit's own + // connection (`display`), so it applies to the real dialog window. + let xlib = match xlib::Xlib::open() { + Ok(x) => x, + Err(_) => return GrabAttempt::NotApplicable, + }; + + // Safety: FFI into libX11 with winit's valid Display pointer and window id. + let result = unsafe { + let r = (xlib.XGrabKeyboard)( + display, + xid, + xlib::True, // owner_events: deliver normally to our window + xlib::GrabModeAsync, // pointer_mode + xlib::GrabModeAsync, // keyboard_mode + xlib::CurrentTime, + ); + (xlib.XFlush)(display); + r + }; + + if result == xlib::GrabSuccess { + GrabAttempt::Grabbed(Box::new(KeyboardGrab { xlib, display })) + } else { + // GrabNotViewable (window not mapped yet), AlreadyGrabbed, etc. + GrabAttempt::Retry + } + } +} + +#[cfg(not(target_os = "linux"))] +mod other { + use super::GrabAttempt; + use winit::window::Window; + + /// Placeholder grab guard on platforms without an X11 keyboard grab. + pub(crate) struct KeyboardGrab; + + pub(crate) fn try_grab(_window: &Window) -> GrabAttempt { + GrabAttempt::NotApplicable + } +} diff --git a/src/main.rs b/src/main.rs index 9caaf17..3d60210 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,13 @@ use winit::platform::run_on_demand::EventLoopExtRunOnDemand; use winit::window::{Window, WindowId}; use zeroize::Zeroizing; +// The keyboard grab is opt-in: with the `x11` feature off, none of this is +// compiled and no libX11 loader is linked. +#[cfg(feature = "x11")] +mod grab; +#[cfg(feature = "x11")] +use grab::{GrabAttempt, KeyboardGrab}; + fn percent_decode(s: &str) -> String { let bytes = s.as_bytes(); let mut out = Vec::with_capacity(bytes.len()); @@ -221,6 +228,12 @@ struct App { surface: Option, egui_state: Option, + // Held for the dialog's lifetime; dropping it releases the keyboard grab. + #[cfg(feature = "x11")] + grab: Option>, + #[cfg(feature = "x11")] + grab_done: bool, + result: Option, error: Option, } @@ -237,6 +250,10 @@ impl App { window: None, surface: None, egui_state: None, + #[cfg(feature = "x11")] + grab: None, + #[cfg(feature = "x11")] + grab_done: false, result: None, error: None, } @@ -248,6 +265,21 @@ impl App { } fn redraw(&mut self, elwt: &ActiveEventLoop, window: &Rc) { + // Grab the keyboard once the window is viewable (X11 only), retrying on + // later frames until it succeeds or is determined not to apply. Applies + // to every dialog window, passphrase entry and confirmation alike. + #[cfg(feature = "x11")] + if !self.grab_done { + match grab::try_grab(window) { + GrabAttempt::Grabbed(g) => { + self.grab = Some(g); + self.grab_done = true; + } + GrabAttempt::NotApplicable => self.grab_done = true, + GrabAttempt::Retry => window.request_redraw(), + } + } + let Some(state) = self.egui_state.as_mut() else { return; };