From 65f95b038091d9d0a3ed63c3025ed27cfdba6282 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 23 Dec 2024 08:23:07 +1100 Subject: [PATCH] Removed OnShouldClose: Create single way of handling conditional and unconditional close. --- v3/examples/hide-window/main.go | 15 ++++--- v3/examples/systray-basic/main.go | 10 +++-- v3/examples/systray-custom/main.go | 10 +++-- v3/examples/systray-menu/main.go | 10 +++-- v3/examples/window/main.go | 40 +++++++++---------- .../commands/appimage_testfiles/main.go | 36 +++++++---------- .../desktop/@wailsio/runtime/package.json | 2 +- .../@wailsio/runtime/src/event_types.js | 2 +- .../@wailsio/runtime/types/event_types.d.ts | 2 +- v3/pkg/application/webview_window.go | 30 +++++++++----- v3/pkg/application/webview_window_darwin.go | 1 + v3/pkg/application/webview_window_options.go | 4 -- v3/pkg/application/webview_window_windows.go | 22 +++++++--- v3/pkg/events/defaults.go | 2 +- v3/pkg/events/events.go | 6 +-- v3/pkg/events/events.txt | 2 +- 16 files changed, 105 insertions(+), 89 deletions(-) diff --git a/v3/examples/hide-window/main.go b/v3/examples/hide-window/main.go index a78fb2d17..df89c7d4a 100644 --- a/v3/examples/hide-window/main.go +++ b/v3/examples/hide-window/main.go @@ -2,12 +2,11 @@ package main import ( _ "embed" - "log" - "runtime" - "github.com/wailsapp/wails/v3/pkg/application" "github.com/wailsapp/wails/v3/pkg/events" "github.com/wailsapp/wails/v3/pkg/icons" + "log" + "runtime" ) func main() { @@ -29,16 +28,16 @@ func main() { AlwaysOnTop: false, Hidden: false, DisableResize: false, - ShouldClose: func(window *application.WebviewWindow) bool { - println("close") - window.Hide() - return false - }, Windows: application.WindowsWindow{ HiddenOnTaskbar: true, }, }) + window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { + window.Hide() + e.Cancel() + }) + if runtime.GOOS == "darwin" { systemTray.SetTemplateIcon(icons.SystrayMacTemplate) } diff --git a/v3/examples/systray-basic/main.go b/v3/examples/systray-basic/main.go index 33448a27f..7a33d08e5 100644 --- a/v3/examples/systray-basic/main.go +++ b/v3/examples/systray-basic/main.go @@ -2,6 +2,7 @@ package main import ( _ "embed" + "github.com/wailsapp/wails/v3/pkg/events" "log" "runtime" @@ -29,10 +30,6 @@ func main() { AlwaysOnTop: true, Hidden: true, DisableResize: true, - ShouldClose: func(window *application.WebviewWindow) bool { - window.Hide() - return false - }, Windows: application.WindowsWindow{ HiddenOnTaskbar: true, }, @@ -43,6 +40,11 @@ func main() { }, }) + window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { + window.Hide() + e.Cancel() + }) + if runtime.GOOS == "darwin" { systemTray.SetTemplateIcon(icons.SystrayMacTemplate) } diff --git a/v3/examples/systray-custom/main.go b/v3/examples/systray-custom/main.go index b248cb00d..256c65c84 100644 --- a/v3/examples/systray-custom/main.go +++ b/v3/examples/systray-custom/main.go @@ -2,6 +2,7 @@ package main import ( _ "embed" + "github.com/wailsapp/wails/v3/pkg/events" "log" "runtime" @@ -29,15 +30,16 @@ func main() { AlwaysOnTop: true, Hidden: true, DisableResize: true, - ShouldClose: func(window *application.WebviewWindow) bool { - window.Hide() - return false - }, Windows: application.WindowsWindow{ HiddenOnTaskbar: true, }, }) + window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { + window.Hide() + e.Cancel() + }) + if runtime.GOOS == "darwin" { systemTray.SetTemplateIcon(icons.SystrayMacTemplate) } diff --git a/v3/examples/systray-menu/main.go b/v3/examples/systray-menu/main.go index 1dcb2d38c..4195d1fd4 100644 --- a/v3/examples/systray-menu/main.go +++ b/v3/examples/systray-menu/main.go @@ -2,6 +2,7 @@ package main import ( _ "embed" + "github.com/wailsapp/wails/v3/pkg/events" "log" "runtime" @@ -29,10 +30,6 @@ func main() { AlwaysOnTop: true, Hidden: true, DisableResize: true, - ShouldClose: func(window *application.WebviewWindow) bool { - window.Hide() - return false - }, Windows: application.WindowsWindow{ HiddenOnTaskbar: true, }, @@ -43,6 +40,11 @@ func main() { }, }) + window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { + window.Hide() + e.Cancel() + }) + if runtime.GOOS == "darwin" { systemTray.SetTemplateIcon(icons.SystrayMacTemplate) } diff --git a/v3/examples/window/main.go b/v3/examples/window/main.go index a0c3ceda9..6d5512cec 100644 --- a/v3/examples/window/main.go +++ b/v3/examples/window/main.go @@ -283,31 +283,29 @@ func main() { myMenu.Add("New WebviewWindow (Hides on Close one time)"). SetAccelerator("CmdOrCtrl+H"). OnClick(func(ctx *application.Context) { - app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ - // This will be called when the user clicks the close button - // on the window. It will hide the window for 5 seconds. - // If the user clicks the close button again, the window will - // close. - ShouldClose: func(window *application.WebviewWindow) bool { - if !lo.Contains(hiddenWindows, window) { - hiddenWindows = append(hiddenWindows, window) - go func() { - time.Sleep(5 * time.Second) - window.Show() - }() - window.Hide() - return false - } - // Remove the window from the hiddenWindows list - hiddenWindows = lo.Without(hiddenWindows, window) - return true - }, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). + w := app.NewWebviewWindow() + + w.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { + if !lo.Contains(hiddenWindows, w) { + hiddenWindows = append(hiddenWindows, w) + go func() { + time.Sleep(5 * time.Second) + w.Show() + }() + w.Hide() + e.Cancel() + } + // Remove the window from the hiddenWindows list + hiddenWindows = lo.Without(hiddenWindows, w) + }) + + w.SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). SetRelativePosition(rand.Intn(1000), rand.Intn(800)). SetURL("https://wails.io"). Show() + windowCounter++ + }) myMenu.Add("New WebviewWindow (Frameless)"). SetAccelerator("CmdOrCtrl+F"). diff --git a/v3/internal/commands/appimage_testfiles/main.go b/v3/internal/commands/appimage_testfiles/main.go index e63f9f4d5..2688d2c33 100644 --- a/v3/internal/commands/appimage_testfiles/main.go +++ b/v3/internal/commands/appimage_testfiles/main.go @@ -60,27 +60,21 @@ func main() { myMenu.Add("New WebviewWindow (Hides on Close one time)"). SetAccelerator("CmdOrCtrl+H"). OnClick(func(ctx *application.Context) { - app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ - // This will be called when the user clicks the close button - // on the window. It will hide the window for 5 seconds. - // If the user clicks the close button again, the window will - // close. - ShouldClose: func(window *application.WebviewWindow) bool { - if !lo.Contains(hiddenWindows, window) { - hiddenWindows = append(hiddenWindows, window) - go func() { - time.Sleep(5 * time.Second) - window.Show() - }() - window.Hide() - return false - } - // Remove the window from the hiddenWindows list - hiddenWindows = lo.Without(hiddenWindows, window) - return true - }, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). + w := app.NewWebviewWindow() + w.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { + if !lo.Contains(hiddenWindows, w) { + hiddenWindows = append(hiddenWindows, w) + go func() { + time.Sleep(5 * time.Second) + w.Show() + }() + w.Hide() + e.Cancel() + } + // Remove the window from the hiddenWindows list + hiddenWindows = lo.Without(hiddenWindows, w) + }) + w.SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). SetRelativePosition(rand.Intn(1000), rand.Intn(800)). SetURL("https://wails.io"). Show() diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/package.json b/v3/internal/runtime/desktop/@wailsio/runtime/package.json index 86782696c..4c909126b 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/package.json +++ b/v3/internal/runtime/desktop/@wailsio/runtime/package.json @@ -1,7 +1,7 @@ { "name": "@wailsio/runtime", "type": "module", - "version": "3.0.0-alpha.34", + "version": "3.0.0-alpha.35", "description": "Wails Runtime", "types": "types/index.d.ts", "exports": { diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js b/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js index 0d98a52d3..eea9aed8b 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js +++ b/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js @@ -19,7 +19,7 @@ export const EventTypes = { WindowRestore: "windows:WindowRestore", WindowMinimise: "windows:WindowMinimise", WindowUnMinimise: "windows:WindowUnMinimise", - WindowClose: "windows:WindowClose", + WindowClosing: "windows:WindowClosing", WindowSetFocus: "windows:WindowSetFocus", WindowKillFocus: "windows:WindowKillFocus", WindowDragDrop: "windows:WindowDragDrop", diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts b/v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts index ebafefb67..9c90df3d4 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts +++ b/v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts @@ -19,7 +19,7 @@ export declare const EventTypes: { WindowRestore: string, WindowMinimise: string, WindowUnMinimise: string, - WindowClose: string, + WindowClosing: string, WindowSetFocus: string, WindowKillFocus: string, WindowDragDrop: string, diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index 2ea543579..4e9406bcf 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -162,6 +162,9 @@ type WebviewWindow struct { runtimeLoaded bool // pendingJS holds JS that was sent to the window before the runtime was loaded pendingJS []string + + // unconditionallyClose marks the window to be unconditionally closed + unconditionallyClose bool } // EmitEvent emits an event from the window @@ -250,15 +253,10 @@ func NewWindow(options WebviewWindowOptions) *WebviewWindow { // Listen for window closing events and de result.OnWindowEvent(events.Common.WindowClosing, func(event *WindowEvent) { - shouldClose := true - if result.options.ShouldClose != nil { - shouldClose = result.options.ShouldClose(result) - } - if shouldClose { - result.markAsDestroyed() - InvokeSync(result.impl.close) - globalApplication.deleteWindowByID(result.id) - } + result.unconditionallyClose = true + result.markAsDestroyed() + InvokeSync(result.impl.close) + globalApplication.deleteWindowByID(result.id) }) // Process keybindings @@ -395,6 +393,7 @@ func (w *WebviewWindow) Run() { return } w.impl = newWindowImpl(w) + InvokeSync(w.impl.run) } @@ -991,7 +990,12 @@ func (w *WebviewWindow) ZoomOut() { // Close closes the window func (w *WebviewWindow) Close() { - // NOOP? + if w.impl == nil && !w.isDestroyed() { + return + } + InvokeAsync(func() { + w.emit(events.Common.WindowClosing) + }) } func (w *WebviewWindow) Zoom() { @@ -1337,3 +1341,9 @@ func (w *WebviewWindow) delete() { w.impl.delete() } } + +func (w *WebviewWindow) redo() { + if w.impl == nil && !w.isDestroyed() { + w.impl.redo() + } +} diff --git a/v3/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go index bea282f0b..1c855f749 100644 --- a/v3/pkg/application/webview_window_darwin.go +++ b/v3/pkg/application/webview_window_darwin.go @@ -956,6 +956,7 @@ func (w *macosWebviewWindow) windowZoom() { func (w *macosWebviewWindow) close() { C.windowClose(w.nsWindow) + // TODO: Check if we need to unregister the window here or not } func (w *macosWebviewWindow) zoomIn() { diff --git a/v3/pkg/application/webview_window_options.go b/v3/pkg/application/webview_window_options.go index 8b7c3a520..ddb8d41e1 100644 --- a/v3/pkg/application/webview_window_options.go +++ b/v3/pkg/application/webview_window_options.go @@ -128,10 +128,6 @@ type WebviewWindowOptions struct { MaximiseButtonState ButtonState CloseButtonState ButtonState - // ShouldClose is called when the window is about to close. - // Return true to allow the window to close, or false to prevent it from closing. - ShouldClose func(window *WebviewWindow) bool - // If true, the window's devtools will be available (default true in builds without the `production` build tag) DevToolsEnabled bool diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index e57c4ecab..ed9d55561 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -577,9 +577,7 @@ func (w *windowsWebviewWindow) setZoom(zoom float64) { } func (w *windowsWebviewWindow) close() { - // Unregister the window with the application - windowsApp := globalApplication.impl.(*windowsApp) - windowsApp.unregisterWindow(w) + // Send WM_CLOSE message to trigger the same flow as clicking the X button w32.SendMessage(w.hwnd, w32.WM_CLOSE, 0, 0) } @@ -1033,8 +1031,22 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp } } case w32.WM_CLOSE: - w.parent.emit(events.Windows.WindowClose) - return 0 + + if w.parent.unconditionallyClose == false { + // We were called by `Close()` or pressing the close button on the window + w.parent.emit(events.Windows.WindowClosing) + return 0 + } + + defer func() { + windowsApp := globalApplication.impl.(*windowsApp) + windowsApp.unregisterWindow(w) + + }() + + // Now do the actual close + return w32.DefWindowProc(w.hwnd, w32.WM_CLOSE, 0, 0) + case w32.WM_KILLFOCUS: if w.focusingChromium { return 0 diff --git a/v3/pkg/events/defaults.go b/v3/pkg/events/defaults.go index 24bc118de..0600dc715 100644 --- a/v3/pkg/events/defaults.go +++ b/v3/pkg/events/defaults.go @@ -4,7 +4,7 @@ import "runtime" var defaultWindowEventMapping = map[string]map[WindowEventType]WindowEventType{ "windows": { - Windows.WindowClose: Common.WindowClosing, + Windows.WindowClosing: Common.WindowClosing, Windows.WindowInactive: Common.WindowLostFocus, Windows.WindowClickActive: Common.WindowFocus, Windows.WindowActive: Common.WindowFocus, diff --git a/v3/pkg/events/events.go b/v3/pkg/events/events.go index 17a7cf43e..dc34cb3f6 100644 --- a/v3/pkg/events/events.go +++ b/v3/pkg/events/events.go @@ -374,7 +374,7 @@ type windowsEvents struct { WindowRestore WindowEventType WindowMinimise WindowEventType WindowUnMinimise WindowEventType - WindowClose WindowEventType + WindowClosing WindowEventType WindowSetFocus WindowEventType WindowKillFocus WindowEventType WindowDragDrop WindowEventType @@ -421,7 +421,7 @@ func newWindowsEvents() windowsEvents { WindowRestore: 1175, WindowMinimise: 1176, WindowUnMinimise: 1177, - WindowClose: 1178, + WindowClosing: 1178, WindowSetFocus: 1179, WindowKillFocus: 1180, WindowDragDrop: 1181, @@ -608,7 +608,7 @@ var eventToJS = map[uint]string{ 1175: "windows:WindowRestore", 1176: "windows:WindowMinimise", 1177: "windows:WindowUnMinimise", - 1178: "windows:WindowClose", + 1178: "windows:WindowClosing", 1179: "windows:WindowSetFocus", 1180: "windows:WindowKillFocus", 1181: "windows:WindowDragDrop", diff --git a/v3/pkg/events/events.txt b/v3/pkg/events/events.txt index 724f8c90e..02193852e 100644 --- a/v3/pkg/events/events.txt +++ b/v3/pkg/events/events.txt @@ -152,7 +152,7 @@ windows:WindowUnFullscreen windows:WindowRestore windows:WindowMinimise windows:WindowUnMinimise -windows:WindowClose +windows:WindowClosing windows:WindowSetFocus windows:WindowKillFocus windows:WindowDragDrop