this post was submitted on 26 Dec 2023
127 points (96.4% liked)

Programming

17497 readers
35 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities [email protected]



founded 1 year ago
MODERATORS
 

it seems ridiculous that we have to embed an entire browser, meant for internet web browsing, just to create a cross-platform UI with moderate ease.

Why are native or semi-native UI frameworks lagging so far behind? am I wrong in thinking this? are there easier, declarative frameworks for creating semi-native UIs on desktop that don't look like windows 1998?

top 40 comments
sorted by: hot top controversial new old
[–] [email protected] 52 points 11 months ago* (last edited 11 months ago) (2 children)

Ha! I'm partially looking at this issue in my bachelor's thesis.

It's not at all necessary to embed a browser, but it's really easy to transfer your web app to a "near native" experience with stuff like electron, ionic, cordova, react native or whatever other web stuff is out there. The issue is mostly that native APIs are complicated and relying on web views or just providing your own "browser" is a relatively easy approach.

Stuff like Flutter, Xamarin or .NET MAUI compile depending on the platform to native or are interpreted by a runtime. There's a study I use that compares Flutter to React Native, native Java and Ionic on Android and finds that unsurprisingly the native implementation is best, but is closely followed by Flutter (with a few hiccups), with the remainder being significantly slower.

The thing is. I don't think these compiled frameworks lag behind in any way. But when you have a dev team, that's competent in web development, you won't make them learn C#, Xaml, Dart or C++, just to get native API access - you'll just let a framework handle that for you because it's cheaper and easier.

Edit: To add some further reading. This paper and this one explore the different approaches out there and suggest which one might be "the best". I don't feel like they're good papers, but there's almost no other write up of cross-platform dev approaches out there.

Edit2: I also believe that the approach "we are web devs that want access to native APIs" may be turned around in the future, since Flutter and now also .NET offer ways to deploy cross-platforn apps as web apps. I'll get back to writing the thesis now and stop editing.

[–] [email protected] 4 points 11 months ago

You may also want to checkout xilem

[–] BatmanAoD 4 points 11 months ago (1 children)

I remember thinking that Qt seemed like a really good approach that should be more widely adopted...until I actually had to use it.

Not that it's terrible; it's really not. But C++ is just not at all a good language for anything UI stuff.

[–] eluvatar 4 points 11 months ago

QML on the other hand is awesome imo.

[–] [email protected] 39 points 11 months ago* (last edited 11 months ago)

It's not that native UIs are lagging behind, there is a whole set of reasons.

TL;DR: browsers, as opposed to desktop apps, are stardartized - because they were originally designed to display and deliver text documents. We were never supposed to build complex application UIs on a web stack.

First, there is no standard way of making native UI on a desktop. Every OS uses it's own solution, while Linux offers several different ones. Browsers rely on a set of open standards developed specifically for the web, and even there not everything works exactly the same.

Second, browsers are designed to draw a very specific kind of UI through a very specific rendering mode - they run an immutable hierarchy of elements through layouting and painting engines. It works great for documents, but it becomes extremely unweildy for most other things, which is why we have an entire zoo of different UI implementations (crutches, most of them) for browsers.

On the desktop we often make a choice of what UI technology would fit best our purpose. For a game engine I would use an immediate-mode UI solution like ImGUI, for the ease of prototyping, integration and fast iterations.

For consumer software I might choose between something like QT or GTK for robust functionality, reliable performance, acessibility and community support. Mobile platforms come with their own native UI solutions.

For data-intensive UIs and heavy editors (e.g. CAD, video and music production, games) I might need to designan entirely new rendering pipeline to comply with users requirements for ergonomics, speed, latency etc.

It is also easy to notice that as a team or employer, it is often much easier to hire someone for web stack, than for native development. Simply put, more people can effectively code in JS, so we get more JS and tech like Electron enables that.

If you are interested in a single solution that will get you nice results in general, no matter the platform - you might see some success with projects like Flutter or OrbTK.

UI rendering in general is a deep and very rewarding rabbit hole. If you are in the mood, this article by Raph Levien gives a good overview of existing architectures: https://raphlinus.github.io/rust/gui/2022/05/07/ui-architecture.html

[–] [email protected] 34 points 11 months ago (1 children)

This is because each desktop operating system using a different graphics rendering engine—Quartz on macOS and X/Wayland on Linux, for example. In order to write an application that works on all major operating systems, you either need to use a graphics library that has already done the heavy lifting of calling the native frameworks under the hood or you have to do it yourself. Or you can use a web-based graphics library that has also already done that heavy lifting, with the added advantage that you can use languages like HTML, CSS, and Javascript to easily create visual elements. This is attractive when the alternatives like Qt are notoriously difficult to deploy and force you to use C/C++.

[–] [email protected] 7 points 11 months ago* (last edited 11 months ago) (1 children)

Quartz (usually referred to as Core Graphics) isn’t recommended anymore on Macs.

Developers should be using SwiftUI now, which is a completely different approach:

class HelloWorldView: NSView {
    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        // Drawing code here.
        guard let context = NSGraphicsContext.current?.cgContext else { return }

        // Set text attributes
        let attributes: [NSAttributedString.Key: Any] = [
            .font: NSFont.systemFont(ofSize: 24),
            .foregroundColor: NSColor.black
        ]

        // Create the string
        let string = NSAttributedString(string: "Hello World", attributes: attributes)

        // Draw the string
        string.draw(at: CGPoint(x: 20, y: 20))
    }
}

Here’s the same thing with SwiftUI:

struct HelloWorldView: View {
    var body: some View {
        Text("Hello World")
            .font(.system(size: 24))
            .foregroundColor(.black)
            .padding()
    }
}
[–] [email protected] 6 points 11 months ago

Quartz is a layer beneath SwiftUI or AppKit. SwiftUI is still using Quartz under the hood. The way you use Quartz directly from SwiftUI vs AppKit is a bit different, though still fairly similar. A more fair comparison of the SwiftUI code would be:

struct HelloWorldView: View {
  var body: some View {
    Canvas { context, _ in
      context.draw(
        Text("HelloWorld")
          .font(.system(size: 24))
          .foregroundColor(.black),
        at: CGPoint(x: 20, y: 20)
      )
    }
  }
}

Alternatively an AppKit solution (not using Quartz directly) would be something like:

class HelloWorldView: NSView {
  override init(frame frameRect: NSRect) {
    super.init(frame: frameRect)
    let text = NSAttributedString(
      string: “Hello World”,
      attributes: [.font: NSFont.systemFont(ofSize: 24), .foregroundColor: NSColor.black]
    )
    let label = NSTextField(labelWithAttributedString: text)
    addSubview(label)
  }

  required init?(coder: NSCoder) {
    fatalError()
  }
}

In either AppKit or SwiftUI, you can access Quartz directly to implement custom views. However, most of the time the UI code you write in either SwiftUI or AppKit won’t call Quartz directly at all, but will instead be composed of built-in views, like (NS)TextField or (NS)Button. Under the hood, SwiftUI is mainly just using the AppKit components at the moment, but provides a significantly nicer way to use them (especially in regards to layout and data synchronization).

[–] mrkite 23 points 11 months ago (1 children)
[–] [email protected] 2 points 11 months ago

I'm not too familiar with slinr or fybe but DearImGui seems like an odd one out here.

[–] blackshadev 21 points 11 months ago (1 children)

You mean like qt/qml? Due mind that even with those ui toolkits you will need to ship 'some' library. In case of QT it is not minimal at all. GTK can be more minimal but it still is significant.

Also there is tauri. Which doesn't ship a browser, but uses the platform native we view and is compiled while still having an amazing dev experience.

[–] [email protected] 4 points 11 months ago (1 children)

How is webview different from a browser exactly?

[–] [email protected] 5 points 11 months ago

Electron apps ship their own chromium-based renderer, but 'webview' means the OS gets to use its own renderer. It's still a browser-like environment, but at least the OS can choose the most performant one.

[–] charolastra 16 points 11 months ago (2 children)
[–] [email protected] 7 points 11 months ago (2 children)

I don't understand exactly how this is different. Is "WebView" not still very similar to a browser?

[–] [email protected] 9 points 11 months ago

but.... but..... RUST!!!!!!!!!!!!!!!!!

q. e. d.

\s

[–] charolastra 8 points 11 months ago* (last edited 11 months ago)

It doesn't embed Chromium, it uses the native webview that already exists on the system. The average app I make using Tauri is less than 15MB, and being Rust on the backend you can go as low level as you like. The Tauri API provides access in your front end code to all the native APIs you can think of.

[–] [email protected] 5 points 11 months ago

A genuinely cool and somewhat lean alternative to Electron!

[–] [email protected] 14 points 11 months ago (1 children)

Lots of other very pragmatic solutions also seem ridiculous.

Every problem is going to cost either clock cycles or highly skilled programmer time.

Currently, in the world, all eleven competent user interface element developers are occupied with more important tasks.

Until one of those eleven finds some extra free time, the rest of us get to slap electron into everything, and he thankful we can spread our atrocious CSS anti-talents to one more problem-space.

[–] [email protected] 3 points 11 months ago* (last edited 11 months ago) (1 children)

~~Who are these eleven? Didn't realize the number is so small. Who determines who they are?~~

Turns out it was an exaggeration

[–] [email protected] 9 points 11 months ago (2 children)

I am, hopefully, exaggerating on the 11 count. I don't know the exact number, and likely no one does - but it genuinely is shockingly small, considering how critical usability and accessibility are to everyday use of code.

Anyone can study the principles of usability and accessibility, but the number of experts we have really is far too few, and I suspect it's is why we have so much reuse instead of innovation, right now.

[–] [email protected] 2 points 11 months ago

My bad for misunderstanding your exaggeration 😅

[–] [email protected] 2 points 11 months ago

You are not far off. In my previous project we attempted to rewrite a desktop app and we started with a skeleton crew. Hiring for the frontend was tough, we got one very good xaml (wpf / winui etc) dev in the first year. Then, in the middle of the corona lockdowns, for 12 months we kept only getting mediocre candidates from across the world, with no relevant experience whatsoever. Then we found our second full time frontend dev, who only stayed 3 months and once he saw how clueless management is, bolted.

Funnily enough the aforementioned manager experts started asking what's wrong and why we 'fail to fill the positions'. We were stuck in the native desktop world product-wise, an unattractive and challenging tech stack with difficult problems to solve, with poor management and low budget. That's what was up. Now I'm happily working on the backend / web / cloud side of things and I'm definitely not looking back or picking up another tech lead position for a project with non existent team to start with. /o\

[–] [email protected] 11 points 11 months ago (1 children)

basically this comes down to time and money. if you're a hobbyist, you have lots of options available, but they take time to learn and you probably already know html. if you're a professional, developer time is more expensive than cpu cycles and you probably already employ a web developer. unless there's a good reason, most people won't learn an entirely new GUI toolchain.

[–] [email protected] 5 points 11 months ago (1 children)

Plus, on average web developers earn less. So if you can create your desktop application with a web tech-stack, that saves you money as a manager, which in turn increases your bonuses: You're incentiviced to do that!

[–] [email protected] 2 points 11 months ago

Really depends where you live

[–] onlinepersona 8 points 11 months ago

https://slint.dev/ has gotten there, IMO. They're working on a python binding and even to compile to android apps.

CC BY-NC-SA 4.0

[–] [email protected] 6 points 11 months ago

Check out qtquick, it's a bit clunky but capable

[–] porgamrer 6 points 11 months ago (1 children)

The real question is how we got any portable solution to this problem in the first place.

To me problems are fundamentally economic and political, not technical. For example, the unique circumstances that led to a portable web standard involved multiple major interventions against Microsoft by antitrust regulators (in 2001, 2006, 2009, 2013, etc). The other tech giants were happy to go along with this as a way to break microsoft's monopoly. Very soon after, Google and Apple put the walls straight back up with mobile apps.

If you go back before HTML, OS research was progressing swiftly towards portable, high-level networked GUI technology via stuff like smalltalk. Unfortunately all of the money was mysteriously pulled from those research groups after Apple and Microsoft stole all the smalltalk research and turned it into a crude walled garden of GUI apps, then started printing money faster than the US Mint.

Whenever you see progress towards portable solutions, such as Xamarin and open source C#, React Native, or even Flutter, it is usually being funded by a company that lost a platform war and is now scrambling to build some awkward metaplatform on top of everyone else's stuff. It never really works.

One exception is webassembly, which was basically forced into existence against everyone's will by some ingenious troublemakers at Mozilla. That's a whole other story though!

[–] [email protected] 3 points 11 months ago

I need that story

[–] [email protected] 5 points 11 months ago

The painfully obvious solution is for these to open in a browser you already have.

[–] [email protected] 3 points 11 months ago

Avalonia is great. It's cross-platform, supports hot reloading, it's XAML based, so not too different from HTML, it's FAST, has IDE integration and can be styled to match any OS's native UI.

[–] Mreeman 3 points 11 months ago

Check out kotlin compose multiplatform. Takes the Android declarative jetpack compose UI framework and makes it run cross platform. You get most of the modern UX conveniences from Android, can reuse libraries etc. Works with either JVM or compiling to native code too.

[–] [email protected] 3 points 11 months ago

It's much easier to write an abstraction over one platform, an embedded chromium browser, than it is to write abstractions over several drastically different platforms. For most applications, the developers are satisfied with the performance and footprint anyway and see no value in maintaining a different application for the different platforms when it can all be written once with something like Electron.

Still, there are people out there trying to write cross-platform, native UI frameworks. For example, I believe that's what Slint is trying to do, although I've never tried it myself.

[–] [email protected] 2 points 11 months ago* (last edited 11 months ago)

It depends on just how "cross-platform" you want to make it. If you came up with another standards-based UI framework that had the same cross-platform penetration of web browsers, then you'll have effectively reinvented the browser. For everything else, you can basically pick a maximum of two: cross-platform, native, and easy.

[–] [email protected] 2 points 11 months ago

Haven't dabbled with them yet but I've heard of Avalonia and Compose.

[–] SmartmanApps 2 points 11 months ago

I'm not sure what you mean about embedding a browser - do you mean writing your UI in XAML? If so I wrote a whole blog post suitable for beginners and up on how to write a MAUI UI using only C# Creating MAUI UI's in C#

[–] [email protected] 2 points 11 months ago (1 children)

Never expected to see imgui mentioned in one sentence with flutter ngl

[–] [email protected] 1 points 11 months ago

Why's that?

[–] [email protected] 1 points 11 months ago

There's https://redbean.dev/, but it's not quite what you mean.

It runs on the browser with a local host reference to a lua server with access to c libs.