From 5d5ac4d41ab4266e44beb366eaf746e37854afa6 Mon Sep 17 00:00:00 2001 From: Eugene Date: Sat, 24 Jan 2026 11:37:44 +0100 Subject: [PATCH] bump xterm (#10974) --- tabby-terminal/package.json | 19 ++-- .../src/api/baseTerminalTab.component.ts | 10 +-- tabby-terminal/src/frontends/xterm.css | 12 +-- tabby-terminal/src/frontends/xtermFrontend.ts | 40 +++++++-- .../src/middleware/oscProcessing.ts | 8 -- tabby-terminal/yarn.lock | 86 +++++++++++-------- 6 files changed, 98 insertions(+), 77 deletions(-) diff --git a/tabby-terminal/package.json b/tabby-terminal/package.json index cb26cd77..c11e15d6 100644 --- a/tabby-terminal/package.json +++ b/tabby-terminal/package.json @@ -19,15 +19,16 @@ "author": "Tabby Developers", "license": "MIT", "devDependencies": { - "@xterm/addon-canvas": "^0.6.0", - "@xterm/addon-fit": "^0.9.0", - "@xterm/addon-image": "^0.7.0", - "@xterm/addon-ligatures": "^0.8.0", - "@xterm/addon-search": "^0.14.0", - "@xterm/addon-serialize": "^0.12.0", - "@xterm/addon-unicode11": "^0.7.0", - "@xterm/addon-webgl": "^0.17.0", - "@xterm/xterm": "^5.4.0", + "@xterm/addon-canvas": "^0.7.0", + "@xterm/addon-clipboard": "^0.2.0", + "@xterm/addon-fit": "^0.11.0", + "@xterm/addon-image": "^0.9.0", + "@xterm/addon-ligatures": "^0.10.0", + "@xterm/addon-search": "^0.16.0", + "@xterm/addon-serialize": "^0.14.0", + "@xterm/addon-unicode11": "^0.9.0", + "@xterm/addon-webgl": "^0.19.0", + "@xterm/xterm": "^6.0.0", "ansi-colors": "^4.1.1", "binstring": "^0.2.1", "buffer-replace": "^1.0.0", diff --git a/tabby-terminal/src/api/baseTerminalTab.component.ts b/tabby-terminal/src/api/baseTerminalTab.component.ts index 05156840..aa82a006 100644 --- a/tabby-terminal/src/api/baseTerminalTab.component.ts +++ b/tabby-terminal/src/api/baseTerminalTab.component.ts @@ -447,10 +447,7 @@ export class BaseTerminalTabComponent

extends Bas .subscribe(visibility => { if (this.frontend instanceof XTermFrontend) { if (visibility) { - // this.frontend.resizeHandler() - const term = this.frontend.xterm as any - term._core._renderService.clear() - term._core._renderService.handleResize(term.cols, term.rows) + this.frontend.xterm.refresh(0, this.frontend.xterm.rows - 1) } else { this.frontend.xterm.element?.querySelectorAll('canvas').forEach(c => { c.height = c.width = 0 @@ -826,11 +823,6 @@ export class BaseTerminalTabComponent

extends Bas this.attachSessionHandler(this.session.destroyed$, () => { this.onSessionDestroyed() }) - - this.attachSessionHandler(this.session.oscProcessor.copyRequested$, content => { - this.platform.setClipboard({ text: content }) - this.notifications.notice(this.translate.instant('Copied')) - }) } /** diff --git a/tabby-terminal/src/frontends/xterm.css b/tabby-terminal/src/frontends/xterm.css index 6f3696b2..761efd1b 100644 --- a/tabby-terminal/src/frontends/xterm.css +++ b/tabby-terminal/src/frontends/xterm.css @@ -5,15 +5,11 @@ src: url(../fonts/SourceCodePro.ttf) format("truetype"); } -.xterm-viewport::-webkit-scrollbar { - background: rgba(0, 0, 0, .125); -} - -.xterm-viewport::-webkit-scrollbar-thumb { - background: rgba(255, 255, 255, .25); -} - .xterm-decoration-overview-ruler { right: 1px; pointer-events: none; } + +.xterm-viewport { + background: none !important; +} diff --git a/tabby-terminal/src/frontends/xtermFrontend.ts b/tabby-terminal/src/frontends/xtermFrontend.ts index 9146fe51..ba4c118a 100644 --- a/tabby-terminal/src/frontends/xtermFrontend.ts +++ b/tabby-terminal/src/frontends/xtermFrontend.ts @@ -1,10 +1,11 @@ import deepEqual from 'deep-equal' import { BehaviorSubject, filter, firstValueFrom, takeUntil } from 'rxjs' import { Injector } from '@angular/core' -import { ConfigService, getCSSFontFamily, getWindows10Build, HostAppService, HotkeysService, Platform, PlatformService, ThemesService } from 'tabby-core' +import { ConfigService, getCSSFontFamily, getWindows10Build, HostAppService, HotkeysService, NotificationsService, Platform, PlatformService, ThemesService, TranslateService } from 'tabby-core' import { Frontend, SearchOptions, SearchState } from './frontend' import { Terminal, ITheme } from '@xterm/xterm' import { FitAddon } from '@xterm/addon-fit' +import { ClipboardAddon } from '@xterm/addon-clipboard' import { LigaturesAddon } from '@xterm/addon-ligatures' import { ISearchOptions, SearchAddon } from '@xterm/addon-search' import { WebglAddon } from '@xterm/addon-webgl' @@ -87,6 +88,8 @@ export class XTermFrontend extends Frontend { private platformService: PlatformService private hostApp: HostAppService private themes: ThemesService + private notifications: NotificationsService + private translate: TranslateService constructor (injector: Injector) { super(injector) @@ -95,11 +98,18 @@ export class XTermFrontend extends Frontend { this.platformService = injector.get(PlatformService) this.hostApp = injector.get(HostAppService) this.themes = injector.get(ThemesService) + this.notifications = injector.get(NotificationsService) + this.translate = injector.get(TranslateService) this.xterm = new Terminal({ allowTransparency: true, allowProposedApi: true, - overviewRulerWidth: 8, + overviewRuler: { + width: 8, + showBottomBorder: false, + showTopBorder: false, + }, + reflowCursorLine: true, windowsPty: process.platform === 'win32' ? { backend: this.configService.store.terminal.useConPTY ? 'conpty' : 'winpty', buildNumber: getWindows10Build(), @@ -135,6 +145,15 @@ export class XTermFrontend extends Frontend { this.xterm.loadAddon(this.fitAddon) this.xterm.loadAddon(this.serializeAddon) this.xterm.loadAddon(new Unicode11Addon()) + this.xterm.loadAddon(new ClipboardAddon(undefined, { + readText: async () => { + return this.platformService.readClipboard() + }, + writeText: async (_, text) => { + this.platformService.setClipboard({ text }) + this.notifications.notice(this.translate.instant('Copied')) + }, + })) this.xterm.unicode.activeVersion = '11' if (this.configService.store.terminal.sixel) { @@ -200,7 +219,7 @@ export class XTermFrontend extends Frontend { try { if (this.xterm.element && getComputedStyle(this.xterm.element).getPropertyValue('height') !== 'auto') { this.fitAddon.fit() - this.xtermCore.viewport._refresh() + this.xterm.refresh(0, this.xterm.rows - 1) } } catch (e) { // tends to throw when element wasn't shown yet @@ -220,6 +239,7 @@ export class XTermFrontend extends Frontend { const altBufferActive = this.xterm.buffer.active.type === 'alternate' this.alternateScreenActive.next(altBufferActive) }) + } async attach (host: HTMLElement, profile: BaseTerminalProfile): Promise { @@ -377,12 +397,17 @@ export class XTermFrontend extends Frontend { background: getTerminalBackgroundColor(this.configService, this.themes, scheme) ?? '#00000000', cursor: scheme.cursor, cursorAccent: scheme.cursorAccent, + overviewRulerBorder: scheme.background, } for (let i = 0; i < COLOR_NAMES.length; i++) { theme[COLOR_NAMES[i]] = scheme.colors[i] } + theme.scrollbarSliderBackground = theme.brightBlack + theme.scrollbarSliderHoverBackground = theme.brightBlack + theme.scrollbarSliderHoverBackground = theme.brightBlack + if (!deepEqual(this.configuredTheme, theme)) { this.xterm.options.theme = theme this.configuredTheme = theme @@ -404,9 +429,12 @@ export class XTermFrontend extends Frontend { } }) - this.xtermCore.browser.isWindows = this.hostApp.platform === Platform.Windows - this.xtermCore.browser.isLinux = this.hostApp.platform === Platform.Linux - this.xtermCore.browser.isMac = this.hostApp.platform === Platform.macOS + this.xtermCore.browser = { + ...this.xtermCore.browser, + isWindows: this.hostApp.platform === Platform.Windows, + isLinux: this.hostApp.platform === Platform.Linux, + isMac: this.hostApp.platform === Platform.macOS, + } this.xterm.options.fontFamily = getCSSFontFamily(config) this.xterm.options.cursorStyle = { diff --git a/tabby-terminal/src/middleware/oscProcessing.ts b/tabby-terminal/src/middleware/oscProcessing.ts index c29b1bd2..9beff0ee 100644 --- a/tabby-terminal/src/middleware/oscProcessing.ts +++ b/tabby-terminal/src/middleware/oscProcessing.ts @@ -7,10 +7,8 @@ const OSCSuffixes = [Buffer.from('\x07'), Buffer.from('\x1b\\')] export class OSCProcessor extends SessionMiddleware { get cwdReported$ (): Observable { return this.cwdReported } - get copyRequested$ (): Observable { return this.copyRequested } private cwdReported = new Subject() - private copyRequested = new Subject() feedFromSession (data: Buffer): void { let startIndex = 0 @@ -45,11 +43,6 @@ export class OSCProcessor extends SessionMiddleware { } else { console.debug('Unsupported OSC 1337 parameter:', paramString) } - } else if (oscCode === 52) { - if (oscParams[0] === 'c' || oscParams[0] === '') { - const content = Buffer.from(oscParams[1], 'base64') - this.copyRequested.next(content.toString()) - } } else { continue } @@ -59,7 +52,6 @@ export class OSCProcessor extends SessionMiddleware { close (): void { this.cwdReported.complete() - this.copyRequested.complete() super.close() } } diff --git a/tabby-terminal/yarn.lock b/tabby-terminal/yarn.lock index 30d85b02..503ff0aa 100644 --- a/tabby-terminal/yarn.lock +++ b/tabby-terminal/yarn.lock @@ -2,53 +2,60 @@ # yarn lockfile v1 -"@xterm/addon-canvas@^0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-canvas/-/addon-canvas-0.6.0.tgz#08b2af252b8e4c5af3870820576a9a6ca18d517e" - integrity sha512-+nj2x595vItxfuAFxzXp46Izrh4EnEyS0Z60hX1iy6OFliP5OQu8Wu7n59m7m1vT6Q4nIWoN1WiH+VLAk4D9jQ== - -"@xterm/addon-fit@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-fit/-/addon-fit-0.9.0.tgz#29846f08782c51ad85b949528c45b84ad4ec45d7" - integrity sha512-hDlPPbTVPYyvwXu/asW8HbJkI/2RMi0cMaJnBZYVeJB0SWP2NeESMCNr+I7CvBlyI0sAxpxOg8Wk4OMkxBz9WA== - -"@xterm/addon-image@^0.7.0": +"@xterm/addon-canvas@^0.7.0": version "0.7.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.7.0.tgz#86e7342a3fe3fac6ba42944054e660916ec44953" - integrity sha512-OXJvmWXhJ5tdqSFX9yR2/d9AXwOz8+lJOghEPu2lSuwgLlMcOZ2YA+YuxPrisXIB2UctEHPAvVDGLbS9cESbzg== + resolved "https://registry.yarnpkg.com/@xterm/addon-canvas/-/addon-canvas-0.7.0.tgz#d3a3835f3634e0106e108661315ae14da23e8dd7" + integrity sha512-LF5LYcfvefJuJ7QotNRdRSPc9YASAVDeoT5uyXS/nZshZXjYplGXRECBGiznwvhNL2I8bq1Lf5MzRwstsYQ2Iw== -"@xterm/addon-ligatures@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-ligatures/-/addon-ligatures-0.8.0.tgz#d7f196c09edad0e7e45c691dce74f28bab683c37" - integrity sha512-hvClRA4a4saHXJV+Svxo6tC9NLN17coKbbFChhaQFvTe+TAx+G+LI1NytI8rmSIosOhg9m4uYB3J9o3Qyj4qxA== +"@xterm/addon-clipboard@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@xterm/addon-clipboard/-/addon-clipboard-0.2.0.tgz#8f2027b141e78f70fc76ba56aacf467250c284a3" + integrity sha512-Dl31BCtBhLaUEECUbEiVcCLvLBbaeGYdT7NofB8OJkGTD3MWgBsaLjXvfGAD4tQNHhm6mbKyYkR7XD8kiZsdNg== + dependencies: + js-base64 "^3.7.5" + +"@xterm/addon-fit@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@xterm/addon-fit/-/addon-fit-0.11.0.tgz#ba4778b69fcc9044a060c2176bbe077657d7b37e" + integrity sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g== + +"@xterm/addon-image@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0.tgz#3a12c8fe5bdb05457b955f36d4ce8372d8cb3035" + integrity sha512-oYWA8/QAr5/Emwl1xL7WCoOqeG3IZfpzEz/OVq1j4Oi9934TQmHiyubClikRf0D/jL3JNiNuz/Lsqx0kXQ02BA== + +"@xterm/addon-ligatures@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@xterm/addon-ligatures/-/addon-ligatures-0.10.0.tgz#4d33c75828c8b155bdc23dfd1a7e6fe8d80bda51" + integrity sha512-/Few8ZSHMib7sGjRJoc5l7bCtEB9XJfkNofvPpOcWADxKaUl8og8P172j67OoACSNJAXqeCLIuvj8WFCBkcTxg== dependencies: font-finder "^1.1.0" font-ligatures "^1.4.1" -"@xterm/addon-search@^0.14.0": +"@xterm/addon-search@^0.16.0": + version "0.16.0" + resolved "https://registry.yarnpkg.com/@xterm/addon-search/-/addon-search-0.16.0.tgz#ddadcbc6e556e45fc4b153f8a0efdf2aa1456b82" + integrity sha512-9OeuBFu0/uZJPu+9AHKY6g/w0Czyb/Ut0A5t79I4ULoU4IfU5BEpPFVGQxP4zTTMdfZEYkVIRYbHBX1xWwjeSA== + +"@xterm/addon-serialize@^0.14.0": version "0.14.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-search/-/addon-search-0.14.0.tgz#783c1a3fb301a98f0d0598453bd80d22cb0863ed" - integrity sha512-gyKIjC1c2bqxBevPmWlMWRsHqiufUgl3HjN3OYim6YPClqNRUlTab7l8aW8i3W83XzU9q0gmAfIOe4KDmo0GfQ== + resolved "https://registry.yarnpkg.com/@xterm/addon-serialize/-/addon-serialize-0.14.0.tgz#70c9f6dcd4632b086a0aa0deafd0e26e7482843b" + integrity sha512-uteyTU1EkrQa2Ux6P/uFl2fzmXI46jy5uoQMKEOM0fKTyiW7cSn0WrFenHm5vO5uEXX/GpwW/FgILvv3r0WbkA== -"@xterm/addon-serialize@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-serialize/-/addon-serialize-0.12.0.tgz#e83e8c21722dac7970521ade2df3ea07dbc2fd30" - integrity sha512-VJGfiTYfWJ1MC+eBBm7lY29+EMxnwpl2i6GecEwqe/7oXr2OEdMofdrpeXMa8OtlMd9bqjfdIfOoSZMmAzBm3w== +"@xterm/addon-unicode11@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@xterm/addon-unicode11/-/addon-unicode11-0.9.0.tgz#e1811bb75d9d783c36bd7126066d8084be70c799" + integrity sha512-FxDnYcyuXhNl+XSqGZL/t0U9eiNb/q3EWT5rYkQT/zuig8Gz/VagnQANKHdDWFM2lTMk9ly0EFQxxxtZUoRetw== -"@xterm/addon-unicode11@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-unicode11/-/addon-unicode11-0.7.0.tgz#cf4fa4da58b0cbcad3666e03d642184f76fe7d27" - integrity sha512-HIhQpRenrslPn6GlUmCYZcSXvdU0JkTgXQ66dx9QwXEzgNhoh70b7hXPZDBoMD/bH/7DYlseeGO7qKQlFzyhbA== +"@xterm/addon-webgl@^0.19.0": + version "0.19.0" + resolved "https://registry.yarnpkg.com/@xterm/addon-webgl/-/addon-webgl-0.19.0.tgz#02533c3f7c0af3ac9a44bbb095cbd47d48e90c25" + integrity sha512-b3fMOsyLVuCeNJWxolACEUED0vm7qC0cy4wRvf3oURSzDTYVQiGPhTnhWZwIHdvC48Y+oLhvYXnY4XDXPoJo6A== -"@xterm/addon-webgl@^0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-webgl/-/addon-webgl-0.17.0.tgz#1da534456b7971ebb2f08c381d4732d1f104d7d8" - integrity sha512-KUH//EZCz7j1+IekW8sZzmcj/y9gOLf/HMcsWXjg0Xr5cT1lIBIIbbBlbf5kZ+XnA/8c1IuBm1vx+blzlfPk0g== - -"@xterm/xterm@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@xterm/xterm/-/xterm-5.4.0.tgz#a35b585750ca492cbf2a4c99472c480d8c122840" - integrity sha512-GlyzcZZ7LJjhFevthHtikhiDIl8lnTSgol6eTM4aoSNLcuXu3OEhnbqdCVIjtIil3jjabf3gDtb1S8FGahsuEw== +"@xterm/xterm@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@xterm/xterm/-/xterm-6.0.0.tgz#93637b0f2ee3a70718b5746a27c9c506af16745b" + integrity sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg== "@yarnpkg/lockfile@^1.1.0": version "1.1.0" @@ -290,6 +297,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +js-base64@^3.7.5: + version "3.7.8" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.8.tgz#af44496bc09fa178ed9c4adf67eb2b46f5c6d2a4" + integrity sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow== + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"