diff --git a/gesture/gesture.go b/gesture/gesture.go index 890e3e4c..aa3585b5 100644 --- a/gesture/gesture.go +++ b/gesture/gesture.go @@ -27,6 +27,46 @@ import ( // The duration is somewhat arbitrary. const doubleClickDuration = 200 * time.Millisecond +// Hover detects the hover gesture for a pointer area. +type Hover struct { + // entered tracks whether the pointer is inside the gesture. + entered bool + // pid is the pointer.ID. + pid pointer.ID +} + +// Add the gesture to detect hovering over the current pointer area. +func (h *Hover) Add(ops *op.Ops) { + pointer.InputOp{ + Tag: h, + Types: pointer.Enter | pointer.Leave, + }.Add(ops) +} + +// Hovered returns whether a pointer is inside the area. +func (h *Hover) Hovered(q event.Queue) bool { + for _, ev := range q.Events(h) { + e, ok := ev.(pointer.Event) + if !ok { + continue + } + switch e.Type { + case pointer.Leave: + if h.entered && h.pid == e.PointerID { + h.entered = false + } + case pointer.Enter: + if !h.entered { + h.pid = e.PointerID + } + if h.pid == e.PointerID { + h.entered = true + } + } + } + return h.entered +} + // Click detects click gestures in the form // of ClickEvents. type Click struct { diff --git a/gesture/gesture_test.go b/gesture/gesture_test.go index 3c9f0383..f9fd3365 100644 --- a/gesture/gesture_test.go +++ b/gesture/gesture_test.go @@ -1,15 +1,42 @@ package gesture import ( + "image" "testing" "time" + "gioui.org/f32" "gioui.org/io/event" "gioui.org/io/pointer" "gioui.org/io/router" "gioui.org/op" ) +func TestHover(t *testing.T) { + ops := new(op.Ops) + var h Hover + rect := image.Rect(20, 20, 40, 40) + stack := pointer.Rect(rect).Push(ops) + h.Add(ops) + stack.Pop() + r := new(router.Router) + r.Frame(ops) + + r.Queue( + pointer.Event{Type: pointer.Move, Position: f32.Pt(30, 30)}, + ) + if !h.Hovered(r) { + t.Fatal("expected hovered") + } + + r.Queue( + pointer.Event{Type: pointer.Move, Position: f32.Pt(50, 50)}, + ) + if h.Hovered(r) { + t.Fatal("expected not hovered") + } +} + func TestMouseClicks(t *testing.T) { for _, tc := range []struct { label string