Skip to content

Commit

Permalink
Support vscode's titleBarStyle
Browse files Browse the repository at this point in the history
  • Loading branch information
msujew committed Oct 7, 2021
1 parent 7239957 commit 1bcdf4b
Show file tree
Hide file tree
Showing 12 changed files with 384 additions and 80 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
<a name="breaking_changes_1.19.0">[Breaking Changes:](#breaking_changes_1.19.0)</a>

- [view-container] `ViewContainerPart` constructor takes new 2 parameters: `originalContainerId` and `originalContainerTitle`. The existing `viewContainerId` parameter has been renamed to `currentContainerId` to enable drag & drop views. [#9644](https://github.com/eclipse-theia/theia/pull/9644)
- [electron] `ElectronMainMenuFactory` now inherits from `BrowserMainMenuFactory` and its methods have been renamed. [#10044](https://github.com/eclipse-theia/theia/pull/10044)
- renamed `handleDefault` to `handleElectronDefault`
- renamed `createContextMenu` to `createElectronContextMenu`
- renamed `createMenuBar` to `createElectronMenuBar`

## v1.18.0 - 9/30/2021

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
class SampleElectronMainMenuFactory extends ElectronMainMenuFactory {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected handleDefault(menuNode: CompositeMenuNode, args: any[] = [], options?: ElectronMenuOptions): Electron.MenuItemConstructorOptions[] {
protected handleElectronDefault(menuNode: CompositeMenuNode, args: any[] = [], options?: ElectronMenuOptions): Electron.MenuItemConstructorOptions[] {
if (menuNode instanceof PlaceholderMenuNode) {
return [{
label: menuNode.label,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class ElectronMenuUpdater {
this.setMenu();
}

private setMenu(menu: Menu | null = this.factory.createMenuBar(), electronWindow: BrowserWindow = remote.getCurrentWindow()): void {
private setMenu(menu: Menu | null = this.factory.createElectronMenuBar(), electronWindow: BrowserWindow = remote.getCurrentWindow()): void {
if (isOSX) {
remote.Menu.setApplicationMenu(menu);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class BrowserContextMenuRenderer extends ContextMenuRenderer {
super();
}

protected doRender({ menuPath, anchor, args, onHide }: RenderContextMenuOptions): BrowserContextMenuAccess {
protected doRender({ menuPath, anchor, args, onHide }: RenderContextMenuOptions): ContextMenuAccess {
const contextMenu = this.menuFactory.createContextMenu(menuPath, args);
const { x, y } = coordinateFromAnchor(anchor);
if (onHide) {
Expand Down
30 changes: 25 additions & 5 deletions packages/core/src/browser/menu/browser-menu-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { injectable, inject } from 'inversify';
import { MenuBar, Menu as MenuWidget, Widget } from '@phosphor/widgets';
import { CommandRegistry as PhosphorCommandRegistry } from '@phosphor/commands';
import {
CommandRegistry, ActionMenuNode, CompositeMenuNode,
CommandRegistry, ActionMenuNode, CompositeMenuNode, environment,
MenuModelRegistry, MAIN_MENU_BAR, MenuPath, DisposableCollection, Disposable, MenuNode
} from '../../common';
import { KeybindingRegistry } from '../keybinding';
Expand All @@ -28,6 +28,7 @@ import { ContextMenuContext } from './context-menu-context';
import { waitForRevealed } from '../widgets';
import { ApplicationShell } from '../shell';
import { CorePreferences } from '../core-preferences';
import { PreferenceService } from '../preferences/preference-service';

export abstract class MenuBarWidget extends MenuBar {
abstract activateMenu(label: string, ...labels: string[]): Promise<MenuWidget>;
Expand Down Expand Up @@ -371,21 +372,40 @@ export class BrowserMenuBarContribution implements FrontendApplicationContributi
@inject(ApplicationShell)
protected readonly shell: ApplicationShell;

@inject(PreferenceService)
protected readonly preferenceService: PreferenceService;

constructor(
@inject(BrowserMainMenuFactory) protected readonly factory: BrowserMainMenuFactory
) { }

onStart(app: FrontendApplication): void {
const logo = this.createLogo();
app.shell.addWidget(logo, { area: 'top' });
const menu = this.factory.createMenuBar();
app.shell.addWidget(menu, { area: 'top' });
this.appendMenu(app.shell);
}

get menuBar(): MenuBarWidget | undefined {
return this.shell.topPanel.widgets.find(w => w instanceof MenuBarWidget) as MenuBarWidget | undefined;
}

protected appendMenu(shell: ApplicationShell): void {
const logo = this.createLogo();
shell.addWidget(logo, { area: 'top' });
const menu = this.factory.createMenuBar();
shell.addWidget(menu, { area: 'top' });
// Hiding the menu is only necessary in electron
// In the browser we hide the whole top panel
if (environment.electron.is()) {
this.preferenceService.ready.then(() => {
menu.setHidden(['compact', 'hidden'].includes(this.preferenceService.get('window.menuBarVisibility', '')));
});
this.preferenceService.onPreferenceChanged(change => {
if (change.preferenceName === 'window.menuBarVisibility') {
menu.setHidden(['compact', 'hidden'].includes(change.newValue));
}
});
}
}

protected createLogo(): Widget {
const logo = new Widget();
logo.id = 'theia:icon';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import * as electron from '../../../shared/electron';
import { inject, injectable } from 'inversify';
import { ContextMenuRenderer, RenderContextMenuOptions, ContextMenuAccess, FrontendApplicationContribution, CommonCommands, coordinateFromAnchor } from '../../browser';
import { inject, injectable, postConstruct } from 'inversify';
import {
ContextMenuRenderer, RenderContextMenuOptions, ContextMenuAccess, FrontendApplicationContribution, CommonCommands, coordinateFromAnchor, PreferenceService
} from '../../browser';
import { ElectronMainMenuFactory } from './electron-main-menu-factory';
import { ContextMenuContext } from '../../browser/menu/context-menu-context';
import { MenuPath, MenuContribution, MenuModelRegistry } from '../../common';
import { BrowserContextMenuRenderer } from '../../browser/menu/browser-context-menu-renderer';
import { RequestTitleBarStyle, TitleBarStyleAtStartup } from '../../electron-common/messaging/electron-messages';

export class ElectronContextMenuAccess extends ContextMenuAccess {
constructor(readonly menu: electron.Menu) {
Expand Down Expand Up @@ -73,27 +77,45 @@ export class ElectronTextInputContextMenuContribution implements FrontendApplica
}

@injectable()
export class ElectronContextMenuRenderer extends ContextMenuRenderer {
export class ElectronContextMenuRenderer extends BrowserContextMenuRenderer {

@inject(ContextMenuContext)
protected readonly context: ContextMenuContext;

constructor(@inject(ElectronMainMenuFactory) private menuFactory: ElectronMainMenuFactory) {
super();
@inject(PreferenceService)
protected readonly preferenceService: PreferenceService;

protected useNativeStyle: boolean = true;

constructor(@inject(ElectronMainMenuFactory) private electronMenuFactory: ElectronMainMenuFactory) {
super(electronMenuFactory);
}

@postConstruct()
protected async init(): Promise<void> {
electron.ipcRenderer.on(TitleBarStyleAtStartup, (_event, style: string) => {
this.useNativeStyle = style === 'native';
});
electron.ipcRenderer.send(RequestTitleBarStyle);
}

protected doRender({ menuPath, anchor, args, onHide }: RenderContextMenuOptions): ElectronContextMenuAccess {
const menu = this.menuFactory.createContextMenu(menuPath, args);
const { x, y } = coordinateFromAnchor(anchor);
const zoom = electron.webFrame.getZoomFactor();
// x and y values must be Ints or else there is a conversion error
menu.popup({ x: Math.round(x * zoom), y: Math.round(y * zoom) });
// native context menu stops the event loop, so there is no keyboard events
this.context.resetAltPressed();
if (onHide) {
menu.once('menu-will-close', () => onHide());
protected doRender(options: RenderContextMenuOptions): ContextMenuAccess {
if (this.useNativeStyle) {
const { menuPath, anchor, args, onHide } = options;
const menu = this.electronMenuFactory.createElectronContextMenu(menuPath, args);
const { x, y } = coordinateFromAnchor(anchor);
const zoom = electron.webFrame.getZoomFactor();
// x and y values must be Ints or else there is a conversion error
menu.popup({ x: Math.round(x * zoom), y: Math.round(y * zoom) });
// native context menu stops the event loop, so there is no keyboard events
this.context.resetAltPressed();
if (onHide) {
menu.once('menu-will-close', () => onHide());
}
return new ElectronContextMenuAccess(menu);
} else {
return super.doRender(options);
}
return new ElectronContextMenuAccess(menu);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ import {
} from '../../common';
import { Keybinding } from '../../common/keybinding';
import { PreferenceService, KeybindingRegistry, CommonCommands } from '../../browser';
import { ContextKeyService } from '../../browser/context-key-service';
import debounce = require('lodash.debounce');
import { ContextMenuContext } from '../../browser/menu/context-menu-context';
import { MAXIMIZED_CLASS } from '../../browser/shell/theia-dock-panel';
import { BrowserMainMenuFactory } from '../../browser/menu/browser-menu-plugin';

/**
* Representation of possible electron menu options.
Expand Down Expand Up @@ -55,23 +54,18 @@ export type ElectronMenuItemRole = ('undo' | 'redo' | 'cut' | 'copy' | 'paste' |
'moveTabToNewWindow' | 'windowMenu');

@injectable()
export class ElectronMainMenuFactory {
export class ElectronMainMenuFactory extends BrowserMainMenuFactory {

protected _menu: Electron.Menu | undefined;
protected _toggledCommands: Set<string> = new Set();

@inject(ContextKeyService)
protected readonly contextKeyService: ContextKeyService;

@inject(ContextMenuContext)
protected readonly context: ContextMenuContext;

constructor(
@inject(CommandRegistry) protected readonly commandRegistry: CommandRegistry,
@inject(PreferenceService) protected readonly preferencesService: PreferenceService,
@inject(MenuModelRegistry) protected readonly menuProvider: MenuModelRegistry,
@inject(KeybindingRegistry) protected readonly keybindingRegistry: KeybindingRegistry
) {
super();
preferencesService.onPreferenceChanged(
debounce(e => {
if (e.preferenceName === 'window.menuBarVisibility') {
Expand All @@ -92,15 +86,16 @@ export class ElectronMainMenuFactory {

async setMenuBar(): Promise<void> {
await this.preferencesService.ready;
const createdMenuBar = this.createMenuBar();
if (isOSX) {
const createdMenuBar = this.createElectronMenuBar();
electron.remote.Menu.setApplicationMenu(createdMenuBar);
} else {
} else if (this.preferencesService.get('window.titleBarStyle') === 'native') {
const createdMenuBar = this.createElectronMenuBar();
electron.remote.getCurrentWindow().setMenu(createdMenuBar);
}
}

createMenuBar(): Electron.Menu | null {
createElectronMenuBar(): Electron.Menu | null {
const preference = this.preferencesService.get<string>('window.menuBarVisibility') || 'classic';
const maxWidget = document.getElementsByClassName(MAXIMIZED_CLASS);
if (preference === 'visible' || (preference === 'classic' && maxWidget.length === 0)) {
Expand All @@ -118,7 +113,7 @@ export class ElectronMainMenuFactory {
return null;
}

createContextMenu(menuPath: MenuPath, args?: any[]): Electron.Menu {
createElectronContextMenu(menuPath: MenuPath, args?: any[]): Electron.Menu {
const menuModel = this.menuProvider.getMenu(menuPath);
const template = this.fillMenuTemplate([], menuModel, args, { showDisabled: false });
return electron.remote.Menu.buildFromTemplate(template);
Expand Down Expand Up @@ -221,13 +216,13 @@ export class ElectronMainMenuFactory {
this._toggledCommands.add(commandId);
}
} else {
items.push(...this.handleDefault(menu, args, options));
items.push(...this.handleElectronDefault(menu, args, options));
}
}
return items;
}

protected handleDefault(menuNode: MenuNode, args: any[] = [], options?: ElectronMenuOptions): Electron.MenuItemConstructorOptions[] {
protected handleElectronDefault(menuNode: MenuNode, args: any[] = [], options?: ElectronMenuOptions): Electron.MenuItemConstructorOptions[] {
return [];
}

Expand Down
Loading

0 comments on commit 1bcdf4b

Please sign in to comment.