Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix terminal resize when hidden #136

Merged
merged 4 commits into from
Aug 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions spec/element-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ describe('XTerminalElement', () => {
['removeItem', 'getActiveItem', 'destroyItem'])
const element = new XTerminalElement()
await element.initialize(model)
await element.createTerminal()
return element
}

Expand Down Expand Up @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand Down
22 changes: 14 additions & 8 deletions src/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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()
Expand Down Expand Up @@ -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()) {
Expand Down