Skip to content

Commit

Permalink
Encapsulate Electron Window Logic - Allow Exit during Load (eclipse-t…
Browse files Browse the repository at this point in the history
…heia#10600)

- Extracts logic for handling various window events from the
  ElectronMainApplication class into a TheiaElectronWindow wrapper class
- Adds communication about application state between window and the
  TheiaElectronWindow
  • Loading branch information
colin-grant-work committed Feb 23, 2022
1 parent 03014b1 commit 42f546c
Show file tree
Hide file tree
Showing 11 changed files with 402 additions and 148 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
- `TerminalServer`
- `TimelineTreeWidget`
- `TypeHierarchyTreeWidget`

- [core] Moved methods `attachReadyToShow`, `restoreMaximizedState`, `attachCloseListeners`, `handleStopRequest`, `checkSafeToStop`, `handleReload`, `reload` from `ElectronMainAPplication` into new class `TheiaElectronWindow`. [#10600](https://github.com/eclipse-theia/theia/pull/10600)
## v1.22.0 - 1/27/2022

[1.22.0 Milestone](https://github.com/eclipse-theia/theia/milestone/30)
Expand Down
36 changes: 17 additions & 19 deletions packages/core/src/browser/frontend-application-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,9 @@ import { injectable, inject } from 'inversify';
import { Emitter, Event } from '../common/event';
import { Deferred } from '../common/promise-util';
import { ILogger } from '../common/logger';
import { FrontendApplicationState } from '../common/frontend-application-state';

export type FrontendApplicationState =
'init'
| 'started_contributions'
| 'attached_shell'
| 'initialized_layout'
| 'ready'
| 'closing_window';
export { FrontendApplicationState };

@injectable()
export class FrontendApplicationStateService {
Expand All @@ -44,24 +39,28 @@ export class FrontendApplicationStateService {

set state(state: FrontendApplicationState) {
if (state !== this._state) {
if (this.deferred[this._state] === undefined) {
this.deferred[this._state] = new Deferred();
}
const oldState = this._state;
this._state = state;
if (this.deferred[state] === undefined) {
this.deferred[state] = new Deferred();
}
this.deferred[state].resolve();
this.logger.info(`Changed application state from '${oldState}' to '${this._state}'.`);
this.stateChanged.fire(state);
this.doSetState(state);
}
}

get onStateChanged(): Event<FrontendApplicationState> {
return this.stateChanged.event;
}

protected doSetState(state: FrontendApplicationState): void {
if (this.deferred[this._state] === undefined) {
this.deferred[this._state] = new Deferred();
}
const oldState = this._state;
this._state = state;
if (this.deferred[state] === undefined) {
this.deferred[state] = new Deferred();
}
this.deferred[state].resolve();
this.logger.info(`Changed application state from '${oldState}' to '${this._state}'.`);
this.stateChanged.fire(state);
}

reachedState(state: FrontendApplicationState): Promise<void> {
if (this.deferred[state] === undefined) {
this.deferred[state] = new Deferred();
Expand All @@ -72,5 +71,4 @@ export class FrontendApplicationStateService {
reachedAnyState(...states: FrontendApplicationState[]): Promise<void> {
return Promise.race(states.map(s => this.reachedState(s)));
}

}
23 changes: 23 additions & 0 deletions packages/core/src/common/frontend-application-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/********************************************************************************
* Copyright (C) 2022 Ericsson and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

export type FrontendApplicationState =
'init'
| 'started_contributions'
| 'attached_shell'
| 'initialized_layout'
| 'ready'
| 'closing_window';
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/********************************************************************************
* Copyright (C) 2022 Ericsson and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { ipcRenderer } from '../../../electron-shared/electron';
import { injectable } from 'inversify';
import { APPLICATION_STATE_CHANGE_SIGNAL } from '../../electron-common/messaging/electron-messages';
import { FrontendApplicationState, FrontendApplicationStateService } from '../../browser/frontend-application-state';

@injectable()
export class ElectronFrontendApplicationStateService extends FrontendApplicationStateService {
protected override doSetState(state: FrontendApplicationState): void {
super.doSetState(state);
ipcRenderer.send(APPLICATION_STATE_CHANGE_SIGNAL, state);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ import { ClipboardService } from '../../browser/clipboard-service';
import { ElectronMainWindowService, electronMainWindowServicePath } from '../../electron-common/electron-main-window-service';
import { ElectronIpcConnectionProvider } from '../messaging/electron-ipc-connection-provider';
import { bindWindowPreferences } from './electron-window-preferences';
import { FrontendApplicationStateService } from '../../browser/frontend-application-state';
import { ElectronFrontendApplicationStateService } from './electron-frontend-application-state';

export default new ContainerModule(bind => {
export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(ElectronMainWindowService).toDynamicValue(context =>
ElectronIpcConnectionProvider.createProxy(context.container, electronMainWindowServicePath)
).inSingletonScope();
bindWindowPreferences(bind);
bind(WindowService).to(ElectronWindowService).inSingletonScope();
bind(FrontendApplicationContribution).toService(WindowService);
bind(ClipboardService).to(ElectronClipboardService).inSingletonScope();
rebind(FrontendApplicationStateService).to(ElectronFrontendApplicationStateService).inSingletonScope();
});
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export const CLOSE_REQUESTED_SIGNAL = 'close-requested';
* Emitted by window when a reload is requested.
*/
export const RELOAD_REQUESTED_SIGNAL = 'reload-requested';
/**
* Emitted by the window when the application changes state
*/
export const APPLICATION_STATE_CHANGE_SIGNAL = 'application-state-changed';

export enum StopReason {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { ElectronMessagingContribution } from './messaging/electron-messaging-co
import { ElectronMessagingService } from './messaging/electron-messaging-service';
import { ElectronConnectionHandler } from '../electron-common/messaging/electron-connection-handler';
import { ElectronSecurityTokenService } from './electron-security-token-service';
import { TheiaBrowserWindowOptions, TheiaElectronWindow, TheiaElectronWindowFactory, WindowApplicationConfig } from './theia-electron-window';

const electronSecurityToken: ElectronSecurityToken = { value: v4() };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -50,4 +51,12 @@ export default new ContainerModule(bind => {
).inSingletonScope();

bind(ElectronMainProcessArgv).toSelf().inSingletonScope();

bind(TheiaElectronWindow).toSelf();
bind(TheiaElectronWindowFactory).toFactory(({ container }) => (options, config) => {
const child = container.createChild();
child.bind(TheiaBrowserWindowOptions).toConstantValue(options);
child.bind(WindowApplicationConfig).toConstantValue(config);
return child.get(TheiaElectronWindow);
});
});
Loading

0 comments on commit 42f546c

Please sign in to comment.