diff --git a/internal/ui/ui_glfw.go b/internal/ui/ui_glfw.go index 72420306d..3ab73e2d0 100644 --- a/internal/ui/ui_glfw.go +++ b/internal/ui/ui_glfw.go @@ -56,9 +56,6 @@ type userInterfaceImpl struct { title string window *glfw.Window - windowWidthInDIP int - windowHeightInDIP int - minWindowWidthInDIP int minWindowHeightInDIP int maxWindowWidthInDIP int @@ -555,7 +552,7 @@ func (u *userInterfaceImpl) SetFullscreen(fullscreen bool) { if u.isFullscreen() == fullscreen { return } - w, h := u.windowWidthInDIP, u.windowHeightInDIP + w, h := u.origWindowSizeInDIP() u.setWindowSizeInDIP(w, h, fullscreen) }) } @@ -972,7 +969,7 @@ func (u *userInterfaceImpl) init() error { } func (u *userInterfaceImpl) updateSize() { - ww, wh := u.windowWidthInDIP, u.windowHeightInDIP + ww, wh := u.origWindowSizeInDIP() u.setWindowSizeInDIP(ww, wh, u.isFullscreen()) } @@ -993,11 +990,12 @@ func (u *userInterfaceImpl) outsideSize() (float64, float64) { } if u.window.GetAttrib(glfw.Iconified) == glfw.True { - return float64(u.windowWidthInDIP), float64(u.windowHeightInDIP) + w, h := u.origWindowSizeInDIP() + return float64(w), float64(h) } - // Instead of u.windowWidthInDIP and u.windowHeightInDIP, use the actual window size - // here. On Windows, the specified size at SetSize and the actual window size might + // Instead of u.origWindowSizeInDIP(), use the actual window size here. + // On Windows, the specified size at SetSize and the actual window size might // not match (#1163). ww, wh := u.window.GetSize() w := u.dipFromGLFWPixel(float64(ww), u.currentMonitor()) @@ -1245,7 +1243,7 @@ func (u *userInterfaceImpl) setWindowSizeInDIP(width, height int, fullscreen boo u.graphicsDriver.SetFullscreen(fullscreen) scale := u.deviceScaleFactor(u.currentMonitor()) - if u.windowWidthInDIP == width && u.windowHeightInDIP == height && u.isFullscreen() == fullscreen && u.lastDeviceScaleFactor == scale { + if ow, oh := u.origWindowSizeInDIP(); ow == width && oh == height && u.isFullscreen() == fullscreen && u.lastDeviceScaleFactor == scale { return } @@ -1280,8 +1278,7 @@ func (u *userInterfaceImpl) setWindowSizeInDIP(width, height int, fullscreen boo u.adjustViewSize() // As width might be updated, update windowWidth/Height here. - u.windowWidthInDIP = width - u.windowHeightInDIP = height + u.setOrigWindowSizeInDIP(width, height) } func (u *userInterfaceImpl) minimumWindowWidth() int { diff --git a/internal/ui/ui_glfw_darwin.go b/internal/ui/ui_glfw_darwin.go index 8219686f6..7a7220491 100644 --- a/internal/ui/ui_glfw_darwin.go +++ b/internal/ui/ui_glfw_darwin.go @@ -25,6 +25,8 @@ package ui // @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; +// // origSize is the window's original size. +// @property CGSize origSize; // @end // // @implementation EbitenWindowDelegate { @@ -85,6 +87,7 @@ package ui // NSWindow* window = (NSWindow*)[notification object]; // [self pushResizableState:window]; // self->_origPos = [window frame].origin; +// self->_origSize = [window frame].size; // } // // - (void)windowDidEnterFullScreen:(NSNotification *)notification { @@ -100,7 +103,10 @@ package ui // - (void)windowDidExitFullScreen:(NSNotification *)notification { // NSWindow* window = (NSWindow*)[notification object]; // [self popResizableState:window]; -// [window setFrameOrigin:self->_origPos]; +// CGRect frame; +// frame.origin = self->_origPos; +// frame.size = self->_origSize; +// [window setFrame:frame display:YES]; // } // // @end @@ -190,9 +196,8 @@ package ui // // static void windowOriginalPosition(uintptr_t windowPtr, int* x, int* y) { // NSWindow* window = (NSWindow*)windowPtr; -// CGPoint pos; // EbitenWindowDelegate* delegate = (EbitenWindowDelegate*)window.delegate; -// pos = delegate.origPos; +// CGPoint pos = delegate.origPos; // *x = pos.x; // *y = pos.y; // } @@ -206,6 +211,23 @@ package ui // delegate.origPos = pos; // } // +// static void windowOriginalSize(uintptr_t windowPtr, int* width, int* height) { +// NSWindow* window = (NSWindow*)windowPtr; +// EbitenWindowDelegate* delegate = (EbitenWindowDelegate*)window.delegate; +// CGSize size = delegate.origSize; +// *width = size.width; +// *height = size.height; +// } +// +// static void setWindowOriginalSize(uintptr_t windowPtr, int width, int height) { +// NSWindow* window = (NSWindow*)windowPtr; +// EbitenWindowDelegate* delegate = (EbitenWindowDelegate*)window.delegate; +// CGSize size; +// size.width = width; +// size.height = height; +// delegate.origSize = size; +// } +// // static void setNativeCursor(int cursorID) { // id cursor = [[NSCursor class] performSelector:@selector(arrowCursor)]; // switch (cursorID) { @@ -287,8 +309,7 @@ func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) { // clearVideoModeScaleCache must be called from the main thread. func clearVideoModeScaleCache() {} -type userInterfaceImplNative struct { -} +type userInterfaceImplNative struct{} // dipFromGLFWMonitorPixel must be called from the main thread. func (u *userInterfaceImpl) dipFromGLFWMonitorPixel(x float64, monitor *glfw.Monitor) float64 { @@ -401,7 +422,8 @@ func (u *userInterfaceImpl) origWindowPos() (int, int) { var cx, cy C.int C.windowOriginalPosition(C.uintptr_t(u.window.GetCocoaWindow()), &cx, &cy) x := int(cx) - y := flipY(int(cy)) - u.windowHeightInDIP + _, h := u.origWindowSizeInDIP() + y := flipY(int(cy)) - h return x, y } @@ -410,9 +432,25 @@ func (u *userInterfaceImpl) setOrigWindowPos(x, y int) { return } cx := C.int(x) - cy := C.int(flipY(y + u.windowHeightInDIP)) + _, h := u.origWindowSizeInDIP() + cy := C.int(flipY(y + h)) C.setWindowOriginalPosition(C.uintptr_t(u.window.GetCocoaWindow()), cx, cy) } +func (u *userInterfaceImpl) origWindowSizeInDIP() (int, int) { + // TODO: Make these values consistent with the original positions that are updated only when the app is in fullscreen. + var cw, ch C.int + C.windowOriginalSize(C.uintptr_t(u.window.GetCocoaWindow()), &cw, &ch) + w := int(u.dipFromGLFWPixel(float64(cw), u.currentMonitor())) + h := int(u.dipFromGLFWPixel(float64(ch), u.currentMonitor())) + return w, h +} + +func (u *userInterfaceImpl) setOrigWindowSizeInDIP(width, height int) { + cw := C.int(u.dipFromGLFWPixel(float64(width), u.currentMonitor())) + ch := C.int(u.dipFromGLFWPixel(float64(height), u.currentMonitor())) + C.setWindowOriginalSize(C.uintptr_t(u.window.GetCocoaWindow()), cw, ch) +} + func (u *userInterfaceImplNative) initialize() { } diff --git a/internal/ui/ui_glfw_unix.go b/internal/ui/ui_glfw_unix.go index fc4ec6402..a4f422085 100644 --- a/internal/ui/ui_glfw_unix.go +++ b/internal/ui/ui_glfw_unix.go @@ -143,8 +143,10 @@ func videoModeScaleUncached(m *glfw.Monitor) float64 { } type userInterfaceImplNative struct { - origWindowPosX int - origWindowPosY int + origWindowPosX int + origWindowPosY int + origWindowWidthInDIP int + origWindowHeightInDIP int } // dipFromGLFWMonitorPixel must be called from the main thread. @@ -245,6 +247,15 @@ func (u *userInterfaceImpl) setOrigWindowPos(x, y int) { u.native.origWindowPosY = y } +func (u *userInterfaceImpl) origWindowSizeInDIP() (int, int) { + return u.native.origWindowWidthInDIP, u.native.origWindowHeightInDIP +} + +func (u *userInterfaceImpl) setOrigWindowSizeInDIP(width, height int) { + u.native.origWindowWidthInDIP = width + u.native.origWindowHeightInDIP = height +} + func (u *userInterfaceImplNative) initialize() { u.origWindowPosX = invalidPos u.origWindowPosY = invalidPos diff --git a/internal/ui/ui_glfw_windows.go b/internal/ui/ui_glfw_windows.go index 55f42d9a9..66bbe5248 100644 --- a/internal/ui/ui_glfw_windows.go +++ b/internal/ui/ui_glfw_windows.go @@ -63,8 +63,10 @@ func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) { } type userInterfaceImplNative struct { - origWindowPosX int - origWindowPosY int + origWindowPosX int + origWindowPosY int + origWindowWidthInDIP int + origWindowHeightInDIP int } // clearVideoModeScaleCache must be called from the main thread. @@ -201,6 +203,15 @@ func (u *userInterfaceImpl) setOrigWindowPos(x, y int) { u.native.origWindowPosY = y } +func (u *userInterfaceImpl) origWindowSizeInDIP() (int, int) { + return u.native.origWindowWidthInDIP, u.native.origWindowHeightInDIP +} + +func (u *userInterfaceImpl) setOrigWindowSizeInDIP(width, height int) { + u.native.origWindowWidthInDIP = width + u.native.origWindowHeightInDIP = height +} + func (u *userInterfaceImplNative) initialize() { u.origWindowPosX = invalidPos u.origWindowPosY = invalidPos diff --git a/internal/ui/window_glfw.go b/internal/ui/window_glfw.go index 8fa686d86..4663f6d0d 100644 --- a/internal/ui/window_glfw.go +++ b/internal/ui/window_glfw.go @@ -189,11 +189,10 @@ func (w *glfwWindow) Size() (int, int) { ww, wh := w.ui.getInitWindowSizeInDIP() return w.ui.adjustWindowSizeBasedOnSizeLimitsInDIP(ww, wh) } - ww, wh := 0, 0 + var ww, wh int w.ui.t.Call(func() { - // Unlike origWindowPos, windowWidth/HeightInDPI is always updated via the callback. - ww = w.ui.windowWidthInDIP - wh = w.ui.windowHeightInDIP + // Unlike origWindowPos, origWindowSizeInDPI is always updated via the callback. + ww, wh = w.ui.origWindowSizeInDIP() }) return ww, wh } @@ -204,13 +203,6 @@ func (w *glfwWindow) SetSize(width, height int) { return } w.ui.t.Call(func() { - // When a window is a native fullscreen, forcing to resize the window might leave unexpected image lags. - // Forbid this. - // TODO: Remove this condition (#1590). - if w.ui.isNativeFullscreen() { - return - } - w.ui.setWindowSizeInDIP(width, height, w.ui.isFullscreen()) }) }