This commit switches to the new Regular() collection method in gofont,
ensuring that the regular face is only ever loaded once.
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit adds back support for loading font collections, which we
lost when switching to the harfbuzz-based shaper last January. In
addition, this commit takes advantage of our new font loading library's
metadata facilities to automatically construct text.FontFaces for all
fonts within a collection. This is significantly more ergonomic for
users, and can be used to load single fonts with automatic metadata
detection as well.
I've exposed a opentype.Face.Font() method that can be used to get the
font metadata for a given face as well, though you have to type assert to
see it:
var myFace text.Face
if asOpentype, ok := myFace.(opentype.Face); ok {
myFont := asOpentype.Font()
}
The one problem with this approach is that the font variant field always
be automatically populated. Mono font detection is supported, but
other variants like SmallCaps are more complicated and may need to be
expressed differently in the future (smallcaps is a feature that any font
file can have, not necessarily a separate font file). See this [0] upstream
issue for details.
Additionally, in order to avoid import cycles, I've moved the declarations
of font attributes to package font. You can fix your code automatically to
refer to the new definitions by running the following:
gofmt -w -r 'text.FontFace -> font.FontFace' .
gofmt -w -r 'text.Variant -> font.Variant' .
gofmt -w -r 'text.Style -> font.Style' .
gofmt -w -r 'text.Typeface -> font.Typeface' .
gofmt -w -r 'text.Font -> font.Font' .
gofmt -w -r 'text.Regular -> font.Regular' .
gofmt -w -r 'text.Italic -> font.Italic' .
gofmt -w -r 'text.Thin -> font.Thin' .
gofmt -w -r 'text.ExtraLight -> font.ExtraLight' .
gofmt -w -r 'text.Light -> font.Light' .
gofmt -w -r 'text.Normal -> font.Normal' .
gofmt -w -r 'text.Medium -> font.Medium' .
gofmt -w -r 'text.SemiBold -> font.SemiBold' .
gofmt -w -r 'text.Bold -> font.Bold' .
gofmt -w -r 'text.ExtraBold -> font.ExtraBold' .
gofmt -w -r 'text.Black -> font.Black' .
gofmt -w -r 'text.Hairline -> font.Thin' .
gofmt -w -r 'text.UltraLight -> font.ExtraLight' .
gofmt -w -r 'text.DemiBold -> font.SemiBold' .
gofmt -w -r 'text.UltraBold -> font.ExtraBold' .
gofmt -w -r 'text.Heavy -> font.Black' .
gofmt -w -r 'text.ExtraBlack -> font.Black+50' .
gofmt -w -r 'text.UltraBlack -> font.ExtraBlack' .
Make sure each affected file imports gioui.org/font.
[0] https://github.com/go-text/typesetting/issues/57
Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
Now, Gio will send one system.StageEvent with system.StageInactive when
the window is not active. It is implemented on macOS and Windows.
This change is not fully backward compatible, if your code compares
the Stage (`stage < system.StageRunning`), you need to consider
the new system.StageInactive.
Signed-off-by: inkeliz <inkeliz@inkeliz.com>
Window.decorations.height is supposed to be a constant during the
lifetime of the window, unlike w.decorations.Config.decoHeight that
varies depending on the decorations state (fallback or custom).
This change makes that so, fixing a problem where the fallback
decorations would fail to offset client content after a maximize
or minimize.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Pass through a fallback window decoration height to the Wayland backend,
so that it can account for it when determining surface size.
Fixes: https://todo.sr.ht/~eliasnaur/gio/435
Signed-off-by: Elias Naur <mail@eliasnaur.com>
When a window is destroyed, it is no longer valid to call its wakeup
method.
Thanks to Jack Mordaunt for identifying the race.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Before this change, Perform and Configure could be called during the
event processing where additional events would be queued. However,
a Maximize animation on macOS works by repeatedly sending draw
requests, and they must not be postponed.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The app.Window.Perform(ActionMove) is the wrong abstraction for
initiating a move gesture: Windows needs to know the move gesture
area at pointer move, and macOS needs to know the pointer button
down event that triggers the move gesture. This change replaces
Perform(ActionMove) with a new system.ActionInputOp that marks an
area movable.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Allowing clients to initiate resize gestures is a waste: macOS
doesn't support them, and the only reason we added them was to
implement client-side decorations for Wayland. Now all desktop
platforms implement resize gestures as needed, and we no longer
need the system.Action actions.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Not only is the client guaranteed a ConfigEvent, but app.Window
can assume that an unsupported decoration change will be corrected
(by a ConfigEvent with Decorated forced to the supported value).
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Until now, fallback decorations were only needed for Wayland client-side
decorations. We're about to support app.Decorated(false) one some platforms,
where Window should not fall back to drawing its own decorations.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Before this change, client-side decorations for Wayland were drawn
before client content, which was prevented from drawing over
decorations with a clip. While visually correct, resize handles would't
work as long as client listeners are near the window edges to swallow
pointer input.
This change makes app.Window draw decorations last, fixing resizing
and saves a clipping operation. This is an alternative to the original
fix for #361, commit 20d4bc2.
References: https://todo.sr.ht/~eliasnaur/gio/361
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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.
Switching to typed float32s has multiple advantages
- They can be constants:
const touchSlop = unit.Dp(16)
- Casting untyped constants is no longer necessary:
insets := layout.UniformInset(16)
- Calculation with values is natural:
func (s ScrollbarStyle) Width() unit.Dp {
return s.Indicator.MinorWidth + s.Track.MinorPadding + s.Track.MinorPadding
}
The main API change is that calls to gtx.Px must be replaced with either
gtx.Dp or gtx.Sp depending on the unit.
Idea by Christophe Meessen.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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.
Fixes: https://todo.sr.ht/~eliasnaur/gio/412
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
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.
Fixes: https://todo.sr.ht/~eliasnaur/gio/410
Signed-off-by: Mearaj <mearajbhagad@gmail.com>
Instead of cmpletely replacing the IME snippet for every update, expand
the old range if there is overlap. This change avoids never-ending
restarts of the IME on Android where snippets are expanded in two
calls, one for expanding before the selection and one for exanding after
the selection.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
It's much simpler to map the Android back button to a key.Event and
let the usual key filtering determine whether to block its default
behaviour.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This change adds key.NameUp/Down/Left/Right and maps the Android TV
remote directional keys to them. As a side-effect a key.InputOp can
now receive directional keys (and block their focus movement).
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Before this change, Tab and Shift-Tab would always result in focus
movement. This this change, a key.InputOp with a matching Keys set
will block focus movement and deliver the events to it.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
We should return as soon as possible from FrameEvent.Frame to allow the main
goroutine to continue processing other tasks. Whereas GPU.Frame may touch
the frame ops, GPU.Present will not, so this change moves Present to after
returning from FrameEvent.Frame.
This is a variant of 38ff78df5d that
works on OpenGL where context locking is required.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
We should return as soon as possible from FrameEvent.Frame to
allow the main goroutine to continue processing other tasks.
Whereas GPU.Frame may touch the frame ops, GPU.Present will not,
so this change moves Present to after returning from FrameEvent.Frame.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
List was recently changed to include an extra child at each end, to
automatically scroll when reaching the end of a focus direction. However,
if List includes unfocusable children that strategy may fail. This change
adds another fallback where app.Window will scroll a constant amount in
the focus direction, to reveal more children.
For https://github.com/tailscale/tailscale/issues/4278.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
A focused widget may be partially or completely off-screen in which case
the user will have difficulty interacting with it. This change attempts to
scroll the focused widget into view by issuing synthetic scroll events.
For https://github.com/tailscale/tailscale/issues/4278, but doesn't completely
solve it because layout.Lists won't layout focusable widgets outside its visible
bounds. A follow-up change deals with that.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This is a refactor to make it easier to add higher level logic to
focus moves. A follow-up will add automatic scrolling to bring
focused widgets into view.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
It's now possible to directly user pointer.Cursor to add to the ops.
pointer.CursorText.Add(gtx.Ops)
This is an API change. Use pointer.Cursor directly instead of CursorNameOp.
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
Events such as system.CommandEvent may result in Invalidate being
called. Ensure animation state is properly updated.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Mapping it to key.NameReturn confuses widgets such as Editor that
treats clicks separate from return key presses.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This change implements reporting of the caret position from Editor, as well
as Windows, macOS, Android support. As a result, the IME composition window
on Windows and macOS is now positioned correctly.
References: https://todo.sr.ht/~eliasnaur/gio/246
Signed-off-by: Elias Naur <mail@eliasnaur.com>
When a text range in the IME snippet is replaced, the replacement
is discarded if the range don't overlap with the snippet range. However,
the replacement is more relevant than whatever snippet is current.
This change discards the snippet in case of no overlap.
As a bonus, IMEs that leaves the snippet range at [0:0] will have the
snippet track the composing region now.
The FuzzIME test is adjusted to always generate replacements that overlap
Editor content; otherwise the IME snippet and editor state can't be expected
to match.
Signed-off-by: Elias Naur <mail@eliasnaur.com>