diff --git a/tabby-terminal/src/api/baseTerminalTab.component.ts b/tabby-terminal/src/api/baseTerminalTab.component.ts index e2454259..04438017 100644 --- a/tabby-terminal/src/api/baseTerminalTab.component.ts +++ b/tabby-terminal/src/api/baseTerminalTab.component.ts @@ -9,6 +9,7 @@ import { BaseSession } from '../session' import { Frontend } from '../frontends/frontend' import { XTermFrontend, XTermWebGLFrontend } from '../frontends/xtermFrontend' +import { syncTerminalVisibility } from '../frontends/visibility' import { ResizeEvent, BaseTerminalProfile } from './interfaces' import { TerminalDecorator } from './decorator' import { SearchPanelComponent } from '../components/searchPanel.component' @@ -446,17 +447,7 @@ export class BaseTerminalTabComponent

extends Bas .pipe(debounce(visibility => interval(visibility ? 0 : INACTIVE_TAB_UNLOAD_DELAY))) .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) - } else { - this.frontend.xterm.element?.querySelectorAll('canvas').forEach(c => { - c.height = c.width = 0 - c.style.height = c.style.width = '0px' - }) - } + syncTerminalVisibility(this.frontend, visibility) } }) } diff --git a/tabby-terminal/src/frontends/visibility.test.js b/tabby-terminal/src/frontends/visibility.test.js new file mode 100644 index 00000000..de564117 --- /dev/null +++ b/tabby-terminal/src/frontends/visibility.test.js @@ -0,0 +1,38 @@ +import assert from 'node:assert/strict' +import test from 'node:test' + +import { syncTerminalVisibility } from './visibility.ts' + +test('syncTerminalVisibility reactivates the frontend when the tab becomes visible', () => { + let reactivated = 0 + let deactivated = 0 + + syncTerminalVisibility({ + reactivateAfterVisibilityChange: () => { + reactivated++ + }, + deactivateAfterVisibilityChange: () => { + deactivated++ + }, + }, true) + + assert.equal(reactivated, 1) + assert.equal(deactivated, 0) +}) + +test('syncTerminalVisibility releases hidden-tab resources when the tab becomes invisible', () => { + let reactivated = 0 + let deactivated = 0 + + syncTerminalVisibility({ + reactivateAfterVisibilityChange: () => { + reactivated++ + }, + deactivateAfterVisibilityChange: () => { + deactivated++ + }, + }, false) + + assert.equal(reactivated, 0) + assert.equal(deactivated, 1) +}) diff --git a/tabby-terminal/src/frontends/visibility.ts b/tabby-terminal/src/frontends/visibility.ts new file mode 100644 index 00000000..7302e765 --- /dev/null +++ b/tabby-terminal/src/frontends/visibility.ts @@ -0,0 +1,12 @@ +export interface VisibilityManagedTerminalFrontend { + reactivateAfterVisibilityChange: () => void + deactivateAfterVisibilityChange: () => void +} + +export function syncTerminalVisibility (frontend: VisibilityManagedTerminalFrontend, visible: boolean): void { + if (visible) { + frontend.reactivateAfterVisibilityChange() + } else { + frontend.deactivateAfterVisibilityChange() + } +} diff --git a/tabby-terminal/src/frontends/xtermFrontend.ts b/tabby-terminal/src/frontends/xtermFrontend.ts index d2adbcf8..f34a10e2 100644 --- a/tabby-terminal/src/frontends/xtermFrontend.ts +++ b/tabby-terminal/src/frontends/xtermFrontend.ts @@ -98,15 +98,20 @@ export class XTermFrontend extends Frontend { this.hostApp = injector.get(HostAppService) this.themes = injector.get(ThemesService) - this.xterm = new Terminal({ + const terminalOptions = { allowTransparency: true, allowProposedApi: true, - overviewRulerWidth: 8, windowsPty: process.platform === 'win32' ? { - backend: this.configService.store.terminal.useConPTY ? 'conpty' : 'winpty', + backend: this.configService.store.terminal.useConPTY ? 'conpty' as const : 'winpty' as const, buildNumber: getWindows10Build(), } : undefined, - }) + } + ;(terminalOptions as Record).overviewRuler = { + width: 8, + showBottomBorder: false, + showTopBorder: false, + } + this.xterm = new Terminal(terminalOptions) this.flowControl = new FlowControl(this.xterm) this.xtermCore = this.xterm['_core'] @@ -360,6 +365,17 @@ export class XTermFrontend extends Frontend { delete this.resizeObserver } + reactivateAfterVisibilityChange (): void { + this.resizeHandler() + } + + deactivateAfterVisibilityChange (): void { + this.xterm.element?.querySelectorAll('canvas').forEach(c => { + c.height = c.width = 0 + c.style.height = c.style.width = '0px' + }) + } + destroy (): void { super.destroy() this.webGLAddon?.dispose()