internal/ui: refactoring: simplify logic by removing setSizeCallbackEnabled

Closes #1816
This commit is contained in:
Hajime Hoshi 2022-09-25 23:29:58 +09:00
parent 70ebd34d99
commit 12f42544dd
3 changed files with 25 additions and 115 deletions

View File

@ -119,6 +119,9 @@ func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, update
return err return err
} }
theUI.beginFrame()
defer theUI.endFrame()
// The given outside size can be 0 e.g. just after restoring from the fullscreen mode on Windows (#1589) // The given outside size can be 0 e.g. just after restoring from the fullscreen mode on Windows (#1589)
// Just ignore such cases. Otherwise, creating a zero-sized framebuffer causes a panic. // Just ignore such cases. Otherwise, creating a zero-sized framebuffer causes a panic.
if outsideWidth == 0 || outsideHeight == 0 { if outsideWidth == 0 || outsideHeight == 0 {

View File

@ -70,9 +70,7 @@ type userInterfaceImpl struct {
windowBeingClosed bool windowBeingClosed bool
windowResizingMode WindowResizingMode windowResizingMode WindowResizingMode
justAfterResized bool justAfterResized bool
inFrame bool
// setSizeCallbackEnabled must be accessed from the main thread.
setSizeCallbackEnabled bool
// err must be accessed from the main thread. // err must be accessed from the main thread.
err error err error
@ -729,14 +727,18 @@ func (u *userInterfaceImpl) createWindow(width, height int) error {
return nil return nil
} }
func (u *userInterfaceImpl) beginFrame() {
u.inFrame = true
}
func (u *userInterfaceImpl) endFrame() {
u.inFrame = false
}
// registerWindowSetSizeCallback must be called from the main thread. // registerWindowSetSizeCallback must be called from the main thread.
func (u *userInterfaceImpl) registerWindowSetSizeCallback() { func (u *userInterfaceImpl) registerWindowSetSizeCallback() {
if u.sizeCallback == nil { if u.sizeCallback == nil {
u.sizeCallback = glfw.ToSizeCallback(func(_ *glfw.Window, width, height int) { u.sizeCallback = glfw.ToSizeCallback(func(_ *glfw.Window, width, height int) {
if !u.setSizeCallbackEnabled {
return
}
u.adjustViewSizeAfterFullscreen() u.adjustViewSizeAfterFullscreen()
if u.window.GetAttrib(glfw.Resizable) == glfw.False { if u.window.GetAttrib(glfw.Resizable) == glfw.False {
@ -749,7 +751,12 @@ func (u *userInterfaceImpl) registerWindowSetSizeCallback() {
if width != 0 || height != 0 { if width != 0 || height != 0 {
w := int(u.dipFromGLFWPixel(float64(width), u.currentMonitor())) w := int(u.dipFromGLFWPixel(float64(width), u.currentMonitor()))
h := int(u.dipFromGLFWPixel(float64(height), u.currentMonitor())) h := int(u.dipFromGLFWPixel(float64(height), u.currentMonitor()))
u.setWindowSizeInDIP(w, h) u.setWindowSizeInDIP(w, h, false)
}
// Now the state is in a frame. (force)UpdateFrame cannot be called recursively.
if u.inFrame {
return
} }
outsideWidth, outsideHeight := u.outsideSize() outsideWidth, outsideHeight := u.outsideSize()
@ -816,7 +823,7 @@ func (u *userInterfaceImpl) registerWindowFramebufferSizeCallback() {
s := u.deviceScaleFactor(u.currentMonitor()) s := u.deviceScaleFactor(u.currentMonitor())
ww := int(float64(w) / s) ww := int(float64(w) / s)
wh := int(float64(h) / s) wh := int(float64(h) / s)
u.setWindowSizeInDIP(ww, wh) u.setWindowSizeInDIP(ww, wh, false)
}) })
} }
u.window.SetFramebufferSizeCallback(u.defaultFramebufferSizeCallback) u.window.SetFramebufferSizeCallback(u.defaultFramebufferSizeCallback)
@ -931,8 +938,6 @@ func (u *userInterfaceImpl) init() error {
return err return err
} }
u.setSizeCallbackEnabled = true
// The position must be set before the size is set (#1982). // The position must be set before the size is set (#1982).
// setWindowSize refers the current monitor's device scale. // setWindowSize refers the current monitor's device scale.
// TODO: currentMonitor is very hard to use correctly. Refactor this. // TODO: currentMonitor is very hard to use correctly. Refactor this.
@ -951,7 +956,7 @@ func (u *userInterfaceImpl) init() error {
wy = max wy = max
} }
u.setWindowPositionInDIP(wx, wy, u.initMonitor) u.setWindowPositionInDIP(wx, wy, u.initMonitor)
u.setWindowSizeInDIP(ww, wh) u.setWindowSizeInDIP(ww, wh, true)
// Maximizing a window requires a proper size and position. Call Maximize here (#1117). // Maximizing a window requires a proper size and position. Call Maximize here (#1117).
if u.isInitWindowMaximized() { if u.isInitWindowMaximized() {
@ -1231,10 +1236,7 @@ func (u *userInterfaceImpl) adjustWindowSizeBasedOnSizeLimitsInDIP(width, height
} }
// setWindowSize must be called from the main thread. // setWindowSize must be called from the main thread.
// func (u *userInterfaceImpl) setWindowSizeInDIP(width, height int, callSetSize bool) {
// TODO: Split this function into two: setting members and calling (*glfw.Window).SetSize.
// This function is invoked from the SetSize callback, but calling (*glfw.Window).SetSize from the callback is odd (#1816).
func (u *userInterfaceImpl) setWindowSizeInDIP(width, height int) {
if microsoftgdk.IsXbox() { if microsoftgdk.IsXbox() {
// Do nothing. The size is always fixed. // Do nothing. The size is always fixed.
return return
@ -1261,18 +1263,7 @@ func (u *userInterfaceImpl) setWindowSizeInDIP(width, height int) {
// swap buffers here before SetSize is called. // swap buffers here before SetSize is called.
u.swapBuffers() u.swapBuffers()
// Disable the callback of SetSize. This callback can be invoked by SetMonitor or SetSize. if !u.isFullscreen() && callSetSize {
// ForceUpdateFrame is called from the callback.
// While setWindowSize can be called from UpdateFrame,
// calling ForceUpdateFrame inside UpdateFrame is illegal (#1505).
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
if !u.isFullscreen() {
// Set the window size after the position. The order matters. // Set the window size after the position. The order matters.
// In the opposite order, the window size might not be correct when going back from fullscreen with multi monitors. // In the opposite order, the window size might not be correct when going back from fullscreen with multi monitors.
oldW, oldH := u.window.GetSize() oldW, oldH := u.window.GetSize()
@ -1297,17 +1288,6 @@ func (u *userInterfaceImpl) setFullscreen(fullscreen bool) {
} }
u.graphicsDriver.SetFullscreen(fullscreen) u.graphicsDriver.SetFullscreen(fullscreen)
// Disable the callback of SetSize. This callback can be invoked by SetMonitor or SetSize.
// ForceUpdateFrame is called from the callback.
// While setWindowSize can be called from UpdateFrame,
// calling ForceUpdateFrame inside UpdateFrame is illegal (#1505).
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
// Enter the fullscreen. // Enter the fullscreen.
if fullscreen { if fullscreen {
if x, y := u.origWindowPos(); x == invalidPos || y == invalidPos { if x, y := u.origWindowPos(); x == invalidPos || y == invalidPos {
@ -1503,31 +1483,17 @@ func (u *userInterfaceImpl) maximizeWindow() {
return return
} }
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
u.window.Maximize()
if u.isFullscreen() { if u.isFullscreen() {
return return
} }
u.window.Maximize()
// On Linux/UNIX, maximizing might not finish even though Maximize returns. Just wait for its finish. // On Linux/UNIX, maximizing might not finish even though Maximize returns. Just wait for its finish.
// Do not check this in the fullscreen since apparently the condition can never be true. // Do not check this in the fullscreen since apparently the condition can never be true.
for u.window.GetAttrib(glfw.Maximized) != glfw.True { for u.window.GetAttrib(glfw.Maximized) != glfw.True {
glfw.PollEvents() glfw.PollEvents()
} }
// Call setWindowSize explicitly in order to update the rendering since the callback is disabled now.
// Do not call setWindowSize in the fullscreen mode since setWindowSize requires the window size
// before the fullscreen, while window.GetSize() returns the desktop screen size in the fullscreen mode.
w, h := u.window.GetSize()
ww := int(u.dipFromGLFWPixel(float64(w), u.currentMonitor()))
wh := int(u.dipFromGLFWPixel(float64(h), u.currentMonitor()))
u.setWindowSizeInDIP(ww, wh)
} }
// iconifyWindow must be called from the main thread. // iconifyWindow must be called from the main thread.
@ -1537,32 +1503,16 @@ func (u *userInterfaceImpl) iconifyWindow() {
return return
} }
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
u.window.Iconify() u.window.Iconify()
// On Linux/UNIX, iconifying might not finish even though Iconify returns. Just wait for its finish. // On Linux/UNIX, iconifying might not finish even though Iconify returns. Just wait for its finish.
for u.window.GetAttrib(glfw.Iconified) != glfw.True { for u.window.GetAttrib(glfw.Iconified) != glfw.True {
glfw.PollEvents() glfw.PollEvents()
} }
// After iconifiying, the window is invisible and setWindowSize doesn't have to be called.
// Rather, the window size might be (0, 0) and it might be impossible to call setWindowSize (#1585).
} }
// restoreWindow must be called from the main thread. // restoreWindow must be called from the main thread.
func (u *userInterfaceImpl) restoreWindow() { func (u *userInterfaceImpl) restoreWindow() {
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
u.window.Restore() u.window.Restore()
// On Linux/UNIX, restoring might not finish even though Restore returns (#1608). Just wait for its finish. // On Linux/UNIX, restoring might not finish even though Restore returns (#1608). Just wait for its finish.
@ -1573,16 +1523,6 @@ func (u *userInterfaceImpl) restoreWindow() {
time.Sleep(time.Second / 60) time.Sleep(time.Second / 60)
} }
} }
// Call setWindowSize explicitly in order to update the rendering since the callback is disabled now.
// Do not call setWindowSize in the fullscreen mode since setWindowSize requires the window size
// before the fullscreen, while window.GetSize() returns the desktop screen size in the fullscreen mode.
if !u.isFullscreen() {
w, h := u.window.GetSize()
ww := int(u.dipFromGLFWPixel(float64(w), u.currentMonitor()))
wh := int(u.dipFromGLFWPixel(float64(h), u.currentMonitor()))
u.setWindowSizeInDIP(ww, wh)
}
} }
// setWindowDecorated must be called from the main thread. // setWindowDecorated must be called from the main thread.
@ -1591,12 +1531,6 @@ func (u *userInterfaceImpl) setWindowDecorated(decorated bool) {
return return
} }
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
v := glfw.False v := glfw.False
if decorated { if decorated {
v = glfw.True v = glfw.True
@ -1615,12 +1549,6 @@ func (u *userInterfaceImpl) setWindowFloating(floating bool) {
return return
} }
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
v := glfw.False v := glfw.False
if floating { if floating {
v = glfw.True v = glfw.True
@ -1638,13 +1566,6 @@ func (u *userInterfaceImpl) setWindowResizingMode(mode WindowResizingMode) {
return return
} }
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
u.windowResizingMode = mode u.windowResizingMode = mode
v := glfw.False v := glfw.False
@ -1666,13 +1587,6 @@ func (u *userInterfaceImpl) setWindowPositionInDIP(x, y int, monitor *glfw.Monit
return return
} }
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
mx, my := monitor.GetPos() mx, my := monitor.GetPos()
xf := u.dipToGLFWPixel(float64(x), monitor) xf := u.dipToGLFWPixel(float64(x), monitor)
yf := u.dipToGLFWPixel(float64(y), monitor) yf := u.dipToGLFWPixel(float64(y), monitor)
@ -1685,13 +1599,6 @@ func (u *userInterfaceImpl) setWindowPositionInDIP(x, y int, monitor *glfw.Monit
// setWindowTitle must be called from the main thread. // setWindowTitle must be called from the main thread.
func (u *userInterfaceImpl) setWindowTitle(title string) { func (u *userInterfaceImpl) setWindowTitle(title string) {
if u.setSizeCallbackEnabled {
u.setSizeCallbackEnabled = false
defer func() {
u.setSizeCallbackEnabled = true
}()
}
u.window.SetTitle(title) u.window.SetTitle(title)
} }

View File

@ -217,7 +217,7 @@ func (w *glfwWindow) SetSize(width, height int) {
if w.ui.isWindowMaximized() && runtime.GOOS != "darwin" { if w.ui.isWindowMaximized() && runtime.GOOS != "darwin" {
return return
} }
w.ui.setWindowSizeInDIP(width, height) w.ui.setWindowSizeInDIP(width, height, true)
}) })
} }