internal/cglfw: let functions return errors in native_darwin.go and glfw_unix.go

Updates #2703
This commit is contained in:
Hajime Hoshi 2023-10-07 18:05:03 +09:00
parent cb023af4b6
commit 82bceba847
8 changed files with 141 additions and 53 deletions

View File

@ -208,3 +208,18 @@ func fetchError() *Error {
return nil
}
}
// fetchErrorIgnoringPlatformError is fetchError igoring platformError.
// This emulates panicError but without panicking.
func fetchErrorIgnoringPlatformError() error {
select {
case err := <-lastError:
if err.Code == platformError {
fmt.Fprintln(os.Stderr, err)
return nil
}
return err
default:
return nil
}
}

View File

@ -123,9 +123,9 @@ func GetClipboardString() string {
// string.
//
// This function may only be called from the main thread.
func SetClipboardString(str string) {
func SetClipboardString(str string) error {
cp := C.CString(str)
defer C.free(unsafe.Pointer(cp))
C.glfwSetClipboardString(nil, cp)
panicError()
return fetchErrorIgnoringPlatformError()
}

View File

@ -23,22 +23,19 @@ import "C"
import "unsafe"
// GetCocoaMonitor returns the CGDirectDisplayID of the monitor.
func (m *Monitor) GetCocoaMonitor() uintptr {
func (m *Monitor) GetCocoaMonitor() (uintptr, error) {
ret := uintptr(C.glfwGetCocoaMonitor(m.data))
panicError()
return ret
return ret, fetchErrorIgnoringPlatformError()
}
// GetCocoaWindow returns the NSWindow of the window.
func (w *Window) GetCocoaWindow() unsafe.Pointer {
func (w *Window) GetCocoaWindow() (unsafe.Pointer, error) {
ret := C.workaround_glfwGetCocoaWindow(w.data)
panicError()
return ret
return ret, fetchErrorIgnoringPlatformError()
}
// GetNSGLContext returns the NSOpenGLContext of the window.
func (w *Window) GetNSGLContext() unsafe.Pointer {
func (w *Window) GetNSGLContext() (unsafe.Pointer, error) {
ret := C.workaround_glfwGetNSGLContext(w.data)
panicError()
return ret
return ret, fetchErrorIgnoringPlatformError()
}

View File

@ -14,10 +14,18 @@
package glfw
func (w *Window) GetCocoaWindow() uintptr {
return uintptr(w.w.GetCocoaWindow())
func (w *Window) GetCocoaWindow() (uintptr, error) {
ptr, err := w.w.GetCocoaWindow()
if err != nil {
return 0, err
}
return uintptr(ptr), nil
}
func (m *Monitor) GetCocoaMonitor() uintptr {
return m.m.GetCocoaMonitor()
func (m *Monitor) GetCocoaMonitor() (uintptr, error) {
ptr, err := m.m.GetCocoaMonitor()
if err != nil {
return 0, err
}
return uintptr(ptr), nil
}

View File

@ -628,7 +628,11 @@ func (u *userInterfaceImpl) isFullscreen() (bool, error) {
if err != nil {
return false, err
}
return m != nil || u.isNativeFullscreen(), nil
n, err := u.isNativeFullscreen()
if err != nil {
return false, err
}
return m != nil || n, nil
}
func (u *userInterfaceImpl) IsFullscreen() bool {
@ -1188,7 +1192,9 @@ func (u *userInterfaceImpl) initOnMainThread(options *RunOptions) error {
}
}
u.setWindowResizingModeForOS(u.windowResizingMode)
if err := u.setWindowResizingModeForOS(u.windowResizingMode); err != nil {
return err
}
if options.SkipTaskbar {
// Ignore the error.
@ -1239,7 +1245,11 @@ func (u *userInterfaceImpl) outsideSize() (float64, float64, error) {
if err != nil {
return 0, 0, err
}
if f && !u.isNativeFullscreen() {
n, err := u.isNativeFullscreen()
if err != nil {
return 0, 0, err
}
if f && !n {
// On Linux, the window size is not reliable just after making the window
// fullscreened. Use the monitor size.
// On macOS's native fullscreen, the window's size returns a more precise size
@ -1600,8 +1610,10 @@ func (u *userInterfaceImpl) updateWindowSizeLimits() error {
return err
}
// The window size limit affects the resizing mode, especially on macOS (#).
u.setWindowResizingModeForOS(u.windowResizingMode)
// The window size limit affects the resizing mode, especially on macOS (#2260).
if err := u.setWindowResizingModeForOS(u.windowResizingMode); err != nil {
return err
}
return nil
}
@ -1744,7 +1756,9 @@ func (u *userInterfaceImpl) setFullscreen(fullscreen bool) error {
}
if u.isNativeFullscreenAvailable() {
u.setNativeFullscreen(fullscreen)
if err := u.setNativeFullscreen(fullscreen); err != nil {
return err
}
} else {
m, err := u.currentMonitor()
if err != nil {
@ -1759,7 +1773,9 @@ func (u *userInterfaceImpl) setFullscreen(fullscreen bool) error {
return err
}
}
u.adjustViewSizeAfterFullscreen()
if err := u.adjustViewSizeAfterFullscreen(); err != nil {
return err
}
return nil
}
@ -1779,7 +1795,9 @@ func (u *userInterfaceImpl) setFullscreen(fullscreen bool) error {
ww := int(dipToGLFWPixel(float64(u.origWindowWidthInDIP), m))
wh := int(dipToGLFWPixel(float64(u.origWindowHeightInDIP), m))
if u.isNativeFullscreenAvailable() {
u.setNativeFullscreen(false)
if err := u.setNativeFullscreen(false); err != nil {
return err
}
// Adjust the window size later (after adjusting the position).
} else {
m, err := u.window.GetMonitor()
@ -1932,7 +1950,11 @@ func (u *userInterfaceImpl) Window() Window {
// maximizeWindow must be called from the main thread.
func (u *userInterfaceImpl) maximizeWindow() error {
if u.isNativeFullscreen() {
n, err := u.isNativeFullscreen()
if err != nil {
return err
}
if n {
return nil
}
@ -1969,7 +1991,11 @@ func (u *userInterfaceImpl) maximizeWindow() error {
// iconifyWindow must be called from the main thread.
func (u *userInterfaceImpl) iconifyWindow() error {
// Iconifying a native fullscreen window on macOS is forbidden.
if u.isNativeFullscreen() {
n, err := u.isNativeFullscreen()
if err != nil {
return err
}
if n {
return nil
}
@ -2085,7 +2111,9 @@ func (u *userInterfaceImpl) setWindowResizingMode(mode WindowResizingMode) error
if err := u.window.SetAttrib(glfw.Resizable, v); err != nil {
return err
}
u.setWindowResizingModeForOS(mode)
if err := u.setWindowResizingModeForOS(mode); err != nil {
return err
}
return nil
}
@ -2132,7 +2160,11 @@ func (u *userInterfaceImpl) isWindowMaximized() (bool, error) {
if err != nil {
return false, err
}
return a == glfw.True && !u.isNativeFullscreen(), nil
n, err := u.isNativeFullscreen()
if err != nil {
return false, err
}
return a == glfw.True && !n, nil
}
func (u *userInterfaceImpl) origWindowPos() (int, int) {

View File

@ -274,7 +274,11 @@ func initialMonitorByOS() (*Monitor, error) {
}
func monitorFromWindowByOS(w *glfw.Window) (*Monitor, error) {
window := cocoa.NSWindow{ID: objc.ID(w.GetCocoaWindow())}
cocoaWindow, err := w.GetCocoaWindow()
if err != nil {
return nil, err
}
window := cocoa.NSWindow{ID: objc.ID(cocoaWindow)}
pool := cocoa.NSAutoreleasePool_new()
screen := cocoa.NSScreen_mainScreen()
if window.ID != 0 && window.IsVisible() {
@ -287,7 +291,11 @@ func monitorFromWindowByOS(w *glfw.Window) (*Monitor, error) {
aID := uintptr(screenID.UnsignedIntValue()) // CGDirectDisplayID
pool.Release()
for _, m := range theMonitors.append(nil) {
if m.m.GetCocoaMonitor() == aID {
cocoaMonitor, err := m.m.GetCocoaMonitor()
if err != nil {
return nil, err
}
if cocoaMonitor == aID {
return m, nil
}
}
@ -295,11 +303,15 @@ func monitorFromWindowByOS(w *glfw.Window) (*Monitor, error) {
}
func (u *userInterfaceImpl) nativeWindow() (uintptr, error) {
return u.window.GetCocoaWindow(), nil
return u.window.GetCocoaWindow()
}
func (u *userInterfaceImpl) isNativeFullscreen() bool {
return cocoa.NSWindow{ID: objc.ID(u.window.GetCocoaWindow())}.StyleMask()&cocoa.NSWindowStyleMaskFullScreen != 0
func (u *userInterfaceImpl) isNativeFullscreen() (bool, error) {
w, err := u.window.GetCocoaWindow()
if err != nil {
return false, err
}
return cocoa.NSWindow{ID: objc.ID(w)}.StyleMask()&cocoa.NSWindowStyleMaskFullScreen != 0, nil
}
func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
@ -308,12 +320,16 @@ func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
return true
}
func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) {
func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) error {
// Toggling fullscreen might ignore events like keyUp. Ensure that events are fired.
glfw.WaitEventsTimeout(0.1)
window := cocoa.NSWindow{ID: objc.ID(u.window.GetCocoaWindow())}
w, err := u.window.GetCocoaWindow()
if err != nil {
return err
}
window := cocoa.NSWindow{ID: objc.ID(w)}
if window.StyleMask()&cocoa.NSWindowStyleMaskFullScreen != 0 == fullscreen {
return
return nil
}
// Even though EbitengineWindowDelegate is used, this hack is still required.
// toggleFullscreen doesn't work when the window is not resizable.
@ -329,16 +345,22 @@ func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) {
if !origFullScreen {
window.Send(sel_setCollectionBehavior, cocoa.NSUInteger(cocoa.NSUInteger(origCollectionBehavior)))
}
return nil
}
func (u *userInterfaceImpl) adjustViewSizeAfterFullscreen() {
func (u *userInterfaceImpl) adjustViewSizeAfterFullscreen() error {
if u.graphicsDriver.IsGL() {
return
return nil
}
window := cocoa.NSWindow{ID: objc.ID(u.window.GetCocoaWindow())}
w, err := u.window.GetCocoaWindow()
if err != nil {
return err
}
window := cocoa.NSWindow{ID: objc.ID(w)}
if window.StyleMask()&cocoa.NSWindowStyleMaskFullScreen == 0 {
return
return nil
}
// Reduce the view height (#1745).
@ -347,7 +369,7 @@ func (u *userInterfaceImpl) adjustViewSizeAfterFullscreen() {
view := window.ContentView()
viewSize := view.Frame().Size
if windowSize.Width != viewSize.Width || windowSize.Height != viewSize.Height {
return
return nil
}
viewSize.Width--
view.SetFrameSize(viewSize)
@ -355,6 +377,7 @@ func (u *userInterfaceImpl) adjustViewSizeAfterFullscreen() {
// NSColor.blackColor (0, 0, 0, 1) didn't work.
// Use the transparent color instead.
window.SetBackgroundColor(cocoa.NSColor_colorWithSRGBRedGreenBlueAlpha(0, 0, 0, 0))
return nil
}
func (u *userInterfaceImpl) isFullscreenAllowedFromUI(mode WindowResizingMode) bool {
@ -370,7 +393,7 @@ func (u *userInterfaceImpl) isFullscreenAllowedFromUI(mode WindowResizingMode) b
return false
}
func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode) {
func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode) error {
var collectionBehavior uint
if u.isFullscreenAllowedFromUI(mode) {
collectionBehavior |= cocoa.NSWindowCollectionBehaviorManaged
@ -378,13 +401,22 @@ func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode)
} else {
collectionBehavior |= cocoa.NSWindowCollectionBehaviorFullScreenNone
}
objc.ID(u.window.GetCocoaWindow()).Send(sel_setCollectionBehavior, collectionBehavior)
w, err := u.window.GetCocoaWindow()
if err != nil {
return err
}
objc.ID(w).Send(sel_setCollectionBehavior, collectionBehavior)
return nil
}
func initializeWindowAfterCreation(w *glfw.Window) error {
// TODO: Register NSWindowWillEnterFullScreenNotification and so on.
// Enable resizing temporary before making the window fullscreen.
nswindow := objc.ID(w.GetCocoaWindow())
cocoaWindow, err := w.GetCocoaWindow()
if err != nil {
return err
}
nswindow := objc.ID(cocoaWindow)
delegate := objc.ID(class_EbitengineWindowDelegate).Send(sel_alloc).Send(sel_initWithOrigDelegate, nswindow.Send(sel_delegate))
nswindow.Send(sel_setDelegate, delegate)
return nil

View File

@ -154,22 +154,24 @@ func (u *userInterfaceImpl) nativeWindow() (uintptr, error) {
return 0, nil
}
func (u *userInterfaceImpl) isNativeFullscreen() bool {
return false
func (u *userInterfaceImpl) isNativeFullscreen() (bool, error) {
return false, nil
}
func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
return false
}
func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) {
func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) error {
panic(fmt.Sprintf("ui: setNativeFullscreen is not implemented in this environment: %s", runtime.GOOS))
}
func (u *userInterfaceImpl) adjustViewSizeAfterFullscreen() {
func (u *userInterfaceImpl) adjustViewSizeAfterFullscreen() error {
return nil
}
func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode) {
func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode) error {
return nil
}
func initializeWindowAfterCreation(w *glfw.Window) error {

View File

@ -183,22 +183,24 @@ func (u *userInterfaceImpl) nativeWindow() (uintptr, error) {
return uintptr(w), err
}
func (u *userInterfaceImpl) isNativeFullscreen() bool {
return false
func (u *userInterfaceImpl) isNativeFullscreen() (bool, error) {
return false, nil
}
func (u *userInterfaceImpl) isNativeFullscreenAvailable() bool {
return false
}
func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) {
func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) error {
panic(fmt.Sprintf("ui: setNativeFullscreen is not implemented in this environment: %s", runtime.GOOS))
}
func (u *userInterfaceImpl) adjustViewSizeAfterFullscreen() {
func (u *userInterfaceImpl) adjustViewSizeAfterFullscreen() error {
return nil
}
func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode) {
func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode) error {
return nil
}
func initializeWindowAfterCreation(w *glfw.Window) error {