Add option to prevent application shutdown

This update allows the application shutdown to be cancelled. It implements the shouldQuit function, which can prevent the application from quitting if it returns false. Additional checks have been added to ensure cleanup and quit processes are performed only if required. The darwin delegate and linux and windows applications were modified to include this new functionality.
This commit is contained in:
Lea Anthony
2024-01-17 20:45:30 +11:00
parent ab22ea1f27
commit 861ddea1b2
10 changed files with 66 additions and 18 deletions
+6 -3
View File
@@ -21,7 +21,7 @@ func main() {
Description: "A demo of the WebviewWindow API",
Assets: application.AlphaAssets,
Mac: application.MacOptions{
ApplicationShouldTerminateAfterLastWindowClosed: false,
ApplicationShouldTerminateAfterLastWindowClosed: true,
},
})
app.On(events.Mac.ApplicationDidFinishLaunching, func(event *application.Event) {
@@ -40,8 +40,11 @@ func main() {
// Create a custom menu
menu := app.NewMenu()
menu.AddRole(application.AppMenu)
if runtime.GOOS == "darwin" {
menu.AddRole(application.AppMenu)
} else {
menu.AddRole(application.FileMenu)
}
windowCounter := 1
// Let's make a "Demo" menu
+15 -6
View File
@@ -297,6 +297,7 @@ type App struct {
// Shutdown
performingShutdown bool
// Shutdown tasks are run when the application is shutting down.
// They are run in the order they are added and run on the main thread.
// The application option `OnShutdown` is run first.
@@ -617,12 +618,11 @@ func (a *App) OnShutdown(f func()) {
a.shutdownTasks = append(a.shutdownTasks, f)
}
func (a *App) Quit() {
func (a *App) cleanup() {
if a.performingShutdown {
return
}
a.performingShutdown = true
// Run the shutdown tasks
for _, shutdownTask := range a.shutdownTasks {
InvokeSync(shutdownTask)
}
@@ -639,13 +639,15 @@ func (a *App) Quit() {
}
a.systemTrays = nil
a.systemTraysLock.Unlock()
if a.impl != nil {
a.impl.destroy()
a.impl = nil
}
})
}
func (a *App) Quit() {
if a.impl != nil {
InvokeSync(a.impl.destroy)
}
}
func (a *App) SetIcon(icon []byte) {
if a.impl != nil {
a.impl.setIcon(icon)
@@ -867,3 +869,10 @@ func (a *App) Environment() EnvironmentInfo {
Debug: a.isDebugMode,
}
}
func (a *App) shouldQuit() bool {
if a.options.ShouldQuit != nil {
return a.options.ShouldQuit()
}
return true
}
+9 -3
View File
@@ -334,9 +334,15 @@ func processMenuItemClick(menuID C.uint) {
menuItemClicked <- uint(menuID)
}
//export quitApplication
func quitApplication() {
globalApplication.Quit()
//export shouldQuitApplication
func shouldQuitApplication() C.bool {
// TODO: This should be configurable
return C.bool(globalApplication.shouldQuit())
}
//export cleanup
func cleanup() {
globalApplication.cleanup()
}
func (a *App) logPlatformInfo() {
@@ -7,6 +7,7 @@
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property bool shouldTerminateWhenLastWindowClosed;
@property bool shuttingDown;
- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app;
@end
@@ -2,7 +2,8 @@
#import "application_darwin_delegate.h"
#import "../events/events_darwin.h"
extern bool hasListeners(unsigned int);
extern void quitApplication();
extern bool shouldQuitApplication();
extern void cleanup();
@implementation AppDelegate
- (void)dealloc
@@ -20,8 +21,14 @@ extern void quitApplication();
}
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
quitApplication();
return NSTerminateCancel;
if( ! shouldQuitApplication() ) {
return NSTerminateCancel;
}
if( !self.shuttingDown ) {
self.shuttingDown = true;
cleanup();
}
return NSTerminateNow;
}
- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app
{
+4
View File
@@ -116,6 +116,10 @@ func (m *linuxApp) run() error {
}
func (m *linuxApp) destroy() {
if !globalApplication.shouldQuit() {
return
}
globalApplication.cleanup()
appDestroy(m.application)
}
@@ -192,6 +192,10 @@ func (m *windowsApp) run() error {
}
func (m *windowsApp) destroy() {
if !globalApplication.shouldQuit() {
return
}
globalApplication.cleanup()
// Post a quit message to the main thread
w32.PostQuitMessage(0)
}
+4 -2
View File
@@ -190,8 +190,10 @@ func newDeleteMenuItem() *MenuItem {
}
func newQuitMenuItem() *MenuItem {
panic("implement me")
return newMenuItem("Quit").
OnClick(func(ctx *Context) {
globalApplication.Quit()
})
}
func newSelectAllMenuItem() *MenuItem {
+6 -1
View File
@@ -52,10 +52,15 @@ type Options struct {
// KeyBindings is a map of key bindings to functions
KeyBindings map[string]func(window *WebviewWindow)
// OnShutdown is called when the application is about to quit.
// OnShutdown is called when the application is about to terminate.
// This is useful for cleanup tasks.
// The shutdown process blocks until this function returns
OnShutdown func()
// ShouldQuit is a function that is called when the user tries to quit the application.
// If the function returns true, the application will quit.
// If the function returns false, the application will not quit.
ShouldQuit func() bool
}
// AssetOptions defines the configuration of the AssetServer.
@@ -956,7 +956,14 @@ func (w *macosWebviewWindow) setEnabled(enabled bool) {
}
func (w *macosWebviewWindow) execJS(js string) {
InvokeAsync(func() {
if globalApplication.performingShutdown {
return
}
if w.nsWindow == nil {
return
}
C.windowExecJS(w.nsWindow, C.CString(js))
})
}