diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index c7a2a542d1d8..85d95f4c2d80 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -131,6 +131,10 @@ App::~App() { Browser::Get()->RemoveObserver(this); } +void App::OnBeforeQuit(bool* prevent_default) { + *prevent_default = Emit("before-quit"); +} + void App::OnWillQuit(bool* prevent_default) { *prevent_default = Emit("will-quit"); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 41a820b7a765..062d2d083d2a 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -38,6 +38,7 @@ class App : public mate::EventEmitter, virtual ~App(); // BrowserObserver: + void OnBeforeQuit(bool* prevent_default) override; void OnWillQuit(bool* prevent_default) override; void OnWindowAllClosed() override; void OnQuit() override; diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index b658de410209..123cfc4f9844 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -28,7 +28,9 @@ Browser* Browser::Get() { } void Browser::Quit() { - is_quiting_ = true; + is_quiting_ = HandleBeforeQuit(); + if (!is_quiting_) + return; atom::WindowList* window_list = atom::WindowList::GetInstance(); if (window_list->size() == 0) @@ -114,6 +116,15 @@ void Browser::NotifyAndShutdown() { Shutdown(); } +bool Browser::HandleBeforeQuit() { + bool prevent_default = false; + FOR_EACH_OBSERVER(BrowserObserver, + observers_, + OnBeforeQuit(&prevent_default)); + + return !prevent_default; +} + void Browser::OnWindowCloseCancelled(NativeWindow* window) { if (is_quiting_) // Once a beforeunload handler has prevented the closing, we think the quit diff --git a/atom/browser/browser.h b/atom/browser/browser.h index d079d53a6dea..8648d8853384 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -136,6 +136,9 @@ class Browser : public WindowListObserver { // Send the will-quit message and then shutdown the application. void NotifyAndShutdown(); + // Send the before-quit message and start closing windows. + bool HandleBeforeQuit(); + bool is_quiting_; private: diff --git a/atom/browser/browser_observer.h b/atom/browser/browser_observer.h index 40069cbb4495..4f9f436712d4 100644 --- a/atom/browser/browser_observer.h +++ b/atom/browser/browser_observer.h @@ -11,6 +11,9 @@ namespace atom { class BrowserObserver { public: + // The browser is about to close all windows. + virtual void OnBeforeQuit(bool* prevent_default) {} + // The browser has closed all windows and will quit. virtual void OnWillQuit(bool* prevent_default) {} diff --git a/docs/api/app.md b/docs/api/app.md index 4ac377692622..4119dbf75904 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -34,6 +34,14 @@ user pressed `Cmd + Q`, or the developer called `app.quit()`, atom-shell would first try to close all windows and then emit the `will-quit` event, and in this case the `window-all-closed` would not be emitted. +## Event: before-quit + +* `event` Event + +Emitted before the application starts closing its windows. +Calling `event.preventDefault()` will prevent the default behaviour, which is +terminating the application. + ## Event: will-quit * `event` Event @@ -78,9 +86,9 @@ click on the application's dock icon. ## app.quit() -Try to close all windows. If all windows are successfully closed, the -`will-quit` event will be emitted and by default the application would be -terminated. +Try to close all windows. The `before-quit` event will first be emitted. If all +windows are successfully closed, the `will-quit` event will be emitted and by +default the application would be terminated. This method guarantees all `beforeunload` and `unload` handlers are correctly executed. It is possible that a window cancels the quitting by returning