This thread is a snapshot of some recent conversations about Rust GUIs. This is still a few steps away from a plan, but hopefully we can generate some good discussion around these ideas and what we might explore next.
Rust needs a strong solution for GUI programming. You can work with various existing GUI toolkits, but these are generally fairly thin wrappers over existing systems that have their own learning curve. This prevents you from easily moving your app to another platform, or even reusing the knowledge of one platform on another.
Finding the right approach for Rust
Flora Cat (@FloraCatz on twitter) has been exploring what it might mean to try to map Rust on OOP GUI styles. Unsurprisingly, it appears this is a bit tricky. Rust’s ownership model makes it difficult to model the circular references that some GUI frameworks allow.
The question then is “what’s a more natural way to model a GUI in Rust?” There’s some recent work here that builds on reactive programming. React and Elm give a way of working with events and state that is closer to a functional approach. Elm’s approach takes in the state of the world, and rather than manipulating it directly, you work with the Elm system to handle each update to state, side effect, or even multi-step process. While there’s a lot to be learned working in this model, it too isn’t an exact fit with the more pragmatic Rust approach.
Still another approach could use the channel mechanism that comes with Rust. Rather than GUI components owning each other, or having a runtime reactive system, the channel mechanism would allow components to message back to the programming logic and vice versa. Some research would need to explore if the overhead created by channels pays for itself.
Native vs One-size-fits-all
There’s a fork in the road early in the design of a GUI: should it work directly with the GUI elements that are native to the platform, or should it elect to have a more uniform, one-size-fits-all approach where the app works and looks the same regardless of the platform? There are pluses and minuses to each approach.
Native GUIs
Native GUIs retain the look-and-feel, and will instantly be familiar to users of the platform. Additionally, relatively tricky nuance like how fonts render, how text input works (including multi-language input), keyboard shortcuts, and more will match what the user expects, reducing friction.
This is approach is partly served by the existing native GUI wrappers. That said, there’s an opportunity for a library that works across these native wrappers and offers a Rust-like, single interface to GUI development. The resulting code could then more easily port between platforms.
Creating a universal wrapper gives the programmer a universal API, but is not without its drawbacks as the resulting API is the intersection of the supported platforms. To get the full capability of the platform would need extensions (see below).
One-size-fits-all
Java, wxWidgets, qt, and more have created a more uniform platform that may look similar to the native platform but is built from a more central design.
This approach is less prone to breakage of the underlying platforms, as it only wraps them where necessary. On the other hand, the maintenance cost likely moves to keeping up-to-date with the changes in the native GUIs.
Extensions and crates.io
Rust has a strong friend in cargo and crates.io when it comes to extending existing applications with more functionality. Similarly, the GUI toolkit has a need for optional capabilities. If someone codes up a new widget, it should be easy to share with others on crates.io. Likewise, if the GUI works a bit more universally, having platform specific features and additions will be welcome, and if they’re easily found on crates.io, all the better.
Having cake and eating it, too
I mentioned earlier that there’s a fork in the road between creating native widgets and a more one-size-fits-all approach. Perhaps this GUI library could take a similar approach to some of the thoughts around the compiler and new platforms. Maybe the one-size-fits-all GUI is just another platform you can target with the library: eg) gtk, windows, macOS or rust-ui.
Rough sketches but no solid answers
I’ve cobbled together the notes from some of the recent twitter discussions, but I’m curious to hear other folks thoughts. What approaches are better? What platforms should be included first (ie, should we include web-based UIs or focus on native platforms)? Are there some key application areas it should work well in first (this might help us answer the previous question)? Do you have your own GUI experiments you want to share the results of?