Skip to content

Commit

Permalink
Preferences: Support window.zoomLevel Preference
Browse files Browse the repository at this point in the history
Fixes #8751

What it does

- Allows end-user to specify window zoom level as a preference
- Adds support for the addition of other window preferences

How to test

1. Open `Preferences` view and locate the `window.zoomLevel` preference
2. Enter in a custom value or change the zoom level using zoom commands
   (`ctrl +, ctrl -, ctrl 0`)
3. Observe that the window zoom level changes and the preference is
   updated in the `settings.json` file
4. Reload the window and observe that the preferred zoom level is
   restored

Signed-off-by: seantan22 <[email protected]>
  • Loading branch information
seantan22 committed Mar 2, 2021
1 parent a20b26d commit d15635e
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import {
Command, CommandContribution, CommandRegistry,
isOSX, isWindows, MenuModelRegistry, MenuContribution, Disposable
} from '../../common';
import { KeybindingContribution, KeybindingRegistry } from '../../browser';
import { KeybindingContribution, KeybindingRegistry, PreferenceScope, PreferenceService } from '../../browser';
import { FrontendApplication, FrontendApplicationContribution, CommonMenus } from '../../browser';
import { ElectronMainMenuFactory } from './electron-main-menu-factory';
import { FrontendApplicationStateService, FrontendApplicationState } from '../../browser/frontend-application-state';
import { ZoomLevel } from '../window/electron-window-preferences';

export namespace ElectronCommands {
export const TOGGLE_DEVELOPER_TOOLS: Command = {
Expand Down Expand Up @@ -71,6 +72,9 @@ export class ElectronMenuContribution implements FrontendApplicationContribution
@inject(FrontendApplicationStateService)
protected readonly stateService: FrontendApplicationStateService;

@inject(PreferenceService)
protected readonly preferenceService: PreferenceService;

constructor(
@inject(ElectronMainMenuFactory) protected readonly factory: ElectronMainMenuFactory
) { }
Expand Down Expand Up @@ -154,17 +158,29 @@ export class ElectronMenuContribution implements FrontendApplicationContribution
registry.registerCommand(ElectronCommands.ZOOM_IN, {
execute: () => {
const webContents = currentWindow.webContents;
webContents.setZoomLevel(webContents.zoomLevel + 0.5);
// When starting at a level that is not a multiple of 0.5, increment by at most 0.5 to reach the next highest multiple of 0.5.
let zoomLevel = (Math.floor(webContents.zoomLevel / ZoomLevel.VARIATION) * ZoomLevel.VARIATION) + ZoomLevel.VARIATION;
if (zoomLevel > ZoomLevel.MAX) {
zoomLevel = ZoomLevel.MAX;
return;
};
this.preferenceService.set('window.zoomLevel', zoomLevel, PreferenceScope.User);
}
});
registry.registerCommand(ElectronCommands.ZOOM_OUT, {
execute: () => {
const webContents = currentWindow.webContents;
webContents.setZoomLevel(webContents.zoomLevel - 0.5);
// When starting at a level that is not a multiple of 0.5, decrement by at most 0.5 to reach the next lowest multiple of 0.5.
let zoomLevel = (Math.ceil(webContents.zoomLevel / ZoomLevel.VARIATION) * ZoomLevel.VARIATION) - ZoomLevel.VARIATION;
if (zoomLevel < ZoomLevel.MIN) {
zoomLevel = ZoomLevel.MIN;
return;
};
this.preferenceService.set('window.zoomLevel', zoomLevel, PreferenceScope.User);
}
});
registry.registerCommand(ElectronCommands.RESET_ZOOM, {
execute: () => currentWindow.webContents.setZoomLevel(0)
execute: () => this.preferenceService.set('window.zoomLevel', ZoomLevel.DEFAULT, PreferenceScope.User)
});
}

Expand Down Expand Up @@ -223,5 +239,4 @@ export class ElectronMenuContribution implements FrontendApplicationContribution
commandId: ElectronCommands.CLOSE_WINDOW.id,
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ import { ElectronClipboardService } from '../electron-clipboard-service';
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';

export default new ContainerModule(bind => {
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();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/********************************************************************************
* Copyright (C) 2021 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 { interfaces } from 'inversify';
import { createPreferenceProxy, PreferenceContribution, PreferenceProxy, PreferenceSchema, PreferenceService } from '../../browser/preferences';

export namespace ZoomLevel {
export const DEFAULT = 0;
// copied from https://github.com/microsoft/vscode/blob/dda96b69bfc63f309e60cfc5f98cb863c46b32ac/src/vs/workbench/electron-sandbox/actions/windowActions.ts#L47-L48
export const MIN = -8;
export const MAX = 9;
// amount to increment or decrement the window zoom level.
export const VARIATION = 0.5;
}

export const electronWindowPreferencesSchema: PreferenceSchema = {
type: 'object',
properties: {
'window.zoomLevel': {
'type': 'number',
'default': ZoomLevel.DEFAULT,
'minimum': ZoomLevel.MIN,
'maximum': ZoomLevel.MAX,
'scope': 'application',
// eslint-disable-next-line max-len
'description': 'Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1.0) or below (e.g. -1.0) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity.'
},
}
};

export class ElectronWindowConfiguration {
'window.zoomLevel': number;
}

export const ElectronWindowPreferences = Symbol('ElectronWindowPreferences');
export type ElectronWindowPreferences = PreferenceProxy<ElectronWindowConfiguration>;

export function createElectronWindowPreferences(preferences: PreferenceService): ElectronWindowPreferences {
return createPreferenceProxy(preferences, electronWindowPreferencesSchema);
}

export function bindWindowPreferences(bind: interfaces.Bind): void {
bind(ElectronWindowPreferences).toDynamicValue(ctx => {
const preferences = ctx.container.get<PreferenceService>(PreferenceService);
return createElectronWindowPreferences(preferences);
}).inSingletonScope();

bind(PreferenceContribution).toConstantValue({ schema: electronWindowPreferencesSchema });
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { injectable, inject } from 'inversify';
import { injectable, inject, postConstruct } from 'inversify';
import { remote } from 'electron';
import { NewWindowOptions } from '../../browser/window/window-service';
import { DefaultWindowService } from '../../browser/window/default-window-service';
import { ElectronMainWindowService } from '../../electron-common/electron-main-window-service';
import { ElectronWindowPreferences } from './electron-window-preferences';

@injectable()
export class ElectronWindowService extends DefaultWindowService {
Expand All @@ -36,11 +37,24 @@ export class ElectronWindowService extends DefaultWindowService {
@inject(ElectronMainWindowService)
protected readonly delegate: ElectronMainWindowService;

@inject(ElectronWindowPreferences)
protected readonly electronWindowPreferences: ElectronWindowPreferences;

openNewWindow(url: string, { external }: NewWindowOptions = {}): undefined {
this.delegate.openNewWindow(url, { external });
return undefined;
}

@postConstruct()
protected init(): void {
// Update the default zoom level on startup when the preferences event is fired.
this.electronWindowPreferences.onPreferenceChanged(e => {
if (e.preferenceName === 'window.zoomLevel') {
this.updateWindowZoomLevel();
}
});
}

registerUnloadListeners(): void {
window.addEventListener('beforeunload', event => {
if (this.isUnloading) {
Expand Down Expand Up @@ -85,4 +99,15 @@ export class ElectronWindowService extends DefaultWindowService {
});
return response === 0; // 'Yes', close the window.
}

/**
* Updates the window zoom level based on the preference value.
*/
protected updateWindowZoomLevel(): void {
const preferredZoomLevel = this.electronWindowPreferences['window.zoomLevel'];
const webContents = remote.getCurrentWindow().webContents;
if (webContents.getZoomLevel() !== preferredZoomLevel) {
webContents.setZoomLevel(preferredZoomLevel);
}
}
}

0 comments on commit d15635e

Please sign in to comment.