From 578c226278f37427b50692dd10f59c9e495bf367 Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 15 Dec 2020 12:45:16 +0100 Subject: [PATCH] io/pointer: CursorNameOp no longer needs an InputOp with Leave and Enter events Signed-off-by: pierre --- io/router/pointer.go | 18 +++++++------- io/router/pointer_test.go | 49 +++++++++++++++++++++++++++++++++++++++ widget/editor.go | 6 ++--- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/io/router/pointer.go b/io/router/pointer.go index bd8a9e89..ea70dc14 100644 --- a/io/router/pointer.go +++ b/io/router/pointer.go @@ -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 } } } diff --git a/io/router/pointer_test.go b/io/router/pointer_test.go index 03c78a22..e8638578 100644 --- a/io/router/pointer_test.go +++ b/io/router/pointer_test.go @@ -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) { diff --git a/widget/editor.go b/widget/editor.go index 75709679..f7bbe9a3 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -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