diff --git a/internal/ui/ui_glfw.go b/internal/ui/ui_glfw.go index f59a22a73..c7bc86f09 100644 --- a/internal/ui/ui_glfw.go +++ b/internal/ui/ui_glfw.go @@ -1560,11 +1560,8 @@ func (u *userInterfaceImpl) setWindowTitle(title string) { } func (u *userInterfaceImpl) origPos() (int, int) { - // On macOS, the window can be fullscreened without calling an Ebiten function. - // Then, an original position might not be available by u.window.GetPos(). - // Do not rely on the window position. - if u.isNativeFullscreenAvailable() { - return invalidPos, invalidPos + if x, y, ok := u.origPosByOS(); ok { + return x, y } return u.origPosX, u.origPosY } @@ -1572,10 +1569,7 @@ func (u *userInterfaceImpl) origPos() (int, int) { func (u *userInterfaceImpl) setOrigPos(x, y int) { // TODO: The original position should be updated at a 'PosCallback'. - // On macOS, the window can be fullscreened without calling an Ebiten function. - // Then, an original position might not be available by u.window.GetPos(). - // Do not rely on the window position. - if u.isNativeFullscreenAvailable() { + if u.setOrigPosByOS(x, y) { return } u.origPosX = x diff --git a/internal/ui/ui_glfw_darwin.go b/internal/ui/ui_glfw_darwin.go index 282018039..d23f280c0 100644 --- a/internal/ui/ui_glfw_darwin.go +++ b/internal/ui/ui_glfw_darwin.go @@ -23,6 +23,8 @@ package ui // #import // // @interface EbitenWindowDelegate : NSObject +// // origPos is the window's original position. This is valid only when the application is in the fullscreen mode. +// @property CGPoint origPos; // @end // // @implementation EbitenWindowDelegate { @@ -82,6 +84,7 @@ package ui // - (void)windowWillEnterFullScreen:(NSNotification *)notification { // NSWindow* window = (NSWindow*)[notification object]; // [self pushResizableState:window]; +// self->_origPos = [window frame].origin; // } // // - (void)windowDidEnterFullScreen:(NSNotification *)notification { @@ -97,6 +100,7 @@ package ui // - (void)windowDidExitFullScreen:(NSNotification *)notification { // NSWindow* window = (NSWindow*)[notification object]; // [self popResizableState:window]; +// [window setFrameOrigin:self->_origPos]; // } // // @end @@ -184,6 +188,24 @@ package ui // [window setBackgroundColor: [NSColor colorWithSRGBRed:0 green:0 blue:0 alpha:0]]; // } // +// static void windowOriginalPosition(uintptr_t windowPtr, int* x, int* y) { +// NSWindow* window = (NSWindow*)windowPtr; +// CGPoint pos; +// EbitenWindowDelegate* delegate = (EbitenWindowDelegate*)window.delegate; +// pos = delegate.origPos; +// *x = pos.x; +// *y = pos.y; +// } +// +// static void setWindowOriginalPosition(uintptr_t windowPtr, int x, int y) { +// NSWindow* window = (NSWindow*)windowPtr; +// EbitenWindowDelegate* delegate = (EbitenWindowDelegate*)window.delegate; +// CGPoint pos; +// pos.x = x; +// pos.y = y; +// delegate.origPos = pos; +// } +// // static void setNativeCursor(int cursorID) { // id cursor = [[NSCursor class] performSelector:@selector(arrowCursor)]; // switch (cursorID) { @@ -287,12 +309,7 @@ func (u *userInterfaceImpl) adjustWindowPosition(x, y int, monitor *glfw.Monitor return x, y } -func initialMonitorByOS() (*glfw.Monitor, error) { - var cx, cy C.int - C.currentMouseLocation(&cx, &cy) - x, y := int(cx), int(cy) - - // Flip Y. +func flipY(y int) int { for _, m := range ensureMonitors() { if m.x == 0 && m.y == 0 { y = -y @@ -300,6 +317,13 @@ func initialMonitorByOS() (*glfw.Monitor, error) { break } } + return y +} + +func initialMonitorByOS() (*glfw.Monitor, error) { + var cx, cy C.int + C.currentMouseLocation(&cx, &cy) + x, y := int(cx), flipY(int(cy)) // Find the monitor including the cursor. for _, m := range ensureMonitors() { @@ -365,3 +389,26 @@ func initializeWindowAfterCreation(w *glfw.Window) { // Enable resizing temporary before making the window fullscreen. C.initializeWindow(C.uintptr_t(w.GetCocoaWindow())) } + +func (u *userInterfaceImpl) origPosByOS() (int, int, bool) { + if !u.isNativeFullscreen() { + return invalidPos, invalidPos, true + } + m := u.currentMonitor() + var cx, cy C.int + C.windowOriginalPosition(C.uintptr_t(u.window.GetCocoaWindow()), &cx, &cy) + x := int(u.dipFromGLFWPixel(float64(cx), m)) + y := int(u.dipFromGLFWPixel(float64(flipY(int(cy))), m)) - u.windowHeightInDIP + return x, y, true +} + +func (u *userInterfaceImpl) setOrigPosByOS(x, y int) bool { + if !u.isNativeFullscreen() { + return true + } + m := u.currentMonitor() + cx := C.int(u.dipToGLFWPixel(float64(x), m)) + cy := C.int(flipY(int(u.dipToGLFWPixel(float64(y+u.windowHeightInDIP), m)))) + C.setWindowOriginalPosition(C.uintptr_t(u.window.GetCocoaWindow()), cx, cy) + return true +} diff --git a/internal/ui/ui_glfw_unix.go b/internal/ui/ui_glfw_unix.go index 01bb76ad6..e272e47ae 100644 --- a/internal/ui/ui_glfw_unix.go +++ b/internal/ui/ui_glfw_unix.go @@ -228,3 +228,11 @@ func initializeWindowAfterCreation(w *glfw.Window) { // Apparently the window state is inconsistent just after the window is created, but we are not sure. // For more details, see the discussion in #1829. } + +func (u *userInterfaceImpl) origPosByOS() (int, int, bool) { + return 0, 0, false +} + +func (u *userInterfaceImpl) setOrigPosByOS(x, y int) bool { + return false +} diff --git a/internal/ui/ui_glfw_windows.go b/internal/ui/ui_glfw_windows.go index 0c4a67d13..4b00b38ed 100644 --- a/internal/ui/ui_glfw_windows.go +++ b/internal/ui/ui_glfw_windows.go @@ -243,3 +243,11 @@ func (u *userInterfaceImpl) setWindowResizingModeForOS(mode WindowResizingMode) func initializeWindowAfterCreation(w *glfw.Window) { } + +func (u *userInterfaceImpl) origPosByOS() (int, int, bool) { + return 0, 0, false +} + +func (u *userInterfaceImpl) setOrigPosByOS(x, y int) bool { + return false +} diff --git a/internal/ui/window_glfw.go b/internal/ui/window_glfw.go index 126854f35..8f0fca9df 100644 --- a/internal/ui/window_glfw.go +++ b/internal/ui/window_glfw.go @@ -168,7 +168,7 @@ func (w *Window) Position() (int, int) { x, y := 0, 0 w.ui.t.Call(func() { var wx, wy int - if w.ui.isFullscreen() && !w.ui.isNativeFullscreenAvailable() { + if w.ui.isFullscreen() { wx, wy = w.ui.origPos() } else { wx, wy = w.ui.window.GetPos()