diff --git a/spec/element-spec.js b/spec/element-spec.js index 0c042a57..c6f07af1 100644 --- a/spec/element-spec.js +++ b/spec/element-spec.js @@ -49,6 +49,7 @@ describe('XTerminalElement', () => { ['removeItem', 'getActiveItem', 'destroyItem']) const element = new XTerminalElement() await element.initialize(model) + await element.createTerminal() return element } @@ -1592,13 +1593,31 @@ describe('XTerminalElement', () => { it('refitTerminal() terminal not visible', () => { spyOn(this.element.fitAddon, 'proposeDimensions') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = false this.element.refitTerminal() expect(this.element.fitAddon.proposeDimensions).not.toHaveBeenCalled() }) + it('refitTerminal() terminal no width', () => { + spyOn(this.element.fitAddon, 'proposeDimensions') + this.element.mainDivContentRect = { width: 0, height: 1 } + this.element.terminalDivInitiallyVisible = true + this.element.refitTerminal() + expect(this.element.fitAddon.proposeDimensions).not.toHaveBeenCalled() + }) + + it('refitTerminal() terminal no height', () => { + spyOn(this.element.fitAddon, 'proposeDimensions') + this.element.mainDivContentRect = { width: 1, height: 0 } + this.element.terminalDivInitiallyVisible = true + this.element.refitTerminal() + expect(this.element.fitAddon.proposeDimensions).not.toHaveBeenCalled() + }) + it('refitTerminal() terminal completely visible', () => { spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(null) + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.refitTerminal() expect(this.element.fitAddon.proposeDimensions).toHaveBeenCalled() @@ -1610,6 +1629,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() @@ -1622,6 +1642,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() @@ -1634,6 +1655,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows + 1, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() @@ -1646,6 +1668,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows + 1, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() @@ -1658,6 +1681,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows - 1, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() @@ -1670,6 +1694,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows - 1, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() @@ -1682,6 +1707,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1694,6 +1720,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1706,6 +1733,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows + 1, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1718,6 +1746,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows + 1, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1730,6 +1759,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1742,6 +1772,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows - 1, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1754,6 +1785,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows - 1, }) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1767,6 +1799,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1780,6 +1813,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1793,6 +1827,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1806,6 +1841,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1819,6 +1855,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() @@ -1832,6 +1869,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') + this.element.mainDivContentRect = { width: 1, height: 1 } this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() diff --git a/src/element.js b/src/element.js index 86e7bc3a..bedac9ba 100644 --- a/src/element.js +++ b/src/element.js @@ -72,6 +72,7 @@ class XTerminalElementImpl extends HTMLElement { this.atomXtermProfileMenuElement = new XTerminalProfileMenuElement() this.hoveredLink = null this.pendingTerminalProfileOptions = {} + this.mainDivContentRect = null this.terminalDivInitiallyVisible = false this.isInitialized = false let resolveInit, rejectInit @@ -85,11 +86,12 @@ class XTerminalElementImpl extends HTMLElement { this.setAttribute('session-id', this.model.getSessionId()) await this.atomXtermProfileMenuElement.initialize(new XTerminalProfileMenuModel(this.model)) this.menuDiv.append(this.atomXtermProfileMenuElement) - await this.createTerminal() // An element resize detector is used to check when this element is // resized due to the pane resizing or due to the entire window // resizing. - this.mainDivResizeObserver = new ResizeObserver((entries, observer) => { + this.mainDivResizeObserver = new ResizeObserver(entries => { + const lastEntry = entries.pop() + this.mainDivContentRect = lastEntry.contentRect this.refitTerminal() }) this.mainDivResizeObserver.observe(this.mainDiv) @@ -99,12 +101,11 @@ class XTerminalElementImpl extends HTMLElement { })) // Add an IntersectionObserver in order to apply new options and // refit as soon as the terminal is visible. - this.terminalDivIntersectionObserver = new IntersectionObserver((entries, observer) => { - // NOTE: Only the terminal div should be observed therefore there - // should only be one entry. - const visible = entries.some(e => e.intersectionRatio === 1.0) - if (visible) { + this.terminalDivIntersectionObserver = new IntersectionObserver(async entries => { + const lastEntry = entries.pop() + if (lastEntry.intersectionRatio === 1.0) { this.terminalDivInitiallyVisible = true + await this.createTerminal() this.applyPendingTerminalProfileOptions() // Remove observer once visible this.terminalDivIntersectionObserver.disconnect() @@ -678,7 +679,12 @@ class XTerminalElementImpl extends HTMLElement { refitTerminal () { // Only refit the terminal when it is completely visible. - if (this.terminalDivInitiallyVisible) { + if ( + this.terminalDivInitiallyVisible && + this.mainDivContentRect && + this.mainDivContentRect.width > 0 && + this.mainDivContentRect.height > 0 + ) { this.fitAddon.fit() const geometry = this.fitAddon.proposeDimensions() if (geometry && this.isPtyProcessRunning()) {