Skip to content

Commit 3d3384e

Browse files
Add workbench.view.showQuietly settings object to stop extensions revealing hidden Output view (fix #105270) (#205225)
* Add `output.showQuietly` to stop extensions activating Output view (fix #105270) * Merge branch 'main' into fix-105270 * Merge remote-tracking branch 'upstream/main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge remote-tracking branch 'upstream/main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Merge branch 'main' into fix-105270 * Implement PR feedback * :lipstick * Improve setting description * Clarify setting description * More work on the setting description * Remove unnecessary change * Merge branch 'main' into fix-105270 * Adopt suggestions * Simplify setting description * Merge branch 'main' into fix-105270 * 💄 * change id to not be output specific
1 parent e250246 commit 3d3384e

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

src/vs/workbench/api/browser/mainThreadOutputService.ts

+46-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ import { Extensions, IOutputChannelRegistry, IOutputService, IOutputChannel, OUT
88
import { MainThreadOutputServiceShape, MainContext, ExtHostOutputServiceShape, ExtHostContext } from '../common/extHost.protocol.js';
99
import { extHostNamedCustomer, IExtHostContext } from '../../services/extensions/common/extHostCustomers.js';
1010
import { UriComponents, URI } from '../../../base/common/uri.js';
11-
import { Disposable, toDisposable } from '../../../base/common/lifecycle.js';
11+
import { Disposable, MutableDisposable, toDisposable } from '../../../base/common/lifecycle.js';
1212
import { Event } from '../../../base/common/event.js';
1313
import { IViewsService } from '../../services/views/common/viewsService.js';
1414
import { isNumber } from '../../../base/common/types.js';
15+
import { IConfigurationService } from '../../../platform/configuration/common/configuration.js';
16+
import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from '../../services/statusbar/browser/statusbar.js';
17+
import { localize } from '../../../nls.js';
1518

1619
@extHostNamedCustomer(MainContext.MainThreadOutputService)
1720
export class MainThreadOutputService extends Disposable implements MainThreadOutputServiceShape {
@@ -21,21 +24,30 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
2124
private readonly _proxy: ExtHostOutputServiceShape;
2225
private readonly _outputService: IOutputService;
2326
private readonly _viewsService: IViewsService;
27+
private readonly _configurationService: IConfigurationService;
28+
private readonly _statusbarService: IStatusbarService;
29+
30+
private readonly _outputStatusItem = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
2431

2532
constructor(
2633
extHostContext: IExtHostContext,
2734
@IOutputService outputService: IOutputService,
2835
@IViewsService viewsService: IViewsService,
36+
@IConfigurationService configurationService: IConfigurationService,
37+
@IStatusbarService statusbarService: IStatusbarService,
2938
) {
3039
super();
3140
this._outputService = outputService;
3241
this._viewsService = viewsService;
42+
this._configurationService = configurationService;
43+
this._statusbarService = statusbarService;
3344

3445
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostOutputService);
3546

3647
const setVisibleChannel = () => {
3748
const visibleChannel = this._viewsService.isViewVisible(OUTPUT_VIEW_ID) ? this._outputService.getActiveChannel() : undefined;
3849
this._proxy.$setVisibleChannel(visibleChannel ? visibleChannel.id : null);
50+
this._outputStatusItem.value = undefined;
3951
};
4052
this._register(Event.any<any>(this._outputService.onActiveOutputChannel, Event.filter(this._viewsService.onDidChangeViewVisibility, ({ id }) => id === OUTPUT_VIEW_ID))(() => setVisibleChannel()));
4153
setVisibleChannel();
@@ -65,8 +77,39 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
6577

6678
public async $reveal(channelId: string, preserveFocus: boolean): Promise<void> {
6779
const channel = this._getChannel(channelId);
68-
if (channel) {
69-
this._outputService.showChannel(channel.id, preserveFocus);
80+
if (!channel) {
81+
return;
82+
}
83+
84+
const viewsToShowQuietly = this._configurationService.getValue<Record<string, boolean> | undefined>('workbench.view.showQuietly') ?? {};
85+
if (!this._viewsService.isViewVisible(OUTPUT_VIEW_ID) && viewsToShowQuietly[OUTPUT_VIEW_ID]) {
86+
this._showChannelQuietly(channel);
87+
return;
88+
}
89+
90+
this._outputService.showChannel(channel.id, preserveFocus);
91+
}
92+
93+
// Show status bar indicator
94+
private _showChannelQuietly(channel: IOutputChannel) {
95+
const statusProperties: IStatusbarEntry = {
96+
name: localize('status.showOutput', "Show Output"),
97+
text: '$(output)',
98+
ariaLabel: localize('status.showOutputAria', "Show {0} Output Channel", channel.label),
99+
command: `workbench.action.output.show.${channel.id}`,
100+
tooltip: localize('status.showOutputTooltip', "Show {0} Output Channel", channel.label),
101+
kind: 'prominent'
102+
};
103+
104+
if (!this._outputStatusItem.value) {
105+
this._outputStatusItem.value = this._statusbarService.addEntry(
106+
statusProperties,
107+
'status.view.showQuietly',
108+
StatusbarAlignment.RIGHT,
109+
{ id: 'status.notifications', alignment: StatusbarAlignment.LEFT }
110+
);
111+
} else {
112+
this._outputStatusItem.value.update(statusProperties);
70113
}
71114
}
72115

src/vs/workbench/browser/workbench.contribution.ts

+12
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,18 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
565565
'default': false,
566566
'description': localize('viewVisibility', "Controls the visibility of view header actions. View header actions may either be always visible, or only visible when that view is focused or hovered over.")
567567
},
568+
'workbench.view.showQuietly': {
569+
'type': 'object',
570+
'description': localize('workbench.view.showQuietly', "If an extension requests a hidden view to be shown, display a clickable status bar indicator instead."),
571+
'scope': ConfigurationScope.WINDOW,
572+
'properties': {
573+
'workbench.panel.output': {
574+
'type': 'boolean',
575+
'description': localize('workbench.panel.output', "Output view")
576+
}
577+
},
578+
'additionalProperties': false
579+
},
568580
'workbench.fontAliasing': {
569581
'type': 'string',
570582
'enum': ['default', 'antialiased', 'none', 'auto'],

0 commit comments

Comments
 (0)