Hacker News new | ask | show | jobs
by actf 3008 days ago
I really like where the author went with this. Everytime I read something like this though I can't help but think how we as developers really need a better low level, UI framework for cross platform applications. What the author has done here is a cool idea, but ultimately this still feels flawed, and like it's a workaround to the difficulties of writing a cross platform UI. Everytime I read something like this I can't help but think about how great a low level, cross platform C (or C ABI) library would be (think something like libuv but for UIs). Such a library would abstract away the OS specific system calls of the UI while still providing the ability to easily do things like: * Create a window * Draw to the screen * Declaratively (i.e. html like) add UI widgets to a scene * Apply CSS like styling (like QML, JavaFX, or XAML) * Use native file dialogs, menus, notifications, etc * Statically link as a single dependency

I don't even think something like this necessarily needs to provide native UI elements, rather it just needs to be a more performant, easier to use, smaller, version of electron that could easily be used from any language. It needs to provide common UI elements like buttons, textboxes, divs, grid layouts, etc, but judging by the popularity of electron - I don't think those necessarily need to use native elements.

Qt is close to this, but it feels heavyweight and in my opinion its biggest flaw is that it's difficult to link to an application and setup a development environment for. Tk is kind of like this, but way too limited. JavaFX is a really good example, and would be perfect if it wasn't Java only (same with WPF but it's C# only). Right now the closest attempt to something like this that I know of is https://github.com/andlabs/libui

I think libui could even be a starting point for such a library, but the library I'm thinking of would need some type of declarative UI support (i.e. html like, maybe even support for a subset of html), built in support for styling, and less of a focus on using native widgets. I really wish somebody would build something like this.

7 comments

Am I the only one with the opposite opinion?

I don't think cross-platform UI toolkits should exist, period. Your cross platform code should live underneath the UI layer, and you should write a custom UI for each platform you're bringing your logic to.

Mac apps should look and feel like mac apps, windows apps should look and feel like windows apps, etc.

Trying to abstract away all these platform differences either nets you a lowest common denominator that doesn't feel at home on any platform, or is so complicated to develop for that you end up doing more work in the end (and still isn't as good as writing native UI's for each platform.)

I hear this preached all the time but I honestly don't believe it.

Few third-party applications I use on my Windows computer have a native (or native-looking) UI. Blender, Photoshop, text editors/IDEs, DAWs, video editing software, even web browsers... The only real exception is the file dialog and the window frames.

If they went to match the native UI they would dilute their brand at best and lose usability at worst.

One thing I can do in almost every Windows application is press Alt, or Alt+F, and use the arrow keys to navigate the menus. This has been broken forever in Electron's menu. It's my biggest complaint, even above RAM usage now that I have enough RAM. I guess the Electron devs can take that as a compliment if they want to, but it still gives me a "damn you Electron" moment every few days.

I think it's the sum of those little inconsistencies that bug people about cross-platform apps. On the other hand, people now spend so much time in the browser that a browser-based desktop application can probably feel more natural than a native UI if done right.

There is a base assumption not stated here: that the platform's UI is superior.

Mostly I'd agree. And there are undeniable benefits to supporting what other apps support, which is typically biased towards the platform's stuff.

It's not at all inherent though (TV controls are frequently utter garbage, for example). And the various dimensions of "better" don't always optimize for what the user or dev wants.

You're probably not alone.

Here's the tired counter-argument: I'd rather have an app with a slightly awkward ui for my os, than no app at all. The advantage of these cross platform toolkits (and our bane), is that it makes it significantly easier to make build for other platforms.

> Here's the tired counter-argument: I'd rather have an app with a slightly awkward ui for my os, than no app at all.

I agree. However, I also think that this has an undesirable effect of discouraging a platform-specific app from being created, especially in niche markets.

Edit: clarity

I think it's great that so many apps are available for mac or linux that wouldn't otherwise be available. Electron provides a baseline that simply is much more difficult with platform specific code, or other cross platform applications. It's not all in the box, and far from perfect. But the fact is, I get to use VS Code, Teams, Spotify (I know not electron specifically, but similar enough) and a handful of other apps everywhere I run.

For the most part I stick to cross platform apps, if that means a "lesser" electron based app, so be it. And most of them look far better than other cross platform and even native options a lot of the time.

It sounds like your main concern is preserving the native look and feel of the OS.

I understand the argument, but I don't really understand the reasoning behind it. This is probably me being naive, but (assuming any performance problems are solved) the only reasoning I see to prefer native OS widgets would be to preserve compatibility with adaptive technologies (i.e. screen readers, OS keyboard shortcuts, high scale displays, etc), and to allow for automation of the UI.

Maintaining compatibility with adaptive technologies and allowing for automation both seem like good arguments to me. I think it would be challenging to solve those problems, but I think it could be done. Html already has mechanisms to deal with this, so I think another tool kit could take a similar approach.

Preserving the native look and feel however, doesn't seem nearly as important to me. I usually customize the look and feel of most desktop applications anyway. For example, changing the color scheme of my terminal, text editor, and IDE. I would hate it if I was forced to use the OS defaults. For example, on osx it's not possible to customize the look and feel of the iterm window, where as with hyper (an electron based terminal emulator) it is possible, and I find that I strongly prefer the later's UI (despite the electron performance issues). Even chrome allows me the ability to customize its UI. Of all the desktop applications I regularly use, there's very few these days that exclusively use the native OS widgets - at the moment evernote is the only one that actually comes to mind.

With some exceptions, users seem to manage pretty well on the web where every website already implements a different style of UI. For simple widgets like windows, buttons, textboxes, checkboxes, etc minor differences in style just don't seem like an issue to me. I think users will be able to visually identify a button even if it looks slightly different, and the advantage of allowing customization feels like a worthwhile tradeoff. For more complex UIs (like 3d renders, music editors, video editors, or games) most seem to already implement customized UI elements anyway.

What you're suggesting actually feels like a step backwards to me, so I'm genuinely interested to understand why you would want to maintain the same look and feel between applications? How do you currently customize the look and feel of your own environment?

> With some exceptions, users seem to manage pretty well on the web where every website already implements a different style of UI.

That's not necessarily true. It's easy on a site like GitHub, where they actually have a UX team and user studies to guide their decisions, but stuff like the Intel HD Graphics Panel would be better if they had just used stock WPF.

See also: https://www.nngroup.com/articles/flat-design/

I think there is a case for both.

For many small or hobbyist projects it is not feasible to implement and test multiple UIs. If you have the resources and want a polished smooth experience then implement the UI layer natively.

That said we're not quite there with code sharing of non UI code between web, desktop, and mobile platforms. It's a niche that Kotlin is trying to fill but time will tell if it succeeds.

Yes, if you want to do it professionally and keep up with the developments of a platform you will you have an ongoing cost for a whole product team for each of your target platforms. That additional cost ($500k-$1m per year per team) is very rarely worth the slight upside in usability, and there are probably many potential products that the team could work on that are more beneficial to the company.
> windows apps should look and feel like windows apps

so what happens when microsoft itself uses Qt for official windows apps? :p https://forum.qt.io/topic/87898/microsoft-onedrive-sync-uses...

It means that even their own developers fail at choosing the “right” UI technology from the supported ones:

- MFC

- WinForms

- Silverlight

- WPF

- UWP

...

I can’t really blame them.

Well, I don't see the value in having multiple UI platforms in the first place. So I would rather have one very good UI toolkit for all platforms than having a lot of pros and cons for all the native toolkits.

I think the most common place to find people with your opinion is in mobile app development. And I in my opinion there are two major reasons here at work:

1. Apple is very good at building UIs

2. Mobile devices are comparable weak in processing power, while their use-cases mostly always require an instant & animated result.

So on the one hand iOS users expect the same quality when you build a custom UI and that is hard to match when you start with a UI project. The second reason might be the cause why web-based UI are kinda hard to build for mobile apps. I mean I heard a lot more mobile developers complain about web-app performance than desktop app developers. But maybe that is just because of the different rendering engines.

> you should write a custom UI for each platform you're bringing your logic to

The question isn't of "bringing" your logic to a platform, though. The question is how people who you don't care enough to provide first-party support for, will run your application.

Consider a situation where someone codes native apps for Windows and macOS, but also provides an electron app as source. Who is that app for? Everyone who is using any other platform.

Also consider the "native-ized" apps that exist to wrap web-apps that never created a native app at all. For example, there are numerous Electron wrappers for the Facebook Messenger web-app created by third parties who just wanted to be able to use Facebook Messenger on their PCs as an "app" rather than a webpage.

This doesn't work, though, and we can use Qt and wxwidgets as the reasons why.

Qt has tried a lot of different ways to render GUIs. Traditional qwidget applications use, depending on the widget object, either native platform specific controls that you try to uniformly mutate despite the stylistic differences, psuedo-themes Qt writes for non-standard elements or things that aren't universal and thus you need a facade for where they try to impersonate the native toolkit (this is why so many Qt programs on Windows "feel wrong"), and user-styled controls that don't even attempt to be native but you can mix those freely with the base widgets that emulate the native look and feel. This is how VLC can have its volume slider look the same everywhere.

Then in Qt4 and much more comprehensively in Qt5 they moved to QML, which completely drops the idea of trying to use native window systems and renders the entire UI with 3d acceleration. They also, at first, made no attempt to even provide common toolkit elements - you got basic drawing primitives and the ability to query get a color pallette that you are told by Qt should be the "native" colors.

Turns out not a lot of people took off with that offering so Qt developed QtQuickControls1 - which was a giant mess of depending on qwidgets to map native widget styling into the OpenGL scenegraph they had. It actually did somewhat work, but only insofar as you got buttons that looked native - go try resizing these Controls 1 windows and you discover a lot of incongruency, especially on less practiced platforms like Android, especially where faux-native widgets and GL components mixed.

QtQuickControls2 I feel is an accurate representation of what all GUI development has to be - if you want native look and feel you do need to do some manual management to get it, making your own themes and having logic to change the design to accomodate the target platform. But it also is meant to make good looking software by using the style guides of platforms rather than the lower level actual widgets - the original release has Material and Universal from Google and Microsoft respectively. They don't try to look native, but they try to preserve the stylistic guidelines of the host platforms. They later added a few other options - a "desktop-like" theme, one that you can easily restyle with generic images, and a default that is super plain.

Wxwidgets presents the other extreme. It tried super hard to never implement a widget itself - it was always meant to be a facade over native toolkits. In other to accomplish that they had to sacrifice ergonomics and introduce means to distinguish the platform native widgets that don't map cleanly across platforms. You never get a perfectly universal cross platform UI this way, but you also don't benefit from native toolkit workflows because you are trying to abstract something that isn't a 1 to 1 mapping.

There is one more aspect to all this - native toolkits generally blow chunks. And that precludes how Windows has at least three actively maintained "first class" GUI toolkits now. All first party toolkits today are derived either from bitmap or raster graphics, mangled over years or decades to support new paradigms that they weren't meant to, and to this day have errant behavior abound and little to no consistency due to their backwards commitments.

That would not have been a problem if we were all still operating on computers without GPUs with displays from 1995, but the evolution of hardware keeps pushing on our desktops to take advantage of the resources available - in particular, GPU acceleration. 2d acceleration is completely dead. If the world made sense and legacy could be eschewed for reason every desktop would be from the ground up built on 3d acceleration. I haven't checked in a while but I believe it wasn't until Windows 8 that Microsoft dropped the non-accelerated bitmap Windows desktop for 2d acceleration. KDE on Linux went through a huge churning to migrate their desktop to 3d acceleration and that still only applies to their newer tech - anything QML based - while the bulk of KDE applications are stuck being unaccelerated qwidgets programs. Gnome is in the same boat, and never made the leap to a 3d UI paradigm across the board that they should have made when GTK3 broke everything.

Because mixing these two worlds is just an exercise in suffering, but every UI design on every platform either has to wage the war or just succumb to using the broken old bitmap style with hacks to try to make DPI scaling work.

Not all the blame should fall on UI designers though - this is a structural problem. Before Vulkan we had no seriously universal and working acceleration API. You could not rely on OpenGL a decade ago much less now - just look at Godot, whom released their 3.0 with OpenGL ES 3 and is now forced to adopt an ES2 renderer since so many ES3 implementations on both desktops and mobile are broken. There was simply no universal API to ground the foundations of a "next gen" 3d toolkit in, which is why Qt supports a myriad of backends to QML including an unaccelerated one they were forced to implement because so many edge cases broke the renderer.

Call it the 14 + 1 standards problem, but whoever writes a declarative toolkit built on Vulkan that can be like QML except without all the attached baggage (theres a reason the Rust QML crate has been dead for over a year) would be my choice any day. Its just a hard engineering problem, not just because Vulkan is hard, but because providing simplicity to start without constraining possibility and expandability is an even harder design problem. Maybe the answer will come from game engines? The overlap gets more and more blatant every day - I've been having a lot of fun in Godot and I ask myself why not just do general GUI development in here. Its accelerated, cross platform, and the scripting is a joy. It just lacks API coverage for comprehensive support of what apps expect since its only meant to make games.

There is a point that is always missed about Electron - UI.

By using HTML, CSS & JS you have an extremely rich toolkit to create UI with constant improvements from browser vendors and standards bodies.

If a designer can create a pattern library in sketch then chances are it can be implemented using web technologies.

This is a much bigger and more active open platform when contrasted to the capabilities of a particular framework and community.

Theres another topic around whether you should detour from the OS UI look and feel. But most designers and product owners worth their salt are conscious of keeping known UX patterns and least surprise.

> Qt's [...] biggest flaw is that it's difficult to link to an application and setup a development environment for.

Check out (my) https://github.com/mherrmann/fbs. It's for PyQt but I think does get around the obstacle you mention.

The examples here look more interesting than libui

https://github.com/vurtun/nuklear

There’s a typical window app, game ui, something that looks like unreal engines visual programming.

Seems like a flexible system

Haven’t actually tried to use it though. That’s where it will win or lose, IMO

Edit: and just got to end of the README. Bindings available for rust, python, go, lua, java and more. Gonna have to kick the tires on this one.

> I don't even think something like this necessarily needs to provide native UI elements, rather it just needs to be a more performant, easier to use, smaller, version of electron that could easily be used from any language.

Sounds a whole lot like what you’re talking about https://github.com/zserge/webview

I think about this lately and write about this on:

https://talk.remobjects.com/t/potential-way-to-do-almost-cro...

---- Is well know the problem of try to do a cross-platform GUIs. But in the other end, the necessity to do that have increased with the arrival of mobile and the emergence of OSX as a viable target for commercial apps.

Is kind of ironic that is easier to port a full 3d-game but a “simple” business app is a huge undertaking :)

The key, IMHO, is decouple some tasks (kind of separate “back-end” UI from “front-end” UI).

We can do “partial/almost” cross-platform UI, if we think that some stuff can actually cross cleanly:

- Layout (the big one, IMHO) with something like https://yogalayout.com7. This one was my main block before.

- A well defined way to separate the back from the front UIs. The ELM architecture is a good contender (https://www.elm-tutorial.org/en/02-elm-arch/01-introduction....) (called Update-Model-View, similar to react + redux but simpler and easier to call servers/async)

A big chunk of the logic is totally cross-platform and “only” need to adapt the render of controls. This way of working allow to work with pure objects for the model and the view without actually commit to exactly what is the view UI. Instead, is delegated to the “update” side. It can totally be just in-memory, testeable object.

Dispatching, events and similar stuff, that is not visual. This need a bridge but I don’t think will be complicated. Then finally, the rest can be fully native:

- Controls

- Drawing

- Animations

- Call to native libs

This mean that we build components instead of a class hierarchy and is possible to swap what is a “control”, like, from HTML to iOS Views without moving the rest of the logic.

The big question is what to use for coding this. I’m using .net but wish to have something more low-level. I know swift and it could work for other targets (Java, .NET, native) with elements.

Wish to have a coding partner to do this :slight_smile:

There’s a fast-growing interest to create something like this in the Rust community. An unofficial working group led by a Mozilla employee is being formed:

https://internals.rust-lang.org/t/thoughts-on-rust-guis/6894...

Have you tried Sciter? https://sciter.com/

It's a lightweight HTML and CSS renderer for native desktop apps. Used heavily in the anti-virus industry. Not open-source, unfortunately.

I have looked at sciter and it looks pretty cool, but not being open source is a pretty major downside.