~eliasnaur/gio

578c226278f37427b50692dd10f59c9e495bf367 — pierre 7 months ago 36b9019
io/pointer: CursorNameOp no longer needs an InputOp with Leave and Enter events

Signed-off-by: pierre <pierre.curto@gmail.com>
3 files changed, 60 insertions(+), 13 deletions(-)

M io/router/pointer.go
M io/router/pointer_test.go
M widget/editor.go
M io/router/pointer.go => io/router/pointer.go +9 -9
@@ 177,6 177,7 @@ func (q *pointerQueue) init() {
	if q.handlers == nil {
		q.handlers = make(map[event.Tag]*pointerHandler)
	}
	q.cursor = pointer.CursorDefault
}

func (q *pointerQueue) Frame(root *op.Ops, events *handlerEvents) {


@@ 289,6 290,11 @@ func (q *pointerQueue) Push(e pointer.Event, events *handlerEvents) {
		// No longer need to track pointer.
		q.pointers = append(q.pointers[:pidx], q.pointers[pidx+1:]...)
	}

	for _, k := range p.entered {
		h := q.handlers[k]
		q.hitCursor(h.area)
	}
}

func (q *pointerQueue) deliverEvent(p *pointerInfo, events *handlerEvents, e pointer.Event) {


@@ 327,7 333,6 @@ func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, hits []event.Tag,

		if e.Type&h.types == e.Type {
			events.Add(k, e)
			q.cursor = pointer.CursorDefault
		}
	}
	// Deliver Enter events.


@@ 341,7 346,6 @@ func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, hits []event.Tag,

		if e.Type&h.types == e.Type {
			events.Add(k, e)
			q.hitCursor(h.area)
		}
	}
	p.entered = append(p.entered[:0], hits...)


@@ 349,13 353,9 @@ func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, hits []event.Tag,

func (q *pointerQueue) hitCursor(want int) {
	for _, c := range q.cursors {
		idx := c.area
		for idx != -1 {
			if idx == want {
				q.cursor = c.name
				return
			}
			idx = q.areas[idx].next
		if c.area == want {
			q.cursor = c.name
			return
		}
	}
}

M io/router/pointer_test.go => io/router/pointer_test.go +49 -0
@@ 11,6 11,7 @@ import (
	"gioui.org/f32"
	"gioui.org/io/event"
	"gioui.org/io/pointer"
	"gioui.org/layout"
	"gioui.org/op"
)



@@ 416,6 417,54 @@ func TestMultitouch(t *testing.T) {
	assertEventSequence(t, r.Events(h2), pointer.Cancel, pointer.Enter, pointer.Press, pointer.Release)
}

func TestCursorNameOp(t *testing.T) {
	for _, tc := range []struct {
		label string
		pt    image.Point
		want  pointer.CursorName
	}{
		{label: "inside", pt: image.Pt(50, 50), want: pointer.CursorPointer},
		{label: "outside", pt: image.Pt(200, 200), want: pointer.CursorDefault},
	} {
		t.Run(tc.label, func(t *testing.T) {
			ops := new(op.Ops)
			var r Router
			var h int
			widget := func() {
				// This is the area where the cursor is changed to CursorPointer.
				pointer.Rect(image.Rectangle{Max: image.Pt(100, 100)}).Add(ops)
				// The cursor is checked and changed upon cursor movement.
				pointer.InputOp{
					Tag:   &h,
					Types: pointer.Move,
				}.Add(ops)
				pointer.CursorNameOp{Name: pointer.CursorPointer}.Add(ops)
			}
			// Register the handlers.
			widget()
			// No cursor change as the mouse has not moved yet.
			if got, want := r.Cursor(), pointer.CursorDefault; got != want {
				t.Errorf("got %q; want %q", got, want)
			}
			// Add a mouse move event.
			r.Frame(ops)
			r.Add(
				pointer.Event{
					Source:   pointer.Mouse,
					Type:     pointer.Move,
					Position: layout.FPt(tc.pt),
				},
			)
			// Make the widget process the new event.
			widget()
			// The cursor should now have been changed if the mouse moved over the declared area.
			if got, want := r.Cursor(), tc.want; got != want {
				t.Errorf("got %q; want %q", got, want)
			}
		})
	}
}

// addPointerHandler adds a pointer.InputOp for the tag in a
// rectangular area.
func addPointerHandler(ops *op.Ops, tag event.Tag, area image.Rectangle) {

M widget/editor.go => widget/editor.go +2 -4
@@ 379,10 379,7 @@ func (e *Editor) Layout(gtx layout.Context, sh text.Shaper, font text.Font, size
	}
	e.makeValid()

	dims := e.layout(gtx)
	pointer.Rect(image.Rectangle{Max: dims.Size}).Add(gtx.Ops)
	pointer.CursorNameOp{Name: pointer.CursorText}.Add(gtx.Ops)
	return dims
	return e.layout(gtx)
}

func (e *Editor) layout(gtx layout.Context) layout.Dimensions {


@@ 430,6 427,7 @@ func (e *Editor) layout(gtx layout.Context) layout.Dimensions {
	r.Max.X += pointerPadding
	r.Max.X += pointerPadding
	pointer.Rect(r).Add(gtx.Ops)
	pointer.CursorNameOp{Name: pointer.CursorText}.Add(gtx.Ops)
	e.scroller.Add(gtx.Ops)
	e.clicker.Add(gtx.Ops)
	e.caret.on = false