mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-20 19:09:29 +08:00
[v3 application] Fix race conditions between starting a window/systray and starting the application
Make sure a window is never run before the windowCreated hooks have been executed.
This commit is contained in:
parent
7fd627f169
commit
3049773e7f
@ -1,7 +1,6 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v3/pkg/icons"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -9,6 +8,8 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/icons"
|
||||
|
||||
"github.com/samber/lo"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||
@ -40,6 +41,7 @@ func New(appOptions Options) *App {
|
||||
result := &App{
|
||||
options: appOptions,
|
||||
applicationEventListeners: make(map[uint][]*EventListener),
|
||||
windows: make(map[uint]*WebviewWindow),
|
||||
systemTrays: make(map[uint]*SystemTray),
|
||||
log: logger.New(appOptions.Logger.CustomLoggers...),
|
||||
contextMenus: make(map[string]*Menu),
|
||||
@ -119,6 +121,10 @@ type (
|
||||
getPrimaryScreen() (*Screen, error)
|
||||
getScreens() ([]*Screen, error)
|
||||
}
|
||||
|
||||
runnable interface {
|
||||
run()
|
||||
}
|
||||
)
|
||||
|
||||
// Messages sent from javascript get routed here
|
||||
@ -180,7 +186,10 @@ type App struct {
|
||||
menuItemsLock sync.Mutex
|
||||
|
||||
// Running
|
||||
running bool
|
||||
running bool
|
||||
runLock sync.Mutex
|
||||
pendingRun []runnable
|
||||
|
||||
bindings *Bindings
|
||||
plugins *PluginManager
|
||||
|
||||
@ -288,9 +297,7 @@ func (a *App) error(message string, args ...any) {
|
||||
func (a *App) NewWebviewWindowWithOptions(windowOptions WebviewWindowOptions) *WebviewWindow {
|
||||
newWindow := NewWindow(windowOptions)
|
||||
id := newWindow.id
|
||||
if a.windows == nil {
|
||||
a.windows = make(map[uint]*WebviewWindow)
|
||||
}
|
||||
|
||||
a.windowsLock.Lock()
|
||||
a.windows[id] = newWindow
|
||||
a.windowsLock.Unlock()
|
||||
@ -300,9 +307,7 @@ func (a *App) NewWebviewWindowWithOptions(windowOptions WebviewWindowOptions) *W
|
||||
hook(newWindow)
|
||||
}
|
||||
|
||||
if a.running {
|
||||
newWindow.run()
|
||||
}
|
||||
a.runOrDeferToAppRun(newWindow)
|
||||
|
||||
return newWindow
|
||||
}
|
||||
@ -310,13 +315,13 @@ func (a *App) NewWebviewWindowWithOptions(windowOptions WebviewWindowOptions) *W
|
||||
func (a *App) NewSystemTray() *SystemTray {
|
||||
id := a.getSystemTrayID()
|
||||
newSystemTray := NewSystemTray(id)
|
||||
|
||||
a.systemTraysLock.Lock()
|
||||
a.systemTrays[id] = newSystemTray
|
||||
a.systemTraysLock.Unlock()
|
||||
|
||||
if a.running {
|
||||
newSystemTray.Run()
|
||||
}
|
||||
a.runOrDeferToAppRun(newSystemTray)
|
||||
|
||||
return newSystemTray
|
||||
}
|
||||
|
||||
@ -324,7 +329,6 @@ func (a *App) Run() error {
|
||||
a.info("Starting application")
|
||||
a.impl = newPlatformApp(a)
|
||||
|
||||
a.running = true
|
||||
go func() {
|
||||
for {
|
||||
event := <-applicationEvents
|
||||
@ -363,15 +367,15 @@ func (a *App) Run() error {
|
||||
}
|
||||
}()
|
||||
|
||||
// run windows
|
||||
for _, window := range a.windows {
|
||||
go window.run()
|
||||
}
|
||||
a.runLock.Lock()
|
||||
a.running = true
|
||||
|
||||
// run system trays
|
||||
for _, systray := range a.systemTrays {
|
||||
go systray.Run()
|
||||
for _, systray := range a.pendingRun {
|
||||
go systray.run()
|
||||
}
|
||||
a.pendingRun = nil
|
||||
|
||||
a.runLock.Unlock()
|
||||
|
||||
// set the application menu
|
||||
if runtime.GOOS == "darwin" {
|
||||
@ -617,6 +621,19 @@ func (a *App) GetWindowByName(name string) *WebviewWindow {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) runOrDeferToAppRun(r runnable) {
|
||||
a.runLock.Lock()
|
||||
running := a.running
|
||||
if !running {
|
||||
a.pendingRun = append(a.pendingRun, r)
|
||||
}
|
||||
a.runLock.Unlock()
|
||||
|
||||
if running {
|
||||
r.run()
|
||||
}
|
||||
}
|
||||
|
||||
func invokeSync(fn func()) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
@ -67,7 +67,7 @@ func (s *SystemTray) Label() string {
|
||||
return s.label
|
||||
}
|
||||
|
||||
func (s *SystemTray) Run() {
|
||||
func (s *SystemTray) run() {
|
||||
s.impl = newSystemTrayImpl(s)
|
||||
invokeSync(s.impl.run)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user