From 3db11cbaad4bdda760bc6c822fb9dcb2fc43661f Mon Sep 17 00:00:00 2001 From: Pierre Curto Date: Wed, 15 Dec 2021 19:09:36 +0100 Subject: [PATCH] io/router: make transfer targets hovering easier to detect In commit 929e4dc12, the rules to send pointer.{Enter,Leave} events were relaxed. Unfortunately, to be able to make use of them was not straight forward as it required the transfer target op to use the same handle as the hover one. This patch eases this by allowing any handle for the target as well as not requiring the hover op to be defined on the same clip op as the target (then requiring a PassOp though), making it much easier to use. Also added a test for pointer.Enter events not being generated if the target type does not match the source one. Signed-off-by: Pierre Curto --- io/router/pointer.go | 18 +++++------ io/router/pointer_test.go | 63 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/io/router/pointer.go b/io/router/pointer.go index 86ba96f6..2361789d 100644 --- a/io/router/pointer.go +++ b/io/router/pointer.go @@ -676,18 +676,18 @@ func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, events *handlerEv if p.pressed { // Filter out non-participating handlers, // except potential transfer targets when a transfer has been initiated. - var transferSource *pointerHandler + var hitsHaveTarget bool if p.dataSource != nil { - transferSource = q.handlers[p.dataSource] - } - for i := len(hits) - 1; i >= 0; i-- { - tag := hits[i] - if transferSource != nil { - if _, ok := firstMimeMatch(transferSource, q.handlers[tag]); ok { - continue + transferSource := q.handlers[p.dataSource] + for _, hit := range hits { + if _, ok := firstMimeMatch(transferSource, q.handlers[hit]); ok { + hitsHaveTarget = true + break } } - if _, found := searchTag(p.handlers, tag); !found { + } + for i := len(hits) - 1; i >= 0; i-- { + if _, found := searchTag(p.handlers, hits[i]); !found && !hitsHaveTarget { hits = append(hits[:i], hits[i+1:]...) } } diff --git a/io/router/pointer_test.go b/io/router/pointer_test.go index 394fb583..ba612b5c 100644 --- a/io/router/pointer_test.go +++ b/io/router/pointer_test.go @@ -1004,12 +1004,15 @@ func TestTransfer(t *testing.T) { ops := new(op.Ops) src, _ := setup(ops, "file", "file") var hover gesture.Hover + pass := pointer.PassOp{}.Push(ops) stack := clip.Rect(tgtArea).Push(ops) hover.Add(ops) stack.Pop() + pass.Pop() + var r Router r.Frame(ops) - // Drag and drop. + // Drag. r.Queue( pointer.Event{ Position: f32.Pt(10, 10), @@ -1021,11 +1024,67 @@ func TestTransfer(t *testing.T) { }, pointer.Event{ Position: f32.Pt(40, 10), - Type: pointer.Release, + Type: pointer.Move, }, ) assertEventPointerTypeSequence(t, r.Events(&hover), pointer.Cancel, pointer.Enter) + // Drop. + r.Queue( + pointer.Event{ + Position: f32.Pt(40, 10), + Type: pointer.Release, + }, + ) + + // 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) + }) + + t.Run("invalid target NO enter/leave events", func(t *testing.T) { + ops := new(op.Ops) + src, _ := setup(ops, "file", "nofile") + var hover gesture.Hover + pass := pointer.PassOp{}.Push(ops) + stack := clip.Rect(tgtArea).Push(ops) + hover.Add(ops) + stack.Pop() + pass.Pop() + + var r Router + r.Frame(ops) + // Drag. + 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.Move, + }, + ) + assertEventPointerTypeSequence(t, r.Events(&hover), pointer.Cancel) + + // Drop. + r.Queue( + pointer.Event{ + Position: f32.Pt(40, 10), + Type: pointer.Release, + }, + ) + // Offer valid type and data. ofr := &offer{data: "hello"} transfer.OfferOp{