diff --git a/io/input/pointer.go b/io/input/pointer.go index 7ba9aa36..cc68db4d 100644 --- a/io/input/pointer.go +++ b/io/input/pointer.go @@ -760,6 +760,8 @@ func (q *pointerQueue) Push(handlers map[event.Tag]*handler, state pointerState, if p.pressed { p, evts = q.deliverDragEvent(handlers, p, evts) } + case pointer.Leave: + p, evts, state.cursor, _ = q.deliverEnterLeaveEvents(handlers, state.cursor, p, evts, e) case pointer.Release: evts = q.deliverEvent(handlers, p, evts, e) p.pressed = false @@ -823,7 +825,7 @@ func (q *pointerQueue) deliverEvent(handlers map[event.Tag]*handler, p pointerIn func (q *pointerQueue) deliverEnterLeaveEvents(handlers map[event.Tag]*handler, cursor pointer.Cursor, p pointerInfo, evts []taggedEvent, e pointer.Event) (pointerInfo, []taggedEvent, pointer.Cursor, bool) { changed := false var hits []event.Tag - if e.Source != pointer.Mouse && !p.pressed && e.Kind != pointer.Press { + if e.Kind == pointer.Leave || e.Source != pointer.Mouse && !p.pressed && e.Kind != pointer.Press { // Consider non-mouse pointers leaving when they're released. } else { var transSrc *pointerFilter diff --git a/io/input/pointer_test.go b/io/input/pointer_test.go index a5e3b4a9..de2ee0bf 100644 --- a/io/input/pointer_test.go +++ b/io/input/pointer_test.go @@ -255,6 +255,45 @@ func TestPointerMove(t *testing.T) { assertEventPointerTypeSequence(t, events(&r, -1, filter(handler2)), pointer.Enter, pointer.Move, pointer.Leave, pointer.Cancel) } +func TestPointerLeave(t *testing.T) { + handler := new(int) + var ops op.Ops + + filter := pointer.Filter{ + Target: handler, + Kinds: pointer.Move | pointer.Enter | pointer.Leave | pointer.Cancel, + } + defer clip.Rect(image.Rect(0, 0, 100, 100)).Push(&ops).Pop() + event.Op(&ops, handler) + + var r Router + events(&r, -1, filter) + r.Frame(&ops) + r.Queue( + pointer.Event{ + Kind: pointer.Move, + Source: pointer.Mouse, + PointerID: 1, + Position: f32.Pt(50, 50), + }, + pointer.Event{ + Kind: pointer.Leave, + Source: pointer.Mouse, + PointerID: 1, + Position: f32.Pt(50, 50), + }, + ) + assertEventPointerTypeSequence(t, events(&r, -1, filter), pointer.Enter, pointer.Move, pointer.Leave) + + r.Queue(pointer.Event{ + Kind: pointer.Move, + Source: pointer.Mouse, + PointerID: 1, + Position: f32.Pt(50, 50), + }) + assertEventPointerTypeSequence(t, events(&r, -1, filter), pointer.Enter, pointer.Move) +} + func TestPointerTypes(t *testing.T) { handler := new(int) var ops op.Ops