diff --git a/build/lib/stylelint/vscode-known-variables.json b/build/lib/stylelint/vscode-known-variables.json index 67ec595ed30..7ff08b74263 100644 --- a/build/lib/stylelint/vscode-known-variables.json +++ b/build/lib/stylelint/vscode-known-variables.json @@ -306,6 +306,8 @@ "--vscode-extensionIcon-verifiedForeground", "--vscode-focusBorder", "--vscode-foreground", + "--vscode-hover-whiteSpace", + "--vscode-hoverSource-whiteSpace", "--vscode-icon-foreground", "--vscode-inlineChat-background", "--vscode-inlineChat-border", diff --git a/src/vs/base/browser/ui/hover/hover.css b/src/vs/base/browser/ui/hover/hover.css index 0ce58199354..68907c6a062 100644 --- a/src/vs/base/browser/ui/hover/hover.css +++ b/src/vs/base/browser/ui/hover/hover.css @@ -12,6 +12,7 @@ box-sizing: border-box; animation: fadein 100ms linear; line-height: 1.5em; + white-space: var(--vscode-hover-whiteSpace); } .monaco-hover.hidden { @@ -105,7 +106,7 @@ } .monaco-hover .monaco-tokenized-source { - white-space: pre-wrap; + white-space: var(--vscode-hoverSource-whiteSpace); } .monaco-hover .hover-row.status-bar { diff --git a/src/vs/editor/contrib/hover/browser/contentHover.ts b/src/vs/editor/contrib/hover/browser/contentHover.ts index e284a838116..885b1f41c7d 100644 --- a/src/vs/editor/contrib/hover/browser/contentHover.ts +++ b/src/vs/editor/contrib/hover/browser/contentHover.ts @@ -459,6 +459,7 @@ export class ContentHoverWidget extends ResizableContentWidget { private _visibleData: ContentHoverVisibleData | undefined; private _positionPreference: ContentWidgetPositionPreference | undefined; + private _initialWidth: number | undefined; private readonly _hover: HoverWidget = this._register(new HoverWidget()); private readonly _hoverVisibleKey: IContextKey; @@ -612,13 +613,29 @@ export class ContentHoverWidget extends ResizableContentWidget { return Math.min(availableSpace, maximumHeight); } + private _isHoverTextOverflowing(): boolean { + let overflowing = false; + Array.from(this._hover.contentsDomNode.children).forEach((hoverPart) => { + overflowing = overflowing || hoverPart.scrollWidth > hoverPart.clientWidth; + }); + return overflowing; + } + private _findMaximumRenderingWidth(): number | undefined { if (!this._editor || !this._editor.hasModel()) { return; } - const bodyBoxWidth = dom.getClientArea(document.body).width; - const horizontalPadding = 14; - return bodyBoxWidth - horizontalPadding; + this._setWhiteSpaceProperties('nowrap', 'nowrap'); + const overflowing = this._isHoverTextOverflowing(); + this._setWhiteSpaceProperties('normal', 'pre-wrap'); + + if (overflowing || this._initialWidth && this._hover.containerDomNode.clientWidth < this._initialWidth) { + const bodyBoxWidth = dom.getClientArea(document.body).width; + const horizontalPadding = 14; + return bodyBoxWidth - horizontalPadding; + } else { + return this._hover.containerDomNode.clientWidth + 2; + } } public isMouseGettingCloser(posx: number, posy: number): boolean { @@ -707,10 +724,16 @@ export class ContentHoverWidget extends ResizableContentWidget { }; } + private _setWhiteSpaceProperties(hoverWhiteSpace: 'normal' | 'nowrap', hoverSourceWhiteSpace: 'pre-wrap' | 'nowrap') { + this._hover.containerDomNode.style.setProperty('--vscode-hover-whiteSpace', hoverWhiteSpace); + this._hover.containerDomNode.style.setProperty('--vscode-hoverSource-whiteSpace', hoverSourceWhiteSpace); + } + public showAt(node: DocumentFragment, hoverData: ContentHoverVisibleData): void { if (!this._editor || !this._editor.hasModel()) { return; } + this._setWhiteSpaceProperties('normal', 'pre-wrap'); this._render(node, hoverData); const widgetHeight = dom.getTotalHeight(this._hover.containerDomNode); const widgetPosition = hoverData.showAtPosition; @@ -774,6 +797,7 @@ export class ContentHoverWidget extends ResizableContentWidget { this._adjustHoverHeightForScrollbar(height); } this._layoutContentWidget(); + this._initialWidth = this._hover.containerDomNode.clientWidth; } public focus(): void {