Skip to content

Commit 9556196

Browse files
author
Benjamin Pasero
committed
window picker - indicate dirty windows
1 parent 13b38d2 commit 9556196

8 files changed

Lines changed: 53 additions & 22 deletions

File tree

src/vs/code/electron-main/window.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import * as path from 'vs/base/common/path';
77
import * as objects from 'vs/base/common/objects';
88
import * as nls from 'vs/nls';
9-
import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
9+
import { Emitter } from 'vs/base/common/event';
1010
import { URI } from 'vs/base/common/uri';
1111
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme } from 'electron';
1212
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
@@ -69,21 +69,23 @@ export class CodeWindow extends Disposable implements ICodeWindow {
6969
private static readonly MAX_URL_LENGTH = 2 * 1024 * 1024; // https://cs.chromium.org/chromium/src/url/url_constants.cc?l=32
7070

7171
private readonly _onClose = this._register(new Emitter<void>());
72-
readonly onClose: CommonEvent<void> = this._onClose.event;
72+
readonly onClose = this._onClose.event;
7373

7474
private readonly _onDestroy = this._register(new Emitter<void>());
75-
readonly onDestroy: CommonEvent<void> = this._onDestroy.event;
75+
readonly onDestroy = this._onDestroy.event;
7676

7777
private readonly _onLoad = this._register(new Emitter<void>());
78-
readonly onLoad: CommonEvent<void> = this._onLoad.event;
78+
readonly onLoad = this._onLoad.event;
7979

8080
private hiddenTitleBarStyle: boolean | undefined;
8181
private showTimeoutHandle: NodeJS.Timeout | undefined;
8282
private _lastFocusTime: number;
8383
private _readyState: ReadyState;
8484
private windowState: IWindowState;
8585
private currentMenuBarVisibility: MenuBarVisibility | undefined;
86+
8687
private representedFilename: string | undefined;
88+
private documentEdited: boolean | undefined;
8789

8890
private readonly whenReadyCallbacks: { (window: ICodeWindow): void }[];
8991

@@ -271,6 +273,22 @@ export class CodeWindow extends Disposable implements ICodeWindow {
271273
return this.representedFilename;
272274
}
273275

276+
setDocumentEdited(edited: boolean): void {
277+
if (isMacintosh) {
278+
this._win.setDocumentEdited(edited);
279+
}
280+
281+
this.documentEdited = edited;
282+
}
283+
284+
isDocumentEdited(): boolean {
285+
if (isMacintosh) {
286+
return this._win.isDocumentEdited();
287+
}
288+
289+
return !!this.documentEdited;
290+
}
291+
274292
focus(): void {
275293
if (!this._win) {
276294
return;
@@ -586,9 +604,9 @@ export class CodeWindow extends Disposable implements ICodeWindow {
586604
}
587605

588606
// Clear Document Edited if needed
589-
if (isMacintosh && this._win.isDocumentEdited()) {
607+
if (this.isDocumentEdited()) {
590608
if (!isReload || !this.backupMainService.isHotExitEnabled()) {
591-
this._win.setDocumentEdited(false);
609+
this.setDocumentEdited(false);
592610
}
593611
}
594612

src/vs/platform/electron/electron-main/electronMainService.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ export class ElectronMainService implements IElectronMainService {
6565
workspace: window.openedWorkspace,
6666
folderUri: window.openedFolderUri,
6767
title: window.win.getTitle(),
68-
filename: window.getRepresentedFilename()
68+
filename: window.getRepresentedFilename(),
69+
dirty: window.isDocumentEdited()
6970
}));
7071
}
7172

@@ -271,7 +272,7 @@ export class ElectronMainService implements IElectronMainService {
271272
async setDocumentEdited(windowId: number | undefined, edited: boolean): Promise<void> {
272273
const window = this.windowById(windowId);
273274
if (window) {
274-
window.win.setDocumentEdited(edited);
275+
window.setDocumentEdited(edited);
275276
}
276277
}
277278

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export interface IOpenedWindow {
1515
folderUri?: ISingleFolderWorkspaceIdentifier;
1616
title: string;
1717
filename?: string;
18+
dirty: boolean;
1819
}
1920

2021
export interface IBaseOpenWindowsOptions {

src/vs/platform/windows/electron-main/windows.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ export interface ICodeWindow extends IDisposable {
8080
setRepresentedFilename(name: string): void;
8181
getRepresentedFilename(): string | undefined;
8282

83+
setDocumentEdited(edited: boolean): void;
84+
isDocumentEdited(): boolean;
85+
8386
handleTitleDoubleClick(): void;
8487

8588
updateTouchBar(items: ISerializableCommandAction[][]): void;

src/vs/workbench/browser/actions/layoutActions.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import 'vs/css!./media/actions';
7-
86
import * as nls from 'vs/nls';
97
import { Registry } from 'vs/platform/registry/common/platform';
108
import { Action } from 'vs/base/common/actions';

src/vs/workbench/browser/actions/media/actions.css renamed to src/vs/workbench/electron-browser/actions/media/actions.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
* Copyright (c) Microsoft Corporation. All rights reserved.
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
5+
6+
.quick-input-list .quick-input-list-entry.has-actions:hover .quick-input-list-entry-action-bar .action-label.dirty-window::before {
7+
content: "\ea76"; /* Close icon flips between black dot and "X" for dirty open editors */
8+
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import 'vs/css!./media/actions';
7+
68
import { URI } from 'vs/base/common/uri';
79
import { Action } from 'vs/base/common/actions';
810
import * as nls from 'vs/nls';
@@ -157,6 +159,12 @@ export abstract class BaseSwitchWindow extends Action {
157159
tooltip: nls.localize('close', "Close Window")
158160
};
159161

162+
private readonly closeDirtyWindowAction: IQuickInputButton = {
163+
iconClass: 'dirty-window codicon-circle-filled',
164+
tooltip: nls.localize('close', "Close Window"),
165+
alwaysVisible: true
166+
};
167+
160168
constructor(
161169
id: string,
162170
label: string,
@@ -185,7 +193,7 @@ export abstract class BaseSwitchWindow extends Action {
185193
label: win.title,
186194
iconClasses: getIconClasses(this.modelService, this.modeService, resource, fileKind),
187195
description: (currentWindowId === win.id) ? nls.localize('current', "Current Window") : undefined,
188-
buttons: (!this.isQuickNavigate() && currentWindowId !== win.id) ? [this.closeWindowAction] : undefined
196+
buttons: currentWindowId !== win.id ? win.dirty ? [this.closeDirtyWindowAction] : [this.closeWindowAction] : undefined
189197
};
190198
});
191199
const autoFocusIndex = (picks.indexOf(picks.filter(pick => pick.payload === currentWindowId)[0]) + 1) % picks.length;

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -269,19 +269,17 @@ export class NativeWindow extends Disposable {
269269
}));
270270
}
271271

272-
// Document edited (macOS only): indicate for dirty working copies
273-
if (isMacintosh) {
274-
this._register(this.workingCopyService.onDidChangeDirty(workingCopy => {
275-
const gotDirty = workingCopy.isDirty();
276-
if (gotDirty && !(workingCopy.capabilities & WorkingCopyCapabilities.Untitled) && this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.AFTER_SHORT_DELAY) {
277-
return; // do not indicate dirty of working copies that are auto saved after short delay
278-
}
272+
// Document edited: indicate for dirty working copies
273+
this._register(this.workingCopyService.onDidChangeDirty(workingCopy => {
274+
const gotDirty = workingCopy.isDirty();
275+
if (gotDirty && !(workingCopy.capabilities & WorkingCopyCapabilities.Untitled) && this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.AFTER_SHORT_DELAY) {
276+
return; // do not indicate dirty of working copies that are auto saved after short delay
277+
}
279278

280-
this.updateDocumentEdited(gotDirty);
281-
}));
279+
this.updateDocumentEdited(gotDirty);
280+
}));
282281

283-
this.updateDocumentEdited();
284-
}
282+
this.updateDocumentEdited();
285283

286284
// Detect minimize / maximize
287285
this._register(Event.any(

0 commit comments

Comments
 (0)