Merge remote-tracking branch 'origin/v3' into 731_screen_reader
This commit is contained in:
+5
-5
@@ -39,8 +39,8 @@ function setTerminalSize() {
|
|||||||
var rows = parseInt(rowsElement.value, 10);
|
var rows = parseInt(rowsElement.value, 10);
|
||||||
var viewportElement = document.querySelector('.xterm-viewport');
|
var viewportElement = document.querySelector('.xterm-viewport');
|
||||||
var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth;
|
var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth;
|
||||||
var width = (cols * term.charMeasure.width + 20 /*room for scrollbar*/).toString() + 'px';
|
var width = (cols * term.renderer.dimensions.actualCellWidth + 20 /*room for scrollbar*/).toString() + 'px';
|
||||||
var height = (rows * term.charMeasure.height).toString() + 'px';
|
var height = (rows * term.renderer.dimensions.actualCellHeight).toString() + 'px';
|
||||||
|
|
||||||
terminalContainer.style.width = width;
|
terminalContainer.style.width = width;
|
||||||
terminalContainer.style.height = height;
|
terminalContainer.style.height = height;
|
||||||
@@ -120,9 +120,9 @@ function createTerminal() {
|
|||||||
|
|
||||||
fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) {
|
fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) {
|
||||||
|
|
||||||
res.text().then(function (pid) {
|
res.text().then(function (processId) {
|
||||||
window.pid = pid;
|
pid = processId;
|
||||||
socketURL += pid;
|
socketURL += processId;
|
||||||
socket = new WebSocket(socketURL);
|
socket = new WebSocket(socketURL);
|
||||||
socket.onopen = runRealTerminal;
|
socket.onopen = runRealTerminal;
|
||||||
socket.onclose = runFakeTerminal;
|
socket.onclose = runFakeTerminal;
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ namespace properties {
|
|||||||
|
|
||||||
namespace static_methods {
|
namespace static_methods {
|
||||||
{
|
{
|
||||||
Terminal.loadAddon('attach');
|
Terminal.applyAddon({});
|
||||||
Terminal.loadAddon('fit');
|
Terminal.applyAddon({});
|
||||||
Terminal.loadAddon('fullscreen');
|
Terminal.applyAddon({});
|
||||||
Terminal.loadAddon('search');
|
Terminal.applyAddon({});
|
||||||
Terminal.loadAddon('terminado');
|
Terminal.applyAddon({});
|
||||||
Terminal.loadAddon('winptyCompat');
|
Terminal.applyAddon({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ namespace methods_core {
|
|||||||
// no arg
|
// no arg
|
||||||
t.on('blur', () => {});
|
t.on('blur', () => {});
|
||||||
t.on('focus', () => {});
|
t.on('focus', () => {});
|
||||||
t.on('lineFeed', () => {});
|
t.on('linefeed', () => {});
|
||||||
t.on('selection', () => {});
|
t.on('selection', () => {});
|
||||||
// args
|
// args
|
||||||
t.on('data', () => {});
|
t.on('data', () => {});
|
||||||
@@ -89,7 +89,7 @@ namespace methods_core {
|
|||||||
// no arg
|
// no arg
|
||||||
t.off('blur', () => {});
|
t.off('blur', () => {});
|
||||||
t.off('focus', () => {});
|
t.off('focus', () => {});
|
||||||
t.off('lineFeed', () => {});
|
t.off('linefeed', () => {});
|
||||||
t.off('selection', () => {});
|
t.off('selection', () => {});
|
||||||
// args
|
// args
|
||||||
t.off('data', () => {});
|
t.off('data', () => {});
|
||||||
@@ -170,9 +170,9 @@ namespace methods_core {
|
|||||||
t.setOption('handler', (data: string) => console.log(data));
|
t.setOption('handler', (data: string) => console.log(data));
|
||||||
t.setOption('bellSound', 'foo');
|
t.setOption('bellSound', 'foo');
|
||||||
t.setOption('bellStyle', 'none');
|
t.setOption('bellStyle', 'none');
|
||||||
t.setOption('bellStyle', 'visual');
|
// t.setOption('bellStyle', 'visual');
|
||||||
t.setOption('bellStyle', 'sound');
|
t.setOption('bellStyle', 'sound');
|
||||||
t.setOption('bellStyle', 'both');
|
// t.setOption('bellStyle', 'both');
|
||||||
t.setOption('fontSize', 1);
|
t.setOption('fontSize', 1);
|
||||||
t.setOption('lineHeight', 1);
|
t.setOption('lineHeight', 1);
|
||||||
t.setOption('fontFamily', 'foo');
|
t.setOption('fontFamily', 'foo');
|
||||||
|
|||||||
+2
-2
@@ -138,9 +138,9 @@ export class InputHandler implements IInputHandler {
|
|||||||
/**
|
/**
|
||||||
* This event is emitted whenever the terminal outputs a LF or NL.
|
* This event is emitted whenever the terminal outputs a LF or NL.
|
||||||
*
|
*
|
||||||
* @event lineFeed
|
* @event linefeed
|
||||||
*/
|
*/
|
||||||
this._terminal.emit('lineFeed');
|
this._terminal.emit('linefeed');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+22
-11
@@ -319,7 +319,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
|||||||
* Focus the terminal. Delegates focus handling to the terminal's DOM element.
|
* Focus the terminal. Delegates focus handling to the terminal's DOM element.
|
||||||
*/
|
*/
|
||||||
public focus(): void {
|
public focus(): void {
|
||||||
this.textarea.focus();
|
if (this.textarea) {
|
||||||
|
this.textarea.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get isFocused(): boolean {
|
public get isFocused(): boolean {
|
||||||
@@ -588,19 +590,19 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
|||||||
this.element = this.document.createElement('div');
|
this.element = this.document.createElement('div');
|
||||||
this.element.classList.add('terminal');
|
this.element.classList.add('terminal');
|
||||||
this.element.classList.add('xterm');
|
this.element.classList.add('xterm');
|
||||||
|
|
||||||
this.element.setAttribute('tabindex', '0');
|
this.element.setAttribute('tabindex', '0');
|
||||||
|
this.parent.appendChild(this.element);
|
||||||
|
|
||||||
|
// Performance: Use a document fragment to build the terminal
|
||||||
|
// viewport and helper elements detached from the DOM
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
this.viewportElement = document.createElement('div');
|
this.viewportElement = document.createElement('div');
|
||||||
this.viewportElement.classList.add('xterm-viewport');
|
this.viewportElement.classList.add('xterm-viewport');
|
||||||
this.element.appendChild(this.viewportElement);
|
fragment.appendChild(this.viewportElement);
|
||||||
this.viewportScrollArea = document.createElement('div');
|
this.viewportScrollArea = document.createElement('div');
|
||||||
this.viewportScrollArea.classList.add('xterm-scroll-area');
|
this.viewportScrollArea.classList.add('xterm-scroll-area');
|
||||||
this.viewportElement.appendChild(this.viewportScrollArea);
|
this.viewportElement.appendChild(this.viewportScrollArea);
|
||||||
|
|
||||||
// preload audio
|
|
||||||
this.syncBellSound();
|
|
||||||
|
|
||||||
this._mouseZoneManager = new MouseZoneManager(this);
|
this._mouseZoneManager = new MouseZoneManager(this);
|
||||||
this.on('scroll', () => this._mouseZoneManager.clearAll());
|
this.on('scroll', () => this._mouseZoneManager.clearAll());
|
||||||
this.linkifier.attachToDom(this._mouseZoneManager);
|
this.linkifier.attachToDom(this._mouseZoneManager);
|
||||||
@@ -609,8 +611,8 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
|||||||
// capturing DOM Events. Then produce the helpers.
|
// capturing DOM Events. Then produce the helpers.
|
||||||
this.helperContainer = document.createElement('div');
|
this.helperContainer = document.createElement('div');
|
||||||
this.helperContainer.classList.add('xterm-helpers');
|
this.helperContainer.classList.add('xterm-helpers');
|
||||||
// TODO: This should probably be inserted once it's filled to prevent an additional layout
|
fragment.appendChild(this.helperContainer);
|
||||||
this.element.appendChild(this.helperContainer);
|
|
||||||
this.textarea = document.createElement('textarea');
|
this.textarea = document.createElement('textarea');
|
||||||
this.textarea.classList.add('xterm-helper-textarea');
|
this.textarea.classList.add('xterm-helper-textarea');
|
||||||
this.textarea.setAttribute('autocorrect', 'off');
|
this.textarea.setAttribute('autocorrect', 'off');
|
||||||
@@ -628,11 +630,14 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
|||||||
|
|
||||||
this.charSizeStyleElement = document.createElement('style');
|
this.charSizeStyleElement = document.createElement('style');
|
||||||
this.helperContainer.appendChild(this.charSizeStyleElement);
|
this.helperContainer.appendChild(this.charSizeStyleElement);
|
||||||
|
|
||||||
this.parent.appendChild(this.element);
|
|
||||||
|
|
||||||
this.charMeasure = new CharMeasure(document, this.helperContainer);
|
this.charMeasure = new CharMeasure(document, this.helperContainer);
|
||||||
|
|
||||||
|
// Preload audio, this relied on helperContainer
|
||||||
|
this.syncBellSound();
|
||||||
|
|
||||||
|
// Performance: Add viewport and helper elements from the fragment
|
||||||
|
this.element.appendChild(fragment);
|
||||||
|
|
||||||
this.renderer = new Renderer(this, this.options.theme);
|
this.renderer = new Renderer(this, this.options.theme);
|
||||||
this.options.theme = null;
|
this.options.theme = null;
|
||||||
this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
|
this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
|
||||||
@@ -681,6 +686,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
|||||||
// Listen for mouse events and translate
|
// Listen for mouse events and translate
|
||||||
// them into terminal mouse protocols.
|
// them into terminal mouse protocols.
|
||||||
this.bindMouse();
|
this.bindMouse();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2124,6 +2130,11 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
|||||||
}
|
}
|
||||||
|
|
||||||
private syncBellSound(): void {
|
private syncBellSound(): void {
|
||||||
|
// Don't update anything if the terminal has not been opened yet
|
||||||
|
if (!this.element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.soundBell() && this.bellAudioElement) {
|
if (this.soundBell() && this.bellAudioElement) {
|
||||||
this.bellAudioElement.setAttribute('src', this.options.bellSound);
|
this.bellAudioElement.setAttribute('src', this.options.bellSound);
|
||||||
} else if (this.soundBell()) {
|
} else if (this.soundBell()) {
|
||||||
|
|||||||
+9
-14
@@ -26,27 +26,22 @@ export function proposeGeometry(term) {
|
|||||||
var availableHeight = parentElementHeight - elementPaddingVer;
|
var availableHeight = parentElementHeight - elementPaddingVer;
|
||||||
var availableWidth = parentElementWidth - elementPaddingHor;
|
var availableWidth = parentElementWidth - elementPaddingHor;
|
||||||
var geometry = {
|
var geometry = {
|
||||||
cols: Math.floor(availableWidth / term.charMeasure.width),
|
cols: Math.floor(availableWidth / term.renderer.dimensions.actualCellWidth),
|
||||||
rows: Math.floor(availableHeight / Math.floor(term.charMeasure.height * term.getOption('lineHeight')))
|
rows: Math.floor(availableHeight / term.renderer.dimensions.actualCellHeight)
|
||||||
};
|
};
|
||||||
|
|
||||||
return geometry;
|
return geometry;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function fit(term) {
|
export function fit(term) {
|
||||||
// Wrap fit in a setTimeout as charMeasure needs time to get initialized
|
var geometry = exports.proposeGeometry(term);
|
||||||
// after calling Terminal.open
|
if (geometry) {
|
||||||
setTimeout(function () {
|
// Force a full render
|
||||||
var geometry = exports.proposeGeometry(term);
|
if (term.rows !== geometry.rows || term.cols !== geometry.cols) {
|
||||||
|
term.renderer.clear();
|
||||||
if (geometry) {
|
term.resize(geometry.cols, geometry.rows);
|
||||||
// Force a full render
|
|
||||||
if (term.rows !== geometry.rows || term.cols !== geometry.cols) {
|
|
||||||
term.renderer.clear();
|
|
||||||
term.resize(geometry.cols, geometry.rows);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, 0);
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export function apply(terminalConstructor) {
|
export function apply(terminalConstructor) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function winptyCompatInit(terminal): void {
|
|||||||
// space. This is certainly not without its problems, but generally on
|
// space. This is certainly not without its problems, but generally on
|
||||||
// Windows when text reaches the end of the terminal it's likely going to be
|
// Windows when text reaches the end of the terminal it's likely going to be
|
||||||
// wrapped.
|
// wrapped.
|
||||||
terminal.on('lineFeed', () => {
|
terminal.on('linefeed', () => {
|
||||||
const line = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y - 1);
|
const line = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y - 1);
|
||||||
const lastChar = line[terminal.cols - 1];
|
const lastChar = line[terminal.cols - 1];
|
||||||
|
|
||||||
|
|||||||
+65
-53
@@ -52,6 +52,7 @@ export class Renderer extends EventEmitter implements IRenderer {
|
|||||||
actualCellHeight: null
|
actualCellHeight: null
|
||||||
};
|
};
|
||||||
this._devicePixelRatio = window.devicePixelRatio;
|
this._devicePixelRatio = window.devicePixelRatio;
|
||||||
|
this._updateDimensions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public onWindowResize(devicePixelRatio: number): void {
|
public onWindowResize(devicePixelRatio: number): void {
|
||||||
@@ -78,59 +79,8 @@ export class Renderer extends EventEmitter implements IRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onResize(cols: number, rows: number, didCharSizeChange: boolean): void {
|
public onResize(cols: number, rows: number, didCharSizeChange: boolean): void {
|
||||||
if (!this._terminal.charMeasure.width || !this._terminal.charMeasure.height) {
|
// Update character and canvas dimensions
|
||||||
return;
|
this._updateDimensions();
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the scaled character width. Width is floored as it must be
|
|
||||||
// drawn to an integer grid in order for the CharAtlas "stamps" to not be
|
|
||||||
// blurry. When text is drawn to the grid not using the CharAtlas, it is
|
|
||||||
// clipped to ensure there is no overlap with the next cell.
|
|
||||||
this.dimensions.scaledCharWidth = Math.floor(this._terminal.charMeasure.width * window.devicePixelRatio);
|
|
||||||
|
|
||||||
// Calculate the scaled character height. Height is ceiled in case
|
|
||||||
// devicePixelRatio is a floating point number in order to ensure there is
|
|
||||||
// enough space to draw the character to the cell.
|
|
||||||
this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio);
|
|
||||||
|
|
||||||
// Calculate the scaled cell height, if lineHeight is not 1 then the value
|
|
||||||
// will be floored because since lineHeight can never be lower then 1, there
|
|
||||||
// is a guarentee that the scaled line height will always be larger than
|
|
||||||
// scaled char height.
|
|
||||||
this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight);
|
|
||||||
|
|
||||||
// Calculate the y coordinate within a cell that text should draw from in
|
|
||||||
// order to draw in the center of a cell.
|
|
||||||
this.dimensions.scaledCharTop = this._terminal.options.lineHeight === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2);
|
|
||||||
|
|
||||||
// Calculate the scaled cell width, taking the letterSpacing into account.
|
|
||||||
this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing);
|
|
||||||
|
|
||||||
// Calculate the x coordinate with a cell that text should draw from in
|
|
||||||
// order to draw in the center of a cell.
|
|
||||||
this.dimensions.scaledCharLeft = Math.floor(this._terminal.options.letterSpacing / 2);
|
|
||||||
|
|
||||||
// Recalculate the canvas dimensions; scaled* define the actual number of
|
|
||||||
// pixel in the canvas
|
|
||||||
this.dimensions.scaledCanvasHeight = this._terminal.rows * this.dimensions.scaledCellHeight;
|
|
||||||
this.dimensions.scaledCanvasWidth = this._terminal.cols * this.dimensions.scaledCellWidth;
|
|
||||||
|
|
||||||
// The the size of the canvas on the page. It's very important that this
|
|
||||||
// rounds to nearest integer and not ceils as browsers often set
|
|
||||||
// window.devicePixelRatio as something like 1.100000023841858, when it's
|
|
||||||
// actually 1.1. Ceiling causes blurriness as the backing canvas image is 1
|
|
||||||
// pixel too large for the canvas element size.
|
|
||||||
this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio);
|
|
||||||
this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio);
|
|
||||||
|
|
||||||
// Get the _actual_ dimensions of an individual cell. This needs to be
|
|
||||||
// derived from the canvasWidth/Height calculated above which takes into
|
|
||||||
// account window.devicePixelRatio. CharMeasure.width/height by itself is
|
|
||||||
// insufficient when the page is not at 100% zoom level as CharMeasure is
|
|
||||||
// measured in CSS pixels, but the actual char size on the canvas can
|
|
||||||
// differ.
|
|
||||||
this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._terminal.rows;
|
|
||||||
this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._terminal.cols;
|
|
||||||
|
|
||||||
// Resize all render layers
|
// Resize all render layers
|
||||||
this._renderLayers.forEach(l => l.resize(this._terminal, this.dimensions, didCharSizeChange));
|
this._renderLayers.forEach(l => l.resize(this._terminal, this.dimensions, didCharSizeChange));
|
||||||
@@ -218,4 +168,66 @@ export class Renderer extends EventEmitter implements IRenderer {
|
|||||||
this._renderLayers.forEach(l => l.onGridChanged(this._terminal, start, end));
|
this._renderLayers.forEach(l => l.onGridChanged(this._terminal, start, end));
|
||||||
this._terminal.emit('refresh', {start, end});
|
this._terminal.emit('refresh', {start, end});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recalculates the character and canvas dimensions.
|
||||||
|
*/
|
||||||
|
private _updateDimensions(): void {
|
||||||
|
// Perform a new measure if the CharMeasure dimensions are not yet available
|
||||||
|
if (!this._terminal.charMeasure.width || !this._terminal.charMeasure.height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the scaled character width. Width is floored as it must be
|
||||||
|
// drawn to an integer grid in order for the CharAtlas "stamps" to not be
|
||||||
|
// blurry. When text is drawn to the grid not using the CharAtlas, it is
|
||||||
|
// clipped to ensure there is no overlap with the next cell.
|
||||||
|
this.dimensions.scaledCharWidth = Math.floor(this._terminal.charMeasure.width * window.devicePixelRatio);
|
||||||
|
|
||||||
|
// Calculate the scaled character height. Height is ceiled in case
|
||||||
|
// devicePixelRatio is a floating point number in order to ensure there is
|
||||||
|
// enough space to draw the character to the cell.
|
||||||
|
this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio);
|
||||||
|
|
||||||
|
// Calculate the scaled cell height, if lineHeight is not 1 then the value
|
||||||
|
// will be floored because since lineHeight can never be lower then 1, there
|
||||||
|
// is a guarentee that the scaled line height will always be larger than
|
||||||
|
// scaled char height.
|
||||||
|
this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight);
|
||||||
|
|
||||||
|
// Calculate the y coordinate within a cell that text should draw from in
|
||||||
|
// order to draw in the center of a cell.
|
||||||
|
this.dimensions.scaledCharTop = this._terminal.options.lineHeight === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2);
|
||||||
|
|
||||||
|
// Calculate the scaled cell width, taking the letterSpacing into account.
|
||||||
|
this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing);
|
||||||
|
|
||||||
|
// Calculate the x coordinate with a cell that text should draw from in
|
||||||
|
// order to draw in the center of a cell.
|
||||||
|
this.dimensions.scaledCharLeft = Math.floor(this._terminal.options.letterSpacing / 2);
|
||||||
|
|
||||||
|
// Recalculate the canvas dimensions; scaled* define the actual number of
|
||||||
|
// pixel in the canvas
|
||||||
|
this.dimensions.scaledCanvasHeight = this._terminal.rows * this.dimensions.scaledCellHeight;
|
||||||
|
this.dimensions.scaledCanvasWidth = this._terminal.cols * this.dimensions.scaledCellWidth;
|
||||||
|
|
||||||
|
// The the size of the canvas on the page. It's very important that this
|
||||||
|
// rounds to nearest integer and not ceils as browsers often set
|
||||||
|
// window.devicePixelRatio as something like 1.100000023841858, when it's
|
||||||
|
// actually 1.1. Ceiling causes blurriness as the backing canvas image is 1
|
||||||
|
// pixel too large for the canvas element size.
|
||||||
|
this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio);
|
||||||
|
this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio);
|
||||||
|
|
||||||
|
// Get the _actual_ dimensions of an individual cell. This needs to be
|
||||||
|
// derived from the canvasWidth/Height calculated above which takes into
|
||||||
|
// account window.devicePixelRatio. CharMeasure.width/height by itself is
|
||||||
|
// insufficient when the page is not at 100% zoom level as CharMeasure is
|
||||||
|
// measured in CSS pixels, but the actual char size on the canvas can
|
||||||
|
// differ.
|
||||||
|
this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._terminal.rows;
|
||||||
|
this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._terminal.cols;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,41 +25,18 @@ describe('CharMeasure', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('measure', () => {
|
describe('measure', () => {
|
||||||
it('should set _measureElement on first call', () => {
|
it('should have _measureElement', () => {
|
||||||
charMeasure.measure({});
|
assert.isDefined((<any>charMeasure)._measureElement, 'new CharMeasure() should have created _measureElement');
|
||||||
assert.isDefined((<any>charMeasure)._measureElement, 'CharMeasure.measure should have created _measureElement');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be performed async on first call', done => {
|
it('should be performed sync', () => {
|
||||||
assert.equal(charMeasure.width, null);
|
|
||||||
charMeasure.measure({});
|
|
||||||
// Mock getBoundingClientRect since jsdom doesn't have a layout engine
|
// Mock getBoundingClientRect since jsdom doesn't have a layout engine
|
||||||
(<any>charMeasure)._measureElement.getBoundingClientRect = () => {
|
(<any>charMeasure)._measureElement.getBoundingClientRect = () => {
|
||||||
return { width: 1, height: 1 };
|
return { width: 1, height: 1 };
|
||||||
};
|
};
|
||||||
assert.equal(charMeasure.width, null);
|
|
||||||
setTimeout(() => {
|
|
||||||
assert.equal(charMeasure.width, 1);
|
|
||||||
done();
|
|
||||||
}, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be performed sync on successive calls', done => {
|
|
||||||
charMeasure.measure({});
|
charMeasure.measure({});
|
||||||
// Mock getBoundingClientRect since jsdom doesn't have a layout engine
|
assert.equal(charMeasure.height, 1);
|
||||||
(<any>charMeasure)._measureElement.getBoundingClientRect = () => {
|
assert.equal(charMeasure.width, 1);
|
||||||
return { width: 1, height: 1 };
|
|
||||||
};
|
|
||||||
setTimeout(() => {
|
|
||||||
const firstWidth = charMeasure.width;
|
|
||||||
// Mock getBoundingClientRect since jsdom doesn't have a layout engine
|
|
||||||
(<any>charMeasure)._measureElement.getBoundingClientRect = () => {
|
|
||||||
return { width: 2, height: 2 };
|
|
||||||
};
|
|
||||||
charMeasure.measure({});
|
|
||||||
assert.equal(charMeasure.width, firstWidth * 2);
|
|
||||||
done();
|
|
||||||
}, 0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should NOT do a measure when the parent is hidden', done => {
|
it('should NOT do a measure when the parent is hidden', done => {
|
||||||
|
|||||||
@@ -22,6 +22,14 @@ export class CharMeasure extends EventEmitter implements ICharMeasure {
|
|||||||
super();
|
super();
|
||||||
this._document = document;
|
this._document = document;
|
||||||
this._parentElement = parentElement;
|
this._parentElement = parentElement;
|
||||||
|
this._measureElement = this._document.createElement('span');
|
||||||
|
this._measureElement.style.position = 'absolute';
|
||||||
|
this._measureElement.style.top = '0';
|
||||||
|
this._measureElement.style.left = '-9999em';
|
||||||
|
this._measureElement.style.lineHeight = 'normal';
|
||||||
|
this._measureElement.textContent = 'W';
|
||||||
|
this._measureElement.setAttribute('aria-hidden', 'true');
|
||||||
|
this._parentElement.appendChild(this._measureElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get width(): number {
|
public get width(): number {
|
||||||
@@ -33,24 +41,6 @@ export class CharMeasure extends EventEmitter implements ICharMeasure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public measure(options: ITerminalOptions): void {
|
public measure(options: ITerminalOptions): void {
|
||||||
if (!this._measureElement) {
|
|
||||||
this._measureElement = this._document.createElement('span');
|
|
||||||
this._measureElement.style.position = 'absolute';
|
|
||||||
this._measureElement.style.top = '0';
|
|
||||||
this._measureElement.style.left = '-9999em';
|
|
||||||
this._measureElement.style.lineHeight = 'normal';
|
|
||||||
this._measureElement.textContent = 'W';
|
|
||||||
this._measureElement.setAttribute('aria-hidden', 'true');
|
|
||||||
this._parentElement.appendChild(this._measureElement);
|
|
||||||
// Perform _doMeasure async if the element was just attached as sometimes
|
|
||||||
// getBoundingClientRect does not return accurate values without this.
|
|
||||||
setTimeout(() => this._doMeasure(options), 0);
|
|
||||||
} else {
|
|
||||||
this._doMeasure(options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _doMeasure(options: ITerminalOptions): void {
|
|
||||||
this._measureElement.style.fontFamily = options.fontFamily;
|
this._measureElement.style.fontFamily = options.fontFamily;
|
||||||
this._measureElement.style.fontSize = `${options.fontSize}px`;
|
this._measureElement.style.fontSize = `${options.fontSize}px`;
|
||||||
const geometry = this._measureElement.getBoundingClientRect();
|
const geometry = this._measureElement.getBoundingClientRect();
|
||||||
@@ -65,4 +55,5 @@ export class CharMeasure extends EventEmitter implements ICharMeasure {
|
|||||||
this.emit('charsizechanged');
|
this.emit('charsizechanged');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+7
-7
@@ -20,7 +20,7 @@ declare module 'xterm' {
|
|||||||
/**
|
/**
|
||||||
* The type of the bell notification the terminal will use.
|
* The type of the bell notification the terminal will use.
|
||||||
*/
|
*/
|
||||||
bellStyle?: 'none' | 'visual' | 'sound' | 'both';
|
bellStyle?: 'none' /*| 'visual'*/ | 'sound' /*| 'both'*/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of columns in the terminal.
|
* The number of columns in the terminal.
|
||||||
@@ -218,7 +218,7 @@ declare module 'xterm' {
|
|||||||
* @param type The type of the event.
|
* @param type The type of the event.
|
||||||
* @param listener The listener.
|
* @param listener The listener.
|
||||||
*/
|
*/
|
||||||
on(type: 'blur' | 'focus' | 'lineFeed' | 'selection', listener: () => void): void;
|
on(type: 'blur' | 'focus' | 'linefeed' | 'selection', listener: () => void): void;
|
||||||
/**
|
/**
|
||||||
* Registers an event listener.
|
* Registers an event listener.
|
||||||
* @param type The type of the event.
|
* @param type The type of the event.
|
||||||
@@ -273,7 +273,7 @@ declare module 'xterm' {
|
|||||||
* @param type The type of the event.
|
* @param type The type of the event.
|
||||||
* @param listener The listener.
|
* @param listener The listener.
|
||||||
*/
|
*/
|
||||||
off(type: 'blur' | 'focus' | 'lineFeed' | 'selection' | 'data' | 'key' | 'keypress' | 'keydown' | 'refresh' | 'resize' | 'scroll' | 'title' | string, listener: (...args: any[]) => void): void;
|
off(type: 'blur' | 'focus' | 'linefeed' | 'selection' | 'data' | 'key' | 'keypress' | 'keydown' | 'refresh' | 'resize' | 'scroll' | 'title' | string, listener: (...args: any[]) => void): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resizes the terminal.
|
* Resizes the terminal.
|
||||||
@@ -500,10 +500,10 @@ declare module 'xterm' {
|
|||||||
reset(): void
|
reset(): void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads an addon, attaching it to the Terminal prototype and making it
|
* Applies an addon to the Terminal prototype, making it available to all
|
||||||
* available to all newly created Terminals.
|
* newly created Terminals.
|
||||||
* @param addon The addon to load.
|
* @param addon The addon to apply.
|
||||||
*/
|
*/
|
||||||
static loadAddon(addon: 'attach' | 'fit' | 'fullscreen' | 'search' | 'terminado' | 'winptyCompat'): void;
|
static applyAddon(addon: any): void;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user