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"
)
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 {
if cb == nil {
return 0
return nil
}
id := CharModsCallback(len(charModsCallbacks) + 1)
var gcb glfw.CharModsCallback = func(window *glfw.Window, char rune, mods glfw.ModifierKey) {
return func(window *glfw.Window, char rune, mods glfw.ModifierKey) {
cb(theWindows.get(window), char, ModifierKey(mods))
}
charModsCallbacks[id] = gcb
return id
}
func ToCloseCallback(cb func(window *Window)) CloseCallback {
if cb == nil {
return 0
return nil
}
id := CloseCallback(len(closeCallbacks) + 1)
var gcb glfw.CloseCallback = func(window *glfw.Window) {
return func(window *glfw.Window) {
cb(theWindows.get(window))
}
closeCallbacks[id] = gcb
return id
}
func ToFramebufferSizeCallback(cb func(window *Window, width int, height int)) FramebufferSizeCallback {
if cb == nil {
return 0
return nil
}
id := FramebufferSizeCallback(len(framebufferSizeCallbacks) + 1)
var gcb glfw.FramebufferSizeCallback = func(window *glfw.Window, width int, height int) {
return func(window *glfw.Window, width int, height int) {
cb(theWindows.get(window), width, height)
}
framebufferSizeCallbacks[id] = gcb
return id
}
func ToMonitorCallback(cb func(monitor *Monitor, event PeripheralEvent)) MonitorCallback {
if cb == nil {
return 0
return nil
}
id := MonitorCallback(len(monitorCallbacks) + 1)
var gcb glfw.MonitorCallback = func(monitor *glfw.Monitor, event glfw.PeripheralEvent) {
return func(monitor *glfw.Monitor, event glfw.PeripheralEvent) {
var m *Monitor
if monitor != nil {
m = &Monitor{monitor}
}
cb(m, PeripheralEvent(event))
}
monitorCallbacks[id] = gcb
return id
}
func ToScrollCallback(cb func(window *Window, xoff float64, yoff float64)) ScrollCallback {
if cb == nil {
return 0
return nil
}
id := ScrollCallback(len(scrollCallbacks) + 1)
var gcb glfw.ScrollCallback = func(window *glfw.Window, xoff float64, yoff float64) {
return func(window *glfw.Window, xoff float64, yoff float64) {
cb(theWindows.get(window), xoff, yoff)
}
scrollCallbacks[id] = gcb
return id
}
func ToSizeCallback(cb func(window *Window, width int, height int)) SizeCallback {
if cb == nil {
return 0
return nil
}
id := SizeCallback(len(sizeCallbacks) + 1)
var gcb glfw.SizeCallback = func(window *glfw.Window, width, height int) {
return func(window *glfw.Window, width, height int) {
cb(theWindows.get(window), width, height)
}
sizeCallbacks[id] = gcb
return id
}

View File

@ -18,68 +18,82 @@ import (
"golang.org/x/sys/windows"
)
var uniquePtrToCallback = map[uniquePtr]uintptr{}
func ToCharModsCallback(cb func(window *Window, char rune, mods ModifierKey)) CharModsCallback {
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)
return 0
}))
})
return CharModsCallback(ptr)
}
func ToCloseCallback(cb func(window *Window)) CloseCallback {
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))
return 0
}))
})
return CloseCallback(ptr)
}
func ToFramebufferSizeCallback(cb func(window *Window, width int, height int)) FramebufferSizeCallback {
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)
return 0
}))
})
return FramebufferSizeCallback(ptr)
}
func ToMonitorCallback(cb func(monitor *Monitor, event PeripheralEvent)) MonitorCallback {
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
if monitor != 0 {
m = &Monitor{monitor}
}
cb(m, event)
return 0
}))
})
return MonitorCallback(ptr)
}
func ToScrollCallback(cb func(window *Window, xoff float64, yoff float64)) ScrollCallback {
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
// machines via NewCallback. We've fixed GLFW side to use pointer values.
cb(theGLFWWindows.get(window), *xoff, *yoff)
return 0
}))
})
return ScrollCallback(ptr)
}
func ToSizeCallback(cb func(window *Window, width int, height int)) SizeCallback {
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)
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) {
w.w.SetCharModsCallback(charModsCallbacks[cbfun])
w.w.SetCharModsCallback(cbfun)
return ToCharModsCallback(nil) // TODO
}
@ -179,17 +179,17 @@ func (w *Window) SetCursor(cursor *Cursor) {
}
func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) {
w.w.SetCloseCallback(closeCallbacks[cbfun])
w.w.SetCloseCallback(cbfun)
return ToCloseCallback(nil) // TODO
}
func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) {
w.w.SetFramebufferSizeCallback(framebufferSizeCallbacks[cbfun])
w.w.SetFramebufferSizeCallback(cbfun)
return ToFramebufferSizeCallback(nil) // TODO
}
func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) {
w.w.SetScrollCallback(scrollCallbacks[cbfun])
w.w.SetScrollCallback(cbfun)
return ToScrollCallback(nil) // TODO
}
@ -198,7 +198,7 @@ func (w *Window) SetShouldClose(value bool) {
}
func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) {
w.w.SetSizeCallback(sizeCallbacks[cbfun])
w.w.SetSizeCallback(cbfun)
prev := w.prevSizeCallback
w.prevSizeCallback = cbfun
return prev
@ -302,7 +302,7 @@ func PostEmptyEvent() {
}
func SetMonitorCallback(cbfun MonitorCallback) MonitorCallback {
glfw.SetMonitorCallback(monitorCallbacks[cbfun])
glfw.SetMonitorCallback(cbfun)
return ToMonitorCallback(nil)
}

View File

@ -206,13 +206,13 @@ func (w *Window) Restore() {
}
func (w *Window) SetCharModsCallback(cbfun CharModsCallback) (previous CharModsCallback) {
glfwDLL.call("glfwSetCharModsCallback", w.w, uintptr(cbfun))
glfwDLL.call("glfwSetCharModsCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError()
return ToCharModsCallback(nil) // TODO
}
func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) {
glfwDLL.call("glfwSetWindowCloseCallback", w.w, uintptr(cbfun))
glfwDLL.call("glfwSetWindowCloseCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError()
return ToCloseCallback(nil) // TODO
}
@ -226,13 +226,13 @@ func (w *Window) SetCursor(cursor *Cursor) {
}
func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) {
glfwDLL.call("glfwSetFramebufferSizeCallback", w.w, uintptr(cbfun))
glfwDLL.call("glfwSetFramebufferSizeCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError()
return ToFramebufferSizeCallback(nil) // TODO
}
func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) {
glfwDLL.call("glfwSetScrollCallback", w.w, uintptr(cbfun))
glfwDLL.call("glfwSetScrollCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError()
return ToScrollCallback(nil) // TODO
}
@ -247,7 +247,7 @@ func (w *Window) SetShouldClose(value bool) {
}
func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) {
glfwDLL.call("glfwSetWindowSizeCallback", w.w, uintptr(cbfun))
glfwDLL.call("glfwSetWindowSizeCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
panicError()
prev := w.prevSizeCallback
w.prevSizeCallback = cbfun
@ -413,7 +413,7 @@ func PostEmptyEvent() {
}
func SetMonitorCallback(cbfun MonitorCallback) MonitorCallback {
glfwDLL.call("glfwSetMonitorCallback", uintptr(cbfun))
glfwDLL.call("glfwSetMonitorCallback", uniquePtrToCallback[uniquePtr(cbfun)])
panicError()
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
type uniquePtr *byte
type (
CharModsCallback uintptr
CloseCallback uintptr
FramebufferSizeCallback uintptr
MonitorCallback uintptr
ScrollCallback uintptr
SizeCallback uintptr
CharModsCallback uniquePtr
CloseCallback uniquePtr
FramebufferSizeCallback uniquePtr
MonitorCallback uniquePtr
ScrollCallback uniquePtr
SizeCallback uniquePtr
)
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.
func (u *userInterfaceImpl) registerWindowSetSizeCallback() {
if u.sizeCallback == 0 {
if u.sizeCallback == nil {
u.sizeCallback = glfw.ToSizeCallback(func(_ *glfw.Window, width, height int) {
if !u.setSizeCallbackEnabled {
return
@ -734,7 +734,7 @@ func (u *userInterfaceImpl) registerWindowSetSizeCallback() {
// registerWindowCloseCallback must be called from the main thread.
func (u *userInterfaceImpl) registerWindowCloseCallback() {
if u.closeCallback == 0 {
if u.closeCallback == nil {
u.closeCallback = glfw.ToCloseCallback(func(_ *glfw.Window) {
u.m.Lock()
u.windowBeingClosed = true
@ -751,7 +751,7 @@ func (u *userInterfaceImpl) registerWindowCloseCallback() {
// registerWindowFramebufferSizeCallback must be called from the main thread.
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
// 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.
@ -782,7 +782,7 @@ func (u *userInterfaceImpl) registerWindowFramebufferSizeCallback() {
func (u *userInterfaceImpl) waitForFramebufferSizeCallback(window *glfw.Window, f func()) {
u.framebufferSizeCallbackCh = make(chan struct{}, 1)
if u.framebufferSizeCallback == 0 {
if u.framebufferSizeCallback == nil {
u.framebufferSizeCallback = glfw.ToFramebufferSizeCallback(func(_ *glfw.Window, _, _ int) {
// This callback can be invoked multiple times by one PollEvents in theory (#1618).
// Allow the case when the channel is full.