Commit Graph

46 Commits

Author SHA1 Message Date
Elias Naur e3ef98dda3 Revert "io/router: try all handlers if a key don't match the focus ancestor tree"
This reverts commit 28c206fc78. The commit
introduced counter-intuitive behaviour as demonstrated by #503. In the
meantime, topmost handlers now receive all unhandled key.Events[0], which
should cover the use-cases that motivated the original commit.

[0] https://gioui.org/commit/0dba85f52e5131c03d903c84355fb90cdb978811

Fixes: https://todo.sr.ht/~eliasnaur/gio/503
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2023-05-26 17:06:22 -06:00
Dominik Honnef b6e0376ad2 io/semantic: avoid unnecessary pointer indirection
Putting a string in an interface value has to (normally) heap allocate
the string header and string. However, putting the address of a local
string variable in an interface value has the same effect, as this
causes the local variable to escape to the heap.

Signed-off-by: Dominik Honnef <dominik@honnef.co>
2023-04-14 16:30:51 -06:00
Elias Naur 0dba85f52e io,app: route all unhandled key events to the topmost handler
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2023-02-06 17:10:44 -06:00
Elias Naur 28c206fc78 io/router: try all handlers if a key don't match the focus ancestor tree
When a key.InputOp is focused, a key.Event is matched to it and its ancestors.
If there is no focus, every handler is matched.
This change always matches to every handler, after checking the focus and
its ancestors.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-07-20 10:37:28 +02:00
Elias Naur 0057e871d0 io/router: search all key handlers when there is no focus
Fixes: https://todo.sr.ht/~eliasnaur/gio/434
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-07-02 20:51:26 +02:00
Elias Naur 3f38e67ce0 io/system: add ActionInputOp to register window move gesture areas
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>
2022-06-25 19:40:46 +02:00
Chris Waldon 44ec48d325 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.

This commit also adds a test to lock in the new behavior.

This can likely be made more efficient by adding a rapid way to map
from the focused key tag to its index in the hit tree. I wasn't sure
whether the complexity was warranted, but I'm happy to do that if
it's desired.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
2022-06-01 19:52:59 +02:00
Elias Naur b5f12c5f26 f32: [API] unexport Rectangle
There are no public API that uses f32.Rectangle anymore. Move Rectangle
to an internal package for internal use.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-05-31 10:24:09 +02:00
Elias Naur 2381c5ad70 io/router,widget: give every key.InputOp a chance to process events
If the currently focused handler don't want the key event, try every
other handler, from top to bottom. This change requires widgets to
only react when focused.

Fixes: https://todo.sr.ht/~eliasnaur/gio/406
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-04-23 15:36:45 +02:00
Elias Naur 0273203743 app,io/router: expand IME snippets if a new range overlaps the old
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>
2022-04-23 13:20:46 +02:00
Elias Naur 30fa85f518 io/router: send key events to root handlers if nothing else wants them
Fixes: https://todo.sr.ht/~eliasnaur/gio/403
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-04-23 09:40:23 +02:00
Elias Naur 380f96b3fc io/key: [API] implement key event propagation
Before this change, every Event would be passed to the focused InputOp
tag, making it impossible to implement, say, program-wide shortcuts.
This change implements key.Event routing similar to how pointer.Events
are routed: every InputOp describes the set of keys it can handle, and
the router use that information to deliver an Event to the matching
handler.

This is an API change, because every InputOp must now include a filter
matching the keys it wants to handle.

Fixes: https://todo.sr.ht/~eliasnaur/gio/395
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-04-14 19:09:00 +02:00
Elias Naur bd7f50438a io/router: account for parent clip areas when scrolling focus into view
Fixes: https://todo.sr.ht/~eliasnaur/gio/389
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-04-02 15:49:41 +02:00
Elias Naur a1b5ff059c io/router,app: scroll a bit when reaching the end in a focus direction
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>
2022-03-31 12:58:29 +02:00
Elias Naur e8603ba59e io/router: use areas to determine targets for synthetic clicks
Before this change, semantic clicks would be delivered according to
the center of the targeted widget, which could result in a different
widget receiving the click. Or in worst case, no widget in case the
center is not visible because of clipping.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-03-31 11:52:31 +02:00
Elias Naur 4326fee704 app,io/router: scroll focused widgets into view
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>
2022-03-31 11:52:31 +02:00
Elias Naur 6389b1a384 io/router: add ScrollGesture
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-03-30 22:20:27 +02:00
Elias Naur e72c46f13c io/router: use integer coordinates for bounds
There is no need for floating point coordinates, except for transforming
bounds and hit testing.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-03-30 22:20:27 +02:00
Egon Elbre cdb288d1f9 app,io/pointer: [API] remove CursorNameOp and rename CursorName -> Cursor
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>
2022-03-01 14:05:46 +01:00
Egon Elbre 4172566aad io/pointer: [API] make cursor name into a byte
Add most of the common cursors defined by different systems.

Normalize cursor names to match CSS.

This is API change: some cursor names have changed, and the
underlying type is no longer a string.

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2022-03-01 14:04:21 +01:00
Elias Naur 21431975de app,io/router: map Androids' DPAD_CENTER to a click
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>
2022-02-28 17:28:13 +01:00
Elias Naur 73eabb352d io/router,app: add support for directional focus moves
Implement support for up/down/right/left directional focus moves
and map Android directional pad keys to focus moves.

Fixes: https://todo.sr.ht/~eliasnaur/gio/195
References: https://github.com/tailscale/tailscale/issues/1611
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-02-27 19:01:32 +01:00
Elias Naur 31f55232bf app,widget,io: implement IME positioning
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>
2022-02-13 20:09:06 +01:00
Elias Naur 58cdb3e1da app,widget: implement Editor IME support, add Android implementation
Fixes: https://todo.sr.ht/~eliasnaur/gio/116
References: https://todo.sr.ht/~eliasnaur/gio/246
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-02-06 10:31:53 +01:00
Elias Naur cce0a121e1 io/router: don't panic if AppendSemantics is called without a frame
Fixes: https://todo.sr.ht/~eliasnaur/gio/328
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-12-30 10:23:23 +01:00
Pierre Curto 03016f0c69 widget: add drag and drop support
This patch adds internal Drag and Drop support to app.Windows.

The new package io/transfer adds the ability to
define draggable and droppable targets, which
are leveraged by the new widget.Draggable type.

The API is generic and could handle future use
cases, such as external Drag and Drop.

Updates gio#153

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-12-07 12:45:53 +01:00
Elias Naur 8a90074d04 io/semantic: add package for adding semantic descriptions to UI components
Software such as screen readers require semantic descriptions of user
interfaces to effectively present and interact with them. Package
semantic, combined with the existing package clip provide the operations
for Gio programs to describe themselves.

This change implements the semantic package and the routing changes for
accessing semantic trees; follow-ups add semantic information to widgets
and implement mapping semantic tree to platform representations.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-12-01 17:23:54 +01:00
Elias Naur 48a96305c8 io/router: move transform state tracking from pointerCollector to Router
We're going to need transform tracking for the upcoming meta ops.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-12-01 17:23:54 +01:00
Elias Naur 303b819539 io/router: don't panic for nil op.Ops arguements to Router.Frame
Fixes gio#306

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-11-10 15:24:22 +01:00
Elias Naur 29cea1db49 io/pointer,io/router: replace AreaOp with clip.Op
Pointer hit areas and paint clip areas are separate concepts, but
similar enough to warrant merging. This change replaces pointer hit
areas with clip areas, so Gio is left with just one area concept (in
package op/clip).

The reason for separating the concepts in the original Gio release was
because of my being unsure general path/stroke hit areas would ever be
implemented, let alone efficient.

This change represents a change of mind, in the sense that it's better
to have an incomplete API than two separate area concepts.

Leave the deprecated pointer.Rect, pointer.Ellipse for temporary
backwards compatibility.

This is an API change. Most existing programs should continue to build
with this change, but may have to adjust to having all clip.Ops participate
in InputOp hit areas.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-11-03 14:12:31 +01:00
Pierre Curto 241e566053 io/router: remove unnecessary panics while routing key ops
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-24 08:31:31 +02:00
Elias Naur e4b96cb779 io/router: avoid a decode round for key ops
Like a previous change for pointer ops, process key ops during the
router decode of ops. This is a performance optimization and preparation
for processing future accessibility ops without without another decode
loop.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-22 15:17:05 +02:00
Elias Naur 60846d112b io/router: introduce pointerCollector to avoid an ops decode
The router package decodes the entire ops list thrice: once for pointer
ops, once for key ops, once for other ops. This change removes one
decode round by merging other ops and pointer ops decoding.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-21 18:16:12 +02:00
Elias Naur 391725b9d0 op: move Ops internal methods and state to internal package ops
Merge package opconsts into ops as well; it only existed to break
import cycles.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 17:21:56 +02:00
Pierre Curto 3c34a39d88 io/router: remove panics in clipboardQueue
Since the Process* methods on clipboardQueue are called while decoding
the ops, no need to recheck for the op type.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-06 09:40:27 +02:00
Inkeliz 9b4b91fec0 app, io: [wasm, android] add support for numeric/email keyboard mode
Previously, the on-screen keyboard always displays the text keyboard,
(QWERTY or equivalent).

For optimal user experience, it's possible to specify the keyboard type
using `InputHint`. The on-screen keyboard will provide shortcuts or
restrict what the user can input.

Due to some limitations (gio#116), only numeric and text keyboards are
supported on Android.

Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
2021-06-05 17:49:08 +02:00
Elias Naur 4f45d9a567 io/router: rename Router.Add to the more specific Queue
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-22 16:36:14 +01:00
Elias Naur 24f69bf4bb io/router: don't trigger redraw for handler reset events
key.InputOp and pointer.InputOp handlers are reset on first registration
through a key.FocusEvent{false} or pointer.Cancel, respectively.

However, the mere act of registering a handle shouldn't result in a
redraw. This is particularly true for misconfigured handlers where a new
tag is supplied every frame, resulting in continously redrawing.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-22 16:34:51 +01:00
Elias Naur 95953b2ae0 io/router: remove redundant field
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-22 12:10:59 +01:00
pierre 7c5bcd3db8 io/pointer: added CursorNameOp
The cursor can now be customized for a given area.

Signed-off-by: pierre <pierre.curto@gmail.com>
2020-12-09 09:38:31 +01:00
Inkeliz a76f816ae9 io/clipboard,app: add WriteOp, ReadOp
Previously, the only way to manipulate the clipboard (read or write) is
using the `app.Window`.

The new `clipboard.ReadOp` and `clipboard.WriteOp`makes possible to
read/write from the widget.

Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
2020-12-06 22:15:16 +01:00
Elias Naur d280d438c7 io/router: don't clear event queue before cancel events
There may be unrelated events in the queue, so it's not appropriate
to clear the queue just because an input Cancel event occurs.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-07 18:20:18 +02:00
Elias Naur ff71d0c518 io/router: fix typo
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-06-02 14:20:40 +02:00
Elias Naur 03db2817ac all: rename io/event.Key to Tag
Key had an unfortunate association with keyboard input.

This is an API change. The following rewrites were run to fixup
Gio code:

        $ gofmt -r 'pointer.InputOp{Key:a} -> pointer.InputOp{Tag:a}' -w .
        $ gofmt -r 'pointer.InputOp{Key:a, Grab:b} -> pointer.InputOp{Tag:a, Grab:b}' -w .
        $ gofmt -r 'key.InputOp{Key:a} -> key.InputOp{Tag:a}' -w .
        $ gofmt -r 'key.InputOp{Key:a, Focus:b} -> key.InputOp{Tag:a, Focus:b}' -w .
        $ gofmt -r 'event.Key -> event.Tag' -w .

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-05-17 19:48:12 +02:00
Elias Naur 5a3ffad00a io/router: expand Router.Add to accept multiple events
Niver API and useful for testing.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 09:08:56 +01:00
Elias Naur 34c6a2f735 io/router: expose the event router
For integrating with external window implementations (replacing
package app), access to the event router is required. Extract it
and put it into the new package router.

Router may belong in package io/event, but can't without introducing
import cycles.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-07 20:41:04 +01:00