From 18d526c2d3e67c3d285950247b6df084a0458c98 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Tue, 23 Feb 2021 16:52:09 +0900 Subject: [PATCH] internal/uidriver/glfw: Bug fix: Crash when returning from fullscreen ForceUpdate was called unexpectedly inside Update. This caused the race condition. Closes #1505 --- internal/glfw/glfw_notwindows.go | 8 ++++++-- internal/glfw/glfw_windows.go | 10 +++++++--- internal/uidriver/glfw/ui.go | 6 ++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/internal/glfw/glfw_notwindows.go b/internal/glfw/glfw_notwindows.go index 4f8f5e810..1b4a7e1e7 100644 --- a/internal/glfw/glfw_notwindows.go +++ b/internal/glfw/glfw_notwindows.go @@ -35,7 +35,7 @@ func (w windows) add(win *glfw.Window) *Window { if win == nil { return nil } - ww := &Window{win} + ww := &Window{w: win} windowsM.Lock() w[win] = ww windowsM.Unlock() @@ -87,6 +87,8 @@ func (m *Monitor) GetVideoMode() *VidMode { type Window struct { w *glfw.Window + + prevSizeCallback SizeCallback } func (w *Window) Destroy() { @@ -191,7 +193,9 @@ func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) { } } w.w.SetSizeCallback(gcb) - return nil // TODO + prev := w.prevSizeCallback + w.prevSizeCallback = cbfun + return prev } func (w *Window) SetIcon(images []image.Image) { diff --git a/internal/glfw/glfw_windows.go b/internal/glfw/glfw_windows.go index c13595cf7..8cc6b880f 100644 --- a/internal/glfw/glfw_windows.go +++ b/internal/glfw/glfw_windows.go @@ -42,7 +42,7 @@ func (w glfwWindows) add(win uintptr) *Window { if win == 0 { return nil } - ww := &Window{win} + ww := &Window{w: win} glfwWindowsM.Lock() w[win] = ww glfwWindowsM.Unlock() @@ -91,6 +91,8 @@ func (m *Monitor) GetVideoMode() *VidMode { type Window struct { w uintptr + + prevSizeCallback SizeCallback } func (w *Window) Destroy() { @@ -218,7 +220,7 @@ func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallbac return nil // TODO } -func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous FramebufferSizeCallback) { +func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) { var gcb uintptr if cbfun != nil { gcb = windows.NewCallbackCDecl(func(window uintptr, width int, height int) uintptr { @@ -228,7 +230,9 @@ func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous FramebufferSizeCa } glfwDLL.call("glfwSetWindowSizeCallback", w.w, gcb) panicError() - return nil // TODO + prev := w.prevSizeCallback + w.prevSizeCallback = cbfun + return prev } func (w *Window) SetIcon(images []image.Image) { diff --git a/internal/uidriver/glfw/ui.go b/internal/uidriver/glfw/ui.go index dc85c9a95..c0b69290c 100644 --- a/internal/uidriver/glfw/ui.go +++ b/internal/uidriver/glfw/ui.go @@ -946,6 +946,12 @@ func (u *UserInterface) setWindowSize(width, height int, fullscreen bool) { // swap buffers here before SetSize is called. u.swapBuffers() + // Do not fire the callback of SetSize. This callback can be invoked by SetMonitor or SetSize. + // ForceUpdate is called from the callback. + // While setWindowSize can be called from Update, calling ForceUpdate inside Update is illegal (#1505). + f := u.window.SetSizeCallback(nil) + defer u.window.SetSizeCallback(f) + var windowRecreated bool if fullscreen {