@@ -14,6 +14,7 @@ import Event, { Emitter } from 'vs/base/common/event';
1414import { createDecorator } from 'vs/platform/instantiation/common/instantiation' ;
1515import { ICodeWindow } from "vs/platform/windows/electron-main/windows" ;
1616import { ReadyState } from 'vs/platform/windows/common/windows' ;
17+ import { handleVetos } from "vs/platform/lifecycle/common/lifecycle" ;
1718
1819export const ILifecycleService = createDecorator < ILifecycleService > ( 'lifecycleService' ) ;
1920
@@ -24,6 +25,12 @@ export enum UnloadReason {
2425 LOAD = 4
2526}
2627
28+ export interface IWindowUnloadEvent {
29+ window : ICodeWindow ;
30+ reason : UnloadReason ;
31+ veto ( value : boolean | TPromise < boolean > ) : void ;
32+ }
33+
2734export interface ILifecycleService {
2835 _serviceBrand : any ;
2936
@@ -46,6 +53,11 @@ export interface ILifecycleService {
4653 */
4754 onBeforeWindowClose : Event < ICodeWindow > ;
4855
56+ /**
57+ * An even that can be vetoed to prevent a window from being unloaded.
58+ */
59+ onBeforeWindowUnload : Event < IWindowUnloadEvent > ;
60+
4961 ready ( ) : void ;
5062 registerWindow ( codeWindow : ICodeWindow ) : void ;
5163
@@ -78,6 +90,9 @@ export class LifecycleService implements ILifecycleService {
7890 private _onBeforeWindowClose = new Emitter < ICodeWindow > ( ) ;
7991 onBeforeWindowClose : Event < ICodeWindow > = this . _onBeforeWindowClose . event ;
8092
93+ private _onBeforeWindowUnload = new Emitter < IWindowUnloadEvent > ( ) ;
94+ onBeforeWindowUnload : Event < IWindowUnloadEvent > = this . _onBeforeWindowUnload . event ;
95+
8196 constructor (
8297 @IEnvironmentService private environmentService : IEnvironmentService ,
8398 @ILogService private logService : ILogService ,
@@ -173,6 +188,32 @@ export class LifecycleService implements ILifecycleService {
173188
174189 this . logService . log ( 'Lifecycle#unload()' , codeWindow . id ) ;
175190
191+ const windowUnloadReason = this . quitRequested ? UnloadReason . QUIT : reason ;
192+
193+ // first ask the window itself if it vetos the unload
194+ return this . doUnloadWindowInRenderer ( codeWindow , windowUnloadReason ) . then ( veto => {
195+ if ( veto ) {
196+ return this . handleVeto ( veto ) ;
197+ }
198+
199+ // then check for vetos in the main side
200+ return this . doUnloadWindowInMain ( codeWindow , windowUnloadReason ) . then ( veto => this . handleVeto ( veto ) ) ;
201+ } ) ;
202+ }
203+
204+ private handleVeto ( veto : boolean ) : boolean {
205+
206+ // Any cancellation also cancels a pending quit if present
207+ if ( veto && this . pendingQuitPromiseComplete ) {
208+ this . pendingQuitPromiseComplete ( true /* veto */ ) ;
209+ this . pendingQuitPromiseComplete = null ;
210+ this . pendingQuitPromise = null ;
211+ }
212+
213+ return veto ;
214+ }
215+
216+ private doUnloadWindowInRenderer ( codeWindow : ICodeWindow , reason : UnloadReason ) : TPromise < boolean /* veto */ > {
176217 return new TPromise < boolean > ( ( c ) => {
177218 const oneTimeEventToken = this . oneTimeListenerTokenGenerator ++ ;
178219 const okChannel = `vscode:ok${ oneTimeEventToken } ` ;
@@ -183,21 +224,27 @@ export class LifecycleService implements ILifecycleService {
183224 } ) ;
184225
185226 ipc . once ( cancelChannel , ( ) => {
186-
187- // Any cancellation also cancels a pending quit if present
188- if ( this . pendingQuitPromiseComplete ) {
189- this . pendingQuitPromiseComplete ( true /* veto */ ) ;
190- this . pendingQuitPromiseComplete = null ;
191- this . pendingQuitPromise = null ;
192- }
193-
194227 c ( true ) ; // veto
195228 } ) ;
196229
197- codeWindow . send ( 'vscode:beforeUnload' , { okChannel, cancelChannel, reason : this . quitRequested ? UnloadReason . QUIT : reason } ) ;
230+ codeWindow . send ( 'vscode:beforeUnload' , { okChannel, cancelChannel, reason } ) ;
198231 } ) ;
199232 }
200233
234+ private doUnloadWindowInMain ( window : ICodeWindow , reason : UnloadReason ) : TPromise < boolean /* veto */ > {
235+ const vetos : ( boolean | TPromise < boolean > ) [ ] = [ ] ;
236+
237+ this . _onBeforeWindowUnload . fire ( {
238+ reason,
239+ window,
240+ veto ( value ) {
241+ vetos . push ( value ) ;
242+ }
243+ } ) ;
244+
245+ return handleVetos ( vetos , err => this . logService . error ( err ) ) ;
246+ }
247+
201248 /**
202249 * A promise that completes to indicate if the quit request has been veto'd
203250 * by the user or not.
0 commit comments