From 929e4dc1200325bae66986f27873e1e554f04503 Mon Sep 17 00:00:00 2001 From: Pierre Curto Date: Fri, 10 Dec 2021 10:44:26 +0100 Subject: [PATCH] io/router: deliver enter/leave events to transfer participants When a drag and drop gesture is ongoing, let the potential target handlers receive enter/leave events so that they can react to them (e.g. highlight themselves when the dragged item is over them). Fixes #321. Signed-off-by: Pierre Curto --- io/router/pointer.go | 15 +++++++++++++-- io/router/pointer_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/io/router/pointer.go b/io/router/pointer.go index 2ecfac43..86ba96f6 100644 --- a/io/router/pointer.go +++ b/io/router/pointer.go @@ -674,9 +674,20 @@ func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, events *handlerEv } else { hits = q.opHit(e.Position) if p.pressed { - // Filter out non-participating handlers. + // Filter out non-participating handlers, + // except potential transfer targets when a transfer has been initiated. + var transferSource *pointerHandler + if p.dataSource != nil { + transferSource = q.handlers[p.dataSource] + } for i := len(hits) - 1; i >= 0; i-- { - if _, found := searchTag(p.handlers, hits[i]); !found { + tag := hits[i] + if transferSource != nil { + if _, ok := firstMimeMatch(transferSource, q.handlers[tag]); ok { + continue + } + } + if _, found := searchTag(p.handlers, tag); !found { hits = append(hits[:i], hits[i+1:]...) } } diff --git a/io/router/pointer_test.go b/io/router/pointer_test.go index 695a80c6..394fb583 100644 --- a/io/router/pointer_test.go +++ b/io/router/pointer_test.go @@ -10,6 +10,7 @@ import ( "testing" "gioui.org/f32" + "gioui.org/gesture" "gioui.org/io/event" "gioui.org/io/key" "gioui.org/io/pointer" @@ -998,6 +999,43 @@ func TestTransfer(t *testing.T) { t.Error("offer was not closed") } }) + + t.Run("valid target enter/leave events", func(t *testing.T) { + ops := new(op.Ops) + src, _ := setup(ops, "file", "file") + var hover gesture.Hover + stack := clip.Rect(tgtArea).Push(ops) + hover.Add(ops) + stack.Pop() + var r Router + r.Frame(ops) + // Drag and drop. + r.Queue( + pointer.Event{ + Position: f32.Pt(10, 10), + Type: pointer.Press, + }, + pointer.Event{ + Position: f32.Pt(10, 10), + Type: pointer.Move, + }, + pointer.Event{ + Position: f32.Pt(40, 10), + Type: pointer.Release, + }, + ) + assertEventPointerTypeSequence(t, r.Events(&hover), pointer.Cancel, pointer.Enter) + + // Offer valid type and data. + ofr := &offer{data: "hello"} + transfer.OfferOp{ + Tag: src, + Type: "file", + Data: ofr, + }.Add(ops) + r.Frame(ops) + assertEventPointerTypeSequence(t, r.Events(&hover), pointer.Leave) + }) } // offer satisfies io.ReadCloser for use in data transfers.