diff --git a/v3/examples/window/main.go b/v3/examples/window/main.go index 95f0c603e..5bc59a38b 100644 --- a/v3/examples/window/main.go +++ b/v3/examples/window/main.go @@ -203,6 +203,25 @@ func main() { }) }) + positionMenu.Add("Set Absolute Position (0,0)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetAbsolutePosition(0, 0) + }) + }) + + positionMenu.Add("Set Absolute Position (Random)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetAbsolutePosition(rand.Intn(1000), rand.Intn(800)) + }) + }) + + positionMenu.Add("Get Absolute Position").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + x, y := w.AbsolutePosition() + app.InfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() + }) + }) + positionMenu.Add("Center").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { w.Center() diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index b5f887e42..857787f27 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -68,6 +68,8 @@ type ( startResize(border string) error print() error setEnabled(enabled bool) + absolutePosition() (int, int) + setAbsolutePosition(x int, y int) } ) @@ -586,6 +588,18 @@ func (w *WebviewWindow) RelativePosition() (int, int) { return x, y } +// AbsolutePosition returns the absolute position of the window to the screen +func (w *WebviewWindow) AbsolutePosition() (int, int) { + if w.impl == nil { + return 0, 0 + } + var x, y int + invokeSync(func() { + x, y = w.impl.absolutePosition() + }) + return x, y +} + func (w *WebviewWindow) Destroy() { if w.impl == nil { return @@ -932,3 +946,13 @@ func (w *WebviewWindow) SetEnabled(enabled bool) { w.impl.setEnabled(enabled) }) } + +func (w *WebviewWindow) SetAbsolutePosition(x int, y int) { + // set absolute position + if w.impl == nil { + return + } + invokeSync(func() { + w.impl.setAbsolutePosition(x, y) + }) +} diff --git a/v3/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go index d41626d07..34841bbad 100644 --- a/v3/pkg/application/webview_window_darwin.go +++ b/v3/pkg/application/webview_window_darwin.go @@ -278,7 +278,7 @@ void windowZoomOut(void* nsWindow) { } // set the window position relative to the screen -void windowSetrelativePosition(void* nsWindow, int x, int y) { +void windowSetRelativePosition(void* nsWindow, int x, int y) { WebviewWindow* window = (WebviewWindow*)nsWindow; NSScreen* screen = [window screen]; if( screen == NULL ) { @@ -492,7 +492,7 @@ int windowGetHeight(void* nsWindow) { } // Get window position -void windowGetPosition(void* nsWindow, int* x, int* y) { +void windowGetRelativePosition(void* nsWindow, int* x, int* y) { WebviewWindow* window = (WebviewWindow*)nsWindow; NSRect frame = [window frame]; *x = frame.origin.x; @@ -506,6 +506,20 @@ void windowGetPosition(void* nsWindow, int* x, int* y) { *y = screenFrame.size.height - frame.origin.y - frame.size.height; } +// Get absolute window position +void windowGetAbsolutePosition(void* nsWindow, int* x, int* y) { + NSRect frame = [(WebviewWindow*)nsWindow frame]; + *x = frame.origin.x; + *y = frame.origin.y; +} + +void windowSetAbsolutePosition(void* nsWindow, int x, int y) { + NSRect frame = [(WebviewWindow*)nsWindow frame]; + frame.origin.x = x; + frame.origin.y = y; + [(WebviewWindow*)nsWindow setFrame:frame display:YES]; +} + // Destroy window void windowDestroy(void* nsWindow) { [(WebviewWindow*)nsWindow close]; @@ -942,9 +956,12 @@ func (w *macosWebviewWindow) size() (int, int) { } func (w *macosWebviewWindow) setRelativePosition(x, y int) { - C.windowSetrelativePosition(w.nsWindow, C.int(x), C.int(y)) + C.windowSetRelativePosition(w.nsWindow, C.int(x), C.int(y)) } +func (w *macosWebviewWindow) setRelativePosition(x, y int) { + C.windowSetAbsolutePosition(w.nsWindow, C.int(x), C.int(y)) +} func (w *macosWebviewWindow) width() int { var width C.int var wg sync.WaitGroup @@ -1080,10 +1097,19 @@ func (w *macosWebviewWindow) setBackgroundColour(colour RGBA) { C.windowSetBackgroundColour(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha)) } -func (w *macosWebviewWindow) position() (int, int) { +func (w *macosWebviewWindow) relativePosition() (int, int) { var x, y C.int invokeSync(func() { - C.windowGetPosition(w.nsWindow, &x, &y) + C.windowGetRelativePosition(w.nsWindow, &x, &y) + }) + + return int(x), int(y) +} + +func (w *macosWebviewWindow) absolutePosition() (int, int) { + var x, y C.int + invokeSync(func() { + C.windowGetAbsolutePosition(w.nsWindow, &x, &y) }) return int(x), int(y) diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index d82a56471..7cc9843f0 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -630,6 +630,18 @@ func (w *linuxWebviewWindow) height() int { return height } +func (w *linuxWebviewWindow) absolutePosition() (int, int) { + var x, y C.int + var wg sync.WaitGroup + wg.Add(1) + globalApplication.dispatchOnMainThread(func() { + C.gtk_window_get_position((*C.GtkWindow)(w.window), &x, &y) + wg.Done() + }) + wg.Wait() + return int(x), int(y) +} + func (w *linuxWebviewWindow) run() { for eventId := range w.parent.eventListeners { w.on(eventId) @@ -738,12 +750,24 @@ func (w *linuxWebviewWindow) setBackgroundColour(colour RGBA) { C.webkit_web_view_set_background_color((*C.WebKitWebView)(w.webview), &rgba) } -func (w *linuxWebviewWindow) position() (int, int) { +func (w *linuxWebviewWindow) relativePosition() (int, int) { var x, y C.int var wg sync.WaitGroup wg.Add(1) go globalApplication.dispatchOnMainThread(func() { C.gtk_window_get_position((*C.GtkWindow)(w.window), &x, &y) + + // The position must be relative to the screen it is on + // We need to get the screen it is on + screen := C.gtk_widget_get_screen((*C.GtkWidget)(w.window)) + monitor := C.gdk_screen_get_monitor_at_window(screen, (*C.GdkWindow)(w.window)) + geometry := C.GdkRectangle{} + C.gdk_screen_get_monitor_geometry(screen, monitor, &geometry) + x = x - geometry.x + y = y - geometry.y + + // TODO: Scale based on DPI + wg.Done() }) wg.Wait() diff --git a/v3/pkg/application/webview_window_linux_purego.go b/v3/pkg/application/webview_window_linux_purego.go index c3f5381c4..fa9ff9f57 100644 --- a/v3/pkg/application/webview_window_linux_purego.go +++ b/v3/pkg/application/webview_window_linux_purego.go @@ -706,6 +706,27 @@ func (w *linuxWebviewWindow) relativePosition() (int, int) { wg.Add(1) go globalApplication.dispatchOnMainThread(func() { getPosition(w.window, &x, &y) + + // Get the position of the window relative to the screen + var getOrigin func(uintptr, *int, *int) + purego.RegisterLibFunc(&getOrigin, gtk, "gtk_widget_translate_coordinates") + getOrigin(w.window, &x, &y) + + wg.Done() + }) + wg.Wait() + return x, y +} + +func (w *linuxWebviewWindow) absolutePosition() (int, int) { + var getOrigin func(uintptr, *int, *int) + purego.RegisterLibFunc(&getOrigin, gtk, "gtk_widget_translate_coordinates") + + var x, y int + var wg sync.WaitGroup + wg.Add(1) + go globalApplication.dispatchOnMainThread(func() { + getOrigin(w.window, nil, nil) wg.Done() }) wg.Wait() diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index 4bb9b686d..f4f9a4bfc 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -63,6 +63,17 @@ type windowsWebviewWindow struct { resizeBorderHeight int32 } +func (w *windowsWebviewWindow) setAbsolutePosition(x int, y int) { + // Set the window's absolute position + w32.SetWindowPos(w.hwnd, 0, x, y, 0, 0, w32.SWP_NOSIZE|w32.SWP_NOZORDER) +} + +func (w *windowsWebviewWindow) absolutePosition() (int, int) { + rect := w32.GetWindowRect(w.hwnd) + left, right := w.scaleToDefaultDPI(int(rect.Left), int(rect.Right)) + return left, right +} + func (w *windowsWebviewWindow) setEnabled(enabled bool) { w32.EnableWindow(w.hwnd, enabled) } @@ -335,9 +346,20 @@ func (w *windowsWebviewWindow) height() int { } func (w *windowsWebviewWindow) relativePosition() (int, int) { + // Get monitor for window + monitor := w32.MonitorFromWindow(w.hwnd, w32.MONITOR_DEFAULTTONEAREST) + var monitorInfo w32.MONITORINFO + monitorInfo.CbSize = uint32(unsafe.Sizeof(monitorInfo)) + w32.GetMonitorInfo(monitor, &monitorInfo) + + // Get window rect rect := w32.GetWindowRect(w.hwnd) - left, right := w.scaleToDefaultDPI(int(rect.Left), int(rect.Right)) - return left, right + + // Calculate relative position + x := int(rect.Left) - int(monitorInfo.RcWork.Left) + y := int(rect.Top) - int(monitorInfo.RcWork.Top) + + return w.scaleToDefaultDPI(x, y) } func (w *windowsWebviewWindow) destroy() {