diff --git a/gesture/gesture.go b/gesture/gesture.go index 5d9a1554..8167f7d6 100644 --- a/gesture/gesture.go +++ b/gesture/gesture.go @@ -173,9 +173,8 @@ func (c *Click) Pressed() bool { return c.pressed } -// Update state and return the click events. -func (c *Click) Update(q input.Source) []ClickEvent { - var events []ClickEvent +// Update state and return the next click events, if any. +func (c *Click) Update(q input.Source) (ClickEvent, bool) { for { evt, ok := q.Event(c, pointer.Filter{Kinds: pointer.Press | pointer.Release | pointer.Enter | pointer.Leave}) if !ok { @@ -192,9 +191,15 @@ func (c *Click) Update(q input.Source) []ClickEvent { } c.pressed = false if !c.entered || c.hovered { - events = append(events, ClickEvent{Kind: KindClick, Position: e.Position.Round(), Source: e.Source, Modifiers: e.Modifiers, NumClicks: c.clicks}) + return ClickEvent{ + Kind: KindClick, + Position: e.Position.Round(), + Source: e.Source, + Modifiers: e.Modifiers, + NumClicks: c.clicks, + }, true } else { - events = append(events, ClickEvent{Kind: KindCancel}) + return ClickEvent{Kind: KindCancel}, true } case pointer.Cancel: wasPressed := c.pressed @@ -202,7 +207,7 @@ func (c *Click) Update(q input.Source) []ClickEvent { c.hovered = false c.entered = false if wasPressed { - events = append(events, ClickEvent{Kind: KindCancel}) + return ClickEvent{Kind: KindCancel}, true } case pointer.Press: if c.pressed { @@ -224,7 +229,7 @@ func (c *Click) Update(q input.Source) []ClickEvent { c.clicks = 1 } c.clickedAt = e.Time - events = append(events, ClickEvent{Kind: KindPress, Position: e.Position.Round(), Source: e.Source, Modifiers: e.Modifiers, NumClicks: c.clicks}) + return ClickEvent{Kind: KindPress, Position: e.Position.Round(), Source: e.Source, Modifiers: e.Modifiers, NumClicks: c.clicks}, true case pointer.Leave: if !c.pressed { c.pid = e.PointerID @@ -242,7 +247,7 @@ func (c *Click) Update(q input.Source) []ClickEvent { } } } - return events + return ClickEvent{}, false } func (ClickEvent) ImplementsEvent() {} @@ -364,9 +369,8 @@ func (d *Drag) Add(ops *op.Ops) { event.InputOp(ops, d) } -// Update state and return the drag events. -func (d *Drag) Update(cfg unit.Metric, q input.Source, axis Axis) []pointer.Event { - var events []pointer.Event +// Update state and return the next drag event, if any. +func (d *Drag) Update(cfg unit.Metric, q input.Source, axis Axis) (pointer.Event, bool) { for { ev, ok := q.Event(d, pointer.Filter{Kinds: pointer.Press | pointer.Drag | pointer.Release}) if !ok { @@ -416,10 +420,10 @@ func (d *Drag) Update(cfg unit.Metric, q input.Source, axis Axis) []pointer.Even d.dragging = false } - events = append(events, e) + return e, true } - return events + return pointer.Event{}, false } // Dragging reports whether it is currently in use. diff --git a/gesture/gesture_test.go b/gesture/gesture_test.go index a68dad3c..af30ffda 100644 --- a/gesture/gesture_test.go +++ b/gesture/gesture_test.go @@ -77,8 +77,16 @@ func TestMouseClicks(t *testing.T) { r.Frame(&ops) r.Queue(tc.events...) - events := click.Update(r.Source()) - clicks := filterMouseClicks(events) + var clicks []ClickEvent + for { + ev, ok := click.Update(r.Source()) + if !ok { + break + } + if ev.Kind == KindClick { + clicks = append(clicks, ev) + } + } if got, want := len(clicks), len(tc.clicks); got != want { t.Fatalf("got %d mouse clicks, expected %d", got, want) } @@ -108,13 +116,3 @@ func mouseClickEvents(times ...time.Duration) []event.Event { } return events } - -func filterMouseClicks(events []ClickEvent) []ClickEvent { - var clicks []ClickEvent - for _, ev := range events { - if ev.Kind == KindClick { - clicks = append(clicks, ev) - } - } - return clicks -} diff --git a/widget/button.go b/widget/button.go index 28e43ad8..4888166d 100644 --- a/widget/button.go +++ b/widget/button.go @@ -116,7 +116,11 @@ func (b *Clickable) Update(gtx layout.Context) (Click, bool) { NumClicks: c, }, true } - for _, e := range b.click.Update(gtx.Source) { + for { + e, ok := b.click.Update(gtx.Source) + if !ok { + break + } switch e.Kind { case gesture.KindClick: if l := len(b.history); l > 0 { diff --git a/widget/dnd.go b/widget/dnd.go index 4d62f2fa..afc2dda2 100644 --- a/widget/dnd.go +++ b/widget/dnd.go @@ -53,7 +53,11 @@ func (d *Draggable) Dragging() bool { // requested to offer data, if any func (d *Draggable) Update(gtx layout.Context) (mime string, requested bool) { pos := d.pos - for _, ev := range d.drag.Update(gtx.Metric, gtx.Source, gesture.Both) { + for { + ev, ok := d.drag.Update(gtx.Metric, gtx.Source, gesture.Both) + if !ok { + break + } switch ev.Kind { case pointer.Press: d.click = ev.Position diff --git a/widget/editor.go b/widget/editor.go index ed5f9e16..79408879 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -316,10 +316,18 @@ func (e *Editor) processPointer(gtx layout.Context) { func (e *Editor) clickDragEvents(gtx layout.Context) []event.Event { var combinedEvents []event.Event - for _, evt := range e.clicker.Update(gtx.Source) { + for { + evt, ok := e.clicker.Update(gtx.Source) + if !ok { + break + } combinedEvents = append(combinedEvents, evt) } - for _, evt := range e.dragger.Update(gtx.Metric, gtx.Source, gesture.Both) { + for { + evt, ok := e.dragger.Update(gtx.Metric, gtx.Source, gesture.Both) + if !ok { + break + } combinedEvents = append(combinedEvents, evt) } return combinedEvents diff --git a/widget/enum.go b/widget/enum.go index 545a18a2..2f208381 100644 --- a/widget/enum.go +++ b/widget/enum.go @@ -47,7 +47,11 @@ func (e *Enum) Update(gtx layout.Context) bool { e.hovering = false changed := false for _, state := range e.keys { - for _, ev := range state.click.Update(gtx.Source) { + for { + ev, ok := state.click.Update(gtx.Source) + if !ok { + break + } switch ev.Kind { case gesture.KindPress: if ev.Source == pointer.Mouse { diff --git a/widget/float.go b/widget/float.go index d0bb5f8e..558e9f1f 100644 --- a/widget/float.go +++ b/widget/float.go @@ -48,7 +48,11 @@ func (f *Float) Layout(gtx layout.Context, axis layout.Axis, pointerMargin unit. // The range of f is set by the minimum constraints main axis value. func (f *Float) Update(gtx layout.Context) bool { changed := false - for _, e := range f.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(f.axis)) { + for { + e, ok := f.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(f.axis)) + if !ok { + break + } if f.length > 0 && (e.Kind == pointer.Press || e.Kind == pointer.Drag) { pos := e.Position.X if f.axis == layout.Vertical { diff --git a/widget/list.go b/widget/list.go index b9de5ee6..d5b4b82f 100644 --- a/widget/list.go +++ b/widget/list.go @@ -61,7 +61,11 @@ func (s *Scrollbar) Update(gtx layout.Context, axis layout.Axis, viewportStart, } // Jump to a click in the track. - for _, event := range s.track.Update(gtx.Source) { + for { + event, ok := s.track.Update(gtx.Source) + if !ok { + break + } if event.Kind != gesture.KindClick || event.Modifiers != key.Modifiers(0) || event.NumClicks > 1 { @@ -80,7 +84,11 @@ func (s *Scrollbar) Update(gtx layout.Context, axis layout.Axis, viewportStart, } // Offset to account for any drags. - for _, event := range s.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(axis)) { + for { + event, ok := s.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(axis)) + if !ok { + break + } switch event.Kind { case pointer.Drag: case pointer.Release, pointer.Cancel: @@ -136,7 +144,11 @@ func (s *Scrollbar) Update(gtx layout.Context, axis layout.Axis, viewportStart, // Process events from the indicator so that hover is // detected properly. - _ = s.indicator.Update(gtx.Source) + for { + if _, ok := s.indicator.Update(gtx.Source); !ok { + break + } + } } // AddTrack configures the track click listener for the scrollbar to use diff --git a/widget/selectable.go b/widget/selectable.go index f6956578..4486cf10 100644 --- a/widget/selectable.go +++ b/widget/selectable.go @@ -283,10 +283,18 @@ func (e *Selectable) processPointer(gtx layout.Context) { func (e *Selectable) clickDragEvents(gtx layout.Context) []event.Event { var combinedEvents []event.Event - for _, evt := range e.clicker.Update(gtx.Source) { + for { + evt, ok := e.clicker.Update(gtx.Source) + if !ok { + break + } combinedEvents = append(combinedEvents, evt) } - for _, evt := range e.dragger.Update(gtx.Metric, gtx.Source, gesture.Both) { + for { + evt, ok := e.dragger.Update(gtx.Metric, gtx.Source, gesture.Both) + if !ok { + break + } combinedEvents = append(combinedEvents, evt) } return combinedEvents