From ba1881740080d151f0554fe964163b4711f17428 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Fri, 12 Jul 2019 14:34:24 +0200 Subject: [PATCH] ui/app/internal/input: add tracking up updates to handlerEvents In preparation for only redrawing when new events are available. Signed-off-by: Elias Naur --- ui/app/internal/input/key.go | 17 +++++---- ui/app/internal/input/pointer.go | 10 +++--- ui/app/internal/input/router.go | 62 +++++++++++++++++++++++--------- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/ui/app/internal/input/key.go b/ui/app/internal/input/key.go index 84272a8c..4a63ce06 100644 --- a/ui/app/internal/input/key.go +++ b/ui/app/internal/input/key.go @@ -35,7 +35,7 @@ func (q *keyQueue) InputState() key.TextInputState { return q.state } -func (q *keyQueue) Frame(root *ui.Ops, events handlerEvents) { +func (q *keyQueue) Frame(root *ui.Ops, events *handlerEvents) { if q.handlers == nil { q.handlers = make(map[input.Key]*keyHandler) } @@ -56,11 +56,11 @@ func (q *keyQueue) Frame(root *ui.Ops, events handlerEvents) { changed := focus != nil && focus != q.focus if focus != q.focus { if q.focus != nil { - events[q.focus] = append(events[q.focus], key.FocusEvent{Focus: false}) + events.Add(q.focus, key.FocusEvent{Focus: false}) } q.focus = focus if q.focus != nil { - events[q.focus] = append(events[q.focus], key.FocusEvent{Focus: true}) + events.Add(q.focus, key.FocusEvent{Focus: true}) } else { hide = true } @@ -77,14 +77,13 @@ func (q *keyQueue) Frame(root *ui.Ops, events handlerEvents) { } } -func (q *keyQueue) Push(e input.Event, events handlerEvents) { - if q.focus == nil { - return +func (q *keyQueue) Push(e input.Event, events *handlerEvents) { + if q.focus != nil { + events.Add(q.focus, e) } - events[q.focus] = append(events[q.focus], e) } -func (q *keyQueue) resolveFocus(events handlerEvents) (input.Key, listenerPriority, bool) { +func (q *keyQueue) resolveFocus(events *handlerEvents) (input.Key, listenerPriority, bool) { var k input.Key var pri listenerPriority var hide bool @@ -112,7 +111,7 @@ loop: h = new(keyHandler) q.handlers[op.Key] = h // Reset the handler on (each) first appearance. - events[op.Key] = []input.Event{key.FocusEvent{Focus: false}} + events.Set(op.Key, []input.Event{key.FocusEvent{Focus: false}}) } h.active = true case ops.TypeHideInput: diff --git a/ui/app/internal/input/pointer.go b/ui/app/internal/input/pointer.go index d834f20d..c5cc8a9b 100644 --- a/ui/app/internal/input/pointer.go +++ b/ui/app/internal/input/pointer.go @@ -63,7 +63,7 @@ const ( areaEllipse ) -func (q *pointerQueue) collectHandlers(r *ui.OpsReader, events handlerEvents, t ui.Transform, area, node int, pass bool) { +func (q *pointerQueue) collectHandlers(r *ui.OpsReader, events *handlerEvents, t ui.Transform, area, node int, pass bool) { for encOp, ok := r.Decode(); ok; encOp, ok = r.Decode() { switch ops.OpType(encOp.Data[0]) { case ops.TypePush: @@ -103,7 +103,7 @@ func (q *pointerQueue) collectHandlers(r *ui.OpsReader, events handlerEvents, t if !ok { h = new(pointerHandler) q.handlers[op.Key] = h - events[op.Key] = []input.Event{pointer.Event{Type: pointer.Cancel}} + events.Set(op.Key, []input.Event{pointer.Event{Type: pointer.Cancel}}) } h.active = true h.area = area @@ -160,7 +160,7 @@ func (q *pointerQueue) init() { } } -func (q *pointerQueue) Frame(root *ui.Ops, events handlerEvents) { +func (q *pointerQueue) Frame(root *ui.Ops, events *handlerEvents) { q.init() for _, h := range q.handlers { // Reset handler. @@ -189,7 +189,7 @@ func (q *pointerQueue) dropHandler(k input.Key) { } } -func (q *pointerQueue) Push(e pointer.Event, events handlerEvents) { +func (q *pointerQueue) Push(e pointer.Event, events *handlerEvents) { q.init() if e.Type == pointer.Cancel { q.pointers = q.pointers[:0] @@ -257,7 +257,7 @@ func (q *pointerQueue) Push(e pointer.Event, events handlerEvents) { } e.Hit = q.hit(h.area, e.Position) e.Position = h.transform.InvTransform(e.Position) - events[k] = append(events[k], e) + events.Add(k, e) if e.Type == pointer.Release { // Release grab when the number of grabs reaches zero. grabs := 0 diff --git a/ui/app/internal/input/router.go b/ui/app/internal/input/router.go index bc023800..ca339fc9 100644 --- a/ui/app/internal/input/router.go +++ b/ui/app/internal/input/router.go @@ -18,39 +18,67 @@ type Router struct { handlers handlerEvents } -type handlerEvents map[input.Key][]input.Event +type handlerEvents struct { + handlers map[input.Key][]input.Event + updated bool +} func (q *Router) Events(k input.Key) []input.Event { - events := q.handlers[k] - delete(q.handlers, k) - return events + return q.handlers.For(k) } func (q *Router) Frame(ops *ui.Ops) { - q.init() - for k := range q.handlers { - delete(q.handlers, k) - } - q.pqueue.Frame(ops, q.handlers) - q.kqueue.Frame(ops, q.handlers) + q.handlers.Clear() + q.pqueue.Frame(ops, &q.handlers) + q.kqueue.Frame(ops, &q.handlers) } -func (q *Router) Add(e input.Event) { - q.init() +func (q *Router) Add(e input.Event) bool { switch e := e.(type) { case pointer.Event: - q.pqueue.Push(e, q.handlers) + q.pqueue.Push(e, &q.handlers) case key.EditEvent, key.ChordEvent, key.FocusEvent: - q.kqueue.Push(e, q.handlers) + q.kqueue.Push(e, &q.handlers) } + return q.handlers.Updated() } func (q *Router) InputState() key.TextInputState { return q.kqueue.InputState() } -func (q *Router) init() { - if q.handlers == nil { - q.handlers = make(handlerEvents) +func (h *handlerEvents) init() { + if h.handlers == nil { + h.handlers = make(map[input.Key][]input.Event) + } +} + +func (h *handlerEvents) Set(k input.Key, evts []input.Event) { + h.init() + h.handlers[k] = evts + h.updated = true +} + +func (h *handlerEvents) Add(k input.Key, e input.Event) { + h.init() + h.handlers[k] = append(h.handlers[k], e) + h.updated = true +} + +func (h *handlerEvents) Updated() bool { + u := h.updated + h.updated = false + return u +} + +func (h *handlerEvents) For(k input.Key) []input.Event { + events := h.handlers[k] + delete(h.handlers, k) + return events +} + +func (h *handlerEvents) Clear() { + for k := range h.handlers { + delete(h.handlers, k) } }