|
| 1 | +--- |
| 2 | +title: Newsletter, September 2025 |
| 3 | +shorttitle: September 2025 |
| 4 | +subtitle: A Wave of Commuity-Driven Enhancements |
| 5 | +date: "2025-01-14T12:00:00Z" |
| 6 | +--- |
| 7 | + |
| 8 | +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. |
| 9 | + |
| 10 | +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. |
| 11 | + |
| 12 | +# Sponsorship |
| 13 | + |
| 14 | +These past few months, Gio thanks the following organizations and community members for their ongoing support! |
| 15 | + |
| 16 | +Supporting the whole team: |
| 17 | + |
| 18 | +- [Plato Team](https://www.platoapp.com/) via GitHub Sponsorship of Elias and Chris. |
| 19 | +- [Steve Russo](https://github.com/steverusso) via GitHub Sponsorship of Gioui. |
| 20 | +- [Denys Smirnov](https://github.com/dennwc) via OpenCollective. |
| 21 | +- [Larry Clapp](https://github.com/theclapp) via GitHub Sponsorship of Elias and Chris. |
| 22 | + |
| 23 | +Supporting a maintainer: |
| 24 | + |
| 25 | +- [Kristian Mide](https://github.com/fasmide) via GitHub Sponsorship of Elias. |
| 26 | +- [Dmitri Shuralyov](https://github.com/dmitshur) via GitHub Sponsorship of Elias. |
| 27 | +- [Paul Greenberg](https://github.com/greenpau) via GitHub Sponsorship of Elias. |
| 28 | +- [anedel](https://github.com/anedel) via GitHub Sponsorship of Elias. |
| 29 | +- A number of anonymous community members supporting both Elias and Chris. |
| 30 | + |
| 31 | +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](https://opencollective.com/gioui) or [GitHub Sponsors](https://github.com/sponsors/gioui). |
| 32 | + |
| 33 | + |
| 34 | + |
| 35 | +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: |
| 36 | + |
| 37 | +- Walter Werner Schneider made numerous renderer, platform, and ergonomic fixes across Gio. |
| 38 | +- Dave Akers fixed a number of wayland event-handling bugs. |
| 39 | +- Marcel Juffermans fixed Windows window positioning (centered at startup) and added minimal support for touchscreens on Windows. |
| 40 | +- zjzhang fixed a text line height issue. |
| 41 | +- vasijob225 fixed some counterintuitive behaviors in the window decorations on Windows. |
| 42 | +- kurth4cker improved some documentation. |
| 43 | +- Lucas Rodrigues enabled scrolling in a horizontal list with a normal mouse wheel. |
| 44 | +- Miles Alan fixed compatibility with Go 1.23 which we accidentally lost by using iterators too early. |
| 45 | +- Veikko Sariola eliminated many heap allocations during typical uses of layout.Stack and layout.Flex. |
| 46 | + |
| 47 | +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. |
| 48 | + |
| 49 | +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. |
| 50 | + |
| 51 | +## Changes by Author |
| 52 | + |
| 53 | +Walter Werner Schneider: |
| 54 | + |
| 55 | +- **`layout`**: add Values map to Context. Fixes: #654 [c3ce484b](https://git.sr.ht/~eliasnaur/gio/commit/c3ce484b) |
| 56 | +- **`internal/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. [6ce7ffa4](https://git.sr.ht/~eliasnaur/gio/commit/6ce7ffa4) |
| 57 | +- **`app`**: [Wayland] don't recreate EGL surface during resize. Fixes: #656 [420f4c32](https://git.sr.ht/~eliasnaur/gio/commit/420f4c32) |
| 58 | +- **`widget`**: 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. [b2b12d62](https://git.sr.ht/~eliasnaur/gio/commit/b2b12d62) |
| 59 | +- **`app`**: optimize window context locking. Avoids unnecessary eglMakeCurrent and thread locking calls to enhance performance. [3e601e73](https://git.sr.ht/~eliasnaur/gio/commit/3e601e73) |
| 60 | +- **`f32`**: replace Affine2D{} with AffineId() for identity transformations. Reduces ambiguity by introducing AffineId() for representing identity transformation matrices. [d76b4272](https://git.sr.ht/~eliasnaur/gio/commit/d76b4272) |
| 61 | +- **`f32`**: use value receiver for Split method on Affine2D. [3b1effb7](https://git.sr.ht/~eliasnaur/gio/commit/3b1effb7) |
| 62 | +- **`f32`**: add tests for Affine2D transformations. References: #655 [31564b98](https://git.sr.ht/~eliasnaur/gio/commit/31564b98) |
| 63 | +- **`app`**: [Wayland] add forth and fifth buttons. [78b54615](https://git.sr.ht/~eliasnaur/gio/commit/78b54615) |
| 64 | +- **`f32`**: replace Affine2D{} with AffineId() for identity transformations. References: #655 [4e5a344c](https://git.sr.ht/~eliasnaur/gio/commit/4e5a344c) |
| 65 | +- **`all`**: avoid collides with builtin min/max functions. [ba82ae46](https://git.sr.ht/~eliasnaur/gio/commit/ba82ae46) |
| 66 | +- **`op/clip`**: add bounds expansion after move. After moving the pen, the next action should update the bounds for the start position. [0c145b38](https://git.sr.ht/~eliasnaur/gio/commit/0c145b38) |
| 67 | +- **`app`**: properly initialize editorState for tests. [a274f6fe](https://git.sr.ht/~eliasnaur/gio/commit/a274f6fe) |
| 68 | +- **`gpu`**: respect the offset fraction when clipping. Fixes: #534 [bbb6d05f](https://git.sr.ht/~eliasnaur/gio/commit/bbb6d05f) |
| 69 | +- **`gpu`**: replace f32.Point/Rectangle with image.Point/Rectangle. [36a2fa37](https://git.sr.ht/~eliasnaur/gio/commit/36a2fa37) |
| 70 | +- **`internal/stroke`**: handle zero-length points. [17657052](https://git.sr.ht/~eliasnaur/gio/commit/17657052) |
| 71 | +- **`internal/stroke`**: fix point normalization for unit length.. [30f8ac10](https://git.sr.ht/~eliasnaur/gio/commit/30f8ac10) |
| 72 | +- **`internal/stroke`**: quickly handle zero length normalization. [f4503973](https://git.sr.ht/~eliasnaur/gio/commit/f4503973) |
| 73 | +- **`gpu/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](https://git.sr.ht/~eliasnaur/gio/commit/4c0e526c) |
| 74 | + |
| 75 | +Elias Naur: |
| 76 | + |
| 77 | +- **`all`**: replace golang.org/x/exp/slices with the standard library package. [a5068a19](https://git.sr.ht/~eliasnaur/gio/commit/a5068a19) |
| 78 | +- **`app`**: [macOS] correct error handling for newMtlContext. Fixes: #632 [af446e8b](https://git.sr.ht/~eliasnaur/gio/commit/af446e8b) |
| 79 | +- **`gpu`**: don't store transformed rectangle paths under the same cache key. Fixes incorrect rendering of multiple transformed instances of a rectangle. [77709d17](https://git.sr.ht/~eliasnaur/gio/commit/77709d17) |
| 80 | +- **`gpu/internal/rendertest`**: allow nil pixel check functions. [0d232405](https://git.sr.ht/~eliasnaur/gio/commit/0d232405) |
| 81 | +- **`app`**: [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. [72a72a2b](https://git.sr.ht/~eliasnaur/gio/commit/72a72a2b) |
| 82 | +- **`layout,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. [fff23754](https://git.sr.ht/~eliasnaur/gio/commit/fff23754) |
| 83 | +- **`io/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. [efd31ad6](https://git.sr.ht/~eliasnaur/gio/commit/efd31ad6) |
| 84 | +- **`io/pointer`**: remove Foremost priority. The only known use-case (nested scrolling) now works without special treatment of the foremost handler. [e18db649](https://git.sr.ht/~eliasnaur/gio/commit/e18db649) |
| 85 | +- **`flake.*`**: upgrade to nixpkgs 25.05, use nixpkgs android SDK. [0a209f7d](https://git.sr.ht/~eliasnaur/gio/commit/0a209f7d) |
| 86 | +- **`app`**: [macOS] limit full screen window size when MaxSize is set. There are two max window size settings on macOS, `contentMaxSize` and `maxFullScreenContentSize`. Set the latter to avoid a window being resized larger than its maximum in full screen mode. [d50ef687](https://git.sr.ht/~eliasnaur/gio/commit/d50ef687) |
| 87 | +- **`app`**: [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. [ea979b43](https://git.sr.ht/~eliasnaur/gio/commit/ea979b43) |
| 88 | +- **`io/pointer`**: delete documentation that Cancel events have pointer IDs. Cancel events affect the entire gesture and as such all active pointers. [b2f6707a](https://git.sr.ht/~eliasnaur/gio/commit/b2f6707a) |
| 89 | +- **`app`**: [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. [6553915e](https://git.sr.ht/~eliasnaur/gio/commit/6553915e) |
| 90 | +- **`app`**: [macOS] make the app delegate optional. Inspired by the discussion at golang.org/issue/70089, this change makes our particular NSApplicationDelegate implementation optional. [3f4f8ba7](https://git.sr.ht/~eliasnaur/gio/commit/3f4f8ba7) |
| 91 | + |
| 92 | +Dave Akers: |
| 93 | + |
| 94 | +- **`app`**: [Wayland] use correct serial for wl_pointer_set_cursor. [a3117d38](https://git.sr.ht/~eliasnaur/gio/commit/a3117d38) |
| 95 | +- **`app`**: [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. [016714a6](https://git.sr.ht/~eliasnaur/gio/commit/016714a6) |
| 96 | +- **`app`**: [Wayland] remove window.seat in favor of wlSeat.pointerFocus. [cc6048bc](https://git.sr.ht/~eliasnaur/gio/commit/cc6048bc) |
| 97 | + |
| 98 | +Marcel Juffermans: |
| 99 | + |
| 100 | +- **`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(). [35ec76e5](https://git.sr.ht/~eliasnaur/gio/commit/35ec76e5) |
| 101 | +- **`io/pointer`**: add forth and fifth buttons. [0eac4f2c](https://git.sr.ht/~eliasnaur/gio/commit/0eac4f2c) |
| 102 | +- **`app`**: [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<DOWN|UP>, 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](https://git.sr.ht/~eliasnaur/gio/commit/809a6d0d) |
| 103 | + |
| 104 | +Chris Waldon: |
| 105 | + |
| 106 | +- **`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. [593c5fbf](https://git.sr.ht/~eliasnaur/gio/commit/593c5fbf) |
| 107 | +- **`go.*`**: 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](https://git.sr.ht/~eliasnaur/gio/commit/14a9fbcc) |
| 108 | + |
| 109 | +Admin: |
| 110 | + |
| 111 | +- **`go.*`**: bump Go to 1.23, upgrade dependencies. [86668e8b](https://git.sr.ht/~eliasnaur/gio/commit/86668e8b) |
| 112 | +- **`all`**: clean up code, upgrade to modern Go. [f73287be](https://git.sr.ht/~eliasnaur/gio/commit/f73287be) |
| 113 | + |
| 114 | +zjzhang: |
| 115 | + |
| 116 | +- **`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](https://git.sr.ht/~eliasnaur/gio/commit/adaace86) |
| 117 | + |
| 118 | +vasijob225: |
| 119 | + |
| 120 | +- **`app`**: [Windows] hide the maximize button when MaxSize is set. Also, disable window frame resizing when MaxSize equals MinSize. [95354d80](https://git.sr.ht/~eliasnaur/gio/commit/95354d80) |
| 121 | + |
| 122 | +kurth4cker: |
| 123 | + |
| 124 | +- **`app`**: fix miss included doc comment. [4f720af6](https://git.sr.ht/~eliasnaur/gio/commit/4f720af6) |
| 125 | + |
| 126 | +Lucas Rodrigues: |
| 127 | + |
| 128 | +- **`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](https://git.sr.ht/~eliasnaur/gio/commit/02253341) |
| 129 | + |
| 130 | +Miles Alan: |
| 131 | + |
| 132 | +- **`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](https://git.sr.ht/~eliasnaur/gio/commit/8104d527) |
| 133 | + |
| 134 | +Veikko Sariola |
| 135 | + |
| 136 | +- **`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](https://git.sr.ht/~eliasnaur/gio/commit/1a17e9ea) |
| 137 | + |
| 138 | + |
| 139 | + |
| 140 | +Gio-x gained some new layout helpers courtesy of Jack Mordaunt, but otherwise has been quiet lately. |
| 141 | + |
| 142 | +## Changes by Author |
| 143 | + |
| 144 | +Jack Mordaunt: |
| 145 | + |
| 146 | +- **`outlay`**: spacing helpers. [ed8d2c4](https://git.sr.ht/~whereswaldon/gio-x/commit/ed8d2c4) |
| 147 | +- **`outlay`**: 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. [f881e51](https://git.sr.ht/~whereswaldon/gio-x/commit/f881e51) |
| 148 | +- **`outlay`**: multi list. The multi list allows easily building up a single "list" composed of several list widgets. [c005f2a](https://git.sr.ht/~whereswaldon/gio-x/commit/c005f2a) |
| 149 | + |
| 150 | +Chris Waldon: |
| 151 | + |
| 152 | +- **`go.*`**: tidy modules. [9e809b8](https://git.sr.ht/~whereswaldon/gio-x/commit/9e809b8) |
| 153 | +- **`go.*`**: update to gio v0.9.0. [b7ffb7b](https://git.sr.ht/~whereswaldon/gio-x/commit/b7ffb7b) |
| 154 | + |
| 155 | + |
| 156 | + |
| 157 | +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. |
| 158 | + |
| 159 | +## Changes by Author |
| 160 | + |
| 161 | +Chris Waldon: |
| 162 | + |
| 163 | +- **`go.*`**: drop accidental go.work. [8a43e32](https://git.sr.ht/~eliasnaur/gio-example/commit/8a43e32) |
| 164 | +- **`git`**: ignore go.work. [da54675](https://git.sr.ht/~eliasnaur/gio-example/commit/da54675) |
| 165 | +- **`git`**: drop ignorefile. As per Elias' request, this drops the ignore file in favor of using a global git ignore on my machine. [c6bccec](https://git.sr.ht/~eliasnaur/gio-example/commit/c6bccec) |
| 166 | + |
| 167 | +Admin: |
| 168 | + |
| 169 | +- **`go.*`**: bump Go version and dependencies. [5930499](https://git.sr.ht/~eliasnaur/gio-example/commit/5930499) |
| 170 | +- **`all`**: clean up code, upgrade to modern Go facilities. [0d07110](https://git.sr.ht/~eliasnaur/gio-example/commit/0d07110) |
| 171 | + |
| 172 | +Reto Brunner: |
| 173 | + |
| 174 | +- **`7gui/counter`**: update counter before displaying it. Opening the app and "clicking" the button with say <Tab><Space> does not increment the counter prior to this change. Fix this by first processing the clicks, then render. [76286d5](https://git.sr.ht/~eliasnaur/gio-example/commit/76286d5) |
| 175 | + |
| 176 | + |
| 177 | + |
| 178 | +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. |
| 179 | + |
| 180 | +## Changes by Author |
| 181 | + |
| 182 | +Elias Naur: |
| 183 | + |
| 184 | +- **`go.mod,.builds`**: upgrade minimum Go version to 1.23. [d1bccae](https://git.sr.ht/~eliasnaur/gio-cmd/commit/d1bccae) |
| 185 | +- **`.builds`**: upgrade debian image to fix a wine compatibility issue. [51c6d80](https://git.sr.ht/~eliasnaur/gio-cmd/commit/51c6d80) |
| 186 | +- **`gogio`**: disable failing JS test. [01ffdf7](https://git.sr.ht/~eliasnaur/gio-cmd/commit/01ffdf7) |
| 187 | +- **`gogio`**: improve -version parse error message. [1b42337](https://git.sr.ht/~eliasnaur/gio-cmd/commit/1b42337) |
| 188 | +- **`gogio`**: use ANDROID_HOME instead of the deprecated ANDROID_SDK_ROOT. [3f0ad89](https://git.sr.ht/~eliasnaur/gio-cmd/commit/3f0ad89) |
| 189 | + |
| 190 | +Admin: |
| 191 | + |
| 192 | +- **`go.*`**: bump Go and dependencies. [ab2d621](https://git.sr.ht/~eliasnaur/gio-cmd/commit/ab2d621) |
| 193 | +- **`all`**: cleanup code and upgrade to modern Go facilities. [ae8dd54](https://git.sr.ht/~eliasnaur/gio-cmd/commit/ae8dd54) |
| 194 | + |
| 195 | +Lucas Rodrigues: |
| 196 | + |
| 197 | +- **`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](https://git.sr.ht/~eliasnaur/gio-cmd/commit/aecb472) |
| 198 | + |
| 199 | +Thomas Bruyelle: |
| 200 | + |
| 201 | +- **`gogio`**: fix #633 wasm_exec.js location for go1.24. [37612f9](https://git.sr.ht/~eliasnaur/gio-cmd/commit/37612f9) |
| 202 | + |
| 203 | +Sean E. Russell: |
| 204 | + |
| 205 | +- **`gogio`**: read -signpass from environment variable if it isn't provided as an argument. [c108ce0](https://git.sr.ht/~eliasnaur/gio-cmd/commit/c108ce0) |
| 206 | + |
| 207 | +# giouiorg |
| 208 | + |
| 209 | +Egon updated the site to explain color blends more clearly, and Oliver fixed a timestamp formatting issue. |
| 210 | + |
| 211 | +## Changes by Author |
| 212 | + |
| 213 | +Oliver Lowe: |
| 214 | + |
| 215 | +- **`site`**: use RSS spec compliant timestamp in feed. [808cf4e](https://git.sr.ht/~eliasnaur/giouiorg/commit/808cf4e) |
| 216 | + |
| 217 | +Egon Elbre: |
| 218 | + |
| 219 | +- **`internal/f32color`**: fix difference between BlendRGBA and BlendSRGBA. [81bcbc9](https://git.sr.ht/~eliasnaur/giouiorg/commit/81bcbc9) |
| 220 | + |
| 221 | +# End |
| 222 | + |
| 223 | +Thanks for reading! |
| 224 | + |
| 225 | +Chris Waldon |
0 commit comments