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{