
Speedy Desktop Apps with GTK and Rust - luu
https://nora.codes/tutorial/speedy-desktop-apps-with-gtk-and-rust/
======
aarroyoc
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.

~~~
pjmlp
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.

~~~
barrkel
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.

~~~
pjmlp
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.

Or what is being done to Firefox actually.

------
fasterdom
Is anybody working on bringing reactivity to GUI development?

After working with Vue/React, doing GUI apps "the old way" feels like writing
quick-sort in assembly language.

~~~
kbumsik
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.

~~~
realharo
Last time I looked at QML (a few years ago), you couldn't just use any data in
your UI directly, you had to wrap it in clunky models.

When using C++, looks like you have to use things like QAbstractListModel
[https://qmlbook.github.io/ch16-qtcpp/qtcpp.html#a-simple-
mod...](https://qmlbook.github.io/ch16-qtcpp/qtcpp.html#a-simple-model)

Even without C++, there are things like ListModel and ListElement
[https://qmlbook.github.io/ch07-modelview/modelview.html](https://qmlbook.github.io/ch07-modelview/modelview.html)

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.

~~~
asveikau
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?

~~~
realharo
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.

~~~
asveikau
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.)

~~~
realharo
I'm thinking of a structure similar to
[https://reactjs.org/blog/2015/12/18/react-components-
element...](https://reactjs.org/blog/2015/12/18/react-components-elements-and-
instances.html)

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](https://github.com/peterholak/mogul)

~~~
ptx
That Kotlin project looks pretty cool! What happened to it – was there some
fundamental problem, or just lack of time?

~~~
realharo
Mostly just lack of time, more important things got in the way, and it became
less fun after the initial excitement.

I'm also still not convinced that Kotlin/Native will catch on in any
significant way, but we'll see.

------
dijit
I tend to prefer Qt as an end user, are there similar tutorials for Qt+Rust?

I remember someone telling me that it’s not as good a fit but I can’t remember
why that is.

~~~
simion314
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.

~~~
pknopf
[https://github.com/qmlnet/qmlnet](https://github.com/qmlnet/qmlnet)

~~~
simion314
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)

~~~
pknopf
I'm the author.

The QtSharp project used technology that couldn't really address the problem
(MonoCppSharp).

QML.Net is different. It is purely a QML integration (no c++ wrapper), using a
C interop.

There is extensive unit tests for QML.Net, including garbage collection tests.

I consider it segfault-proof.

It's currently used in production on embedded medical devices:
[https://medxchange.com/4klear-all-in-one-camera-
recorder/](https://medxchange.com/4klear-all-in-one-camera-recorder/)

~~~
mlevental
does it work with .net core? i.e. linux?

~~~
pknopf
It works on every platform Qt and .NET Core works.

I run it on embedded Linux.

Travis and Appveyor cover tests for Linux/Mac/Windows.

~~~
mlevental
that's pretty amazing. i've been looking for a gui framework that i can use
with csharp on linux. i'll take a look.

------
chronogram
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.

~~~
ubercow13
Is there a choice which won't leave you hated by half of Linux users?

~~~
simion314
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.

~~~
jancsika
> 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.

~~~
simion314
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.

~~~
chronogram
The downvotes prove your point, wow.

------
danielscrubs
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...

~~~
opencl
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.

~~~
superkuh
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.

~~~
0815test
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.

~~~
superkuh
>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.

------
bayesian_horse
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.

~~~
thegeomaster
I strongly disagree.

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.

~~~
yawaramin
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.

