internal/glfw: refactoring: use pointers or functions for callbacks

This commit is contained in:
Hajime Hoshi 2022-05-20 17:34:06 +09:00
parent 006b4324dc
commit eec5ea00ec
7 changed files with 108 additions and 79 deletions

View File

@ -21,87 +21,60 @@ import (
"github.com/go-gl/glfw/v3.3/glfw" "github.com/go-gl/glfw/v3.3/glfw"
) )
var (
charModsCallbacks = map[CharModsCallback]glfw.CharModsCallback{}
closeCallbacks = map[CloseCallback]glfw.CloseCallback{}
framebufferSizeCallbacks = map[FramebufferSizeCallback]glfw.FramebufferSizeCallback{}
monitorCallbacks = map[MonitorCallback]glfw.MonitorCallback{}
scrollCallbacks = map[ScrollCallback]glfw.ScrollCallback{}
sizeCallbacks = map[SizeCallback]glfw.SizeCallback{}
)
func ToCharModsCallback(cb func(window *Window, char rune, mods ModifierKey)) CharModsCallback { func ToCharModsCallback(cb func(window *Window, char rune, mods ModifierKey)) CharModsCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
id := CharModsCallback(len(charModsCallbacks) + 1) return func(window *glfw.Window, char rune, mods glfw.ModifierKey) {
var gcb glfw.CharModsCallback = func(window *glfw.Window, char rune, mods glfw.ModifierKey) {
cb(theWindows.get(window), char, ModifierKey(mods)) cb(theWindows.get(window), char, ModifierKey(mods))
} }
charModsCallbacks[id] = gcb
return id
} }
func ToCloseCallback(cb func(window *Window)) CloseCallback { func ToCloseCallback(cb func(window *Window)) CloseCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
id := CloseCallback(len(closeCallbacks) + 1) return func(window *glfw.Window) {
var gcb glfw.CloseCallback = func(window *glfw.Window) {
cb(theWindows.get(window)) cb(theWindows.get(window))
} }
closeCallbacks[id] = gcb
return id
} }
func ToFramebufferSizeCallback(cb func(window *Window, width int, height int)) FramebufferSizeCallback { func ToFramebufferSizeCallback(cb func(window *Window, width int, height int)) FramebufferSizeCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
id := FramebufferSizeCallback(len(framebufferSizeCallbacks) + 1) return func(window *glfw.Window, width int, height int) {
var gcb glfw.FramebufferSizeCallback = func(window *glfw.Window, width int, height int) {
cb(theWindows.get(window), width, height) cb(theWindows.get(window), width, height)
} }
framebufferSizeCallbacks[id] = gcb
return id
} }
func ToMonitorCallback(cb func(monitor *Monitor, event PeripheralEvent)) MonitorCallback { func ToMonitorCallback(cb func(monitor *Monitor, event PeripheralEvent)) MonitorCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
id := MonitorCallback(len(monitorCallbacks) + 1) return func(monitor *glfw.Monitor, event glfw.PeripheralEvent) {
var gcb glfw.MonitorCallback = func(monitor *glfw.Monitor, event glfw.PeripheralEvent) {
var m *Monitor var m *Monitor
if monitor != nil { if monitor != nil {
m = &Monitor{monitor} m = &Monitor{monitor}
} }
cb(m, PeripheralEvent(event)) cb(m, PeripheralEvent(event))
} }
monitorCallbacks[id] = gcb
return id
} }
func ToScrollCallback(cb func(window *Window, xoff float64, yoff float64)) ScrollCallback { func ToScrollCallback(cb func(window *Window, xoff float64, yoff float64)) ScrollCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
id := ScrollCallback(len(scrollCallbacks) + 1) return func(window *glfw.Window, xoff float64, yoff float64) {
var gcb glfw.ScrollCallback = func(window *glfw.Window, xoff float64, yoff float64) {
cb(theWindows.get(window), xoff, yoff) cb(theWindows.get(window), xoff, yoff)
} }
scrollCallbacks[id] = gcb
return id
} }
func ToSizeCallback(cb func(window *Window, width int, height int)) SizeCallback { func ToSizeCallback(cb func(window *Window, width int, height int)) SizeCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
id := SizeCallback(len(sizeCallbacks) + 1) return func(window *glfw.Window, width, height int) {
var gcb glfw.SizeCallback = func(window *glfw.Window, width, height int) {
cb(theWindows.get(window), width, height) cb(theWindows.get(window), width, height)
} }
sizeCallbacks[id] = gcb
return id
} }

View File

@ -18,68 +18,82 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
var uniquePtrToCallback = map[uniquePtr]uintptr{}
func ToCharModsCallback(cb func(window *Window, char rune, mods ModifierKey)) CharModsCallback { func ToCharModsCallback(cb func(window *Window, char rune, mods ModifierKey)) CharModsCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
return CharModsCallback(windows.NewCallbackCDecl(func(window uintptr, char rune, mods ModifierKey) uintptr { ptr := uniquePtr(new(byte))
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr, char rune, mods ModifierKey) uintptr {
cb(theGLFWWindows.get(window), char, mods) cb(theGLFWWindows.get(window), char, mods)
return 0 return 0
})) })
return CharModsCallback(ptr)
} }
func ToCloseCallback(cb func(window *Window)) CloseCallback { func ToCloseCallback(cb func(window *Window)) CloseCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
return CloseCallback(windows.NewCallbackCDecl(func(window uintptr) uintptr { ptr := uniquePtr(new(byte))
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr) uintptr {
cb(theGLFWWindows.get(window)) cb(theGLFWWindows.get(window))
return 0 return 0
})) })
return CloseCallback(ptr)
} }
func ToFramebufferSizeCallback(cb func(window *Window, width int, height int)) FramebufferSizeCallback { func ToFramebufferSizeCallback(cb func(window *Window, width int, height int)) FramebufferSizeCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
return FramebufferSizeCallback(windows.NewCallbackCDecl(func(window uintptr, width int, height int) uintptr { ptr := uniquePtr(new(byte))
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr, width int, height int) uintptr {
cb(theGLFWWindows.get(window), width, height) cb(theGLFWWindows.get(window), width, height)
return 0 return 0
})) })
return FramebufferSizeCallback(ptr)
} }
func ToMonitorCallback(cb func(monitor *Monitor, event PeripheralEvent)) MonitorCallback { func ToMonitorCallback(cb func(monitor *Monitor, event PeripheralEvent)) MonitorCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
return MonitorCallback(windows.NewCallbackCDecl(func(monitor uintptr, event PeripheralEvent) uintptr { ptr := uniquePtr(new(byte))
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(monitor uintptr, event PeripheralEvent) uintptr {
var m *Monitor var m *Monitor
if monitor != 0 { if monitor != 0 {
m = &Monitor{monitor} m = &Monitor{monitor}
} }
cb(m, event) cb(m, event)
return 0 return 0
})) })
return MonitorCallback(ptr)
} }
func ToScrollCallback(cb func(window *Window, xoff float64, yoff float64)) ScrollCallback { func ToScrollCallback(cb func(window *Window, xoff float64, yoff float64)) ScrollCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
return ScrollCallback(windows.NewCallbackCDecl(func(window uintptr, xoff *float64, yoff *float64) uintptr { ptr := uniquePtr(new(byte))
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr, xoff *float64, yoff *float64) uintptr {
// xoff and yoff were originally float64, but there is no good way to pass them on 32bit // xoff and yoff were originally float64, but there is no good way to pass them on 32bit
// machines via NewCallback. We've fixed GLFW side to use pointer values. // machines via NewCallback. We've fixed GLFW side to use pointer values.
cb(theGLFWWindows.get(window), *xoff, *yoff) cb(theGLFWWindows.get(window), *xoff, *yoff)
return 0 return 0
})) })
return ScrollCallback(ptr)
} }
func ToSizeCallback(cb func(window *Window, width int, height int)) SizeCallback { func ToSizeCallback(cb func(window *Window, width int, height int)) SizeCallback {
if cb == nil { if cb == nil {
return 0 return nil
} }
return SizeCallback(windows.NewCallbackCDecl(func(window uintptr, width int, height int) uintptr { ptr := uniquePtr(new(byte))
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr, width int, height int) uintptr {
cb(theGLFWWindows.get(window), width, height) cb(theGLFWWindows.get(window), width, height)
return 0 return 0
})) })
return SizeCallback(ptr)
} }

View File

@ -166,7 +166,7 @@ func (w *Window) SetAttrib(attrib Hint, value int) {
} }
func (w *Window) SetCharModsCallback(cbfun CharModsCallback) (previous CharModsCallback) { func (w *Window) SetCharModsCallback(cbfun CharModsCallback) (previous CharModsCallback) {
w.w.SetCharModsCallback(charModsCallbacks[cbfun]) w.w.SetCharModsCallback(cbfun)
return ToCharModsCallback(nil) // TODO return ToCharModsCallback(nil) // TODO
} }
@ -179,17 +179,17 @@ func (w *Window) SetCursor(cursor *Cursor) {
} }
func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) { func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) {
w.w.SetCloseCallback(closeCallbacks[cbfun]) w.w.SetCloseCallback(cbfun)
return ToCloseCallback(nil) // TODO return ToCloseCallback(nil) // TODO
} }
func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) { func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) {
w.w.SetFramebufferSizeCallback(framebufferSizeCallbacks[cbfun]) w.w.SetFramebufferSizeCallback(cbfun)
return ToFramebufferSizeCallback(nil) // TODO return ToFramebufferSizeCallback(nil) // TODO
} }
func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) { func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) {
w.w.SetScrollCallback(scrollCallbacks[cbfun]) w.w.SetScrollCallback(cbfun)
return ToScrollCallback(nil) // TODO return ToScrollCallback(nil) // TODO
} }
@ -198,7 +198,7 @@ func (w *Window) SetShouldClose(value bool) {
} }
func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) { func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) {
w.w.SetSizeCallback(sizeCallbacks[cbfun]) w.w.SetSizeCallback(cbfun)
prev := w.prevSizeCallback prev := w.prevSizeCallback
w.prevSizeCallback = cbfun w.prevSizeCallback = cbfun
return prev return prev
@ -302,7 +302,7 @@ func PostEmptyEvent() {
} }
func SetMonitorCallback(cbfun MonitorCallback) MonitorCallback { func SetMonitorCallback(cbfun MonitorCallback) MonitorCallback {
glfw.SetMonitorCallback(monitorCallbacks[cbfun]) glfw.SetMonitorCallback(cbfun)
return ToMonitorCallback(nil) return ToMonitorCallback(nil)
} }

View File

@ -206,13 +206,13 @@ func (w *Window) Restore() {
} }
func (w *Window) SetCharModsCallback(cbfun CharModsCallback) (previous CharModsCallback) { func (w *Window) SetCharModsCallback(cbfun CharModsCallback) (previous CharModsCallback) {
glfwDLL.call("glfwSetCharModsCallback", w.w, uintptr(cbfun)) glfwDLL.call("glfwSetCharModsCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError() panicError()
return ToCharModsCallback(nil) // TODO return ToCharModsCallback(nil) // TODO
} }
func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) { func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) {
glfwDLL.call("glfwSetWindowCloseCallback", w.w, uintptr(cbfun)) glfwDLL.call("glfwSetWindowCloseCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError() panicError()
return ToCloseCallback(nil) // TODO return ToCloseCallback(nil) // TODO
} }
@ -226,13 +226,13 @@ func (w *Window) SetCursor(cursor *Cursor) {
} }
func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) { func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) {
glfwDLL.call("glfwSetFramebufferSizeCallback", w.w, uintptr(cbfun)) glfwDLL.call("glfwSetFramebufferSizeCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError() panicError()
return ToFramebufferSizeCallback(nil) // TODO return ToFramebufferSizeCallback(nil) // TODO
} }
func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) { func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) {
glfwDLL.call("glfwSetScrollCallback", w.w, uintptr(cbfun)) glfwDLL.call("glfwSetScrollCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError() panicError()
return ToScrollCallback(nil) // TODO return ToScrollCallback(nil) // TODO
} }
@ -247,7 +247,7 @@ func (w *Window) SetShouldClose(value bool) {
} }
func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) { func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) {
glfwDLL.call("glfwSetWindowSizeCallback", w.w, uintptr(cbfun)) glfwDLL.call("glfwSetWindowSizeCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError() panicError()
prev := w.prevSizeCallback prev := w.prevSizeCallback
w.prevSizeCallback = cbfun w.prevSizeCallback = cbfun
@ -413,7 +413,7 @@ func PostEmptyEvent() {
} }
func SetMonitorCallback(cbfun MonitorCallback) MonitorCallback { func SetMonitorCallback(cbfun MonitorCallback) MonitorCallback {
glfwDLL.call("glfwSetMonitorCallback", uintptr(cbfun)) glfwDLL.call("glfwSetMonitorCallback", uniquePtrToCallback[uniquePtr(cbfun)])
panicError() panicError()
return ToMonitorCallback(nil) // TODO return ToMonitorCallback(nil) // TODO
} }

View File

@ -0,0 +1,40 @@
// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !windows && !js
// +build !windows,!js
package glfw
import (
"github.com/go-gl/glfw/v3.3/glfw"
)
type (
CharModsCallback = glfw.CharModsCallback
CloseCallback = glfw.CloseCallback
FramebufferSizeCallback = glfw.FramebufferSizeCallback
MonitorCallback = glfw.MonitorCallback
ScrollCallback = glfw.ScrollCallback
SizeCallback = glfw.SizeCallback
)
type VidMode struct {
Width int
Height int
RedBits int
GreenBits int
BlueBits int
RefreshRate int
}

View File

@ -17,13 +17,15 @@
package glfw package glfw
type uniquePtr *byte
type ( type (
CharModsCallback uintptr CharModsCallback uniquePtr
CloseCallback uintptr CloseCallback uniquePtr
FramebufferSizeCallback uintptr FramebufferSizeCallback uniquePtr
MonitorCallback uintptr MonitorCallback uniquePtr
ScrollCallback uintptr ScrollCallback uniquePtr
SizeCallback uintptr SizeCallback uniquePtr
) )
type VidMode struct { type VidMode struct {

View File

@ -687,7 +687,7 @@ func (u *userInterfaceImpl) createWindow(width, height int) error {
// 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 == 0 { 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 { if !u.setSizeCallbackEnabled {
return return
@ -734,7 +734,7 @@ func (u *userInterfaceImpl) registerWindowSetSizeCallback() {
// registerWindowCloseCallback must be called from the main thread. // registerWindowCloseCallback must be called from the main thread.
func (u *userInterfaceImpl) registerWindowCloseCallback() { func (u *userInterfaceImpl) registerWindowCloseCallback() {
if u.closeCallback == 0 { if u.closeCallback == nil {
u.closeCallback = glfw.ToCloseCallback(func(_ *glfw.Window) { u.closeCallback = glfw.ToCloseCallback(func(_ *glfw.Window) {
u.m.Lock() u.m.Lock()
u.windowBeingClosed = true u.windowBeingClosed = true
@ -751,7 +751,7 @@ func (u *userInterfaceImpl) registerWindowCloseCallback() {
// registerWindowFramebufferSizeCallback must be called from the main thread. // registerWindowFramebufferSizeCallback must be called from the main thread.
func (u *userInterfaceImpl) registerWindowFramebufferSizeCallback() { func (u *userInterfaceImpl) registerWindowFramebufferSizeCallback() {
if u.defaultFramebufferSizeCallback == 0 { if u.defaultFramebufferSizeCallback == nil {
// When the window gets resized (either by manual window resize or a window // When the window gets resized (either by manual window resize or a window
// manager), glfw sends a framebuffer size callback which we need to handle (#1960). // manager), glfw sends a framebuffer size callback which we need to handle (#1960).
// This event is the only way to handle the size change at least on i3 window manager. // This event is the only way to handle the size change at least on i3 window manager.
@ -782,7 +782,7 @@ func (u *userInterfaceImpl) registerWindowFramebufferSizeCallback() {
func (u *userInterfaceImpl) waitForFramebufferSizeCallback(window *glfw.Window, f func()) { func (u *userInterfaceImpl) waitForFramebufferSizeCallback(window *glfw.Window, f func()) {
u.framebufferSizeCallbackCh = make(chan struct{}, 1) u.framebufferSizeCallbackCh = make(chan struct{}, 1)
if u.framebufferSizeCallback == 0 { if u.framebufferSizeCallback == nil {
u.framebufferSizeCallback = glfw.ToFramebufferSizeCallback(func(_ *glfw.Window, _, _ int) { u.framebufferSizeCallback = glfw.ToFramebufferSizeCallback(func(_ *glfw.Window, _, _ int) {
// This callback can be invoked multiple times by one PollEvents in theory (#1618). // This callback can be invoked multiple times by one PollEvents in theory (#1618).
// Allow the case when the channel is full. // Allow the case when the channel is full.