Newsletter, May 2022
Material Data Table added and unit.Value removed

material data table

I’m sure you’re all wondering “what happened to the material data table?” Well, good news! This month, Jan’s work was merged into gio-x and the bounty payout is processing right now!

The basic grid type is available in gioui.org/x/outlay.Grid. It provides a two-dimensional surface of cells that can be populated with elements much like layout.List. All rows must currently be the same height, though columns may vary in width.

The material styling is available in gioui.org/x/component.GridStyle and gioui.org/x/component.TableStyle. These add scrollbars, and the Table version provides a simple way to add persistent headers to your table.

For examples of the use of these new types, see gioui.org/example/fps-table and gioui.org/examle/color-grid.

core gio

Elias and I spent a lot of time away from Gio this month, but that doesn’t mean that nothing happened. Elias merged an important change to how Gio handles units that considerably simplifies how they work and dramatically reduces the number of casts required to change units.

At a high level, the unit.Value type is gone, replaced by concrete types unit.Dp and unit.Sp. These unit types are now accepted explicitly by the APIs that consume them, which prevents accidentally using an inappropriate unit. As these new values are simply float32 under the hood, you can now do math directly on them instead of invoking methods like unit.Add. The new units can each be converted into pixels using unit.Metric.Dp and unit.Metric.Sp respectively. As a unit.Metric is embedded in the layout.Context, the following is sufficient to resolve Dp into pixels:

gtx.Dp(8)

The clip package API has been updated to use integer coordinates for most common operations as well. Usually, rectangles and other shapes should be pixel-aligned, so the loss of precision won’t matter for most use-cases. If you need floating point precision, the clip.Path API still provides it so that complex shapes can be drawn with sub-pixel precision.

I mostly focused on bugfixes. I tackled several visual bugs, a memory leak, and a problem with the semantics of key event propagation.

There were 27 commits to core since the last newsletter.

Breaking API changes by author:

Elias Naur:

  • gesture,widget,f32: [API] use integer coordinates for gesture coordinates. Most widget code operate in integer coordinates. This change makes gesture pointer coordinates integer, to lessen the number of float32 to int conversions. (14805af3)
  • all: [API] change op.Offset to take integer coordinates. op.Offset is a convenience function most often used by layouts. Layouts usually operate in integer coordinates, and the float32 version of op.Offset needlessly force conversions from int to float32. This change makes op.Offset take integer coordinates, to better match its intended use. (a63e0cb4)
  • all: [API] change clip.RRect and UniformRRect to take integer coordinates. Like the change to op.Offset before this, clip.RRect and UniformRRect is usually used with integer coordinates. Change to integer coordinates to eliminate many useless conversions to float32. (48a8540a)
  • all: [API] replace unit.Value with separate unit.Dp, unit.Sp types. The unit.Value is a struct and thus more inconvenient to use than its underlying float32 type. In addition, most uses don’t need a general value, but rather a specific unit given by the context. This change replaces unit.Value with two float32 units, Dp and Sp. It also changes variables and parameters of unit.Value to a specific unit type matching the context. That is, unit.Dp everywhere except for text sizes which are in Sp. (3d374913)
  • layout: [API] remove FRect. We’re about to unexport f32.Rectangle, this change removes the only public API for it. (fc79ec5c)
  • f32: [API] unexport Rectangle. There are no public API that uses f32.Rectangle anymore. Move Rectangle to an internal package for internal use. (b5f12c5f)

Non-breaking changes by author:

Elias Naur:

  • go.*: upgrade github.com/benoitkugler/textlayout to v0.1.1. The v0.1.1 release is much smaller because the module no longer contains test data. See (c68417aa)
  • io/key: remove key.NameUp/Down/Left/Right. They’re no longer used now that Android directional keys are mapped to key.Name*Arrow. (7fc594fa)
  • app: don’t lock up when using custom renderers. A recent change broke custom rendering by not allowing the client to continue after calling FrameEvent.Frame. This change makes sure the client is allowed to continue regardless of rendering mode. (0e2e02a6)
  • app: lock GPU context during present. The OpenGL backend needs it, but I keep forgetting to test it when rearranging the window rendering code. The gogio X11 end-to-end test tests this issue, but unfortunately it is disabled because of flakiness. (79f037f9)
  • app: don’t deadlock if Window.validateAndProcess fails. Fixes: #417 (2a0a196d)
  • flake.lock: run nix flake update. Otherwise, running Gio programs fails with an error because of GPU driver mismatch. (9bf68963)
  • all: apply suggestions from staticcheck.io. (916efb46)
  • gpu: re-align coverUniforms struct. Direct3D requires GPU vertex attribute structs sizes be a multiple 16. A cleanup commit removed an unused field, and broke that assumption. (44416833)
  • app: restore IME snippet after an EditorReplace. Commit 02732037436f547717ec53073ce8b295329c9bd8 removed the snippet restore event, which broke IME on macOS and Windows. (5cf916c0)

Chris Waldon:

  • widget: ensure empty editor makes space for caret. Prior to this change an editor with no content and a zero minimum constraint would return itself has having width zero. This prevented users from being able to see the editor when they moved focus to it, as it could not display its caret. This simple change ensures that, at minimum, the editor returns its dimensions to include the width of a caret. (4996337d)
  • text: fix doc typos. (28acb79b)
  • widget/material: prevent invalid list item constraints. Previously, a bug in the ListStyle could result in items being passed a negative value in the minimum constraints. (99d03320)
  • widget/material: ensure scrollbar within dimensions. This commit fixes a visual-only bug in the ListStyle that could make the scrollbar float at the edge of the maximum constraints when the list did not occupy the full constraints. The list would still reserve layout space for the scrollbar in the correct position, but the scrollbar would not be displayed there. (87be31cb)
  • io/router: fix focused key event propagation. When a key.InputOp is focused, keypresses that it does not explicitly include in its key set should check for ancestor clip areas that are interested in them. Previously this check only included ancestors of the final clip area in the hit tree, and could fail to find ancestors of the focused key.InputOp because they were in a different branch. (44ec48d3)
  • text: eliminate path cache memory leak. This commit alters the method we use to check for valid cache hits in the text path cache. Previously we stored the entire text.Layout that was provided when the cache entry was set so that we could ensure only identical text.Layouts would produce hits (guarding against hash collisions). This commit instead pulls the glyph IDs for every glyph in the text.Layout and stores them in the cache. This uses far less memory and seems to allow cache entries to be GCed after eviction. (11192a51)

Mearaj:

  • app,widget: use arrow keys for Android navigation. Android doesn’t distinguish between the arrow keys on a keyboard and the directional keys on a remote control, so there’s no way to move the caret in an Editor with arrow keys. This change updates the Android port to map Android’s DPAD_* key codes to the arrow key names, fixing caret movement. The change also updates Editor to only request arrow keys that actually move the caret, to keep directional focus movement working. (7ced0d29)

Inkeliz:

  • app: [Android] improve keyboard hints. This patch adds support for the following KeyboardHint: Text, Email, Telephone and URL. (c97f976e)

Egon Elbre:

gio-x

The biggest change in x was the merge of the material data table, but there were also some bugfixes and new features.

There have been 7 commits to gio-x since the last newsletter.

Breaking API changes by author:

Chris Waldon:

  • all: [API] convert to unit API. This change updates all packages to be compatible with the new unit package exposed by Gio core. (48c6fc7)
  • outlay: drop previous table and rename grid to flow. This commit removes the outlay.Table type that is obsolete now that we have a more general two dimensional grid type available. (d3f24a3)

Non-breaking changes:

Chris Waldon:

  • outlay: make gridwrap return correct baseline. The GridWrap type previously returned a zero baseline unconditionally, which made it impossible to align content outside of the grid to the first line of text within the grid. Now the baseline is set to the baseline of the first widget laid out within the grid. (1b330a1)
  • component: simplify text field border clipping. This commit alters the way in which the decorative border around the text field is drawn. It was previously drawn in three clipped segments, but now is drawn all at once with a single clip mask. (1978dde)

Jan Kåre Vatne:

  • component: implement grid and table layouts. This commit adds support for material themed grid and table widgets with appropriate scorllbars and headings. (8732bd3)
  • outlay: implement grid layout. This patch implements a two dimensional grid that functions much like layout.List. The API accepts a closure to provide the dimensions of each row and column, and a separate closure to supply the contents of each cell. (df70009)

er:

  • component: adding a way to remove selected item. (25f67b5)

gio-example

A couple of small changes went into the examples repository this month:

Chris Waldon:

  • deps,all: update to latest gio{,-x} and fix all examples. This commit updates all examples to use the latest units API. It also drops the outlay/table example, as outlay no longer provides that layout. (b5ffb1e)
  • color-grid,fps-table: add simple demos exploring grid/table usage. This commit adds two demonstrations of the new grid and table types available in gioui.org/x/component. (caaef92)

Elias Naur:

  • go.*: upgrade to latest Gio, bump go.mod to 1.17. (b8e926b)

gioui.org

Elias updated the website to the latest API as well.

Elias Naur:

  • go.*,include/files/architecture: upgrade to latest Gio. (f1940f3)

gio-cmd

Lucas updated gogio to refuse compilation if the flags are malformed.

Inkeliz:

  • gogio: refuse compilation with additional arguments. Previously, it was possible to misuse gigio with arguments after the package, such as gogio -target android . -o foo.apk. That cause an undesired effect, since -o is silently ignored by gogio. (35e56c5)

chipalee

Turns out my daughter really likes music, so to entertain her I wrote a chiptune pipe organ in Gio. It’s very simple, but was a fun little project. There’s (currently) a web demo of it available here:

https://whereswaldon.srht.site/

After it loads, type to play notes. Hold shift to play chords.

You can find the source here:

https://git.sr.ht/~whereswaldon/chipalee

You can try it locally by running:

go run git.sr.ht/~whereswaldon/chipalee@latest

The desktop version provides additional features when using the control and alt modifiers.