mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
fix(list): 🐛 list/tree should show focus outline while context menu is open
Closes: #123771
This commit is contained in:
parent
0961dbb56d
commit
144d7e3f68
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
|
@ -79,5 +79,12 @@
|
|||
},
|
||||
"typescript.tsc.autoDetect": "off",
|
||||
"testing.autoRun.mode": "rerun",
|
||||
"conventionalCommits.scopes": ["tree", "scm", "grid", "splitview", "table"]
|
||||
"conventionalCommits.scopes": [
|
||||
"tree",
|
||||
"scm",
|
||||
"grid",
|
||||
"splitview",
|
||||
"table",
|
||||
"list"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -854,6 +854,7 @@ export class DefaultStyleController implements IStyleController {
|
|||
content.push(`
|
||||
.monaco-drag-image,
|
||||
.monaco-list${suffix}:focus .monaco-list-row.focused { outline: 1px solid ${styles.listFocusOutline}; outline-offset: -1px; }
|
||||
.monaco-workbench.context-menu-visible .monaco-list${suffix}.last-focused .monaco-list-row.focused { outline: 1px solid ${styles.listFocusOutline}; outline-offset: -1px; }
|
||||
`);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,11 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
|
|||
|
||||
private contextMenuHandler: ContextMenuHandler;
|
||||
|
||||
readonly onDidShowContextMenu = new Emitter<void>().event;
|
||||
private readonly _onDidShowContextMenu = new Emitter<void>();
|
||||
readonly onDidShowContextMenu = this._onDidShowContextMenu.event;
|
||||
|
||||
private readonly _onDidHideContextMenu = new Emitter<void>();
|
||||
readonly onDidHideContextMenu = this._onDidHideContextMenu.event;
|
||||
|
||||
constructor(
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
|
@ -40,7 +44,17 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
|
|||
// ContextMenu
|
||||
|
||||
showContextMenu(delegate: IContextMenuDelegate): void {
|
||||
this.contextMenuHandler.showContextMenu(delegate);
|
||||
this.contextMenuHandler.showContextMenu({
|
||||
...delegate,
|
||||
onHide: (didCancel) => {
|
||||
if (delegate.onHide) {
|
||||
delegate.onHide(didCancel);
|
||||
}
|
||||
|
||||
this._onDidHideContextMenu.fire();
|
||||
}
|
||||
});
|
||||
ModifierKeyEmitter.getInstance().resetKeyStatus();
|
||||
this._onDidShowContextMenu.fire();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ export interface IContextMenuService {
|
|||
readonly _serviceBrand: undefined;
|
||||
|
||||
readonly onDidShowContextMenu: Event<void>;
|
||||
readonly onDidHideContextMenu: Event<void>;
|
||||
|
||||
showContextMenu(delegate: IContextMenuDelegate): void;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,16 @@ export class ListService implements IListService {
|
|||
return this._lastFocusedWidget;
|
||||
}
|
||||
|
||||
constructor(@IThemeService private readonly _themeService: IThemeService) {
|
||||
constructor(@IThemeService private readonly _themeService: IThemeService) { }
|
||||
|
||||
private setLastFocusedList(widget: WorkbenchListWidget | undefined): void {
|
||||
if (widget === this._lastFocusedWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._lastFocusedWidget?.getHTMLElement().classList.remove('last-focused');
|
||||
this._lastFocusedWidget = widget;
|
||||
this._lastFocusedWidget?.getHTMLElement().classList.add('last-focused');
|
||||
}
|
||||
|
||||
register(widget: WorkbenchListWidget, extraContextKeys?: (IContextKey<boolean>)[]): IDisposable {
|
||||
|
@ -83,16 +92,16 @@ export class ListService implements IListService {
|
|||
|
||||
// Check for currently being focused
|
||||
if (widget.getHTMLElement() === document.activeElement) {
|
||||
this._lastFocusedWidget = widget;
|
||||
this.setLastFocusedList(widget);
|
||||
}
|
||||
|
||||
return combinedDisposable(
|
||||
widget.onDidFocus(() => this._lastFocusedWidget = widget),
|
||||
widget.onDidFocus(() => this.setLastFocusedList(widget)),
|
||||
toDisposable(() => this.lists.splice(this.lists.indexOf(registeredList), 1)),
|
||||
widget.onDidDispose(() => {
|
||||
this.lists = this.lists.filter(l => l !== registeredList);
|
||||
if (this._lastFocusedWidget === widget) {
|
||||
this._lastFocusedWidget = undefined;
|
||||
this.setLastFocusedList(undefined);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
|
||||
class ContextMenuContribution implements IWorkbenchContribution {
|
||||
|
||||
private readonly disposables = new DisposableStore();
|
||||
|
||||
constructor(
|
||||
@ILayoutService layoutService: ILayoutService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService
|
||||
) {
|
||||
const update = (visible: boolean) => layoutService.container.classList.toggle('context-menu-visible', visible);
|
||||
contextMenuService.onDidShowContextMenu(() => update(true), null, this.disposables);
|
||||
contextMenuService.onDidHideContextMenu(() => update(false), null, this.disposables);
|
||||
}
|
||||
}
|
||||
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
|
||||
.registerWorkbenchContribution(ContextMenuContribution, LifecyclePhase.Eventually);
|
|
@ -24,7 +24,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
|||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { stripIcons } from 'vs/base/common/iconLabels';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
|
||||
export class ContextMenuService extends Disposable implements IContextMenuService {
|
||||
|
||||
|
@ -32,8 +32,8 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
|
|||
|
||||
private impl: IContextMenuService;
|
||||
|
||||
private readonly _onDidShowContextMenu = this._register(new Emitter<void>());
|
||||
readonly onDidShowContextMenu = this._onDidShowContextMenu.event;
|
||||
get onDidShowContextMenu(): Event<void> { return this.impl.onDidShowContextMenu; }
|
||||
get onDidHideContextMenu(): Event<void> { return this.impl.onDidHideContextMenu; }
|
||||
|
||||
constructor(
|
||||
@INotificationService notificationService: INotificationService,
|
||||
|
@ -58,7 +58,6 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
|
|||
|
||||
showContextMenu(delegate: IContextMenuDelegate): void {
|
||||
this.impl.showContextMenu(delegate);
|
||||
this._onDidShowContextMenu.fire();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +65,11 @@ class NativeContextMenuService extends Disposable implements IContextMenuService
|
|||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
readonly onDidShowContextMenu = new Emitter<void>().event;
|
||||
private readonly _onDidShowContextMenu = new Emitter<void>();
|
||||
readonly onDidShowContextMenu = this._onDidShowContextMenu.event;
|
||||
|
||||
private readonly _onDidHideContextMenu = new Emitter<void>();
|
||||
readonly onDidHideContextMenu = this._onDidHideContextMenu.event;
|
||||
|
||||
constructor(
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
|
@ -85,6 +88,7 @@ class NativeContextMenuService extends Disposable implements IContextMenuService
|
|||
}
|
||||
|
||||
dom.ModifierKeyEmitter.getInstance().resetKeyStatus();
|
||||
this._onDidHideContextMenu.fire();
|
||||
});
|
||||
|
||||
const menu = this.createMenu(delegate, actions, onHide);
|
||||
|
@ -120,6 +124,8 @@ class NativeContextMenuService extends Disposable implements IContextMenuService
|
|||
y: Math.floor(y),
|
||||
positioningItem: delegate.autoSelectFirstItem ? 0 : undefined,
|
||||
}, () => onHide());
|
||||
|
||||
this._onDidShowContextMenu.fire();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,6 +157,9 @@ import 'vs/workbench/contrib/preferences/browser/preferencesSearch';
|
|||
// Performance
|
||||
import 'vs/workbench/contrib/performance/browser/performance.contribution';
|
||||
|
||||
// Context Menus
|
||||
import 'vs/workbench/contrib/contextmenu/browser/contextmenu.contribution';
|
||||
|
||||
// Notebook
|
||||
import 'vs/workbench/contrib/notebook/browser/notebook.contribution';
|
||||
|
||||
|
|
Loading…
Reference in a new issue