From e2a3b75db236d1c69f59070a8eeec7b0e9a3a618 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 9 Sep 2016 10:13:38 +0200 Subject: [PATCH] Fix app not quitting on win32 and linux when closing the last window This regression was caused by a nuance in the way we maintain state in `AtomApplication` for open windows. Specifically, when closing the last window on Windows and Linux, we were explicitly calling `app.quit` *before* removing such window from the list of open ones. In turn, this caused the new `before-quit` behavior introduced in #12619 to work improperly because it made the application wait on saving the state of a stale window before exiting. With this commit we are fixing that by making sure the stale window is removed before calling `app.quit` in `removeWindow`. --- spec/main-process/atom-application.test.js | 44 +++++++++++++++++++++- src/main-process/atom-application.coffee | 4 +- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/spec/main-process/atom-application.test.js b/spec/main-process/atom-application.test.js index 7fd68e038..5a8e6230b 100644 --- a/spec/main-process/atom-application.test.js +++ b/spec/main-process/atom-application.test.js @@ -14,10 +14,12 @@ const ATOM_RESOURCE_PATH = path.resolve(__dirname, '..', '..') describe('AtomApplication', function () { this.timeout(60 * 1000) - let originalAppQuit, originalAtomHome, atomApplicationsToDestroy + let originalPlatform, originalAppQuit, originalAtomHome, atomApplicationsToDestroy beforeEach(function () { + originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform') originalAppQuit = electron.app.quit + mockElectronAppQuit() originalAtomHome = process.env.ATOM_HOME process.env.ATOM_HOME = makeTempDir('atom-home') // Symlinking the compile cache into the temporary home dir makes the windows load much faster @@ -32,6 +34,7 @@ describe('AtomApplication', function () { }) afterEach(async function () { + Object.defineProperty(process, 'platform', originalPlatform) electron.app.quit = originalAppQuit process.env.ATOM_HOME = originalAtomHome for (let atomApplication of atomApplicationsToDestroy) { @@ -366,11 +369,48 @@ describe('AtomApplication', function () { await focusWindow(app2Window) assert.deepEqual(await getTreeViewRootDirectories(app2Window), []) }) + + describe('when closing the last window', function () { + describe('on win32', function () { + it('quits the application', async function () { + const atomApplication = buildAtomApplication() + Object.defineProperty(process, 'platform', {get: () => 'win32'}) + const window = atomApplication.launch(parseCommandLine([path.join(makeTempDir("a"), 'file-a')])) + await focusWindow(window) + window.close() + await window.closedPromise + assert(electron.app.hasQuitted()) + }) + }) + + describe('on linux', function () { + it('quits the application', async function () { + const atomApplication = buildAtomApplication() + Object.defineProperty(process, 'platform', {get: () => 'linux'}) + const window = atomApplication.launch(parseCommandLine([path.join(makeTempDir("a"), 'file-a')])) + await focusWindow(window) + window.close() + await window.closedPromise + assert(electron.app.hasQuitted()) + }) + }) + + describe('on darwin', function () { + it('leaves the application open', async function () { + const atomApplication = buildAtomApplication() + Object.defineProperty(process, 'platform', {get: () => 'darwin'}) + const window = atomApplication.launch(parseCommandLine([path.join(makeTempDir("a"), 'file-a')])) + await focusWindow(window) + window.close() + await window.closedPromise + assert(!electron.app.hasQuitted()) + }) + }) + }) }) describe('before quitting', function () { it('waits until all the windows have saved their state and then quits', async function () { - mockElectronAppQuit() const dirAPath = makeTempDir("a") const dirBPath = makeTempDir("b") const atomApplication = buildAtomApplication() diff --git a/src/main-process/atom-application.coffee b/src/main-process/atom-application.coffee index 701710337..8969a1763 100644 --- a/src/main-process/atom-application.coffee +++ b/src/main-process/atom-application.coffee @@ -122,12 +122,12 @@ class AtomApplication # Public: Removes the {AtomWindow} from the global window list. removeWindow: (window) -> - if @windows.length is 1 + @windows.splice(@windows.indexOf(window), 1) + if @windows.length is 0 @applicationMenu?.enableWindowSpecificItems(false) if process.platform in ['win32', 'linux'] app.quit() return - @windows.splice(@windows.indexOf(window), 1) @saveState(true) unless window.isSpec # Public: Adds the {AtomWindow} to the global window list.