I tried this and is awful. GTK and Rust have two very different ways of managing memory and it's painful. Lucky, gtk-rs already helps you with their own types prepared to be used with Rc but with your custom types you need to define all the garbage collector stuff your yourself which makes the code look very ugly (lots of clone, which aren't really clones).
At the end the result is good, but the code looks awful.
My experience is kind of similar. Unfortunately the way Rust interacts with memory is quite different from how Gtk does (and most GUI tool-kits to be fair). The end result is a kind-of awkward battle between the Rust borrow checker and the internal memory handling of Gtk+ leading to loads of Rc<RefCell<T>>. This makes also quite hard to implement custom Widgets in an intuitive way. In Python or C++ you would subclass the generic "Widget" class and start implementing the bits you need. With Rust things are slightly complicated; you can't just implement the IsA<Widget> trait and call it a day; at least not a straightforward way. Hopefully gnome-class [0] will probably solve this problem eventually.
That being said it's been a while since I've used gtk-rs so it is entirely possible things have changed. I'd love to be corrected if that's the case :)
Agreed, I went through the same pain when I ported by dummy Gtkmm from an old article into Gtk-rs, Rc<RefCell<T>> everywhere.
This is such a pain that even Gtk-rs samples have macros to work around cloning widget state into callbacks.
From my point of view language ergonomics still need to improve for Rust to actually be a candidate for GUI development, versus what the GC based languages (RC and tracing GC) offer out of the box with their UI kits.
Unless one envisions it just to take C++'s role of visualization layer and integration with graphics drivers.
One way to handle GUI componentry is to separate out the notions of ownership, parentage and reference.
Ownership defines who frees who. Parentage defines control nesting. References should to be handled via an indirection (e.g. names) and a protocol so that referees get notified when referents die. The indirection means that components get wired up in a late bound fashion; and the late binding means the gubbins for a protocol can be in place by then.
This stuff was figured out reasonably well with Delphi's VCL.
I guess the advantage here is that Delphi and C++ Builder don't have a borrow checker.
Even simple stuff like what Apple has demoed with SwiftUI designer can be a challenge, as you cannot just drag stuff around without changing the ownership semantics.
Naturally Swift has the advantage that Rc<RefCell<T>> is implicit, so it isn't as if the cost is magical gone.
However having to deal with it explicitly is a hard sell for anyone used to the comfort of GUI tooling.
So I imagine Rust is an easier sell for doing the low level stuff of a GUI engine, with what 90% of the devs using some managed language on top.
Basically what is happening to C++ on current desktop and mobile OSes, although for different reasons.
I tried event-driven programming with Rust 4 years ago and came to the same conclusion. It just isn't a good fit for the language. Rust works best when there is a stack and clear ownership semantics. Any kind of callbacks cause a certain amount of pain due to the need for unergonomic wrapper types.
Since then it got better libraries which reduce lots of the verbosity (e.g. gtk-rs), which is great. But the language itself probably won't change too much to better accommodate that use-case, since what things things painful here are the core features that prevent issues elsewhere.
I think we have to accept the fact that for different kinds of problems different programing languages are preferable instead of trying to find a single solution for all problems.
For UIs I think a naturally garbage-collected or refcounted language with reasonable support for dynamic dispatch is a lot easier to work with. In addition to that a restriction towards a single thread or even an inbuilt event loop can avoid bugs, improve interoperability between libraries, and reduce the amount of boilerplate and application-level design decisions even further.
If we take those properties we get the most common languages for GUI apps: Javascript/Dart which have single-threaded runtimes, and C#/Java/Kotlin/Swift as general-purpose languages which are more powerful but require an eventloop on application/library/framework level.
Those properties actually also expand to other very stateful and very concurrent applications. E.g. stateful network servers (something like Redis or a websocket server) have similar implementation challenges, and therefore are currently not very straightforward to write in Rust either (compared to e.g. in node.js).
In SWT, even though Java is garbage-collected, resources must be explicitly disposed[1]. Often they are bound to the lifetime of a parent object and disposed when that parent is disposed.
This seems to work OK in SWT, so what's the problem in GTK/Rust? Are there some particular categories of objects that don't fit into that hierarchical model and need to be handled with a GC?
(Those objects would presumably be regular Java objects in an SWT app and handled by Java's GC.)
The problem is called borrow checker, and that while the Rust team already has done lots of improvements with NLL, the use of widget data in callbacks remains a pain point.
So one could say, it is a case of holding it wrong, and a Rust UI toolkit needs to be written from scratch. Which might be ok, but it does require some support for market adoption.
Having said this, Gtk-rs now has some help in the form of relm, exactly to overcome this issue.
I have kept an eye on this for a long time. Is there any design pattern with Rust style (no unsafe and not ugly from Rust community's perspective) that proved in prototype to be able to achieve the same scaling of performance and memory usage as native C/C++ GUI framework with more complicated interface (e.g. Office)? Could this be an inherent limit of Rust because of the memory safety principle?
I was wondering something similar. This reminds me of the time a few months ago where someone gave up on writing a pure Rust binding to Wayland because the memory model in Wayland doesn't play well with the borrow checker[0]. It seems that the problem is you can write any arbitrary way of manually managing memory in C that doesn't necessarily have a complement in entirely safe Rust.
I'm not really sure this can be reconciled with any arbitrary C library. One of the benefits I see from Rust is the ability to be unable to do unsafe things without explicitly stating you know what you're doing, thus preventing various classes of errors. But it feels like if the ownership model just doesn't fit with Rust's model that allows those guarantees to be made in the first place, it won't work. You can't write just anything in safe Rust without limiting the things you can do, but C libraries don't have such limits.
It might take creating new ways of representing GUI objects before the best model for that problem arises for Rust. I don't think libraries like GTK were designed with the lessons in safe memory management Rust learned from years after the fact in mind.
I would like to see an ECS style UI design in Rust that represents widgets as IDs, to allow arbitrary object graphs without interior mutability. I don't see a reason why this would be incompatible with GTK, but we won't know until we try. It might work out really well.
It also might be that Rust is not the right language to write high level UI logic in at this time, and a GC'd language would be more appropriate. That's fine too. One of the strengths of Rust is its interoperability with other languages. C and C++ are certainly not the right languages to implement high level UI logic in, for example.
I agree with you. From my point of view, the advantage of C/C++ for UI is not about high level logic, but complicated custom widget with lots of low level functions and good performance. C/C++ is not good for a weather app, but almost the only choice for the canvas of Photoshop or the waveform of Audition, and it seems like no one else considers seriously challenging this. I am confident that given enough time, Rust will be adopted for social app or game GUI. But I don’t know if this would prevent Rust from writing practical large productivity software.
Yet, although Microsoft security now advises for C#, Rust and constrained C++, they went ahead and are using C++ for React Native and WinUI 3.0, removing the dependecy on .NET Native.
Apparently because that is the only way to sell MFC/ATL holdouts to WinUI, and allow WinUI to be called from classical Win32 without too much overhead, and also because .NET Native ideas will be migrated to .NET 5.
I am not saying that C++ is the answer for large-scale productivity software, but C++ is the answer for the complicated widgets used there. I would prefer Rust for the main framework of photoshop too, but I am not sure whether there is an elegant way writing the canvas widget.
Delphi and C++ Builder did well enough with high level UI logic.
C++'s problem is that the path of righteousness is too narrow, but with heavy cultural idioms and norms, you can keep a lot of the people safely hemmed in, while retaining all the escape hatches.
Actually reactivity in GUI (maybe declarative GUI programming is a more accurate form?) is also "the old way" in the GUI development. I mean it is already done a decade ago, even before react. Try QML. The view is automatically updated when a signal is triggered or its state changes.
You will notice that it is surprisingly simpler than React.
React got so popular because React implemented it very nicely in the web browsers, not because it brought new concepts.
This is a far cry from React where you just use language-native data structures directly (you only need to do mutations in specific ways).
As far as I can tell, you also can't just use native language constructs like functions/ifs/.map, etc. to compose the UI elements. Instead you have containers like Repeater.
It seems very different to me compared to React, like built around a significantly different philosophy.
Your comment seems to just be highlighting the fact that inspecting types at runtime is non-idiomatic at best in C++ or similar languages, so it would make sense to require a specific data structure or format.
Even defining what a "native" type is seems like it would be fraught. I guess the c++ way would be to accept begin and end iterators - but of what type?
I don't think I understand how RTTI/reflection relates to this.
When I imagine how a C++ implementation of something like React would look, my first thought is a bunch of functions which take whatever custom types they need (props), and return a tree of UI primitives (analogous to DOM element representations). Nothing that would require inspecting types.
And that works in other languages because you can iterate through trees and properties without needing to specify how to iterate through them or how they are stored.
Think about it. How do you iterate the tree? What even is a tree? The typical c++ answer depends on templates and iterators within the template. Which means they wildly change at compile time. It is clumsy for a shared library to deal with this, or, say, bind properties from an XML file or similar parsed at runtime.
Hence, it would make sense for a c++ solution to impose its own format or base class for trees or models. (Perhaps a template could help to wrap it.)
There may be some limitations and some things may need to be done differently because of C++, but from a brief look it should be basically possible. The UI library doesn't need to iterate through props, those can be a single opaque structure from its point of view.
I tried doing something similar in Kotlin a few years back and from what I remember there wasn't any reflection used for that part. https://github.com/peterholak/mogul
The .NET Framework, specifically the WinForms and the WebForms did that. Of course you could change everything manually, but DataBinding was a core concept which relied on changing data to change the contents of the GUI.
WPF still has the same kind of approach and to be terribly honest, Silverlight, as hated as it was, did it before React.
Yet it allows to build native applications where UI structure is defined by HTML, style by CSS and reactivity by script or by Rust (or by C++, Go, Python, etc.)
1. FlexBox breaks existing CSS Box model that mandates that dimensions of the element are defined by its width/height properties.
2. FlexBox introduces 12 (sic!) new properties in already overcrowded CSS property map. But as demonstrated by Sciter that can be achieved by just one property `flow` and flex units.
3. Flexbox and Grid are conflicting in the sense that the flexibility (as a feature) is defined in two different ways: separate properties (FlexBox) and 'fr' units (Grid) - overall CSS architecture becomes a zoo. Yet CSS has that famous 'auto' value that in some cases is just 1fr ( 1* in Sciter terms).
4. FlexBox is applied through 'display' property that is conceptually wrong. 'display' specifies how the element itself is replaced among its siblings but flexbox is rather about layout of element's children. These two entities are orthogonal. Example:
display:list-item; or display:table-cell; cannot be flexboxes. Just because of architectural specification error but physically nothing prevents <td> to use flexbox layout for their children.
5. Flexbox arrived too late. We started talking about the feature 12 years ago on www-style WG at W3C. And all these years Sciter already used flexibility (the must for desktop UI).
Not the parent, but in my view it is basically a 1-dimensional subset of Grid, which is great for mostly-1D website design.
But when it comes to making applications (which often use the whole screen, with tabs and whatnot, instead of being scroll-oriented), it makes some things either really difficult, either still requiring custom code to get it just right, or having a handful of wrapper elements for relatively simple layouts.
Don't get me wrong, it's _miles_ better for web layout than the old systems, but since Sciter seems to be focused on application-style layouts, it makes sense to prefer a layout system that can better represent common patterns in that domain.
Also, if you plan on go responsive, the required flex wrappers kind of hold you back when you need to reorient a bunch of your layout to fit a vertical screen (or horizontal, if you're doing mobile-first), while Grid's `grid-area` is beautifully flexible in that regard.
TL;DR: If you're gonna have to have Grid, then just having Grid is perfectly fine as it can do everything Flex can and more.
I know about revery[0] and cljfx[0], though I haven't had the chance to use them in anger. These both seem like very nice approaches to me - I'm partial to cljfx because I've been utterly spoiled by the clojure/script development experience, but I've also come to enjoy the typescript environment and revery seems to another step along that road.
Fn-fx is a more complex beast and no one seems to really know how it all works internally except the creator who isn't maintaining it.. so unfortunately it's in a semi unmaintained state. But the interface was a bit cleaner when I tried it
cljfx is actually inspired on fn-fx, and presents a much cleaner and more usable api, just by comparing the docs. I'm pretty sold on data-based apis instead of macro-based ones, though, so maybe it's just catering towards my preferred style of development.
oh okay. you sound more knowledgeable than me, so thanks for the input. I'll stick to cljfx then. I found it clunkier to mix with Java code, so I was considering switching back to fn-fx
I've used WPF extensively 10 years ago. It's nowhere near as easy to create a complex GUI as Vue/HTML/CSS. And that just for functionality. If we talk about looks, WPF is very clunky to theme.
I happen to have the opposite view, specially with Blend and component libraries into the mix.
CSS had to get WPF grid design in order to not be a poor table sibling in what concerns layouts.
While WPF is backed by DirectX, CSS requires playing with Z order, so that some browsers might eventually put the rendering into the GPU, but one needs to take care because space is limited.
While I can render anything down to pixel level control, if I wish to do so, I am still waiting for Houdini and worlets to actually become available.
And the whole template language with events and theming for low level customisation of control behaviours? Nowhere to be seen.
Using Blend feels to me like using Word to create HTML pages - the resulting output is horrible.
CSS layout was indeed a struggle many years ago, but now with flexbox I never failed to put stuff exactly where I wanted, and I barely understand it. And the new shiny thing, CSS Grid, is supposedly even better at controlling layout.
Similarly to many MS technologies from that era, WPF/XAML is not half bad at the core, but so verbose. Probably intended to be primarily generated by tooling.
Having been a Turbo Vision and OWL user, which lacked UI designer support, following up with VB and Delphi/C++ Builder, I never understood the macho attitude of doing GUI design manually without tooling support.
Any framework that comes with tooling support out of box is a plus for me.
Hence in what concerns Web, I care mostly about WebComponents, CMS middleware with page designers and SPA frameworks like Angular.
I reckon for designers are excellent for forms. The further you go beyond a data crud app, the less benefit you get from visual designers, because more stuff will be animated, contextual, custom, etc.
CRUD apps is a really big application space to cede, though, I totally think tooling is worth it.
It depends very strongly on how you used WPF. It had many footguns, due to a foolish decision to seemingly support the expectations of winforms developers.
Microsoft and others have MVVM frameworks, such as WPF, which have reactive data binding. Qt Quick also, but I haven't tried it myself. That said, it is not that similar to React or Vue because the "DOM"s are so different.
Try to use WPF from anything other than dotnet. It will be hard, given that you will have to hack its main loop to work with an external code. I'm not sure if that was ever done.
I've been in involuntarily involved in webdev for quite a few years. I will give everything to get that quick and easy manner of building GUIs in GTK+ to the web.
I wrote my first GTK+ program in my high school years in 2014-2015, and I can't think of any native toolkit ever approached the ease of work of GTK.
Been working on Windows side with every Microsoft's take on GUI library, Android, tried Qt (before QML,) and am involuntarily dealing with all those Web toolkits on almost every project involving web.
Microsoft very actively works on React Native for Windows, and last I checked there were decent RN desktop ports for Linux and MacOS. So that's one potential option.
JavaFX actually has a lot of reactive elements in its design. Basically every attribute of any GUI element are an “observable” type which allow you to register handlers for doing stuff when the internal value changes.
There seems to be a perception that anything running on the JVM is going to be slow and look bad. Considering I work with Java every day in a gigantic Swing application, (IntelliJ IDEA, if you didn’t guess) and it has great performance for all the things it’s doing for me, that seems to be an old holdover from early days of Java. Also enterprise apps, which of course are going to be bad and slow. At least the JVM has real threads for background work which don’t take another 100MB of RAM like an electron background worker :)
Yea, its hard to wash out a stain like that, in general, JIT:d JVM based applications performs as good or better than AOT application, but do still need more memory.
The “or better” tagged into JVM applications really needs to go away. Realistically, most JVM applications do not have as good performance as native ones. Yes, it’s possible to run better, but it’s very hard to create code that JITs to something faster than a thing written in C/C++/Rust/etc. You have to basically write code that looks like C to make it run as fast or faster, because there’s real overhead that comes with a lot of things in the JVM. You don’t just write standard Java or Scala and suddenly it’s as fast as C++, in general. It’s still heckin blazing fast, to be fair, but not AS heckin blazing fast. (As long as you aren’t just going insane with objects, at least, such as huge lists of integer objects)
Microsoft. Their XAML apps are pretty much web apps done right, ie not javascript and a more powerful layout system -- and everything on the gui part is reactive.
GTK is a C toolkit and Qt is C++, it is easier for other languages to use GTK if those languages have a way to interact with C library. There are a lot of bindings to GTK and very few to Qt.
There were C# Qt bindings since many years ago but those were not official supported so the quality was not that good,once there was a Java official binding/port that was dropped after a short time, I would not use someone's hobby bindings for a real world project(I mean a project with many users that you need to support for years , through OS and oteher system updates)
Sounds like a nice project, I did not want to insinuate that the quality is not good, I did not used Qt in a few years(since Qt4 days) so I am not sure about QML, without doing any research I think I am inclined to use the classic QtWidgedts for a desktop applications, SQML seems to me more mobile or designer first toolkit.
I strongly believe that Microsoft made a huge mistake not making .Net WPF and Silverlight cross platform and open source it. they would have made money by selling the Visual Studio IDE,
The real problem isn't that C++ is that hard to bind. Writing a C style wrapper around the OO style code in Qt is easy. But Qt relies on compile time code generation for event handling, properties and such, and this part is hard to replicate in other languages. It can be done; PyQt, PySide, etc do it, but it takes quite some effort.
Hm... unless I am mistaken, this misses the ability to write arbitrary slots and connect them. If I am right, then a major part of what moc is responsible for - the whole signal/slot glue code - is not covered in this library.
Yes because C++ doesn't have a standardized ABI, and C++ language concepts sometimes map badly to other languages, while C is sort of a lowest-common-demoninator (pretty much any language can call C functions through some sort of FFI mechanism).
The usual workaround is to wrap the C++ API into a C API.
The other commenters so far have blamed name mangling. Name mangling isn't actually that big of a deal: to mangle most functions, just write out the fully-qualified name of the function/method, convert each component of the name individually via a simple function, and then tack on the mangling of the types for every argument. Name mangling can get hairy, but realistically, you're not going to be linking against a template using an unnamed lambda as a parameter.
The minor complication you get is that the C/C++ ecosystem uses char, short, int, long, and long long to determine types, while most other languages use a more sensible i8, i16, i32, i64 system. This means you can't use the native type system of your target language as the base for mangling, since i32 and i64 do not map cleanly to int, long, and long long. (Doesn't help either that pre-stdint.h libraries for defining target-independent i64 types may have chosen a different value for i64 than stdint.h).
The real problem is that a lot of the functions you would wish to call don't actually exist in the binary library you're linking against. Inline methods are frequently excluded as linkable targets, and you often don't want to link to them anyways, because they're meant to be inlined (think something like std::vector<T>::operator[]). On top of that, templated things are rarely instantiated (and have code generated for them) until their point of use).
Your list isn't even complete. Exception handling, deriving from C++ classes, RTTI etc. all add their own sets of challenges on top of what you have mentioned.
Because it's so flexible, low-level in some parts (memory management, raw pointers) and high-level in others (template metaprogramming, lambdas).
If you restrict the API to a subset of the language, you can make C++ ABI just fine. My favorite style is abstract interfaces.
For the GUI example, look at WinRT. It exposes very high-level functionality, expressed in C++ as IUnknown-derived interfaces. These interfaces can be consumed or implemented by any compilers, or even other languages.
Such APIs work well even for very performance-critical code like DirectX or Direct2D. But there's downside, such APIs is not the most idiomatic form of C++: no exceptions, no iterators or other template shenanigans, no RTTI, no standard collections not even strings. All that stuff needs to be replaced with some equivalents.
When I only have C++ clients, I don't usually inherit from IUnknown, instead making an abstract base class with virtual destructor, and using std::unique_ptr smart pointers instead of CComPTR.
Primarily it's due to function overloading. Different implementations may use different means to consistently and uniquely "mangle" function names on symbols to uniquely identify them in the library export. This mangling depends upon numerous factors, including parameter types and calling convention (if there are multiple conventions on a platform).
This is actually a really useful walkthrough. With so many options and things out there, it’s great to have a step by step walkthrough of a project.
No idea why anyone would want to do this, because it seems you’ll be hated by half the Linux users for using gtk, but seems cool for personal projects.
Use Electron, then everyone on all OSes will hate your application. /s
I did not see people asking for GTK apps to be ported to Qt (if it happens is much lower then the rewrite it in rust phenomenon) , there were a number of projects that switched from GTK2 to Qt instead of GTK3 because they re-evaluated the toolkits and decided Qt was better for those projects.
> Use Electron, then everyone on all OSes will hate your application. /s
Actually this is a real benefit.
It means no one will show up and convince people on your project to waste time packaging your software for [pick a Linux Distribution].
Now instead of getting user reports from a hall of mirrors of various packages for various distros with various states of dependency disrepair, you've got one central source of truth.
Yeah. Instead people just won't use your webpage because it's slow, bloated, abstracted, and insecure. Native applications are much better in every way except for the bottom line of companies.
Just point them to the make files and have them compile it,
I personally I am more happy if you offer a .tar.gz build that I can run without root then a .deb . It happened that someone had a .deb ut I did not trust them, so I unpacked the .deb and runt he application directly.
Anyway if you don't have a Linux system and your program is open source then the useers should contribute packages. For closed source programs then you are fine with a cross distro method, like I seen small games made with Unity,Unreal,RenPy,RPG Maker that are also packagted for linux into a .zip archive and nobody complained and asked for special packages.
There are assholes Linux users out-there but is the same in all communities where you have entitled people that think their opinions are the truth.
The approach I take, which is to never even interact with them and just keep my projects to friends and myself. I do submit pull requests to upstream projects I use if they’re on GitHub!
wxWidgets is good for cross-platform support on Windows and Mac, but it just wraps GTK+ on Linux. And the native bindings are rather crufty MFC-like C++, I'm not sure that there's even an idiomatic Rust binding just yet.
Isn't the problem that users don't want the eye-candy of 1995, but the one of 2019 and therefore we don't have any choice but to bundle a browser and use JS if we want users?
There is a heavy focus on transition animations, fonts, media query breakpoints and drag and drop.
It's kind of embarrassing (or a testament to hard of a problem that it is) the state we are in because of (IMO) Microsoft/Apple/Canonical.
If they had a really, really good GUI foundation, it'd be a quick job to do a minimal Slack or Things for macOS clone in C++/Rust.
Edit:
Seems people get irritated about what the users want. But that's not really up to us to decide as coders...
There is at least one toolkit around that can do this: Qt. Yes, you can only use it from C++ in a meaningful way, but it has all the building blocks for designing, styling and animating UIs that you might wish for. I don't think the extent to which this is possible is known by most HN users. It is quite easy to write e.g. conditional widget style sheets that change widget appearance based on widget state (e.g. failing input validation) without a single line of C++ code required.
WPF can also be styled extensively, at least in theory, but this is much harder to accomplish. MS has developed Blend to assist with this, but you still need a deep knowledge of the internal hierarchy if elements of a widget to get good results.
To me, the eye-candy of 2019 is often uglier and worse then the one of the 2000s, since the fashion these days is for 'flat' interfaces, and the UI latency seems to be a bit higher.
Nobody cares what users want. Users use what they have to. Developers just pushed web UI over their throats, because it's so easy to bundle website with browser and call it an application. People dreamed about it since forever: not to duplicate all GUI work over and over again for every platform and now when web is a platform, it become even worse, so when Electron became a thing, developers jumped and users did not really care, because those apps were good enough and that's all that really matters.
Given the choice I would prever native UI any day.
What makes you think modern GTK isn't capable of 2019 eye-candy? The GNOME people love transition animations. Lollypop for example has a very fancy-looking "modern" UI.
The eye-candy in question is really more about usability of the GUI when people are on terrible computers with bad network connectivity and terrible UI input restrictions. I am, of course, speaking of smart phones.
The smart phone design aesthetic has taken over and is now constantly being used in places where the whitespace is a waste and the giant buttons make things terrible. Canonical may have finally given up on "convergence" but few other companies have woken up.
The real "convergence" is all about bringing the plain old desktop design aesthetic to the smartphone. "Bad network connectivity" is a fiddly modem connection at 300 baud, compared to that what you get on smartphones is excellent. If one can browse HN, reply to comments and even do operations like voting/flagging comments on a smartphone, that's proof enough that "usability" is no obstacle.
>a fiddly modem connection at 300 baud, compared to that what you get on smartphones is excellent.
No, both those examples are terrible. The 300 baud modem because of the low speed and the smart phone LTE connection because the round trip time is highly variable and TCP backoff applies a heavy penalty. Additionally, most smart phone internet connections don't have ports or even an ipv4 and are behind Carrier-NAT. Given that, I'd prefer the 300 baud modem.
> If they had a really, really good GUI foundation.
It is not true at all. They already have really nice GUI foundations. Brining the web tech to desktop apps gots so popular because the web is won so that devs are forced to make web apps, not because it is better than the "traditional" GUI development.
I'm not saying that traditional GUI development is worse. I'm saying that the users want shiny stuff that in many cases comes out of the box with Electron for example.
Do I want to code in 3 languages, let the app swallow copious amounts of RAM and break behaviours that users expect? NO. Will they do a hard pass on software if it's not pretty enough? YES.
If you want to chalk it up to not enough good themes in QT/JavaFX, that's fine two less languages and less packaging for them to worry about. But until those themes exist that makes the user turn its head...
That's not true though, they only work on one platform: the web browser, and often they only work well on one specific browser.
If you're going to allow a runtime as bloated and complicated as a web browser to count as "cross platform" then you'll have to admit that Java met those same criteria 2 decades ago.
I think the major benefit of a native/compiled language like C or Rust over interpreted/JIT ones like Python or Javascript for desktop applications is the overhead in terms of distribution size and memory consumption.
Speed doesn't come into it that much. Current desktop systems are fast enough such that most GUI manipulation just isn't a speed bottleneck, except for things like realtime graphics or something.
Complex web UIs in general have perceivable latency and are perceivably sluggish for me. I noticed how bad the problem is when I noticed some latency in responding to mouse clicks in a React application I was developing. After unsuccessfully trying to bring it down, I compared it to a handful of other web apps I use routinely, and then a handful of native desktop apps. When I did that it became depressingly obvious how conditioned I am to the poor responsiveness of these UIs.
For the record, this is all on a 4-core i7 machine with an NVMe SSD and 16GB of RAM. It's fair to say that the average machine where these are used is far lower.
Well it depends on the app :-) if the app is running something time-consuming in the hot path of every render, then yes it will be laggy. You can run the same risk even on a native app.
I animated SVG elements at 60fps with React. So yes, React can be pretty fast and low-latency.
And obviously, most users don't seem to care that much. Otherwise you wouldn't have these web applications. Developers would spend the multiple amounts of work, gladly paid by their employers and investors and gladly reimbursed by the users through licensing fees, necessary to make hot-to-the touch user interfaces for everything we use computers nowadays.
And now consider that developers would have to spend a multiple of their time on every little app. And they will be more buggy and insecure. And you'd often need to trust the binaries and install them.
Rust drives all of that down somewhat. Also webassembly will bring the ability to trust almost-native machine code.
Also: I said the main benefit of compiled languages is the memory overhead. If your 8gb of RAM can't handle multiple Chrome tabs, it's because of the memory overhead, not because javascript is slower. Most of the tabs aren't doing anything to the CPU most of the time.
What I really wish is that these Electron apps could share a common instance of Chromium. That would help the memory consumption issue a lot, but I'm not sure how to implement it best.
Often they can, if they don't use certain features not yet encapsulated in webapps.
Most of it is about trust, and you'll see certain web APIs built around asking for permission to access the camera, or image files or whatever.
Desktop apps often can't really trust each other. It's not a problem right now, but if you could XSS something into a game or social app which, with user-level permissions on your desktop could remote-control (for example click-simulating) your electron banking app, that would be really bad. Just a contrived example, but with great power comes great exploitability.
Couldn't they just run like a regular website, except be available offline? Then you could just open it up in your browser, so only one instance of Chrome/Firefox is used. Not sure how hard it would be to allow electron apps to run like that, but it seems like they are basically just websites as it is, given that they run on Chromium, maybe it would be harder for them to work with the OS filesystem though.
For the electron apps I use, they are generally available online as a website anyways, so I just use that, and get the whole common instance thing for free.
Well, Electron is essentially a server and chromium, so there should also be a way to execute nodejs code inside the browser then... which would break sandboxing.
I think this isn’t really a problem of Electron, but more to Chromium.
We bundle python inside the binary and it’s fine. I don’t think I’ll hate command line programs that embed nodejs inside the binary.
It’s the Chromium that’s problematic, and just by switching Chromium to the native WebView will make Electron apps much, much more lightweight.
At the end the result is good, but the code looks awful.