From 920e6dd004ea34055139202ee3e81d53ec38624d Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Tue, 29 Mar 2022 17:30:23 +0200 Subject: [PATCH] io/router,app: move Tab-to-focus conversion to app.Window This is a refactor to make it easier to add higher level logic to focus moves. A follow-up will add automatic scrolling to bring focused widgets into view. Signed-off-by: Elias Naur --- app/window.go | 19 +++++++++++++++---- io/router/key.go | 42 ++++++++++++++++++++---------------------- io/router/key_test.go | 26 +++++--------------------- 3 files changed, 40 insertions(+), 47 deletions(-) diff --git a/app/window.go b/app/window.go index 4702958b..af2349af 100644 --- a/app/window.go +++ b/app/window.go @@ -498,9 +498,13 @@ func (c *callbacks) SetEditorSnippet(r key.Range) { } func (c *callbacks) MoveFocus(dir router.FocusDirection) { - c.w.queue.q.MoveFocus(dir) - c.w.setNextFrame(time.Time{}) - c.w.updateAnimation(c.d) + c.w.moveFocus(dir, c.d) +} + +func (w *Window) moveFocus(dir router.FocusDirection, d driver) { + w.queue.q.MoveFocus(dir) + w.setNextFrame(time.Time{}) + w.updateAnimation(d) } func (c *callbacks) ClickFocus() { @@ -793,7 +797,14 @@ func (w *Window) processEvent(d driver, e event.Event) { e2.Config.Size = e2.Config.Size.Sub(w.decorations.size) w.out <- e2 case event.Event: - if w.queue.q.Queue(e2) { + // Convert tab or shift+tab presses to focus moves. + if e, ok := e.(key.Event); ok && e.State == key.Press && e.Name == key.NameTab && e.Modifiers&^key.ModShift == 0 { + dir := router.FocusForward + if e.Modifiers.Contain(key.ModShift) { + dir = router.FocusBackward + } + w.moveFocus(dir, d) + } else if w.queue.q.Queue(e2) { w.setNextFrame(time.Time{}) w.updateAnimation(d) } diff --git a/io/router/key.go b/io/router/key.go index 8266c1c1..8482c5b0 100644 --- a/io/router/key.go +++ b/io/router/key.go @@ -70,6 +70,8 @@ const ( FocusLeft FocusUp FocusDown + FocusForward + FocusBackward ) // InputState returns the last text input state as @@ -173,6 +175,24 @@ func (q *keyQueue) MoveFocus(dir FocusDirection, events *handlerEvents) { } focus := q.dirOrder[order] switch dir { + case FocusForward, FocusBackward: + if len(q.order) == 0 { + break + } + order := 0 + if dir == FocusBackward { + order = -1 + } + if q.focus != nil { + order = q.handlers[q.focus].order + if dir == FocusForward { + order++ + } else { + order-- + } + } + order = (order + len(q.order)) % len(q.order) + q.setFocus(q.order[order], events) case FocusRight, FocusLeft: next := order if q.focus != nil { @@ -226,28 +246,6 @@ func (q *keyQueue) MoveFocus(dir FocusDirection, events *handlerEvents) { } func (q *keyQueue) Push(e event.Event, events *handlerEvents) { - // Convert tab or shift+tab presses to focus moves. - if e, ok := e.(key.Event); ok && e.Name == key.NameTab && e.Modifiers&^key.ModShift == 0 { - if e.State == key.Release || len(q.order) == 0 { - return - } - forward := !e.Modifiers.Contain(key.ModShift) - order := 0 - if !forward { - order = -1 - } - if q.focus != nil { - order = q.handlers[q.focus].order - if forward { - order++ - } else { - order-- - } - } - order = (order + len(q.order)) % len(q.order) - q.setFocus(q.order[order], events) - return - } if q.focus != nil { events.Add(q.focus, e) } diff --git a/io/router/key_test.go b/io/router/key_test.go index 41183037..fd048d76 100644 --- a/io/router/key_test.go +++ b/io/router/key_test.go @@ -227,27 +227,6 @@ func TestNoOps(t *testing.T) { r.Frame(nil) } -func TestTabFocus(t *testing.T) { - handlers := make([]int, 3) - ops := new(op.Ops) - r := new(Router) - - for i := range handlers { - key.InputOp{Tag: &handlers[i]}.Add(ops) - } - r.Frame(ops) - - tab := func(mod key.Modifiers) { - r.Queue( - key.Event{Name: key.NameTab, State: key.Press, Modifiers: mod}, - key.Event{Name: key.NameTab, State: key.Release, Modifiers: mod}, - ) - } - tab(0) - tab(key.ModShift) - assertFocus(t, r, &handlers[2]) -} - func TestDirectionalFocus(t *testing.T) { ops := new(op.Ops) r := new(Router) @@ -281,6 +260,11 @@ func TestDirectionalFocus(t *testing.T) { assertFocus(t, r, &handlers[3]) r.MoveFocus(FocusUp) assertFocus(t, r, &handlers[0]) + + r.MoveFocus(FocusForward) + assertFocus(t, r, &handlers[1]) + r.MoveFocus(FocusBackward) + assertFocus(t, r, &handlers[0]) } func assertKeyEvent(t *testing.T, events []event.Event, expected bool, expectedInputs ...event.Event) {