From 1527e91a026c3d8e8f1126a5e559723dc23123cd Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 13 Dec 2023 18:10:40 -0600 Subject: [PATCH] app: [macOS] send ViewEvents when the NSView is attached to a NSWindow Instead of sending ViewEvents once at construction and once at destruction, it's better to send them when the underlying NSView changes attachment. The main advantage is that we're about to move the destruction and emitting of DestroyEvent to the NSView's dealloc method. However, the dealloc will not be called if user code has a strong reference to it through a non-empty ViewEvent. By sending an empty ViewEvent when the view is detached, well-behaving users will remove the strong reference. Signed-off-by: Elias Naur --- app/os_macos.go | 16 ++++++++++++---- app/os_macos.m | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/os_macos.go b/app/os_macos.go index 59b87acc..1d677827 100644 --- a/app/os_macos.go +++ b/app/os_macos.go @@ -857,11 +857,21 @@ func configFor(scale float32) unit.Metric { } } +//export gio_onAttached +func gio_onAttached(h C.uintptr_t, attached C.int) { + w := windowFor(h) + if attached != 0 { + layer := C.layerForView(w.view) + w.ProcessEvent(ViewEvent{View: uintptr(w.view), Layer: uintptr(layer)}) + } else { + w.ProcessEvent(ViewEvent{}) + w.setStage(StagePaused) + } +} + //export gio_onClose func gio_onClose(h C.uintptr_t) { w := windowFor(h) - w.ProcessEvent(ViewEvent{}) - w.setStage(StagePaused) w.ProcessEvent(DestroyEvent{}) w.displayLink.Close() w.displayLink = nil @@ -927,8 +937,6 @@ func newWindow(win *callbacks, options []Option) { nextTopLeft = C.cascadeTopLeftFromPoint(window, nextTopLeft) // makeKeyAndOrderFront assumes ownership of our window reference. C.makeKeyAndOrderFront(window) - layer := C.layerForView(w.view) - w.ProcessEvent(ViewEvent{View: uintptr(w.view), Layer: uintptr(layer)}) }) <-res } diff --git a/app/os_macos.m b/app/os_macos.m index 70439c2d..f6e4c5fa 100644 --- a/app/os_macos.m +++ b/app/os_macos.m @@ -89,6 +89,7 @@ static void handleMouse(GioView *view, NSEvent *event, int typ, CGFloat dx, CGFl return layer; } - (void)viewDidMoveToWindow { + gio_onAttached(self.handle, self.window != nil ? 1 : 0); if (self.window == nil) { gio_onClose(self.handle); }