[v3] Ensure impl calls from WebvieWindow are on the main thread. Support size.

This commit is contained in:
Lea Anthony 2023-05-01 20:28:46 +10:00 committed by Misite Bao
commit 66bfcf0e36
4 changed files with 156 additions and 77 deletions

View file

@ -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 | |

View file

@ -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
}

View file

@ -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
}

View file

@ -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() {