Thoughts on Rust GUIs

@rocallahan In a sense that list isn’t of different kinds of applications, but of different kinds of UI libraries, with the classification of applications being a mapping “the kind of application which needs the X kind of UI library”.

Could you say a bit more (you’ve mentioned a bit w.r.t. browsers and games) what the characteristics of the applications themselves are which lead to them having different requirements of their UI libraries?

GUIs are a big and complicated topic for sure. I’m doing a musicplayer and debugger in Rust and both needs a GUI. I used “dear imgui” for quite a while but in the end had to drop it because it simply didn’t scale to my use-cases.

I looked around quite a bit for alternatives but in the end settled for Qt being the best one to use (regardless of language) but I had issues with all the current wrappers for Qt so I ended up doing my own which I develop over here https://github.com/emoon/Rute (more detailed info here)

I can see the appeal of doing a native implementation in Rust for a GUI but it’s very important to be aware that is an enormous task and there are lots of opinions on the direction to take.

While I certainty support an effort for an “official” Rust GUI I think it will be hard to get there.

2 Likes

In a sense that list isn’t of different kinds of applications, but of different kinds of UI libraries, with the classification of applications being a mapping “the kind of application which needs the X kind of UI library”.

That's fair. Let's say I've classified applications by their requirements.

Could you say a bit more (you’ve mentioned a bit w.r.t. browsers and games) what the characteristics of the applications themselves are which lead to them having different requirements of their UI libraries?

I think applications in class 1 either only target one platform, or have enough resources to write custom UIs for each platform they target and deem it worth doing so to get the very best results. E.g. the applications OS vendors write for their own platforms.

Applications in class 2 are generally reasonably simple, or the complex parts can be factored out and handled some other way (e.g. writing per-platform UI in some places). They generally don't require customizing UI components in deep ways (difficult to do portably). Lots of undemanding business applications in this category.

Applications in class 3 include browsers and other applications that need very precise control and customization of UI components. For example browsers need to implement CSS layout and theming, the DOM event model, the complex CSS rendering model, features like spellcheck, handle absurd numbers of form controls on a page without crashing, etc etc. A very long time ago all browser engines used actual native form widgets but they all transitioned to reimplementing everything because it was the only way to make things work (even browser engines like Webkit and IE that really only cared about one platform initially!). I guess applications also fit into this category if they want Write Once Run Anywhere and a broad feature set without doing a whole lot of work --- by reusing an existing solution.

I think category 4 includes a lot of games because they tend to have limited UI needs; consistency with the underlying platform is not seen as an issue; performance is really important (and historically platform GUI toolkits have interacted poorly with high-performance graphics output); they don't need to interface much with other applications in the platform; and the UI needs of games don't generally evolve much over the maintenance lifespan of the game.

3 Likes

I’ve been working on GUIs for 15 years and can’t corroborate with that. A visual designer mostly complicates things, IMO. UI components, just like other components, evolve constantly. You have to have 2 sets of components - new/existing GUI components you are working on in source form and compiled components that are installed in the IDE/visual designer, and you have to keep the latter up to date, so they reflect the state of components actually used by your app. You won’t see a preview of a custom component in your designer (only a placeholder at best, possibly a designer error) anyway. Creating custom components is a drag because of this, you have to compile them, uninstall the previous version of a component from your visual designer and install a new one. You have to have some description language for your GUI (extra thing to know, can’t benefit from static typing). Bug fixing older versions of the app is also a drag because you have to have a visual designer with older components installed, at the state they were when that older version of the app shipped; simply checking out the old code branch is not enough. You can’t really do the same things from the visual designer you can do from code, so it inevitably feels limited. Finally, somebody has to work on the GUI designer itself, this time can be better spent elsewhere. For these reasons, I much prefer environments with fast compilation speed, live reload and type-safe GUI DSLs in the same language your app is written to any form of GUI designers.

8 Likes

Android might be great source of inspiration for new GUI framework. Recently added GUI components are amazing:

  • RecyclerView for complex and fast list layouts
  • ConstraintLayout for complex and flexible relative layouts
  • VectorDrawable for scalable SVG graphics
  • DataBinding to not mess around with update-refresh logic

It’s community GUI libraries also great:

Google recomendations for Android apps are very useful, clean and comprehensive. There might be something like that, especially for design.

Also important lessons might be learned from Android:

  • Don’t use weird DSL for GUI framework
  • Visual editors are buggy, complex and heavyweight
  • There is no need in any front-end scripting language
  • Theming should be done properly
6 Likes

Yes, and given modern HW, base it on HW Rendering GL/Vulkan etc.

1 Like

I’m new to Rust, but have a lot of experience with JS and Electron and well as GTK, etc. My take on application development is that GUI libraries such as GTK are dying a slow death. Apps I’ve built with Electron are easier to write, are more colorful, and move between platforms with literally no code changes. I read a blog that said Crystal was planning an Electron like clone. Why can’t Rust do the same? Having a language like rust for the back end would be incredible. I’m not talking about a connection between JS and Rust. I’m talking about about replacing JS. Since I’m new to Rust I have no idea how to go about this or how much work it would be. But what I’ve read here indicates that what is being discussed is an enormous amount of work.

1 Like

I believe if you read all the comments you'll see that there are several projects along these lines in the works.

It's worth noting that the only way to get the same code to move between platforms unchanged is if it doesn't strictly adhere to 'native' style, which some people really covet. Of native style, portability, and ease-of-development, you really only get to pick two, and different people have different priorities about these things.

Which is probably why a "single UI framework for Rust" is a bit of ephemera that will never satisfy everyone.

6 Likes

This got really rambley so I’m collapsing it. I try to predict the future and wish everyone could have more time to get future work done now.

As a user, I’d note that I prefer a consistent experience between platforms more than a truly native UI.

That said, modal dialogs that really should be handled by the OS, like file selectors, really should be the native one rather than a cross-platform fake, and confirm/cancel placement should match the platform’s.

As a developer, though, I definitely want to have the choice to write this above “semi-native” portable UI, or to drop down and write native OS UIs.

And in predict the future mode:

I think the ideal end position would be:

  • A Rust-first GUI platform, with “semi-native” support for tier1 platforms at least, as well as a fall back for platforms that don’t have that work done yet, and
  • For as many GUI platforms as possible, a mature and ergonomic(-as-possible) interop story for writing your “native” GUI in its host language, but writing logic in Rust. (Electron is in this category.)

The first would be the “default” choice for a GUI if you just want something that works across tier1 and maybe tier2 platforms, accelerated by fearless concurrency, but the native interop is there if you want to write a native API.

And ideally, in my ideal scenario, the high level Rust semi-native library plays well with the native libraries, so you can compose them to some extent.

Nothing will beat using the native language to write native GUIs, as the library serves the language it was written for (or in some cases, such as Swift, the language also serves the API design). Rust should not try to replace it, as there’s no way to beat GUI APIs in home turf (yet). Where we can stake a claim is in the semi-native zone, where Electron is used.

To that end, an Electron clone-ish based on Rust/WASM powering it, or even just a really good interop story, is a great place to start. Maybe once js-sys and web-sys are done, we can get node-sys and electron-sys? Maybe we can eventually make an Electron variant powered by Servo instead of Chromium? Who knows? I’m done trying to predict the future for now, but I’m watching with interest.

Whatever the solution, though, it should be async-first and multithreading-first to the very core.

4 Likes

An interesting counter-point here: IntelliJ has it's own open-file dialog. I don't know what is the motivation for this (historical reasons most probably), but the end result works better than native open file dialog, at least for me: IntelliJ knows more about programming-related file types then my OS, and the UI is more keyboard centric (completion & fuzzy search).

Overall, I definitely agree with yours factoring of the problem, though I'd probably bet on Flutter-like architecture for a cross-platform solution, rather then on Electron.

2 Likes

This is not true. A simple counterexample is a Rust macro that expands down to imperative GUI programming. Even if the macro language doesn't explicitly use type annotations, it still benefits from them by virtue of Rust itself benefiting from them.

I can’t speak to new components (Android 8.0 and after) but generally speaking, to me Android seems like the exact thing to avoid as inspiration for GUI frameworks. They’ve made a lot of mistakes*, and calling the API and design not nice is a real understatement.

*Perhaps this was to be expected, given the time constraints the Android team was under to get 1.0 out the door. The poor architecture just stuck around afterwards due to inertia. Even after the rendering stack got a major overhaul, the GUI-level APIs (understandably) remained largely the same so that didn’t fix anything either, at least within the confines of this thread.

The problem with electron is performance. Most electron apps straight up suck in that regard: Ever tried using slack? The Atom editor with a few plugins? They tend to suck up gigabytes of memory while doing nothing in particular, and are a real drain to CPU resources and battery life when they are doing something.

No, electron may perhaps be considered a partial prototype of what is needed, but electron’s model verbatim is definitely not the way forward.

8 Likes

I have been hoping for something like this. A web view renderer for html/css (and ideally only a modern subset) driven from wasm (and maybe even without any JS at all) or linkable as a crate for native rust to take events and manipulate DOM.

1 Like

I’m still keeping my eye on the web-view crate, as a light-weight way to generate a cross-platform UI.

4 Likes

Hello together.

I’ve wrote earlier in this thread. I’m working as (UX) Software Engineer for WPF and Qt (Qml) at Ergosign https://www.ergosign.de. My employer gives us a Friday per month to work on own projects called Focus Time. At this time I’m working with three of my colleagues (one Developer and two UX Designers) at a complete redesign and new development of the g(ui) framework OrbTk from the Redox OS project https://www.redox-os.org/. Our goal is to provide a modern, easy to use, fast and platform independent ui framework. We invest all of our knowledge as UX Developers and UX Designers to reach this goal. From API side our inspirations are Flutter https://flutter.io/ and React https://reactjs.org/.

As first result of our work we’ve released the dces framework as preview on crates.io https://crates.io/crates/dces. DCES is an Entity Component System framework, we are using in OrbTk. It is used to handle the instances and properties of the widgets (controls). You could use DCES also in games / game engines. Feedback is welcome!!!

A preview of OrbTk itself will follow at the end of this year / beginning of the next year.

22 Likes

That sounds more or less exactly like what Azul is / does: https://github.com/maps4print/azul

The OrbTk changes are now open. Check https://gitlab.redox-os.org/redox-os/orbtk.

5 Likes

I’m not an expert on gui programming by far, but from a pure dev experience point of view, I feel like the write once run anywhere approach (which no ui framework has actually achieved as of yet to my knowledge) should be the overarching goal of any future project for rust (or any language) in 2018. Doesn’t matter if your a cto at a major corp, a single developer working on a MVP for your startup, or a team of devs working on an open source project, the goal is always going to be the same, code and skill reuse.

The closest thing think of is uno for .net https://platform.uno and https://microsoft.github.io/reactxp for typescript. That being said, tradeoffs would have to be made, in the rust community, it seems like performance is always the biggest factor in everything, which is expected and understandable considering the goals of the language, but in this instance, I would expect usability applicability to take precedence over performance alone. That’s not to say that performance shouldn’t matter, but sometimes (most of the time ) good enough is all that’s needed.

All and all, I love the idea of the wasm approach using servo, it seems to be able to meet all of the right goals with the greatest degree of flexibility without sacrificing to much in terms of performance at the same time. Personally, I wouldn’t mind things not being platform native, that’s what theming is for, and designers are easier to come by than good programmers anyhow, that’s the approach that flutter has taken and it seems to be working out just fine.

1 Like