mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Support setting padding on the .xterm element (#1208)
* Support padding on the .xterm element
This commit is contained in:
@@ -64,6 +64,10 @@
|
||||
<label for="rows">Rows</label>
|
||||
<input type="number" id="rows" />
|
||||
</div>
|
||||
<div style="display: inline-block; margin-right: 16px;">
|
||||
<label for="padding">Padding</label>
|
||||
<input type="number" id="padding" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+11
-6
@@ -33,23 +33,27 @@ var terminalContainer = document.getElementById('terminal-container'),
|
||||
bellStyle: document.querySelector('#option-bell-style')
|
||||
},
|
||||
colsElement = document.getElementById('cols'),
|
||||
rowsElement = document.getElementById('rows');
|
||||
rowsElement = document.getElementById('rows'),
|
||||
paddingElement = document.getElementById('padding');
|
||||
|
||||
function setTerminalSize() {
|
||||
var cols = parseInt(colsElement.value, 10);
|
||||
var rows = parseInt(rowsElement.value, 10);
|
||||
var viewportElement = document.querySelector('.xterm-viewport');
|
||||
var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth;
|
||||
var width = (cols * term.renderer.dimensions.actualCellWidth + 20 /*room for scrollbar*/).toString() + 'px';
|
||||
var width = (cols * term.renderer.dimensions.actualCellWidth + term.viewport.scrollBarWidth).toString() + 'px';
|
||||
var height = (rows * term.renderer.dimensions.actualCellHeight).toString() + 'px';
|
||||
|
||||
terminalContainer.style.width = width;
|
||||
terminalContainer.style.height = height;
|
||||
term.resize(cols, rows);
|
||||
term.fit();
|
||||
}
|
||||
|
||||
function setPadding() {
|
||||
term.element.style.padding = parseInt(paddingElement.value, 10).toString() + 'px';
|
||||
term.fit();
|
||||
}
|
||||
|
||||
colsElement.addEventListener('change', setTerminalSize);
|
||||
rowsElement.addEventListener('change', setTerminalSize);
|
||||
paddingElement.addEventListener('change', setPadding);
|
||||
|
||||
actionElements.findNext.addEventListener('keypress', function (e) {
|
||||
if (e.key === "Enter") {
|
||||
@@ -119,6 +123,7 @@ function createTerminal() {
|
||||
setTimeout(function () {
|
||||
colsElement.value = term.cols;
|
||||
rowsElement.value = term.rows;
|
||||
paddingElement.value = 0;
|
||||
|
||||
// Set terminal size again to set the specific dimensions on the demo
|
||||
setTerminalSize();
|
||||
|
||||
@@ -309,7 +309,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
* @param event The mouse event.
|
||||
*/
|
||||
private _getMouseBufferCoords(event: MouseEvent): [number, number] {
|
||||
const coords = this._terminal.mouseHelper.getCoords(event, this._terminal.element, this._charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows, true);
|
||||
const coords = this._terminal.mouseHelper.getCoords(event, this._terminal.screenElement, this._charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows, true);
|
||||
if (!coords) {
|
||||
return null;
|
||||
}
|
||||
@@ -329,7 +329,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
||||
* @param event The mouse event.
|
||||
*/
|
||||
private _getMouseEventScrollAmount(event: MouseEvent): number {
|
||||
let offset = MouseHelper.getCoordsRelativeToElement(event, this._terminal.element)[1];
|
||||
let offset = MouseHelper.getCoordsRelativeToElement(event, this._terminal.screenElement)[1];
|
||||
const terminalHeight = this._terminal.rows * Math.ceil(this._charMeasure.height * this._terminal.options.lineHeight);
|
||||
if (offset >= 0 && offset <= terminalHeight) {
|
||||
return 0;
|
||||
|
||||
+11
-7
@@ -96,6 +96,7 @@ const DEFAULT_OPTIONS: ITerminalOptions = {
|
||||
export class Terminal extends EventEmitter implements ITerminal, IInputHandlingTerminal {
|
||||
public textarea: HTMLTextAreaElement;
|
||||
public element: HTMLElement;
|
||||
public screenElement: HTMLElement;
|
||||
|
||||
/**
|
||||
* The HTMLElement that the terminal is created in, set by Terminal.open.
|
||||
@@ -609,15 +610,18 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
this.viewportScrollArea.classList.add('xterm-scroll-area');
|
||||
this.viewportElement.appendChild(this.viewportScrollArea);
|
||||
|
||||
this._mouseZoneManager = new MouseZoneManager(this);
|
||||
this.on('scroll', () => this._mouseZoneManager.clearAll());
|
||||
this.linkifier.attachToDom(this._mouseZoneManager);
|
||||
|
||||
this.screenElement = document.createElement('div');
|
||||
this.screenElement.classList.add('xterm-screen');
|
||||
// Create the container that will hold helpers like the textarea for
|
||||
// capturing DOM Events. Then produce the helpers.
|
||||
this.helperContainer = document.createElement('div');
|
||||
this.helperContainer.classList.add('xterm-helpers');
|
||||
fragment.appendChild(this.helperContainer);
|
||||
this.screenElement.appendChild(this.helperContainer);
|
||||
fragment.appendChild(this.screenElement);
|
||||
|
||||
this._mouseZoneManager = new MouseZoneManager(this);
|
||||
this.on('scroll', () => this._mouseZoneManager.clearAll());
|
||||
this.linkifier.attachToDom(this._mouseZoneManager);
|
||||
|
||||
this.textarea = document.createElement('textarea');
|
||||
this.textarea.classList.add('xterm-helper-textarea');
|
||||
@@ -735,7 +739,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
button = getButton(ev);
|
||||
|
||||
// get mouse coordinates
|
||||
pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows);
|
||||
pos = self.mouseHelper.getRawByteCoords(ev, self.screenElement, self.charMeasure, self.options.lineHeight, self.cols, self.rows);
|
||||
if (!pos) return;
|
||||
|
||||
sendEvent(button, pos);
|
||||
@@ -761,7 +765,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
|
||||
// ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7<
|
||||
function sendMove(ev: MouseEvent): void {
|
||||
let button = pressed;
|
||||
let pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows);
|
||||
let pos = self.mouseHelper.getRawByteCoords(ev, self.screenElement, self.charMeasure, self.options.lineHeight, self.cols, self.rows);
|
||||
if (!pos) return;
|
||||
|
||||
// buttons marked as motions
|
||||
|
||||
@@ -85,6 +85,7 @@ export interface IInputHandlingTerminal extends IEventEmitter {
|
||||
}
|
||||
|
||||
export interface IViewport {
|
||||
scrollBarWidth: number;
|
||||
syncScrollArea(): void;
|
||||
onWheel(ev: WheelEvent): void;
|
||||
onTouchStart(ev: TouchEvent): void;
|
||||
@@ -175,6 +176,7 @@ export interface ILinkHoverEvent {
|
||||
}
|
||||
|
||||
export interface ITerminal extends PublicTerminal, IElementAccessor, IBufferAccessor, ILinkifierAccessor {
|
||||
screenElement: HTMLElement;
|
||||
selectionManager: ISelectionManager;
|
||||
charMeasure: ICharMeasure;
|
||||
renderer: IRenderer;
|
||||
@@ -188,6 +190,7 @@ export interface ITerminal extends PublicTerminal, IElementAccessor, IBufferAcce
|
||||
buffers: IBufferSet;
|
||||
isFocused: boolean;
|
||||
mouseHelper: IMouseHelper;
|
||||
viewport: IViewport;
|
||||
bracketedPasteMode: boolean;
|
||||
applicationCursor: boolean;
|
||||
|
||||
|
||||
+9
-7
@@ -7,11 +7,14 @@ import { IColorSet } from './renderer/Types';
|
||||
import { ITerminal, IViewport } from './Types';
|
||||
import { CharMeasure } from './utils/CharMeasure';
|
||||
|
||||
const FALLBACK_SCROLL_BAR_WIDTH = 15;
|
||||
|
||||
/**
|
||||
* Represents the viewport of a terminal, the visible area within the larger buffer of output.
|
||||
* Logic for the virtual scroll bar is included in this object.
|
||||
*/
|
||||
export class Viewport implements IViewport {
|
||||
public scrollBarWidth: number = 0;
|
||||
private currentRowHeight: number = 0;
|
||||
private lastRecordedBufferLength: number = 0;
|
||||
private lastRecordedViewportHeight: number = 0;
|
||||
@@ -31,6 +34,10 @@ export class Viewport implements IViewport {
|
||||
private scrollArea: HTMLElement,
|
||||
private charMeasure: CharMeasure
|
||||
) {
|
||||
// Measure the width of the scrollbar. If it is 0 we can assume it's an OSX overlay scrollbar.
|
||||
// Unfortunately the overlay scrollbar would be hidden underneath the screen element in that case,
|
||||
// therefore we account for a standard amount to make it visible
|
||||
this.scrollBarWidth = (this.viewportElement.offsetWidth - this.scrollArea.offsetWidth) || FALLBACK_SCROLL_BAR_WIDTH;
|
||||
this.viewportElement.addEventListener('scroll', this.onScroll.bind(this));
|
||||
|
||||
// Perform this async to ensure the CharMeasure is ready.
|
||||
@@ -48,13 +55,8 @@ export class Viewport implements IViewport {
|
||||
private refresh(): void {
|
||||
if (this.charMeasure.height > 0) {
|
||||
this.currentRowHeight = this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio;
|
||||
|
||||
if (this.lastRecordedViewportHeight !== this.terminal.renderer.dimensions.canvasHeight) {
|
||||
this.lastRecordedViewportHeight = this.terminal.renderer.dimensions.canvasHeight;
|
||||
this.viewportElement.style.height = this.lastRecordedViewportHeight + 'px';
|
||||
}
|
||||
|
||||
const newBufferHeight = Math.round(this.currentRowHeight * this.lastRecordedBufferLength);
|
||||
this.lastRecordedViewportHeight = this.viewportElement.offsetHeight;
|
||||
const newBufferHeight = Math.round(this.currentRowHeight * this.lastRecordedBufferLength) + (this.lastRecordedViewportHeight - this.terminal.renderer.dimensions.canvasHeight);
|
||||
if (this.lastRecordedBufferHeight !== newBufferHeight) {
|
||||
this.lastRecordedBufferHeight = newBufferHeight;
|
||||
this.scrollArea.style.height = this.lastRecordedBufferHeight + 'px';
|
||||
|
||||
+10
-5
@@ -28,17 +28,22 @@ export function proposeGeometry(term: Terminal): IGeometry {
|
||||
}
|
||||
const parentElementStyle = window.getComputedStyle(term.element.parentElement);
|
||||
const parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height'));
|
||||
const parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17);
|
||||
const parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')));
|
||||
const elementStyle = window.getComputedStyle(term.element);
|
||||
const elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom'));
|
||||
const elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left'));
|
||||
const elementPadding = {
|
||||
top: parseInt(elementStyle.getPropertyValue('padding-top')),
|
||||
bottom: parseInt(elementStyle.getPropertyValue('padding-bottom')),
|
||||
right: parseInt(elementStyle.getPropertyValue('padding-right')),
|
||||
left: parseInt(elementStyle.getPropertyValue('padding-left'))
|
||||
};
|
||||
const elementPaddingVer = elementPadding.top + elementPadding.bottom;
|
||||
const elementPaddingHor = elementPadding.right + elementPadding.left;
|
||||
const availableHeight = parentElementHeight - elementPaddingVer;
|
||||
const availableWidth = parentElementWidth - elementPaddingHor;
|
||||
const availableWidth = parentElementWidth - elementPaddingHor - (<any>term).viewport.scrollBarWidth;
|
||||
const geometry = {
|
||||
cols: Math.floor(availableWidth / (<any>term).renderer.dimensions.actualCellWidth),
|
||||
rows: Math.floor(availableHeight / (<any>term).renderer.dimensions.actualCellHeight)
|
||||
};
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ export class MouseZoneManager implements IMouseZoneManager {
|
||||
}
|
||||
|
||||
private _findZoneEventAt(e: MouseEvent): IMouseZone {
|
||||
const coords = this._terminal.mouseHelper.getCoords(e, this._terminal.element, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows);
|
||||
const coords = this._terminal.mouseHelper.getCoords(e, this._terminal.screenElement, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows);
|
||||
if (!coords) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ export class Renderer extends EventEmitter implements IRenderer {
|
||||
}
|
||||
|
||||
this._renderLayers = [
|
||||
new TextRenderLayer(this._terminal.element, 0, this.colorManager.colors, this._terminal.options.allowTransparency),
|
||||
new SelectionRenderLayer(this._terminal.element, 1, this.colorManager.colors),
|
||||
new LinkRenderLayer(this._terminal.element, 2, this.colorManager.colors, this._terminal),
|
||||
new CursorRenderLayer(this._terminal.element, 3, this.colorManager.colors)
|
||||
new TextRenderLayer(this._terminal.screenElement, 0, this.colorManager.colors, this._terminal.options.allowTransparency),
|
||||
new SelectionRenderLayer(this._terminal.screenElement, 1, this.colorManager.colors),
|
||||
new LinkRenderLayer(this._terminal.screenElement, 2, this.colorManager.colors, this._terminal),
|
||||
new CursorRenderLayer(this._terminal.screenElement, 3, this.colorManager.colors)
|
||||
];
|
||||
this.dimensions = {
|
||||
scaledCharWidth: null,
|
||||
@@ -120,6 +120,10 @@ export class Renderer extends EventEmitter implements IRenderer {
|
||||
this._terminal.refresh(0, this._terminal.rows - 1);
|
||||
}
|
||||
|
||||
// Resize the screen
|
||||
this._terminal.screenElement.style.width = `${this.dimensions.canvasWidth + this._terminal.viewport.scrollBarWidth}px`;
|
||||
this._terminal.screenElement.style.height = `${this.dimensions.canvasHeight}px`;
|
||||
|
||||
this.emit('resize', {
|
||||
width: this.dimensions.canvasWidth,
|
||||
height: this.dimensions.canvasHeight
|
||||
|
||||
@@ -80,6 +80,7 @@ export class MockTerminal implements ITerminal {
|
||||
isFocused: boolean;
|
||||
options: ITerminalOptions = {};
|
||||
element: HTMLElement;
|
||||
screenElement: HTMLElement;
|
||||
rowContainer: HTMLElement;
|
||||
selectionContainer: HTMLElement;
|
||||
selectionManager: ISelectionManager;
|
||||
@@ -96,6 +97,7 @@ export class MockTerminal implements ITerminal {
|
||||
scrollback: number;
|
||||
buffers: IBufferSet;
|
||||
buffer: IBuffer;
|
||||
viewport: IViewport;
|
||||
applicationCursor: boolean;
|
||||
handler(data: string): void {
|
||||
throw new Error('Method not implemented.');
|
||||
@@ -308,6 +310,7 @@ export class MockRenderer implements IRenderer {
|
||||
}
|
||||
|
||||
export class MockViewport implements IViewport {
|
||||
scrollBarWidth: number = 0;
|
||||
onThemeChanged(colors: IColorSet): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
+10
-1
@@ -96,9 +96,18 @@
|
||||
background-color: #000;
|
||||
overflow-y: scroll;
|
||||
cursor: default;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.xterm canvas {
|
||||
.xterm .xterm-screen {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.xterm .xterm-screen canvas {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
Reference in New Issue
Block a user