Skip to content

Commit

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

What it does

- Adds support to specify window zoom level as a preference

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 ctrl + / - / 0
3. Observe that the zoom level preference is updated
4. Reload the window and observe that the preferred zoom level is
   preserved

Signed-off-by: seantan22 <[email protected]>
  • Loading branch information
seantan22 committed Feb 22, 2021
1 parent c2a82d5 commit 13e44f5
Show file tree
Hide file tree
Showing 4 changed files with 131 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 { WindowPreferences } from '../window/window-preferences';

export namespace ElectronCommands {
export const TOGGLE_DEVELOPER_TOOLS: Command = {
Expand Down Expand Up @@ -68,9 +69,21 @@ export namespace ElectronMenus {
@injectable()
export class ElectronMenuContribution implements FrontendApplicationContribution, CommandContribution, MenuContribution, KeybindingContribution {

// Specified in window-preferences.ts windowPreferencesSchema
protected ZOOM_MIN = -8;
protected ZOOM_MAX = 9;
// Amount to increment or decrement the window zoom level.
protected ZOOM_VARIATION = 0.5;

@inject(FrontendApplicationStateService)
protected readonly stateService: FrontendApplicationStateService;

@inject(PreferenceService)
protected readonly preferenceService: PreferenceService;

@inject(WindowPreferences)
protected readonly windowPreferences: WindowPreferences;

constructor(
@inject(ElectronMainMenuFactory) protected readonly factory: ElectronMainMenuFactory
) { }
Expand Down Expand Up @@ -152,19 +165,31 @@ export class ElectronMenuContribution implements FrontendApplicationContribution
});

registry.registerCommand(ElectronCommands.ZOOM_IN, {
execute: () => {
execute: async () => {
const webContents = currentWindow.webContents;
webContents.setZoomLevel(webContents.zoomLevel + 0.5);
let zoomLevel = this.roundZoomLevel(webContents.zoomLevel, this.ZOOM_VARIATION, true) + this.ZOOM_VARIATION;
if (zoomLevel > this.ZOOM_MAX) {
zoomLevel = this.ZOOM_MAX;
return;
};
this.preferenceService.set('window.zoomLevel', zoomLevel, PreferenceScope.User);
}
});
registry.registerCommand(ElectronCommands.ZOOM_OUT, {
execute: () => {
execute: async () => {
const webContents = currentWindow.webContents;
webContents.setZoomLevel(webContents.zoomLevel - 0.5);
let zoomLevel = this.roundZoomLevel(webContents.zoomLevel, this.ZOOM_VARIATION, false) - this.ZOOM_VARIATION;
if (zoomLevel < this.ZOOM_MIN) {
zoomLevel = this.ZOOM_MIN;
return;
};
this.preferenceService.set('window.zoomLevel', zoomLevel, PreferenceScope.User);
}
});
registry.registerCommand(ElectronCommands.RESET_ZOOM, {
execute: () => currentWindow.webContents.setZoomLevel(0)
execute: async () => {
this.preferenceService.set('window.zoomLevel', 0, PreferenceScope.User);
}
});
}

Expand Down Expand Up @@ -224,4 +249,15 @@ export class ElectronMenuContribution implements FrontendApplicationContribution
});
}

/**
* Returns the zoom level rounded to the nearest multiple of a specified value.
*
* @param zoomLevel the current window zoom level.
* @param nearestMultiple the nearest multiple to round to.
* @param isIncreasing true, if rounding before increasing zoom; false, if rounding before decreasing zoom.
*/
private roundZoomLevel(zoomLevel: number, nearestMultiple: number, isIncreasing: boolean): number {
return isIncreasing ? Math.floor(zoomLevel / nearestMultiple) * nearestMultiple : Math.ceil(zoomLevel / nearestMultiple) * nearestMultiple;
}

}
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 './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
Expand Up @@ -19,6 +19,8 @@ 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 { WindowConfiguration, WindowPreferences } from './window-preferences';
import { PreferenceChangeEvent } from '../../browser';

@injectable()
export class ElectronWindowService extends DefaultWindowService {
Expand All @@ -33,15 +35,26 @@ export class ElectronWindowService extends DefaultWindowService {
*/
protected closeOnUnload: boolean = false;

/**
* Most recent value set for window.zoomLevel preference
*/
protected prevPreferredZoomLevel: number | undefined;

@inject(ElectronMainWindowService)
protected readonly delegate: ElectronMainWindowService;

@inject(WindowPreferences)
protected readonly windowPreferences: WindowPreferences;

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

registerUnloadListeners(): void {
// Update changes to zoom level.
// this.updateWindowZoomLevel(); // window updates before getting the correct window.zoomLevel value
remote.getCurrentWindow().webContents.setZoomLevel(2.5); // hardcoded
window.addEventListener('beforeunload', event => {
if (this.isUnloading) {
// Unloading process ongoing, do nothing:
Expand All @@ -67,6 +80,12 @@ export class ElectronWindowService extends DefaultWindowService {
return this.preventUnload(event);
}
});

this.windowPreferences.onPreferenceChanged((e: PreferenceChangeEvent<WindowConfiguration>) => {
if (e.preferenceName === 'window.zoomLevel') {
this.updateWindowZoomLevel();
}
});
}

/**
Expand All @@ -85,4 +104,20 @@ export class ElectronWindowService extends DefaultWindowService {
});
return response === 0; // 'Yes', close the window.
}

/**
* Updates the window zoom level based on the value set in `Preferences`.
*/
protected updateWindowZoomLevel(): void {
const preferredZoomLevel = this.windowPreferences['window.zoomLevel'];
console.log(`Preferred Zoom Level: ${preferredZoomLevel}`);
if (this.prevPreferredZoomLevel === preferredZoomLevel) {
return;
}
this.prevPreferredZoomLevel = preferredZoomLevel;
const webContents = remote.getCurrentWindow().webContents;
if (webContents.getZoomLevel() !== preferredZoomLevel) {
webContents.setZoomLevel(preferredZoomLevel);
}
}
}
52 changes: 52 additions & 0 deletions packages/core/src/electron-browser/window/window-preferences.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/********************************************************************************
* 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 const windowPreferencesSchema: PreferenceSchema = {
type: 'object',
scope: 'application',
properties: {
'window.zoomLevel': {
'type': 'number',
'default': 0,
'minimum': -8,
'maximum': 9,
'description': 'Adjust the zoom level of the window. The original size is 0. Each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller.'
},
}
};

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

export const WindowPreferences = Symbol('WindowPreferences');
export type WindowPreferences = PreferenceProxy<WindowConfiguration>;

export function createWindowPreferences(preferences: PreferenceService): WindowPreferences {
return createPreferenceProxy(preferences, windowPreferencesSchema);
}

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

bind(PreferenceContribution).toConstantValue({ schema: windowPreferencesSchema });
}

0 comments on commit 13e44f5

Please sign in to comment.