Thoughts on Rust GUIs


+1! If our goal would be to make good native GUIs for rust programs, we should be focusing on a good way to let a rust backend communicate with a frontend written in Swift for macOS, a C# one for Windows and one written in whatever for linux. Imo thats the only way to write a good native GUI is to write it in the way they are intended to write. Everything else is a lesson in frustration.

I’ve never seen a cross platform GUI library thats tries to be native really succeed. The universal Wrapper tends to be useless, the “we do our own, but emulate platform looks and behaviour” tends to land deep in the uncanny valley. Also, one thing to consider: Doing the tedious, miserable work chasing platform behaviour to create an at best mediocre product is not a good basis to attract volunteer work…

Imo, if it’s going to be cross platform, then native standard functionality like file and color pickers, standard key combinations etc. plus non-native overall GUI seems to be a sweet spot.


What do you think about React Native approach? Basically, they provide React as API/engine which works the same on all the platforms, and a set of bridges to native components (there is no guarantee that all the components will present on all the platforms). Their mantra is “learn once, write anywhere”, which IMO works great for mobile platfroms (and they show competing performance with the pure native applications).

Flutter uses another approach; they went through a hassle of reimplementing all the components from scratch in Dart (AFAIK Qt went the same way). It is definitely not a short-term project, but it gives a great portability since they control all the drawing and, thus, can have a better portability to exotic platforms (e.g. with such an approach, we don’t need to implement a whole set of bridges to all the components for every single platform, instead, we only need to adapt the drawing engine and we can run e.g. Mac OS look application on Redox), but implementing a native feel theming and accessibility will be a tedious task.

There is a project called Toga (written in Python), which follows React Native ideas targetting desktop OSes first (though they have experiments with mobile and web platforms) and it seems that they are doing great (though, they don’t have enough contributors to polish the project to the level of React Native in terms of feature-completeness and documentation).

I like React Native / Toga approach the best, and I believe it is an order of magnitude easier to implement a single API with bridges to native components than reimplement the whole drawing from scratch.

P.S. Another project I want to bring to this discussion is Yoga, which is a cross-platform layout engine which implements Flexbox. It may or may not help someone with an implementation of layout system.


First, i just wanted to say that my last post was quite negative. I don’t intend to devalue projects that follow a paradigm i don’t like, so i’ll answer this post and try to expand a little bit.

I haven’t worked with react native specifically yet (but have worked with toolkits that are comparable in this regard), so take this with a grain of salt: The problem is that this prohibits a lot of the stuff some applications need. Many applications tweak native components (often that happens through subclassing, and that does not fit into this model). Native components on different platforms may be not equivalent for all the usecases of a specific application.

If an application fits into the common denominator of all standard UI-components and no further control is needed, this can work out great. But i cannot imagine writing a complex, UI-heavy program like a digital audio workstation or an image manipulation program that way.

Side note: maybe this is in indicator that the problem space of this discussion is underspecified. What are the programs that our hypothetical GUI-framework should enable?

I’ve worked with QT for a few years for a job, and i’ve a ton of appreciation for the project. But it just never looks quite right… a little bit like the uncanny valley. That can be jarring or even confusing, when a component that mimics a native one behaves differently in subtle ways. Also, like you said, it’s an unholy amount of work. If a project like QT, with all their resources and all their expertise cannot pull it off properly, i’d wouldn’t want to try it…

On a general note: Maybe i should backtrack a little bit. One of the assumptions i made, but didn’t specify, is that rust niche in the desktop space is more in the “complex” territory. I don’t see the “wrapper around common native components” approach work for that, but there is certainly some areas where thats the right solution.

On an even more general note: “We” hackers and computer scientist love abstraction and slicing up the problem space into neatly separated sections where elegant solutions can be found. But (in my experience) UIs, information design, layout in general and similar problems don’t let you do that. Content cannot be separated from the form it’s presented in, form easily (mis-)communicates as much as the content itself and delightful UI-solutions may require unreasonable amounts of customisation. Imo applications should be able to do that.


I too, on reflection, found my original response more negative than I intended. I agree with everything you’ve said above pretty much for the same reasons you’ve articulated.

In my experience, uniformity of application GUI (within reason) is nothing more than marketing ploy (one that every few years advocates some new “paradigm” that is supposedly the be-all, end-all only to be abandoned as “legacy” the next cycle). A GUI library is useful if the following is true:

  • Customizable (styling/theming/user-overridable)
  • Extensible (Application can extend/inherit components and create new components easily)
  • GUI implements widely accepted standards, but, does permit diverging from those standards as needed for the specific application
  • Looks the same (or nearly so) on all platforms (given using the same theme/style/overrides)
  • Permits access to the lowest-levels of the rendering and events stack from application code if necessary (but doesn’t require it)
  • Ability to be themed/styled/customized such that it looks pleasing on and behaves compatibly (withing reason) to the “Native” GUI

What is NOT important:

  • Looking exactly like the “Native” (whatever that is even supposed to mean these days)
  • Behaving exactly like the “Native” GUI
  • Being the actual “Native” GUI (this one is particularly counter-productive in my opinion)


My requirements are:

  • Accessible by default. Especially on Windows where all the tooling is there and applications have no excuse to not implement the necessary interfaces.
  • Use native bits wherever possible. Especially for things like file selection dialogs where often the entire thing is pre-made and ready to use with minimal effort, such as IFileOpenDialog on Windows.
  • High DPI support. Everything should be designed in a way that the user has no choice but to write their application in a manner that supports high DPI.
  • Pure Rust. Should not depend on any external libraries other than system libraries.


Couldn’t agree more. I must admit that i’m out of my depth on that one. All GUI work i did was in industry automation, where assistive technologies where not a big concern, or for the web.

Do you know if it’s possible to abstract over the OS capabilities? Of course Windows is a priority here, but the Mac is quite important too, since afaik a lot of people with visual impairments use Apple stuff.

It may be good to have folks who use assistive technologies themselves on this hypothetical GUI project. Also, missing accessibility should be an automatic veto for a feature.

I’d say, use native bits wherever sensible. The file dialog would be the prime example. Also standard key combinations. In the end, it’ll be a value judgment on a case by case basis.

My first thought was: “Yeah, that goes without saying”. But one has to be very careful to not bake in any assumptions between pixels and actual size.


Just to dig in a bit more, what cases would it make sense to be intentionally not the native experience?


The cases where one would have to sacrifice portability or flexibility. Take text fields for example. They are commonly extended with syntax highlighting and other live feedback about the inputted text and they are often styled quite heavily. Providing a unified interface for that will prohibit a lot of stuff or will leak platform details. Also, on most platforms they own the content, which could clash with a more functional data-flow based approach and they handle unicode in a way that could inject platform dependent quirks into the whole framework.


Using native file selectors and other controls like that is fine. Trying to use exclusively native controls has a lot of downsides- least-common-denominator support, lack of control over the rendering implementation, etc.

Native buttons/textboxes/etc is probably not worth it. Windows doesn’t even have a single native version of these at this point- there’s Win32 and WPF and UWP, with no clear “winner” in terms of the way forward.

So reimplementing the primary set of controls in a way that can be composed with whatever idioms we come up with for custom controls and state management, usefully hardware-accelerated (i.e. like WebRender or QtQuick, not like WPF or pre-WebRender browsers), and themed using the same APIs across platforms, seems far more desirable to me.


That might be true for some widgets, where it’s just as easy to draw your own. I mentioned textboxes a bit earlier in the thread, and how I found these to be extra tricky to do. Input sources can be different types, plus dealing with multi-byte characters, different kinds of unicode, selection/copy/paste like native, etc. It was just a lot of details to get right. I think @madmalik’s comment says something similar (though correct me if I’m wrong). Maybe there’s a way to have the native functionality without going all the way to being the native widget?

This is a good point, and why it’s even hard to say “native widgets” for a give platform, since there might not even be just one set of native widgets. Same issue on Linux, which doesn’t have native widgets so you end up having to pick gtk, qt, or both.

Events are another thing that got brought up early in the thread. Each UI system seems to have its own event system and as you pointed out earlier in the thread, each system is paired up with a language that can work pretty well with it. There are some experiments we need to do here, but perhaps there is a system that feels native to Rust (like the reactive ones that folks have pointed out). And this system would need to work well with the native widgets we do decide to support.


The question of text input is a bit more interesting when you consider internationalization- I’m not as familiar with text input APIs as I am with accessibility APIs. I suspect they’re at least as (if not more) applicable to non-native controls as the accessibility APIs are, but it would be worth investigating.


To summarise the discussion:

  • there seems to be somewhat of a consensus (?) to not rely on native component (whatever they may be, since that is not always clear), but use them where it makes sense.
  • Accessibility is a major concern. More expertise is needed.
  • There seems to be a push for Flux inspired data model, tailored to rust strengths and weaknesses and not a lot of appetite for object based solution in the QT/Swing/every other GUI toolkit from that era sense

Imo its time to shift the discussion into another avenue? It’s getting confusing here I’ve made a gitter room since that seems to be the preferred medium for working groups. Maybe thats a start?


Hi @all. Currently we working with a group of three people from my work on an update for OrbTk. We are one user experience designer and two ui developers (one Qt/Qml developer and one Qt/Qml + WPF developer). Our plan is to create a fast and easy to use pure Rust ui framework. We are strongly oriented towards and, because we think such an approach is good to implement with / for Rust. We’ve started with the planning and implementation last week.


Excellent, I’ll hop over there as well. And thanks for the summary, I think that’s a good starting place.