Newsletter, September 2023
Opacity Manipulation, Constraint Debugging, and More

This month brings us Gio (and Gio-x) v0.3.1, which is the first tagged version to contain no breaking changes. Applications should be able to update from v0.3.0 with no changes.

That being said, there are two exciting new features this month:

  • Opacity manipulation, which allows you to control the opacity of a group of drawing operations as a whole, enabling applications to (among other things) fade widget content in and out of view. See the section on core for more details.
  • An interactive constraint debugger, which you can drop into your layout code with a simple function call and use to both visualize and manipulate your widget constraints live. See the section on gio-x for more details.

Sponsorship

This month, Gio thanks the following organizations and community members for their ongoing support!

Supporting the whole team:

Supporting a maintainer:

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.3.1

As mentioned above, the major feature in core this month is opacity manipulation. The API works similarly to the clip and transformation APIs. You invoke paint.PushOpacity to create a paint.OpacityStack. Until you call paint.OpacityStack.Pop(), all drawing operations will be multiplied by the opacity value provided to paint.PushOpacity (in the range [0,1]).

Here’s a practical example of drawing a widget at 50% opacity:

    func(gtx layout.Context, w layout.Widget) layout.Dimensions {
		defer paint.PushOpacity(gtx.Ops, .5).Pop()
		return w(gtx)
	}

For an interactive example of opacity manipulation, see the new gioui.org/example/opacity.

Additionally, there were several platform-specific bugfixes, a big performance improvement from Dominik Honnef, and XKB support for numpad keys from Dominik again.

Changes by Author

Elias Naur:

  • internal/ops: remove unused TypePushTransform. ae43d18c
  • op/paint: add opacity operation. The new paint.PushOpacity allows for adjusting the opacity of a group of drawing operations. ae3bd2a1
  • app: [Windows] remove redundant call to SetWindowText. f30e936d
  • app: [Windows] remove padding from maximized custom decorated windows. As described in https://devblogs.microsoft.com/oldnewthing/20150304-00/?p=44543 Windows extends maximized windows outside the visible display. This is not appropriate for custom decorated windows, so this change implements a workaround in the handling of WM_NCCALCSIZE. 313c488e
  • gpu: fix opacity layer rendering on OpenGL. Fixes: #536 526db27c
  • app: [macOS] fix transition from maximized to restored. The NSWindow.zoomed property is not reliable when a window is being constructed. Only call it when necessary. b66dcc43

Dominik Honnef:

  • app: support numpad keys in xkb. b9654eb4
  • op: don’t allocate for each string reference. When storing a string in an interface value that escapes, Go has to heap allocate space for the string header, as interface values can only store pointers. In text-heavy applications, this can lead to hundreds of allocations per frame due to semantic.LabelOp, the primary user of string-typed references in ops. b4d93379

Chris Waldon:

  • op/clip: prevent no-op path segments. This commit prevents the insertion of LineTo and QuadTo path segments that have no visible effect on the path (because the path’s pen is already at their end state). This eliminates whisker artifacts from some stroked paths. Thanks to Morlay for the bug report leading to this fix. 27193ae8

gioui.org/x@v0.3.1

The major addition to gio-x is package debug. This package is intended to provide useful tools for debugging Gio layouts interactively. Right now it contains a simple interactive constraint debugger, but the plan is to enhance it continuously as new opportunities for debug tooling are identified.

You can see what the debugger looks like here.

To use the constraint debugger, you wrap an existing widget call. If you have existing code of the form:

return myWidget.Layout(gtx)

You can wrap myWidget in a constraint debugger by calling:

return debug.Wrap(&tag, myWidget.Layout)

The &tag parameter needs to be a unique value for that widget. This will be used as a key in a global map to automatically manage the widget state of the constraint editor. If you only have a single constraint editor, you could just provide a constant value, like 0, but for many constraint editors it’s best to supply unique values. When laying out stateful widgets, a pointer to the widget state works well.

The constraint editor will visualize the minimum and maximum constraints of the widget, as well as its returned dimensions. You can click and drag both the minimum and maximum constraint boxes in order to modify the constraints, though you cannot create invalid constraints (like min larger than max). The changes you make are not persisted across application restarts, but should help developers understand why widgets are laid out in unexpected ways more easily.

Changes by Author

Chris Waldon:

  • component: deprecate TruncatingLabelStyle. 1013889
  • outlay: fix pre go 1.21 slices package use. I didn’t realize that my editor imported the wrong slices package here. We do support Go 1.20, so I’ve swapped to the old slices package in x. f859e99
  • go.*: update golang.org/x for slices.Reverse. 3246478
  • component: update context area absolute position docs. This commit clarifies the documentation for component.ContextArea’s AbsolutePosition field to make the intended use clearer. 9b6e934
  • debug: define simple constraint editor. This commit defines debug.ConstraintEditor, a type that can be easily inserted into layout code to allow the programmer to experiment with constraint manipulations within their live interface. 01f5b44
  • debug: add global helpers with automagic state management. This commit adds two global functions that can use any unique tag to store the constraint editor state in a map, making it much easier for layout authors to insert ad-hoc constraint editors into their code. 679b6cf
  • debug: display constraint/size values as text. 8819fac
  • go.*: update to gio v0.3.1. 4bee51d

gioui.org/example@v0.3.1

In the examples repo, I made a minor improvement to the customdeco example and added an example for playing with the new opacity manipulation and how it composes when nested.

Changes by Author

Chris Waldon:

  • customdeco: visually indicate if custom decorations are expected. Some platforms (notably X11) do not support custom window decorations. This change makes the example program indicate whether the window has been told by the OS whether such decorations should be used. 8867314
  • go.*: update to latest gio. ce20cf9
  • opacity: add example program for the new opacity layer operations. This commit adds a simple example that demonstrates how to use the new opacity layer paint functions and how this operation composes when nested. d2e46ca
  • go.*: update to gio and gio-x v0.3.1. e70eb14

End

Thanks for reading!

Chris Waldon