internal/uidriver/glfw: Update the screen on resizing

Closes #1204
This commit is contained in:
Hajime Hoshi 2021-01-20 02:21:51 +09:00
parent 5f81065d78
commit 9400efa9a5
4 changed files with 70 additions and 12 deletions

View File

@ -20,6 +20,7 @@ type Thread interface {
Call(f func() error) error
}
// SetMainThread must be called from the main thread (i.e, the goroutine where the thread is created).
func SetMainThread(thread Thread) {
theThread = thread
}

View File

@ -59,3 +59,32 @@ func (u *UserInterface) Run(uicontext driver.UIContext) error {
u.setRunning(false)
return <-ch
}
// runOnAnotherThreadFromMainThread is called from the main thread, and calls f on a new goroutine (thread).
// runOnAnotherThreadFromMainThread creates a new nested main thread and runs the run loop.
// u.t is updated to the new thread until runOnAnotherThreadFromMainThread is called.
//
// Inside f, another functions that must be called from the main thread can be called safely.
func (u *UserInterface) runOnAnotherThreadFromMainThread(f func() error) error {
// As this function is called from the main thread, u.t should never be accessed and can be updated here.
t := u.t
defer func() {
u.t = t
graphicscommand.SetMainThread(t)
}()
u.t = thread.NewOSThread()
graphicscommand.SetMainThread(u.t)
var err error
go func() {
defer func() {
_ = u.t.Call(func() error {
return thread.BreakLoop
})
}()
err = f()
}()
u.t.Loop()
return err
}

View File

@ -45,3 +45,7 @@ func (u *UserInterface) Run(uicontext driver.UIContext) error {
u.setRunning(false)
return nil
}
func (u *UserInterface) runOnAnotherThreadFromMainThread(f func() error) error {
return f()
}

View File

@ -50,6 +50,9 @@ type UserInterface struct {
runnableOnUnfocused bool
vsync bool
// err must be accessed from the main thread.
err error
lastDeviceScaleFactor float64
initMonitor *glfw.Monitor
@ -73,9 +76,6 @@ type UserInterface struct {
vsyncInited bool
reqWidth int
reqHeight int
input Input
iwindow window
@ -628,8 +628,35 @@ func (u *UserInterface) createWindow() error {
if u.isFullscreen() {
return
}
u.reqWidth = width
u.reqHeight = height
if err := u.runOnAnotherThreadFromMainThread(func() error {
var outsideWidth, outsideHeight float64
var outsideSizeChanged bool
_ = u.t.Call(func() error {
if width != 0 || height != 0 {
u.setWindowSize(width, height, u.isFullscreen())
}
outsideWidth, outsideHeight, outsideSizeChanged = u.updateSize()
return nil
})
if outsideSizeChanged {
u.context.Layout(outsideWidth, outsideHeight)
}
if err := u.context.ForceUpdate(); err != nil {
return err
}
if u.Graphics().IsGL() {
_ = u.t.Call(func() error {
u.swapBuffers()
return nil
})
}
return nil
}); err != nil {
u.err = err
}
})
return nil
@ -754,6 +781,10 @@ func (u *UserInterface) updateSize() (float64, float64, bool) {
// update must be called from the main thread.
func (u *UserInterface) update() (float64, float64, bool, error) {
if u.err != nil {
return 0, 0, false, u.err
}
if u.window.ShouldClose() {
return 0, 0, false, driver.RegularTermination
}
@ -772,13 +803,6 @@ func (u *UserInterface) update() (float64, float64, bool, error) {
u.vsyncInited = true
}
// Update the screen size when the window is resizable.
if w, h := u.reqWidth, u.reqHeight; w != 0 || h != 0 {
u.setWindowSize(w, h, u.isFullscreen())
}
u.reqWidth = 0
u.reqHeight = 0
outsideWidth, outsideHeight, outsideSizeChanged := u.updateSize()
// TODO: Updating the input can be skipped when clock.Update returns 0 (#1367).