Skip to content

Commit

Permalink
Add keybinding to show workbench hover for active element
Browse files Browse the repository at this point in the history
  • Loading branch information
benibenj committed Feb 6, 2025
1 parent 8fab0b5 commit 0f06b7c
Showing 1 changed file with 33 additions and 3 deletions.
36 changes: 33 additions & 3 deletions src/vs/editor/browser/services/hoverService/hoverService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import { ManagedHoverWidget } from './updatableHoverWidget.js';
import { timeout, TimeoutTimer } from '../../../../base/common/async.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
import { isNumber } from '../../../../base/common/types.js';
import { KeyCode } from '../../../../base/common/keyCodes.js';
import { KeyChord, KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';
import { KeybindingsRegistry, KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
import { EditorContextKeys } from '../../../common/editorContextKeys.js';

export class HoverService extends Disposable implements IHoverService {
declare readonly _serviceBrand: undefined;
Expand All @@ -41,6 +43,9 @@ export class HoverService extends Disposable implements IHoverService {

private _lastFocusedElementBeforeOpen: HTMLElement | undefined;

private readonly _delayedHovers = new Map<HTMLElement, { show: (focus: boolean) => void }>();
private readonly _managedHovers = new Map<HTMLElement, IManagedHover>();

constructor(
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
Expand All @@ -53,6 +58,14 @@ export class HoverService extends Disposable implements IHoverService {

this._register(contextMenuService.onDidShowContextMenu(() => this.hideHover()));
this._contextViewHandler = this._register(new ContextViewHandler(this._layoutService));

this._register(KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.action.showHover',
weight: KeybindingWeight.WorkbenchContrib - 1,
when: EditorContextKeys.editorTextFocus.negate(),
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyI),
handler: () => { this._showAndFocusHoverForActiveElement(); },
}));
}

showHover(options: IHoverOptions, focus?: boolean, skipLastFocusedUpdate?: boolean, dontShow?: boolean): IHoverWidget | undefined {
Expand Down Expand Up @@ -160,6 +173,10 @@ export class HoverService extends Disposable implements IHoverService {
}
}));
}

this._delayedHovers.set(target, { show: (focus: boolean) => { this.showHover(resolveHoverOptions(), focus); } });
store.add(toDisposable(() => this._delayedHovers.delete(target)));

return store;
}

Expand Down Expand Up @@ -301,6 +318,21 @@ export class HoverService extends Disposable implements IHoverService {
this.showHover(this._lastHoverOptions, true, true);
}

private _showAndFocusHoverForActiveElement(): void {
// TODO: if hover is visible, focus it to avoid flickering

let activeElement = getActiveElement() as HTMLElement | null;
while (activeElement) {
const hover = this._delayedHovers.get(activeElement) ?? this._managedHovers.get(activeElement);
if (hover) {
hover.show(true);
return;
}

activeElement = activeElement.parentElement;
}
}

private _keyDown(e: KeyboardEvent, hover: HoverWidget, hideOnKeyDown: boolean) {
if (e.key === 'Alt') {
hover.isLocked = true;
Expand Down Expand Up @@ -328,8 +360,6 @@ export class HoverService extends Disposable implements IHoverService {
}
}

private readonly _managedHovers = new Map<HTMLElement, IManagedHover>();

// TODO: Investigate performance of this function. There seems to be a lot of content created
// and thrown away on start up
setupManagedHover(hoverDelegate: IHoverDelegate, targetElement: HTMLElement, content: IManagedHoverContentOrFactory, options?: IManagedHoverOptions | undefined): IManagedHover {
Expand Down

0 comments on commit 0f06b7c

Please sign in to comment.