It’s been quite a while since the last newsletter, and the Gio commuity has contributed many refinements to the platform. I’m immensely grateful to everyone who has been working hard at improving Gio.
I think you’ll find that Gio v0.9.0 fixes both many small issues in the window system integration layer as well as the renderer. This upgrade should be easy (the breaking changes are trivial and obscure, so unlikely to affect real code), and the results should speak for themselves.
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.9.0
This new version of core Gio contains many small window implementation bugfixes and macOS improvements from Elias, some text handling fixes from Chris, and contributions from many community members:
- Walter Werner Schneider made numerous renderer, platform, and ergonomic fixes across Gio.
- Dave Akers fixed a number of wayland event-handling bugs.
- Marcel Juffermans fixed Windows window positioning (centered at startup) and added minimal support for touchscreens on Windows.
- zjzhang fixed a text line height issue.
- vasijob225 fixed some counterintuitive behaviors in the window decorations on Windows.
- kurth4cker improved some documentation.
- Lucas Rodrigues enabled scrolling in a horizontal list with a normal mouse wheel.
- Miles Alan fixed compatibility with Go 1.23 which we accidentally lost by using iterators too early.
- Veikko Sariola eliminated many heap allocations during typical uses of layout.Stack and layout.Flex.
There are no major breaking changes, but there are many small changes that are technically API-changing. For instance, the zero valid of f32.Affine2D
is no longer treated as the identity transformation. You should use f32.AffineId()
instead. Also, io/pointer.Foremost
is no longer defined as an event priority. This was only used by nested scrolling and is no longer needed.
A major quality-of-life improvement comes from Walter’s patch to add a Values
map to layout.Context
. This allows applications to smuggle information down the widget call tree without breaking the layout.Widget
call signature by wrapping the context or adding extra parameters.
Changes by Author
Walter Werner Schneider:
layout
: add Values map to Context. Fixes: #654 c3ce484binternal/stroke
: fix normal vector size and direction. The normal vector size and direction depend on the input point and the sign of the unit value provided. 6ce7ffa4app
: [Wayland] don’t recreate EGL surface during resize. Fixes: #656 420f4c32widget
: remove focus on click behavior from Clickable. This is a breaking change, users that need the old behavior can implement it using the existing API. b2b12d62app
: optimize window context locking. Avoids unnecessary eglMakeCurrent and thread locking calls to enhance performance. 3e601e73f32
: replace Affine2D{} with AffineId() for identity transformations. Reduces ambiguity by introducing AffineId() for representing identity transformation matrices. d76b4272f32
: use value receiver for Split method on Affine2D. 3b1effb7f32
: add tests for Affine2D transformations. References: #655 31564b98app
: [Wayland] add forth and fifth buttons. 78b54615f32
: replace Affine2D{} with AffineId() for identity transformations. References: #655 4e5a344call
: avoid collides with builtin min/max functions. ba82ae46op/clip
: add bounds expansion after move. After moving the pen, the next action should update the bounds for the start position. 0c145b38app
: properly initialize editorState for tests. a274f6fegpu
: respect the offset fraction when clipping. Fixes: #534 bbb6d05fgpu
: replace f32.Point/Rectangle with image.Point/Rectangle. 36a2fa37internal/stroke
: handle zero-length points. 17657052internal/stroke
: fix point normalization for unit length.. 30f8ac10internal/stroke
: quickly handle zero length normalization. f4503973gpu/clip
: fix vertex corner positions. Fixes the 1px overlap of curve quads. Without this patch the rendered quads were skewed vertically and were 2 pixels shorter in height. The NorthWest pixels were moved to the SouthWest instead of NorthWest and the SouthEast pixels were moved to the NorthEast instead of SouthEast. 4c0e526c
Elias Naur:
all
: replace golang.org/x/exp/slices with the standard library package. a5068a19app
: [macOS] correct error handling for newMtlContext. Fixes: #632 af446e8bgpu
: don’t store transformed rectangle paths under the same cache key. Fixes incorrect rendering of multiple transformed instances of a rectangle. 77709d17gpu/internal/rendertest
: allow nil pixel check functions. 0d232405app
: [macOS] don’t discard IME session for consistent snippets. An IME session must be discarded when its text content no longer matches the underlying text component content. However, the check for matching was too pessimistic; the IME session would be discarded if the new snippet from the text component was not equal to the snippet reported to the IME. This change implements a refined check that only discards a session if the content of the overlap between the new and old snippets don’t match. 72a72a2blayout,io/input
: move disabling events from layout.Context to input.Source. The fix for #605 moved the disabling of event delivery from Source to Context to enable disabled Contexts to still react to commands (invalidate, focus etc.). However, that change in turn caused #641 where the exported Context.Source field would no longer know not to deliver events. fff23754io/input/pointer
: ignore grab commands for tags that don’t have the pointer. Without this fix, two gestures that both issue GrabCmd on the same frame will cancel each other. With the fix, the first will win the grab, and the other ignored. efd31ad6io/pointer
: remove Foremost priority. The only known use-case (nested scrolling) now works without special treatment of the foremost handler. e18db649flake.*
: upgrade to nixpkgs 25.05, use nixpkgs android SDK. 0a209f7dapp
: [macOS] limit full screen window size when MaxSize is set. There are two max window size settings on macOS,contentMaxSize
andmaxFullScreenContentSize
. Set the latter to avoid a window being resized larger than its maximum in full screen mode. d50ef687app
: [Windows] show the maximize button even when MaxSize is set. According to @kkeybbs, pressing the maximize button on Windows only resizes the window up to its maximum bounds. That means we can leave the button available, and only hide it when the window has a fixed size. ea979b43io/pointer
: delete documentation that Cancel events have pointer IDs. Cancel events affect the entire gesture and as such all active pointers. b2f6707aapp
: [macOS/iOS] simplify running functions in the main thread. Using cgo.Handle allows us to pass a reference to a Go function through the GCD API for running main thread code, saving a goroutine and a channel. 6553915eapp
: [macOS] make the app delegate optional. Inspired by the discussion at golang.org/issue/70089, this change makes our particular NSApplicationDelegate implementation optional. 3f4f8ba7
Dave Akers:
app
: [Wayland] use correct serial for wl_pointer_set_cursor. a3117d38app
: [Wayland] use correct serial for wl_pointer_set_cursor, take 2. To fix #644 the serial passed to wl_pointer_set_cursor must come from the pointer enter event. To do this we need a place to keep the serial so I’ve added a field to the wlSeat struct to hold on to it. 016714a6app
: [Wayland] remove window.seat in favor of wlSeat.pointerFocus. cc6048bc
Marcel Juffermans:
app
: [Windows] correctly center window on startup. When the window is created position it before processing the actions to perform (which may include system.ActionCenter). Note that the actions are performed in the callback windowProc(). 35ec76e5io/pointer
: add forth and fifth buttons. 0eac4f2capp
: [Windows] add minimal support for devices with touch screens. The Windows Pointer API (https://learn.microsoft.com/en-us/windows/win32/api/_inputmsg/) was used to allow the detection of events when interacting with touch screens. This also opens the gates for supporting other types of input devices (e.g. pens and touchpads). Mouse events are now part of the pointer events (primary events trigger WM_POINTER, whereas secondary ones vanilla WM_POINTERUPDATE, and cancellations WM_POINTERCAPTURECHANGED). A fourth and fifth button (usually found in modern mice) has also been added for completeness, though their integration in other OS-es shall be the objective of future patches. 809a6d0d
Chris Waldon:
text
: round y offset of trailing newline. This commit tries to ensure that trailing newlines do not introduce more vertical space below the text than is occupied by a typical text run within the text. 593c5fbfgo.*
: update typesetting for truncator ordering fix. This commit updates our typesetting dependency to a version that properly bidi-orders truncator runs. This fixes an issue in which the truncator symbol could appear on the wrong side of text. 14a9fbcc
Admin:
go.*
: bump Go to 1.23, upgrade dependencies. 86668e8ball
: clean up code, upgrade to modern Go. f73287be
zjzhang:
text
: respect line height when layout the last empty line.. Text Shaper set the last empty line height to ascent+decent of the paragraph break glyph which causes the last visual empty line to have a smaller line height. This commit tries to fix it by setting the line height using the line height from the last line. adaace86
vasijob225:
app
: [Windows] hide the maximize button when MaxSize is set. Also, disable window frame resizing when MaxSize equals MinSize. 95354d80
kurth4cker:
app
: fix miss included doc comment. 4f720af6
Lucas Rodrigues:
layout,gesture
: add option to handle vertical scroll on horizontal list. Previously, it was impossible to scroll a Axis == Horizontal using ordinary mouse-wheel. Now, it’s possible to set ScrollAnyAxis == True, which combine scrolling from any direction. That makes possible to scroll Horizontal lists with vertical mouse-wheel. 02253341
Miles Alan:
internal/debug
: go 1.23.8 compat; use strings.Split not strings.SplitSeq. Currently build fails as go.mod uses go 1.23.8 which doesn’t have strings.SplitSeq. Note: strings.SplitSeq was introduced in go 1.24. 8104d527
Veikko Sariola
layout
: avoid heap escapes in Stack and Flex. Stack.Layout and Flex.Layout caused a lot of heap allocations / escapes. The reason was that scratch space for dims and call and was inside Stack/FlexChild. child.call.Add(gtx.Ops) confused the go escape analysis and caused the entired children slice to escape to the heap, including all widgets in it. This caused a lot of heap allocations. Now the scratch space is separate from children, and for cases len(children) <= 32, we will allocate the scratch space on the stack. For cases len(children) > 32, only the scratch space gets allocated from the heap, during append. 1a17e9ea
gioui.org/x@v0.9.0
Gio-x gained some new layout helpers courtesy of Jack Mordaunt, but otherwise has been quiet lately.
Changes by Author
Jack Mordaunt:
outlay
: spacing helpers. ed8d2c4outlay
: conditional helpers. outlay.If can be used to conditionally layout a subwidget. It has flex and stack helpers so it can be used in many common places. f881e51outlay
: multi list. The multi list allows easily building up a single “list” composed of several list widgets. c005f2a
Chris Waldon:
gioui.org/example@v0.9.0
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
Chris Waldon:
go.*
: drop accidental go.work. 8a43e32git
: ignore go.work. da54675git
: drop ignorefile. As per Elias’ request, this drops the ignore file in favor of using a global git ignore on my machine. c6bccec
Admin:
go.*
: bump Go version and dependencies. 5930499all
: clean up code, upgrade to modern Go facilities. 0d07110
Reto Brunner:
7gui/counter
: update counter before displaying it. Opening the app and “clicking” the button with saydoes not increment the counter prior to this change. Fix this by first processing the clicks, then render. 76286d5
gioui.org/cmd@v0.9.0
Cmd has numerous small improvements like new Go versions, support for building Android apps with 16KB-page-sizes, a fix for WASM builds on Go 1.24, and a fallback for passing signing passwords via the environment instead of flags.
Changes by Author
Elias Naur:
go.mod,.builds
: upgrade minimum Go version to 1.23. d1bccae.builds
: upgrade debian image to fix a wine compatibility issue. 51c6d80gogio
: disable failing JS test. 01ffdf7gogio
: improve -version parse error message. 1b42337gogio
: use ANDROID_HOME instead of the deprecated ANDROID_SDK_ROOT. 3f0ad89
Admin:
go.*
: bump Go and dependencies. ab2d621all
: cleanup code and upgrade to modern Go facilities. ae8dd54
Lucas Rodrigues:
gogio
: [Android] support 16kB page sizes, required for Android 15+. Previously, Gio crashes on 16KB page-size enable version of Android 15. Also, Google Play will require 16KB compatible apps by November 2025. aecb472
Thomas Bruyelle:
gogio
: fix #633 wasm_exec.js location for go1.24. 37612f9
Sean E. Russell:
gogio
: read -signpass from environment variable if it isn’t provided as an argument. c108ce0
giouiorg
Egon updated the site to explain color blends more clearly, and Oliver fixed a timestamp formatting issue.
Changes by Author
Oliver Lowe:
site
: use RSS spec compliant timestamp in feed. 808cf4e
Egon Elbre:
internal/f32color
: fix difference between BlendRGBA and BlendSRGBA. 81bcbc9
End
Thanks for reading!
Chris Waldon