+25
-23
@@ -39,9 +39,8 @@ import { KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseActio
|
||||
import { evaluateKeyboardEvent } from 'common/input/Keyboard';
|
||||
import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
|
||||
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
||||
import { ColorManager } from 'browser/ColorManager';
|
||||
import { RenderService } from 'browser/services/RenderService';
|
||||
import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ICoreBrowserService, ICharacterJoinerService } from 'browser/services/Services';
|
||||
import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ICoreBrowserService, ICharacterJoinerService, IThemeService } from 'browser/services/Services';
|
||||
import { CharSizeService } from 'browser/services/CharSizeService';
|
||||
import { IBuffer } from 'common/buffer/Types';
|
||||
import { MouseService } from 'browser/services/MouseService';
|
||||
@@ -57,6 +56,7 @@ import { DecorationService } from 'common/services/DecorationService';
|
||||
import { IDecorationService } from 'common/services/Services';
|
||||
import { OscLinkProvider } from 'browser/OscLinkProvider';
|
||||
import { toDisposable } from 'common/Lifecycle';
|
||||
import { ThemeService } from 'browser/services/ThemeService';
|
||||
|
||||
// Let it work inside Node.js for automated testing purposes.
|
||||
const document: Document = (typeof window !== 'undefined') ? window.document : null as any;
|
||||
@@ -86,6 +86,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
private _coreBrowserService: ICoreBrowserService | undefined;
|
||||
private _mouseService: IMouseService | undefined;
|
||||
private _renderService: IRenderService | undefined;
|
||||
private _themeService: IThemeService | undefined;
|
||||
private _characterJoinerService: ICharacterJoinerService | undefined;
|
||||
private _selectionService: ISelectionService | undefined;
|
||||
|
||||
@@ -120,8 +121,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
public viewport: IViewport | undefined;
|
||||
private _compositionHelper: ICompositionHelper | undefined;
|
||||
private _accessibilityManager: AccessibilityManager | undefined;
|
||||
private _colorManager: ColorManager | undefined;
|
||||
private _theme: ITheme | undefined;
|
||||
|
||||
private readonly _onCursorMove = this.register(new EventEmitter<void>());
|
||||
public readonly onCursorMove = this._onCursorMove.event;
|
||||
@@ -199,9 +198,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
* while an event from OSC 10|110 | 11|111 | 12|112 always contains a single request.
|
||||
*/
|
||||
private _handleColorEvent(event: IColorEvent): void {
|
||||
if (!this._colorManager) return;
|
||||
if (!this._themeService) return;
|
||||
for (const req of event) {
|
||||
let acc: 'foreground' | 'background' | 'cursor' | 'ansi' | undefined = undefined;
|
||||
let acc: 'foreground' | 'background' | 'cursor' | 'ansi';
|
||||
let ident = '';
|
||||
switch (req.index) {
|
||||
case ColorIndex.FOREGROUND: // OSC 10 | 110
|
||||
@@ -224,21 +223,26 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
switch (req.type) {
|
||||
case ColorRequestType.REPORT:
|
||||
const channels = color.toColorRGB(acc === 'ansi'
|
||||
? this._colorManager.colors.ansi[req.index]
|
||||
: this._colorManager.colors[acc]);
|
||||
? this._themeService.colors.ansi[req.index]
|
||||
: this._themeService.colors[acc]);
|
||||
this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(channels)}${C1_ESCAPED.ST}`);
|
||||
break;
|
||||
case ColorRequestType.SET:
|
||||
if (acc === 'ansi') this._colorManager.colors.ansi[req.index] = rgba.toColor(...req.color);
|
||||
else this._colorManager.colors[acc] = rgba.toColor(...req.color);
|
||||
if (acc === 'ansi') {
|
||||
this._themeService.modifyColors(colors => colors.ansi[req.index] = rgba.toColor(...req.color));
|
||||
} else {
|
||||
const narrowedAcc = acc;
|
||||
this._themeService.modifyColors(colors => colors[narrowedAcc] = rgba.toColor(...req.color));
|
||||
}
|
||||
break;
|
||||
case ColorRequestType.RESTORE:
|
||||
this._colorManager.restoreColor(req.index);
|
||||
this._themeService.restoreColor(req.index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._renderService?.setColors(this._colorManager.colors);
|
||||
this.viewport?.handleThemeChange(this._colorManager.colors);
|
||||
// TODO: Have these listen to theme change
|
||||
this._renderService?.setColors(this._themeService.colors);
|
||||
this.viewport?.handleThemeChange(this._themeService.colors);
|
||||
}
|
||||
|
||||
protected _setup(): void {
|
||||
@@ -498,10 +502,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
this._charSizeService = this._instantiationService.createInstance(CharSizeService, this._document, this._helperContainer);
|
||||
this._instantiationService.setService(ICharSizeService, this._charSizeService);
|
||||
|
||||
this._theme = this.options.theme || this._theme;
|
||||
this._colorManager = new ColorManager();
|
||||
this.register(this.optionsService.onOptionChange(e => this._colorManager!.handleOptionsChange(e, this.optionsService.rawOptions[e])));
|
||||
this._colorManager.setTheme(this._theme);
|
||||
this._themeService = this._instantiationService.createInstance(ThemeService);
|
||||
this._instantiationService.setService(IThemeService, this._themeService);
|
||||
|
||||
this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
|
||||
this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
|
||||
@@ -533,7 +535,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
this._viewportScrollArea,
|
||||
this.element
|
||||
);
|
||||
this.viewport.handleThemeChange(this._colorManager.colors);
|
||||
// TODO: Listen to theme service event
|
||||
this.viewport.handleThemeChange(this._themeService.colors);
|
||||
this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea()));
|
||||
this.register(this.viewport);
|
||||
|
||||
@@ -610,7 +613,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
}
|
||||
|
||||
private _createRenderer(): IRenderer {
|
||||
return this._instantiationService.createInstance(DomRenderer, this._colorManager!.colors, this.element!, this.screenElement!, this._viewportElement!, this.linkifier2);
|
||||
// TODO: Listen to theme service
|
||||
return this._instantiationService.createInstance(DomRenderer, this._themeService!.colors, this.element!, this.screenElement!, this._viewportElement!, this.linkifier2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -618,10 +622,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
* @param theme The theme to set.
|
||||
*/
|
||||
private _setTheme(theme: ITheme): void {
|
||||
this._theme = theme;
|
||||
this._colorManager?.setTheme(theme);
|
||||
this._renderService?.setColors(this._colorManager!.colors);
|
||||
this.viewport?.handleThemeChange(this._colorManager!.colors);
|
||||
// TODO: Listen to theme service events
|
||||
this.viewport?.handleThemeChange(this._themeService!.colors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+3
-1
@@ -126,6 +126,8 @@ export interface IColorSet {
|
||||
contrastCache: IColorContrastCache;
|
||||
}
|
||||
|
||||
export type ReadonlyColorSet = Readonly<Omit<IColorSet, 'ansi'>> & { ansi: Readonly<Pick<IColorSet, 'ansi'>['ansi']> };
|
||||
|
||||
export interface IColorContrastCache {
|
||||
clear(): void;
|
||||
setCss(bg: number, fg: number, value: string | null): void;
|
||||
@@ -150,7 +152,7 @@ export interface IViewport extends IDisposable {
|
||||
handleWheel(ev: WheelEvent): boolean;
|
||||
handleTouchStart(ev: TouchEvent): void;
|
||||
handleTouchMove(ev: TouchEvent): boolean;
|
||||
handleThemeChange(colors: IColorSet): void;
|
||||
handleThemeChange(colors: ReadonlyColorSet): void;
|
||||
}
|
||||
|
||||
export interface ILinkifierEvent {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { IRenderer, IRenderDimensions, IRequestRedrawEvent } from 'browser/rende
|
||||
import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_BLINK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from 'browser/renderer/dom/DomRendererRowFactory';
|
||||
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
|
||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||
import { IColorSet, ILinkifierEvent, ILinkifier2 } from 'browser/Types';
|
||||
import { IColorSet, ILinkifierEvent, ILinkifier2, ReadonlyColorSet } from 'browser/Types';
|
||||
import { ICharSizeService, ICoreBrowserService } from 'browser/services/Services';
|
||||
import { IOptionsService, IBufferService, IInstantiationService } from 'common/services/Services';
|
||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||
@@ -43,7 +43,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
||||
public readonly onRequestRedraw = this.register(new EventEmitter<IRequestRedrawEvent>()).event;
|
||||
|
||||
constructor(
|
||||
private _colors: IColorSet,
|
||||
private _colors: ReadonlyColorSet,
|
||||
private readonly _element: HTMLElement,
|
||||
private readonly _screenElement: HTMLElement,
|
||||
private readonly _viewportElement: HTMLElement,
|
||||
|
||||
@@ -9,7 +9,7 @@ import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
|
||||
import { color, rgba } from 'common/Color';
|
||||
import { IColorSet } from 'browser/Types';
|
||||
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
|
||||
import { ICharacterJoinerService, ICoreBrowserService } from 'browser/services/Services';
|
||||
import { JoinedCellData } from 'browser/services/CharacterJoinerService';
|
||||
import { excludeFromContrastRatioDemands } from 'browser/renderer/shared/RendererUtils';
|
||||
@@ -35,7 +35,7 @@ export class DomRendererRowFactory {
|
||||
|
||||
constructor(
|
||||
private readonly _document: Document,
|
||||
private _colors: IColorSet,
|
||||
private _colors: ReadonlyColorSet,
|
||||
@ICharacterJoinerService private readonly _characterJoinerService: ICharacterJoinerService,
|
||||
@IOptionsService private readonly _optionsService: IOptionsService,
|
||||
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ISelectionRenderModel } from 'browser/renderer/shared/Types';
|
||||
import { ICoreBrowserService } from 'browser/services/Services';
|
||||
import { IColorSet } from 'browser/Types';
|
||||
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
|
||||
import { Attributes, BgFlags, FgFlags } from 'common/buffer/Constants';
|
||||
import { IDecorationService } from 'common/services/Services';
|
||||
import { ICellData } from 'common/Types';
|
||||
@@ -26,7 +26,7 @@ export class CellColorResolver {
|
||||
|
||||
constructor(
|
||||
private readonly _terminal: Terminal,
|
||||
private _colors: IColorSet,
|
||||
private _colors: ReadonlyColorSet,
|
||||
private readonly _selectionRenderModel: ISelectionRenderModel,
|
||||
private readonly _decorationService: IDecorationService,
|
||||
private readonly _coreBrowserService: ICoreBrowserService
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas';
|
||||
import { Terminal } from 'xterm';
|
||||
import { IColorSet, ITerminal } from 'browser/Types';
|
||||
import { ITerminal, ReadonlyColorSet } from 'browser/Types';
|
||||
import { ICharAtlasConfig, ITextureAtlas } from 'browser/renderer/shared/Types';
|
||||
import { generateConfig, configEquals } from 'browser/renderer/shared/CharAtlasUtils';
|
||||
|
||||
@@ -27,7 +27,7 @@ const charAtlasCache: ITextureAtlasCacheEntry[] = [];
|
||||
*/
|
||||
export function acquireTextureAtlas(
|
||||
terminal: Terminal,
|
||||
colors: IColorSet,
|
||||
colors: ReadonlyColorSet,
|
||||
scaledCellWidth: number,
|
||||
scaledCellHeight: number,
|
||||
scaledCharWidth: number,
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
import { ICharAtlasConfig } from './Types';
|
||||
import { Attributes } from 'common/buffer/Constants';
|
||||
import { Terminal } from 'xterm';
|
||||
import { IColorSet } from 'browser/Types';
|
||||
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
|
||||
import { NULL_COLOR } from 'common/Color';
|
||||
|
||||
export function generateConfig(scaledCellWidth: number, scaledCellHeight: number, scaledCharWidth: number, scaledCharHeight: number, terminal: Terminal, colors: IColorSet, devicePixelRatio: number): ICharAtlasConfig {
|
||||
export function generateConfig(scaledCellWidth: number, scaledCellHeight: number, scaledCharWidth: number, scaledCharHeight: number, terminal: Terminal, colors: ReadonlyColorSet, devicePixelRatio: number): ICharAtlasConfig {
|
||||
// null out some fields that don't matter
|
||||
const clonedColors: IColorSet = {
|
||||
foreground: colors.foreground,
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
|
||||
import { IEvent } from 'common/EventEmitter';
|
||||
import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
|
||||
import { IColorSet } from 'browser/Types';
|
||||
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
|
||||
import { ISelectionRedrawRequestEvent as ISelectionRequestRedrawEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
|
||||
import { createDecorator } from 'common/services/ServiceRegistry';
|
||||
import { IDisposable } from 'common/Types';
|
||||
import { ColorIndex, IDisposable } from 'common/Types';
|
||||
import { ITheme } from 'common/services/Services';
|
||||
|
||||
export const ICharSizeService = createDecorator<ICharSizeService>('CharSizeService');
|
||||
export interface ICharSizeService {
|
||||
@@ -73,7 +74,7 @@ export interface IRenderService extends IDisposable {
|
||||
resize(cols: number, rows: number): void;
|
||||
hasRenderer(): boolean;
|
||||
setRenderer(renderer: IRenderer): void;
|
||||
setColors(colors: IColorSet): void;
|
||||
setColors(colors: ReadonlyColorSet): void;
|
||||
handleDevicePixelRatioChange(): void;
|
||||
handleResize(cols: number, rows: number): void;
|
||||
handleCharSizeChanged(): void;
|
||||
@@ -121,3 +122,17 @@ export interface ICharacterJoinerService {
|
||||
deregister(joinerId: number): boolean;
|
||||
getJoinedCharacters(row: number): [number, number][];
|
||||
}
|
||||
|
||||
export const IThemeService = createDecorator<IThemeService>('ThemeService');
|
||||
export interface IThemeService {
|
||||
serviceBrand: undefined;
|
||||
|
||||
readonly colors: ReadonlyColorSet;
|
||||
setTheme(theme?: ITheme): void;
|
||||
restoreColor(slot?: ColorIndex): void;
|
||||
/**
|
||||
* Allows external modifying of colors in the theme, this is used instead of {@link colors} to
|
||||
* prevent accidental writes.
|
||||
*/
|
||||
modifyColors(callback: (colors: IColorSet) => void): void;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2022 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ColorManager } from 'browser/ColorManager';
|
||||
import { IThemeService } from 'browser/services/Services';
|
||||
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import { IOptionsService, ITheme } from 'common/services/Services';
|
||||
import { ColorIndex } from 'common/Types';
|
||||
|
||||
export class ThemeService extends Disposable implements IThemeService {
|
||||
public serviceBrand: undefined;
|
||||
|
||||
// TODO: Merge color manager into theme service
|
||||
private _colorManager = new ColorManager();
|
||||
|
||||
public get colors(): ReadonlyColorSet { return this._colorManager.colors; }
|
||||
|
||||
constructor(
|
||||
@IOptionsService private readonly _optionsService: IOptionsService
|
||||
) {
|
||||
super();
|
||||
this.register(this._optionsService.onOptionChange(key => {
|
||||
if (key === 'theme') {
|
||||
this.setTheme(this._optionsService.rawOptions.theme);
|
||||
}
|
||||
this._colorManager.handleOptionsChange(key, this._optionsService.rawOptions[key]);
|
||||
}));
|
||||
this._colorManager.setTheme(this._optionsService.rawOptions.theme);
|
||||
}
|
||||
|
||||
public setTheme(theme: ITheme = {}): void {
|
||||
this._colorManager.setTheme(theme);
|
||||
}
|
||||
|
||||
public restoreColor(slot?: ColorIndex): void {
|
||||
this._colorManager.restoreColor(slot);
|
||||
}
|
||||
|
||||
public modifyColors(callback: (colors: IColorSet) => void): void {
|
||||
callback(this._colorManager.colors);
|
||||
// TODO: Fire event
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user