262 Commits

Author SHA1 Message Date
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 a4626d9304 io/router: make the zero value collectState the reset state
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-20 11:31:00 +02:00
Pierre Curto 6b0e00b9aa io/pointer: change Type to uint
This is to allow for future new Types.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-20 10:09:58 +02:00
Pierre Curto e6ed25bb1f io/router: deduplicate pointer handlers
When the same handler is added several times
and that handler sets pointer.Grabbed, it gets lost.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-19 15:00:29 +02:00
Pierre Curto e5d8a4b8d0 io/router: reuse scratch space in pointerQueue.Frame
This removes the allocation needed to drop all handlers except one.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-18 11:47:49 +02:00
Pierre Curto 9be171190e io/router: convert pointerQueue.dropHandlers to pointerQueue.dropHandler
dropHandlers is mainly used for single tag removal except in one instance.
In that case, simply use a loop.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-18 11:47:36 +02:00
Pierre Curto ae5219e4d4 io/pointer: print all types in Type.String
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-17 14:50:28 +02:00
Elias Naur 0048f7be1d internal/ops: hide Ops methods by converting them to package functions
Ops is in the internal package ops, but external clients can reach its
method through op.Ops.Internal. Hide them by converting them to internal
package functions.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-12 14:50:15 +02:00
Elias Naur 87d050bcc7 internal/ops: remove Data, Version, Refs methods from Ops
They're only used internally.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-12 14:28:05 +02:00
Elias Naur 960f3068a1 io/pointer: re-introduce PassOp
A previous change merged PassOp with AreaOp under the assumption that
the pass mode would be set on a particular area. That assumption turns
out not to hold, so this change brings back PassOp as an independent
stack operation.

This is an API change: replace AreaOp{Pass: true} with a separate
pointer.PassOp operation.

Fixes gio#288

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-09 16:31:54 +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
Elias Naur 936c266b03 all: [API] split operation stack into per-state stacks
The op.Save and Load methods exist to support the need for
transformation, clip, pointer area state to behave as stacks. For
example, layout needs to apply an offset to its children but not
subsequent operations.

Before this change, op.Save and Load were used to save and restore the
state:

    ops := new(op.Ops)
    // Save state.
    state := op.Save(ops)
    // Apply offset.
    op.Offset(...).Add(ops)
    // Draw with offset applied.
    draw(ops)
    // Restore state.
    state.Load()

A drawback with the op.Save mechanism is that there is no direct
connection between the state change and the saving and loading of state.
This causes confusion as to when a Save/Load is needed and who is
responsible for performing them, which leads to subtle bugs and over-use
of Save/Loads.

This change gets rid of the general state stack and replaces it with
per-state stacks. There is now a stack for transformation, clip, pointer
areas, and they can only be restored by the code pushing state to them.
The example above now becomes:

    ops := new(op.Ops)
    // Push offset to the transformation stack.
    stack := op.Offset(...).Push(ops)
    // Draw with offset applied.
    draw(ops)
    // Restore state.
    stack.Pop()

For convenience, transformation also be Add'ed if the stack operation is
not required.

Simple state such as the current material no longer has a way to be
restored; it is assumed the client of a PaintOp adds their desired
material operation before it.

API change: replace op.Save/Load with explicit Push/Pop scopes for
op.TransformOps, pointer.AreaOps, clip.Ops.

To ease porting, this change retains a version of op.Save/Load that
saves and restores the transformation and clip stacks. It also retains
an Add method for clip.Op.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 17:21:56 +02:00
Elias Naur 6f80b94b4a io/pointer,io/router: [API] make pass-through a property of AreaOp
We're about to make operation scopes explicit, which would result in
both AreaOp and PassOp be scoped. However, PassOp seems to light to have
its separate stack, so this change instead makes pass-through a property
of an area. We're assuming that clients that want pass-through are also
aware of the affected hit area.

API change: replace PassOps with the AreaOp.PassThrough field.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 15:54:50 +02:00
Elias Naur cccb8d2c2b io/router: remove redundant state field
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-07 15:01:17 +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
Pierre Curto c1bd206ece io/router: removed unused field
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-06 08:21:48 +02:00
Pierre Curto bfd1e76b78 io/router: refactor pointer.Push for clearer flow
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-03 17:38:39 +02:00
Pierre Curto 5860818537 io/router: merge cancelHandlers and dropHandlers
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-10-03 17:32:00 +02:00
Elias Naur 414be0a0b3 gpu: Merge GPU.Collect and GPU.Frame
There's no meaningful reason to have them separate. The intention was to
enable rendering concurrent with other processing, but that's gaining
framerate at the expense of input latency and complicating ImageOp
semantics.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-24 08:30:52 +02:00
Elias Naur 060ae1cdf9 all: add //go:build lines
They're automatically added by Go 1.17 source formatters. This change
adds them all now.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-26 15:17:51 +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
pierre 5e1a662b94 io/pointer: support nested scrollables
Fixes #185.

Signed-off-by: pierre <pierre.curto@gmail.com>
2021-03-31 09:57:13 +02:00
Elias Naur 17ba8e28af io/router: drop the correct handlers when a pointer grab is requested
Fixes gio#208

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-27 13:18:30 +01:00
pierre 3e525a0393 io/router: move static conditions out of the loop
Signed-off-by: pierre <pierre.curto@gmail.com>
2021-03-25 11:11:30 +01:00
pierre e0262c20e3 io/key: add NameSpace, report it on Linux
Fixes gio#204.

Signed-off-by: pierre <pierre.curto@gmail.com>
2021-03-12 13:18:08 +01:00
Elias Naur ffb26b0e17 io/pointer: rename button names to reflect their meaning, not placement
For example, ButtonLeft may be the right-most button for a left-handed user.
Rename the button names to match their intended use.

This is an API change. Use the following commands to update your
projects:

    $ gofmt -r 'pointer.ButtonLeft -> pointer.ButtonPrimary' -w .
    $ gofmt -r 'pointer.ButtonRight -> pointer.ButtonSecondary' -w .
    $ gofmt -r 'pointer.ButtonMiddle -> pointer.ButtonTertiary' -w .

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-03 11:08:41 +01:00
Egon Elbre e66979a8c0 io/router: fix negative areas
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2021-02-24 17:12:36 +01:00
pierre cfb16083a2 io/router: improve areaOp methods performance
name             old time/op  new time/op  delta
AreaOp_Decode-8  10.5ns ± 2%   6.2ns ± 3%  -41.50%  (p=0.000 n=10+10)
AreaOp_Hit-8     4.44ns ± 4%  3.57ns ± 2%  -19.59%  (p=0.000 n=10+10)

Signed-off-by: pierre <pierre.curto@gmail.com>
2021-02-24 12:42:34 +01:00
pierre 60d48014d4 io/router: avoid event copy for filtered events in pointerQueue
Signed-off-by: pierre <pierre.curto@gmail.com>
2021-02-24 12:32:01 +01:00
pierre a581acf3fd io/pointer: added the grab cursor
Signed-off-by: pierre <pierre.curto@gmail.com>
2021-02-08 09:15:14 +01:00
pierre b698c8ed82 io/router: only calculate position if event is delivered in Router
Signed-off-by: pierre <pierre.curto@gmail.com>
2021-01-27 22:21:31 +01:00
pierre 1100e03c1e io/router: support cursor changes on Frame events
Add support to Router so that the cursor can be changed with CursorNameOp without any mouse movement.
Enter and Leave events are also delivered as areas change.

Signed-off-by: pierre <pierre.curto@gmail.com>
2021-01-27 22:21:27 +01:00
pierre c3346680f4 io/router: merge cursor and delivery of Enter/Leave events in Router
Cursor and Enter/Leave events should follow the same rules, specifically:
when pointerInfo.pressed is true, Enter/Leave processing ignores
pointer.Areas not hit during the pointer.Press event.

Signed-off-by: pierre <pierre.curto@gmail.com>
2021-01-27 22:21:24 +01:00
pierre b11fd6ee8e io/router: fix default cursor in Router
Do not update the cursor was reset upon receiving Cancel events. Added more tests.

Signed-off-by: pierre <pierre.curto@gmail.com>
2021-01-25 17:41:47 +01:00
Elias Naur cc63a3aeb7 io/router: don't send pointer.Cancel events to disappearing handlers
As a follow-up to gioui.org/commit/24f69bf4, this change makes it so
that merely adding a pointer.InputOp doesn't trigger redraws when
the pointer is hovered over its area.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-23 12:00:50 +01:00
Elias Naur 686d680ea3 io/key,io/pointer: forbid nil tags for InputOps
Forcing a non-nil tag ensures that all handler tags are either unique,
or intentionally equal. Additionally, a nil tag has special meaning in
FocusOps.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-22 16:38:25 +01: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 e70a16c345 io/router/key: add explicit tag to FocusOp; make last SoftKeyboardOp apply
The target of FocusOp is too subtle; be explicit instead and remove
any doubt.

Multiple SoftKeyboardOp in a single frame is rare, but if they do occur,
they should behave as if they were from separate frames: the last one
applies.

As a side-effect the key event router can be much simplified.

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
Elias Naur d6886737a5 op: change Defer to only restore transformation state
It turns out restoring all operation state from the moment Defer
is executed is too much; for example, a right-click pop-up needs
the transformation, but not the current clip.

Change Defer to only restore the transformation, and reset all
other state.

Other combinations may be needed in future; we'll deal with them then,
possibly by exposing the load state mask.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-19 20:04:30 +01:00
Elias Naur d331dd2de8 op: rename StackOp/Push/Pop to StateOp/Save/Load
The semantics were relaxed in a previous commit; this change renames
to operations accordingly.

API change. Use gofmt to adjust your code accordingly:

gofmt -r 'op.Push(a).Pop() -> op.Save(a).Load()'
gofmt -r 'op.Push(a) -> op.Save(a)'
gofmt -r 'v.Pop() -> v.Load()'
gofmt -r 'op.StackOp -> op.StateOp'

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-12 21:28:59 +01:00
Elias Naur f7902f299b op: implement StackOp in terms of general save/load of state
Push/Pop only allows saving and restoring operation state in a
stack-like manner. We're going to need restoring arbitrary state
for implementing deferred operations.

Generalize state save/restore and implement Push and Pop on top of
that.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-12 20:53:25 +01:00
pierre 578c226278 io/pointer: CursorNameOp no longer needs an InputOp with Leave and Enter events
Signed-off-by: pierre <pierre.curto@gmail.com>
2020-12-15 18:11:48 +01:00
Sebastien Binet e71bf13c9a gpu,op/clip: implement dashed stroked paths
Signed-off-by: Sebastien Binet <s@sbinet.org>
2020-12-09 11:23:13 +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
pierre 59720a8a58 router: removed unnecessary checks.
Signed-off-by: pierre <pierre.curto@gmail.com>
2020-12-06 21:58:04 +01:00
Inkeliz 828f19304b app: move system.ClipboardEvent to its own package
API change. Update your code with gofmt rule and goimports:

gofmt -r "system.ClipboardEvent -> clipboard.Event"
goimports

Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-12-05 10:20:55 +01:00
Inkeliz cd3b4561cf io/key: improve InputOp focus and blur
The existing implementation cannot remove the focus of some widget,
doesn't have an option to focus without display the on-screen keyboard
and it automatically focuses the first InputOp, aggressively.

That change aims to make possible: remove focus from any widget. Add
focus without displaying the on-screen-keyboard/soft keyboard. Don't
automatically focus any widget. Don't recover focus when the widget is
visible again.

Fixes gio#180.

Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
2020-12-03 16:46:48 +01:00