From 1de8c9f3b051d7396f91e4ecec717a9014ac74df Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Tue, 18 Jan 2022 12:27:54 +0100 Subject: [PATCH] app: process one event at a time Commit 11aec807b2b7a2a155de65f0bcfce30e308bbb81 added a waiting flag to avoid processing platform events recursively. However the flag was only true when the window goroutine is blocked waiting for client events, so deferred window functions such as Window.Option may still runs multiple times for recursive events. This change renames the flag to busy and sets it during the entire processing of an event, including recursive events and deferred window functions. Fixes: https://todo.sr.ht/~eliasnaur/gio/344 Signed-off-by: Elias Naur --- app/window.go | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/app/window.go b/app/window.go index b853a8cd..8a4259d3 100644 --- a/app/window.go +++ b/app/window.go @@ -46,12 +46,10 @@ type Window struct { // scheduledRedraws is sent the most recent delayed redraw time. scheduledRedraws chan time.Time - waiting bool - waitEvents []event.Event - defers []func(d driver) - out chan event.Event - frames chan *op.Ops - frameAck chan struct{} + defers []func(d driver) + out chan event.Event + frames chan *op.Ops + frameAck chan struct{} // dead is closed when the window is destroyed. dead chan struct{} @@ -81,8 +79,10 @@ type Window struct { } type callbacks struct { - w *Window - d driver + w *Window + d driver + busy bool + waitEvents []event.Event } // queue is an event.Queue implementation that distributes system events @@ -398,21 +398,23 @@ func (c *callbacks) Event(e event.Event) { if c.d == nil { panic("event while no driver active") } - if c.w.waiting { - c.w.waitEvents = append(c.w.waitEvents, e) + if c.busy { + c.waitEvents = append(c.waitEvents, e) return } + c.busy = true + defer func() { + c.busy = false + }() c.w.processEvent(c.d, e) - for len(c.w.waitEvents) > 0 { - we := c.w.waitEvents[0] - copy(c.w.waitEvents, c.w.waitEvents[1:]) - c.w.waitEvents = c.w.waitEvents[:len(c.w.waitEvents)-1] - c.w.processEvent(c.d, we) + for _, e := range c.waitEvents { + c.w.processEvent(c.d, e) } + c.waitEvents = c.waitEvents[:0] for _, f := range c.w.defers { f(c.d) } - c.w.defers = nil + c.w.defers = c.w.defers[:0] c.w.updateState(c.d) } @@ -443,10 +445,6 @@ func (c *callbacks) SemanticAt(pos f32.Point) (router.SemanticID, bool) { } func (w *Window) waitAck() { - w.waiting = true - defer func() { - w.waiting = false - }() for { select { case f := <-w.driverFuncs: @@ -478,10 +476,6 @@ func (w *Window) destroyGPU() { // or to continue event handling. It returns whether the client // called Frame or not. func (w *Window) waitFrame() (*op.Ops, bool) { - w.waiting = true - defer func() { - w.waiting = false - }() for { select { case f := <-w.driverFuncs: