Rust doesn't like having shared mutable state, but event-based UIs have a global event loop and can mutate anything at any time.
Rust works best with strictly tree-shaped data structures, but event handlers turn trees of widgets into arbitrary webs with possibility of circular references.
Rust prefers everything thread-safe, but many UI toolkits can't even be touched from a "non-main" thread.
Rust's object-oriented programming features are pretty shallow, and Rust doesn't have inheritance. That makes it awkward to model most toolkits that have deep hierarchies with a base View type and a dozen of Button subclasses.
So instead of retrofitting mutable single-threaded OOP to a functional multi-threaded language, there's a quest to find another approach for UIs. This change of approach has worked for games. Rust wasn't nice for "class Player extends Entity" design, but turned out to be a great fit the ECS pattern.
And that's great, because they give plenty of useful insight into things that work and don't work when designing UI frameworks this way.
To be fair, it's not exactly like nobody realized this. More than one Rust desktop UI framework is explicitly React inspired, and it's not like FRP-based UI was non-existent prior to being popularized in web frameworks. Still, all the same... I suspect the best answers for how to do good UI in Rust are not far away from this paradigm.
I wonder if something like SwiftUI would work well for Rust.
I wonder if React-like approaches are going to work for Rust UI toolkits. They could even wrap some native controls, much like React does with DOM controls, or React Native with Android controls.
* Yes, I know elm-derive UIs are also a thing and have laid a lot of ground work in this area.
btw I've had great experience 10 or so years ago doing composition-based UI design in GTK with Python. When Maemo switched from GTK to Qt, the requirements on inheritance were one of my points of frustration and I got away with creating a couple adapter classes to avoid most of it.
This is also the problem with closures. And why you can't do Haskell/Ocaml style functional programming in Rust.
Rust has the reputation of being fast, but if you force everything into a tree, you are making big compromises from the start.
So when you e.g. mutate a variable, it doesn’t actually change until the next frame. which you can get by calling some sort of poll function. The poll function has mutable access to your entire widget tree, applies the updates, then you can have more UI with shared access
Rust is fast enough that i think performance won’t be an issue.
*of course Elixir/erlang is actually OO done right (actor model) but that’s another story
The readme mentions a macOS adapter prototype, but I don't see that directory. Does it exist in a different branch? I'd love to check it out – I'm pretty experienced with the Mac's AX implementation, but have basically no experience with AX on Windows...
I think this is vastly over-stating the technical churn of UI development on macOS.
While we're definitely seeing new UI toolkits introduced that are Swift-only (like the new Charts.framework[0]), nearly every Mac app Apple ships is written using AppKit. For example, I just verified (`otool -l PATH_TO_APP_BINARY`) that Mail, App Store, Notes, Music, Xcode[1], and Photos all link against AppKit, and none link against SwiftUI (on macOS 12.4 21F79, which I'm running).
There is, in my opinion, approximately zero chance that Apple either:
(A) rewrites all of the UI in all of their apps, replacing AppKit with SwiftUI, in even the medium-term, or
(B) starts treating AppKit apps as second-class citizens by introducing a new design language only available from SwiftUI.
Yes, we're going to keep seeing cool new widgets and features which are only available from Swift. No, the platform's design language is not going change in a way that makes AppKit apps obsolete.
[0]https://developer.apple.com/documentation/Charts
[1]I bet Xcode links SwiftUI somewhere for IDE integration, but I'm specifically referring to the UI implementation, parts of which have been in development since, like, NeXTSTEP and are certainly built using Objective-C & AppKit.
Similar to the Carbon/Cocoa split, I'm sure we'll see AppKit supported well into the future, especially since we just passed the latest major architecture transition. But that doesn't mean AppKit isn't a dead end.
Being in GUI business for almost 30+ years I shall admit that this above is true. And not just Rust but C/C++ are there too.
Real (a.k.a. practical) GUIs are multi-paradigm entities. Same GUI implementation may have React'ive alike widgets immersed into purely declarative DOM/widget tree with elements of immediate mode graphics on top or inside that.
It is just that GUI reflects complexity of real life - you cannot say that sickle and hammer are best tools for everything...
Back to Rust... As a language behind UI Rust is the worst language imaginable. That's primarily due to its strictness.
Object ownership graph in GUI is usually quite complex. yet it is dynamic and frequently contain loops. This situation is best handled by GCable languages. On-click-here-highlight-the-thing-there-and-remove-that-one.
Also each part of UI declaration needs it's own DSL: for UI structure definition, style system and logic behind the UI.
Before arriving with Sciter [1] I've tried [2] many things for UI: C++, D, Java, etc.
Conclusion: HTML/CSS/JS is the best (most flexible and multi-paradigm) solution that we've got so far. Not perfect of course but good enough. And considering existence of Sciter it can be fast and lightweight.
Practical example: RustDesk (https://github.com/rustdesk/ - remote desktop access) is using Sciter for UI layer and Rust for app logic layer. So it is using proper tool for each task.
[1] https://sciter.com [2] https://terrainformatica.com/2014/07/17/10-years-road-to-sci...
This is actually one thing I think rust has going for it, the procedural macro system makes it possible to embed reasonably arbitrary DSLs in rust.
egui, an immediate mode GUI on top of winit, is interesting. It works OK, but only does part of the job. It displays the GUI widgets, but doing something with them is your problem. Usually, you need each widget to have some persistent state. Managing that state is the user's problem. So is generating, queuing, and distributing events to and from the GUI elements. There's also something strange which causes some scrolled windows to vibrate between two states.
egui's default widgets are not very good looking. Light grey text on a dark grey background, super-thin scroll bars, that kind of thing. The aesthetics need work.
Overall, though, not bad. This stuff just needs to be used more. It has not had enough attention and polishing.
It's impressive that most of this works cross-platform, even cross-compiled. You don't even need a Windows machine to develop for a Windows target.
It has a little meta language for describing the UI that gets compiled when you compile the code and that was nice because it catches type and syntax errors at compile time.
I almost went with Tauri, but the cross-compile story didn't seem quite as good compared to Slint. Tauri does look nice though—web UIs are more flexible than Slint at this point. But for my simple little tool, Slint really hit the spot.
1. The language itself has a way of introducing compiler plugins that lets you express your own tree structures in a succint syntax (comparable to macros in Rust I guess)
2. Then they figured out most UIs are trees and came up with a Flutter-like UI tree declaration API with react-like re-renders. Thus Android Compose was born! This went mainstream because most android devs fell in love with this new way of writing GUI
3. Like flutter, they are slowly exposing Skia (underlying rendering engine) APIs as kotlin wrappers - I guess the project's name is Skiko
4. Now with all these pieces they are building a full-fledged UI toolkit that renders over every platform (including web) - Jetpack Compose
This is it! Browsers handle all of this. It's a ton of work. Many many gui kits start with just ASCII and really don't realize how deep the rabbit hole is for making all of this work.
And as always, if you haven't read them
I'm loosely following the progress of slint ui (formerly SixtyFPS), anything interesting in their approach or does it strictly matches one of your examples?
Even Qt, with it's built-in widgets is not enough (e.g. no multiple widgets/windows in non-main window), but there are some extensions/libraries/hacks to go around.
Recently, few years ago, imgui got proper support for these too. And flutter has one or more design docs around it - e.g. multi-window support, which might be the stepping stone to these.
Desktop apps are always going to be important in this space. Our game editor (Radiant) relies on this functionality when you use two, three or even more monitors.
The article opens:
> A few times a week, someone asks on the #gui-and-ui channel on the Rust Discord, “what is the best UI toolkit for my application?” Unfortunately there is still no clear answer to this question.
I would say if by 'UI toolkit for my application' you just want a way to make a GUI app, not a game or some kind of highly native or specific interaction needs thing, just use Tauri. No idea why it's not a 'top contender', it has an order of magnitude more GH stars than Druid, for whatever that counts; I can only assume they mean lower-level toolkits. (No affiliation.)
I just think someone new or unexposed to rust's going to see this and think it's way harder than it needs to be or is just to do something basic.
Iced, slint, sycamore, Dioxus , yew ... they all have quite different but very workable API surfaces. Yes, three of those target the browser, but there's nothing stopping them from building on a lower level Rust widget system instead. Even gtk-rs found a solid way to map a class structure to Rust extension traits.
Isn't the real problem in the weak fundamentals? Solid window and input handling, text rendering, layouting and 2d drawing libraries, ...
I see all the UI attempts struggling with those, and either implementing their own solutions or battling the existing ones (like winit).
I feel like if all those pieces were in place decent solutions could emerge.
The missing feature I need is supporting detachable tabs (like what chrome and sublime text have).
I think for productivity apps, this is very important. But implementing a windowing lib from scratch is not easy.
It’s now possible to implement an equivalent on all modern platforms which have a 3D GPU. An open-source example in C# https://github.com/Const-me/Vrmac#vector-graphics-engine That particular one requires GLES 3.1, but I’m sure (did it before) it’s also possible to implement comparable stuff on top of GLES2.
Waiting for target devices to have TFlops of FP32 performance, and good support for compute shaders, is less than ideal. Many currently sold phones, tablets, laptops, and even some desktop PCs, have limited GPGPU capabilities and/or performance. These currently sold devices gonna stay in use for at least couple years in the future.
Rendering things on CPU is less than ideal, because many devices have high-rez displays yet relatively slow CPU and especially RAM.
Am I missing something? What’s the reason there’re no cross-platform GPU-first 2D graphics libraries, despite GLES2 (or better equivalents) is now universally available, and have been for years?
Missing from this otherwise great list, is basic system-standard text navigation and editing. I get so annoyed when basic stuff like ctrl+end or ctrl+v doesn't work like they should.
Electron is not gaining momentum, it already is the standard.
No matter what people try to invent, it needs to do all Electron does but ways better.
It works on multiple platforms, and is flexible, and it's easier to find off the shelf pieces due to the web technology involved, and it's lighter than Electron. It's a no-brainer for me (and others, I think) if I'm starting a new GUI desktop project.
Maybe it is time for some experiments
Why reinvent the wheel?
He is undoubtedly highly knowledgeable about the subject, but this knowledge may be a curse in his case.
A mix of second system syndrome and Architecture Astronaut, trying to satisfy too many constraints can be a deadlock.
I think the sensible approach is starting with a Minimum Viable Product, cutting some corners and consciously making tradeoffs. And if success comes, then try to organically grow from there.