From 43c23d2bc033a3e6fbabb4dcf81f9a38104f4914 Mon Sep 17 00:00:00 2001 From: Filip Barl Date: Fri, 18 May 2018 11:45:04 +0200 Subject: [PATCH 1/3] Adjusted character width/height estimation. --- client/app/scripts/components/terminal.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/app/scripts/components/terminal.js b/client/app/scripts/components/terminal.js index 0f7f902ed..d7ea7e58a 100644 --- a/client/app/scripts/components/terminal.js +++ b/client/app/scripts/components/terminal.js @@ -32,8 +32,8 @@ function ab2str(buf) { function terminalCellSize(wrapperNode) { // Badly guess the width/height of the row. - let characterWidth = 20; - let characterHeight = 20; + let characterWidth = 9; + let characterHeight = 17; // Now try and measure the first row we find. const subjectRow = wrapperNode.querySelector('.terminal .xterm-rows div'); @@ -261,8 +261,8 @@ class Terminal extends React.Component { } handleResize() { - // scrollbar === 16px - const width = this.innerFlex.clientWidth - (2 * 8) - 16; + // scrollbar === 20px + const width = this.innerFlex.clientWidth - (2 * 8) - 20; const height = this.innerFlex.clientHeight - (2 * 8); const cols = Math.floor(width / this.state.characterWidth); const rows = Math.floor(height / this.state.characterHeight); From 6e139c940814817b522f1889a1db82f9fc61775a Mon Sep 17 00:00:00 2001 From: Filip Barl Date: Fri, 18 May 2018 12:11:44 +0200 Subject: [PATCH 2/3] Remove outdated terminalCellSize estimation code. --- client/app/scripts/components/terminal.js | 30 +++-------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/client/app/scripts/components/terminal.js b/client/app/scripts/components/terminal.js index d7ea7e58a..58be8c7c8 100644 --- a/client/app/scripts/components/terminal.js +++ b/client/app/scripts/components/terminal.js @@ -30,32 +30,6 @@ function ab2str(buf) { return decodedString; } -function terminalCellSize(wrapperNode) { - // Badly guess the width/height of the row. - let characterWidth = 9; - let characterHeight = 17; - - // Now try and measure the first row we find. - const subjectRow = wrapperNode.querySelector('.terminal .xterm-rows div'); - if (!subjectRow) { - log("ERROR: Couldn't find first row, resizing might not work very well."); - } else { - const rowDisplay = subjectRow.style.display; - const contentBuffer = subjectRow.innerHTML; - - subjectRow.innerHTML = 'W'; - subjectRow.style.display = 'inline'; - characterWidth = subjectRow.getBoundingClientRect().width; - subjectRow.style.display = rowDisplay; - characterHeight = parseInt(subjectRow.offsetHeight, 10); - subjectRow.innerHTML = contentBuffer; - } - - log('Calculated (charWidth, charHeight) sizes in px: ', characterWidth, characterHeight); - return {characterWidth, characterHeight}; -} - - function openNewWindow(url, bcr, minWidth = 200) { const screenLeft = window.screenX || window.screenLeft; const screenTop = window.screenY || window.screenTop; @@ -190,7 +164,9 @@ class Terminal extends React.Component { this.createWebsocket(this.term); - const {characterWidth, characterHeight} = terminalCellSize(this.term.element); + // Estimate the character width/height. + const characterHeight = 17; + const characterWidth = 9; window.addEventListener('resize', this.handleResizeDebounced); From 45486f44c05d975dfeefe51e7b696da36a5747bb Mon Sep 17 00:00:00 2001 From: Filip Barl Date: Fri, 18 May 2018 17:48:54 +0200 Subject: [PATCH 3/3] Use xterm/fit addon. --- client/app/scripts/components/terminal.js | 55 ++++++----------------- client/app/styles/_base.scss | 1 + 2 files changed, 15 insertions(+), 41 deletions(-) diff --git a/client/app/scripts/components/terminal.js b/client/app/scripts/components/terminal.js index 58be8c7c8..d32b37f32 100644 --- a/client/app/scripts/components/terminal.js +++ b/client/app/scripts/components/terminal.js @@ -5,6 +5,7 @@ import { connect } from 'react-redux'; import classNames from 'classnames'; import { debounce } from 'lodash'; import { Terminal as Term } from 'xterm'; +import * as fit from 'xterm/lib/addons/fit/fit'; import { closeTerminal } from '../actions/app-actions'; import { getNeutralColor } from '../utils/color-utils'; @@ -63,8 +64,6 @@ class Terminal extends React.Component { detached: false, rows: DEFAULT_ROWS, cols: DEFAULT_COLS, - characterWidth: 0, - characterHeight: 0 }; this.handleCloseClick = this.handleCloseClick.bind(this); @@ -145,9 +144,8 @@ class Terminal extends React.Component { } mountTerminal() { + Term.applyAddon(fit); this.term = new Term({ - cols: this.state.cols, - rows: this.state.rows, convertEol: !this.props.pipe.get('raw'), cursorBlink: true, scrollback: 10000, @@ -162,19 +160,19 @@ class Terminal extends React.Component { } }); - this.createWebsocket(this.term); + this.term.on('resize', ({ cols, rows }) => { + const resizeTtyControl = this.props.pipe.get('resizeTtyControl'); + if (resizeTtyControl) { + doResizeTty(this.getPipeId(), resizeTtyControl, cols, rows); + } + this.setState({ cols, rows }); + }); - // Estimate the character width/height. - const characterHeight = 17; - const characterWidth = 9; + this.createWebsocket(this.term); window.addEventListener('resize', this.handleResizeDebounced); this.resizeTimeout = setTimeout(() => { - this.setState({ - characterWidth, - characterHeight - }); this.handleResize(); }, 10); } @@ -207,14 +205,7 @@ class Terminal extends React.Component { } } - componentDidUpdate(prevProps, prevState) { - const sizeChanged = ( - prevState.cols !== this.state.cols || - prevState.rows !== this.state.rows - ); - if (sizeChanged) { - this.term.resize(this.state.cols, this.state.rows); - } + componentDidUpdate() { if (!this.isEmbedded()) { setDocumentTitle(this.getTitle()); } @@ -232,24 +223,11 @@ class Terminal extends React.Component { this.setState({detached: true}); const bcr = this.node.getBoundingClientRect(); - const minWidth = (this.state.characterWidth * 80) + (8 * 2); - openNewWindow(`${basePath(window.location.pathname)}/terminal.html#!/state/${paramString}`, bcr, minWidth); + openNewWindow(`${basePath(window.location.pathname)}/terminal.html#!/state/${paramString}`, bcr); } handleResize() { - // scrollbar === 20px - const width = this.innerFlex.clientWidth - (2 * 8) - 20; - const height = this.innerFlex.clientHeight - (2 * 8); - const cols = Math.floor(width / this.state.characterWidth); - const rows = Math.floor(height / this.state.characterHeight); - - const resizeTtyControl = this.props.pipe.get('resizeTtyControl'); - if (resizeTtyControl) { - doResizeTty(this.getPipeId(), resizeTtyControl, cols, rows) - .then(() => this.setState({cols, rows})); - } else if (!this.props.pipe.get('raw')) { - this.setState({cols, rows}); - } + this.term.fit(); } isEmbedded() { @@ -328,9 +306,6 @@ class Terminal extends React.Component { opacity: this.state.connected ? 1 : 0.8, overflow: 'hidden', }; - const innerStyle = { - width: (this.state.cols + 2) * this.state.characterWidth - }; const innerClassName = classNames('terminal-inner hideable', { 'terminal-inactive': !this.state.connected }); @@ -338,9 +313,7 @@ class Terminal extends React.Component { return (
{this.isEmbedded() && this.getTerminalHeader()} -
-
-
+
{this.getTerminalStatusBar()}
); diff --git a/client/app/styles/_base.scss b/client/app/styles/_base.scss index b176308fa..e76782736 100644 --- a/client/app/styles/_base.scss +++ b/client/app/styles/_base.scss @@ -1303,6 +1303,7 @@ a { right: 0; background-color: $color-black; padding: 8px; + box-sizing: content-box; border-bottom-left-radius: $border-radius-soft; .terminal {