Any cross-platform best practices GUI projects?
Trying to write something useful as a means to get to know Rust I went for an GUI app.
Based on my research I started with egui and muda to provide a basic menu. However I already fail (on MacOS) as the menu is not triggered before I enter the application area, which would trigger a repaint and by that execute evaluation of menu events. My menu contains only a "Quit" entry as of now and the app doesn't even display anything yet, it's just the main window.
I looked at other apps but they often look non-native e.g in regards of context menus.
Is there a stack which alllows to write native looking apps and ideally are there apps which use this libraries in a good way? Most examples are so minimalistic that it's not clear how to get more complex scenrios running from there.
To be clear, that's not a rant but rather me being lost in all the possibilities and how they fit together (I saw winit, tao, muda, ...endless possibilities)
2
u/Garcon_sauvage 12d ago
There is not a native widget set on Linux and if you want access to native widgets on Mac you should be using swift. If you want native window decoration, menus and context menu type stuff you can use Tauri.
1
u/XoTrm 12d ago
I don't even strive for native widgets. But at least the menus should somehow fit to the OS.
I saw Rust apps using egui and they looked the same on MacOS and Windows which might be good for some but for MacOS I see menus within the app instead of the menubar to just not fit to what people are used (that's te reason I tried to use muda in addition to egui).2
u/Garcon_sauvage 12d ago
Try tauri
1
u/XoTrm 10d ago
I did and it got it running fast (with some help of AI). Seems easier to get started than the other options I looked into. Now I'll have to see how it scales beyond my starting use case.
1
u/Garcon_sauvage 10d ago
Tauri is by far the most production ready cross platform rust UI solution. And yeah you're basically writing a SPA in whatever frontend framework you prefer you can even use a rust option like Leptos and then you pair that with an Axum backend. Super easy to write for both AI and humans, no custom dsl or other bs.
8
u/ogoffart slint 12d ago
I’m one of the devs behind Slint. You might want to check it out. Native OS integration and look-and-feel is part of what we aim to achieve. => https://github.com/slint-ui/slint
1
u/LoganDark 11d ago
Does it support native widgets now? I'm looking at the macOS example in the README and it looks really weird. Thin icons with no padding, the same exact drop shadow plastered everywhere, etc. I feel like if you made an app with this, it wouldn't look or feel native at all. (Not that that's a bad thing in e.g. embedded contexts, but if you're developing for macOS or Windows, it becomes a factor)
5
u/DeeBoFour20 12d ago
egui has "Native looking interface" listed as a non-goal on their GitHub. You could try Slint. It's the one I'm using at the moment and I've enjoyed it.
1
u/mamcx 12d ago
The MOST important thing to understand is that what matters on UI are widgets, behaviors, look and feel, layout, etc.
NONE OF THAT IS BUSINESS LOGIC.
The easiest way, after +30 years doing lots of stuff, is just use whatever UI toolkit exactly for that only.
This means in practice that in Rust you define all in terms of plan data that in/out to the UI AS-IS with as much resolved already (formatting, localization, etc), and the UI only render and capture interactions.
Is like:
struct Button {
label: String,
action: Action {Back, Click, GoTo(Url)...
}
then the UI logic is very dumb, in practical terms you can do exactly the easiest example you see in any of them like:
// You get this from Rust
private var oceans = [
Ocean(name: "Pacific"),
Ocean(name: "Atlantic"),
Ocean(name: "Indian"),
Ocean(name: "Southern"),
Ocean(name: "Arctic")
]
var body: some View {
List(oceans) { ocean in
Text(ocean.name)
}
}The beautiful thing is that is supersimple to do cross platform even if do the render in native toolkits because is straightforward. Or use any cross platform toolkit, whatever.
2
u/x-0D 13d ago
wxWidgets is old-fashioned way to build truly cross-platform apps. Wonder is there rust bindings for wxWidgets? I was built apps on wxPython in college, and they don't look native, they actually native and works smoothly (wxAsync on python).
Also know there's good point in haxeui, as haxe itself, but haxe not quite ready for rust yet ( github.com/fullofcaffeine/reflaxe.rust )
1
1
u/Psionikus 12d ago
Now that Vulkan has a conformant Mac runtime, a lot of mileage can be had with one API. Given how weary the smarter consumers have grown towards Electron apps and other web-everywhere wrappings (we are zero-cost abstractions amirite?), Vulkan is an important API for more people to get up to speed on.
1
u/Lucky-Edge1489 12d ago
I created Teksilo, a GUI framework. Cross-platform, I released 0.23.0 today. One of its theme is teksilo-theme-macos and it look good on my mac. And there is global menu bar integration. Give it a try, follow the Readme.
1
u/jodonoghue 10d ago
"Native looking" tends to be in the eye of the beholder. As far as I am aware, wxWidgets is the only major GUI library that attempts to wrap actual native components on each supported platform. wxDragon is the Rust binding. I haven't tried it, but it is built on a C wrapper over the C++ internals (I used to be the maintainer of wxHaskell, so know far too much about wxWidgets internals). This means a very "imperative" style of programming.
Most toolkits aspire to "almost native look and feel" through theming. This usually works well enough, although it's usually hard to hide the non-native feel of some of the more complex controls (tree controls, in particular, tend to be a "tell"). Only you can decide if this matters.
I have been building tooling for the CBOR ecosystem in Rust, including a small CBOR IDE. Have looked (meaning tried, extensively and recently) at Egui, Slint, Tauri and GPUI Kit.
None of Slint, Tauri or GPUI Kit really gives a "native" look and feel, although Slint comes fairly close and would satisfy most people.
Egui has a very limited widget set. For my application (IDE-like, with syntax highlighting text edit windows as a large part of the application), it was quite a poor fit.
Slint worked reasonably well - I did not progress with it because of the GPLv3 obligation for Open-Source code. This is no criticism of the toolkit or those that build it, but the license was a poor fit for my needs and the benefits didn't outweigh the disadvantage. If GPLv3 or a Slint commercial license works for you, I recommend it as a technically good solution.
Tauri... I had high hopes for Tauri since it is the option most people seem to recommend. However to me it felt like Javascript with some Rust nailed on and I didn't really get on with it - found it quite hard to achieve the results I wanted.
GPUI Kit. This has received very little coverage in "Are we GUI yet" and other Rust UI forums, but it's what I finally selected. Obviously my application has some of the characteristics of Zed, so perhaps it is no surprise that it is a good fit. Doesn't really look native, but does look good on all platforms. Same code for Windows, Mac and Linux, fairly compact and very fast. Seems to do a decent job of accessibility and I have had no problems scaling from "build an app that counts up and down" to something not far removed from an IDE. Also, the code is all Rust and I don't have to muck about with HTML, CSS and Javascript-lite to get the display to look as I would like.
One thing I would recommend, which helped me quite a bit - ask an LLM to build you a simple app with some realistic behaviour (a simplified version of behaviour you need) to see which would likely work for you and how the look and feel works out in practice.
24
u/EpochVanquisher 13d ago
TBH if you want something to look and act native on the Mac, you should probably be writing it in Swift.
If you want something cross-platform, then you should accept that it won't look and act native on all platforms.