From 5ce066b93e2739ba3511981695b3358b150f6888 Mon Sep 17 00:00:00 2001 From: Tony Brix Date: Mon, 27 Jul 2020 00:45:32 -0500 Subject: [PATCH] fix: fix resize when switching docks --- .eslintrc.js | 1 + package-lock.json | 13 --------- package.json | 1 - spec/custom-runner.js | 1 + spec/element-spec.js | 67 +++++++++++++++++++------------------------ src/element.js | 36 ++++++++++++++--------- 6 files changed, 55 insertions(+), 64 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index bf5c0765..3b9330e4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -18,5 +18,6 @@ module.exports = { 'comma-dangle': ['error', 'always-multiline'], indent: ['error', 'tab', { SwitchCase: 1 }], 'no-tabs': ['error', { allowIndentationTabs: true }], + 'no-console': 'warn', }, } diff --git a/package-lock.json b/package-lock.json index 7bcda40d..04a335a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -970,11 +970,6 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" }, - "batch-processor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", - "integrity": "sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg=" - }, "before-after-hook": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", @@ -1689,14 +1684,6 @@ "integrity": "sha512-+05RF8S9rk8S0G8eBCqBRBaRq7+UN3lDs2DAvnG8SBSgQO3hjy0+qt4CmRk5eiuGbTcaicgXfPmBi31a+BD3lg==", "dev": true }, - "element-resize-detector": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.1.tgz", - "integrity": "sha512-BdFsPepnQr9fznNPF9nF4vQ457U/ZJXQDSNF1zBe7yaga8v9AdZf3/NElYxFdUh7SitSGt040QygiTo6dtatIw==", - "requires": { - "batch-processor": "1.0.0" - } - }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", diff --git a/package.json b/package.json index 5877b3c7..4a5dbfb7 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,6 @@ }, "dependencies": { "deep-object-diff": "^1.1.0", - "element-resize-detector": "^1.2.1", "fs-extra": "^9.0.1", "marked": "^1.1.1", "node-pty-prebuilt-multiarch": "^0.9.0", diff --git a/spec/custom-runner.js b/spec/custom-runner.js index 1ba64681..fb0a068e 100644 --- a/spec/custom-runner.js +++ b/spec/custom-runner.js @@ -22,6 +22,7 @@ import { createRunner } from 'atom-jasmine3-test-runner' module.exports = createRunner({}, () => { + // eslint-disable-next-line no-console const warn = console.warn.bind(console) beforeEach(() => { spyOn(console, 'warn').and.callFake((...args) => { diff --git a/spec/element-spec.js b/spec/element-spec.js index 3b52b35e..0c042a57 100644 --- a/spec/element-spec.js +++ b/spec/element-spec.js @@ -1592,21 +1592,14 @@ describe('XTerminalElement', () => { it('refitTerminal() terminal not visible', () => { spyOn(this.element.fitAddon, 'proposeDimensions') - this.element.terminalDivIntersectionRatio = 0.0 - this.element.refitTerminal() - expect(this.element.fitAddon.proposeDimensions).not.toHaveBeenCalled() - }) - - it('refitTerminal() terminal partially visible', () => { - spyOn(this.element.fitAddon, 'proposeDimensions') - this.element.terminalDivIntersectionRatio = 0.5 + this.element.terminalDivInitiallyVisible = false 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.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.refitTerminal() expect(this.element.fitAddon.proposeDimensions).toHaveBeenCalled() }) @@ -1617,7 +1610,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() expect(this.element.terminal.resize).not.toHaveBeenCalled() @@ -1629,7 +1622,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() expect(this.element.terminal.resize).toHaveBeenCalled() @@ -1641,7 +1634,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows + 1, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() expect(this.element.terminal.resize).toHaveBeenCalled() @@ -1653,7 +1646,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows + 1, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() expect(this.element.terminal.resize).toHaveBeenCalled() @@ -1665,7 +1658,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows - 1, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() expect(this.element.terminal.resize).toHaveBeenCalled() @@ -1677,7 +1670,7 @@ describe('XTerminalElement', () => { rows: this.element.terminal.rows - 1, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = false this.element.refitTerminal() expect(this.element.terminal.resize).toHaveBeenCalled() @@ -1689,7 +1682,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).not.toHaveBeenCalled() @@ -1701,7 +1694,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalled() @@ -1713,7 +1706,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows + 1, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalled() @@ -1725,7 +1718,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows + 1, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalled() @@ -1737,7 +1730,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalled() @@ -1749,7 +1742,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows - 1, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalled() @@ -1761,7 +1754,7 @@ describe('XTerminalElement', () => { rows: this.element.ptyProcessRows - 1, }) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalled() @@ -1774,7 +1767,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalledWith(expected.cols, expected.rows) @@ -1787,7 +1780,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalledWith(expected.cols, expected.rows) @@ -1800,7 +1793,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalledWith(expected.cols, expected.rows) @@ -1813,7 +1806,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalledWith(expected.cols, expected.rows) @@ -1826,7 +1819,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalledWith(expected.cols, expected.rows) @@ -1839,7 +1832,7 @@ describe('XTerminalElement', () => { } spyOn(this.element.fitAddon, 'proposeDimensions').and.returnValue(expected) spyOn(this.element.terminal, 'resize') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.ptyProcessRunning = true this.element.refitTerminal() expect(this.element.ptyProcess.resize).toHaveBeenCalledWith(expected.cols, expected.rows) @@ -2224,7 +2217,7 @@ describe('XTerminalElement', () => { it('applyPendingTerminalProfileOptions() terminal not visible', () => { spyOn(this.element, 'refitTerminal') - this.element.terminalDivIntersectionRatio = 0.0 + this.element.terminalDivInitiallyVisible = false this.element.applyPendingTerminalProfileOptions() expect(this.element.refitTerminal).not.toHaveBeenCalled() }) @@ -2234,7 +2227,7 @@ describe('XTerminalElement', () => { spyOn(this.element, 'setMainBackgroundColor') spyOn(this.element, 'restartPtyProcess') spyOn(this.element.terminal, 'setOption') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.applyPendingTerminalProfileOptions() expect(this.element.setMainBackgroundColor).toHaveBeenCalled() expect(this.element.terminal.setOption).not.toHaveBeenCalled() @@ -2247,7 +2240,7 @@ describe('XTerminalElement', () => { spyOn(this.element, 'setMainBackgroundColor') spyOn(this.element, 'restartPtyProcess') spyOn(this.element.terminal, 'setOption') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.pendingTerminalProfileOptions.xtermOptions = { cursorBlink: true, } @@ -2263,7 +2256,7 @@ describe('XTerminalElement', () => { spyOn(this.element, 'setMainBackgroundColor') spyOn(this.element, 'restartPtyProcess') spyOn(this.element.terminal, 'setOption') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.pendingTerminalProfileOptions.command = 'somecommand' this.element.applyPendingTerminalProfileOptions() expect(this.element.setMainBackgroundColor).toHaveBeenCalled() @@ -2277,7 +2270,7 @@ describe('XTerminalElement', () => { spyOn(this.element, 'setMainBackgroundColor') spyOn(this.element, 'restartPtyProcess') spyOn(this.element.terminal, 'setOption') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.pendingTerminalProfileOptions.xtermOptions = { cursorBlink: true, } @@ -2291,7 +2284,7 @@ describe('XTerminalElement', () => { it('applyPendingTerminalProfileOptions() terminal not visible pending xtermOptions and pty changes kept', () => { spyOn(this.element, 'refitTerminal') - this.element.terminalDivIntersectionRatio = 0.0 + this.element.terminalDivInitiallyVisible = false this.element.pendingTerminalProfileOptions.xtermOptions = { cursorBlink: true, } @@ -2307,7 +2300,7 @@ describe('XTerminalElement', () => { it('applyPendingTerminalProfileOptions() terminal visible pending xtermOptions and pty changes removed', () => { spyOn(this.element, 'refitTerminal') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.pendingTerminalProfileOptions.xtermOptions = { cursorBlink: true, } @@ -2318,7 +2311,7 @@ describe('XTerminalElement', () => { it('applyPendingTerminalProfileOptions() terminal not visible x-terminal options removed', () => { spyOn(this.element, 'refitTerminal') - this.element.terminalDivIntersectionRatio = 0.0 + this.element.terminalDivInitiallyVisible = false this.element.pendingTerminalProfileOptions.leaveOpenAfterExit = true this.element.pendingTerminalProfileOptions.relaunchTerminalOnStartup = true this.element.pendingTerminalProfileOptions.title = 'foo' @@ -2328,7 +2321,7 @@ describe('XTerminalElement', () => { it('applyPendingTerminalProfileOptions() terminal visible x-terminal options removed', () => { spyOn(this.element, 'refitTerminal') - this.element.terminalDivIntersectionRatio = 1.0 + this.element.terminalDivInitiallyVisible = true this.element.pendingTerminalProfileOptions.leaveOpenAfterExit = true this.element.pendingTerminalProfileOptions.relaunchTerminalOnStartup = true this.element.pendingTerminalProfileOptions.title = 'foo' diff --git a/src/element.js b/src/element.js index 6b2c6c01..0b50a4c0 100644 --- a/src/element.js +++ b/src/element.js @@ -19,7 +19,7 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { CompositeDisposable } from 'atom' +import { CompositeDisposable, Disposable } from 'atom' import { spawn as spawnPty } from 'node-pty-prebuilt-multiarch' import { Terminal } from 'xterm' import { FitAddon } from 'xterm-addon-fit' @@ -34,8 +34,6 @@ import { XTerminalProfilesSingleton } from './profiles' import fs from 'fs-extra' -import elementResizeDetectorMaker from 'element-resize-detector' - const PTY_PROCESS_OPTIONS = new Set([ 'command', 'args', @@ -74,7 +72,7 @@ class XTerminalElementImpl extends HTMLElement { this.atomXtermProfileMenuElement = new XTerminalProfileMenuElement() this.hoveredLink = null this.pendingTerminalProfileOptions = {} - this.terminalDivIntersectionRatio = 0.0 + this.terminalDivInitiallyVisible = false this.isInitialized = false let resolveInit, rejectInit this.initializedPromise = new Promise((resolve, reject) => { @@ -91,25 +89,37 @@ class XTerminalElementImpl extends HTMLElement { // 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.erd = elementResizeDetectorMaker({ - strategy: 'scroll', - }) - this.erd.listenTo(this.mainDiv, (element) => { + this.mainDivResizeObserver = new ResizeObserver((entries, observer) => { this.refitTerminal() }) + this.mainDivResizeObserver.observe(this.mainDiv) + this.disposables.add(new Disposable(() => { + this.mainDivResizeObserver.disconnect() + this.mainDivResizeObserver = null + })) // 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 entry = entries[0] - this.terminalDivIntersectionRatio = entry.intersectionRatio - this.applyPendingTerminalProfileOptions() + const visible = entries.some(e => e.intersectionRatio === 1.0) + if (visible) { + this.terminalDivInitiallyVisible = true + this.applyPendingTerminalProfileOptions() + // Remove observer once visible + this.terminalDivIntersectionObserver.disconnect() + this.terminalDivIntersectionObserver = null + } }, { root: this, threshold: 1.0, }) this.terminalDivIntersectionObserver.observe(this.terminalDiv) + this.disposables.add(new Disposable(() => { + if (this.terminalDivIntersectionObserver) { + this.terminalDivIntersectionObserver.disconnect() + } + })) // Add event handler for increasing/decreasing the font when // holding 'ctrl' and moving the mouse wheel up or down. this.terminalDiv.addEventListener( @@ -614,7 +624,7 @@ class XTerminalElementImpl extends HTMLElement { applyPendingTerminalProfileOptions () { // For any changes involving the xterm.js Terminal object, only apply them // when the terminal is visible. - if (this.terminalDivIntersectionRatio === 1.0) { + if (this.terminalDivInitiallyVisible) { const xtermOptions = this.pendingTerminalProfileOptions.xtermOptions || {} // NOTE: For legacy reasons, the font size is defined from the 'fontSize' // key outside of any defined xterm.js Terminal options. @@ -668,7 +678,7 @@ class XTerminalElementImpl extends HTMLElement { refitTerminal () { // Only refit the terminal when it is completely visible. - if (this.terminalDivIntersectionRatio === 1.0) { + if (this.terminalDivInitiallyVisible) { this.fitAddon.fit() const geometry = this.fitAddon.proposeDimensions() if (geometry && this.isPtyProcessRunning()) {