Expose modes api

Part of #3417
This commit is contained in:
Daniel Imms
2021-08-16 14:44:39 -07:00
parent 012468785b
commit 6affe68ca3
6 changed files with 114 additions and 37 deletions
+23 -23
View File
@@ -267,8 +267,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
* Binds the desired focus behavior on a given terminal object.
*/
private _onTextAreaFocus(ev: KeyboardEvent): void {
if (this._coreService.decPrivateModes.sendFocus) {
this._coreService.triggerDataEvent(C0.ESC + '[I');
if (this.coreService.decPrivateModes.sendFocus) {
this.coreService.triggerDataEvent(C0.ESC + '[I');
}
this.updateCursorStyle(ev);
this.element!.classList.add('focus');
@@ -292,8 +292,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
// screen readers reading it out.
this.textarea!.value = '';
this.refresh(this.buffer.y, this.buffer.y);
if (this._coreService.decPrivateModes.sendFocus) {
this._coreService.triggerDataEvent(C0.ESC + '[O');
if (this.coreService.decPrivateModes.sendFocus) {
this.coreService.triggerDataEvent(C0.ESC + '[O');
}
this.element!.classList.remove('focus');
this._onBlur.fire();
@@ -340,7 +340,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
copyHandler(event, this._selectionService!);
}));
const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea!, this._coreService);
const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea!, this.coreService);
this.register(addDisposableDomListener(this.textarea!, 'paste', pasteHandlerWrapper));
this.register(addDisposableDomListener(this.element!, 'paste', pasteHandlerWrapper));
@@ -526,7 +526,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.onMouseDown(e)));
// apply mouse event classes set by escape codes before terminal was attached
if (this._coreMouseService.areMouseEventsActive) {
if (this.coreMouseService.areMouseEventsActive) {
this._selectionService.disable();
this.element.classList.add('enable-mouse-events');
} else {
@@ -644,7 +644,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
return false;
}
return self._coreMouseService.triggerMouseEvent({
return self.coreMouseService.triggerMouseEvent({
col: pos.x - 33, // FIXME: why -33 here?
row: pos.y - 33,
button: but,
@@ -699,11 +699,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
}
};
this.register(this._coreMouseService.onProtocolChange(events => {
this.register(this.coreMouseService.onProtocolChange(events => {
// apply global changes on events
if (events) {
if (this.optionsService.options.logLevel === 'debug') {
this._logService.debug('Binding to mouse events:', this._coreMouseService.explainEvents(events));
this._logService.debug('Binding to mouse events:', this.coreMouseService.explainEvents(events));
}
this.element!.classList.add('enable-mouse-events');
this._selectionService!.disable();
@@ -746,7 +746,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
}));
// force initial onProtocolChange so we dont miss early mouse requests
this._coreMouseService.activeProtocol = this._coreMouseService.activeProtocol;
this.coreMouseService.activeProtocol = this.coreMouseService.activeProtocol;
/**
* "Always on" event listeners.
@@ -758,7 +758,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
// Don't send the mouse button to the pty if mouse events are disabled or
// if the selection manager is having selection forced (ie. a modifier is
// held).
if (!this._coreMouseService.areMouseEventsActive || this._selectionService!.shouldForceSelection(ev)) {
if (!this.coreMouseService.areMouseEventsActive || this._selectionService!.shouldForceSelection(ev)) {
return;
}
@@ -791,12 +791,12 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
// Construct and send sequences
const sequence = C0.ESC + (this._coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
let data = '';
for (let i = 0; i < Math.abs(amount); i++) {
data += sequence;
}
this._coreService.triggerDataEvent(data, true);
this.coreService.triggerDataEvent(data, true);
}
return;
}
@@ -812,13 +812,13 @@ export class Terminal extends CoreTerminal implements ITerminal {
}, { passive: false }));
this.register(addDisposableDomListener(el, 'touchstart', (ev: TouchEvent) => {
if (this._coreMouseService.areMouseEventsActive) return;
if (this.coreMouseService.areMouseEventsActive) return;
this.viewport!.onTouchStart(ev);
return this.cancel(ev);
}, { passive: true }));
this.register(addDisposableDomListener(el, 'touchmove', (ev: TouchEvent) => {
if (this._coreMouseService.areMouseEventsActive) return;
if (this.coreMouseService.areMouseEventsActive) return;
if (!this.viewport!.onTouchMove(ev)) {
return this.cancel(ev);
}
@@ -860,8 +860,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
* Display the cursor element
*/
private _showCursor(): void {
if (!this._coreService.isCursorInitialized) {
this._coreService.isCursorInitialized = true;
if (!this.coreService.isCursorInitialized) {
this.coreService.isCursorInitialized = true;
this.refresh(this.buffer.y, this.buffer.y);
}
}
@@ -872,7 +872,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
public paste(data: string): void {
paste(data, this.textarea!, this._coreService);
paste(data, this.textarea!, this.coreService);
}
/**
@@ -1025,7 +1025,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
return false;
}
const result = evaluateKeyboardEvent(event, this._coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta);
const result = evaluateKeyboardEvent(event, this.coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta);
this.updateCursorStyle(event);
@@ -1061,7 +1061,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._onKey.fire({ key: result.key, domEvent: event });
this._showCursor();
this._coreService.triggerDataEvent(result.key, true);
this.coreService.triggerDataEvent(result.key, true);
// Cancel events when not in screen reader mode so events don't get bubbled up and handled by
// other listeners. When screen reader mode is enabled, this could cause issues if the event
@@ -1138,7 +1138,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._onKey.fire({ key, domEvent: ev });
this._showCursor();
this._coreService.triggerDataEvent(key, true);
this.coreService.triggerDataEvent(key, true);
return true;
}
@@ -1247,12 +1247,12 @@ export class Terminal extends CoreTerminal implements ITerminal {
case WindowsOptionsReportType.GET_WIN_SIZE_PIXELS:
const canvasWidth = this._renderService.dimensions.scaledCanvasWidth.toFixed(0);
const canvasHeight = this._renderService.dimensions.scaledCanvasHeight.toFixed(0);
this._coreService.triggerDataEvent(`${C0.ESC}[4;${canvasHeight};${canvasWidth}t`);
this.coreService.triggerDataEvent(`${C0.ESC}[4;${canvasHeight};${canvasWidth}t`);
break;
case WindowsOptionsReportType.GET_CELL_SIZE_PIXELS:
const cellWidth = this._renderService.dimensions.scaledCellWidth.toFixed(0);
const cellHeight = this._renderService.dimensions.scaledCellHeight.toFixed(0);
this._coreService.triggerDataEvent(`${C0.ESC}[6;${cellHeight};${cellWidth}t`);
this.coreService.triggerDataEvent(`${C0.ESC}[6;${cellHeight};${cellWidth}t`);
break;
}
}
+3 -1
View File
@@ -13,7 +13,7 @@ import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, I
import { Buffer } from 'common/buffer/Buffer';
import * as Browser from 'common/Platform';
import { Terminal } from 'browser/Terminal';
import { IUnicodeService, IOptionsService } from 'common/services/Services';
import { IUnicodeService, IOptionsService, ICoreService, ICoreMouseService } from 'common/services/Services';
import { IFunctionIdentifier, IParams } from 'common/parser/Types';
import { AttributeData } from 'common/buffer/AttributeData';
@@ -43,6 +43,8 @@ export class MockTerminal implements ITerminal {
public onRender!: IEvent<{ start: number, end: number }>;
public onResize!: IEvent<{ cols: number, rows: number }>;
public markers!: IMarker[];
public coreMouseService!: ICoreMouseService;
public coreService!: ICoreService;
public optionsService!: IOptionsService;
public unicodeService!: IUnicodeService;
public addMarker(cursorYOffset: number): IMarker {
+22 -1
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBufferNamespace as IBufferNamespaceApi, IParser, ILinkProvider, IUnicodeHandling, FontWeight } from 'xterm';
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBufferNamespace as IBufferNamespaceApi, IParser, ILinkProvider, IUnicodeHandling, FontWeight, IModes } from 'xterm';
import { ITerminal } from 'browser/Types';
import { Terminal as TerminalCore } from 'browser/Terminal';
import * as Strings from 'browser/LocalizableStrings';
@@ -68,6 +68,27 @@ export class Terminal implements ITerminalApi {
this._checkProposedApi();
return this._core.markers;
}
public get modes(): IModes {
const m = this._core.coreService.decPrivateModes;
let mouseTrackingMode: 'none' | 'x10' | 'vt200' | 'drag' | 'any' = 'none';
switch (this._core.coreMouseService.activeProtocol) {
case 'X10': mouseTrackingMode = 'x10'; break;
case 'VT200': mouseTrackingMode = 'vt200'; break;
case 'DRAG': mouseTrackingMode = 'drag'; break;
case 'ANY': mouseTrackingMode = 'any'; break;
}
return {
applicationCursorKeysMode: m.applicationCursorKeys,
applicationKeypadMode: m.applicationKeypad,
bracketedPasteMode: m.bracketedPasteMode,
insertMode: this._core.coreService.modes.insertMode,
mouseTrackingMode: mouseTrackingMode,
originMode: m.origin,
reverseWraparoundMode: m.reverseWraparound,
sendFocusMode: m.sendFocus,
wraparoundMode: m.wraparound
};
}
public blur(): void {
this._core.blur();
}
+11 -11
View File
@@ -47,11 +47,11 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
protected readonly _instantiationService: IInstantiationService;
protected readonly _bufferService: IBufferService;
protected readonly _logService: ILogService;
protected readonly _coreService: ICoreService;
protected readonly _charsetService: ICharsetService;
protected readonly _coreMouseService: ICoreMouseService;
protected readonly _dirtyRowService: IDirtyRowService;
public readonly coreMouseService: ICoreMouseService;
public readonly coreService: ICoreService;
public readonly unicodeService: IUnicodeService;
public readonly optionsService: IOptionsService;
@@ -100,10 +100,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
this._instantiationService.setService(IBufferService, this._bufferService);
this._logService = this._instantiationService.createInstance(LogService);
this._instantiationService.setService(ILogService, this._logService);
this._coreService = this.register(this._instantiationService.createInstance(CoreService, () => this.scrollToBottom()));
this._instantiationService.setService(ICoreService, this._coreService);
this._coreMouseService = this._instantiationService.createInstance(CoreMouseService);
this._instantiationService.setService(ICoreMouseService, this._coreMouseService);
this.coreService = this.register(this._instantiationService.createInstance(CoreService, () => this.scrollToBottom()));
this._instantiationService.setService(ICoreService, this.coreService);
this.coreMouseService = this._instantiationService.createInstance(CoreMouseService);
this._instantiationService.setService(ICoreMouseService, this.coreMouseService);
this._dirtyRowService = this._instantiationService.createInstance(DirtyRowService);
this._instantiationService.setService(IDirtyRowService, this._dirtyRowService);
this.unicodeService = this._instantiationService.createInstance(UnicodeService);
@@ -112,14 +112,14 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
this._instantiationService.setService(ICharsetService, this._charsetService);
// Register input handler and handle/forward events
this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService);
this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this.coreService, this._dirtyRowService, this._logService, this.optionsService, this.coreMouseService, this.unicodeService);
this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed));
this.register(this._inputHandler);
// Setup listeners
this.register(forwardEvent(this._bufferService.onResize, this._onResize));
this.register(forwardEvent(this._coreService.onData, this._onData));
this.register(forwardEvent(this._coreService.onBinary, this._onBinary));
this.register(forwardEvent(this.coreService.onData, this._onData));
this.register(forwardEvent(this.coreService.onBinary, this._onBinary));
this.register(this.optionsService.onOptionChange(key => this._updateOptions(key)));
this.register(this._bufferService.onScroll(event => {
this._onScroll.fire({ position: this._bufferService.buffer.ydisp, source: ScrollSource.TERMINAL });
@@ -250,8 +250,8 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
this._inputHandler.reset();
this._bufferService.reset();
this._charsetService.reset();
this._coreService.reset();
this._coreMouseService.reset();
this.coreService.reset();
this.coreMouseService.reset();
}
protected _updateOptions(key: string): void {
+3 -1
View File
@@ -7,10 +7,12 @@ import { IFunctionIdentifier, ITerminalOptions as IPublicTerminalOptions } from
import { IEvent, IEventEmitter } from 'common/EventEmitter';
import { IDeleteEvent, IInsertEvent } from 'common/CircularList';
import { IParams } from 'common/parser/Types';
import { IOptionsService, IUnicodeService } from 'common/services/Services';
import { ICoreMouseService, ICoreService, IOptionsService, IUnicodeService } from 'common/services/Services';
import { IBufferSet } from 'common/buffer/Types';
export interface ICoreTerminal {
coreMouseService: ICoreMouseService;
coreService: ICoreService;
optionsService: IOptionsService;
unicodeService: IUnicodeService;
buffers: IBufferSet;
+52
View File
@@ -622,6 +622,11 @@ declare module 'xterm' {
*/
readonly unicode: IUnicodeHandling;
/**
* Gets the terminal modes as set by SM/DECSET.
*/
readonly modes: IModes;
/**
* Natural language strings that can be localized.
*/
@@ -1622,4 +1627,51 @@ declare module 'xterm' {
*/
activeVersion: string;
}
/**
* Terminal modes as set by SM/DECSET.
*/
export interface IModes {
/**
* Application Cursor Keys (DECCKM): `CSI ? 1 h`
*/
readonly applicationCursorKeysMode: boolean;
/**
* Application Keypad Mode (DECNKM): `CSI ? 6 6 h`
*/
readonly applicationKeypadMode: boolean;
/**
* Bracketed Paste Mode: `CSI ? 2 0 0 4 h`
*/
readonly bracketedPasteMode: boolean;
/**
* Insert Mode (IRM): `CSI 4 h`
*/
readonly insertMode: boolean;
/**
* Mouse Tracking, this can be one of the following:
* - none: This is the default value and can be reset with DECRST
* - x10: Send Mouse X & Y on button press `CSI ? 9 h`
* - vt200: Send Mouse X & Y on button press and release `CSI ? 1 0 0 0 h`
* - drag: Use Cell Motion Mouse Tracking `CSI ? 1 0 0 2 h`
* - any: Use All Motion Mouse Tracking `CSI ? 1 0 0 3 h`
*/
readonly mouseTrackingMode: 'none' | 'x10' | 'vt200' | 'drag' | 'any';
/**
* Origin Mode (DECOM): `CSI ? 6 h`
*/
readonly originMode: boolean;
/**
* Reverse-wraparound Mode: `CSI ? 4 5 h`
*/
readonly reverseWraparoundMode: boolean;
/**
* Send FocusIn/FocusOut events: `CSI ? 1 0 0 3 h`
*/
readonly sendFocusMode: boolean;
/**
* Auto-Wrap Mode (DECAWM): `CSI ? 7 h`
*/
readonly wraparoundMode: boolean
}
}