It’s been a long time since the last newsletter, but here’s a new one! I’m excited to bring you lots of small improvements to Gio’s window and event processing on many platforms.
I’ve also started work on a rich text API within core Gio, but it is not yet in a reviewable state. This work is funded by your support on OpenCollective, so thanks to everyone who has contributed there. Stay tuned for more updates.
Sponsorship
These past few months, Gio thanks the following organizations and community members for their ongoing support!
Supporting the whole team:
- Plato Team via GitHub Sponsorship of Elias and Chris.
- Steve Russo via GitHub Sponsorship of Gioui.
- Denys Smirnov via OpenCollective.
- Larry Clapp via GitHub Sponsorship of Elias and Chris.
Supporting a maintainer:
- Kristian Mide via GitHub Sponsorship of Elias.
- Dmitri Shuralyov via GitHub Sponsorship of Elias.
- Paul Greenberg via GitHub Sponsorship of Elias.
- anedel via GitHub Sponsorship of Elias.
- A number of anonymous community members supporting both Elias and Chris.
Sponsorship money given to Gio enables Elias and I to cover the costs of running Gio’s infrastructure, to pay for some of our time spent maintaining and improving Gio, and to plan for funding significant feature work. You can support Gio by contributing on OpenCollective or GitHub Sponsors.
gioui.org@v0.8.0
This new version of core Gio contains many small window implementation bugfixes from Elias, some security and text wrapping improvements from Chris, and contributions from several community members:
- Lucas Rodrigues fixed backwards compatibility with older Android versions, which we had accidentally lost.
- Larry Clapp added documentation steering users clear from common mistakes with the text shaper.
- Benoit Kugler helped update us to a newer version of go-text/typesetting, which improves line wrapping and font selection.
API Change: Decorations
widget.Decorations.Maximized()
has been replaced by an exported field by the same name. Instead of widget.Decorations
managing the state of this boolean, applications are expected to set it in response to app.ConfigEvent
s. This makes app.ConfigEvent
the source of truth about the the state of the window, with widget.Decorations
just providing an easy way to make controls for window actions.
Here is a complete application (minus the imports and package statement) demonstrating correct use of widget.Decorations
:
func main() {
var w app.Window
// Ask Gio not to draw its own decorations.
w.Option(app.Decorated(false))
var d widget.Decorations
var ops op.Ops
th := material.NewTheme()
drawDecorations := true
for {
switch ev := w.Event().(type) {
case app.DestroyEvent:
if ev.Err != nil {
log.Fatal(ev.Err)
}
return
case app.ConfigEvent:
// Synchronize our decoration widget with the window's decoration state.
d.Maximized = (ev.Config.Mode == app.Maximized || ev.Config.Mode == app.Fullscreen)
if ev.Config.Decorated {
// Gio doesn't support custom decorations on every platform, so detect when Gio is
// providing them and don't draw our own.
drawDecorations = false
}
case app.FrameEvent:
gtx := app.NewContext(&ops, ev)
// Perform any window actions initiated through the decorations widget.
if actions := d.Update(gtx); actions != system.Action(0) {
w.Perform(actions)
}
// Lay out our GUI.
layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
if drawDecorations {
return material.Decorations(th, &d, system.ActionClose|system.ActionMaximize|system.ActionMinimize, "Gio").Layout(gtx)
}
return layout.Dimensions{}
}),
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
// Do layout here
return layout.Dimensions{Size: gtx.Constraints.Max}
}),
)
ev.Frame(&ops)
}
}
}
API Change: Disabled Contexts
Previously, you could disable a layout.Context
by setting the Source
field to an empty Source
. This unfortunately made it impossible for code with a disabled context to execute commands, which has many valid use-cases even when the widget should not receive input events.
Thus, the implementation has been changed to allow commands on a disabled context, but still not deliver events. This required the following changes to the API:
You now disable a context with:
gtx = gtx.Disabled()
You check if a context is enabled with:
if gtx.Enabled() {
// Do things.
}
Breaking Changes by Author
Elias Naur:
- widget: [API] change Decorations to leave the user in control of window state. As suggested by ~egonelbre, Decorations should not be the source of truth for the windows state, because external gestures may also change state. 6722c796
- layout,io/input: [API] change Context.Disabled to only disable events. Also unexport Source.Enabled because the nil-ness of its embedded router is now an implementation detail. 6c6cc157
Non-Breaking Changes by Author
Elias Naur:
- Revert “app: [Windows] suppress double-click behaviour for custom decorations”. 9dceca6c
- io/input: fix typo. b1db32ef
- app: [Windows] remove redundant code. 6aa02713
- app: [Windows] don’t draw after WM_DESTROY destroyed the window. There may be a window of time from WM_DESTROY is received to the WM_QUIT message is delivered by PostQuitMessage. If so, we must not call w.draw. 042ed4ab
- app: [macOS] track window state changes initiated by the operating system. Before this change, the window state was explicitly updated whenever Window.Option was called. However, the system may also change window state as a result of user gestures, but those changes did not result in ConfigEvents reflecting them. af6dda67
- app: [Windows] track window state changes initiated by the OS. Like the previous change, update the Windows backend to track and report window state changes initiated by the OS. 97044e53
- app: [Windows] remove redundant code. Change f7aa4b5c8 changed the fullscreen implementation to no longer require the position and size of the fullscreen window. 8cf44903
- app: close the window before reporting a GPU error. When a GPU error occurs forcing the reporting of a DestroyEvent is not appropriate, because the backend that controls the underlying window is not aware of the error and will continue to report events. f6e9f686
- Revert “app: [Windows] don’t draw after WM_DESTROY destroyed the window”. This reverts commit 635df374952019ff8d274646ea9ce040744daa0f because it didn’t fix #603 after all. 6efcb65c
- app: [Windows] don’t ignore Min|MaxSize options. The support for minimum and maximum window sizes were broken by a recent change. Found while investigating #608. 0781e62b
- app: [Windows] compute min, max window sizes correctly when un-minimzing. Fixes: #608 a5f7e7b2
- app: [Window] don’t report Win32ViewEvent before window configuration. Fixes: #609 c7277581
- app: [android] ensure a new frame is always scheduled when visible and animating. Possible fix to #614. 44ac5050
- app: remove dead code. d4c5e543
- app: [macos] don’t relay key events handled by the IME. Widgets such as Editor use certain key events such as the backspace key to implement text editing. On macOS, such key events are sometimes used by an input method, and in those cases the key effect would be applied twice: first by the IME and then the Editor. d7a1ec74
- app: fix typo. 520efdfa
- app: fix race condition between Window.Invalidate and event loop. References: #603 aa158e0c
- app: [windows] ensure no callbacks after DestroyEvent. Setting the callback handler to nil in DestroyEvent should have no effect, but may help debugging #603. 8daff13a
- gpu: remove compute renderer. The compute renderer is a failed experiment: a better port of the Vello vector renderer exists[0] and the upcoming Go 1.24 release no longer builds the gioui.org/cpu module because of #60725. ea456f42
- internal/vk: remove methods on C types, for Go 1.24 compatibility. 94355e52
- app: [macOS] send keypress events for modifier keys. This change generates keypress and release events for modifier keys in macOS. Specifically the Control, Alt, Shift and Command keys. 7337c06d
- flake.*: upgrade to nixpkgs 24.11. 1d95c7c6
- .builds: upgrade FreeBSD builder. e1fbb189
- .builds: work around iOS build failure. Later versions of clang no longer accepts our ancient SDK root. Force it by supressing a warning. 971f86ea
- app: [macOS] remove support for key bindings. The fix for #616 went to far by attempting to support macOS key bindings through doCommandBySelector. Issue #625 is a consequence, but more fundamentally, key bindings does not work with support for key.Release events. 8107ec22
- app: [macOS] propagate unhandled key shortcuts. By propagation, we restore the system behaviour for shortcuts the program don’t want, for example the system beep. fe4bf00c
- app: [macOS] don’t draw when minimized. References: #621 1ae2b9b8
- app: [Windows] don’t draw minimized windows. Fixes: #621 f200f0e9
Chris Waldon:
- go.*: update typesetting for unifont panic fix. This commit updates our typesetting dependency to avoid a crash when shaping GNU unifont. Thanks to Jeff Williams for raising the issue on the mailing list. 5d886b4d
- text: use upstream bidi visual order algorithm. We’ve migrated the processing of bidi run ordering into the upstream typesetting package, so now we can just consume the already-ordered runs instead of computing their ordering ourselves. 26cddb00
- widget: update text indexing expectations. The typesetting package has smarter line wrapping now, which is making our test text require fewer lines to display. We needed to update the expected data accordingly. 1d0d5f03
- text: allow disabling space trimming. This commit adds a shaping parameter that disables the trimming of trailing whitespace from lines. Text editors and similar use-cases want trailing whitspace glyphs to be selectable, which means they must occupy space. b5762529
- widget: ensure editor does not trim trailing whitespace. This commit makes the editor widget suppress the trimming of trailing whitespace so that the spaces can be selected intuitively. e025ed13
- app: [Windows] use NewLazySystemDLL for kernel32.dll. In order to avoid DLL preloading attacks, we should always load our system dependencies using the helper that only searches the system library path. a206e5e8
- internal/{egl,gl}: [Windows] restrict graphics DLL sources. In order to avoid DLL preloading attacks, we should be careful about where we load DLLs from. These packages load graphics DLLs, which may be provided by the OS, by a graphics vendor, or even by individual applications. As such, we can’t restrict loading them to just system32-provided paths. Instead, we invoke LoadLibraryEx with the
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
path, which will search system32, application-defined paths, and the path of the primary application executable. This mode ignores the system %PATH% variable, which dramatically reduces the attack surface of malicious or unintended DLLs. d2db4f68
inkeliz:
- app: [android] fix compatibility with older Android versions. Previously, setHighRefreshRate requires APIs restricted to Android 30, or higher. 38e4b1c6
Larry Clapp:
- text,widget/material: Update doc for Shaper & Theme. Note that you should use different Themes, with different Shapers, for different top-level windows, and explain why. 95f63c66
Benoit KUGLER:
- [text, font] Bump go-text version to 0.2.1. 0cbbacc4
gioui.org/x@v0.8.1
Gio-x recieved some minor improvements and bugfixes, but was otherwise quiet since v0.7.1
Changes by Author
Chris Waldon:
- component: allow specifying discloser control and summary alignment. d4cc70e
- outlay: add rigid rows layout. This commit adds a new layout primitive that acts like a multi-column flexed layout with only rigid children. 6035587
- pref/locale: [Linux] add fallback for C locale. Since C is a relatively common locale, but is not a language code, we should fall back to English if the locale is C. This at least gives the caller a language to work with instead of returning an error indicating language detection is unsupported. 3b38cc6
- go.*: update to gio v0.8.0. bd638c2
Spywire:
- outlay: fix issue with grid rows inheriting first row height. 86446d1
gioui.org/example@v0.7.1
Example was updated to compatibility with core and x v0.7.1. I also updated the opengl example to provide a simpler example of integrating Gio with an external renderer, and Egon fixed a windowing bug in the multiwindow example.
Changes by Author
Elias Naur:
- go.*: bump Gio to latest version. 043b7b2
- customdeco: track the maximized state of the window. References: #600 c1f4ec2
Chris Waldon:
- ci: bump go version to latest. The mirror was broken because we started using Go 1.21 features and the CI environment used Go 1.19. This commit should fix the mirroring to GitHub. cd0e948
- go.*: update to gio v0.8.0. cc20163
Alec Avakov:
- cursor_position: add simple example for mouse event monitoring. 715969b
gioui.org/cmd@v0.8.0
Cmd was updated to be compatible with the latest core gio, but was otherwise unchanged.
Changes by Author
Chris Waldon:
- go.*: update to gio v0.8.0. 03a1ada
giouiorg
Egon updated the site to be compatible with API changes, and Miles added a cool public transit application to the showcase.
Changes by Author
Chris Waldon:
- content/doc/install: [WASM] clarify where to run gogio from. Folks were trying to run gogio in a random directory, not realizing that it acts within the current module (and fails if there is no current module. c5b0178
- content/doc/install: add link to cross-compilation tips. Now that we have decent instructions on how to do this, it makes sense to make them easy to find. f32f516
- go.*: update to gio v0.8.0. 396671b
Miles Alan:
- doc/showcase: Add Transito. a1f3d55
Egon Elbre:
- go.mod: bump to gio@v0.7.1. fec3e7f
End
Thanks for reading!
Chris Waldon