diff options
Diffstat (limited to '_posts/2025-04-13-2025-survey-of-rust-gui-libraries.md')
-rw-r--r-- | _posts/2025-04-13-2025-survey-of-rust-gui-libraries.md | 106 |
1 files changed, 54 insertions, 52 deletions
diff --git a/_posts/2025-04-13-2025-survey-of-rust-gui-libraries.md b/_posts/2025-04-13-2025-survey-of-rust-gui-libraries.md index 28eaf48..8afc523 100644 --- a/_posts/2025-04-13-2025-survey-of-rust-gui-libraries.md +++ b/_posts/2025-04-13-2025-survey-of-rust-gui-libraries.md @@ -350,7 +350,10 @@ Per the README, [Freya](https://freyaui.dev/) is “a cross-platform GUI library [Evidently](https://book.freyaui.dev/differences_with_dioxus.html), it takes the logic and structure of Dioxus and but renders everything itself instead of using Diet Electron. I did grumble about the Diet Electron-hood of Dioxus, so maybe this is the exact thing I was hoping for all along. -Freya’s latest stable release depends on the prior minor version of Dioxus, which may or may not have a slightly different `rsx!` macro (Dioxus 0.6 uses `rsx! {}` but Freya’s Dioxus 0.5 uses `rsx!()`, and I forget if that’s actually different or not), but this still looks a lot like our Dioxus code: +*Edit 2025-04-15*: I’ve been asked to run this again with the week-old release candidate rather than the year-old latest stable release, and I’ve ignored other year-old latest stable releases so it’s fair to do that here too. +Next time, unless I forget to, I’m deciding up front when to use a stable release vs an unstable release vs the main branch. + +Freya’s README example uses `rsx!()` rather than the Dioxus docs’ `rsx! {}`, and it still feels weird to me that those are interchangeable, but aside from that, the only difference from the Dioxus code is some component names: ```rust let mut text = use_signal(|| "Hello, world!".to_string()); @@ -365,13 +368,12 @@ rsx!(  -Narrator appears to almost understand the structure of this window — it’s seeing that there’s a text edit, at least — but it can’t actually figure out what any of the text actually is. -The IME activates, but in the wrong place on screen, and neither the provisional kana nor the final kanji actually shows up in the text input. -Even my WinCompose shortcuts don’t work. +Narrator sees the text label fine, but something’s gone wacky with the text input: Narrator can see that there’s a text input with those bounds on the screen, but it doesn’t seem like it actually knows the contents of the text input. +The IME shows up in the corner of the screen, and the provisional states aren’t displayed at all, but the final kanji land correctly in the text input once I accept them from the converter. There are some drawbacks to rendering things yourself instead of letting Chrome-via-Edge-via-WebView2 do it for you, it seems. Regardless, it’s extremely cool that Dioxus is set up in a way that makes this possible, and it’s extremely cool that someone’s trying to do it. -It is not, however, at a point where I would recommend using it. +I’m not sure that Freya is quite ready for serious use yet, but it’s definitely promising. ## fui @@ -1334,8 +1336,8 @@ Let’s pick some winners. If you’d rather take the quirks of CSS layout over the quirks of some other layout engine, [Dioxus](#dioxus) seems like a pretty reasonable choice; Diet Electron is definitely better than regular Electron, and that may be good enough for you, but it feels not-better-enough to me (although my sense of not-better-enough is [non-standard](https://en.wikipedia.org/wiki/Obsessive%E2%80%93compulsive_personality_disorder)). If you like DSL-driven UIs that are putting serious effort into developer tooling, [Slint](#slint) might be for you. If you want to avoid DSLs and macros and write only regular Rust, [egui](#egui) offers that. -If you’re looking for something to invest in early, [Xilem](#xilem) is basically usable now if you don’t mind pointing at the Git repo and putting up with some jank. -There are open issues for improving accessibility in [Floem](https://github.com/lapce/floem/issues/8), [Freya](https://github.com/marc2332/freya/issues/844), and [iced](https://github.com/iced-rs/iced/issues/552), so it may be worth at least keeping an eye on those issues, although the iced issue has been open for 4½ years now. +If you’re looking for something to invest in early, [Freya](#freya) and [Xilem](#xilem) are both basically usable now if you don’t mind living on the bleeding edge and putting up with some jank. +There are open issues for improving accessibility in [Floem](https://github.com/lapce/floem/issues/8) and [iced](https://github.com/iced-rs/iced/issues/552), so it may be worth at least keeping an eye on those issues, although the iced issue has been open for 4½ years now. I would not describe any of these as a super easy slam dunk obviously correct choice, but there are a lot of reasonable options available, and that’s better than 2021, where I was [longing for wxPython](/_posts/2021-10-24-2021-survey-of-rust-gui-libraries.md#whining) by the end of the post. Maybe better things are possible after all. @@ -1346,48 +1348,48 @@ Now if you’ll excuse me, I’ve got some `cargo clean`s to run: ## The Table -| library | works at all? | screen reader accessible? | IME works? | -|---------------------------------------------|---------------------------|---------------------------|------------------------------------------------------------------------------------------| -| [Azul](#azul) | linker hell | | | -| [cacao](#cacao) | macOS-specific | | | -| [core-foundation](#core-foundation) | macOS-specific | | | -| [Crux](#crux) | no desktop targets | | | -| [Cushy](#cushy) | yes! | nope | composer hidden, converter works | -| [CXX-Qt](#cxx-qt) | linker hell | | | -| [Dioxus](#dioxus) | yes! | yes! | yes! | -| [Dominator](#dominator) | web-specific | | | -| [egui](#egui) | yes! | yes! | composer works, Tab press stolen from converter | -| [Floem](#floem) | yes! | nope | nope | -| [fltk](#fltk) | yes! | with extra crate | yes! | -| [flutter_rust_bridge](#flutter_rust_bridge) | kinda, but state hell | yes! | kinda, but state hell | -| [Freya](#freya) | yes! | nope | nope | -| [fui](#fui) | qmake hell | | | -| [GemGui](#gemgui) | technically | | | -| [GPUI](#gpui) | yes! | nope | yes! | -| [GTK 3](#gtk-3) | unmaintained | | | -| [GTK 4](#gtk-4) | yes! | nope | yes! | -| [Iced](#iced) | yes! | nope | nope | -| [imgui](#imgui) | yes! | nope | nope | -| [KAS](#kas) | yes! | nope | nope | -| [kittest](#kittest) | only for testing | | | -| [Leptos](#leptos) | web-specific | | | -| [lvgl](#lvgl) | C dependency hell | | | -| [Makepad](#makepad) | yes! | nope | composer outside window, converter works | -| [masonry](#masonry) | yes! | content but not position | yes! but some temporary tofu | -| [Maycoon](#maycoon) | no text input widget | | | -| [Pax](#pax) | no Windows support | | | -| [qmetaobject](#qmetaobject) | no windows-msvc | | | -| [relm](#relm) | uses unmaintained GTK 3 | | | -| [Relm4](#relm4) | yes! | nope | yes! | -| [Ribir](#ribir) | kinda, but state hell | nope | composer hidden, converter works | -| [Rinf](#rinf) | does not use Rust for GUI | | | -| [rui](#rui) | yes! | nope | nope | -| [Slint](#slint) | yes! | yes! | missing glyphs in provisional states but logic works and final kanji displayed correctly | -| [Tauri](#tauri) | yes! | yes! | composer outside window, converter works | -| [tinyfiledialogs](#tinyfiledialogs) | not general-purpose | | | -| [Tk](#tk) | yes! | nope | yes! | -| [Vizia](#vizia) | yes! | structure but not content | converter outside window, everything works | -| [WebRender](#webrender) | too low-level | | | -| [windows](#windows) | i don’t know Win32 | | | -| [WinSafe](#winsafe) | yes! | yes! | yes! | -| [Xilem](#xilem) | yes! | content but not position | yes! but some temporary tofu | +| library | works at all? | screen reader accessible? | IME works? | +|---------------------------------------------|---------------------------|----------------------------------|------------------------------------------------------------------------------------------| +| [Azul](#azul) | linker hell | | | +| [cacao](#cacao) | macOS-specific | | | +| [core-foundation](#core-foundation) | macOS-specific | | | +| [Crux](#crux) | no desktop targets | | | +| [Cushy](#cushy) | yes! | nope | composer hidden, converter works | +| [CXX-Qt](#cxx-qt) | linker hell | | | +| [Dioxus](#dioxus) | yes! | yes! | yes! | +| [Dominator](#dominator) | web-specific | | | +| [egui](#egui) | yes! | yes! | composer works, Tab press stolen from converter | +| [Floem](#floem) | yes! | nope | nope | +| [fltk](#fltk) | yes! | with extra crate | yes! | +| [flutter_rust_bridge](#flutter_rust_bridge) | kinda, but state hell | yes! | kinda, but state hell | +| [Freya](#freya) | yes! | mostly, but some content missing | composer hidden, converter works | +| [fui](#fui) | qmake hell | | | +| [GemGui](#gemgui) | technically | | | +| [GPUI](#gpui) | yes! | nope | yes! | +| [GTK 3](#gtk-3) | unmaintained | | | +| [GTK 4](#gtk-4) | yes! | nope | yes! | +| [Iced](#iced) | yes! | nope | nope | +| [imgui](#imgui) | yes! | nope | nope | +| [KAS](#kas) | yes! | nope | nope | +| [kittest](#kittest) | only for testing | | | +| [Leptos](#leptos) | web-specific | | | +| [lvgl](#lvgl) | C dependency hell | | | +| [Makepad](#makepad) | yes! | nope | composer outside window, converter works | +| [masonry](#masonry) | yes! | content but not position | yes! but some temporary tofu | +| [Maycoon](#maycoon) | no text input widget | | | +| [Pax](#pax) | no Windows support | | | +| [qmetaobject](#qmetaobject) | no windows-msvc | | | +| [relm](#relm) | uses unmaintained GTK 3 | | | +| [Relm4](#relm4) | yes! | nope | yes! | +| [Ribir](#ribir) | kinda, but state hell | nope | composer hidden, converter works | +| [Rinf](#rinf) | does not use Rust for GUI | | | +| [rui](#rui) | yes! | nope | nope | +| [Slint](#slint) | yes! | yes! | missing glyphs in provisional states but logic works and final kanji displayed correctly | +| [Tauri](#tauri) | yes! | yes! | composer outside window, converter works | +| [tinyfiledialogs](#tinyfiledialogs) | not general-purpose | | | +| [Tk](#tk) | yes! | nope | yes! | +| [Vizia](#vizia) | yes! | structure but not content | converter outside window, everything works | +| [WebRender](#webrender) | too low-level | | | +| [windows](#windows) | i don’t know Win32 | | | +| [WinSafe](#winsafe) | yes! | yes! | yes! | +| [Xilem](#xilem) | yes! | content but not position | yes! but some temporary tofu | |