Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d4c395a
Cache container width for the task, clear in microtask
Tyriar Oct 20, 2025
806b0a4
Don't imply appearance via style
Tyriar Oct 20, 2025
69d1cbe
Adopt HoverStyle.Pointer in a few places
Tyriar Oct 20, 2025
c2c62db
Merge pull request #272241 from microsoft/tyriar/272239
Tyriar Oct 20, 2025
ef3f16d
Merge pull request #272244 from microsoft/tyriar/style_position
Tyriar Oct 20, 2025
d568dbb
SCM - cancel Graph view refresh when view is disposed (#272246)
lszomoru Oct 20, 2025
795c809
stricter validation for remote mcp servers - #272247 (#272249)
sandy081 Oct 20, 2025
ec115fc
Don't present command line rule if it was denied
Tyriar Oct 20, 2025
2eec892
SCM - cleanup `scm.repositories.selectionMode` setting management (#2…
lszomoru Oct 20, 2025
3925c19
Leaked Disposable in promptValidator (#272255)
aeschli Oct 20, 2025
4963216
Merge branch 'main' into tyriar/style_position__adopt_pointer
Tyriar Oct 20, 2025
67961ab
Fixes https://github.com/microsoft/vscode/issues/272152 (#272261)
hediet Oct 20, 2025
58553f4
Merge pull request #272245 from microsoft/tyriar/style_position__adop…
Tyriar Oct 20, 2025
63ef47f
Merge pull request #272253 from microsoft/tyriar/272251
Tyriar Oct 20, 2025
7a90c2c
Bump actions/setup-node from 5 to 6 (#272258)
dependabot[bot] Oct 20, 2025
f77f4c5
eng - disable `start debugging` test that is flaky (#242033) (#272273)
bpasero Oct 20, 2025
afecaaa
fix(chat): guard against undefined customModes.custom Fix #272223 and…
tamuratak Oct 20, 2025
b46218e
SCM - fix bug related to pinned repositories (#272275)
lszomoru Oct 20, 2025
901240c
Show workspace-level agent instruction files in 'configure instructio…
jruales Oct 20, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/monaco-editor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
with:
persist-credentials: false

- uses: actions/setup-node@v5
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-darwin-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-linux-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/pr-node-modules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down Expand Up @@ -95,7 +95,7 @@ jobs:
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down Expand Up @@ -167,7 +167,7 @@ jobs:
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down Expand Up @@ -228,7 +228,7 @@ jobs:
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-win32-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@v5

- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/telemetry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
with:
persist-credentials: false

- uses: 'actions/setup-node@v5'
- uses: 'actions/setup-node@v6'
with:
node-version: 'lts/*'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ suite('vscode API - debug', function () {
assert.strictEqual(functionBreakpoint.functionName, 'func');
});

test('start debugging', async function () {
test.skip('start debugging', async function () { // Flaky: https://github.com/microsoft/vscode/issues/242033
let stoppedEvents = 0;
let variablesReceived: () => void;
let initializedReceived: () => void;
Expand Down
23 changes: 14 additions & 9 deletions src/vs/base/common/async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ export interface ITask<T> {
(): T;
}

export interface ICancellableTask<T> {
(token: CancellationToken): T;
}

/**
* A helper to prevent accumulation of sequential async tasks.
*
Expand Down Expand Up @@ -221,18 +225,19 @@ export class Throttler implements IDisposable {

private activePromise: Promise<any> | null;
private queuedPromise: Promise<any> | null;
private queuedPromiseFactory: ITask<Promise<any>> | null;

private isDisposed = false;
private queuedPromiseFactory: ICancellableTask<Promise<any>> | null;
private cancellationTokenSource: CancellationTokenSource;

constructor() {
this.activePromise = null;
this.queuedPromise = null;
this.queuedPromiseFactory = null;

this.cancellationTokenSource = new CancellationTokenSource();
}

queue<T>(promiseFactory: ITask<Promise<T>>): Promise<T> {
if (this.isDisposed) {
queue<T>(promiseFactory: ICancellableTask<Promise<T>>): Promise<T> {
if (this.cancellationTokenSource.token.isCancellationRequested) {
return Promise.reject(new Error('Throttler is disposed'));
}

Expand All @@ -243,7 +248,7 @@ export class Throttler implements IDisposable {
const onComplete = () => {
this.queuedPromise = null;

if (this.isDisposed) {
if (this.cancellationTokenSource.token.isCancellationRequested) {
return;
}

Expand All @@ -263,7 +268,7 @@ export class Throttler implements IDisposable {
});
}

this.activePromise = promiseFactory();
this.activePromise = promiseFactory(this.cancellationTokenSource.token);

return new Promise((resolve, reject) => {
this.activePromise!.then((result: T) => {
Expand All @@ -277,7 +282,7 @@ export class Throttler implements IDisposable {
}

dispose(): void {
this.isDisposed = true;
this.cancellationTokenSource.cancel();
}
}

Expand Down Expand Up @@ -458,7 +463,7 @@ export class ThrottledDelayer<T> {
this.throttler = new Throttler();
}

trigger(promiseFactory: ITask<Promise<T>>, delay?: number): Promise<T> {
trigger(promiseFactory: ICancellableTask<Promise<T>>, delay?: number): Promise<T> {
return this.delayer.trigger(() => this.throttler.queue(promiseFactory), delay) as unknown as Promise<T>;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { EditorOption } from '../../../../common/config/editorOptions.js';
import { EndOfLinePreference, IModelDeltaDecoration } from '../../../../common/model.js';
import { ViewConfigurationChangedEvent, ViewCursorStateChangedEvent, ViewDecorationsChangedEvent, ViewFlushedEvent, ViewLinesChangedEvent, ViewLinesDeletedEvent, ViewLinesInsertedEvent, ViewScrollChangedEvent, ViewZonesChangedEvent } from '../../../../common/viewEvents.js';
import { ViewContext } from '../../../../common/viewModel/viewContext.js';
import { RestrictedRenderingContext, RenderingContext } from '../../../view/renderingContext.js';
import { RestrictedRenderingContext, RenderingContext, HorizontalPosition } from '../../../view/renderingContext.js';
import { ViewController } from '../../../view/viewController.js';
import { ClipboardEventUtils, ClipboardStoredMetadata, getDataToCopy, InMemoryClipboardMetadataManager } from '../clipboardUtils.js';
import { AbstractEditContext } from '../editContext.js';
Expand Down Expand Up @@ -60,7 +60,7 @@ export class NativeEditContext extends AbstractEditContext {
private _editContextPrimarySelection: Selection = new Selection(1, 1, 1, 1);

// Overflow guard container
private _parent: HTMLElement | undefined;
private readonly _parent: HTMLElement;
private _decorations: string[] = [];
private _primarySelection: Selection = new Selection(1, 1, 1, 1);

Expand Down Expand Up @@ -241,9 +241,13 @@ export class NativeEditContext extends AbstractEditContext {
return this._primarySelection.getPosition();
}

public prepareRender(ctx: RenderingContext): void {
public override prepareRender(ctx: RenderingContext): void {
this._screenReaderSupport.prepareRender(ctx);
this._updateSelectionAndControlBounds(ctx);
this._updateSelectionAndControlBoundsData(ctx);
}

public override onDidRender(): void {
this._updateSelectionAndControlBoundsAfterRender();
}

public render(ctx: RestrictedRenderingContext): void {
Expand Down Expand Up @@ -483,26 +487,35 @@ export class NativeEditContext extends AbstractEditContext {
this._decorations = this._context.viewModel.model.deltaDecorations(this._decorations, decorations);
}

private _updateSelectionAndControlBounds(ctx: RenderingContext) {
if (!this._parent) {
return;
private _linesVisibleRanges: HorizontalPosition | null = null;
private _updateSelectionAndControlBoundsData(ctx: RenderingContext): void {
const viewSelection = this._context.viewModel.coordinatesConverter.convertModelRangeToViewRange(this._primarySelection);
if (this._primarySelection.isEmpty()) {
const linesVisibleRanges = ctx.visibleRangeForPosition(viewSelection.getStartPosition());
this._linesVisibleRanges = linesVisibleRanges;
} else {
this._linesVisibleRanges = null;
}
}

private _updateSelectionAndControlBoundsAfterRender() {
const options = this._context.configuration.options;
const contentLeft = options.get(EditorOption.layoutInfo).contentLeft;
const parentBounds = this._parent.getBoundingClientRect();

const viewSelection = this._context.viewModel.coordinatesConverter.convertModelRangeToViewRange(this._primarySelection);
const verticalOffsetStart = this._context.viewLayout.getVerticalOffsetForLineNumber(viewSelection.startLineNumber);
const verticalOffsetEnd = this._context.viewLayout.getVerticalOffsetAfterLineNumber(viewSelection.endLineNumber);

// Make sure this doesn't force an extra layout (i.e. don't call it before rendering finished)
const parentBounds = this._parent.getBoundingClientRect();
const top = parentBounds.top + verticalOffsetStart - this._scrollTop;
const verticalOffsetEnd = this._context.viewLayout.getVerticalOffsetAfterLineNumber(viewSelection.endLineNumber);
const height = verticalOffsetEnd - verticalOffsetStart;
let left = parentBounds.left + contentLeft - this._scrollLeft;
let width: number;

if (this._primarySelection.isEmpty()) {
const linesVisibleRanges = ctx.visibleRangeForPosition(viewSelection.getStartPosition());
if (linesVisibleRanges) {
left += linesVisibleRanges.left;
if (this._linesVisibleRanges) {
left += this._linesVisibleRanges.left;
}
width = 0;
} else {
Expand All @@ -515,9 +528,6 @@ export class NativeEditContext extends AbstractEditContext {
}

private _updateCharacterBounds(e: CharacterBoundsUpdateEvent): void {
if (!this._parent) {
return;
}
const options = this._context.configuration.options;
const typicalHalfWidthCharacterWidth = options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth;
const contentLeft = options.get(EditorOption.layoutInfo).contentLeft;
Expand Down
2 changes: 0 additions & 2 deletions src/vs/editor/browser/services/hoverService/hoverWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,6 @@ export class HoverWidget extends Widget implements IHoverWidget {
options.appearance ??= {};
options.appearance.compact ??= true;
options.appearance.showPointer ??= true;
options.position ??= {};
options.position.hoverPosition ??= HoverPosition.BELOW;
break;
}
case HoverStyle.Mouse: {
Expand Down
6 changes: 2 additions & 4 deletions src/vs/editor/contrib/rename/browser/renameWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
widgetShadow
} from '../../../../platform/theme/common/colorRegistry.js';
import { IColorTheme, IThemeService } from '../../../../platform/theme/common/themeService.js';
import { HoverStyle } from '../../../../base/browser/ui/hover/hover.js';

/** for debugging */
const _sticky = false
Expand Down Expand Up @@ -935,10 +936,7 @@ class InputWithButton implements IDisposable {
this._buttonHoverContent = this._buttonGenHoverText;
this._disposables.add(getBaseLayerHoverDelegate().setupDelayedHover(this._buttonNode, () => ({
content: this._buttonHoverContent,
appearance: {
showPointer: true,
compact: true,
}
style: HoverStyle.Pointer,
})));

this._domNode.appendChild(this._buttonNode);
Expand Down
6 changes: 2 additions & 4 deletions src/vs/workbench/browser/parts/compositeBarActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { Action2, IAction2Options } from '../../../platform/actions/common/actio
import { ViewContainerLocation } from '../../common/views.js';
import { IPaneCompositePartService } from '../../services/panecomposite/browser/panecomposite.js';
import { createConfigureKeybindingAction } from '../../../platform/actions/common/menuService.js';
import { HoverStyle } from '../../../base/browser/ui/hover/hover.js';

export interface ICompositeBar {

Expand Down Expand Up @@ -260,16 +261,13 @@ export class CompositeBarActionViewItem extends BaseActionViewItem {

this._register(this.hoverService.setupDelayedHover(this.container, () => ({
content: this.computeTitle(),
style: HoverStyle.Pointer,
position: {
hoverPosition: this.options.hoverOptions.position(),
},
persistence: {
hideOnKeyDown: true,
},
appearance: {
showPointer: true,
compact: true,
}
}), { groupId: 'composite-bar-actions' }));

// Label
Expand Down
17 changes: 10 additions & 7 deletions src/vs/workbench/contrib/chat/browser/chatAttachmentWidgets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { $ } from '../../../../base/browser/dom.js';
import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
import { StandardMouseEvent } from '../../../../base/browser/mouseEvent.js';
import { Button } from '../../../../base/browser/ui/button/button.js';
import type { IHoverLifecycleOptions, IHoverOptions } from '../../../../base/browser/ui/hover/hover.js';
import { HoverStyle, type IHoverLifecycleOptions, type IHoverOptions } from '../../../../base/browser/ui/hover/hover.js';
import { createInstantHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegateFactory.js';
import { HoverPosition } from '../../../../base/browser/ui/hover/hoverWidget.js';
import { Codicon } from '../../../../base/common/codicons.js';
Expand Down Expand Up @@ -59,10 +59,7 @@ import { ILanguageModelToolsService, ToolSet } from '../common/languageModelTool
import { getCleanPromptName } from '../common/promptSyntax/config/promptFileLocations.js';

const commonHoverOptions: Partial<IHoverOptions> = {
appearance: {
compact: true,
showPointer: true,
},
style: HoverStyle.Pointer,
position: {
hoverPosition: HoverPosition.BELOW
},
Expand Down Expand Up @@ -336,9 +333,15 @@ function createImageElements(resource: URI | undefined, name: string, fullName:
if ((!supportsVision && currentLanguageModel) || omittedState === OmittedState.Full) {
element.classList.add('warning');
hoverElement.textContent = localize('chat.imageAttachmentHover', "{0} does not support images.", currentLanguageModelName ?? 'This model');
disposable.add(hoverService.setupDelayedHover(element, { content: hoverElement, appearance: { showPointer: true } }));
disposable.add(hoverService.setupDelayedHover(element, {
content: hoverElement,
style: HoverStyle.Pointer,
}));
} else {
disposable.add(hoverService.setupDelayedHover(element, { content: hoverElement, appearance: { showPointer: true } }));
disposable.add(hoverService.setupDelayedHover(element, {
content: hoverElement,
style: HoverStyle.Pointer,
}));

const blob = new Blob([buffer as Uint8Array<ArrayBuffer>], { type: 'image/png' });
const url = URL.createObjectURL(blob);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Codicon } from '../../../../../base/common/codicons.js';
import { localize } from '../../../../../nls.js';
import { Button } from '../../../../../base/browser/ui/button/button.js';
import { generateUuid } from '../../../../../base/common/uuid.js';
import { HoverStyle } from '../../../../../base/browser/ui/hover/hover.js';


export class ChatAgentCommandContentPart extends Disposable implements IChatContentPart {
Expand All @@ -36,14 +37,20 @@ export class ChatAgentCommandContentPart extends Disposable implements IChatCont
const commandSpan = document.createElement('span');
this.domNode.appendChild(commandSpan);
commandSpan.innerText = chatSubcommandLeader + cmd.name;
this._store.add(this._hoverService.setupDelayedHover(commandSpan, { content: cmd.description, appearance: { showPointer: true } }, { groupId }));
this._store.add(this._hoverService.setupDelayedHover(commandSpan, {
content: cmd.description,
style: HoverStyle.Pointer,
}, { groupId }));

const rerun = localize('rerun', "Rerun without {0}{1}", chatSubcommandLeader, cmd.name);
const btn = new Button(this.domNode, { ariaLabel: rerun });
btn.icon = Codicon.close;
this._store.add(btn.onDidClick(() => onClick()));
this._store.add(btn);
this._store.add(this._hoverService.setupDelayedHover(btn.element, { content: rerun, appearance: { showPointer: true } }, { groupId }));
this._store.add(this._hoverService.setupDelayedHover(btn.element, {
content: rerun,
style: HoverStyle.Pointer,
}, { groupId }));
}

hasSameContent(other: IChatRendererContent, followingContent: IChatRendererContent[], element: ChatTreeItem): boolean {
Expand Down
Loading
Loading