diff --git a/internal/glfw/callback_notwindows.go b/internal/glfw/callback_notwindows.go index d509fd4c3..2b9bbe27d 100644 --- a/internal/glfw/callback_notwindows.go +++ b/internal/glfw/callback_notwindows.go @@ -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 } diff --git a/internal/glfw/callback_windows.go b/internal/glfw/callback_windows.go index 9e46e76c3..0323f3a68 100644 --- a/internal/glfw/callback_windows.go +++ b/internal/glfw/callback_windows.go @@ -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) } diff --git a/internal/glfw/glfw_notwindows.go b/internal/glfw/glfw_notwindows.go index dda78ddff..feccc5434 100644 --- a/internal/glfw/glfw_notwindows.go +++ b/internal/glfw/glfw_notwindows.go @@ -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) } diff --git a/internal/glfw/glfw_windows.go b/internal/glfw/glfw_windows.go index 564e2bff8..115ed4e14 100644 --- a/internal/glfw/glfw_windows.go +++ b/internal/glfw/glfw_windows.go @@ -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 } diff --git a/internal/glfw/type_notwindows.go b/internal/glfw/type_notwindows.go new file mode 100644 index 000000000..d112eec19 --- /dev/null +++ b/internal/glfw/type_notwindows.go @@ -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 +} diff --git a/internal/glfw/type.go b/internal/glfw/type_windows.go similarity index 76% rename from internal/glfw/type.go rename to internal/glfw/type_windows.go index 3e94738ec..d0fb4023c 100644 --- a/internal/glfw/type.go +++ b/internal/glfw/type_windows.go @@ -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 { diff --git a/internal/ui/ui_glfw.go b/internal/ui/ui_glfw.go index da3595064..392b54167 100644 --- a/internal/ui/ui_glfw.go +++ b/internal/ui/ui_glfw.go @@ -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.