diff --git a/tabby-settings/src/components/editProfileModal.component.ts b/tabby-settings/src/components/editProfileModal.component.ts index e8b2977e..15b4bd4c 100644 --- a/tabby-settings/src/components/editProfileModal.component.ts +++ b/tabby-settings/src/components/editProfileModal.component.ts @@ -16,7 +16,7 @@ const iconsClassList = Object.keys(iconsData).map( templateUrl: './editProfileModal.component.pug', }) export class EditProfileModalComponent

> { - @Input('profile') _profile: P + @Input('profile') partialProfile: P @Input() profileProvider: PP @Input() settingsComponent: new () => ProfileSettingsComponent @Input() defaultsMode: 'enabled'|'group'|'disabled' = 'disabled' @@ -56,7 +56,7 @@ export class EditProfileModalComponent

(this._profile, { skipGlobalDefaults: this.defaultsMode === 'enabled', skipGroupDefaults: this.defaultsMode === 'group' }) + this.profile = this.profilesService.getConfigProxyForProfile

(this.partialProfile, { skipGlobalDefaults: this.defaultsMode === 'enabled', skipGroupDefaults: this.defaultsMode === 'group' }) } ngAfterViewInit () { @@ -96,7 +96,7 @@ export class EditProfileModalComponent

null) @@ -193,7 +193,7 @@ export class ProfilesSettingsTabComponent extends BaseComponent { ) const model = group.defaults?.[provider.id] ?? {} model.type = provider.id - modal.componentInstance.profile = Object.assign({}, model) + modal.componentInstance.partialProfile = Object.assign({}, model) modal.componentInstance.profileProvider = provider modal.componentInstance.defaultsMode = 'group' @@ -300,7 +300,7 @@ export class ProfilesSettingsTabComponent extends BaseComponent { ) const model = this.profilesService.getProviderDefaults(provider) model.type = provider.id - modal.componentInstance.profile = Object.assign({}, model) + modal.componentInstance.partialProfile = Object.assign({}, model) modal.componentInstance.profileProvider = provider modal.componentInstance.defaultsMode = 'enabled' const result = await modal.result.catch(() => null) diff --git a/tabby-terminal/package.json b/tabby-terminal/package.json index cfd11709..f0a83411 100644 --- a/tabby-terminal/package.json +++ b/tabby-terminal/package.json @@ -19,16 +19,15 @@ "author": "Tabby Developers", "license": "MIT", "devDependencies": { - "@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", + "@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", "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 bd814e57..b91623ef 100644 --- a/tabby-terminal/src/api/baseTerminalTab.component.ts +++ b/tabby-terminal/src/api/baseTerminalTab.component.ts @@ -447,7 +447,10 @@ export class BaseTerminalTabComponent

extends Bas .subscribe(visibility => { if (this.frontend instanceof XTermFrontend) { if (visibility) { - this.frontend.xterm.refresh(0, this.frontend.xterm.rows - 1) + // this.frontend.resizeHandler() + const term = this.frontend.xterm as any + term._core._renderService?.clear() + term._core._renderService?.handleResize(term.cols, term.rows) } else { this.frontend.xterm.element?.querySelectorAll('canvas').forEach(c => { c.height = c.width = 0 @@ -823,6 +826,11 @@ 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 761efd1b..6f3696b2 100644 --- a/tabby-terminal/src/frontends/xterm.css +++ b/tabby-terminal/src/frontends/xterm.css @@ -5,11 +5,15 @@ 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 15073382..56345534 100644 --- a/tabby-terminal/src/frontends/xtermFrontend.ts +++ b/tabby-terminal/src/frontends/xtermFrontend.ts @@ -1,11 +1,10 @@ import deepEqual from 'deep-equal' import { BehaviorSubject, filter, firstValueFrom, takeUntil } from 'rxjs' import { Injector } from '@angular/core' -import { ConfigService, getCSSFontFamily, getWindows10Build, HostAppService, HotkeysService, NotificationsService, Platform, PlatformService, ThemesService, TranslateService } from 'tabby-core' +import { ConfigService, getCSSFontFamily, getWindows10Build, HostAppService, HotkeysService, Platform, PlatformService, ThemesService } 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' @@ -89,8 +88,6 @@ 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) @@ -99,18 +96,11 @@ 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, - overviewRuler: { - width: 8, - showBottomBorder: false, - showTopBorder: false, - }, - reflowCursorLine: true, + overviewRulerWidth: 8, windowsPty: process.platform === 'win32' ? { backend: this.configService.store.terminal.useConPTY ? 'conpty' : 'winpty', buildNumber: getWindows10Build(), @@ -146,15 +136,6 @@ 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) { @@ -231,7 +212,7 @@ export class XTermFrontend extends Frontend { const savedViewportY = this.xterm.buffer.active.viewportY this.fitAddon.fit() - this.xterm.refresh(0, this.xterm.rows - 1) + this.xtermCore.viewport._refresh() if (savedPinned) { this.xtermCore._scrollToBottom() @@ -260,7 +241,6 @@ export class XTermFrontend extends Frontend { const altBufferActive = this.xterm.buffer.active.type === 'alternate' this.alternateScreenActive.next(altBufferActive) }) - } private isAtBottom (): boolean { @@ -485,17 +465,12 @@ 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 @@ -517,12 +492,9 @@ export class XTermFrontend extends Frontend { } }) - 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.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.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 d67a4cd6..adbc6b13 100644 --- a/tabby-terminal/src/middleware/oscProcessing.ts +++ b/tabby-terminal/src/middleware/oscProcessing.ts @@ -7,9 +7,11 @@ 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 buffer: Buffer | null = null + private copyRequested = new Subject() feedFromSession (data: Buffer): void { // Prepend any buffered data from previous chunks @@ -72,6 +74,11 @@ 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()) + } } // Move past this OSC sequence @@ -86,6 +93,7 @@ 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 503ff0aa..30d85b02 100644 --- a/tabby-terminal/yarn.lock +++ b/tabby-terminal/yarn.lock @@ -2,60 +2,53 @@ # yarn lockfile v1 -"@xterm/addon-canvas@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-canvas/-/addon-canvas-0.7.0.tgz#d3a3835f3634e0106e108661315ae14da23e8dd7" - integrity sha512-LF5LYcfvefJuJ7QotNRdRSPc9YASAVDeoT5uyXS/nZshZXjYplGXRECBGiznwvhNL2I8bq1Lf5MzRwstsYQ2Iw== +"@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-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": +"@xterm/addon-fit@^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== + resolved "https://registry.yarnpkg.com/@xterm/addon-fit/-/addon-fit-0.9.0.tgz#29846f08782c51ad85b949528c45b84ad4ec45d7" + integrity sha512-hDlPPbTVPYyvwXu/asW8HbJkI/2RMi0cMaJnBZYVeJB0SWP2NeESMCNr+I7CvBlyI0sAxpxOg8Wk4OMkxBz9WA== -"@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== +"@xterm/addon-image@^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== + +"@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== dependencies: font-finder "^1.1.0" font-ligatures "^1.4.1" -"@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": +"@xterm/addon-search@^0.14.0": version "0.14.0" - resolved "https://registry.yarnpkg.com/@xterm/addon-serialize/-/addon-serialize-0.14.0.tgz#70c9f6dcd4632b086a0aa0deafd0e26e7482843b" - integrity sha512-uteyTU1EkrQa2Ux6P/uFl2fzmXI46jy5uoQMKEOM0fKTyiW7cSn0WrFenHm5vO5uEXX/GpwW/FgILvv3r0WbkA== + resolved "https://registry.yarnpkg.com/@xterm/addon-search/-/addon-search-0.14.0.tgz#783c1a3fb301a98f0d0598453bd80d22cb0863ed" + integrity sha512-gyKIjC1c2bqxBevPmWlMWRsHqiufUgl3HjN3OYim6YPClqNRUlTab7l8aW8i3W83XzU9q0gmAfIOe4KDmo0GfQ== -"@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-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-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-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/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== +"@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== "@yarnpkg/lockfile@^1.1.0": version "1.1.0" @@ -297,11 +290,6 @@ 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"