mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
[v3] Ensure impl calls from WebvieWindow are on the main thread. Support size.
This commit is contained in:
parent
0b3559abfe
commit
66bfcf0e36
4 changed files with 156 additions and 77 deletions
|
|
@ -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 | |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue