-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Focus revealed external widgets in electron
Adds a new service `SecondaryWindowService` to handle creating and focussing external windows based on the platform. Signed-off-by: Lucas Koehler <[email protected]>
- Loading branch information
1 parent
dd58c2e
commit ad86315
Showing
7 changed files
with
166 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
packages/core/src/browser/window/default-secondary-window-service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// ***************************************************************************** | ||
// Copyright (C) 2022 STMicroelectronics, Ericsson, ARM, EclipseSource 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 { inject, injectable, postConstruct } from 'inversify'; | ||
import { SecondaryWindowService } from './secondary-window-service'; | ||
import { WindowService } from './window-service'; | ||
|
||
@injectable() | ||
export class DefaultSecondaryWindowService implements SecondaryWindowService { | ||
// secondary-window.html is part of Theia's generated code. It is generated by dev-packages/application-manager/src/generator/frontend-generator.ts | ||
protected static SECONDARY_WINDOW_URL = 'secondary-window.html'; | ||
|
||
/** | ||
* Randomized prefix to be included in opened windows' ids. | ||
* This avoids conflicts when creating sub-windows from multiple theia instances (e.g. by opening Theia multiple times in the same browser) | ||
*/ | ||
protected readonly prefix = crypto.getRandomValues(new Uint32Array(1))[0]; | ||
/** Unique id. Increase after every access. */ | ||
private nextId = 0; | ||
|
||
protected secondaryWindows: Window[] = []; | ||
|
||
@inject(WindowService) | ||
protected readonly windowService: WindowService; | ||
|
||
@postConstruct() | ||
init(): void { | ||
// Close all open windows when the main window is closed. | ||
this.windowService.onUnload(() => { | ||
// Iterate backwards because calling window.close might remove the window from the array | ||
for (let i = this.secondaryWindows.length - 1; i >= 0; i--) { | ||
this.secondaryWindows[i].close(); | ||
} | ||
}); | ||
} | ||
|
||
createSecondaryWindow(): Window | undefined { | ||
const win = this.doCreateSecondaryWindow(); | ||
if (win) { | ||
this.secondaryWindows.push(win); | ||
win.addEventListener('beforeunload', () => { | ||
const extIndex = this.secondaryWindows.indexOf(win); | ||
if (extIndex > -1) { | ||
this.secondaryWindows.splice(extIndex, 1); | ||
} | ||
}); | ||
} | ||
return win ?? undefined; | ||
} | ||
|
||
protected doCreateSecondaryWindow(): Window | undefined { | ||
return window.open(DefaultSecondaryWindowService.SECONDARY_WINDOW_URL, this.nextWindowId(), 'popup') ?? undefined; | ||
} | ||
|
||
focus(win: Window): void { | ||
win.focus(); | ||
} | ||
|
||
protected nextWindowId(): string { | ||
return `${this.prefix}-secondaryWindow-${this.nextId++}`; | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
packages/core/src/browser/window/secondary-window-service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// ***************************************************************************** | ||
// Copyright (C) 2022 STMicroelectronics, Ericsson, ARM, EclipseSource 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 const SecondaryWindowService = Symbol('SecondaryWindowService'); | ||
|
||
/** Service for opening new secondary windows to contain widgets extracted from the application shell. */ | ||
export interface SecondaryWindowService { | ||
/** | ||
* Creates a new secondary window for a widget to be extracted from the application shell. | ||
* The created window is closed automatically when the current theia instance is closed. | ||
* | ||
* @returns the created window or `undefined` if it could not be created | ||
*/ | ||
createSecondaryWindow(): Window | undefined; | ||
|
||
/** Handles focussing the given secondary window in the browser and on Electron. */ | ||
focus(win: Window): void; | ||
} |
50 changes: 50 additions & 0 deletions
50
packages/core/src/electron-browser/window/electron-secondary-window-service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// ***************************************************************************** | ||
// Copyright (C) 2022 STMicroelectronics, Ericsson, ARM, EclipseSource 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 { BrowserWindow } from '../../../electron-shared/electron'; | ||
import * as electronRemote from '../../../electron-shared/@electron/remote'; | ||
import { injectable } from 'inversify'; | ||
import { DefaultSecondaryWindowService } from '../../browser/window/default-secondary-window-service'; | ||
|
||
@injectable() | ||
export class ElectronSecondaryWindowService extends DefaultSecondaryWindowService { | ||
protected electronWindows: Map<string, BrowserWindow> = new Map(); | ||
|
||
protected override doCreateSecondaryWindow(): Window | undefined { | ||
const id = this.nextWindowId(); | ||
electronRemote.getCurrentWindow().webContents.once('did-create-window', newElectronWindow => { | ||
newElectronWindow.setMenuBarVisibility(false); | ||
this.electronWindows.set(id, newElectronWindow); | ||
}); | ||
const win = window.open(DefaultSecondaryWindowService.SECONDARY_WINDOW_URL, id); | ||
win?.addEventListener('beforeunload', () => { | ||
this.electronWindows.delete(id); | ||
}); | ||
return win ?? undefined; | ||
} | ||
|
||
override focus(win: Window): void { | ||
// window.name is the target name given to the window.open call as the second parameter. | ||
const electronWindow = this.electronWindows.get(win.name); | ||
if (electronWindow) { | ||
if (electronWindow.isMinimized()) { | ||
electronWindow.restore(); | ||
} | ||
electronWindow.focus(); | ||
} else { | ||
console.warn(`There is no known secondary window '${win.name}'. Thus, the window could not be focussed.`); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters