mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Fix buffer decoration onRender, start using internal decoration
This commit is contained in:
+1
-1
@@ -548,7 +548,7 @@ function addDecoration() {
|
||||
const marker = term.addMarker(1);
|
||||
const decoration = term.registerDecoration({ marker });
|
||||
decoration.onRender((e) => {
|
||||
console.log(e);
|
||||
console.log('onRender', e);
|
||||
e.style.backgroundColor = 'red';
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,19 +4,20 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { addDisposableDomListener } from 'browser/Lifecycle';
|
||||
import { IDecorationService, IRenderService } from 'browser/services/Services';
|
||||
import { IRenderService } from 'browser/services/Services';
|
||||
import { IEvent, EventEmitter } from 'common/EventEmitter';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { IBufferService } from 'common/services/Services';
|
||||
import { IBufferService, IDecorationService, IInternalDecoration } from 'common/services/Services';
|
||||
import { IMarker } from 'common/Types';
|
||||
import { IDecoration, IDecorationOptions } from 'xterm';
|
||||
|
||||
export interface IDecorationRenderer {
|
||||
refreshDecorations(shouldRecreate?: boolean): void;
|
||||
renderDecoration(decoration: IDecoration, decorationOptions: IDecorationOptions): void;
|
||||
renderDecoration(decoration: IInternalDecoration, decorationOptions: IDecorationOptions): void;
|
||||
}
|
||||
|
||||
export class BufferDecorationRenderer extends Disposable implements IDecorationRenderer {
|
||||
private _animationFrame: number | undefined;
|
||||
private _decorationContainer: HTMLElement;
|
||||
private readonly _decorations: BufferDecoration[] = [];
|
||||
private _altBufferIsActive: boolean = false;
|
||||
@@ -30,32 +31,40 @@ export class BufferDecorationRenderer extends Disposable implements IDecorationR
|
||||
this._decorationContainer = document.createElement('div');
|
||||
this._decorationContainer.classList.add('xterm-decoration-container');
|
||||
this._screenElement.appendChild(this._decorationContainer);
|
||||
this.register(this._renderService.onRenderedBufferChange(() => this.refreshDecorations()));
|
||||
this.register(this._renderService.onDimensionsChange(() => this.refreshDecorations()));
|
||||
this.register(addDisposableDomListener(window, 'resize', () => this.refreshDecorations()));
|
||||
this.register(this._renderService.onRenderedBufferChange(() => this._queueRefresh()));
|
||||
this.register(this._renderService.onDimensionsChange(() => this._queueRefresh()));
|
||||
this.register(addDisposableDomListener(window, 'resize', () => this._queueRefresh()));
|
||||
this.register(this._bufferService.buffers.onBufferActivate(() => {
|
||||
this._altBufferIsActive = this._bufferService.buffer === this._bufferService.buffers.alt;
|
||||
}));
|
||||
this.register(this._decorationService.onDecorationRegistered(options => this.renderDecoration(options)));
|
||||
}
|
||||
public refreshDecorations(shouldRecreate?: boolean): void {
|
||||
if (!this._renderService) {
|
||||
|
||||
private _queueRefresh(): void {
|
||||
if (this._animationFrame !== undefined) {
|
||||
return;
|
||||
}
|
||||
this._animationFrame = window.requestAnimationFrame(() => {
|
||||
this.refreshDecorations();
|
||||
this._animationFrame = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
public refreshDecorations(shouldRecreate?: boolean): void {
|
||||
console.log('refresh decorations', this._decorations.length);
|
||||
for (const decoration of this._decorations) {
|
||||
decoration.render(this._decorationContainer, this._renderService, shouldRecreate);
|
||||
}
|
||||
}
|
||||
|
||||
public renderDecoration(decorationOptions: IDecorationOptions): void {
|
||||
if (decorationOptions.overviewRulerItemColor) {
|
||||
return;
|
||||
}
|
||||
const decoration = new BufferDecoration(this._bufferService, decorationOptions);
|
||||
(decoration as BufferDecoration).render(this._decorationContainer, this._renderService, true);
|
||||
if (this._decorationContainer && decoration.element && !this._decorationContainer.contains(decoration.element)) {
|
||||
this._decorationContainer.append(decoration.element!);
|
||||
public renderDecoration(decoration: IInternalDecoration): void {
|
||||
const bufferDecoration = new BufferDecoration(this._bufferService, decoration, decoration.options);
|
||||
this._decorations.push(bufferDecoration);
|
||||
// bufferDecoration.render(this._decorationContainer, this._renderService, true);
|
||||
if (this._decorationContainer && bufferDecoration.element && !this._decorationContainer.contains(bufferDecoration.element)) {
|
||||
this._decorationContainer.append(bufferDecoration.element!);
|
||||
}
|
||||
this._queueRefresh();
|
||||
}
|
||||
|
||||
public override dispose(): void {
|
||||
@@ -68,6 +77,7 @@ export class BufferDecorationRenderer extends Disposable implements IDecorationR
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class BufferDecoration extends Disposable implements IDecoration {
|
||||
private readonly _marker: IMarker;
|
||||
private _element: HTMLElement | undefined;
|
||||
@@ -85,7 +95,6 @@ export class BufferDecoration extends Disposable implements IDecoration {
|
||||
private _onRender = new EventEmitter<HTMLElement>();
|
||||
public get onRender(): IEvent<HTMLElement> { return this._onRender.event; }
|
||||
|
||||
|
||||
public x: number;
|
||||
public anchor: 'left' | 'right';
|
||||
public width: number;
|
||||
@@ -93,6 +102,7 @@ export class BufferDecoration extends Disposable implements IDecoration {
|
||||
|
||||
constructor(
|
||||
private readonly _bufferService: IBufferService,
|
||||
private readonly _internalDecoration: IInternalDecoration,
|
||||
options: IDecorationOptions
|
||||
) {
|
||||
super();
|
||||
@@ -107,16 +117,18 @@ export class BufferDecoration extends Disposable implements IDecoration {
|
||||
public render(container: HTMLElement, renderService: IRenderService, shouldRecreate?: boolean): void {
|
||||
this._container = container;
|
||||
if (!this._element || shouldRecreate) {
|
||||
this._createElement(renderService, shouldRecreate);
|
||||
const element = this._createElement(renderService, shouldRecreate);
|
||||
this._container.appendChild(element);
|
||||
}
|
||||
this._refreshStyle(renderService);
|
||||
if (this._element) {
|
||||
console.log('firing on render');
|
||||
this._onRender.fire(this._element);
|
||||
this._internalDecoration.onRenderEmitter.fire(this._element!);
|
||||
}
|
||||
}
|
||||
|
||||
private _createElement(renderService: IRenderService, shouldRecreate?: boolean): void {
|
||||
private _createElement(renderService: IRenderService, shouldRecreate?: boolean): HTMLElement {
|
||||
if (shouldRecreate && this._element && this._container && this._container.contains(this._element)) {
|
||||
this._container.removeChild(this._element);
|
||||
}
|
||||
@@ -136,6 +148,8 @@ export class BufferDecoration extends Disposable implements IDecoration {
|
||||
} else {
|
||||
this._element.style.left = this.x ? `${this.x * renderService.dimensions.actualCellWidth}px` : '';
|
||||
}
|
||||
|
||||
return this._element;
|
||||
}
|
||||
|
||||
private _refreshStyle(renderService: IRenderService): void {
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
import { addDisposableDomListener } from 'browser/Lifecycle';
|
||||
import { IDecorationRenderer } from 'browser/Decorations/BufferDecorationRenderer';
|
||||
import { IDecorationService, IRenderService } from 'browser/services/Services';
|
||||
import { IRenderService } from 'browser/services/Services';
|
||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { IBufferService, IInstantiationService } from 'common/services/Services';
|
||||
import { IBufferService, IDecorationService, IInstantiationService, IInternalDecoration } from 'common/services/Services';
|
||||
import { IDecorationOptions, IDecoration, IMarker } from 'xterm';
|
||||
const enum ScrollbarConstants {
|
||||
WIDTH = 7
|
||||
@@ -45,14 +45,16 @@ export class OverviewRulerRenderer extends Disposable implements IDecorationRend
|
||||
this.register(this._decorationService.onDecorationRegistered(e => this.renderDecoration(e)));
|
||||
this.register(this._decorationService.onDecorationRemoved(d => d.dispose()));
|
||||
}
|
||||
public renderDecoration(decorationOptions: IDecorationOptions): void {
|
||||
if (!this._ctx || !decorationOptions.overviewRulerItemColor) {
|
||||
public renderDecoration(decoration: IInternalDecoration): void {
|
||||
if (!this._ctx || !decoration.options.overviewRulerItemColor) {
|
||||
return;
|
||||
}
|
||||
const decoration = this._instantiationService.createInstance(ScrollbarDecoration, { marker: decorationOptions.marker, overviewRulerItemColor: decorationOptions.overviewRulerItemColor });
|
||||
|
||||
// TODO: Does this do anything anymore?
|
||||
this._instantiationService.createInstance(ScrollbarDecoration, { marker: decoration.options.marker, overviewRulerItemColor: decoration.options.overviewRulerItemColor });
|
||||
|
||||
this._ctx.lineWidth = 1;
|
||||
this._ctx.strokeStyle = decorationOptions.overviewRulerItemColor;
|
||||
this._ctx.strokeStyle = decoration.options.overviewRulerItemColor;
|
||||
this._ctx.strokeRect(
|
||||
0,
|
||||
Math.round(this._canvas.height * (decoration.marker.line / this._bufferService.buffers.active.lines.length)),
|
||||
|
||||
@@ -83,11 +83,14 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
|
||||
private _customKeyEventHandler: CustomKeyEventHandler | undefined;
|
||||
|
||||
// TODO: Move into CoreTerminal.ts
|
||||
// common services
|
||||
private _decorationService: DecorationService;
|
||||
|
||||
// browser services
|
||||
private _charSizeService: ICharSizeService | undefined;
|
||||
private _mouseService: IMouseService | undefined;
|
||||
private _renderService: IRenderService | undefined;
|
||||
private _decorationService: DecorationService | undefined;
|
||||
private _characterJoinerService: ICharacterJoinerService | undefined;
|
||||
private _selectionService: ISelectionService | undefined;
|
||||
private _soundService: ISoundService | undefined;
|
||||
|
||||
Vendored
-5
@@ -206,11 +206,6 @@ export interface ILinkifier {
|
||||
registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number;
|
||||
deregisterLinkMatcher(matcherId: number): boolean;
|
||||
}
|
||||
export interface IDecorationService extends IDisposable {
|
||||
readonly onDecorationRegistered: IEvent<IDecorationOptions>;
|
||||
readonly onDecorationRemoved: IEvent<IDecoration>;
|
||||
registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined;
|
||||
}
|
||||
|
||||
interface ILinkState {
|
||||
decorations: ILinkDecorations;
|
||||
|
||||
@@ -115,9 +115,3 @@ export interface ICharacterJoinerService {
|
||||
deregister(joinerId: number): boolean;
|
||||
getJoinedCharacters(row: number): [number, number][];
|
||||
}
|
||||
export const IDecorationService = createDecorator<IDecorationService>('DecorationService');
|
||||
export interface IDecorationService extends IDisposable {
|
||||
readonly onDecorationRegistered: IEvent<IDecorationOptions>;
|
||||
readonly onDecorationRemoved: IEvent<IDecoration>;
|
||||
registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined;
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
|
||||
import { EventEmitter } from 'common/EventEmitter';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { IDecorationService } from 'common/services/Services';
|
||||
import { IDecorationService, IInternalDecoration } from 'common/services/Services';
|
||||
import { IDecorationOptions, IDecoration, IMarker, IEvent } from 'xterm';
|
||||
|
||||
export class DecorationService extends Disposable implements IDecorationService {
|
||||
private _animationFrame: number | undefined;
|
||||
private _onDecorationRegistered = this.register(new EventEmitter<IDecorationOptions>());
|
||||
public get onDecorationRegistered(): IEvent<IDecorationOptions> { return this._onDecorationRegistered.event; }
|
||||
private _onDecorationRemoved = this.register(new EventEmitter<IDecoration>());
|
||||
public get onDecorationRemoved(): IEvent<IDecoration> { return this._onDecorationRemoved.event; }
|
||||
private _decorations: IDecoration[] = [];
|
||||
private _onDecorationRegistered = this.register(new EventEmitter<IInternalDecoration>());
|
||||
public get onDecorationRegistered(): IEvent<IInternalDecoration> { return this._onDecorationRegistered.event; }
|
||||
private _onDecorationRemoved = this.register(new EventEmitter<IInternalDecoration>());
|
||||
public get onDecorationRemoved(): IEvent<IInternalDecoration> { return this._onDecorationRemoved.event; }
|
||||
private _decorations: IInternalDecoration[] = [];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -33,7 +33,7 @@ export class DecorationService extends Disposable implements IDecorationService
|
||||
}
|
||||
});
|
||||
this._decorations.push(decoration);
|
||||
this._onDecorationRegistered.fire(options);
|
||||
this._onDecorationRegistered.fire(decoration);
|
||||
}
|
||||
return decoration;
|
||||
}
|
||||
@@ -57,19 +57,21 @@ export class DecorationService extends Disposable implements IDecorationService
|
||||
}
|
||||
}
|
||||
|
||||
class Decoration implements IDecoration {
|
||||
class Decoration implements IInternalDecoration {
|
||||
public marker: IMarker;
|
||||
private _onRender = new EventEmitter<HTMLElement>();
|
||||
public get onRender(): IEvent<HTMLElement> { return this._onRender.event; }
|
||||
public readonly onRenderEmitter = new EventEmitter<HTMLElement>();
|
||||
public readonly onRender = this.onRenderEmitter.event;
|
||||
private _onDispose = new EventEmitter<void>();
|
||||
public get onDispose(): IEvent<void> { return this._onDispose.event; }
|
||||
public readonly onDispose = this._onDispose.event;
|
||||
public element: HTMLElement | undefined;
|
||||
public isDisposed: boolean = false;
|
||||
public dispose(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
constructor(decorationOptions: IDecorationOptions) {
|
||||
this.marker = decorationOptions?.marker;
|
||||
constructor(
|
||||
public readonly options: IDecorationOptions
|
||||
) {
|
||||
this.marker = options.marker;
|
||||
this.element = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IEvent } from 'common/EventEmitter';
|
||||
import { IEvent, IEventEmitter } from 'common/EventEmitter';
|
||||
import { IBuffer, IBufferSet } from 'common/buffer/Types';
|
||||
import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType, ICharset, IWindowOptions, IModes, IAttributeData, ScrollSource, IDisposable } from 'common/Types';
|
||||
import { createDecorator } from 'common/services/ServiceRegistry';
|
||||
@@ -300,8 +300,14 @@ export interface IUnicodeVersionProvider {
|
||||
readonly version: string;
|
||||
wcwidth(ucs: number): 0 | 1 | 2;
|
||||
}
|
||||
|
||||
export const IDecorationService = createDecorator<IDecorationService>('DecorationService');
|
||||
export interface IDecorationService extends IDisposable {
|
||||
readonly onDecorationRegistered: IEvent<IDecorationOptions>;
|
||||
readonly onDecorationRemoved: IEvent<IDecoration>;
|
||||
readonly onDecorationRegistered: IEvent<IInternalDecoration>;
|
||||
readonly onDecorationRemoved: IEvent<IInternalDecoration>;
|
||||
registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined;
|
||||
}
|
||||
export interface IInternalDecoration extends IDecoration {
|
||||
readonly options: IDecorationOptions;
|
||||
readonly onRenderEmitter: IEventEmitter<HTMLElement>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user