Description
SetPosition() on macOS cannot reliably move a window from one screen to another. The Y-coordinate conversion in windowSetPosition uses [window screen] (the screen the window is currently on) rather than determining which screen the target coordinates belong to.
This means if a window is on Screen A and you call SetPosition with coordinates intended for Screen B, the Y-axis conversion uses Screen A's height, placing the window at the wrong location.
Root Cause
In pkg/application/webview_window_darwin.go (lines 627-641):
void windowSetPosition(void* nsWindow, int x, int y) {
WebviewWindow* window = (WebviewWindow*)nsWindow;
NSScreen* screen = [window screen]; // ← always the CURRENT screen
if (screen == NULL) {
screen = [NSScreen mainScreen];
}
CGFloat scale = [screen backingScaleFactor];
NSRect frame = [window frame];
frame.origin.x = x / scale;
frame.origin.y = (screen.frame.size.height - frame.size.height) - (y / scale);
// ^^^^^^^^^^^^^^^^^^^^^^^ wrong screen height for cross-screen moves
[window setFrame:frame display:YES];
}
The same issue exists in windowGetPosition (lines 612-625) — both use [window screen] for conversion, so coordinates are always relative to the current screen rather than absolute.
Steps to Reproduce
- Connect an external monitor above or below the built-in display
- Create a window on the primary screen
- Call
SetPosition(x, y) with coordinates that should place the window on the external monitor
- Window appears at the wrong position (still on the primary screen, or offset)
Expected Behavior
SetPosition should move the window to the correct absolute position regardless of which screen it's currently on.
Suggested Fix
windowSetPosition should determine which screen the target (x, y) belongs to, rather than using [window screen]. For example:
void windowSetPosition(void* nsWindow, int x, int y) {
WebviewWindow* window = (WebviewWindow*)nsWindow;
NSScreen* screen = [window screen];
if (screen == NULL) {
screen = [NSScreen mainScreen];
}
CGFloat scale = [screen backingScaleFactor];
// Convert target point to NSScreen coordinates to find the target screen
CGFloat targetX = x / scale;
CGFloat targetY = (screen.frame.size.height - 1) - (y / scale); // approximate
NSPoint target = NSMakePoint(targetX, targetY);
// Find which screen the target point belongs to
for (NSScreen *s in [NSScreen screens]) {
if (NSMouseInRect(target, [s frame], NO)) {
screen = s;
break;
}
}
NSRect frame = [window frame];
frame.origin.x = x / scale;
frame.origin.y = (screen.frame.size.height - frame.size.height) - (y / scale);
[window setFrame:frame display:YES];
}
(This is a rough sketch — the exact conversion depends on how Wails defines its coordinate system for multi-screen setups.)
Workaround
I bypassed Wails' SetPosition entirely by using NativeWindow() to get the NSWindow* pointer and calling [window setFrameOrigin:] directly with native macOS coordinates:
// Go side
nw := w.NativeWindow()
winW, winH := w.Size()
centerWindowOnActiveScreen(nw, winW, winH)
// Objective-C via cgo
int centerWindowOnMouseScreen(void* nsWindow, int winWidth, int winHeight) {
NSPoint mouse = [NSEvent mouseLocation];
for (NSScreen *s in [NSScreen screens]) {
if (NSMouseInRect(mouse, [s frame], NO)) {
NSRect wa = [s visibleFrame];
CGFloat x = wa.origin.x + (wa.size.width - winWidth) / 2.0;
CGFloat y = wa.origin.y + (wa.size.height - winHeight) / 2.0;
dispatch_async(dispatch_get_main_queue(), ^{
[(NSWindow *)nsWindow setFrameOrigin:NSMakePoint(x, y)];
});
return 1;
}
}
return 0;
}
Environment
- Wails v3.0.0-alpha.74
- macOS 26.4 (arm64)
- Go 1.25.4
- Setup: MacBook built-in display + external monitor stacked vertically
Related Issues
Description
SetPosition()on macOS cannot reliably move a window from one screen to another. The Y-coordinate conversion inwindowSetPositionuses[window screen](the screen the window is currently on) rather than determining which screen the target coordinates belong to.This means if a window is on Screen A and you call
SetPositionwith coordinates intended for Screen B, the Y-axis conversion uses Screen A's height, placing the window at the wrong location.Root Cause
In
pkg/application/webview_window_darwin.go(lines 627-641):The same issue exists in
windowGetPosition(lines 612-625) — both use[window screen]for conversion, so coordinates are always relative to the current screen rather than absolute.Steps to Reproduce
SetPosition(x, y)with coordinates that should place the window on the external monitorExpected Behavior
SetPositionshould move the window to the correct absolute position regardless of which screen it's currently on.Suggested Fix
windowSetPositionshould determine which screen the target(x, y)belongs to, rather than using[window screen]. For example:(This is a rough sketch — the exact conversion depends on how Wails defines its coordinate system for multi-screen setups.)
Workaround
I bypassed Wails'
SetPositionentirely by usingNativeWindow()to get theNSWindow*pointer and calling[window setFrameOrigin:]directly with native macOS coordinates:Environment
Related Issues
ScreenstructPosition()andSetPosition(), but didn't address cross-screen moves