mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 18:05:35 +00:00
io/pointer,io/router,gesture: add pointer.Foremost priority
Replace the pointer.Scroll special case with a new priority that indicates the foremost handler, checked in gesture.Scroll. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -225,6 +225,9 @@ func (s *Scroll) Scroll(cfg unit.Converter, q event.Queue, t time.Time, axis Axi
|
|||||||
s.dragging = false
|
s.dragging = false
|
||||||
s.grab = false
|
s.grab = false
|
||||||
case pointer.Scroll:
|
case pointer.Scroll:
|
||||||
|
if e.Priority < pointer.Foremost {
|
||||||
|
continue
|
||||||
|
}
|
||||||
switch s.axis {
|
switch s.axis {
|
||||||
case Horizontal:
|
case Horizontal:
|
||||||
s.scroll += e.Scroll.X
|
s.scroll += e.Scroll.X
|
||||||
|
|||||||
@@ -113,6 +113,9 @@ const (
|
|||||||
// Shared priority is for handlers that
|
// Shared priority is for handlers that
|
||||||
// are part of a matching set larger than 1.
|
// are part of a matching set larger than 1.
|
||||||
Shared Priority = iota
|
Shared Priority = iota
|
||||||
|
// Foremost priority is like Shared, but the
|
||||||
|
// handler is the foremost of the matching set.
|
||||||
|
Foremost
|
||||||
// Grabbed is used for matching sets of size 1.
|
// Grabbed is used for matching sets of size 1.
|
||||||
Grabbed
|
Grabbed
|
||||||
)
|
)
|
||||||
@@ -199,6 +202,8 @@ func (p Priority) String() string {
|
|||||||
switch p {
|
switch p {
|
||||||
case Shared:
|
case Shared:
|
||||||
return "Shared"
|
return "Shared"
|
||||||
|
case Foremost:
|
||||||
|
return "Foremost"
|
||||||
case Grabbed:
|
case Grabbed:
|
||||||
return "Grabbed"
|
return "Grabbed"
|
||||||
default:
|
default:
|
||||||
|
|||||||
+16
-13
@@ -262,29 +262,34 @@ func (q *pointerQueue) Push(e pointer.Event, events *handlerEvents) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *pointerQueue) deliverEvent(p *pointerInfo, events *handlerEvents, e pointer.Event) {
|
func (q *pointerQueue) deliverEvent(p *pointerInfo, events *handlerEvents, e pointer.Event) {
|
||||||
|
foremost := true
|
||||||
for _, k := range p.handlers {
|
for _, k := range p.handlers {
|
||||||
h := q.handlers[k]
|
h := q.handlers[k]
|
||||||
e := e
|
e := e
|
||||||
if p.pressed && len(p.handlers) == 1 {
|
if p.pressed && len(p.handlers) == 1 {
|
||||||
e.Priority = pointer.Grabbed
|
e.Priority = pointer.Grabbed
|
||||||
|
} else if foremost {
|
||||||
|
e.Priority = pointer.Foremost
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Position = h.transform.Invert().Transform(e.Position)
|
e.Position = h.transform.Invert().Transform(e.Position)
|
||||||
|
|
||||||
addPointerEvent(events, k, e, h.types)
|
if e.Type&h.types == e.Type {
|
||||||
|
foremost = false
|
||||||
// Only deliver scroll events to the foremost handler.
|
events.Add(k, e)
|
||||||
if e.Type == pointer.Scroll && e.Type&h.types != 0 {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, events *handlerEvents, e pointer.Event) {
|
func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, events *handlerEvents, e pointer.Event) {
|
||||||
|
foremost := true
|
||||||
for _, k := range p.handlers {
|
for _, k := range p.handlers {
|
||||||
h := q.handlers[k]
|
h := q.handlers[k]
|
||||||
e := e
|
e := e
|
||||||
if p.pressed && len(p.handlers) == 1 {
|
if p.pressed && len(p.handlers) == 1 {
|
||||||
e.Priority = pointer.Grabbed
|
e.Priority = pointer.Grabbed
|
||||||
|
} else if foremost {
|
||||||
|
e.Priority = pointer.Foremost
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hit-test to deliver Enter/Leave events. Consider non-mouse
|
// Hit-test to deliver Enter/Leave events. Consider non-mouse
|
||||||
@@ -304,18 +309,16 @@ func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, events *handlerEv
|
|||||||
case !hit && entered != -1:
|
case !hit && entered != -1:
|
||||||
p.entered = append(p.entered[:entered], p.entered[entered+1:]...)
|
p.entered = append(p.entered[:entered], p.entered[entered+1:]...)
|
||||||
e.Type = pointer.Leave
|
e.Type = pointer.Leave
|
||||||
addPointerEvent(events, k, e, h.types)
|
|
||||||
case hit && entered == -1:
|
case hit && entered == -1:
|
||||||
p.entered = append(p.entered, k)
|
p.entered = append(p.entered, k)
|
||||||
e.Type = pointer.Enter
|
e.Type = pointer.Enter
|
||||||
addPointerEvent(events, k, e, h.types)
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if e.Type&h.types == e.Type {
|
||||||
|
foremost = false
|
||||||
|
events.Add(k, e)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func addPointerEvent(events *handlerEvents, k event.Tag, e pointer.Event, types pointer.Type) {
|
|
||||||
if e.Type&types == e.Type {
|
|
||||||
events.Add(k, e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ func TestPointerTypes(t *testing.T) {
|
|||||||
assertEventSequence(t, r.Events(handler), pointer.Cancel, pointer.Press, pointer.Release)
|
assertEventSequence(t, r.Events(handler), pointer.Cancel, pointer.Press, pointer.Release)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPointerScroll(t *testing.T) {
|
func TestPointerPriority(t *testing.T) {
|
||||||
handler1 := new(int)
|
handler1 := new(int)
|
||||||
handler2 := new(int)
|
handler2 := new(int)
|
||||||
var ops op.Ops
|
var ops op.Ops
|
||||||
@@ -139,7 +139,7 @@ func TestPointerScroll(t *testing.T) {
|
|||||||
var r Router
|
var r Router
|
||||||
r.Frame(&ops)
|
r.Frame(&ops)
|
||||||
r.Add(
|
r.Add(
|
||||||
// Hit handler 2.
|
// Hit both handlers.
|
||||||
pointer.Event{
|
pointer.Event{
|
||||||
Type: pointer.Scroll,
|
Type: pointer.Scroll,
|
||||||
Position: f32.Point{
|
Position: f32.Point{
|
||||||
@@ -164,8 +164,12 @@ func TestPointerScroll(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assertEventSequence(t, r.Events(handler1), pointer.Cancel, pointer.Scroll)
|
hev1 := r.Events(handler1)
|
||||||
assertEventSequence(t, r.Events(handler2), pointer.Cancel, pointer.Scroll)
|
hev2 := r.Events(handler2)
|
||||||
|
assertEventSequence(t, hev1, pointer.Cancel, pointer.Scroll, pointer.Scroll)
|
||||||
|
assertEventSequence(t, hev2, pointer.Cancel, pointer.Scroll)
|
||||||
|
assertEventPriorities(t, hev1, pointer.Shared, pointer.Shared, pointer.Foremost)
|
||||||
|
assertEventPriorities(t, hev2, pointer.Shared, pointer.Foremost)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPointerEnterLeave(t *testing.T) {
|
func TestPointerEnterLeave(t *testing.T) {
|
||||||
@@ -463,7 +467,7 @@ func pointerTypes(events []event.Event) []pointer.Type {
|
|||||||
return types
|
return types
|
||||||
}
|
}
|
||||||
|
|
||||||
// assertEventSequence ensures that the provided actualEvents match the expected event types
|
// assertEventSequence checks that the provided events match the expected pointer event types
|
||||||
// in the provided order.
|
// in the provided order.
|
||||||
func assertEventSequence(t *testing.T, events []event.Event, expected ...pointer.Type) {
|
func assertEventSequence(t *testing.T, events []event.Event, expected ...pointer.Type) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
@@ -473,6 +477,20 @@ func assertEventSequence(t *testing.T, events []event.Event, expected ...pointer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assertEventPriorities checks that the pointer.Event priorities of events match prios.
|
||||||
|
func assertEventPriorities(t *testing.T, events []event.Event, prios ...pointer.Priority) {
|
||||||
|
t.Helper()
|
||||||
|
var got []pointer.Priority
|
||||||
|
for _, e := range events {
|
||||||
|
if e, ok := e.(pointer.Event); ok {
|
||||||
|
got = append(got, e.Priority)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, prios) {
|
||||||
|
t.Errorf("expected priorities %v, got %v", prios, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkRouterAdd(b *testing.B) {
|
func BenchmarkRouterAdd(b *testing.B) {
|
||||||
// Set this to the number of overlapping handlers that you want to
|
// Set this to the number of overlapping handlers that you want to
|
||||||
// evaluate performance for. Typical values for the example applications
|
// evaluate performance for. Typical values for the example applications
|
||||||
|
|||||||
Reference in New Issue
Block a user