diff --git a/v3/STATUS.md b/v3/STATUS.md index 0a0a9d687..5ed7c2dba 100644 --- a/v3/STATUS.md +++ b/v3/STATUS.md @@ -31,15 +31,14 @@ Webview Window Interface Methods | center() | Y | | Y | | | close() | | | Y | | | destroy() | | | Y | | -| disableSizeConstraints() | | | Y | | | execJS(js string) | | | Y | | | forceReload() | | | Y | | -| fullscreen() | | | Y | | +| fullscreen() | Y | | Y | | | getScreen() (*Screen, error) | | | Y | | | getZoom() float64 | | | Y | | | height() int | Y | | Y | | | hide() | Y | | Y | | -| isFullscreen() bool | | | Y | | +| isFullscreen() bool | Y | | Y | | | isMaximised() bool | Y | | Y | | | isMinimised() bool | Y | | Y | | | maximise() | Y | | Y | | @@ -64,9 +63,9 @@ Webview Window Interface Methods | setURL(url string) | | | Y | | | setZoom(zoom float64) | | | Y | | | show() | Y | | Y | | -| size() (int, int) | | | Y | | +| size() (int, int) | Y | | Y | | | toggleDevTools() | | | Y | | -| unfullscreen() | | | Y | | +| unfullscreen() | Y | | Y | | | unmaximise() | Y | | Y | | | unminimise() | Y | | Y | | | width() int | Y | | Y | | diff --git a/v3/pkg/application/application.go b/v3/pkg/application/application.go index 08f52aaf5..8fb8152ed 100644 --- a/v3/pkg/application/application.go +++ b/v3/pkg/application/application.go @@ -614,3 +614,35 @@ func (a *App) GetWindowByName(name string) *WebviewWindow { } return nil } + +func invokeSync(fn func()) { + var wg sync.WaitGroup + wg.Add(1) + globalApplication.dispatchOnMainThread(func() { + fn() + wg.Done() + }) + wg.Wait() +} + +func invokeSyncWithResult[T any](fn func() T) (res T) { + var wg sync.WaitGroup + wg.Add(1) + globalApplication.dispatchOnMainThread(func() { + res = fn() + wg.Done() + }) + wg.Wait() + return res +} + +func invokeSyncWithResultAndError[T any](fn func() (T, error)) (res T, err error) { + var wg sync.WaitGroup + wg.Add(1) + globalApplication.dispatchOnMainThread(func() { + res, err = fn() + wg.Done() + }) + wg.Wait() + return res, err +} diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index cd7f874e4..1537cd8b3 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -136,7 +136,9 @@ func (w *WebviewWindow) SetTitle(title string) *WebviewWindow { defer w.implLock.RUnlock() w.options.Title = title if w.impl != nil { - w.impl.setTitle(title) + invokeSync(func() { + w.impl.setTitle(title) + }) } return w } @@ -182,7 +184,9 @@ func (w *WebviewWindow) SetSize(width, height int) *WebviewWindow { } if w.impl != nil { - w.impl.setSize(width, height) + invokeSync(func() { + w.impl.setSize(width, height) + }) } return w } @@ -194,14 +198,16 @@ func (w *WebviewWindow) run() { w.implLock.Lock() w.impl = newWindowImpl(w) w.implLock.Unlock() - w.impl.run() + invokeSync(w.impl.run) } // SetAlwaysOnTop sets the window to be always on top. func (w *WebviewWindow) SetAlwaysOnTop(b bool) *WebviewWindow { w.options.AlwaysOnTop = b if w.impl != nil { - w.impl.setAlwaysOnTop(b) + invokeSync(func() { + w.impl.setAlwaysOnTop(b) + }) } return w } @@ -215,7 +221,7 @@ func (w *WebviewWindow) Show() *WebviewWindow { w.run() return w } - w.impl.show() + invokeSync(w.impl.show) return w } @@ -223,7 +229,7 @@ func (w *WebviewWindow) Show() *WebviewWindow { func (w *WebviewWindow) Hide() *WebviewWindow { w.options.Hidden = true if w.impl != nil { - w.impl.hide() + invokeSync(w.impl.hide) } return w } @@ -231,7 +237,9 @@ func (w *WebviewWindow) Hide() *WebviewWindow { func (w *WebviewWindow) SetURL(s string) *WebviewWindow { w.options.URL = s if w.impl != nil { - w.impl.setURL(s) + invokeSync(func() { + w.impl.setURL(s) + }) } return w } @@ -240,7 +248,9 @@ func (w *WebviewWindow) SetURL(s string) *WebviewWindow { func (w *WebviewWindow) SetZoom(magnification float64) *WebviewWindow { w.options.Zoom = magnification if w.impl != nil { - w.impl.setZoom(magnification) + invokeSync(func() { + w.impl.setZoom(magnification) + }) } return w } @@ -248,7 +258,7 @@ func (w *WebviewWindow) SetZoom(magnification float64) *WebviewWindow { // GetZoom returns the current zoom level of the window. func (w *WebviewWindow) GetZoom() float64 { if w.impl != nil { - return w.impl.getZoom() + return invokeSyncWithResult(w.impl.getZoom) } return 1 } @@ -257,7 +267,9 @@ func (w *WebviewWindow) GetZoom() float64 { func (w *WebviewWindow) SetResizable(b bool) *WebviewWindow { w.options.DisableResize = !b if w.impl != nil { - w.impl.setResizable(b) + invokeSync(func() { + w.impl.setResizable(b) + }) } return w } @@ -288,9 +300,13 @@ func (w *WebviewWindow) SetMinSize(minWidth, minHeight int) *WebviewWindow { } if w.impl != nil { if newSize { - w.impl.setSize(newWidth, newHeight) + invokeSync(func() { + w.impl.setSize(newWidth, newHeight) + }) } - w.impl.setMinSize(minWidth, minHeight) + invokeSync(func() { + w.impl.setMinSize(minWidth, minHeight) + }) } return w } @@ -316,9 +332,13 @@ func (w *WebviewWindow) SetMaxSize(maxWidth, maxHeight int) *WebviewWindow { } if w.impl != nil { if newSize { - w.impl.setSize(newWidth, newHeight) + invokeSync(func() { + w.impl.setSize(newWidth, newHeight) + }) } - w.impl.setMaxSize(maxWidth, maxHeight) + invokeSync(func() { + w.impl.setMaxSize(maxWidth, maxHeight) + }) } return w } @@ -339,7 +359,7 @@ func (w *WebviewWindow) Fullscreen() *WebviewWindow { } if !w.IsFullscreen() { w.disableSizeConstraints() - w.impl.fullscreen() + invokeSync(w.impl.fullscreen) } return w } @@ -347,7 +367,9 @@ func (w *WebviewWindow) Fullscreen() *WebviewWindow { func (w *WebviewWindow) SetFullscreenButtonEnabled(enabled bool) *WebviewWindow { w.options.FullscreenButtonEnabled = enabled if w.impl != nil { - w.impl.setFullscreenButtonEnabled(enabled) + invokeSync(func() { + w.impl.setFullscreenButtonEnabled(enabled) + }) } return w } @@ -357,7 +379,7 @@ func (w *WebviewWindow) IsMinimised() bool { if w.impl == nil { return false } - return w.impl.isMinimised() + return invokeSyncWithResult(w.impl.isMinimised) } // IsVisible returns true if the window is visible @@ -365,7 +387,7 @@ func (w *WebviewWindow) IsVisible() bool { if w.impl == nil { return false } - return w.impl.isVisible() + return invokeSyncWithResult(w.impl.isVisible) } // IsMaximised returns true if the window is maximised @@ -373,15 +395,19 @@ func (w *WebviewWindow) IsMaximised() bool { if w.impl == nil { return false } - return w.impl.isMaximised() + return invokeSyncWithResult(w.impl.isMaximised) } // Size returns the size of the window -func (w *WebviewWindow) Size() (width int, height int) { +func (w *WebviewWindow) Size() (int, int) { if w.impl == nil { return 0, 0 } - return w.impl.size() + var width, height int + invokeSync(func() { + width, height = w.impl.size() + }) + return width, height } // IsFullscreen returns true if the window is fullscreen @@ -391,14 +417,16 @@ func (w *WebviewWindow) IsFullscreen() bool { if w.impl == nil { return false } - return w.impl.isFullscreen() + return invokeSyncWithResult(w.impl.isFullscreen) } // SetBackgroundColour sets the background colour of the window func (w *WebviewWindow) SetBackgroundColour(colour RGBA) *WebviewWindow { w.options.BackgroundColour = colour if w.impl != nil { - w.impl.setBackgroundColour(colour) + invokeSync(func() { + w.impl.setBackgroundColour(colour) + }) } return w } @@ -407,7 +435,9 @@ func (w *WebviewWindow) handleMessage(message string) { w.info(message) // Check for special messages if message == "test" { - w.SetTitle("Hello World") + invokeSync(func() { + w.SetTitle("Hello World") + }) } w.info("ProcessMessage from front end:", message) @@ -418,7 +448,7 @@ func (w *WebviewWindow) Center() { if w.impl == nil { return } - w.impl.center() + invokeSync(w.impl.center) } // On registers a callback for the given window event @@ -455,7 +485,7 @@ func (w *WebviewWindow) Width() int { if w.impl == nil { return 0 } - return w.impl.width() + return invokeSyncWithResult(w.impl.width) } // Height returns the height of the window @@ -463,7 +493,7 @@ func (w *WebviewWindow) Height() int { if w.impl == nil { return 0 } - return w.impl.height() + return invokeSyncWithResult(w.impl.height) } // Position returns the position of the window @@ -473,7 +503,11 @@ func (w *WebviewWindow) Position() (int, int) { if w.impl == nil { return 0, 0 } - return w.impl.position() + var x, y int + invokeSync(func() { + x, y = w.impl.position() + }) + return x, y } func (w *WebviewWindow) Destroy() { @@ -484,7 +518,7 @@ func (w *WebviewWindow) Destroy() { for _, cancelFunc := range w.cancellers { cancelFunc() } - w.impl.destroy() + invokeSync(w.impl.destroy) } // Reload reloads the page assets @@ -492,7 +526,7 @@ func (w *WebviewWindow) Reload() { if w.impl == nil { return } - w.impl.reload() + invokeSync(w.impl.reload) } // ForceReload forces the window to reload the page assets @@ -500,7 +534,7 @@ func (w *WebviewWindow) ForceReload() { if w.impl == nil { return } - w.impl.forceReload() + invokeSync(w.impl.forceReload) } // ToggleFullscreen toggles the window between fullscreen and normal @@ -508,24 +542,26 @@ func (w *WebviewWindow) ToggleFullscreen() { if w.impl == nil { return } - if w.IsFullscreen() { - w.UnFullscreen() - } else { - w.Fullscreen() - } + invokeSync(func() { + if w.IsFullscreen() { + w.UnFullscreen() + } else { + w.Fullscreen() + } + }) } func (w *WebviewWindow) ToggleDevTools() { if w.impl == nil { return } - w.impl.toggleDevTools() + invokeSync(w.impl.toggleDevTools) } // ZoomReset resets the zoom level of the webview content to 100% func (w *WebviewWindow) ZoomReset() *WebviewWindow { if w.impl != nil { - w.impl.zoomReset() + invokeSync(w.impl.zoomReset) } return w @@ -536,7 +572,7 @@ func (w *WebviewWindow) ZoomIn() { if w.impl == nil { return } - w.impl.zoomIn() + invokeSync(w.impl.zoomIn) } // ZoomOut decreases the zoom level of the webview content @@ -544,7 +580,7 @@ func (w *WebviewWindow) ZoomOut() { if w.impl == nil { return } - w.impl.zoomOut() + invokeSync(w.impl.zoomOut) } // Close closes the window @@ -552,21 +588,23 @@ func (w *WebviewWindow) Close() { if w.impl == nil { return } - w.impl.close() + invokeSync(w.impl.close) } func (w *WebviewWindow) Zoom() { if w.impl == nil { return } - w.impl.zoom() + invokeSync(w.impl.zoom) } // SetHTML sets the HTML of the window to the given html string. func (w *WebviewWindow) SetHTML(html string) *WebviewWindow { w.options.HTML = html if w.impl != nil { - w.impl.setHTML(html) + invokeSync(func() { + w.impl.setHTML(html) + }) } return w } @@ -576,7 +614,9 @@ func (w *WebviewWindow) SetPosition(x, y int) *WebviewWindow { w.options.X = x w.options.Y = y if w.impl != nil { - w.impl.setPosition(x, y) + invokeSync(func() { + w.impl.setPosition(x, y) + }) } return w } @@ -588,7 +628,7 @@ func (w *WebviewWindow) Minimise() *WebviewWindow { return w } if !w.IsMinimised() { - w.impl.minimise() + invokeSync(w.impl.minimise) } return w } @@ -601,7 +641,7 @@ func (w *WebviewWindow) Maximise() *WebviewWindow { } if !w.IsMaximised() { w.disableSizeConstraints() - w.impl.maximise() + invokeSync(w.impl.maximise) } return w } @@ -612,7 +652,7 @@ func (w *WebviewWindow) UnMinimise() { return } if w.IsMinimised() { - w.impl.unminimise() + invokeSync(w.impl.unminimise) } } @@ -623,7 +663,7 @@ func (w *WebviewWindow) UnMaximise() { } if w.IsMaximised() { w.enableSizeConstraints() - w.impl.unmaximise() + invokeSync(w.impl.unmaximise) } } @@ -634,7 +674,7 @@ func (w *WebviewWindow) UnFullscreen() { } if w.IsFullscreen() { w.enableSizeConstraints() - w.impl.unfullscreen() + invokeSync(w.impl.unfullscreen) } } @@ -643,37 +683,43 @@ func (w *WebviewWindow) Restore() { if w.impl == nil { return } - if w.IsMinimised() { - w.UnMinimise() - } else if w.IsMaximised() { - w.UnMaximise() - } else if w.IsFullscreen() { - w.UnFullscreen() - } + invokeSync(func() { + if w.IsMinimised() { + w.UnMinimise() + } else if w.IsMaximised() { + w.UnMaximise() + } else if w.IsFullscreen() { + w.UnFullscreen() + } + }) } func (w *WebviewWindow) disableSizeConstraints() { if w.impl == nil { return } - if w.options.MinWidth > 0 && w.options.MinHeight > 0 { - w.impl.setMinSize(0, 0) - } - if w.options.MaxWidth > 0 && w.options.MaxHeight > 0 { - w.impl.setMaxSize(0, 0) - } + invokeSync(func() { + if w.options.MinWidth > 0 && w.options.MinHeight > 0 { + w.impl.setMinSize(0, 0) + } + if w.options.MaxWidth > 0 && w.options.MaxHeight > 0 { + w.impl.setMaxSize(0, 0) + } + }) } func (w *WebviewWindow) enableSizeConstraints() { if w.impl == nil { return } - if w.options.MinWidth > 0 && w.options.MinHeight > 0 { - w.SetMinSize(w.options.MinWidth, w.options.MinHeight) - } - if w.options.MaxWidth > 0 && w.options.MaxHeight > 0 { - w.SetMaxSize(w.options.MaxWidth, w.options.MaxHeight) - } + invokeSync(func() { + if w.options.MinWidth > 0 && w.options.MinHeight > 0 { + w.SetMinSize(w.options.MinWidth, w.options.MinHeight) + } + if w.options.MaxWidth > 0 && w.options.MaxHeight > 0 { + w.SetMaxSize(w.options.MaxWidth, w.options.MaxHeight) + } + }) } // GetScreen returns the screen that the window is on @@ -681,14 +727,16 @@ func (w *WebviewWindow) GetScreen() (*Screen, error) { if w.impl == nil { return nil, nil } - return w.impl.getScreen() + return invokeSyncWithResultAndError(w.impl.getScreen) } // SetFrameless removes the window frame and title bar func (w *WebviewWindow) SetFrameless(frameless bool) *WebviewWindow { w.options.Frameless = frameless if w.impl != nil { - w.impl.setFrameless(frameless) + invokeSync(func() { + w.impl.setFrameless(frameless) + }) } return w } diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index 671c3d4e5..b820abe9a 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -190,8 +190,8 @@ func (w *windowsWebviewWindow) enableSizeConstraints() { } func (w *windowsWebviewWindow) size() (int, int) { - //TODO implement me - panic("implement me") + rect := w32.GetWindowRect(w.hwnd) + return int(rect.Right - rect.Left), int(rect.Bottom - rect.Top) } func (w *windowsWebviewWindow) setForeground() {