It is possible to port now app written in GTK3, Gtk-rs and Glade to GTK4?

Hi,
Not so long ago I created an app using Rust and GTK3 via Gtk-rs.
I used Glade 3.38 to simplify GUI creation(I really hate creating GUI with code).

I now want to port my app to GTK4, because in future I won’t have so much free time as now.

Is Gtk4-rs able to run a little more advanced project or needs more time to mature?
Which app I can use to graphically edit .ui or .glade files? Looks that Glade won’t be updated to support GTK4.
How to upgrade .ui or .glade files to GTK4?
It is possible to install GTK4 on Ubuntu 18.04/20.04 on Github CI?

1 Like

There is a tool to help: https://developer.gnome.org/gtk4/stable/gtk4-builder-tool.html

$ gtk4-builder-tool simplify --3to4 my.glade

but you will probably need to complete the work by editing the .ui yourself.

Is Gtk4-rs able to run a little more advanced project or needs more time to mature?

GTK 4 bindings work fine and probably more complete than the GTK 3 ones. Especially for the subclassing part which allows you to create your own custom widgets.

Which app I can use to graphically edit .ui or .glade files? Looks that Glade won’t be updated to support GTK4.

Note .glade files are GTK 2 era, you should use .ui as an extension. Glade doesn’t support GTK 4 though, there are plans to provide some designer app, but no idea of when there would be one.

How to upgrade .ui or .glade files to GTK4?

As you generated the original files using Glade, I think the best is to modify them manually as Glade generates a ton of not needed stuff. Most of that code can probably be removed. Especially that GTK 4 has saner defaults such as widgets being visible by default so you don’t need to specify <property name="visible">True</property> for all your widgets.

It is possible to install GTK4 on Ubuntu 18.04/20.04 on Github CI?

That’s a question Ubuntu people should answer, give it a try. You might need a newer glib/pango which you definitely don’t have in Ubuntu 18.04, no idea about 20.04 though.

1 Like

That is really interesting. Can you tell us more about how subclassing of GObjects is handled in Rust? For Nim we use proxy objects and toggle references. That makes Widgets look like ordinary Nim objects, the user can add additional fields and attributes like it is done in Nim. But we can not use the low level gobject stuff, and proxy objects and toggle references create some overhead of course. So I wonder if there may exist a better solution. (Nim supports destructors, so foreign entities can be destroyed automatically when they go out of scope.)

In the Rust bindings when using existing GObjects, there are no proxy objects or similar like in many other bindings. Instead they’re used as is and integrated with the Rust memory management mechanisms (RAII-style like in C++ for example): a glib::Object in Rust is literally just a pointer like in C (and the same one) and via the Rust Clone (mapping to g_object_ref()) and Drop (mapping to g_object_unref()) traits the memory is handled deterministically and the same as for any other Rust code. If you look at the assembly that is generated for Rust GObject code, it’s very close to what the corresponding C GObject code would look like. This also has the big advantage that it composes well with other languages used in the same process, while toggle references easily make it impossible to have more than one language in the process using them.

For actually creating GObject subclasses, I wrote an very explicit overview of that here some years ago. It’s again basically the same thing you would do in C, there’s basically no runtime overhead compared to C and it looks all the same from a C point of view. That has the big advantage that you can easily write C-compatible GObject libraries in Rust and have them used from any other language with GObject-Introspection support.

Now all that is super verbose, so with a lot of Rust type system trickery and some usage of macros the whole thing looks much simpler nowadays but under the hood still compiles to the same assembly. You can find an example of the current code you’d write in Rust here and explained in great detail here in @julian 's great documentation.

How this would map to Nim, I don’t know. Whenever a GC is involved mapping the behaviour of that nicely to GObject becomes complex but I guess mapping to the Nim reference counting memory management strategies should be nicely possible without having to deal with toggle references. As long as Nim provides you with the necessary API for doing that.

For creating subclasses you’ll have to find a way to map the way how it’s done in C (or what I describe in my blog post above for Rust) to Nim language constructs. I’m sure it would be possible to just do exactly the same as in C but that would be very verbose and nobody would like to write code like that. Based on my blog post, someone did the same for Go for example and with some additional work on top it seems usable in the go-gst GStreamer bindings. The Python, JavaScript, C#, etc. bindings also manage it in a similar way.

The main challenge is to map the whole thing to the target language in a way that it doesn’t feel too alien, isn’t too verbose and developers would like to make use of it. Making it work the same way as in C is usually not very difficult but then people could as well directly write C so that’s kind of defeating the point of using bindings.

6 Likes

Last chance to reply today :frowning: due to the 14 days restriction…

Thanks for your detailed explanations. So it looks that Rust can fully replace Vala, which the current gintro bindings can not, as they use proxy objects and toggle references. Toggle references where introduced in 2005 to GTK. When I started writing the gintro Nim GTK bindings in 2015 the Rust and Go bindings where not so much progressed, so that I decided to write it from scratch. I was not really aware at that time how difficult it is to understand the Gobject-Introspection API. I think gintro is really not bad for people wanting to write applications, as all is high level, and with the proxy objects all entities behave like true Nim entities. The disadvantage is that there is some overhead, which increase code size a bit, and we can not write real new GTK widgets which then can be used from other languages like true core GTK widgets. So maybe, when number of really active Nim GTK users should drastically increase, we may consider writing a new gintro implementation based on the Rust one. But I think I will not do that myself in the next 20 years, the effort is to big. But maybe somehow we can find a sponsor and then can hire some experienced Rust and GTK devs to do that, maybe with some support of some Nim core devs for the needed Nim macros.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.