diff --git a/package.json b/package.json index ecbad95ff23..23e01b9d3a6 100644 --- a/package.json +++ b/package.json @@ -87,13 +87,13 @@ "vscode-proxy-agent": "^0.12.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "8.0.0", - "xterm": "5.2.0-beta.26", + "xterm": "5.2.0-beta.27", "xterm-addon-canvas": "0.4.0-beta.7", "xterm-addon-search": "0.11.0", "xterm-addon-serialize": "0.9.0", "xterm-addon-unicode11": "0.5.0", "xterm-addon-webgl": "0.15.0-beta.6", - "xterm-headless": "5.2.0-beta.26", + "xterm-headless": "5.2.0-beta.27", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/package.json b/remote/package.json index 99ecb595840..fb5995aaf72 100644 --- a/remote/package.json +++ b/remote/package.json @@ -24,13 +24,13 @@ "vscode-proxy-agent": "^0.12.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "8.0.0", - "xterm": "5.2.0-beta.26", + "xterm": "5.2.0-beta.27", "xterm-addon-canvas": "0.4.0-beta.7", "xterm-addon-search": "0.11.0", "xterm-addon-serialize": "0.9.0", "xterm-addon-unicode11": "0.5.0", "xterm-addon-webgl": "0.15.0-beta.6", - "xterm-headless": "5.2.0-beta.26", + "xterm-headless": "5.2.0-beta.27", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/web/package.json b/remote/web/package.json index 4cd100c788e..8954906c6fe 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -11,7 +11,7 @@ "tas-client-umd": "0.1.6", "vscode-oniguruma": "1.7.0", "vscode-textmate": "8.0.0", - "xterm": "5.2.0-beta.26", + "xterm": "5.2.0-beta.27", "xterm-addon-canvas": "0.4.0-beta.7", "xterm-addon-search": "0.11.0", "xterm-addon-unicode11": "0.5.0", diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index caeef05781e..713988393b2 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -88,7 +88,7 @@ xterm-addon-webgl@0.15.0-beta.6: resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0-beta.6.tgz#a99233349b9eaec31df798a312906fe73fb3dc33" integrity sha512-PMEkAT4UFL4Ei222uiHPMdVG3fRQAfS5JuZl9FfRVw0V4qMKHvZxBrZELytVfSgLNGBuPu2z7feeZIFEWQGlhA== -xterm@5.2.0-beta.26: - version "5.2.0-beta.26" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.26.tgz#9b45e481e10ce6c21b34cb36f7c2b2006ec7a136" - integrity sha512-+jp492Ein/xO+nGjZz0CwAYeyUAK5LoH7N1U5w3HGVjYMLZu/Y/Ql5FO+ax/QrrM3Ob+Rw2JNrTuhMQmIZMIMg== +xterm@5.2.0-beta.27: + version "5.2.0-beta.27" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.27.tgz#1f81b86c19c78d2be94b8274591f3e3a4cacded3" + integrity sha512-fBZoyj4ZoHqlIU22Kr11Y7qaaJp46ALQXs1oDIUyOrY9lFsusZjBUrVWudeQLZI6HaMfJbjZXKT8kbvGwSUc5Q== diff --git a/remote/yarn.lock b/remote/yarn.lock index efb8280d7aa..0f434f91f44 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -866,15 +866,15 @@ xterm-addon-webgl@0.15.0-beta.6: resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0-beta.6.tgz#a99233349b9eaec31df798a312906fe73fb3dc33" integrity sha512-PMEkAT4UFL4Ei222uiHPMdVG3fRQAfS5JuZl9FfRVw0V4qMKHvZxBrZELytVfSgLNGBuPu2z7feeZIFEWQGlhA== -xterm-headless@5.2.0-beta.26: - version "5.2.0-beta.26" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.2.0-beta.26.tgz#6e852a183d6cfb230a7fe19947ed727769dae0bb" - integrity sha512-v961nK3TVzqrRcaSLJStSwoNfiOXRRwxT0+hBTdWpgHAZAMj93oHBWKuG882kPiyT/kqlxzxdNRvpWKI504eSQ== +xterm-headless@5.2.0-beta.27: + version "5.2.0-beta.27" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.2.0-beta.27.tgz#f7d939af1b23b392d7b462ed5c073fbbd85034e2" + integrity sha512-yIFWt1YaQo9szRGK6tZT8SaalMsDNwqhVFPZULNg5gy+Dbu/XD2XJiWL6rPYwLwywSQ5rVxZCcctuzLzhQJvJg== -xterm@5.2.0-beta.26: - version "5.2.0-beta.26" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.26.tgz#9b45e481e10ce6c21b34cb36f7c2b2006ec7a136" - integrity sha512-+jp492Ein/xO+nGjZz0CwAYeyUAK5LoH7N1U5w3HGVjYMLZu/Y/Ql5FO+ax/QrrM3Ob+Rw2JNrTuhMQmIZMIMg== +xterm@5.2.0-beta.27: + version "5.2.0-beta.27" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.27.tgz#1f81b86c19c78d2be94b8274591f3e3a4cacded3" + integrity sha512-fBZoyj4ZoHqlIU22Kr11Y7qaaJp46ALQXs1oDIUyOrY9lFsusZjBUrVWudeQLZI6HaMfJbjZXKT8kbvGwSUc5Q== yallist@^4.0.0: version "4.0.0" diff --git a/src/vs/workbench/contrib/terminal/browser/media/xterm.css b/src/vs/workbench/contrib/terminal/browser/media/xterm.css index a2618844cf2..09af6d4f30f 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/xterm.css +++ b/src/vs/workbench/contrib/terminal/browser/media/xterm.css @@ -221,7 +221,11 @@ overflow-x: hidden; } -.xterm .xterm-accessibility-buffer:focus { +.xterm .xterm-accessibility-buffer div { + white-space: pre-wrap; +} + +.xterm .xterm-accessibility-buffer:focus-within { opacity: 1; z-index: 33; top: -5px; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 000bc7764e3..804ff994d5d 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -21,7 +21,7 @@ import { Lazy } from 'vs/base/common/lazy'; import { Disposable, DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import * as path from 'vs/base/common/path'; -import { isMacintosh, isWindows, OperatingSystem, OS } from 'vs/base/common/platform'; +import { isLinux, isMacintosh, isWindows, OperatingSystem, OS } from 'vs/base/common/platform'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { withNullAsUndefined } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; @@ -219,6 +219,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _quickFixAddon: TerminalQuickFixAddon | undefined; private _lineDataEventAddon: LineDataEventAddon | undefined; private _accessibilityBuffer: HTMLElement | undefined; + private _bufferElementFragment: DocumentFragment; readonly capabilities = new TerminalCapabilityStoreMultiplexer(); readonly statusList: ITerminalStatusList; @@ -549,6 +550,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { if (this._fixedCols) { await this._addScrollbar(); } + this._register(this.xterm!.raw.registerBufferElementProvider({ provideBufferElements: () => this._provideBufferElements() })); }).catch((err) => { // Ignore exceptions if the terminal is already disposed if (!this._isDisposed) { @@ -601,6 +603,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { window.clearTimeout(initialDataEventsTimeout); } })); + this._bufferElementFragment = document.createDocumentFragment(); } private _getIcon(): TerminalIcon | undefined { @@ -1108,13 +1111,54 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { if (!this._accessibilityBuffer) { return; } - const accessibleBufferContentEditable = this._configurationService.getValue(TerminalSettingId.AccessibleBufferContentEditable); + // see https://github.com/microsoft/vscode/issues/173532 + const accessibleBufferContentEditable = isLinux ? 'on' : this._configurationService.getValue(TerminalSettingId.AccessibleBufferContentEditable); this._accessibilityBuffer.contentEditable = accessibleBufferContentEditable === 'on' || (accessibleBufferContentEditable === 'auto' && !this._accessibilityService.isScreenReaderOptimized()) ? 'true' : 'false'; // The viewport is undefined when this is focused, so we cannot get the cell height from that. Instead, estimate using the font. const font = this.xterm.getFont(); const lineHeight = font?.charHeight ? font.charHeight * font.lineHeight + 'px' : ''; this._accessibilityBuffer.style.lineHeight = lineHeight; + const commands = this.capabilities.get(TerminalCapability.CommandDetection)?.commands; + if (!commands?.length) { + const noContent = document.createElement('div'); + const noContentLabel = nls.localize('terminal.integrated.noContent', "No terminal content available for this session."); + noContent.textContent = noContentLabel; + this._bufferElementFragment.replaceChildren(noContent); + this._accessibilityBuffer.focus(); + return; + } + let header; + let replaceChildren = true; + for (const command of commands) { + header = document.createElement('h2'); + // without this, the text area gets focused when keyboard shortcuts are used + header.tabIndex = -1; + header.textContent = command.command.replace(new RegExp(' ', 'g'), '\xA0'); + const output = document.createElement('div'); + // without this, the text area gets focused when keyboard shortcuts are used + output.tabIndex = -1; + output.textContent = command.getOutput()?.replace(new RegExp(' ', 'g'), '\xA0') || ''; + if (replaceChildren) { + this._bufferElementFragment.replaceChildren(header, output); + replaceChildren = false; + } else { + this._bufferElementFragment.appendChild(header); + this._bufferElementFragment.appendChild(output); + } + } + if (header) { + // focus the cursor line's header + header.tabIndex = 0; + } this._accessibilityBuffer.focus(); + if (this._accessibilityBuffer.contentEditable === 'true') { + document.execCommand('selectAll', false, undefined); + document.getSelection()?.collapseToEnd(); + } + } + + private _provideBufferElements(): DocumentFragment { + return this._bufferElementFragment; } private _setShellIntegrationContextKey(): void { diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 6dbae03ee82..41f45386549 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -581,7 +581,7 @@ const terminalConfiguration: IConfigurationNode = { default: false }, [TerminalSettingId.AccessibleBufferContentEditable]: { - description: localize('terminal.integrated.accessibleBufferContentEditable', "Controls whether the accessible buffer is marks as a `contenteditable` element. This adds a text cursor to the buffer, allowing selection with the keyboard without a screen reader. Screen reader will typically want to leave this as `'auto'` or `'off'` which will treat the buffer similar to a document."), + description: localize('terminal.integrated.accessibleBufferContentEditable', "Controls whether the accessible buffer is marks as a `contenteditable` element. This adds a text cursor to the buffer, allowing selection with the keyboard without a screen reader. Screen reader users will typically want to leave this as `'auto'` or `'off'` which will treat the buffer similar to a document. By default, on Linux, this will be set to `on` so that it works when using Orca."), type: 'string', enum: ['auto', 'on', 'off'], enumDescriptions: [ diff --git a/yarn.lock b/yarn.lock index 9f383e1ece8..e0e311a8959 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11728,15 +11728,15 @@ xterm-addon-webgl@0.15.0-beta.6: resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0-beta.6.tgz#a99233349b9eaec31df798a312906fe73fb3dc33" integrity sha512-PMEkAT4UFL4Ei222uiHPMdVG3fRQAfS5JuZl9FfRVw0V4qMKHvZxBrZELytVfSgLNGBuPu2z7feeZIFEWQGlhA== -xterm-headless@5.2.0-beta.26: - version "5.2.0-beta.26" - resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.2.0-beta.26.tgz#6e852a183d6cfb230a7fe19947ed727769dae0bb" - integrity sha512-v961nK3TVzqrRcaSLJStSwoNfiOXRRwxT0+hBTdWpgHAZAMj93oHBWKuG882kPiyT/kqlxzxdNRvpWKI504eSQ== +xterm-headless@5.2.0-beta.27: + version "5.2.0-beta.27" + resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.2.0-beta.27.tgz#f7d939af1b23b392d7b462ed5c073fbbd85034e2" + integrity sha512-yIFWt1YaQo9szRGK6tZT8SaalMsDNwqhVFPZULNg5gy+Dbu/XD2XJiWL6rPYwLwywSQ5rVxZCcctuzLzhQJvJg== -xterm@5.2.0-beta.26: - version "5.2.0-beta.26" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.26.tgz#9b45e481e10ce6c21b34cb36f7c2b2006ec7a136" - integrity sha512-+jp492Ein/xO+nGjZz0CwAYeyUAK5LoH7N1U5w3HGVjYMLZu/Y/Ql5FO+ax/QrrM3Ob+Rw2JNrTuhMQmIZMIMg== +xterm@5.2.0-beta.27: + version "5.2.0-beta.27" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.2.0-beta.27.tgz#1f81b86c19c78d2be94b8274591f3e3a4cacded3" + integrity sha512-fBZoyj4ZoHqlIU22Kr11Y7qaaJp46ALQXs1oDIUyOrY9lFsusZjBUrVWudeQLZI6HaMfJbjZXKT8kbvGwSUc5Q== y18n@^3.2.1: version "3.2.2"