Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Colored titlebar for Windows #39972

Merged
merged 35 commits into from
Jun 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f4e80de
Initial changes
rianadon Aug 26, 2017
ddddfde
Add custom titlebar
rianadon Nov 23, 2017
04f2b9b
Revert vibrancy changes, cross-platform support
rianadon Dec 9, 2017
96c530b
Add hover states for titlebar
rianadon Dec 9, 2017
3fc07e3
Implement button actions, make maximize icon change
rianadon Dec 9, 2017
c758472
Merge with master
rianadon Dec 9, 2017
12a1393
Remove debugging statement
rianadon Dec 9, 2017
7f12e76
Remove formatting changes
rianadon Dec 9, 2017
c840d0d
Remove more formatting changes
rianadon Dec 9, 2017
be8cb21
Fix compilation errors
rianadon Dec 9, 2017
a66d521
Fix code formatting
rianadon Dec 10, 2017
bec93d4
Make icon sizes independent of zoom
rianadon Dec 10, 2017
f2648cd
Make positioning of icons same as otherWindows apps
rianadon Dec 10, 2017
c9bf4c9
Use setting, standard titlebar
rianadon Dec 12, 2017
1fdd9ed
Make sizing consistent with Windows
rianadon Dec 12, 2017
ae5e8d4
Make window resiable from top
rianadon Dec 12, 2017
233784d
More consistency
rianadon Dec 12, 2017
80411d3
Make titlebar render correctly on reload
rianadon Dec 12, 2017
94cb977
More positioning changes
rianadon Dec 12, 2017
b5bdbf1
Merge with master
rianadon Dec 12, 2017
a0b33ed
Merge remote-tracking branch 'upstream/master' into titlebar
bpasero Dec 13, 2017
25e5ca6
Make frame show by default on Windows
rianadon Dec 14, 2017
63f86d2
Merge branch 'titlebar' of https://github.com/rianadon/vscode into ti…
rianadon Dec 14, 2017
961ec4c
Try to make window draggable before load
rianadon Dec 14, 2017
a5a0553
Fix drag issue
rianadon Dec 16, 2017
0c7174b
Remove unnecessary console.log
rianadon Dec 16, 2017
8667ae7
Merge remote-tracking branch 'upstream' into titlebar
rianadon Dec 16, 2017
2afb336
Make Linux compatible
rianadon Dec 17, 2017
4ce2f07
Titlebar fixes for linux
rianadon Dec 17, 2017
b3db9ac
Remove unused import
rianadon Dec 17, 2017
0976b51
Make framless window draggable on LInux
rianadon Dec 17, 2017
dc5f62b
Add hover transitions
rianadon Dec 17, 2017
8c8de9f
Make double-clicking icon close window
rianadon Dec 17, 2017
91ac8c8
Merge remote-tracking branch 'upstream/master' into titlebar
bpasero Mar 24, 2018
c1e4b74
Merge remote-tracking branch 'upstream/master' into titlebar
rianadon May 7, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/vs/code/electron-main/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,10 @@ export class CodeWindow implements ICodeWindow {
}

let useCustomTitleStyle = false;
if (isMacintosh && (!windowConfig || !windowConfig.titleBarStyle || windowConfig.titleBarStyle === 'custom')) {
if ((!isMacintosh && windowConfig && windowConfig.titleBarStyle === 'custom') ||
(isMacintosh && (!windowConfig || !windowConfig.titleBarStyle || windowConfig.titleBarStyle === 'custom'))) {
const isDev = !this.environmentService.isBuilt || !!config.extensionDevelopmentPath;
if (!isDev) {
if (!isMacintosh || !isDev) {
useCustomTitleStyle = true; // not enabled when developing due to https://github.com/electron/electron/issues/3647
}
}
Expand All @@ -180,6 +181,9 @@ export class CodeWindow implements ICodeWindow {
if (useCustomTitleStyle) {
options.titleBarStyle = 'hidden';
this.hiddenTitleBarStyle = true;
if (!isMacintosh) {
options.frame = false;
}
}

// Create the browser window.
Expand Down Expand Up @@ -207,6 +211,9 @@ export class CodeWindow implements ICodeWindow {
this._win.setSheetOffset(22); // offset dialogs by the height of the custom title bar if we have any
}

this._win.on('maximize', (e) => app.emit('browser-window-maximize', e, this._win));
this._win.on('unmaximize', (e) => app.emit('browser-window-unmaximize', e, this._win));

if (isFullscreenOrMaximized) {
this._win.maximize();

Expand Down Expand Up @@ -603,6 +610,7 @@ export class CodeWindow implements ICodeWindow {
// Theme
windowConfiguration.baseTheme = this.getBaseTheme();
windowConfiguration.backgroundColor = this.getBackgroundColor();
windowConfiguration.frameless = this.hasHiddenTitleBarStyle() && !isMacintosh;

// Perf Counters
windowConfiguration.perfEntries = exportEntries();
Expand Down
9 changes: 9 additions & 0 deletions src/vs/platform/windows/common/windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ export interface IWindowsService {
onWindowOpen: Event<number>;
onWindowFocus: Event<number>;
onWindowBlur: Event<number>;
onWindowMaximize: Event<number>;
onWindowUnmaximize: Event<number>;

// Dialogs
pickFileFolderAndOpen(options: INativeOpenDialogOptions): TPromise<void>;
Expand Down Expand Up @@ -131,6 +133,7 @@ export interface IWindowsService {
isMaximized(windowId: number): TPromise<boolean>;
maximizeWindow(windowId: number): TPromise<void>;
unmaximizeWindow(windowId: number): TPromise<void>;
minimizeWindow(windowId: number): TPromise<void>;
onWindowTitleDoubleClick(windowId: number): TPromise<void>;
setDocumentEdited(windowId: number, flag: boolean): TPromise<void>;
quit(): TPromise<void>;
Expand Down Expand Up @@ -181,6 +184,7 @@ export interface IWindowService {
_serviceBrand: any;

onDidChangeFocus: Event<boolean>;
onDidChangeMaximize: Event<boolean>;

getConfiguration(): IWindowConfiguration;
getCurrentWindowId(): number;
Expand All @@ -202,6 +206,10 @@ export interface IWindowService {
closeWindow(): TPromise<void>;
isFocused(): TPromise<boolean>;
setDocumentEdited(flag: boolean): TPromise<void>;
isMaximized(): TPromise<boolean>;
maximizeWindow(): TPromise<void>;
unmaximizeWindow(): TPromise<void>;
minimizeWindow(): TPromise<void>;
onWindowTitleDoubleClick(): TPromise<void>;
show(): TPromise<void>;
showMessageBox(options: MessageBoxOptions): TPromise<IMessageBoxResult>;
Expand Down Expand Up @@ -328,6 +336,7 @@ export interface IWindowConfiguration extends ParsedArgs, IOpenFileRequest {
highContrast?: boolean;
baseTheme?: string;
backgroundColor?: string;
frameless?: boolean;
accessibilitySupport?: boolean;

perfEntries: PerformanceEntry[];
Expand Down
23 changes: 23 additions & 0 deletions src/vs/platform/windows/common/windowsIpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface IWindowsChannel extends IChannel {
call(command: 'isMaximized', arg: number): TPromise<boolean>;
call(command: 'maximizeWindow', arg: number): TPromise<void>;
call(command: 'unmaximizeWindow', arg: number): TPromise<void>;
call(command: 'minimizeWindow', arg: number): TPromise<void>;
call(command: 'onWindowTitleDoubleClick', arg: number): TPromise<void>;
call(command: 'setDocumentEdited', arg: [number, boolean]): TPromise<void>;
call(command: 'quit'): TPromise<void>;
Expand All @@ -73,18 +74,24 @@ export class WindowsChannel implements IWindowsChannel {
private onWindowOpen: Event<number>;
private onWindowFocus: Event<number>;
private onWindowBlur: Event<number>;
private onWindowMaximize: Event<number>;
private onWindowUnmaximize: Event<number>;

constructor(private service: IWindowsService) {
this.onWindowOpen = buffer(service.onWindowOpen, true);
this.onWindowFocus = buffer(service.onWindowFocus, true);
this.onWindowBlur = buffer(service.onWindowBlur, true);
this.onWindowMaximize = buffer(service.onWindowMaximize, true);
this.onWindowUnmaximize = buffer(service.onWindowUnmaximize, true);
}

call(command: string, arg?: any): TPromise<any> {
switch (command) {
case 'event:onWindowOpen': return eventToCall(this.onWindowOpen);
case 'event:onWindowFocus': return eventToCall(this.onWindowFocus);
case 'event:onWindowBlur': return eventToCall(this.onWindowBlur);
case 'event:onWindowMaximize': return eventToCall(this.onWindowMaximize);
case 'event:onWindowUnmaximize': return eventToCall(this.onWindowUnmaximize);
case 'pickFileFolderAndOpen': return this.service.pickFileFolderAndOpen(arg);
case 'pickFileAndOpen': return this.service.pickFileAndOpen(arg);
case 'pickFolderAndOpen': return this.service.pickFolderAndOpen(arg);
Expand Down Expand Up @@ -129,6 +136,7 @@ export class WindowsChannel implements IWindowsChannel {
case 'isMaximized': return this.service.isMaximized(arg);
case 'maximizeWindow': return this.service.maximizeWindow(arg);
case 'unmaximizeWindow': return this.service.unmaximizeWindow(arg);
case 'minimizeWindow': return this.service.minimizeWindow(arg);
case 'onWindowTitleDoubleClick': return this.service.onWindowTitleDoubleClick(arg);
case 'setDocumentEdited': return this.service.setDocumentEdited(arg[0], arg[1]);
case 'openWindow': return this.service.openWindow(arg[0], arg[1]);
Expand Down Expand Up @@ -165,6 +173,13 @@ export class WindowsChannelClient implements IWindowsService {
private _onWindowBlur: Event<number> = eventFromCall<number>(this.channel, 'event:onWindowBlur');
get onWindowBlur(): Event<number> { return this._onWindowBlur; }

private _onWindowMaximize: Event<number> = eventFromCall<number>(this.channel, 'event:onWindowMaximize');
get onWindowMaximize(): Event<number> { return this._onWindowMaximize; }

private _onWindowUnmaximize: Event<number> = eventFromCall<number>(this.channel, 'event:onWindowUnmaximize');
get onWindowUnmaximize(): Event<number> { return this._onWindowUnmaximize; }


pickFileFolderAndOpen(options: INativeOpenDialogOptions): TPromise<void> {
return this.channel.call('pickFileFolderAndOpen', options);
}
Expand Down Expand Up @@ -285,6 +300,14 @@ export class WindowsChannelClient implements IWindowsService {
return this.channel.call('unmaximizeWindow', windowId);
}

minimizeWindow(windowId: number): TPromise<void> {
return this.channel.call('minimizeWindow', windowId);
}

addMaximizeListener(windowId: number, listener: (maximized: boolean) => void): TPromise<void> {
return TPromise.as(null);
}

onWindowTitleDoubleClick(windowId: number): TPromise<void> {
return this.channel.call('onWindowTitleDoubleClick', windowId);
}
Expand Down
20 changes: 20 additions & 0 deletions src/vs/platform/windows/electron-browser/windowService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ParsedArgs } from 'vs/platform/environment/common/environment';
export class WindowService implements IWindowService {

readonly onDidChangeFocus: Event<boolean>;
readonly onDidChangeMaximize: Event<boolean>;

_serviceBrand: any;

Expand All @@ -26,7 +27,10 @@ export class WindowService implements IWindowService {
) {
const onThisWindowFocus = mapEvent(filterEvent(windowsService.onWindowFocus, id => id === windowId), _ => true);
const onThisWindowBlur = mapEvent(filterEvent(windowsService.onWindowBlur, id => id === windowId), _ => false);
const onThisWindowMaximize = mapEvent(filterEvent(windowsService.onWindowMaximize, id => id === windowId), _ => true);
const onThisWindowUnmaximize = mapEvent(filterEvent(windowsService.onWindowUnmaximize, id => id === windowId), _ => false);
this.onDidChangeFocus = anyEvent(onThisWindowFocus, onThisWindowBlur);
this.onDidChangeMaximize = anyEvent(onThisWindowMaximize, onThisWindowUnmaximize);
}

getCurrentWindowId(): number {
Expand Down Expand Up @@ -109,6 +113,22 @@ export class WindowService implements IWindowService {
return this.windowsService.isFocused(this.windowId);
}

isMaximized(): TPromise<boolean> {
return this.windowsService.isMaximized(this.windowId);
}

maximizeWindow(): TPromise<void> {
return this.windowsService.maximizeWindow(this.windowId);
}

unmaximizeWindow(): TPromise<void> {
return this.windowsService.unmaximizeWindow(this.windowId);
}

minimizeWindow(): TPromise<void> {
return this.windowsService.minimizeWindow(this.windowId);
}

onWindowTitleDoubleClick(): TPromise<void> {
return this.windowsService.onWindowTitleDoubleClick(this.windowId);
}
Expand Down
14 changes: 13 additions & 1 deletion src/vs/platform/windows/electron-main/windowsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
);

readonly onWindowBlur: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-blur', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));
readonly onWindowMaximize: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-maximize', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));
readonly onWindowUnmaximize: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-unmaximize', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));

constructor(
private sharedProcess: ISharedProcess,
Expand Down Expand Up @@ -338,6 +340,16 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
return TPromise.as(null);
}

minimizeWindow(windowId: number): TPromise<void> {
const codeWindow = this.windowsMainService.getWindowById(windowId);

if (codeWindow) {
codeWindow.win.minimize();
}

return TPromise.as(null);
}

onWindowTitleDoubleClick(windowId: number): TPromise<void> {
this.logService.trace('windowsService#onWindowTitleDoubleClick', windowId);
const codeWindow = this.windowsMainService.getWindowById(windowId);
Expand Down Expand Up @@ -510,4 +522,4 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
dispose(): void {
this.disposables = dispose(this.disposables);
}
}
}
16 changes: 14 additions & 2 deletions src/vs/workbench/browser/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { getZoomFactor } from 'vs/base/browser/browser';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { isMacintosh } from 'vs/base/common/platform';
import { memoize } from 'vs/base/common/decorators';
import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter';
import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts';
Expand All @@ -36,7 +37,7 @@ const PANEL_SIZE_BEFORE_MAXIMIZED_BOUNDARY = 0.7;
const HIDE_SIDEBAR_WIDTH_THRESHOLD = 50;
const HIDE_PANEL_HEIGHT_THRESHOLD = 50;
const HIDE_PANEL_WIDTH_THRESHOLD = 100;
const TITLE_BAR_HEIGHT = 22;
const TITLE_BAR_HEIGHT = isMacintosh ? 22 : 29;
const STATUS_BAR_HEIGHT = 22;
const ACTIVITY_BAR_WIDTH = 50;

Expand Down Expand Up @@ -78,6 +79,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal
private sashY: Sash;
private _sidebarWidth: number;
private sidebarHeight: number;
private titlebarBaseHeight: number;
private titlebarHeight: number;
private statusbarHeight: number;
private panelSizeBeforeMaximized: number;
Expand Down Expand Up @@ -149,6 +151,8 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal
this.toUnbind.push(editorGroupService.onEditorsChanged(() => this.onEditorsChanged()));
this.toUnbind.push(editorGroupService.onGroupOrientationChanged(e => this.onGroupOrientationChanged()));

this.onMaximizeChange(false);

this.registerSashListeners();
}

Expand Down Expand Up @@ -463,7 +467,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal
}

this.statusbarHeight = isStatusbarHidden ? 0 : this.partLayoutInfo.statusbar.height;
this.titlebarHeight = isTitlebarHidden ? 0 : this.partLayoutInfo.titlebar.height / getZoomFactor(); // adjust for zoom prevention
this.titlebarHeight = isTitlebarHidden ? 0 : this.titlebarBaseHeight / getZoomFactor(); // adjust for zoom prevention

this.sidebarHeight = this.workbenchSize.height - this.statusbarHeight - this.titlebarHeight;
let sidebarSize = new Dimension(this.sidebarWidth, this.sidebarHeight);
Expand Down Expand Up @@ -794,6 +798,14 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal
}
}

public onMaximizeChange(maximized: boolean): void {
if (!isMacintosh) {
this.titlebarBaseHeight = maximized ? 23 : this.partLayoutInfo.titlebar.height;
} else {
this.titlebarBaseHeight = this.partLayoutInfo.titlebar.height;
}
}

public dispose(): void {
if (this.toUnbind) {
dispose(this.toUnbind);
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/browser/parts/sidebar/sidebarPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export class SidebarPart extends CompositePart<Viewlet> {
const container = $(this.getContainer());

container.style('background-color', this.getColor(SIDE_BAR_BACKGROUND));

container.style('color', this.getColor(SIDE_BAR_FOREGROUND));

const borderColor = this.getColor(SIDE_BAR_BORDER) || this.getColor(contrastBorder);
Expand Down
61 changes: 60 additions & 1 deletion src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,63 @@
text-overflow: ellipsis;
-webkit-app-region: drag;
zoom: 1; /* prevent zooming */
}
}

/***********************\
| Windows and Linux CSS |
\***********************/

.monaco-workbench.windows > .part.titlebar, .monaco-workbench.linux > .part.titlebar {
line-height: 25px;
height: 25px;
padding: 0 0 0 0.5em;
-webkit-app-region: no-drag;
}

.monaco-workbench.windows > .part.titlebar > .window-title, .monaco-workbench.linux > .part.titlebar > .window-title {
line-height: 25px;
flex-grow: 1;
margin-left: 0.35em;
-webkit-app-region: drag;
}

.monaco-workbench > .part.titlebar > .window-appicon {
width: calc(16em / 12);
height: calc(16em / 12);
-webkit-app-region: no-drag;
}

.monaco-workbench > .part.titlebar > .window-icon {
width: calc(46em / 12);
height: calc(100% - 1.5em / 12);
margin-bottom: calc(1.5em / 12);
display: flex;
align-items: center;
justify-content: center;
-webkit-app-region: no-drag;
-webkit-transition: background-color .2s;
transition: background-color .2s;
}

.window-unmaximize {
display: none;
}

.monaco-workbench > .part.titlebar > .window-icon svg {
width: calc(10em / 12);
height: calc(10em / 12);
shape-rendering: crispEdges;
}

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

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

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