Skip to content

Commit f7db1dc

Browse files
rebornixsbatten
authored andcommitted
Fullscreen Action. (microsoft#75667)
* move keybinding validator out of keybindingRegistry * Fullscreen Action. * use webkit full screen. * Address comments * align typings
1 parent 351c311 commit f7db1dc

9 files changed

Lines changed: 115 additions & 31 deletions

File tree

src/vs/platform/windows/common/windows.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ export interface IWindowService {
238238
closeWorkspace(): Promise<void>;
239239
updateTouchBar(items: ISerializableCommandAction[][]): Promise<void>;
240240
enterWorkspace(path: URI): Promise<IEnterWorkspaceResult | undefined>;
241-
toggleFullScreen(): Promise<void>;
241+
toggleFullScreen(target?: HTMLElement): Promise<void>;
242242
setRepresentedFilename(fileName: string): Promise<void>;
243243
getRecentlyOpened(): Promise<IRecentlyOpened>;
244244
focusWindow(): Promise<void>;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import * as nls from 'vs/nls';
7+
import { Action } from 'vs/base/common/actions';
8+
import { IWindowService } from 'vs/platform/windows/common/windows';
9+
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
10+
import { Registry } from 'vs/platform/registry/common/platform';
11+
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
12+
import { IsFullscreenContext } from 'vs/workbench/browser/contextkeys';
13+
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
14+
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
15+
16+
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
17+
const viewCategory = nls.localize('view', "View");
18+
19+
export class ToggleFullScreenAction extends Action {
20+
21+
static readonly ID = 'workbench.action.toggleFullScreen';
22+
static LABEL = nls.localize('toggleFullScreen', "Toggle Full Screen");
23+
24+
constructor(
25+
id: string,
26+
label: string,
27+
@IWindowService private readonly windowService: IWindowService,
28+
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService) {
29+
super(id, label);
30+
}
31+
32+
run(): Promise<void> {
33+
const container = this.layoutService.getWorkbenchElement();
34+
return this.windowService.toggleFullScreen(container);
35+
}
36+
}
37+
38+
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleFullScreenAction, ToggleFullScreenAction.ID, ToggleFullScreenAction.LABEL, { primary: KeyCode.F11, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_F } }), 'View: Toggle Full Screen', viewCategory);
39+
40+
// Appereance menu
41+
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
42+
group: '1_toggle_view',
43+
command: {
44+
id: ToggleFullScreenAction.ID,
45+
title: nls.localize({ key: 'miToggleFullScreen', comment: ['&& denotes a mnemonic'] }, "&&Full Screen"),
46+
toggled: IsFullscreenContext
47+
},
48+
order: 1
49+
});

src/vs/workbench/browser/web.simpleservices.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { URI } from 'vs/base/common/uri';
7+
import * as browser from 'vs/base/browser/browser';
78
import { IBackupFileService, IResolvedBackup } from 'vs/workbench/services/backup/common/backup';
89
import { ITextSnapshot } from 'vs/editor/common/model';
910
import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel';
@@ -796,7 +797,46 @@ export class SimpleWindowService implements IWindowService {
796797
return Promise.resolve(undefined);
797798
}
798799

799-
toggleFullScreen(): Promise<void> {
800+
toggleFullScreen(target?: HTMLElement): Promise<void> {
801+
if (!target) {
802+
return Promise.resolve();
803+
}
804+
805+
// Chromium
806+
if ((<any>document).fullscreen !== undefined) {
807+
if (!(<any>document).fullscreen) {
808+
809+
return (<any>target).requestFullscreen().then(() => {
810+
browser.setFullscreen(true);
811+
}).catch(() => {
812+
// if it fails, chromium throws an exception with error undefined.
813+
// re https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullscreen
814+
console.warn('Toggle Full Screen failed');
815+
});
816+
} else {
817+
return document.exitFullscreen().then(() => {
818+
browser.setFullscreen(false);
819+
}).catch(() => {
820+
console.warn('Exit Full Screen failed');
821+
});
822+
}
823+
}
824+
825+
// Safari and Edge 14 are all using webkit prefix
826+
if ((<any>document).webkitIsFullScreen !== undefined) {
827+
try {
828+
if (!(<any>document).webkitIsFullScreen) {
829+
(<any>target).webkitRequestFullscreen(); // it's async, but doesn't return a real promise.
830+
browser.setFullscreen(true);
831+
} else {
832+
(<any>document).webkitExitFullscreen(); // it's async, but doesn't return a real promise.
833+
browser.setFullscreen(false);
834+
}
835+
} catch {
836+
console.warn('Enter/Exit Full Screen failed');
837+
}
838+
}
839+
800840
return Promise.resolve();
801841
}
802842

src/vs/workbench/electron-browser/actions/windowActions.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,6 @@ export class NewWindowAction extends Action {
6161
}
6262
}
6363

64-
export class ToggleFullScreenAction extends Action {
65-
66-
static readonly ID = 'workbench.action.toggleFullScreen';
67-
static LABEL = nls.localize('toggleFullScreen', "Toggle Full Screen");
68-
69-
constructor(id: string, label: string, @IWindowService private readonly windowService: IWindowService) {
70-
super(id, label);
71-
}
72-
73-
run(): Promise<void> {
74-
return this.windowService.toggleFullScreen();
75-
}
76-
}
77-
7864
export abstract class BaseZoomAction extends Action {
7965
private static readonly SETTING_KEY = 'window.zoomLevel';
8066

src/vs/workbench/electron-browser/main.contribution.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
1313
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
1414
import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenTwitterUrlAction, OpenRequestFeatureUrlAction, OpenPrivacyStatementUrlAction, OpenLicenseUrlAction, OpenNewsletterSignupUrlAction } from 'vs/workbench/electron-browser/actions/helpActions';
1515
import { ToggleSharedProcessAction, InspectContextKeysAction, ToggleScreencastModeAction, ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions';
16-
import { ShowAboutDialogAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, OpenRecentAction, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ReloadWindowAction, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions';
16+
import { ShowAboutDialogAction, ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, OpenRecentAction, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ReloadWindowAction, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions';
1717
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, DuplicateWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction, CloseWorkspaceAction, OpenLocalFileAction, OpenLocalFolderAction, OpenLocalFileFolderAction, SaveLocalFileAction } from 'vs/workbench/browser/actions/workspaceActions';
1818
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
1919
import { inQuickOpenContext, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen';
2020
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
2121
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
2222
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
2323
import { ADD_ROOT_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
24-
import { SupportsWorkspacesContext, IsMacContext, HasMacNativeTabsContext, IsDevelopmentContext, WorkbenchStateContext, WorkspaceFolderCountContext, RemoteFileDialogContext, IsFullscreenContext } from 'vs/workbench/browser/contextkeys';
24+
import { SupportsWorkspacesContext, IsMacContext, HasMacNativeTabsContext, IsDevelopmentContext, WorkbenchStateContext, WorkspaceFolderCountContext, RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys';
2525
import { NoEditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor';
2626
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
2727
import { LogStorageAction } from 'vs/platform/storage/node/storageService';
@@ -80,7 +80,6 @@ import product from 'vs/platform/product/node/product';
8080
registry.registerWorkbenchAction(new SyncActionDescriptor(ZoomInAction, ZoomInAction.ID, ZoomInAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.US_EQUAL, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_EQUAL, KeyMod.CtrlCmd | KeyCode.NUMPAD_ADD] }), 'View: Zoom In', viewCategory);
8181
registry.registerWorkbenchAction(new SyncActionDescriptor(ZoomOutAction, ZoomOutAction.ID, ZoomOutAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.US_MINUS, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_MINUS, KeyMod.CtrlCmd | KeyCode.NUMPAD_SUBTRACT], linux: { primary: KeyMod.CtrlCmd | KeyCode.US_MINUS, secondary: [KeyMod.CtrlCmd | KeyCode.NUMPAD_SUBTRACT] } }), 'View: Zoom Out', viewCategory);
8282
registry.registerWorkbenchAction(new SyncActionDescriptor(ZoomResetAction, ZoomResetAction.ID, ZoomResetAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.NUMPAD_0 }), 'View: Reset Zoom', viewCategory);
83-
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleFullScreenAction, ToggleFullScreenAction.ID, ToggleFullScreenAction.LABEL, { primary: KeyCode.F11, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_F } }), 'View: Toggle Full Screen', viewCategory);
8483
})();
8584

8685
// Actions: Window
@@ -344,17 +343,6 @@ import product from 'vs/platform/product/node/product';
344343
when: IsMacContext.toNegated()
345344
});
346345

347-
// Appereance menu
348-
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
349-
group: '1_toggle_view',
350-
command: {
351-
id: ToggleFullScreenAction.ID,
352-
title: nls.localize({ key: 'miToggleFullScreen', comment: ['&& denotes a mnemonic'] }, "&&Full Screen"),
353-
toggled: IsFullscreenContext
354-
},
355-
order: 1
356-
});
357-
358346
// Zoom
359347

360348
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {

src/vs/workbench/services/keybinding/browser/keybindingService.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import * as objects from 'vs/base/common/objects';
4646
import { IKeymapService } from 'vs/workbench/services/keybinding/common/keymapService';
4747
import { getDispatchConfig } from 'vs/workbench/services/keybinding/common/dispatchConfig';
4848
import { isArray } from 'vs/base/common/types';
49+
import { INavigatorWithKeyboard } from 'vs/workbench/services/keybinding/common/navigatorKeyboard';
4950

5051
interface ContributedKeyBinding {
5152
command: string;
@@ -237,6 +238,24 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
237238
telemetryService.publicLog('keyboardLayout', {
238239
currentKeyboardLayout: data
239240
});
241+
242+
this._register(browser.onDidChangeFullscreen(() => {
243+
const keyboard = (<INavigatorWithKeyboard>navigator).keyboard;
244+
245+
if (!keyboard) {
246+
return;
247+
}
248+
249+
if (browser.isFullscreen()) {
250+
keyboard.lock(['Escape']);
251+
} else {
252+
keyboard.unlock();
253+
}
254+
255+
// update resolver which will bring back all unbound keyboard shortcuts
256+
this._cachedResolver = null;
257+
this._onDidUpdateKeybindings.fire({ source: KeybindingSource.User });
258+
}));
240259
}
241260

242261
public _dumpDebugInfo(): string {

src/vs/workbench/services/window/electron-browser/windowService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export class WindowService extends Disposable implements IWindowService {
109109
return this.windowsService.closeWindow(this.windowId);
110110
}
111111

112-
toggleFullScreen(): Promise<void> {
112+
toggleFullScreen(target?: HTMLElement): Promise<void> {
113113
return this.windowsService.toggleFullScreen(this.windowId);
114114
}
115115

src/vs/workbench/workbench.main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import 'vs/workbench/electron-browser/main';
2020
//#region --- workbench actions
2121

2222
import 'vs/workbench/browser/actions/layoutActions';
23+
import 'vs/workbench/browser/actions/windowActions';
2324
import 'vs/workbench/browser/actions/listCommands';
2425
import 'vs/workbench/browser/actions/navigationActions';
2526
import 'vs/workbench/browser/parts/quickopen/quickOpenActions';

src/vs/workbench/workbench.web.main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import 'vs/workbench/browser/web.main';
2020
//#region --- workbench actions
2121

2222
import 'vs/workbench/browser/actions/layoutActions';
23+
import 'vs/workbench/browser/actions/windowActions';
2324
import 'vs/workbench/browser/actions/listCommands';
2425
import 'vs/workbench/browser/actions/navigationActions';
2526
import 'vs/workbench/browser/parts/quickopen/quickOpenActions';

0 commit comments

Comments
 (0)