Rik Arends has been working on a cross-platform IDE in Rust called Makepad [1]. It has a custom UI stack that targets wasm/webGL, osx/metal, windows/dx11, and linux/opengl. His premise (which is fairly ambitious) is to work in both 2d and VR environments. It's been fun to watch. There's a demo for the wasm target. [2]
I was very impressed as well. On a desktop with a hardline it loaded instantly however the text is so small I can't make it out. Zooming gives things different degrees of fuzziness, with 150% zoom the least fuzzy (but still fuzzy).
The online version is really nice. When thinking about the benefits of WASM, I have definitely considered sharing code between client and server, but I never really thought about the potential of sharing code between native clients and web clients. It's kind of a different concept of a progressive web app, and it seems really powerful!
This is very cool. Especially the animate into compact code view when holding down the alt key. Is there an extension with similar functionality in any other editor?
Cool indeed, though I foud on Firefox that alt both toggled compact code view and toggled the Firefox menu bar, causing the display to jank around. Hope this is fixable.
The issue I see with a Rust GUI framework that has a target to be native on multiple platforms is that certain platforms (iOS, macOS) have their toolkits so tightly bound to a certain language (Objective-C for Cocoa, Swift for SwiftUI) that it just doesn’t seem feasible to call into it without making using horrible, hacky, unidiomatic Rust code. I’ve seen projects that aim to support macOS literally having code like NSArray(msgSend!(objc::Class(“NSArray”).unwrap(), new)) and it’s just so awful :(
Using the widget set provided by the platform is not easy, and that's not what druid tries to do. Rather, there's a platform abstraction layer (druid-shell) that takes care of all this stuff for you, and has all that nasty unsafe code in it, then it draws its own widgets. We try to feel more "native" in that we're using platform menus and so on. It's certainly possible to be more native (calling into Cocoa widgets) or less (using Web technology), but I think what we're doing is a good pragmatic approach.
Of course, things have gotten a bit postmodern, even on macOS there is no single widget toolkit, but basically a series of choices of what technology to build on. I'm actually not sure that binding other languages to SwiftUI is going to work well at all, but in Objective-C it works fine, just isn't very smooth. On Windows, I've generally found COM to be quite pleasant, and noises coming from Microsoft suggest that story will become even better.
I have never seen this go well in practice :( Qt and Flutter do this and the experience is just…not great. Do you have any ideas on how to do better than them if you're using this approach?
To be clear, we're focusing on the use case of a font editor, where you're mostly interacting with highly custom views, much less so with layouts composed of stock widgets.
As I said elsewhere, increasingly we're in a world where there isn't a standard set of platform UI widgets. I think that was the case when we had Cocoa on macOS, but on Windows it's a choice between MFC, WinForms, WPF, WinUI, and those are only some of the choices offered by Microsoft itself.
It's a good question, though. It's possible somebody will figure out a good way to abstract over officially supported platform UI toolkits, and if so, that might become a compelling choice. This is one reason why the main point of my blog is that we need to figure out the best approach, rather than just assuming we know what to build.
MFC and WinForms both just abstractions over Win32. WPF was clearly targeting being indistinguishable from the old widgets and had a much better success rate than other reimplementation attempts. It's really only with UWP/WinUI that you'd notice the difference without going searching and that has received a lot of consequent complaints.
Paint.NET is the one app I've used extensively that I'm aware of being a WPF app, and that's because I remember reading a dev blog about implementing aero glass when 4.0 was being developed.
There are some advantages to this approach that often go unmentioned. Native widgets often have ad-hoc limitations based on their legacy, for example limits on composing/nesting widgets (can a list box contain a list of arbitrary widgets?) and system resource limits (e.g. windows handles). Attempting to build a cross-platform UI that maps to different legacy systems each with their own quirks and limitations, will never produce something better than QT or Flutter IMHO.
You’re right, I think this is the first time I’ve heard someone mention this. I was actually quite surprised when SwiftUI came out because in Cocoa/Cocoa Touch there is a clear set of things you “can” do and everything else would just break and the new declarative language allows (and even encourages) very strange combinations. I haven’t used it a whole lot, but it seems like they’ve done a pretty good job making it mostly work.
Would it make sense for Rust to have UI primitives that are named the same as SwiftUI's?
e.g. Text, HStack, VStack, ZStack, List, ForEach, Button(action, label)
Even if they don't output the same widgets on all OSes, I think just having a shared convention might be a good first step towards learn-once/write-native-everywhere crossplatform UI.
That would kinda suck for everyone who's used to wpf, qt, swing, gtk+, etc, bootstrap, whatever came before wpf, (winforms? Don't remember) etc etc. "Just copy whatever Apple does" seems like the worst possible solution for a cross platform widget naming convention out of many possible bad solutions.
Naming stuff matters a lot less, (but still sucks) but if you pick UI system and copy all its primatives, you're guaranteed to end up with a bunch of widgets that really, really suck in several native widget sets.
Ultimately, there's not a good way to do cross platform UI. It's always going to either be mediocre on all platforms, or really bad on every platform except one. At best, it will be ok for a while, and then one platform will redefine what "native" looks like and now all of the tradeoffs you've made so that it's mostly ok are just technical debt.
I don't mean to piss on anyone's parade, but cross platform UI is probably the hardest problem in software engineering. There have been a dozen or so teams of people smarter than us who have tried and failed.
If it were my job to make a cross platform UI system for rust, I'd quit and get a job where I wasn't set up to fail. If there was a gun to my head, I'd write a fairly thin wrapper around Qt. The idea being that most people already have 1-3 Qt programs they use regularly. So even though it looks like a Qt application instead of a native one they'd still be familiar with it and it wouldn't look out of place. Then I'd spend most of my time engaged in politics. Install a few developers to developed Qt whose job it is ostensibly to be good Qt developer citizens, but whose actual job is to guide the next major version of Qt (which will break stuff) into breaking as little of my stuff as possible.
The second worst (but still bad) way to make a native cross platform UI is to give up, and make a not UI but close to UI cross platform abstraction layer, and then do the half dozen abstraction layer to native UI things separately. That still sucks more than the arena football league though.
No one's ever really done this, so it definitely sucks more than I think it does. But I walked into that suggestion knowing it sucks, so I don't feel bad. I dunno man. Everything about cross platform UI sucks.
> "Just copy whatever Apple does" seems like the worst possible solution for a cross platform widget naming convention out of many possible bad solutions.
The suggestion wasn't about copying whatever Apple does.
It's that SwiftUI has the most simple syntax (that I've seen.)
If you can make it nicer and more succinct than that, go for it!
But how is that the "worst possible solution?" What OS-specific bias do you see in that?
So maybe the specific constructs for specifying view modifiers and enums could be slightly different for each language, or the ()s might be []s, and maybe we could do away with the {}s.
It would just be a model for describing the UI, that a hypothetical engine backend might take and spit out OS-native widgets. For another OS, you'd plug in a different engine.
If Druid is going to build its own widget system from scratch anyway, what makes it more native than something like Electron? For me, the primary reason I'm interested in finding alternatives to Electron is to avoid shipping an entire UI framework + rendering engine with my code.
At least at first glance it seems to me like if I'm avoiding native OS toolkits, I might as well just target the browser anyway -- or is there something I'm missing?
Nativeness is a scale, for sure. Druid tries to be more native in certain ways, such as using platform drawing API's (Direct2D on Windows) when they're appropriate. I think the main reason to choose druid over browsers is simply performance. Also, druid binaries are pretty small, for example the calculator is 792k.
The state of cross-platform GUI systems really is a bizarre mess in this day and age, and probably can only be solved with a concentrated joint effort by Apple, Google and Microsoft.
Personally I'd love to have something like
import SwiftUI // For controls that are common to all OSes
import SwiftUI.Windows // For OS specific features
Maybe one day when they are populated by employees who grew up with dismay over the state of xplat GUI. :)
I mean even now Apple has an increased focus on services that must be accessible from everywhere: Music, TV, iCloud Drive. Surely there must be someone there who wishes they had to write most code only once for all OSes without making their app a hog.
I'd settle for just a convention; i.e. let C# remain the primary language on Windows, but introduce SwiftUI-like primitives like Text, HStack, ForEach etc.
Which one is their latest tech? Where does "WinUI" fit in? Is there a good, single starting point like SwiftUI's tutorial?
The first hit brought me to "Host a custom UWP control in a WPF app using XAML Islands" so there seems to be a distinction (and it implies WPF isn't the star anymore?)
[0] [1] that I could find after a couple searches look way more complex than what the equivalent SwiftUI would be.
Button(action: play) {
Text("Hello, world!") // Don't need alignment etc. to produce identical output.
}
and ugh [2]:
> If you need to embed any Unicode characters into the text, you can use the standard XML syntax. For example, to put the greeting in smart quotes, use: <Label Text="“Hello, XAML!”" />
I suggested emulating SwiftUI's syntax because it seems to be the most succinct.
WinUI is the latest tech, just UWP as usual, still the future of Windows UI, now re-architected not to depend on a specific Windows 10 release, going back all the way to Falls Creator.
Thanks. Couldn't find a "code first" example before my irrational impatience with Microsoft kicked in :P
I haven't touched C# in ages but that definitely looks odd compared to what I remember of it (like SwiftUI looks a little odd compared to Swift but not by this much.) My immediate thought: why capitalize the property names?
Fabulous is comparatively verbose too but probably more idiomatic with F# (which I have no experience with.)
That problem is normally solved by creating a nicer API abstraction around it.
Windows and OS-X tend to be the more straightforward cases. There is a standard set of UI components which users expect. Things are murkier in the Unix world, with multiple libraries and display technologies.
I'm genuinely curious. Is there a good example of a cross-platform wrapper around platform widgets? That was the original design brief of AWT, which turned out quite bad. Is there a successor which actually gets it right?
I obviously haven't tried every library, but my experience has been they all have some problems. You have to expect things like differing text wrapping and scroll behavior because it's hard to completely abstract the underlying UI frameworks.
The alternative of custom painting everything tends to come with more difficult to fix issues however. AWT's successor Swing struggled with things like respecting system user preferences and accessibility. You can find some old Java 1.5 write ups about it: https://web.mit.edu/java_v1.5.0_22/distrib/share/docs/guide/...
wxWidgets is the most popular one.
It's an ambitious project that allows accessing true native widgets, not just from C++ but also from other languages like Python, etc.
As they mention, this is based on a C wrapper round wxWidgets' native C++ API, originally developed to aid in developing a Haskell binding to wxWidgets:
The Rust binding is probably bitrotted for modern Rust, but since it's mostly generated, generating a low-level API using bindgen, which is actively maintained, and then a high-level API using a Python script of its own, it might be fairly easy to resurrect.
bindgen has got pretty good at converting C++ APIs, so it might be worth trying it on wxWidgets' native API, too.
I have no plans to write a GUI application in Rust myself, but i would love for there to be a good option for other people to write native GUI apps in Rust. As many other commenters have noted, cross-platform synthetic GUIs never look or behave quite right.
I'd love to see more mainstream discussion about what gui approaches we could take.
Personally I'd like to see something like IMGUI but with more of a focus on data structures, you should be able to cache the result of a function much more easily.
I guess I'm asking for a more functional-programming styled API for IMGUI. Allow me to get the benefit of a retained GUI by caching the results of functions.
At least for the few small toys I've made I think IMGUI is by far the easiest GUI paradigm to work with. I don't know how it would handle something more complicated though.
I also would love to see more discussion of this topic. There are some academic papers on functional reactive programming and so on, but now there's this huge wave of frameworks for declarative UI. I've found that there's a strong convergence on goals (one-way data binding, unification of initial creation and deltas, etc), but huge diversity in the way they're implemented.
And I also agree that IMGUI is one of the most interesting of these, mostly because it's very simple. You'll find makepad (mentioned in my blog post and in comments here) is fairly directly based on IMGUI ideas, but also has the ability to retain intermediate results. Also, I've been admiring the architecture of Jetpack Compose, and feel it's true to the ideals of IMGUI - you can think of it as IMGUI + "positional memoization."
And yeah, it's one thing to build toys and another to build real applications. This is one reason the focus of druid is to build a font editor, as opposed to making a GUI toolkit first and hoping for adoption.
Honestly, writing a cross platform gui is a waste of time. Java tried it(multiple times) and failed. Electron tried it and the results are terrible. Qt is moderately successful at it mostly because it is treated as the system toolkit on a lot of Linux platforms and Windows users are conditioned not to care about consistency and experience because of bad enterprise CRUD apps and Microsoft's own inconsistent behavior.
What rust should do is focus more on interop with other languages. Write your critical business logic in Rust and make that cross platform. Then write GUI in the platforms preferred Library/Language combo that handles all the UI and makes calls to a cross platform rust binary for grunt business logic processing.
It's come a long way from the Swing days and I think the biggest issue is it's perceived history, Java / Swing being slow and ugly. The other issues is the lack of marketing of what modern JavaFX can do.
So I wouldn't call it a failure, it's plodded on in the background improving slowly over time, where it has failed is on market adoption.
I use VSCode, Slack, and Discord every day (and some other Electron apps). The results are great and better than anything I've seen in the xplat space where there are always trade-offs.
Is Electron better than most cross platform alternatives? Yes. Is Electron better than platform's native tooklit? No. Electron apps are easily recognizable because they completely stand out from the platform apps (not in a good way). And there are other concerns that are addressed in the numerous electron threads on HN so I won't list them here.
i think that is part of GP's point, if Electron is the best we can do, then thats not a great sign. im a regular discord user and used to heavily use VSC, but i had to abandon it, for my uses it was far too heavy for what it was.
There are definitely trade-offs with Electron. Higher CPU, RAM and battery usage compared to native apps, and on macOS at least, the loss of features which native controls get for free.
Web technology is designed for documents and making non toy apps is a pain, if I may give you a few examples of issues I hit this week:
- I wanted to create a grid of img like elements(something a bit more complex where you have some small buttons on each image), I hit the issue that the browser would take like 2 seconds to load 1000 elements, in a decent GUI toolit this is not a problem, as an example in Flex4 I can have a list with 1000 elements, if only 10 elements are visible then the toolkit creates say 16 GUI elements, as you scroll the elements that get out of view are recycled , in Web you either create all 1000 GUI elements(that each element is maybe formed with a giant div soup) or you use a infinte scrolling like pattern, check Youtube as an example, go to a specific channel video list, you see only 2- 3 rows of videos, then you scroll and wait for next few rows, scroll and wait again, scroll and wait again ...tldr web GUI performance is really bad
- native components are limited, you can't css properly and consistently a numeric input(you can't css the colors of arrows to fit your styles) , you can't have a dropdown that contains icons or some more complex thing like a "Font Families dropdown" , you can't customize the dropdown scrollbar colors so you are forced (is not my fault that desingers want shit to match in theme and not have white crap on a dark theme) to find or create custom components, so you get to import JS libraries and most of the time this components are broken, Ex check the youtube search dropdown, it happened a few time for me to get the dropdown in the search to get stuck open, only way to fix it is to reload the page, Google devs can't properly implement a correct dropdown widget. In PayPal their custom input widget to enter money does not support the "Del" key . In a decent widget toolkit you extend the existing widget, you get all the existing functionality and you add your custom features on top in Web you start with DIVs and CSS do a mediocre job and then fix the issues that get reported if you have the time.
All this issues are solved in Qt, Flex or WPF, the components are performant, you can customize without losing basic features, you don't have to research shit like "what library should I use Monday to implement the numeric spinner input" .
CSS/HTML have some pretty significant problems, but this hasn't been true for years. And in any case, 90% of the native apps I use are basically interactive documents anyway. Unless your definition of "non-toy" apps is primarily referring to apps like Blender or Photoshop, most of the native apps on my computer could be trivially represented in HTML.
You should think of HTML as a render target, not as a document layout framework. HTML isn't where you lay out your application; HTML is where you present your application's data to the user.
> in Web you either create all 1000 GUI elements[...] or you use a infinte scrolling like pattern, check Youtube as an example, go to a specific channel video list, you see only 2- 3 rows of videos, then you scroll and wait for next few rows, scroll and wait again, scroll and wait again
The reason you wait on Youtube is because it's making network requests, not because the HTML is slow to insert. The way you would solve this problem if you weren't worried about network performance would be to use a virtual DOM, because the DOM is a rendering target, not a layout framework.
"Native" controls on the browser do restrict you quite a bit, but that's at least partially on purpose, because the whole point is to use "native" browser conventions with those components. How many times on HN do we see people complaining about scrolljacking on a website? And you want people to be able to style scrollbar colors on top of that? There was significant debate on HN about a month ago about whether it was even a good idea for browsers to respect `autocomplete="off"` in input fields. A significant chunk of your users do not want you to do this kind of stuff.
What the web does do is that it provides you mechanisms to avoid the native components if you have a really, really pressing need to do so -- while encouraging you that most of the time, using built-in browser behaviors will be better for both you and the user.
If Twitter was using native components and not hijacking browser behavior, text input wouldn't insert extra spaces whenever you copy-pasted. If PayPal was using a regular numeric input instead of some custom-built monstrosity, it would respect the delete key and render more consistently with your browser theme. If Youtube wasn't forcing itself to be a single-page app, you wouldn't get bugs where videos failed to load on navigation.
Seeking pixel-level control over every element is the opposite of how you get applications that look and feel native. Looking and feeling native means respecting platform settings and conventions.
About Youtube or my example with a big image grid, do you think you can fit all those JS frameworks and tracking in memory but you can't fit the title and thumbnail url of 200 videos ? you have an array with this 200 objects if titlke,video url, thumbnail url , the network request you will do lazily for the thumbnails and you can load the next row of thumbnail in the background while I am scrolling down. I am not talking about loading all at once, you load only what you need and a bit more so when you scroll down the stuff is already p reloaded , let me know if this is not clear and I can explain (I profiled my app and it was spending 2 seconds in the native browser layouting code)
About the scrollbars, I am not taling about a document side scrollbar, think at an example of a dropdown with all the font families, those have a scrollbar, I don't want to reimplement the scroll. I want to use the native widgets but the designers decided we will use a dark professional looking theme and the native scroller can't be styled with css, I know the discussions we ahd here on HN about the main page scrollbar and I agree we should use the native widget but we should be able to color it to match the webpage colors , what you will notice in application not webpages is that everyone is using custom component, nobody uses the native dropdowns,scrollbars,calendar, numeric inputs, the reason most of the time is that you are forced into using custom widgets because teh native ones are limited, are not customizable enough.
I 100% agree with you about pixel perfect and styling but I am just a developer, I implemented this weak the numeric input using the native input, I presented it to my boss and they asked me to respect the design, so tomorrow I will have to hunt for a JS library that implements this, look trough it's bug tracking for it's issues etc. I hate I have to do this but6 is not my decision and my initial point is that this is a reason why Web apps are bad as performance or UX , this custom components can run code on your mouse move events, on your clicks, on your scroll events , a native component would be faster and have less bugs and more features.
There is already a way as COM is cross-language by design. However what this will hopefully do is provide a library that makes it natural and using Rust idioms. I'm looking forward to it.
This is an interesting question, and one I did not directly address. One of the features of Rust is that it's practical to bind it to other languages, so I think writing a "GUI engine" in Rust that's designed to play scripts in other languages is feasible.
That said, it's not the main goal of the druid project. There, we're focusing on writing a real application in Rust. Dealing with language binding issues is hard, and anything that increases the scope too much puts the project at risk.
So if you want a multi-language GUI toolkit written in Rust, asking me is not the way to get that, because I'm not going to build that. But if you want to be part of a community effort to build it, I'd be open to collaboration.
What I want is to draw it, serialise it to some kind of common markup, and then have an API for dealing with events, altering properties, etc. Making sure that API works well with Rust makes sense, but doing the whole thing programmatically doesn't feel like the right model to me.
You should give Dear ImGui (which is mentioned in the article) a try. I was reluctant myself when I discovered it a couple of years ago, but it is such a joy to work with and so "obviously" the right thing on a very basic level that ImGui is now my default choice for writing UI tools (even with the disadvantage of not having a native look and feel).
It's still possible to put a data layer on top of immediate mode UIs, which basically turn a data representation into a sequence of function calls. But I think this would bring event handling back, which defeats the whole idea of an immediate mode UI :)
"We don’t yet know what to build" - and continues with the thousands of way a GUI-framework could be built.
I'm sitting here thinking: is it that important for the user? For a hobby-project sure, but doesn't developers want to wow customers with really nicely designed GUI:s because of the simple fact that beauty sells?
I'd argue that if you could find a really, really great GUI-designer (not developer) to take a crack on just one platform (so as to not make a Frankensteins monster) it would matter way more than if the architecture was modern or not.
To put it in another way, developers need a guiding hand with UI-design, not how to structure their program.
I think there are (at least) two fundamentally different ways to create UIs, suited for two fundamentally different types of UI applications:
Programmer-driven for "tools" (think Photoshop, Maya, IDEs, debuggers), and artist-driven for "user applications" (think typical mobile applications and games).
For the first type, "maintainability and functionality" is more important than "beauty on the surface", and it's also important to give the programmer a framework which encourages "best practices", so that the result is not an archetypal "programmer UI".
Only for the second type, "shininess" is more important than everything else, this includes general aesthetics, colors, animations / transitions, etc...
1. https://github.com/makepad/makepad
2. https://makepad.github.io/makepad/