September through November - Gtk4 Migration (Tavmjong)
2023年12月5日15:29
It's been three long quick months since my last update. A lot has happened. Most importantly, we can compile and run a Gtk4 version of Inkscape! But while Daniel's contract was extended, he's taken on another full-time job so will only be working on Inkscape in his spare time, and I've had less time due to family obligations. So work has slowed down. Progress is still being made with the help of others including PBS and mikekov.
Toolbar Cleanup
I spent some time cleaning up our toolbar code. We had a Google Summer of Code student, Vaibhav Malik, who did a great job of refactoring our toolbar code in preparation for Gtk4 where the specialized Toolbar widgets are removed. We still had some widgets derived from the removed widgets and these needed to be updated (or removed if no longer used).
Builder Files
We are slowly moving to defining our Graphical User Interface (GUI) by XML "Builder" files rather than having it hard coded in our C++ code. Widgets defined in Builder files, however, still need to be accessed inside the code. There were small changes in how they are accessed between Gtk3 and Gtk4. Daniel wrote some routines that allowed isolating these changes in one file (as well as making accessing the widgets easier). This required updating our code in many files to use his new routines.
File Dialogs
I updated our File Open and Save dialogs to get ready for Gtk4. This was probably the most frustrating code rewrite I've ever done for Inkscape. At first appearances, it seemed rather trivial, but it involved several false starts, and a dive into Windows code that I am quite unfamiliar with (I even compiled Inkscape on Windows for the very first time!).
There were a number of issues, the most important is the handling of file name encodings. Gtk uses UTF-8 encoding internally. If you are not familiar with UTF-8, it is a way of encoding Unicode characters. Unicode, itself, is a system that allows one to encode most of the worlds written scripts. It allows you, for example, to mix Japanese and Hindi in the same sentence. Most modern programs support Unicode but operating systems are not guaranteed to do so, so one must translate file names between UTF-8 (as typed in to the dialog) and whatever encoding the operating system is using. We were handling this translation ourselves (and more often than not wrongly!). Both Gtk3 and Gtk4 file dialogs have the ability to return selected files as Gio::File objects (Gio is a sister library to Gtk that handles low level interfaces to operating systems). This object does the right thing, returning a UTF-8 string for use in the GUI or in a system native encoding for use in accessing the file. In Gtk3 we didn't rely on this object but instead used functions that returned raw file names (left over from Gtk2 days). In Gtk4, access to raw file names was removed so one must use Gio::File objects (this is good!).
In our Gtk3 branch, we have the option to use "native" Windows file dialogs. These dialogs are not Gtk based. To fit into the changes made for Gtk4, we would need to create Gio::File objects ourselves out of the output of the dialogs. This was quite concerning to me as Windows uses UTF-16, another encoding system for Unicode. Converting between UTF-8 and UTF-16 should, in principle, be straight forward but I wasn't in good position to test such conversions and to ensure that we could still open and save files on Windows systems regardless of the system encoding. After a number of discussion during the Inkscape developers meetings it was decided to drop these Windows-based dialogs. They were written for the Windows XP era and had received minimal love since then. Gtk actually has two other dialog options that can replace these dialogs with more modern "native" equivalents. We'll investigate doing so after the Gtk4 port is more mature.
While file name encodings was the thing that I worried most about in getting the file dialogs ready for Gtk4, there were a number of other issues that had to be addressed. Gtk4 dialogs are structured differently and have been simplified. This required several adaptations such as how we create and use file filters (i.e updating the file name extension when you change the type of file you are saving to from the drop-down menu) and in how buttons that represent options are added to the dialog. One big change, is that the dialogs drop the ability to add a preview widget. This should in part be mitigated by the fact that Gtk4 dialogs have an "icon" view option, although, generating icons for SVG files isn't necessarily automatic.
Shortcuts
I've spend quite a bit of time working on our shortcut handling. We have rather complicated code to handle keyboard input, mostly due to our use of single letter shortcuts (e.g. 'R' to select the Rectangle tool). Shortcuts need to be applied after other widgets and the Canvas get access to the keyboard input (otherwise, we wouldn't be able to type in text on the canvas or into the various widgets!). They also need to be added correctly so that they are shown, for example, in menus (a native Gtk feature) and in tooltips (through our own code). Gtk4 offers a simplified way of allowing us to apply shortcuts at the correct time but getting everything to work has been elusive so far. This is also tied into our desire to show icons in menus.
Misc. Fixes
Since we have a working GTK4 branch, we can start work on fixing the many inevitable bugs that such a big transition introduces. Some of the things I've done include: getting the menubar to show, fixing the Startup dialog, fixing tooltips in menu items, fixing a handful of segmentation violations, and making sure newly created windows are visible.
Other
I got sidetracked a few times from working on Gtk4. I did some cleanup of our header files in the hope that it would reduce compile times. I also pushed the switch from C++17 to C++20. As both of these are not Gtk4 related, these were done on my own time.
Current Status
We are were about to merge the GTK4 branch into the main branch. But we've realized that there are some problems with Gtk4 itself. Many programs have been migrated to Gtk4 but Inkscape is a very large program (over 1000 source code files!) and has far greater needs that a typical utility program. We also use the 'Gtkmm' C++ wrapper to the Gtk 'C' code which for historical reasons has more problems than other language ports (for the technical savvy, it predates the introduction of GObject "introspection" which makes writing language bindings easier). Bug fixes to Gtkmm (by Daniel) require building Gtkmm from source. Most of the issues that we find can be worked around or fixed upstream, given time. But there are some issues that probably need to be addressed first before merging the Gtk4 branch. Here are some:
- Our custom cursors don't work on OSX.
- Keyboard handing problems on OSX
- High DPI support fails with the bitmap images.
- Shortcuts.
- Drag and drop.
A more complete list can be found at Issue 4690.