Go(lang) GUI libraries, part ... trois
By Sean E. Russell on on Permalink.
I did some work on a project that uses gioui, and decided to replace Aĉetumi’s GUI with gioui. There are three reasons for this: first, Aĉetumi is just a pared down dailist, so I figured it’d be an easy conversion. Second I was unhappy with a couple of things about the UX of go-gui; I just enjoy the gioui UX more. Third, since I’d already implemented Aĉetumi in three other GUI toolkits, I figured this would give me a solid 1:1 comparison.
I was right about how easy the conversion was. For starters, Aĉetumi is a really trivial program, with almost nothing to the UI. The fact that it’s basically the same program as dailist, which was already using gioui, meant that I basically just deleted a bunch of code: I started with a block of marble and chipped away everything that wasn’t Aĉetumi. It took me about 4 hours, including futzing around getting the build scripts right.
gioui still is a PITA to cross-compile architectures, compared to nucular, or go-gui, or go-shirei. It still needs a container with an arm64 build environment, and it still takes minutes to compile a program. It’s like working with Rust. gioui still lacks a rich widget library, so I don’t have a file-open dialog for choosing the shopping list file like I did with go-gui. And gioui is still more work to program in than go-gui. You get your head around it eventually, but it’s more boilerplate for sure, and it lacks sophisticated convenience structures like scrollable containers you can stuff widgets into. For all of that, the upsides are enough to sway me to keep using it.
gioui binaries are a fraction of the size of go-gui binaries. The numbers below are of equivalent programs; the gioui version is missing the file dialog, but aside from that they’re feature-equivalent:
| Library | Binary |
|---|---|
| gogpu | 12,731,584 |
| go-gui | 31,966,432 |
| gioui | 8,545,352 |
That’s compiled with -w -s, so stripped binaries. The gioui is 4x smaller than go-gui. I just struggle with accepting a 31MB binary for a shopping list. 8MB is bad enough, but if you’re a Go developer you get used to it – it’s the cost of the runtime and not having to futz around with memory management.
[
This looks like it might just be due to the font color, but I played around with setting the font color to white for dark mode and black for light mode, and fonts still look fuzzy.]
There are two other things which troubled me about go-gui on mobile Wayland. First, the fonts are anti-aliased: they’re the right size, but look annoyingly fuzzy. The second thing also happens to nucular: the text entry fields don’t accept upper case characters. I’m almost certain this is due to how Wayland is passing virtual keyboard events to the library. Neither of these are things I want to spend my time troubleshooting, and the latter almost certainly requires an upstream fix; possibly even a fix upstream of the GUI library. gioui suffers neither of these issues.
I don’t know how I’m going to work around the missing widgets in gioui; I’ll probably end up building my own library. So far I’ve been working around dialogs by having separate tabs where I’d use a dialog on desktop, and this applies really well to mobile. Dialogs on Phosh are terrible, opening new windows which – because the Phosh app navigator orders windows by when they were opened, not by when most recently accessed – makes for a terrible navigation experience. Tabs or panes are a far better solution on Phosh. Even so, I’m not looking forward to re-inventing the file chooser dialog. I’ve probably had to do this a dozen times since I started programming, and it’s tedious. The missing scroll container is frankly baffling; it’s such a basic - yet involved - container. gioui does have some scrollable widgets and I’m hoping I can scavange from one of them to build a generic scrollable container.
When I look at it objectively, there’s no reason to pick gioui over go-gui; but I prefer the user experience and binary size of the end result, and I guess that’s enough to sway me.