From c947811e9f7a3421212287cbe9fce125aa059467 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Mon, 12 Sep 2022 16:09:19 -0500 Subject: [PATCH] ui: process tcell events in a separate go routine from rendering The UI runs off a 16 ms ticker. If no render is required, and no event is seen, aerc waits 16 ms before checking for new events or render requests. This severely limits handling of events from tcell, and is particularly noticeable on pasting of large quantities of text. Process tcell events in a separate go routine from the render loop. Signed-off-by: Tim Culverhouse Acked-by: Moritz Poldrack Acked-by: Robin Jarry --- aerc.go | 1 + lib/ui/ui.go | 33 ++++++++++++++++----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/aerc.go b/aerc.go index 203a232..37d9509 100644 --- a/aerc.go +++ b/aerc.go @@ -241,6 +241,7 @@ func main() { setWindowTitle() } + go ui.Run() for !ui.ShouldExit() { for aerc.Tick() { // Continue updating our internal state diff --git a/lib/ui/ui.go b/lib/ui/ui.go index 596000a..7cff575 100644 --- a/lib/ui/ui.go +++ b/lib/ui/ui.go @@ -85,23 +85,6 @@ func (state *UI) Close() { func (state *UI) Tick() bool { more := false - select { - case event := <-state.tcEvents: - if event, ok := event.(*tcell.EventResize); ok { - state.screen.Clear() - width, height := event.Size() - state.ctx = NewContext(width, height, state.screen, state.onPopover) - state.Content.Invalidate() - } - // if we have a popover, and it can handle the event, it does so - if state.popover == nil || !state.popover.Event(event) { - // otherwise, we send the event to the main content - state.Content.Event(event) - } - more = true - default: - } - wasInvalid := atomic.SwapInt32(&state.invalid, 0) if wasInvalid != 0 { if state.popover != nil { @@ -126,3 +109,19 @@ func (state *UI) Tick() bool { func (state *UI) EnableMouse() { state.screen.EnableMouse() } + +func (state *UI) Run() { + for event := range state.tcEvents { + if event, ok := event.(*tcell.EventResize); ok { + state.screen.Clear() + width, height := event.Size() + state.ctx = NewContext(width, height, state.screen, state.onPopover) + state.Content.Invalidate() + } + // if we have a popover, and it can handle the event, it does so + if state.popover == nil || !state.popover.Event(event) { + // otherwise, we send the event to the main content + state.Content.Event(event) + } + } +}