diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index f0ce4694..71998bd5 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -920,7 +920,7 @@ export class Terminal extends CoreTerminal implements ITerminal { return this.buffer.markers; } - public addMarker(cursorYOffset: number): IMarker { + public registerMarker(cursorYOffset: number): IMarker { return this.buffer.addMarker(this.buffer.ybase + this.buffer.y + cursorYOffset); } diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 5981a6b5..7b464a33 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -52,7 +52,7 @@ export class MockTerminal implements ITerminal { public coreService!: ICoreService; public optionsService!: IOptionsService; public unicodeService!: IUnicodeService; - public addMarker(cursorYOffset: number): IMarker { + public registerMarker(cursorYOffset: number): IMarker { throw new Error('Method not implemented.'); } public selectLines(start: number, end: number): void { diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index d32b6099..776790cd 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -3,15 +3,19 @@ * @license MIT */ -import { IDecorationOptions, IDecoration, IDisposable, IMarker } from 'xterm'; +import { IDecorationOptions, IDecoration, IDisposable, IMarker, Terminal as ITerminalApi } from 'xterm'; import { IEvent } from 'common/EventEmitter'; import { ICoreTerminal, CharData, ITerminalOptions, IColor } from 'common/Types'; import { IMouseService, IRenderService } from './services/Services'; import { IBuffer } from 'common/buffer/Types'; import { IFunctionIdentifier, IParams } from 'common/parser/Types'; -export interface ITerminal extends IPublicTerminal, ICoreTerminal { - element: HTMLElement | undefined; +/** + * A portion of the public API that are implemented identially internally and simply passed through. + */ +type InternalPassthroughApis = Omit; + +export interface ITerminal extends InternalPassthroughApis, ICoreTerminal { screenElement: HTMLElement | undefined; browser: IBrowser; buffer: IBuffer; @@ -28,78 +32,6 @@ export interface ITerminal extends IPublicTerminal, ICoreTerminal { cancel(ev: Event, force?: boolean): boolean | void; } -// Portions of the public API that are required by the internal Terminal -export interface IPublicTerminal extends IDisposable { - textarea: HTMLTextAreaElement | undefined; - rows: number; - cols: number; - buffer: IBuffer; - markers: IMarker[]; - onCursorMove: IEvent; - onData: IEvent; - onBinary: IEvent; - onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>; - onLineFeed: IEvent; - onScroll: IEvent; - onSelectionChange: IEvent; - onRender: IEvent<{ start: number, end: number }>; - onResize: IEvent<{ cols: number, rows: number }>; - onWriteParsed: IEvent; - onTitleChange: IEvent; - onBell: IEvent; - blur(): void; - focus(): void; - resize(columns: number, rows: number): void; - open(parent: HTMLElement): void; - attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void; - registerCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean | Promise): IDisposable; - registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise): IDisposable; - registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise): IDisposable; - registerOscHandler(ident: number, callback: (data: string) => boolean | Promise): IDisposable; - registerLinkProvider(linkProvider: ILinkProvider): IDisposable; - registerCharacterJoiner(handler: (text: string) => [number, number][]): number; - deregisterCharacterJoiner(joinerId: number): void; - addMarker(cursorYOffset: number): IMarker; - registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined; - hasSelection(): boolean; - getSelection(): string; - getSelectionPosition(): IBufferRange | undefined; - clearSelection(): void; - select(column: number, row: number, length: number): void; - selectAll(): void; - selectLines(start: number, end: number): void; - dispose(): void; - /** - * Scroll the display of the terminal - * @param amount The number of lines to scroll down (negative scroll up). - */ - scrollLines(amount: number): void; - /** - * Scroll the display of the terminal by a number of pages. - * @param pageCount The number of pages to scroll (negative scrolls up). - */ - scrollPages(pageCount: number): void; - /** - * Scrolls the display of the terminal to the top. - */ - scrollToTop(): void; - /** - * Scrolls the display of the terminal to the bottom. - */ - scrollToBottom(): void; - /** - * Scrolls to a line within the buffer. - * @param line The 0-based line index to scroll to. - */ - scrollToLine(line: number): void; - clear(): void; - write(data: string | Uint8Array, callback?: () => void): void; - paste(data: string): void; - refresh(start: number, end: number): void; - clearTextureAtlas(): void; - reset(): void; -} - export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; export type LineData = CharData[]; diff --git a/src/browser/public/Terminal.ts b/src/browser/public/Terminal.ts index 7a94356b..77f8fdde 100644 --- a/src/browser/public/Terminal.ts +++ b/src/browser/public/Terminal.ts @@ -161,7 +161,7 @@ export class Terminal extends Disposable implements ITerminalApi { } public registerMarker(cursorYOffset: number = 0): IMarker { this._verifyIntegers(cursorYOffset); - return this._core.addMarker(cursorYOffset); + return this._core.registerMarker(cursorYOffset); } public registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined { this._checkProposedApi(); diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index 1449aee6..8126de6e 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -14,7 +14,6 @@ import { color } from 'common/Color'; import { EventEmitter } from 'common/EventEmitter'; import { Disposable, toDisposable } from 'common/Lifecycle'; import { IBufferService, IInstantiationService, IOptionsService } from 'common/services/Services'; -import { createStyle, IStyleSheet } from './StyleSheet'; const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-'; @@ -36,8 +35,8 @@ export class DomRenderer extends Disposable implements IRenderer { private _rowFactory: DomRendererRowFactory; private _terminalClass: number = nextTerminalId++; - private _themeStyle!: IStyleSheet; - private _dimensionsStyle!: IStyleSheet; + private _themeStyleElement!: HTMLStyleElement; + private _dimensionsStyleElement!: HTMLStyleElement; private _rowContainer: HTMLElement; private _rowElements: HTMLElement[] = []; private _selectionContainer: HTMLElement; @@ -92,9 +91,9 @@ export class DomRenderer extends Disposable implements IRenderer { // https://github.com/xtermjs/xterm.js/issues/2960 this._rowContainer.remove(); this._selectionContainer.remove(); - this._themeStyle.dispose(); - this._dimensionsStyle.dispose(); this._widthCache.dispose(); + this._themeStyleElement.remove(); + this._dimensionsStyleElement.remove(); })); this._widthCache = new WidthCache(document); @@ -130,8 +129,9 @@ export class DomRenderer extends Disposable implements IRenderer { element.style.overflow = 'hidden'; } - if (!this._dimensionsStyle) { - this._dimensionsStyle = createStyle(this._screenElement); + if (!this._dimensionsStyleElement) { + this._dimensionsStyleElement = document.createElement('style'); + this._screenElement.appendChild(this._dimensionsStyleElement); } const styles = @@ -141,7 +141,7 @@ export class DomRenderer extends Disposable implements IRenderer { ` vertical-align: top;` + `}`; - this._dimensionsStyle.setCss(styles); + this._dimensionsStyleElement.textContent = styles; this._selectionContainer.style.height = this._viewportElement.style.height; this._screenElement.style.width = `${this.dimensions.css.canvas.width}px`; @@ -149,8 +149,9 @@ export class DomRenderer extends Disposable implements IRenderer { } private _injectCss(colors: ReadonlyColorSet): void { - if (!this._themeStyle) { - this._themeStyle = createStyle(this._screenElement); + if (!this._themeStyleElement) { + this._themeStyleElement = document.createElement('style'); + this._screenElement.appendChild(this._themeStyleElement); } // Base CSS @@ -248,7 +249,7 @@ export class DomRenderer extends Disposable implements IRenderer { `${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(color.opaque(colors.background), 0.5).css}; }` + `${this._terminalSelector} .${BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${colors.foreground.css}; }`; - this._themeStyle.setCss(styles); + this._themeStyleElement.textContent = styles; } /** diff --git a/src/browser/renderer/dom/StyleSheet.ts b/src/browser/renderer/dom/StyleSheet.ts deleted file mode 100644 index 574615f4..00000000 --- a/src/browser/renderer/dom/StyleSheet.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2023 The xterm.js authors. All rights reserved. - * @license MIT - */ - -export interface IStyleSheet { - dispose: () => void; - setCss: (value: string) => void; -} - -const createCssStyleSheet = (doc: Document): IStyleSheet => { - const sheet = new CSSStyleSheet(); - doc.adoptedStyleSheets.push(sheet); - return { - dispose() { - const index = doc.adoptedStyleSheets.indexOf(sheet); - doc.adoptedStyleSheets.splice(index, 1); - }, - setCss(css) { - sheet.replaceSync(css); - } - }; -}; - -const createStyleElement = (parent: HTMLElement): IStyleSheet => { - const doc = parent.ownerDocument; - const element = doc.createElement('style'); - parent.append(element); - return { - dispose() { - element.remove(); - }, - setCss(css) { - element.textContent = css; - } - }; -}; - -export const createStyle = (parent: HTMLElement): IStyleSheet => { - try { - return createCssStyleSheet(parent.ownerDocument); - } catch { - return createStyleElement(parent); - } -}; diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 3870fa56..b05ceeaf 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -17,7 +17,7 @@ export interface ICoreTerminal { optionsService: IOptionsService; unicodeService: IUnicodeService; buffers: IBufferSet; - options: ITerminalOptions; + options: Required; registerCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean | Promise): IDisposable; registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise): IDisposable; registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise): IDisposable; diff --git a/src/headless/Terminal.ts b/src/headless/Terminal.ts index 2c244f21..73bcbe13 100644 --- a/src/headless/Terminal.ts +++ b/src/headless/Terminal.ts @@ -24,7 +24,7 @@ import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { IBuffer } from 'common/buffer/Types'; import { CoreTerminal } from 'common/CoreTerminal'; -import { EventEmitter, forwardEvent, IEvent } from 'common/EventEmitter'; +import { EventEmitter, forwardEvent } from 'common/EventEmitter'; import { ITerminalOptions as IInitializedTerminalOptions } from 'common/services/Services'; import { IMarker, ITerminalOptions, ScrollSource } from 'common/Types'; diff --git a/src/headless/Types.d.ts b/src/headless/Types.d.ts deleted file mode 100644 index 868e5c17..00000000 --- a/src/headless/Types.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { IBuffer, IBufferSet } from 'common/buffer/Types'; -import { IEvent } from 'common/EventEmitter'; -import { IFunctionIdentifier, IParams } from 'common/parser/Types'; -import { ICoreTerminal, IDisposable, IMarker, ITerminalOptions } from 'common/Types'; - -export interface ITerminal extends ICoreTerminal { - rows: number; - cols: number; - buffer: IBuffer; - buffers: IBufferSet; - markers: IMarker[]; - // TODO: We should remove options once components adopt optionsService - options: ITerminalOptions; - - onCursorMove: IEvent; - onData: IEvent; - onBinary: IEvent; - onLineFeed: IEvent; - onResize: IEvent<{ cols: number, rows: number }>; - onTitleChange: IEvent; - resize(columns: number, rows: number): void; - addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable; - addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable; - addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable; - addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable; - addMarker(cursorYOffset: number): IMarker | undefined; - dispose(): void; - clear(): void; - write(data: string | Uint8Array, callback?: () => void): void; - reset(): void; -}