From 083d407b472b0ffc83354ca6b20f50bb32c95a90 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 10 Mar 2022 10:25:08 +0100 Subject: [PATCH] app: [macOS] ensure only one redraw request is in flight at any time After 34f10d9cbb3a45da2ecb8a9fab60b0a5995c1a31, the display link callback will never block. However, if the main thread is blocked for another reason, say a bug in the user program, callback requests will pile up as blocked goroutines. This change ensures that a redraw request is queued only if no other request is pending. References: https://todo.sr.ht/~eliasnaur/gio/370 Signed-off-by: Elias Naur --- app/os_macos.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/os_macos.go b/app/os_macos.go index 44c820ee..e87116cc 100644 --- a/app/os_macos.go +++ b/app/os_macos.go @@ -205,7 +205,10 @@ type window struct { w *callbacks stage system.Stage displayLink *displayLink - cursor pointer.Cursor + // redraw is a single entry channel for making sure only one + // display link redraw request is in flight. + redraw chan struct{} + cursor pointer.Cursor scale float32 config Config @@ -667,6 +670,10 @@ func gio_firstRectForCharacterRange(view C.CFTypeRef, crng C.NSRange, actual C.N } func (w *window) draw() { + select { + case <-w.redraw: + default: + } w.scale = float32(C.getViewBackingScale(w.view)) wf, hf := float32(C.viewWidth(w.view)), float32(C.viewHeight(w.view)) sz := image.Point{ @@ -792,10 +799,16 @@ func newOSWindow() (*window, error) { } scale := float32(C.getViewBackingScale(view)) w := &window{ - view: view, - scale: scale, + view: view, + scale: scale, + redraw: make(chan struct{}, 1), } dl, err := NewDisplayLink(func() { + select { + case w.redraw <- struct{}{}: + default: + return + } w.runOnMain(func() { C.setNeedsDisplay(w.view) })