Skip to content

Commit

Permalink
Adopt WCO for Windows (#147947)
Browse files Browse the repository at this point in the history
* add api to native host service

* get working on windows

* switching machines

* working on windows+web

* fix for macos

* fix initial window control colors

* address comments

* add windows check for calling over to main process

* 💄

* 💄

Co-authored-by: Benjamin Pasero <benjamin.pasero@gmail.com>
  • Loading branch information
sbatten and bpasero authored May 2, 2022
1 parent 708cb0c commit 78914e7
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 175 deletions.
2 changes: 2 additions & 0 deletions src/vs/platform/native/common/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ export interface ICommonNativeHostService {
unmaximizeWindow(): Promise<void>;
minimizeWindow(): Promise<void>;

updateTitleBarOverlay(backgroundColor: string, foregroundColor: string): Promise<void>;

setMinimumSize(width: number | undefined, height: number | undefined): Promise<void>;

saveWindowSplash(splash: IPartsSplash): Promise<void>;
Expand Down
14 changes: 14 additions & 0 deletions src/vs/platform/native/electron-main/nativeHostMainService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,20 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
}
}

async updateTitleBarOverlay(windowId: number | undefined, backgroundColor: string, foregroundColor: string): Promise<void> {
if (!isWindows) {
return; // Windows only
}

const window = this.windowById(windowId);
if (window?.win) {
window.win.setTitleBarOverlay({
color: backgroundColor,
symbolColor: foregroundColor
});
}
}

async focusWindow(windowId: number | undefined, options?: { windowId?: number; force?: boolean }): Promise<void> {
if (options && typeof options.windowId === 'number') {
windowId = options.windowId;
Expand Down
14 changes: 14 additions & 0 deletions src/vs/platform/windows/electron-main/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { IWindowsMainService, OpenContext } from 'vs/platform/windows/electron-m
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService';
import { IWindowState, ICodeWindow, ILoadEvent, WindowMode, WindowError, LoadReason, defaultWindowState } from 'vs/platform/window/electron-main/window';
import { Color } from 'vs/base/common/color';

export interface IWindowCreationOptions {
state: IWindowState;
Expand Down Expand Up @@ -246,6 +247,19 @@ export class CodeWindow extends Disposable implements ICodeWindow {
if (!isMacintosh) {
options.frame = false;
}

if (isWindows) {
// This logic will not perfectly guess the right colors to use on initialization,
// but prefer to keep things simple as it is temporary and not noticeable
const titleBarColor = this.themeMainService.getWindowSplash()?.colorInfo.titleBarBackground ?? this.themeMainService.getBackgroundColor();
const symbolColor = Color.fromHex(titleBarColor).isDarker() ? '#FFFFFF' : '#000000';

options.titleBarOverlay = {
height: 29, // The smallest size of the title bar on windows accounting for the border on windows 11
color: titleBarColor,
symbolColor
};
}
}

// Create the browser window
Expand Down
207 changes: 118 additions & 89 deletions src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,51 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

.monaco-workbench .part.titlebar > .titlebar-container {
/* Part Element */
.monaco-workbench .part.titlebar {
display: flex;
flex-direction: row;
}

.monaco-workbench.mac .part.titlebar {
flex-direction: row-reverse;
}

/* Root Container */
.monaco-workbench .part.titlebar>.titlebar-container {
box-sizing: border-box;
width: 100%;
padding: 0 70px;
overflow: hidden;
flex-shrink: 0;
flex-shrink: 1;
flex-grow: 1;
align-items: center;
justify-content: center;
user-select: none;
-webkit-user-select: none;
zoom: 1; /* prevent zooming */
line-height: 22px;
height: 22px;
display: flex;
height: 100%;
width: 100%;
}

/* Account for zooming */
.monaco-workbench .part.titlebar>.titlebar-container.counter-zoom {
zoom: calc(1.0 / var(--zoom-factor));
}

/* Platform specific root element */
.monaco-workbench.mac .part.titlebar>.titlebar-container {
line-height: 22px;
}

.monaco-workbench .part.titlebar > .titlebar-container {
transform-origin: 0 0;
.monaco-workbench.web .part.titlebar>.titlebar-container,
.monaco-workbench.windows .part.titlebar>.titlebar-container,
.monaco-workbench.linux .part.titlebar>.titlebar-container {
height: 30px;
line-height: 30px;
justify-content: left;
}

.monaco-workbench .part.titlebar > .titlebar-container > .titlebar-drag-region {
/* Draggable region */
.monaco-workbench .part.titlebar>.titlebar-container>.titlebar-drag-region {
top: 0;
left: 0;
display: block;
Expand All @@ -33,6 +57,7 @@
-webkit-app-region: drag;
}

/* Command Center */
.monaco-workbench .part.titlebar>.titlebar-container>.title-menu .action-item.quickopen {
color: var(--vscode-input-foreground);
border: 1px solid var(--vscode-dropdown-border);
Expand Down Expand Up @@ -67,83 +92,97 @@
margin-left: auto;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-title {
/* Window title text */
.monaco-workbench .part.titlebar>.titlebar-container>.window-title {
flex: 0 1 auto;
font-size: 12px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin-left: auto;
margin-right: auto;
zoom: 1; /* prevent zooming */
}

.monaco-workbench .part.titlebar > .titlebar-container.enable-title-menu > .window-title {
display: none;
}

/* Windows/Linux: Rules for custom title (icon, window controls) */
.monaco-workbench.web .part.titlebar > .titlebar-container,
.monaco-workbench.windows .part.titlebar > .titlebar-container,
.monaco-workbench.linux .part.titlebar > .titlebar-container {
.monaco-workbench.web .part.titlebar>.titlebar-container,
.monaco-workbench.windows .part.titlebar>.titlebar-container,
.monaco-workbench.linux .part.titlebar>.titlebar-container {
padding: 0;
height: 30px;
line-height: 30px;
justify-content: left;
overflow: visible;
}

.monaco-workbench.web .part.titlebar > .titlebar-container > .window-title,
.monaco-workbench.windows .part.titlebar > .titlebar-container > .window-title,
.monaco-workbench.linux .part.titlebar > .titlebar-container > .window-title {
.monaco-workbench.web .part.titlebar>.titlebar-container>.window-title,
.monaco-workbench.windows .part.titlebar>.titlebar-container>.window-title,
.monaco-workbench.linux .part.titlebar>.titlebar-container>.window-title {
cursor: default;
}

.monaco-workbench .part.titlebar > .titlebar-container > .menubar {
/* move menubar above drag region as negative z-index on drag region cause greyscale AA */
z-index: 2500;
.monaco-workbench .part.titlebar>.titlebar-container.enable-title-menu>.window-title {
display: none;
}

.monaco-workbench.linux .part.titlebar > .titlebar-container > .window-title {
.monaco-workbench.linux .part.titlebar>.titlebar-container>.window-title {
font-size: inherit;
/* see #55435 */
}

/* Menubar */
.monaco-workbench .part.titlebar>.titlebar-container>.menubar {
/* move menubar above drag region as negative z-index on drag region cause greyscale AA */
z-index: 2500;
min-width: 36px;
}

.monaco-workbench.windows .part.titlebar > .titlebar-container > .resizer,
.monaco-workbench.linux .part.titlebar > .titlebar-container > .resizer {
/* Resizer */
.monaco-workbench.windows .part.titlebar>.titlebar-container>.resizer,
.monaco-workbench.linux .part.titlebar>.titlebar-container>.resizer {
-webkit-app-region: no-drag;
position: absolute;
top: 0;
width: 100%;
height: 4px;
}

.monaco-workbench.windows.fullscreen .part.titlebar > .titlebar-container > .resizer,
.monaco-workbench.linux.fullscreen .part.titlebar > .titlebar-container > .resizer {
.monaco-workbench.windows.fullscreen .part.titlebar>.titlebar-container>.resizer,
.monaco-workbench.linux.fullscreen .part.titlebar>.titlebar-container>.resizer {
display: none;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-appicon {
/* App Icon */
.monaco-workbench .part.titlebar>.titlebar-container>.window-appicon {
width: 35px;
height: 100%;
position: relative;
z-index: 3000;
flex-shrink: 0;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-appicon:not(.codicon) {
.monaco-workbench .part.titlebar>.titlebar-container>.window-appicon:not(.codicon) {
background-image: url('../../../media/code-icon.svg');
background-repeat: no-repeat;
background-position: center center;
background-size: 16px;
}

.monaco-workbench .part.titlebar > .titlebar-container .window-appicon > .home-bar-icon-badge {
.monaco-workbench .part.titlebar>.titlebar-container>.window-appicon.codicon {
line-height: 30px;
}

.monaco-workbench.fullscreen .part.titlebar>.titlebar-container>.window-appicon {
display: none;
}

.monaco-workbench .part.titlebar>.titlebar-container .window-appicon>.home-bar-icon-badge {
position: absolute;
right: 9px;
bottom: 6px;
width: 8px;
height: 8px;
z-index: 1; /* on top of home indicator */
z-index: 1;
/* on top of home indicator */
background-image: url('../../../media/code-icon.svg');
background-repeat: no-repeat;
background-position: center center;
Expand All @@ -153,90 +192,80 @@
border-left: 1px solid transparent;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-appicon.codicon {
line-height: 30px;
}

.monaco-workbench.fullscreen .part.titlebar > .titlebar-container > .window-appicon {
display: none;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-controls-container {
/* Window Controls (Minimize, Max/Restore, Close) */
.monaco-workbench .part.titlebar>.window-controls-container {
display: flex;
flex-grow: 0;
flex-shrink: 0;
text-align: center;
position: relative;
z-index: 3000;
-webkit-app-region: no-drag;
height: 100%;
min-width: 138px;
margin-left: auto;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-controls-container.show-layout-control {
min-width: 160px;
}

.monaco-workbench.web .part.titlebar > .titlebar-container > .window-controls-container.show-layout-control {
min-width: 28px;
padding-right: 8px;
}

.monaco-workbench.mac:not(.web) .part.titlebar > .titlebar-container > .window-controls-container {
position: absolute;
right: 8px;
min-width: 28px;
display: none;
height: 30px;
width: 138px;
zoom: calc(1 / var(--zoom-factor));
}

.monaco-workbench.mac:not(.web) .part.titlebar > .titlebar-container > .window-controls-container.show-layout-control {
display: flex;
.monaco-workbench.mac .part.titlebar>.window-controls-container {
width: 70px;
height: env(titlebar-area-width, 28px);
}

.monaco-workbench.fullscreen .part.titlebar > .titlebar-container > .window-controls-container {
.monaco-workbench.web .part.titlebar>.window-controls-container,
.monaco-workbench.fullscreen .part.titlebar>.window-controls-container {
display: none;
background-color: transparent;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-controls-container > .layout-dropdown-container {
padding-right: 2px;
display: none;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-controls-container.show-layout-control > .layout-dropdown-container {
display: flex;
justify-content: center;
}

.monaco-workbench:not(.mac):not(.web) .part.titlebar > .titlebar-container > .window-controls-container.show-layout-control > .layout-dropdown-container {
min-width: 46px;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-controls-container.show-layout-control > .layout-dropdown-container .codicon {
color: inherit;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-controls-container > .window-icon {
/* Window Control Icons */
.monaco-workbench .part.titlebar>.window-controls-container>.window-icon {
display: inline-block;
line-height: 30px;
height: 100%;
width: 46px;
font-size: 16px;
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-controls-container > .window-icon:hover {
.monaco-workbench .part.titlebar>.window-controls-container>.window-icon:hover {
background-color: rgba(255, 255, 255, 0.1);
}

.monaco-workbench .part.titlebar.light > .titlebar-container > .window-controls-container > .window-icon:hover {
.monaco-workbench .part.titlebar.light>.window-controls-container>.window-icon:hover {
background-color: rgba(0, 0, 0, 0.1);
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-controls-container > .window-icon.window-close:hover {
.monaco-workbench .part.titlebar>.window-controls-container>.window-icon.window-close:hover {
background-color: rgba(232, 17, 35, 0.9);
}

.monaco-workbench .part.titlebar > .titlebar-container > .window-controls-container .window-icon.window-close:hover {
.monaco-workbench .part.titlebar>.window-controls-container .window-icon.window-close:hover {
color: white;
}

/* Layout Controls */
.monaco-workbench .part.titlebar>.titlebar-container>.layout-controls-container {
display: none;
padding-right: 2px;
flex-grow: 0;
flex-shrink: 0;
text-align: center;
position: relative;
z-index: 3000;
-webkit-app-region: no-drag;
height: 100%;
margin-left: auto;
min-width: 28px;
}

.monaco-workbench.mac:not(.web) .part.titlebar>.layout-controls-container {
position: absolute;
right: 8px;
}

.monaco-workbench .part.titlebar>.titlebar-container>.layout-controls-container.show-layout-control {
display: flex;
justify-content: center;
}

.monaco-workbench .part.titlebar>.titlebar-container>.layout-controls-container .codicon {
color: inherit;
}
4 changes: 0 additions & 4 deletions src/vs/workbench/browser/parts/titlebar/menubarControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -921,10 +921,6 @@ export class CustomMenubarControl extends MenubarControl {
}

layout(dimension: Dimension) {
if (this.container) {
this.container.style.height = `${dimension.height}px`;
}

this.menubar?.update(this.getMenuBarOptions());
}

Expand Down
Loading

0 comments on commit 78914e7

Please sign in to comment.