October - GTK4 migration - dboles
20. listopada 2023. 13:55
Here’s the report of what I did on Inkscape month ending October, focusing on the GTK4 migration.
On the `master` branch, doing preparation on GTK3, I finalised and merged the change from Gtk:: TreeIter to TreeModel::[const_]iterator mentioned at the end of last post. I then tackled a key-press- event in our DialogBase class (Widget events need replaced by an EventController to be GTK4- ready; see previous posts!). In this I found it seemingly had not been working, who knows for how long… so fixed that. I was also able to tidy excess function overloads in my Controller helper file.
Fighting errors on my GTK4 branch, I noticed some overdue cleanups. Our `libnrtype` FontLister had some inefficient loops, string-copying, reference-count-trashing, etc. - tidied up as best I can. Our SPTagUse object had some very old code manually de/allocating C strings, so I replaced it all with std::string, and I removed more noise by using std::unique_ptr and removing defunct old code.
The `master` branch was switched over to build in C++20 mode at end of September. This adds some deprecation warnings about lambda captures, which I’ve been fixing while ‘in the area’, and warnings about comparing enums of different types or using enums in arithmetic, etc. - which are good prompts to fix thinkoes and unclear code. So I’ve been chipping away at those when I’m near.
In my `gtk4` branch, I continued my progress since mid-September. Our enum-to-class replacer script (to match changes in gtkmm 4) is great, but skipped some enums, redundant phrasings like `Align::ALIGN_START`, and IconSize - so I added fixes. I updated my commit fixing Controllers, cursors, etc. for GTK4. I tested my TreeModel::iterator changes against GTK4: trying to build each file in isolation, backporting what fixes I could to `master`, and keeping GTK4-specific stuff there.
A big task we can only do on GTK4 (not backported to 3), is drag-and-drop. This has moved from Widget signals to mediation by EventControllers. My Controller module gains helpers to succinctly create and add DnD controllers to widgets, like for ‘normal’ events, but plus C++20 designated initialisers to allow passing many or few argos from a large set available. I got DnD migrated and building for Objects, Filters & Path FX, the latter revealing numerous cleanups doable on `master` to reduce the GTK4 diff. We’ll have to interactively test and maybe slightly tweak once we can build it, of course! After this I fixed RefPtr casts (now shared_ptr) and Actionable API (finally in gtkmm4).
Some DnD looked simple to migrate directly in `gtk4` branch, but that in our Dialog classes is more complex, so I decided to study and simplify it in `master` first. This showed a regression from my GdkEvent-to-EventController porting, causing a crash if moving a tab to a new window & then right clicking it. And… fixing that revealed a bug that we didn’t trigger the required ‘reload’ of the items in said context menu to reflect new child tabs of the source and target notebooks. So I fixed those! I spent the rest of day working on a merge request for `master` that seems to considerably simplify the existing DnD code, while making it less tough to migrate to GTK4 (to be done another day :P)
I noticed GTK3 had outdated documentation about how dragging tabs from GtkNotebook works for the receiving side, so I submitted a merge request to fix the documentation to match current code, so that other apps porting in future won’t get confused. I then went back to a couple of issues I had filed to gtkmm in previous months and submitted MRs to fix them: one to add missing constructor and assignment of Gtk::TreePath from Gtk::TreeModel::const_iterator, and one to add Gtk::Widget .get_children() returning a vector of pointer-to-widget equivalent to GTK3ʼs Container.get_children() so apps iterating children via that useful method won’t have as much work as I’ve had… hehehehe.
In GTK4 GtkModelButton becomes a private class so we won’t be able to use it directly. I removed unneeded use in a dialog, and moved to use it by CSS node name (not class) in a helper function.
Then to a complex task: stopping using Gtk::IconSize::lookup() to get pixel size of a GtkIconSize enum, as GTK4 removes lookup(). We used this in several CellRenderers to show icons in tree views. With a lot of trial-and-error I was able to replace it by making these all CellRendererPixbuf subclasses, then tacking on any additional rendering (overlays, alpha-ising) via the render_vfunc(). This let me remove lots of code for requesting size & padding, and caching icons - instead we now make GTK handle all that, and trust things will be nice and optimal there in GTK4! I also fixed icons not updating when theme or symbolic setting do, & not being dim when backdropped or insensitive.
An easy win for GTK4 was binning avoidable use of GtkContainer API in our Preferences Widgets, which I can only guess came about in the GTK2 era, if gtkmm didn’t wrap something! Then a fix for icons: newly ‘torn off’ dialog windows got the wrong symbolic state - thanks to Mike for mentioning, and for detailed review of my other icon and DnD MRs! Then more cleanups: avoiding more `new` for widgets, saving perf by avoiding unneeded copies in various function args, etc. I also spent time reviewing a new contributor’s MR to make the About dialog close when Escape is pressed: thanks!
I tackled some prep for widgets with Popovers. In GTK3 Popovers can be shown at any widget but in GTK4 this is limited to parents that know they have popover(s), as they must override size- allocate to call present() on the popover(s) to tell them what size is available. To get us more ready, I updated my popup_at*() helper functions & PopoverMenu to require the popover has a :relative-to (parent) widget &, instead of allowing popup at any widget, restricting to parent or a descendant. So in GTK4 we should stay able to say ‘popup at Widget Y’ so long as it’s a descendant, & the helpers will handle fiddly details of figuring out the position, translating the coordinates to parent space, etc.
More things I could resolve while on GTK3 to be ready for 4: We used Widget:is-focus property in some places, but GTK4 removes it, so luckily our uses were replaceable by :has-focus. We used ToolButtons in our IconPreview dialog, which is funny as that’s not a ToolBar… so I ‘translated’ that to plain GtkToggleButton. Ditto ModelButtons in our Display Mode popup, to RadioButtons. I found several places using GtkContainer child-properties – & on investigating saw one set had no effect, one didn’t set a value (just got a proxy), and the other was in a function never called by anyone. . . !
A Fun Task was working around some GtkWidget vfuncs not being wrapped in gtkmm 4 (as C++ virtual functions). These are vfuncs css_changed() and focus(), both of which we use. I designed a custom subclass of Glib::ExtraClassInit to poke the C class vtable, save the original func pointers, and replace them with our own functions to dispatch to C++ virtual functions and/or the ‘real’ one, depending on the return type/value. So widgets that need those vfuncs can now inherit from that and hence get access to C++ virtual functions they can override to implement required responses.
More GTK3-able prep for GTK4 arose in our font lister/collection widgets: We had uses of TreeIters that in gtkmm4 must be const_iterator as they’re used in callbacks that expect it, and const must be respected! We also had code dereferencing some iterators one too many times, i.e. expecting methods of TreeIter to be callable via -> on the already-dereferenced-to TreeRow; in gtkmm 3 this worked as TreeRow is a subclass of TreeIter, but in gtkmm4 these are (rightly!) separate types. So I fixed that. Testing these, I noticed bugs in DnD of fonts into collections: using wrong coord space + not checking if get_path_at_pos() succeeded & issuing a Critical if it failed – these are now fixed.
I got many more files building on GTK4 & cleanups backported to `master`. Then 2 days migrating ComboBoxes with :wrap-width, removed in GTK4, to our PopoverMenu – with needed additions for UX. Then discussed menus with GTK devs & raised feature requests to make them better for us. I finished with an MR to add palette previews to the Swatches dialog just like in the status bar menu.