Improve window destroying on Mac

This commit is contained in:
Lea Anthony 2024-12-14 17:56:16 +11:00
commit 957f759197
No known key found for this signature in database
GPG key ID: 33DAF7BB90A58405
3 changed files with 84 additions and 30 deletions

View file

@ -20,10 +20,10 @@ import (
"github.com/wailsapp/wails/v3/internal/operatingsystem"
"github.com/pkg/browser"
"github.com/samber/lo"
"github.com/wailsapp/wails/v3/internal/signal"
"github.com/pkg/browser"
"github.com/samber/lo"
"github.com/wailsapp/wails/v3/internal/assetserver"
"github.com/wailsapp/wails/v3/internal/assetserver/webview"
"github.com/wailsapp/wails/v3/internal/capabilities"
@ -581,45 +581,73 @@ func (a *App) Run() error {
a.impl = newPlatformApp(a)
go func() {
for {
event := <-applicationEvents
go a.handleApplicationEvent(event)
select {
case <-a.ctx.Done():
return
case event := <-applicationEvents:
go a.handleApplicationEvent(event)
}
}
}()
go func() {
for {
event := <-windowEvents
go a.handleWindowEvent(event)
select {
case <-a.ctx.Done():
return
case event := <-windowEvents:
go a.handleWindowEvent(event)
}
}
}()
go func() {
for {
request := <-webviewRequests
go a.handleWebViewRequest(request)
select {
case <-a.ctx.Done():
return
case request := <-webviewRequests:
go a.handleWebViewRequest(request)
}
}
}()
go func() {
for {
event := <-windowMessageBuffer
go a.handleWindowMessage(event)
select {
case <-a.ctx.Done():
return
case event := <-windowMessageBuffer:
go a.handleWindowMessage(event)
}
}
}()
go func() {
for {
event := <-windowKeyEvents
go a.handleWindowKeyEvent(event)
select {
case <-a.ctx.Done():
return
case event := <-windowKeyEvents:
go a.handleWindowKeyEvent(event)
}
}
}()
go func() {
for {
dragAndDropMessage := <-windowDragAndDropBuffer
go a.handleDragAndDropMessage(dragAndDropMessage)
select {
case <-a.ctx.Done():
return
case dragAndDropMessage := <-windowDragAndDropBuffer:
go a.handleDragAndDropMessage(dragAndDropMessage)
}
}
}()
go func() {
for {
select {
case <-a.ctx.Done():
return
case menuItemID := <-menuItemClicked:
go func() {
for {
menuItemID := <-menuItemClicked
go a.handleMenuItemClicked(menuItemID)
go a.handleMenuItemClicked(menuItemID)
}
}
}()
@ -689,12 +717,15 @@ func (a *App) handleApplicationEvent(event *ApplicationEvent) {
}
func (a *App) handleDragAndDropMessage(event *dragAndDropMessage) {
if globalApplication.performingShutdown {
return
}
// Get window from window map
a.windowsLock.Lock()
window, ok := a.windows[event.windowId]
a.windowsLock.Unlock()
if !ok {
log.Printf("WebviewWindow #%d not found", event.windowId)
log.Printf("handleDragAndDropMessage: WebviewWindow #%d not found", event.windowId)
return
}
// Get callback from window
@ -702,12 +733,15 @@ func (a *App) handleDragAndDropMessage(event *dragAndDropMessage) {
}
func (a *App) handleWindowMessage(event *windowMessage) {
if globalApplication.performingShutdown {
return
}
// Get window from window map
a.windowsLock.RLock()
window, ok := a.windows[event.windowId]
a.windowsLock.RUnlock()
if !ok {
log.Printf("WebviewWindow #%d not found", event.windowId)
log.Printf("handleWindowMessage: WebviewWindow #%d not found", event.windowId)
return
}
// Check if the message starts with "wails:"
@ -725,18 +759,27 @@ func (a *App) handleWebViewRequest(request *webViewAssetRequest) {
}
func (a *App) handleWindowEvent(event *windowEvent) {
if globalApplication.performingShutdown {
return
}
// Get window from window map
a.windowsLock.RLock()
window, ok := a.windows[event.WindowID]
a.windowsLock.RUnlock()
if !ok {
log.Printf("Window #%d not found", event.WindowID)
// Window not found - it's probably been destroyed
return
}
// Normal event handling for active windows
window.HandleWindowEvent(event.EventID)
}
func (a *App) handleMenuItemClicked(menuItemID uint) {
if globalApplication.performingShutdown {
return
}
menuItem := getMenuItemByID(menuItemID)
if menuItem == nil {
log.Printf("MenuItem #%d not found", menuItemID)

View file

@ -28,7 +28,7 @@ const (
)
type MessageProcessor struct {
logger *slog.Logger
logger *slog.Logger
runningCalls map[string]context.CancelFunc
l sync.Mutex

View file

@ -110,6 +110,7 @@ type (
type WindowEvent struct {
ctx *WindowEventContext
Cancelled bool
WindowID uint
}
func (w *WindowEvent) Context() *WindowEventContext {
@ -718,7 +719,7 @@ func (w *WebviewWindow) startResize(border string) error {
if w.impl == nil && !w.isDestroyed() {
return nil
}
return InvokeSyncWithResult(func() error {
return InvokeSyncWithError(func() error {
return w.impl.startResize(border)
})
}
@ -770,6 +771,7 @@ func (w *WebviewWindow) RegisterHook(eventType events.WindowEventType, callback
}
func (w *WebviewWindow) HandleWindowEvent(id uint) {
// Get hooks for this event
w.eventListenersLock.RLock()
defer w.eventListenersLock.RUnlock()
@ -780,6 +782,7 @@ func (w *WebviewWindow) HandleWindowEvent(id uint) {
// Create new WindowEvent
thisEvent := NewWindowEvent()
thisEvent.WindowID = w.id
for _, thisHook := range hooks {
thisHook.callback(thisEvent)
@ -905,11 +908,18 @@ func (w *WebviewWindow) Destroy() {
return
}
// Cancel the callbacks
// Mark as being destroyed - this prevents new events from being processed
w.markAsDestroyed()
// Cancel all callbacks
for _, cancelFunc := range w.cancellers {
cancelFunc()
}
// Remove from global application map and destroy the native window
globalApplication.windowsLock.Lock()
delete(globalApplication.windows, w.id)
globalApplication.windowsLock.Unlock()
InvokeSync(w.impl.destroy)
}
@ -1179,6 +1189,7 @@ func (w *WebviewWindow) HandleDragAndDropMessage(filenames []string) {
ctx := newWindowEventContext()
ctx.setDroppedFiles(filenames)
thisEvent.ctx = ctx
thisEvent.WindowID = w.id
for _, listener := range w.eventListeners[uint(events.Common.WindowFilesDropped)] {
listener.callback(thisEvent)
}
@ -1223,13 +1234,6 @@ func (w *WebviewWindow) Focus() {
w.emit(events.Common.WindowFocus)
}
func (w *WebviewWindow) emit(eventType events.WindowEventType) {
windowEvents <- &windowEvent{
WindowID: w.id,
EventID: uint(eventType),
}
}
func (w *WebviewWindow) startDrag() error {
if w.impl == nil && !w.isDestroyed() {
return nil
@ -1358,3 +1362,10 @@ func (w *WebviewWindow) delete() {
w.impl.delete()
}
}
func (w *WebviewWindow) emit(eventType events.WindowEventType) {
windowEvents <- &windowEvent{
WindowID: w.id,
EventID: uint(eventType),
}
}