Skip to content

Commit

Permalink
aux window - make more native window options available (#198829)
Browse files Browse the repository at this point in the history
aux window - make more native window options available
  • Loading branch information
bpasero authored Nov 22, 2023
1 parent f3da7cb commit 30c4958
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 72 deletions.
14 changes: 14 additions & 0 deletions src/vs/platform/window/common/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,20 @@ export function useWindowControlsOverlay(configurationService: IConfigurationSer
return true;
}

export function useNativeFullScreen(configurationService: IConfigurationService): boolean {
const windowConfig = configurationService.getValue<IWindowSettings | undefined>('window');
if (!windowConfig || typeof windowConfig.nativeFullScreen !== 'boolean') {
return true; // default
}

if (windowConfig.nativeTabs) {
return true; // https://github.com/electron/electron/issues/16142
}

return windowConfig.nativeFullScreen !== false;
}


export interface IPath<T = IEditorOptions> extends IPathData<T> {

/**
Expand Down
121 changes: 50 additions & 71 deletions src/vs/platform/windows/electron-main/windowImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { IApplicationStorageMainService, IStorageMainService } from 'vs/platform
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ThemeIcon } from 'vs/base/common/themables';
import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService';
import { getMenuBarVisibility, getTitleBarStyle, IFolderToOpen, INativeWindowConfiguration, IWindowSettings, IWorkspaceToOpen, MenuBarVisibility, useWindowControlsOverlay } from 'vs/platform/window/common/window';
import { getMenuBarVisibility, getTitleBarStyle, IFolderToOpen, INativeWindowConfiguration, IWindowSettings, IWorkspaceToOpen, MenuBarVisibility, useNativeFullScreen, useWindowControlsOverlay } from 'vs/platform/window/common/window';
import { defaultBrowserWindowOptions, IWindowsMainService, OpenContext } from 'vs/platform/windows/electron-main/windows';
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, toWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService';
Expand Down Expand Up @@ -163,7 +163,7 @@ export abstract class BaseWindow extends Disposable implements IBaseWindow {
protected setFullScreen(fullscreen: boolean): void {

// Set fullscreen state
if (this.useNativeFullScreen()) {
if (useNativeFullScreen(this.configurationService)) {
this.setNativeFullScreen(fullscreen);
} else {
this.setSimpleFullScreen(fullscreen);
Expand Down Expand Up @@ -223,19 +223,6 @@ export abstract class BaseWindow extends Disposable implements IBaseWindow {
win?.webContents.focus(); // workaround issue where focus is not going into window
}

protected useNativeFullScreen(): boolean {
const windowConfig = this.configurationService.getValue<IWindowSettings | undefined>('window');
if (!windowConfig || typeof windowConfig.nativeFullScreen !== 'boolean') {
return true; // default
}

if (windowConfig.nativeTabs) {
return true; // https://github.com/electron/electron/issues/16142
}

return windowConfig.nativeFullScreen !== false;
}

//#endregion
}

Expand Down Expand Up @@ -356,8 +343,6 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
// after the call to maximize/fullscreen (see below)
const isFullscreenOrMaximized = (this.windowState.mode === WindowMode.Maximized || this.windowState.mode === WindowMode.Fullscreen);

const windowSettings = this.configurationService.getValue<IWindowSettings | undefined>('window');

const options = instantiationService.invokeFunction(defaultBrowserWindowOptions, this.windowState, {
show: !isFullscreenOrMaximized, // reduce flicker by showing later
webPreferences: {
Expand All @@ -367,15 +352,6 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
}
});

if (isMacintosh && !this.useNativeFullScreen()) {
options.fullscreenable = false; // enables simple fullscreen mode
}

const useNativeTabs = isMacintosh && windowSettings?.nativeTabs === true;
if (useNativeTabs) {
options.tabbingIdentifier = this.productService.nameShort; // this opts in to sierra tabs
}

const useCustomTitleStyle = getTitleBarStyle(this.configurationService) === 'custom';
if (useCustomTitleStyle) {
options.titleBarStyle = 'hidden';
Expand Down Expand Up @@ -421,51 +397,6 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
}
}

// Windows Custom System Context Menu
// See https://github.com/electron/electron/issues/24893
//
// The purpose of this is to allow for the context menu in the Windows Title Bar
//
// Currently, all mouse events in the title bar are captured by the OS
// thus we need to capture them here with a window hook specific to Windows
// and then forward them to the correct window.
if (isWindows && useCustomTitleStyle) {
const WM_INITMENU = 0x0116; // https://docs.microsoft.com/en-us/windows/win32/menurc/wm-initmenu

// This sets up a listener for the window hook. This is a Windows-only API provided by electron.
this._win.hookWindowMessage(WM_INITMENU, () => {
const [x, y] = this._win.getPosition();
const cursorPos = screen.getCursorScreenPoint();
const cx = cursorPos.x - x;
const cy = cursorPos.y - y;

// In some cases, show the default system context menu
// 1) The mouse position is not within the title bar
// 2) The mouse position is within the title bar, but over the app icon
// We do not know the exact title bar height but we make an estimate based on window height
const shouldTriggerDefaultSystemContextMenu = () => {
// Use the custom context menu when over the title bar, but not over the app icon
// The app icon is estimated to be 30px wide
// The title bar is estimated to be the max of 35px and 15% of the window height
if (cx > 30 && cy >= 0 && cy <= Math.max(this._win.getBounds().height * 0.15, 35)) {
return false;
}

return true;
};

if (!shouldTriggerDefaultSystemContextMenu()) {
// This is necessary to make sure the native system context menu does not show up.
this._win.setEnabled(false);
this._win.setEnabled(true);

this._onDidTriggerSystemContextMenu.fire({ x: cx, y: cy });
}

return 0;
});
}

// TODO@electron (Electron 4 regression): when running on multiple displays where the target display
// to open the window has a larger resolution than the primary display, the window will not size
// correctly unless we set the bounds again (https://github.com/microsoft/vscode/issues/74872)
Expand All @@ -475,6 +406,8 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
// However, when running with native tabs with multiple windows we cannot use this workaround
// because there is a potential that the new window will be added as native tab instead of being
// a window on its own. In that case calling setBounds() would cause https://github.com/microsoft/vscode/issues/75830
const windowSettings = this.configurationService.getValue<IWindowSettings | undefined>('window');
const useNativeTabs = isMacintosh && windowSettings?.nativeTabs === true;
if ((isMacintosh || isWindows) && hasMultipleDisplays && (!useNativeTabs || BrowserWindow.getAllWindows().length === 1)) {
if ([this.windowState.width, this.windowState.height, this.windowState.x, this.windowState.y].every(value => typeof value === 'number')) {
this._win.setBounds({
Expand Down Expand Up @@ -654,6 +587,52 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {

cb({ cancel: false, requestHeaders: Object.assign(details.requestHeaders, headers) });
});

// Windows Custom System Context Menu
// See https://github.com/electron/electron/issues/24893
//
// The purpose of this is to allow for the context menu in the Windows Title Bar
//
// Currently, all mouse events in the title bar are captured by the OS
// thus we need to capture them here with a window hook specific to Windows
// and then forward them to the correct window.
const useCustomTitleStyle = getTitleBarStyle(this.configurationService) === 'custom';
if (isWindows && useCustomTitleStyle) {
const WM_INITMENU = 0x0116; // https://docs.microsoft.com/en-us/windows/win32/menurc/wm-initmenu

// This sets up a listener for the window hook. This is a Windows-only API provided by electron.
this._win.hookWindowMessage(WM_INITMENU, () => {
const [x, y] = this._win.getPosition();
const cursorPos = screen.getCursorScreenPoint();
const cx = cursorPos.x - x;
const cy = cursorPos.y - y;

// In some cases, show the default system context menu
// 1) The mouse position is not within the title bar
// 2) The mouse position is within the title bar, but over the app icon
// We do not know the exact title bar height but we make an estimate based on window height
const shouldTriggerDefaultSystemContextMenu = () => {
// Use the custom context menu when over the title bar, but not over the app icon
// The app icon is estimated to be 30px wide
// The title bar is estimated to be the max of 35px and 15% of the window height
if (cx > 30 && cy >= 0 && cy <= Math.max(this._win.getBounds().height * 0.15, 35)) {
return false;
}

return true;
};

if (!shouldTriggerDefaultSystemContextMenu()) {
// This is necessary to make sure the native system context menu does not show up.
this._win.setEnabled(false);
this._win.setEnabled(true);

this._onDidTriggerSystemContextMenu.fire({ x: cx, y: cy });
}

return 0;
});
}
}

private marketplaceHeadersPromise: Promise<object> | undefined;
Expand Down
11 changes: 10 additions & 1 deletion src/vs/platform/windows/electron-main/windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { URI } from 'vs/base/common/uri';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { ServicesAccessor, createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ICodeWindow, IWindowState } from 'vs/platform/window/electron-main/window';
import { IOpenEmptyWindowOptions, IWindowOpenable, IWindowSettings, WindowMinimumSize, zoomLevelToZoomFactor } from 'vs/platform/window/common/window';
import { IOpenEmptyWindowOptions, IWindowOpenable, IWindowSettings, WindowMinimumSize, useNativeFullScreen, zoomLevelToZoomFactor } from 'vs/platform/window/common/window';
import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService';
import { IProductService } from 'vs/platform/product/common/productService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
Expand Down Expand Up @@ -160,6 +160,15 @@ export function defaultBrowserWindowOptions(accessor: ServicesAccessor, windowSt
}
}

if (isMacintosh && !useNativeFullScreen(configurationService)) {
options.fullscreenable = false; // enables simple fullscreen mode
}

const useNativeTabs = isMacintosh && windowSettings?.nativeTabs === true;
if (useNativeTabs) {
options.tabbingIdentifier = productService.nameShort; // this opts in to sierra tabs
}

return options;
}

Expand Down

0 comments on commit 30c4958

Please sign in to comment.