diff --git a/app/window.go b/app/window.go index dac0b9e6..ae0427fc 100644 --- a/app/window.go +++ b/app/window.go @@ -937,6 +937,11 @@ func (w *Window) processEvent(d driver, e event.Event) bool { handled = false } } + // As a sepcial case, the top-most input handler receives all unhandled + // events. + if e, ok := e.(key.Event); ok && !handled { + handled = w.queue.q.QueueTopmost(e) + } w.updateCursor(d) return handled } diff --git a/io/key/key.go b/io/key/key.go index af31e3e6..4149c883 100644 --- a/io/key/key.go +++ b/io/key/key.go @@ -30,6 +30,8 @@ type InputOp struct { Hint InputHint // Keys is the set of keys Tag can handle. That is, Tag will only // receive an Event if its key and modifiers are accepted by Keys.Contains. + // As a special case, the topmost (first added) InputOp handler receives all + // unhandled events. Keys Set } diff --git a/io/router/router.go b/io/router/router.go index 1feab04a..e3b3be8d 100644 --- a/io/router/router.go +++ b/io/router/router.go @@ -134,7 +134,26 @@ func (q *Router) Frame(frame *op.Ops) { } } -// Queue an event and report whether at least one handler had an event queued. +// Queue key events to the topmost handler. +func (q *Router) QueueTopmost(events ...key.Event) bool { + var topmost event.Tag + pq := &q.pointer.queue + for _, h := range pq.hitTree { + if h.ktag != nil { + topmost = h.ktag + break + } + } + if topmost == nil { + return false + } + for _, e := range events { + q.handlers.Add(topmost, e) + } + return q.handlers.HadEvents() +} + +// Queue events and report whether at least one handler had an event queued. func (q *Router) Queue(events ...event.Event) bool { for _, e := range events { switch e := e.(type) {