Skip to content

Commit

Permalink
GH-8188: Workaround for application.confirmExit
Browse files Browse the repository at this point in the history
From now on, the browser and electron frontends listen on different
events when it comes to saving the app state and releasing the resources.
The browser behavior is unchanged.
Made the `will-prevent-unload` handling sync.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
  • Loading branch information
Akos Kitta committed Nov 7, 2020
1 parent d660747 commit eeae987
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 4 deletions.
7 changes: 5 additions & 2 deletions packages/core/src/browser/frontend-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { ShellLayoutRestorer, ApplicationShellLayoutMigrationError } from './she
import { FrontendApplicationStateService } from './frontend-application-state';
import { preventNavigation, parseCssTime, animationFrame } from './browser';
import { CorePreferences } from './core-preferences';
import { WindowService } from './window/window-service';

/**
* Clients can implement to get a callback for contributing widgets to a shell on start.
Expand Down Expand Up @@ -96,6 +97,9 @@ export class FrontendApplication {
@inject(CorePreferences)
protected readonly corePreferences: CorePreferences;

@inject(WindowService)
protected readonly windowsService: WindowService;

constructor(
@inject(CommandRegistry) protected readonly commands: CommandRegistry,
@inject(MenuModelRegistry) protected readonly menus: MenuModelRegistry,
Expand Down Expand Up @@ -182,8 +186,7 @@ export class FrontendApplication {
*/
protected registerEventListeners(): void {
this.registerCompositionEventListeners(); /* Hotfix. See above. */

window.addEventListener('beforeunload', () => {
this.windowsService.onUnload(() => {
this.stateService.state = 'closing_window';
this.layoutRestorer.storeLayout(this);
this.stopContributions();
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/browser/window/default-window-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
********************************************************************************/

import { inject, injectable, named } from 'inversify';
import { Event, Emitter } from '../../common';
import { CorePreferences } from '../core-preferences';
import { ContributionProvider } from '../../common/contribution-provider';
import { FrontendApplicationContribution, FrontendApplication } from '../frontend-application';
Expand All @@ -24,6 +25,7 @@ import { WindowService } from './window-service';
export class DefaultWindowService implements WindowService, FrontendApplicationContribution {

protected frontendApplication: FrontendApplication;
protected onUnloadEmitter = new Emitter<void>();

@inject(CorePreferences)
protected readonly corePreferences: CorePreferences;
Expand All @@ -39,6 +41,7 @@ export class DefaultWindowService implements WindowService, FrontendApplicationC
return this.preventUnload(event);
}
});
this.registerUnloadListener();
}

openNewWindow(url: string): undefined {
Expand All @@ -61,6 +64,14 @@ export class DefaultWindowService implements WindowService, FrontendApplicationC
return confirmExit !== 'always';
}

protected registerUnloadListener(): void {
window.addEventListener('unload', () => this.onUnloadEmitter.fire());
}

get onUnload(): Event<void> {
return this.onUnloadEmitter.event;
}

/**
* Ask the user to confirm if they want to unload the window. Prevent it if they do not.
* @param event The beforeunload event
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/browser/window/window-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { Event } from '../../common/event';

export interface NewWindowOptions {
readonly external?: boolean;
}
Expand All @@ -38,4 +40,10 @@ export interface WindowService {
*/
canUnload(): boolean;

/**
* Fires when the `window` unloads. On this event, the frontend application can save its state and release resource.
* Saving the state and releasing any resources must be synchronous.
*/
readonly onUnload: Event<void>;

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
********************************************************************************/

import { injectable, inject } from 'inversify';
import { remote } from 'electron';
import { Event } from '../../common/event';
import { NewWindowOptions } from '../../browser/window/window-service';
import { DefaultWindowService } from '../../browser/window/default-window-service';
import { ElectronMainWindowService } from '../../electron-common/electron-main-window-service';
Expand All @@ -30,6 +32,18 @@ export class ElectronWindowService extends DefaultWindowService {
return undefined;
}

registerUnloadListener(): void {
remote.getCurrentWindow().on('closed', () => this.onUnloadEmitter.fire());
}

/**
* Unlike the default implementation, this even is fires when the `ElectronWindow`
* [closes](https://github.com/electron/electron/blob/master/docs/api/browser-window.md#event-close).
*/
get onUnload(): Event<void> {
return this.onUnloadEmitter.event;
}

protected preventUnload(event: BeforeUnloadEvent): string | void {
// The user will be shown a confirmation dialog by the will-prevent-unload handler in the Electron main script
event.returnValue = false;
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/electron-main/electron-main-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,8 @@ export class ElectronMainApplication {
*/
protected attachWillPreventUnload(electronWindow: BrowserWindow): void {
// Fired when a beforeunload handler tries to prevent the page unloading
electronWindow.webContents.on('will-prevent-unload', async event => {
const { response } = await dialog.showMessageBox(electronWindow, {
electronWindow.webContents.on('will-prevent-unload', event => {
const response = dialog.showMessageBoxSync(electronWindow, {
type: 'question',
buttons: ['Yes', 'No'],
title: 'Confirm',
Expand Down

0 comments on commit eeae987

Please sign in to comment.