Merge remote-tracking branch 'upstream/master' into scoped_package
This commit is contained in:
@@ -88,7 +88,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|||||||
this._updateCursorBlink();
|
this._updateCursorBlink();
|
||||||
this.register(_optionsService.onOptionChange(() => this._handleOptionsChanged()));
|
this.register(_optionsService.onOptionChange(() => this._handleOptionsChanged()));
|
||||||
|
|
||||||
this._canvas = document.createElement('canvas');
|
this._canvas = this._coreBrowserService.mainDocument.createElement('canvas');
|
||||||
|
|
||||||
const contextAttributes = {
|
const contextAttributes = {
|
||||||
antialias: false,
|
antialias: false,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
|
|||||||
protected readonly _themeService: IThemeService
|
protected readonly _themeService: IThemeService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._canvas = document.createElement('canvas');
|
this._canvas = this._coreBrowserService.mainDocument.createElement('canvas');
|
||||||
this._canvas.classList.add(`xterm-${id}-layer`);
|
this._canvas.classList.add(`xterm-${id}-layer`);
|
||||||
this._canvas.style.zIndex = zIndex.toString();
|
this._canvas.style.zIndex = zIndex.toString();
|
||||||
this._initCanvas();
|
this._initCanvas();
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
|
|||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._cellColorResolver = new CellColorResolver(this._terminal, this._selectionModel, this._decorationService, this._coreBrowserService, this._themeService);
|
this._cellColorResolver = new CellColorResolver(this._terminal, this._selectionModel, this._decorationService, this._coreBrowserService, this._themeService);
|
||||||
this._canvas = document.createElement('canvas');
|
this._canvas = this._coreBrowserService.mainDocument.createElement('canvas');
|
||||||
this._canvas.classList.add(`xterm-${id}-layer`);
|
this._canvas.classList.add(`xterm-${id}-layer`);
|
||||||
this._canvas.style.zIndex = zIndex.toString();
|
this._canvas.style.zIndex = zIndex.toString();
|
||||||
this._initCanvas();
|
this._initCanvas();
|
||||||
|
|||||||
@@ -134,9 +134,10 @@ export class SearchAddon extends Disposable implements ITerminalAddon {
|
|||||||
if (!this._terminal) {
|
if (!this._terminal) {
|
||||||
throw new Error('Cannot use addon until it has been loaded');
|
throw new Error('Cannot use addon until it has been loaded');
|
||||||
}
|
}
|
||||||
|
const didOptionsChanged = this._lastSearchOptions ? this._didOptionsChange(this._lastSearchOptions, searchOptions) : true;
|
||||||
this._lastSearchOptions = searchOptions;
|
this._lastSearchOptions = searchOptions;
|
||||||
if (searchOptions?.decorations) {
|
if (searchOptions?.decorations) {
|
||||||
if (this._cachedSearchTerm === undefined || term !== this._cachedSearchTerm) {
|
if (this._cachedSearchTerm === undefined || term !== this._cachedSearchTerm || didOptionsChanged) {
|
||||||
this._highlightAllMatches(term, searchOptions);
|
this._highlightAllMatches(term, searchOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,9 +303,10 @@ export class SearchAddon extends Disposable implements ITerminalAddon {
|
|||||||
if (!this._terminal) {
|
if (!this._terminal) {
|
||||||
throw new Error('Cannot use addon until it has been loaded');
|
throw new Error('Cannot use addon until it has been loaded');
|
||||||
}
|
}
|
||||||
|
const didOptionsChanged = this._lastSearchOptions ? this._didOptionsChange(this._lastSearchOptions, searchOptions) : true;
|
||||||
this._lastSearchOptions = searchOptions;
|
this._lastSearchOptions = searchOptions;
|
||||||
if (searchOptions?.decorations) {
|
if (searchOptions?.decorations) {
|
||||||
if (this._cachedSearchTerm === undefined || term !== this._cachedSearchTerm) {
|
if (this._cachedSearchTerm === undefined || term !== this._cachedSearchTerm || didOptionsChanged) {
|
||||||
this._highlightAllMatches(term, searchOptions);
|
this._highlightAllMatches(term, searchOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,6 +318,22 @@ export class SearchAddon extends Disposable implements ITerminalAddon {
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _didOptionsChange(lastSearchOptions: ISearchOptions, searchOptions?: ISearchOptions): boolean {
|
||||||
|
if (!searchOptions) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (lastSearchOptions.caseSensitive !== searchOptions.caseSensitive) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (lastSearchOptions.regex !== searchOptions.regex) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (lastSearchOptions.wholeWord !== searchOptions.wholeWord) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private _fireResults(searchOptions?: ISearchOptions): void {
|
private _fireResults(searchOptions?: ISearchOptions): void {
|
||||||
if (searchOptions?.decorations) {
|
if (searchOptions?.decorations) {
|
||||||
let resultIndex = -1;
|
let resultIndex = -1;
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ The file `src/UnicodeProperties.ts` is generated and depends on the Unicode vers
|
|||||||
|
|
||||||
### Install
|
### Install
|
||||||
|
|
||||||
```bash
|
This addon is not yet published to npm
|
||||||
npm install --save xterm-addon-unicode-graphemes
|
|
||||||
```
|
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ import * as Strings from 'browser/LocalizableStrings';
|
|||||||
import { ITerminal, IRenderDebouncer } from 'browser/Types';
|
import { ITerminal, IRenderDebouncer } from 'browser/Types';
|
||||||
import { TimeBasedDebouncer } from 'browser/TimeBasedDebouncer';
|
import { TimeBasedDebouncer } from 'browser/TimeBasedDebouncer';
|
||||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||||
import { ScreenDprMonitor } from 'browser/ScreenDprMonitor';
|
import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
|
||||||
import { IRenderService } from 'browser/services/Services';
|
|
||||||
import { addDisposableDomListener } from 'browser/Lifecycle';
|
|
||||||
import { IBuffer } from 'common/buffer/Types';
|
import { IBuffer } from 'common/buffer/Types';
|
||||||
|
import { IInstantiationService } from 'common/services/Services';
|
||||||
|
|
||||||
const MAX_ROWS_TO_READ = 20;
|
const MAX_ROWS_TO_READ = 20;
|
||||||
|
|
||||||
@@ -29,8 +28,6 @@ export class AccessibilityManager extends Disposable {
|
|||||||
private _liveRegionLineCount: number = 0;
|
private _liveRegionLineCount: number = 0;
|
||||||
private _liveRegionDebouncer: IRenderDebouncer;
|
private _liveRegionDebouncer: IRenderDebouncer;
|
||||||
|
|
||||||
private _screenDprMonitor: ScreenDprMonitor;
|
|
||||||
|
|
||||||
private _topBoundaryFocusListener: (e: FocusEvent) => void;
|
private _topBoundaryFocusListener: (e: FocusEvent) => void;
|
||||||
private _bottomBoundaryFocusListener: (e: FocusEvent) => void;
|
private _bottomBoundaryFocusListener: (e: FocusEvent) => void;
|
||||||
|
|
||||||
@@ -49,13 +46,15 @@ export class AccessibilityManager extends Disposable {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _terminal: ITerminal,
|
private readonly _terminal: ITerminal,
|
||||||
|
@IInstantiationService instantiationService: IInstantiationService,
|
||||||
|
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
|
||||||
@IRenderService private readonly _renderService: IRenderService
|
@IRenderService private readonly _renderService: IRenderService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._accessibilityContainer = document.createElement('div');
|
this._accessibilityContainer = this._coreBrowserService.mainDocument.createElement('div');
|
||||||
this._accessibilityContainer.classList.add('xterm-accessibility');
|
this._accessibilityContainer.classList.add('xterm-accessibility');
|
||||||
|
|
||||||
this._rowContainer = document.createElement('div');
|
this._rowContainer = this._coreBrowserService.mainDocument.createElement('div');
|
||||||
this._rowContainer.setAttribute('role', 'list');
|
this._rowContainer.setAttribute('role', 'list');
|
||||||
this._rowContainer.classList.add('xterm-accessibility-tree');
|
this._rowContainer.classList.add('xterm-accessibility-tree');
|
||||||
this._rowElements = [];
|
this._rowElements = [];
|
||||||
@@ -72,7 +71,7 @@ export class AccessibilityManager extends Disposable {
|
|||||||
this._refreshRowsDimensions();
|
this._refreshRowsDimensions();
|
||||||
this._accessibilityContainer.appendChild(this._rowContainer);
|
this._accessibilityContainer.appendChild(this._rowContainer);
|
||||||
|
|
||||||
this._liveRegion = document.createElement('div');
|
this._liveRegion = this._coreBrowserService.mainDocument.createElement('div');
|
||||||
this._liveRegion.classList.add('live-region');
|
this._liveRegion.classList.add('live-region');
|
||||||
this._liveRegion.setAttribute('aria-live', 'assertive');
|
this._liveRegion.setAttribute('aria-live', 'assertive');
|
||||||
this._accessibilityContainer.appendChild(this._liveRegion);
|
this._accessibilityContainer.appendChild(this._liveRegion);
|
||||||
@@ -93,13 +92,7 @@ export class AccessibilityManager extends Disposable {
|
|||||||
this.register(this._terminal.onKey(e => this._handleKey(e.key)));
|
this.register(this._terminal.onKey(e => this._handleKey(e.key)));
|
||||||
this.register(this._terminal.onBlur(() => this._clearLiveRegion()));
|
this.register(this._terminal.onBlur(() => this._clearLiveRegion()));
|
||||||
this.register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions()));
|
this.register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions()));
|
||||||
|
this.register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions()));
|
||||||
this._screenDprMonitor = new ScreenDprMonitor(window);
|
|
||||||
this.register(this._screenDprMonitor);
|
|
||||||
this._screenDprMonitor.setListener(() => this._refreshRowsDimensions());
|
|
||||||
// This shouldn't be needed on modern browsers but is present in case the
|
|
||||||
// media query that drives the ScreenDprMonitor isn't supported
|
|
||||||
this.register(addDisposableDomListener(window, 'resize', () => this._refreshRowsDimensions()));
|
|
||||||
|
|
||||||
this._refreshRows();
|
this._refreshRows();
|
||||||
this.register(toDisposable(() => {
|
this.register(toDisposable(() => {
|
||||||
@@ -261,7 +254,7 @@ export class AccessibilityManager extends Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _createAccessibilityTreeNode(): HTMLElement {
|
private _createAccessibilityTreeNode(): HTMLElement {
|
||||||
const element = document.createElement('div');
|
const element = this._coreBrowserService.mainDocument.createElement('div');
|
||||||
element.setAttribute('role', 'listitem');
|
element.setAttribute('role', 'listitem');
|
||||||
element.tabIndex = -1;
|
element.tabIndex = -1;
|
||||||
this._refreshRowDimensions(element);
|
this._refreshRowDimensions(element);
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
||||||
|
|
||||||
export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The screen device pixel ratio monitor allows listening for when the
|
|
||||||
* window.devicePixelRatio value changes. This is done not with polling but with
|
|
||||||
* the use of window.matchMedia to watch media queries. When the event fires,
|
|
||||||
* the listener will be reattached using a different media query to ensure that
|
|
||||||
* any further changes will register.
|
|
||||||
*
|
|
||||||
* The listener should fire on both window zoom changes and switching to a
|
|
||||||
* monitor with a different DPI.
|
|
||||||
*/
|
|
||||||
export class ScreenDprMonitor extends Disposable {
|
|
||||||
private _currentDevicePixelRatio: number;
|
|
||||||
private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined;
|
|
||||||
private _listener: ScreenDprListener | undefined;
|
|
||||||
private _resolutionMediaMatchList: MediaQueryList | undefined;
|
|
||||||
|
|
||||||
constructor(private _parentWindow: Window) {
|
|
||||||
super();
|
|
||||||
this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio;
|
|
||||||
this.register(toDisposable(() => {
|
|
||||||
this.clearListener();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
public setListener(listener: ScreenDprListener): void {
|
|
||||||
if (this._listener) {
|
|
||||||
this.clearListener();
|
|
||||||
}
|
|
||||||
this._listener = listener;
|
|
||||||
this._outerListener = () => {
|
|
||||||
if (!this._listener) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._listener(this._parentWindow.devicePixelRatio, this._currentDevicePixelRatio);
|
|
||||||
this._updateDpr();
|
|
||||||
};
|
|
||||||
this._updateDpr();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _updateDpr(): void {
|
|
||||||
if (!this._outerListener) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear listeners for old DPR
|
|
||||||
this._resolutionMediaMatchList?.removeListener(this._outerListener);
|
|
||||||
|
|
||||||
// Add listeners for new DPR
|
|
||||||
this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio;
|
|
||||||
this._resolutionMediaMatchList = this._parentWindow.matchMedia(`screen and (resolution: ${this._parentWindow.devicePixelRatio}dppx)`);
|
|
||||||
this._resolutionMediaMatchList.addListener(this._outerListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public clearListener(): void {
|
|
||||||
if (!this._resolutionMediaMatchList || !this._listener || !this._outerListener) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._resolutionMediaMatchList.removeListener(this._outerListener);
|
|
||||||
this._resolutionMediaMatchList = undefined;
|
|
||||||
this._listener = undefined;
|
|
||||||
this._outerListener = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+23
-12
@@ -58,9 +58,6 @@ import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker }
|
|||||||
import { WindowsOptionsReportType } from '../common/InputHandler';
|
import { WindowsOptionsReportType } from '../common/InputHandler';
|
||||||
import { AccessibilityManager } from './AccessibilityManager';
|
import { AccessibilityManager } from './AccessibilityManager';
|
||||||
|
|
||||||
// Let it work inside Node.js for automated testing purposes.
|
|
||||||
const document: Document = (typeof window !== 'undefined') ? window.document : null as any;
|
|
||||||
|
|
||||||
export class Terminal extends CoreTerminal implements ITerminal {
|
export class Terminal extends CoreTerminal implements ITerminal {
|
||||||
public textarea: HTMLTextAreaElement | undefined;
|
public textarea: HTMLTextAreaElement | undefined;
|
||||||
public element: HTMLElement | undefined;
|
public element: HTMLElement | undefined;
|
||||||
@@ -397,7 +394,16 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
this._logService.debug('Terminal.open was called on an element that was not attached to the DOM');
|
this._logService.debug('Terminal.open was called on an element that was not attached to the DOM');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._document = parent.ownerDocument!;
|
// If the terminal is already opened
|
||||||
|
if (this.element?.ownerDocument.defaultView && this._coreBrowserService) {
|
||||||
|
// Adjust the window if needed
|
||||||
|
if (this.element.ownerDocument.defaultView !== this._coreBrowserService.window) {
|
||||||
|
this._coreBrowserService.window = this.element.ownerDocument.defaultView;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._document = parent.ownerDocument;
|
||||||
if (this.options.documentOverride && this.options.documentOverride instanceof Document) {
|
if (this.options.documentOverride && this.options.documentOverride instanceof Document) {
|
||||||
this._document = this.optionsService.rawOptions.documentOverride as Document;
|
this._document = this.optionsService.rawOptions.documentOverride as Document;
|
||||||
}
|
}
|
||||||
@@ -411,25 +417,25 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
|
|
||||||
// Performance: Use a document fragment to build the terminal
|
// Performance: Use a document fragment to build the terminal
|
||||||
// viewport and helper elements detached from the DOM
|
// viewport and helper elements detached from the DOM
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = this._document.createDocumentFragment();
|
||||||
this._viewportElement = document.createElement('div');
|
this._viewportElement = this._document.createElement('div');
|
||||||
this._viewportElement.classList.add('xterm-viewport');
|
this._viewportElement.classList.add('xterm-viewport');
|
||||||
fragment.appendChild(this._viewportElement);
|
fragment.appendChild(this._viewportElement);
|
||||||
|
|
||||||
this._viewportScrollArea = document.createElement('div');
|
this._viewportScrollArea = this._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);
|
||||||
|
|
||||||
this.screenElement = document.createElement('div');
|
this.screenElement = this._document.createElement('div');
|
||||||
this.screenElement.classList.add('xterm-screen');
|
this.screenElement.classList.add('xterm-screen');
|
||||||
// Create the container that will hold helpers like the textarea for
|
// Create the container that will hold helpers like the textarea for
|
||||||
// capturing DOM Events. Then produce the helpers.
|
// capturing DOM Events. Then produce the helpers.
|
||||||
this._helperContainer = document.createElement('div');
|
this._helperContainer = this._document.createElement('div');
|
||||||
this._helperContainer.classList.add('xterm-helpers');
|
this._helperContainer.classList.add('xterm-helpers');
|
||||||
this.screenElement.appendChild(this._helperContainer);
|
this.screenElement.appendChild(this._helperContainer);
|
||||||
fragment.appendChild(this.screenElement);
|
fragment.appendChild(this.screenElement);
|
||||||
|
|
||||||
this.textarea = document.createElement('textarea');
|
this.textarea = this._document.createElement('textarea');
|
||||||
this.textarea.classList.add('xterm-helper-textarea');
|
this.textarea.classList.add('xterm-helper-textarea');
|
||||||
this.textarea.setAttribute('aria-label', Strings.promptLabel);
|
this.textarea.setAttribute('aria-label', Strings.promptLabel);
|
||||||
if (!Browser.isChromeOS) {
|
if (!Browser.isChromeOS) {
|
||||||
@@ -444,7 +450,12 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
|
|
||||||
// Register the core browser service before the generic textarea handlers are registered so it
|
// Register the core browser service before the generic textarea handlers are registered so it
|
||||||
// handles them first. Otherwise the renderers may use the wrong focus state.
|
// handles them first. Otherwise the renderers may use the wrong focus state.
|
||||||
this._coreBrowserService = this._instantiationService.createInstance(CoreBrowserService, this.textarea, this._document.defaultView ?? window);
|
this._coreBrowserService = this.register(this._instantiationService.createInstance(CoreBrowserService,
|
||||||
|
this.textarea,
|
||||||
|
parent.ownerDocument.defaultView ?? window,
|
||||||
|
// Force unsafe null in node.js environment for tests
|
||||||
|
this._document ?? (typeof window !== 'undefined') ? window.document : null as any
|
||||||
|
));
|
||||||
this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
|
this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
|
||||||
|
|
||||||
this.register(addDisposableDomListener(this.textarea, 'focus', (ev: KeyboardEvent) => this._handleTextAreaFocus(ev)));
|
this.register(addDisposableDomListener(this.textarea, 'focus', (ev: KeyboardEvent) => this._handleTextAreaFocus(ev)));
|
||||||
@@ -466,7 +477,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
|||||||
this.register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
|
this.register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
|
||||||
this.onResize(e => this._renderService!.resize(e.cols, e.rows));
|
this.onResize(e => this._renderService!.resize(e.cols, e.rows));
|
||||||
|
|
||||||
this._compositionView = document.createElement('div');
|
this._compositionView = this._document.createElement('div');
|
||||||
this._compositionView.classList.add('composition-view');
|
this._compositionView.classList.add('composition-view');
|
||||||
this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
|
this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
|
||||||
this._helperContainer.appendChild(this._compositionView);
|
this._helperContainer.appendChild(this._compositionView);
|
||||||
|
|||||||
@@ -350,11 +350,16 @@ export class MockCompositionHelper implements ICompositionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MockCoreBrowserService implements ICoreBrowserService {
|
export class MockCoreBrowserService implements ICoreBrowserService {
|
||||||
|
public onDprChange = new EventEmitter<number>().event;
|
||||||
|
public onWindowChange = new EventEmitter<Window & typeof globalThis, void>().event;
|
||||||
public serviceBrand: undefined;
|
public serviceBrand: undefined;
|
||||||
public isFocused: boolean = true;
|
public isFocused: boolean = true;
|
||||||
public get window(): Window & typeof globalThis {
|
public get window(): Window & typeof globalThis {
|
||||||
throw Error('Window object not available in tests');
|
throw Error('Window object not available in tests');
|
||||||
}
|
}
|
||||||
|
public get mainDocument(): Document {
|
||||||
|
throw Error('Document object not available in tests');
|
||||||
|
}
|
||||||
public dpr: number = 1;
|
public dpr: number = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { addDisposableDomListener } from 'browser/Lifecycle';
|
import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
|
||||||
import { IRenderService } from 'browser/services/Services';
|
|
||||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||||
import { IBufferService, IDecorationService, IInternalDecoration } from 'common/services/Services';
|
import { IBufferService, IDecorationService, IInternalDecoration } from 'common/services/Services';
|
||||||
|
|
||||||
@@ -19,6 +18,7 @@ export class BufferDecorationRenderer extends Disposable {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly _screenElement: HTMLElement,
|
private readonly _screenElement: HTMLElement,
|
||||||
@IBufferService private readonly _bufferService: IBufferService,
|
@IBufferService private readonly _bufferService: IBufferService,
|
||||||
|
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
|
||||||
@IDecorationService private readonly _decorationService: IDecorationService,
|
@IDecorationService private readonly _decorationService: IDecorationService,
|
||||||
@IRenderService private readonly _renderService: IRenderService
|
@IRenderService private readonly _renderService: IRenderService
|
||||||
) {
|
) {
|
||||||
@@ -33,7 +33,7 @@ export class BufferDecorationRenderer extends Disposable {
|
|||||||
this._dimensionsChanged = true;
|
this._dimensionsChanged = true;
|
||||||
this._queueRefresh();
|
this._queueRefresh();
|
||||||
}));
|
}));
|
||||||
this.register(addDisposableDomListener(window, 'resize', () => this._queueRefresh()));
|
this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh()));
|
||||||
this.register(this._bufferService.buffers.onBufferActivate(() => {
|
this.register(this._bufferService.buffers.onBufferActivate(() => {
|
||||||
this._altBufferIsActive = this._bufferService.buffer === this._bufferService.buffers.alt;
|
this._altBufferIsActive = this._bufferService.buffer === this._bufferService.buffers.alt;
|
||||||
}));
|
}));
|
||||||
@@ -70,7 +70,7 @@ export class BufferDecorationRenderer extends Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _createElement(decoration: IInternalDecoration): HTMLElement {
|
private _createElement(decoration: IInternalDecoration): HTMLElement {
|
||||||
const element = document.createElement('div');
|
const element = this._coreBrowserService.mainDocument.createElement('div');
|
||||||
element.classList.add('xterm-decoration');
|
element.classList.add('xterm-decoration');
|
||||||
element.classList.toggle('xterm-decoration-top-layer', decoration?.options?.layer === 'top');
|
element.classList.toggle('xterm-decoration-top-layer', decoration?.options?.layer === 'top');
|
||||||
element.style.width = `${Math.round((decoration.options.width || 1) * this._renderService.dimensions.css.cell.width)}px`;
|
element.style.width = `${Math.round((decoration.options.width || 1) * this._renderService.dimensions.css.cell.width)}px`;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore';
|
import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore';
|
||||||
import { addDisposableDomListener } from 'browser/Lifecycle';
|
|
||||||
import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
|
import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
|
||||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||||
import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
|
import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
|
||||||
@@ -52,10 +51,10 @@ export class OverviewRulerRenderer extends Disposable {
|
|||||||
@IDecorationService private readonly _decorationService: IDecorationService,
|
@IDecorationService private readonly _decorationService: IDecorationService,
|
||||||
@IRenderService private readonly _renderService: IRenderService,
|
@IRenderService private readonly _renderService: IRenderService,
|
||||||
@IOptionsService private readonly _optionsService: IOptionsService,
|
@IOptionsService private readonly _optionsService: IOptionsService,
|
||||||
@ICoreBrowserService private readonly _coreBrowseService: ICoreBrowserService
|
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._canvas = document.createElement('canvas');
|
this._canvas = this._coreBrowserService.mainDocument.createElement('canvas');
|
||||||
this._canvas.classList.add('xterm-decoration-overview-ruler');
|
this._canvas.classList.add('xterm-decoration-overview-ruler');
|
||||||
this._refreshCanvasDimensions();
|
this._refreshCanvasDimensions();
|
||||||
this._viewportElement.parentElement?.insertBefore(this._canvas, this._viewportElement);
|
this._viewportElement.parentElement?.insertBefore(this._canvas, this._viewportElement);
|
||||||
@@ -112,7 +111,7 @@ export class OverviewRulerRenderer extends Disposable {
|
|||||||
// overview ruler width changed
|
// overview ruler width changed
|
||||||
this.register(this._optionsService.onSpecificOptionChange('overviewRulerWidth', () => this._queueRefresh(true)));
|
this.register(this._optionsService.onSpecificOptionChange('overviewRulerWidth', () => this._queueRefresh(true)));
|
||||||
// device pixel ratio changed
|
// device pixel ratio changed
|
||||||
this.register(addDisposableDomListener(this._coreBrowseService.window, 'resize', () => this._queueRefresh(true)));
|
this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh(true)));
|
||||||
// set the canvas dimensions
|
// set the canvas dimensions
|
||||||
this._queueRefresh(true);
|
this._queueRefresh(true);
|
||||||
}
|
}
|
||||||
@@ -135,11 +134,11 @@ export class OverviewRulerRenderer extends Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _refreshDrawHeightConstants(): void {
|
private _refreshDrawHeightConstants(): void {
|
||||||
drawHeight.full = Math.round(2 * this._coreBrowseService.dpr);
|
drawHeight.full = Math.round(2 * this._coreBrowserService.dpr);
|
||||||
// Calculate actual pixels per line
|
// Calculate actual pixels per line
|
||||||
const pixelsPerLine = this._canvas.height / this._bufferService.buffer.lines.length;
|
const pixelsPerLine = this._canvas.height / this._bufferService.buffer.lines.length;
|
||||||
// Clamp actual pixels within a range
|
// Clamp actual pixels within a range
|
||||||
const nonFullHeight = Math.round(Math.max(Math.min(pixelsPerLine, 12), 6) * this._coreBrowseService.dpr);
|
const nonFullHeight = Math.round(Math.max(Math.min(pixelsPerLine, 12), 6) * this._coreBrowserService.dpr);
|
||||||
drawHeight.left = nonFullHeight;
|
drawHeight.left = nonFullHeight;
|
||||||
drawHeight.center = nonFullHeight;
|
drawHeight.center = nonFullHeight;
|
||||||
drawHeight.right = nonFullHeight;
|
drawHeight.right = nonFullHeight;
|
||||||
@@ -157,9 +156,9 @@ export class OverviewRulerRenderer extends Disposable {
|
|||||||
|
|
||||||
private _refreshCanvasDimensions(): void {
|
private _refreshCanvasDimensions(): void {
|
||||||
this._canvas.style.width = `${this._width}px`;
|
this._canvas.style.width = `${this._width}px`;
|
||||||
this._canvas.width = Math.round(this._width * this._coreBrowseService.dpr);
|
this._canvas.width = Math.round(this._width * this._coreBrowserService.dpr);
|
||||||
this._canvas.style.height = `${this._screenElement.clientHeight}px`;
|
this._canvas.style.height = `${this._screenElement.clientHeight}px`;
|
||||||
this._canvas.height = Math.round(this._screenElement.clientHeight * this._coreBrowseService.dpr);
|
this._canvas.height = Math.round(this._screenElement.clientHeight * this._coreBrowserService.dpr);
|
||||||
this._refreshDrawConstants();
|
this._refreshDrawConstants();
|
||||||
this._refreshColorZonePadding();
|
this._refreshColorZonePadding();
|
||||||
}
|
}
|
||||||
@@ -211,7 +210,7 @@ export class OverviewRulerRenderer extends Disposable {
|
|||||||
if (this._animationFrame !== undefined) {
|
if (this._animationFrame !== undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._animationFrame = this._coreBrowseService.window.requestAnimationFrame(() => {
|
this._animationFrame = this._coreBrowserService.window.requestAnimationFrame(() => {
|
||||||
this._refreshDecorations();
|
this._refreshDecorations();
|
||||||
this._animationFrame = undefined;
|
this._animationFrame = undefined;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ function drawPatternChar(
|
|||||||
if (!pattern) {
|
if (!pattern) {
|
||||||
const width = charDefinition[0].length;
|
const width = charDefinition[0].length;
|
||||||
const height = charDefinition.length;
|
const height = charDefinition.length;
|
||||||
const tmpCanvas = document.createElement('canvas');
|
const tmpCanvas = ctx.canvas.ownerDocument.createElement('canvas');
|
||||||
tmpCanvas.width = width;
|
tmpCanvas.width = width;
|
||||||
tmpCanvas.height = height;
|
tmpCanvas.height = height;
|
||||||
const tmpCtx = throwIfFalsy(tmpCanvas.getContext('2d'));
|
const tmpCtx = throwIfFalsy(tmpCanvas.getContext('2d'));
|
||||||
|
|||||||
@@ -3,22 +3,49 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
||||||
import { ICoreBrowserService } from './Services';
|
import { ICoreBrowserService } from './Services';
|
||||||
|
import { EventEmitter, forwardEvent } from 'common/EventEmitter';
|
||||||
|
import { addDisposableDomListener } from 'browser/Lifecycle';
|
||||||
|
|
||||||
export class CoreBrowserService implements ICoreBrowserService {
|
export class CoreBrowserService extends Disposable implements ICoreBrowserService {
|
||||||
public serviceBrand: undefined;
|
public serviceBrand: undefined;
|
||||||
|
|
||||||
private _isFocused = false;
|
private _isFocused = false;
|
||||||
private _cachedIsFocused: boolean | undefined = undefined;
|
private _cachedIsFocused: boolean | undefined = undefined;
|
||||||
|
private _screenDprMonitor = new ScreenDprMonitor(this._window);
|
||||||
|
|
||||||
|
private readonly _onDprChange = this.register(new EventEmitter<number>());
|
||||||
|
public readonly onDprChange = this._onDprChange.event;
|
||||||
|
private readonly _onWindowChange = this.register(new EventEmitter<Window & typeof globalThis>());
|
||||||
|
public readonly onWindowChange = this._onWindowChange.event;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _textarea: HTMLTextAreaElement,
|
private _textarea: HTMLTextAreaElement,
|
||||||
public readonly window: Window & typeof globalThis
|
private _window: Window & typeof globalThis,
|
||||||
|
public readonly mainDocument: Document
|
||||||
) {
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// Monitor device pixel ratio
|
||||||
|
this.register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w)));
|
||||||
|
this.register(forwardEvent(this._screenDprMonitor.onDprChange, this._onDprChange));
|
||||||
|
|
||||||
this._textarea.addEventListener('focus', () => this._isFocused = true);
|
this._textarea.addEventListener('focus', () => this._isFocused = true);
|
||||||
this._textarea.addEventListener('blur', () => this._isFocused = false);
|
this._textarea.addEventListener('blur', () => this._isFocused = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get window(): Window & typeof globalThis {
|
||||||
|
return this._window;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set window(value: Window & typeof globalThis) {
|
||||||
|
if (this._window !== value) {
|
||||||
|
this._window = value;
|
||||||
|
this._onWindowChange.fire(this._window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public get dpr(): number {
|
public get dpr(): number {
|
||||||
return this.window.devicePixelRatio;
|
return this.window.devicePixelRatio;
|
||||||
}
|
}
|
||||||
@@ -31,3 +58,80 @@ export class CoreBrowserService implements ICoreBrowserService {
|
|||||||
return this._cachedIsFocused;
|
return this._cachedIsFocused;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen device pixel ratio monitor allows listening for when the
|
||||||
|
* window.devicePixelRatio value changes. This is done not with polling but with
|
||||||
|
* the use of window.matchMedia to watch media queries. When the event fires,
|
||||||
|
* the listener will be reattached using a different media query to ensure that
|
||||||
|
* any further changes will register.
|
||||||
|
*
|
||||||
|
* The listener should fire on both window zoom changes and switching to a
|
||||||
|
* monitor with a different DPI.
|
||||||
|
*/
|
||||||
|
class ScreenDprMonitor extends Disposable {
|
||||||
|
private _currentDevicePixelRatio: number;
|
||||||
|
private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined;
|
||||||
|
private _resolutionMediaMatchList: MediaQueryList | undefined;
|
||||||
|
private _windowResizeListener = this.register(new MutableDisposable());
|
||||||
|
|
||||||
|
private readonly _onDprChange = this.register(new EventEmitter<number>());
|
||||||
|
public readonly onDprChange = this._onDprChange.event;
|
||||||
|
|
||||||
|
constructor(private _parentWindow: Window) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// Initialize listener and dpr value
|
||||||
|
this._outerListener = () => this._setDprAndFireIfDiffers();
|
||||||
|
this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio;
|
||||||
|
this._updateDpr();
|
||||||
|
|
||||||
|
// Monitor active window resize
|
||||||
|
this._setWindowResizeListener();
|
||||||
|
|
||||||
|
// Setup additional disposables
|
||||||
|
this.register(toDisposable(() => this.clearListener()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public setWindow(parentWindow: Window): void {
|
||||||
|
this._parentWindow = parentWindow;
|
||||||
|
this._setWindowResizeListener();
|
||||||
|
this._setDprAndFireIfDiffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setWindowResizeListener(): void {
|
||||||
|
this._windowResizeListener.value = addDisposableDomListener(this._parentWindow, 'resize', () => this._setDprAndFireIfDiffers());
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setDprAndFireIfDiffers(): void {
|
||||||
|
if (this._parentWindow.devicePixelRatio !== this._currentDevicePixelRatio) {
|
||||||
|
this._onDprChange.fire(this._parentWindow.devicePixelRatio);
|
||||||
|
}
|
||||||
|
this._updateDpr();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _updateDpr(): void {
|
||||||
|
if (!this._outerListener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear listeners for old DPR
|
||||||
|
this._resolutionMediaMatchList?.removeListener(this._outerListener);
|
||||||
|
|
||||||
|
// Add listeners for new DPR
|
||||||
|
this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio;
|
||||||
|
this._resolutionMediaMatchList = this._parentWindow.matchMedia(`screen and (resolution: ${this._parentWindow.devicePixelRatio}dppx)`);
|
||||||
|
this._resolutionMediaMatchList.addListener(this._outerListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public clearListener(): void {
|
||||||
|
if (!this._resolutionMediaMatchList || !this._outerListener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._resolutionMediaMatchList.removeListener(this._outerListener);
|
||||||
|
this._resolutionMediaMatchList = undefined;
|
||||||
|
this._outerListener = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,16 +3,14 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { addDisposableDomListener } from 'browser/Lifecycle';
|
|
||||||
import { RenderDebouncer } from 'browser/RenderDebouncer';
|
import { RenderDebouncer } from 'browser/RenderDebouncer';
|
||||||
import { ScreenDprMonitor } from 'browser/ScreenDprMonitor';
|
|
||||||
import { IRenderDebouncerWithCallback } from 'browser/Types';
|
import { IRenderDebouncerWithCallback } from 'browser/Types';
|
||||||
import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
|
import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
|
||||||
import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
|
import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
|
||||||
import { EventEmitter } from 'common/EventEmitter';
|
import { EventEmitter } from 'common/EventEmitter';
|
||||||
import { Disposable, MutableDisposable } from 'common/Lifecycle';
|
import { Disposable, MutableDisposable } from 'common/Lifecycle';
|
||||||
import { DebouncedIdleTask } from 'common/TaskQueue';
|
import { DebouncedIdleTask } from 'common/TaskQueue';
|
||||||
import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
|
import { IBufferService, IDecorationService, IInstantiationService, IOptionsService } from 'common/services/Services';
|
||||||
|
|
||||||
interface ISelectionState {
|
interface ISelectionState {
|
||||||
start: [number, number] | undefined;
|
start: [number, number] | undefined;
|
||||||
@@ -25,7 +23,6 @@ export class RenderService extends Disposable implements IRenderService {
|
|||||||
|
|
||||||
private _renderer: MutableDisposable<IRenderer> = this.register(new MutableDisposable());
|
private _renderer: MutableDisposable<IRenderer> = this.register(new MutableDisposable());
|
||||||
private _renderDebouncer: IRenderDebouncerWithCallback;
|
private _renderDebouncer: IRenderDebouncerWithCallback;
|
||||||
private _screenDprMonitor: ScreenDprMonitor;
|
|
||||||
private _pausedResizeTask = new DebouncedIdleTask();
|
private _pausedResizeTask = new DebouncedIdleTask();
|
||||||
|
|
||||||
private _isPaused: boolean = false;
|
private _isPaused: boolean = false;
|
||||||
@@ -59,6 +56,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|||||||
@IDecorationService decorationService: IDecorationService,
|
@IDecorationService decorationService: IDecorationService,
|
||||||
@IBufferService bufferService: IBufferService,
|
@IBufferService bufferService: IBufferService,
|
||||||
@ICoreBrowserService coreBrowserService: ICoreBrowserService,
|
@ICoreBrowserService coreBrowserService: ICoreBrowserService,
|
||||||
|
@IInstantiationService instantiationService: IInstantiationService,
|
||||||
@IThemeService themeService: IThemeService
|
@IThemeService themeService: IThemeService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@@ -66,9 +64,7 @@ export class RenderService extends Disposable implements IRenderService {
|
|||||||
this._renderDebouncer = new RenderDebouncer(coreBrowserService.window, (start, end) => this._renderRows(start, end));
|
this._renderDebouncer = new RenderDebouncer(coreBrowserService.window, (start, end) => this._renderRows(start, end));
|
||||||
this.register(this._renderDebouncer);
|
this.register(this._renderDebouncer);
|
||||||
|
|
||||||
this._screenDprMonitor = new ScreenDprMonitor(coreBrowserService.window);
|
this.register(coreBrowserService.onDprChange(() => this.handleDevicePixelRatioChange()));
|
||||||
this._screenDprMonitor.setListener(() => this.handleDevicePixelRatioChange());
|
|
||||||
this.register(this._screenDprMonitor);
|
|
||||||
|
|
||||||
this.register(bufferService.onResize(() => this._fullRefresh()));
|
this.register(bufferService.onResize(() => this._fullRefresh()));
|
||||||
this.register(bufferService.buffers.onBufferActivate(() => this._renderer.value?.clear()));
|
this.register(bufferService.buffers.onBufferActivate(() => this._renderer.value?.clear()));
|
||||||
@@ -104,10 +100,6 @@ export class RenderService extends Disposable implements IRenderService {
|
|||||||
'cursorStyle'
|
'cursorStyle'
|
||||||
], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, true)));
|
], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, true)));
|
||||||
|
|
||||||
// dprchange should handle this case, we need this as well for browsers that don't support the
|
|
||||||
// matchMedia query.
|
|
||||||
this.register(addDisposableDomListener(coreBrowserService.window, 'resize', () => this.handleDevicePixelRatioChange()));
|
|
||||||
|
|
||||||
this.register(themeService.onChangeColors(() => this._fullRefresh()));
|
this.register(themeService.onChangeColors(() => this._fullRefresh()));
|
||||||
|
|
||||||
// Detect whether IntersectionObserver is detected and enable renderer pause
|
// Detect whether IntersectionObserver is detected and enable renderer pause
|
||||||
|
|||||||
@@ -28,12 +28,21 @@ export interface ICoreBrowserService {
|
|||||||
serviceBrand: undefined;
|
serviceBrand: undefined;
|
||||||
|
|
||||||
readonly isFocused: boolean;
|
readonly isFocused: boolean;
|
||||||
|
|
||||||
|
readonly onDprChange: IEvent<number>;
|
||||||
|
readonly onWindowChange: IEvent<Window & typeof globalThis>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent window that the terminal is rendered into. DOM and rendering APIs
|
* Gets or sets the parent window that the terminal is rendered into. DOM and rendering APIs (e.g.
|
||||||
* (e.g. requestAnimationFrame) should be invoked in the context of this
|
* requestAnimationFrame) should be invoked in the context of this window. This should be set when
|
||||||
* window.
|
* the window hosting the xterm.js instance changes.
|
||||||
*/
|
*/
|
||||||
readonly window: Window & typeof globalThis;
|
window: Window & typeof globalThis;
|
||||||
|
/**
|
||||||
|
* The document of the primary window to be used to create elements when working with multiple
|
||||||
|
* windows. This is defined by the documentOverride setting.
|
||||||
|
*/
|
||||||
|
readonly mainDocument: Document;
|
||||||
/**
|
/**
|
||||||
* Helper for getting the devicePixelRatio of the parent window.
|
* Helper for getting the devicePixelRatio of the parent window.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ export namespace css {
|
|||||||
let $ctx: CanvasRenderingContext2D | undefined;
|
let $ctx: CanvasRenderingContext2D | undefined;
|
||||||
let $litmusColor: CanvasGradient | undefined;
|
let $litmusColor: CanvasGradient | undefined;
|
||||||
if (!isNode) {
|
if (!isNode) {
|
||||||
|
// This is guaranteed to run in the first window, so document should be correct
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
canvas.width = 1;
|
canvas.width = 1;
|
||||||
canvas.height = 1;
|
canvas.height = 1;
|
||||||
|
|||||||
@@ -71,3 +71,8 @@ export class EventEmitter<T, U = void> implements IEventEmitter<T, U> {
|
|||||||
export function forwardEvent<T>(from: IEvent<T>, to: IEventEmitter<T>): IDisposable {
|
export function forwardEvent<T>(from: IEvent<T>, to: IEventEmitter<T>): IDisposable {
|
||||||
return from(e => to.fire(e));
|
return from(e => to.fire(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function runAndSubscribe<T>(event: IEvent<T>, handler: (e: T | undefined) => any): IDisposable {
|
||||||
|
handler(undefined);
|
||||||
|
return event(e => handler(e));
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ interface INavigator {
|
|||||||
// We're declaring a navigator global here as we expect it in all runtimes (node and browser), but
|
// We're declaring a navigator global here as we expect it in all runtimes (node and browser), but
|
||||||
// we want this module to live in common.
|
// we want this module to live in common.
|
||||||
declare const navigator: INavigator;
|
declare const navigator: INavigator;
|
||||||
|
declare const process: unknown;
|
||||||
|
|
||||||
export const isNode = (typeof navigator === 'undefined') ? true : false;
|
export const isNode = (typeof process !== 'undefined') ? true : false;
|
||||||
const userAgent = (isNode) ? 'node' : navigator.userAgent;
|
const userAgent = (isNode) ? 'node' : navigator.userAgent;
|
||||||
const platform = (isNode) ? 'node' : navigator.platform;
|
const platform = (isNode) ? 'node' : navigator.platform;
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-1
@@ -973,7 +973,8 @@ declare module 'xterm' {
|
|||||||
resize(columns: number, rows: number): void;
|
resize(columns: number, rows: number): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the terminal within an element.
|
* Opens the terminal within an element. This should also be called if the
|
||||||
|
* xterm.js element ever changes browser window.
|
||||||
* @param parent The element to create the terminal within. This element
|
* @param parent The element to create the terminal within. This element
|
||||||
* must be visible (have dimensions) when `open` is called as several DOM-
|
* must be visible (have dimensions) when `open` is called as several DOM-
|
||||||
* based measurements need to be performed when this function is called.
|
* based measurements need to be performed when this function is called.
|
||||||
|
|||||||
+4
-2
@@ -39,8 +39,10 @@ const config = {
|
|||||||
output: {
|
output: {
|
||||||
filename: 'xterm.js',
|
filename: 'xterm.js',
|
||||||
path: path.resolve('./lib'),
|
path: path.resolve('./lib'),
|
||||||
libraryTarget: 'umd'
|
libraryTarget: 'umd',
|
||||||
|
// Force usage of globalThis instead of global / self. (This is cross-env compatible)
|
||||||
|
globalObject: 'globalThis',
|
||||||
},
|
},
|
||||||
mode: 'production'
|
mode: 'production',
|
||||||
};
|
};
|
||||||
module.exports = config;
|
module.exports = config;
|
||||||
|
|||||||
@@ -15,6 +15,14 @@
|
|||||||
"@jridgewell/gen-mapping" "^0.3.0"
|
"@jridgewell/gen-mapping" "^0.3.0"
|
||||||
"@jridgewell/trace-mapping" "^0.3.9"
|
"@jridgewell/trace-mapping" "^0.3.9"
|
||||||
|
|
||||||
|
"@babel/code-frame@^7.22.13":
|
||||||
|
version "7.22.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
|
||||||
|
integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
|
||||||
|
dependencies:
|
||||||
|
"@babel/highlight" "^7.22.13"
|
||||||
|
chalk "^2.4.2"
|
||||||
|
|
||||||
"@babel/code-frame@^7.22.5":
|
"@babel/code-frame@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658"
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658"
|
||||||
@@ -48,7 +56,7 @@
|
|||||||
json5 "^2.2.2"
|
json5 "^2.2.2"
|
||||||
semver "^6.3.1"
|
semver "^6.3.1"
|
||||||
|
|
||||||
"@babel/generator@^7.22.7", "@babel/generator@^7.22.9":
|
"@babel/generator@^7.22.9":
|
||||||
version "7.22.9"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d"
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d"
|
||||||
integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==
|
integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==
|
||||||
@@ -58,6 +66,16 @@
|
|||||||
"@jridgewell/trace-mapping" "^0.3.17"
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
jsesc "^2.5.1"
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
|
"@babel/generator@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
|
||||||
|
integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.23.0"
|
||||||
|
"@jridgewell/gen-mapping" "^0.3.2"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
"@babel/helper-compilation-targets@^7.22.9":
|
"@babel/helper-compilation-targets@^7.22.9":
|
||||||
version "7.22.9"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz#f9d0a7aaaa7cd32a3f31c9316a69f5a9bcacb892"
|
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz#f9d0a7aaaa7cd32a3f31c9316a69f5a9bcacb892"
|
||||||
@@ -69,18 +87,23 @@
|
|||||||
lru-cache "^5.1.1"
|
lru-cache "^5.1.1"
|
||||||
semver "^6.3.1"
|
semver "^6.3.1"
|
||||||
|
|
||||||
|
"@babel/helper-environment-visitor@^7.22.20":
|
||||||
|
version "7.22.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
|
||||||
|
integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
|
||||||
|
|
||||||
"@babel/helper-environment-visitor@^7.22.5":
|
"@babel/helper-environment-visitor@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
|
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
|
||||||
integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==
|
integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==
|
||||||
|
|
||||||
"@babel/helper-function-name@^7.22.5":
|
"@babel/helper-function-name@^7.23.0":
|
||||||
version "7.22.5"
|
version "7.23.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be"
|
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
|
||||||
integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==
|
integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/template" "^7.22.5"
|
"@babel/template" "^7.22.15"
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.23.0"
|
||||||
|
|
||||||
"@babel/helper-hoist-variables@^7.22.5":
|
"@babel/helper-hoist-variables@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
@@ -126,6 +149,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
|
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
|
||||||
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
|
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier@^7.22.20":
|
||||||
|
version "7.22.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
|
||||||
|
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
|
||||||
|
|
||||||
"@babel/helper-validator-identifier@^7.22.5":
|
"@babel/helper-validator-identifier@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193"
|
||||||
@@ -145,6 +173,15 @@
|
|||||||
"@babel/traverse" "^7.22.6"
|
"@babel/traverse" "^7.22.6"
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
|
"@babel/highlight@^7.22.13":
|
||||||
|
version "7.22.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
|
||||||
|
integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier" "^7.22.20"
|
||||||
|
chalk "^2.4.2"
|
||||||
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
"@babel/highlight@^7.22.5":
|
"@babel/highlight@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031"
|
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031"
|
||||||
@@ -154,6 +191,11 @@
|
|||||||
chalk "^2.0.0"
|
chalk "^2.0.0"
|
||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
|
"@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
|
||||||
|
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
|
||||||
|
|
||||||
"@babel/parser@^7.22.5", "@babel/parser@^7.22.7":
|
"@babel/parser@^7.22.5", "@babel/parser@^7.22.7":
|
||||||
version "7.22.7"
|
version "7.22.7"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae"
|
||||||
@@ -166,6 +208,15 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.11"
|
regenerator-runtime "^0.13.11"
|
||||||
|
|
||||||
|
"@babel/template@^7.22.15":
|
||||||
|
version "7.22.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
|
||||||
|
integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.22.13"
|
||||||
|
"@babel/parser" "^7.22.15"
|
||||||
|
"@babel/types" "^7.22.15"
|
||||||
|
|
||||||
"@babel/template@^7.22.5":
|
"@babel/template@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
|
||||||
@@ -176,21 +227,30 @@
|
|||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
"@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8":
|
"@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8":
|
||||||
version "7.22.8"
|
version "7.23.2"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e"
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
|
||||||
integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==
|
integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.22.5"
|
"@babel/code-frame" "^7.22.13"
|
||||||
"@babel/generator" "^7.22.7"
|
"@babel/generator" "^7.23.0"
|
||||||
"@babel/helper-environment-visitor" "^7.22.5"
|
"@babel/helper-environment-visitor" "^7.22.20"
|
||||||
"@babel/helper-function-name" "^7.22.5"
|
"@babel/helper-function-name" "^7.23.0"
|
||||||
"@babel/helper-hoist-variables" "^7.22.5"
|
"@babel/helper-hoist-variables" "^7.22.5"
|
||||||
"@babel/helper-split-export-declaration" "^7.22.6"
|
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||||
"@babel/parser" "^7.22.7"
|
"@babel/parser" "^7.23.0"
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.23.0"
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
globals "^11.1.0"
|
globals "^11.1.0"
|
||||||
|
|
||||||
|
"@babel/types@^7.22.15", "@babel/types@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
|
||||||
|
integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-string-parser" "^7.22.5"
|
||||||
|
"@babel/helper-validator-identifier" "^7.22.20"
|
||||||
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@babel/types@^7.22.5":
|
"@babel/types@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe"
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe"
|
||||||
@@ -1145,7 +1205,7 @@ chai@^4.3.4:
|
|||||||
pathval "^1.1.1"
|
pathval "^1.1.1"
|
||||||
type-detect "^4.0.5"
|
type-detect "^4.0.5"
|
||||||
|
|
||||||
chalk@^2.0.0:
|
chalk@^2.0.0, chalk@^2.4.2:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||||
|
|||||||
Reference in New Issue
Block a user