Merge pull request #5953 from xtermjs/cursor/alt-click-for-mouse-events-5b17
Add altClickForMouseEvents option
This commit is contained in:
@@ -37,7 +37,7 @@ import { CharacterJoinerService } from 'browser/services/CharacterJoinerService'
|
||||
import { CoreBrowserService } from 'browser/services/CoreBrowserService';
|
||||
import { LinkProviderService } from 'browser/services/LinkProviderService';
|
||||
import { MouseCoordsService } from 'browser/services/MouseCoordsService';
|
||||
import { MouseService } from 'browser/services/MouseService';
|
||||
import { MouseEventCssClasses, MouseService } from 'browser/services/MouseService';
|
||||
import { RenderService } from 'browser/services/RenderService';
|
||||
import { SelectionService } from 'browser/services/SelectionService';
|
||||
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IKeyboardService, ILinkProviderService, IMouseCoordsService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services';
|
||||
@@ -618,11 +618,12 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
||||
this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
|
||||
|
||||
// apply mouse event classes set by escape codes before terminal was attached
|
||||
if (this.mouseStateService.areMouseEventsActive) {
|
||||
if (this.mouseStateService.areMouseEventsActive && !this.options.mouseEventsRequireAlt) {
|
||||
this._selectionService.disable();
|
||||
this.element.classList.add('enable-mouse-events');
|
||||
this.element.classList.add(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
||||
} else {
|
||||
this._selectionService.enable();
|
||||
this.element.classList.remove(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
||||
}
|
||||
|
||||
if (this.options.screenReaderMode) {
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
* @license MIT
|
||||
*/
|
||||
import { assert } from 'chai';
|
||||
import { MouseService } from 'browser/services/MouseService';
|
||||
import { AltMouseCursorController, MouseEventCssClasses, MouseService } from 'browser/services/MouseService';
|
||||
import { MouseStateService } from 'common/services/MouseStateService';
|
||||
import { CoreMouseAction, CoreMouseButton } from 'common/Types';
|
||||
import { IBufferService, ICoreService, ILogService, IOptionsService } from 'common/services/Services';
|
||||
import { OptionsService } from 'common/services/OptionsService';
|
||||
import { MockCoreBrowserService, MockRenderService, MockSelectionService } from 'browser/TestUtils.test';
|
||||
|
||||
function toBytes(s: string | undefined): number[] {
|
||||
@@ -42,6 +43,36 @@ const logService: ILogService = {
|
||||
error: () => {}
|
||||
} as any;
|
||||
|
||||
class TestSelectionService extends MockSelectionService {
|
||||
public enableCount = 0;
|
||||
public disableCount = 0;
|
||||
|
||||
public override enable(): void {
|
||||
this.enableCount++;
|
||||
}
|
||||
|
||||
public override disable(): void {
|
||||
this.disableCount++;
|
||||
}
|
||||
|
||||
public override shouldForceSelection(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function createTestMouseTargetElement(): HTMLElement {
|
||||
const classes = new Set<string>();
|
||||
return {
|
||||
classList: {
|
||||
add: (className: string) => classes.add(className),
|
||||
remove: (className: string) => classes.delete(className),
|
||||
contains: (className: string) => classes.has(className)
|
||||
},
|
||||
addEventListener: () => {},
|
||||
removeEventListener: () => {}
|
||||
} as any;
|
||||
}
|
||||
|
||||
describe('MouseService _triggerMouseEvent', () => {
|
||||
let mouseService: MouseService;
|
||||
let mouseStateService: MouseStateService;
|
||||
@@ -211,3 +242,112 @@ describe('MouseService _triggerMouseEvent', () => {
|
||||
reports = [];
|
||||
});
|
||||
});
|
||||
|
||||
describe('MouseService mouseEventsRequireAlt', () => {
|
||||
it('should update selection state and cursor class when toggled while mouse events are active', () => {
|
||||
const mouseStateService = new MouseStateService();
|
||||
const optionsService = new OptionsService({});
|
||||
const selectionService = new TestSelectionService();
|
||||
const mouseService = new MouseService(
|
||||
new MockRenderService(),
|
||||
{
|
||||
getMouseReportCoords: (_ev: MouseEvent, _el: HTMLElement) => ({ col: 0, row: 0, x: 0, y: 0 })
|
||||
} as any,
|
||||
mouseStateService,
|
||||
{
|
||||
triggerDataEvent: () => {},
|
||||
triggerBinaryEvent: () => {},
|
||||
decPrivateModes: { applicationCursorKeys: false }
|
||||
} as any,
|
||||
bufferService,
|
||||
optionsService,
|
||||
selectionService,
|
||||
logService,
|
||||
new MockCoreBrowserService()
|
||||
);
|
||||
const element = createTestMouseTargetElement();
|
||||
const screenElement = createTestMouseTargetElement();
|
||||
const document = {
|
||||
addEventListener: () => {},
|
||||
removeEventListener: () => {}
|
||||
} as any;
|
||||
|
||||
mouseService.bindMouse({
|
||||
element,
|
||||
screenElement,
|
||||
document
|
||||
}, disposable => disposable, () => {});
|
||||
|
||||
mouseStateService.activeProtocol = 'ANY';
|
||||
assert.isTrue(element.classList.contains(MouseEventCssClasses.ENABLE_MOUSE_EVENTS));
|
||||
assert.equal(selectionService.disableCount, 1);
|
||||
|
||||
optionsService.options.mouseEventsRequireAlt = true;
|
||||
assert.isFalse(element.classList.contains(MouseEventCssClasses.ENABLE_MOUSE_EVENTS));
|
||||
assert.equal(selectionService.enableCount, 2);
|
||||
|
||||
optionsService.options.mouseEventsRequireAlt = false;
|
||||
assert.isTrue(element.classList.contains(MouseEventCssClasses.ENABLE_MOUSE_EVENTS));
|
||||
assert.equal(selectionService.disableCount, 2);
|
||||
});
|
||||
|
||||
it('should strip alt modifier from forwarded mouse reports', () => {
|
||||
const mouseStateService = new MouseStateService();
|
||||
mouseStateService.activeProtocol = 'ANY';
|
||||
mouseStateService.activeEncoding = 'SGR';
|
||||
const optionsService = new OptionsService({ mouseEventsRequireAlt: true });
|
||||
const reports: string[] = [];
|
||||
const mouseService = new MouseService(
|
||||
new MockRenderService(),
|
||||
{
|
||||
getMouseReportCoords: () => ({ col: 0, row: 0, x: 0, y: 0 })
|
||||
} as any,
|
||||
mouseStateService,
|
||||
{
|
||||
triggerDataEvent: (data: string) => reports.push(data),
|
||||
triggerBinaryEvent: () => {},
|
||||
decPrivateModes: { applicationCursorKeys: false }
|
||||
} as any,
|
||||
bufferService,
|
||||
optionsService,
|
||||
new TestSelectionService(),
|
||||
logService,
|
||||
new MockCoreBrowserService()
|
||||
);
|
||||
const ctx = {
|
||||
target: {
|
||||
screenElement: createTestMouseTargetElement()
|
||||
},
|
||||
requestedEvents: {}
|
||||
} as any;
|
||||
|
||||
const sent = (mouseService as any)._sendEvent(ctx, {
|
||||
type: 'mousedown',
|
||||
button: 0,
|
||||
altKey: true,
|
||||
ctrlKey: false,
|
||||
shiftKey: false
|
||||
} as MouseEvent);
|
||||
|
||||
assert.isTrue(sent);
|
||||
assert.deepEqual(reports, ['\x1b[<0;1;1M']);
|
||||
});
|
||||
|
||||
it('should toggle enable-mouse-events class when alt modifier changes', () => {
|
||||
const element = createTestMouseTargetElement();
|
||||
const altMouseCursor = new AltMouseCursorController(element, {
|
||||
addEventListener: () => {},
|
||||
removeEventListener: () => {}
|
||||
} as any, () => true);
|
||||
|
||||
const sync = (altHeld: boolean) => altMouseCursor.syncFromModifier({
|
||||
getModifierState: (key: string) => key === 'Alt' && altHeld
|
||||
} as KeyboardEvent);
|
||||
|
||||
assert.isFalse(element.classList.contains(MouseEventCssClasses.ENABLE_MOUSE_EVENTS));
|
||||
sync(true);
|
||||
assert.isTrue(element.classList.contains(MouseEventCssClasses.ENABLE_MOUSE_EVENTS));
|
||||
sync(false);
|
||||
assert.isFalse(element.classList.contains(MouseEventCssClasses.ENABLE_MOUSE_EVENTS));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,12 +7,16 @@ import { addDisposableListener } from 'browser/Dom';
|
||||
import { IBufferService, IMouseStateService, ICoreService, ILogService, IOptionsService } from 'common/services/Services';
|
||||
import { CoreMouseAction, CoreMouseButton, CoreMouseEventType, ICoreMouseEvent, IDisposable } from 'common/Types';
|
||||
import { C0 } from 'common/data/EscapeSequences';
|
||||
import { toDisposable } from 'common/Lifecycle';
|
||||
import { DisposableStore, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
||||
import { ICoreBrowserService, IMouseCoordsService, IMouseService, IMouseServiceTarget, IRenderService, ISelectionService } from './Services';
|
||||
import { Gesture, EventType as GestureEventType, IGestureEvent } from 'browser/scrollable/touch';
|
||||
|
||||
type RequestedMouseEvents = Record<'mouseup' | 'wheel' | 'mousedrag' | 'mousemove', EventListener | null>;
|
||||
|
||||
export const enum MouseEventCssClasses {
|
||||
ENABLE_MOUSE_EVENTS = 'enable-mouse-events'
|
||||
}
|
||||
|
||||
interface IMouseBindContext {
|
||||
readonly target: IMouseServiceTarget;
|
||||
readonly focus: () => void;
|
||||
@@ -25,6 +29,7 @@ export class MouseService implements IMouseService {
|
||||
private _lastEvent: ICoreMouseEvent | null = null;
|
||||
private _wheelPartialScroll: number = 0;
|
||||
private _touchScrollAccumulator: number = 0;
|
||||
private _altMouseCursor: AltMouseCursorController | undefined;
|
||||
|
||||
constructor(
|
||||
@IRenderService private readonly _renderService: IRenderService,
|
||||
@@ -63,9 +68,20 @@ export class MouseService implements IMouseService {
|
||||
mousedrag: (ev: Event) => this._handleMouseDrag(ctx, ev as MouseEvent),
|
||||
mousemove: (ev: Event) => this._handleMouseMove(ctx, ev as MouseEvent)
|
||||
};
|
||||
this._altMouseCursor = new AltMouseCursorController(
|
||||
element,
|
||||
document,
|
||||
() => this._mouseStateService.areMouseEventsActive
|
||||
&& !!this._optionsService.rawOptions.mouseEventsRequireAlt
|
||||
);
|
||||
register(this._altMouseCursor);
|
||||
register(this._mouseStateService.onProtocolChange(events => {
|
||||
this._handleProtocolChange(ctx, eventListeners, events);
|
||||
}));
|
||||
register(this._optionsService.onSpecificOptionChange('mouseEventsRequireAlt', () => {
|
||||
this._syncMouseModeState(element);
|
||||
this._altMouseCursor?.sync();
|
||||
}));
|
||||
// force initial onProtocolChange so we dont miss early mouse requests
|
||||
this._mouseStateService.activeProtocol = this._mouseStateService.activeProtocol;
|
||||
|
||||
@@ -153,6 +169,19 @@ export class MouseService implements IMouseService {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (but !== CoreMouseButton.WHEEL
|
||||
&& this._optionsService.rawOptions.mouseEventsRequireAlt
|
||||
&& this._mouseStateService.areMouseEventsActive
|
||||
&& !ev.altKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Alt is only used locally to gate mouse passthrough; do not forward it to the
|
||||
// application (e.g. tmux ignores alt-modified mouse reports).
|
||||
const stripAltFromReport = but !== CoreMouseButton.WHEEL
|
||||
&& this._optionsService.rawOptions.mouseEventsRequireAlt
|
||||
&& this._mouseStateService.areMouseEventsActive;
|
||||
|
||||
return this._triggerMouseEvent({
|
||||
col: pos.col,
|
||||
row: pos.row,
|
||||
@@ -161,7 +190,7 @@ export class MouseService implements IMouseService {
|
||||
button: but,
|
||||
action,
|
||||
ctrl: ev.ctrlKey,
|
||||
alt: ev.altKey,
|
||||
alt: stripAltFromReport ? false : ev.altKey,
|
||||
shift: ev.shiftKey
|
||||
});
|
||||
}
|
||||
@@ -353,6 +382,21 @@ export class MouseService implements IMouseService {
|
||||
this._touchScrollAccumulator = 0;
|
||||
}
|
||||
|
||||
private _syncMouseModeState(element: HTMLElement): void {
|
||||
if (this._mouseStateService.areMouseEventsActive) {
|
||||
if (this._optionsService.rawOptions.mouseEventsRequireAlt) {
|
||||
this._altMouseCursor?.resetClass();
|
||||
this._selectionService.enable();
|
||||
} else {
|
||||
element.classList.add(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
||||
this._selectionService.disable();
|
||||
}
|
||||
} else {
|
||||
element.classList.remove(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
||||
this._selectionService.enable();
|
||||
}
|
||||
}
|
||||
|
||||
private _handleProtocolChange(ctx: IMouseBindContext, eventListeners: Record<'mouseup' | 'wheel' | 'mousedrag' | 'mousemove', EventListener>, events: CoreMouseEventType): void {
|
||||
const { element, document } = ctx.target;
|
||||
const { requestedEvents } = ctx;
|
||||
@@ -361,13 +405,11 @@ export class MouseService implements IMouseService {
|
||||
if (this._optionsService.rawOptions.logLevel === 'debug') {
|
||||
this._logService.debug('Binding to mouse events:', this._explainEvents(events));
|
||||
}
|
||||
element.classList.add('enable-mouse-events');
|
||||
this._selectionService.disable();
|
||||
} else {
|
||||
this._logService.debug('Unbinding from mouse events.');
|
||||
element.classList.remove('enable-mouse-events');
|
||||
this._selectionService.enable();
|
||||
}
|
||||
this._syncMouseModeState(element);
|
||||
this._altMouseCursor?.sync();
|
||||
|
||||
// add/remove handlers from requestedEvents
|
||||
if (!(events & CoreMouseEventType.MOVE)) {
|
||||
@@ -537,3 +579,64 @@ export class MouseService implements IMouseService {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles MouseEventCssClasses.ENABLE_MOUSE_EVENTS on the terminal element while alt is held when
|
||||
* `mouseEventsRequireAlt` is active. DOM listeners are only registered while active.
|
||||
*/
|
||||
export class AltMouseCursorController implements IDisposable {
|
||||
private readonly _listeners = new MutableDisposable<IDisposable>();
|
||||
|
||||
constructor(
|
||||
private readonly _element: HTMLElement,
|
||||
private readonly _document: Document,
|
||||
private readonly _isActive: () => boolean
|
||||
) {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._listeners.dispose();
|
||||
}
|
||||
|
||||
public sync(): void {
|
||||
this._listeners.clear();
|
||||
|
||||
if (!this._isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const store = new DisposableStore();
|
||||
const syncFromModifier = (ev: KeyboardEvent | MouseEvent): void => this.syncFromModifier(ev);
|
||||
store.add(addDisposableListener(this._document, 'keydown', syncFromModifier));
|
||||
store.add(addDisposableListener(this._document, 'keyup', syncFromModifier));
|
||||
store.add(addDisposableListener(this._element, 'mousemove', syncFromModifier));
|
||||
const targetWindow = this._element.ownerDocument?.defaultView;
|
||||
if (targetWindow) {
|
||||
store.add(addDisposableListener(targetWindow, 'blur', () => {
|
||||
if (this._isActive()) {
|
||||
this.resetClass();
|
||||
}
|
||||
}));
|
||||
}
|
||||
this._listeners.value = store;
|
||||
}
|
||||
|
||||
public resetClass(): void {
|
||||
this._updateClass(false);
|
||||
}
|
||||
|
||||
public syncFromModifier(ev: KeyboardEvent | MouseEvent): void {
|
||||
if (!this._isActive()) {
|
||||
return;
|
||||
}
|
||||
this._updateClass(ev.getModifierState('Alt'));
|
||||
}
|
||||
|
||||
private _updateClass(altHeld: boolean): void {
|
||||
if (altHeld) {
|
||||
this._element.classList.add(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
||||
} else {
|
||||
this._element.classList.remove(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { assert } from 'chai';
|
||||
import { SelectionService, SelectionMode } from './SelectionService';
|
||||
import { SelectionModel } from 'browser/selection/SelectionModel';
|
||||
import { IBufferLine } from 'common/Types';
|
||||
import { MockBufferService, MockOptionsService, MockCoreService, createCellData } from 'common/TestUtils.test';
|
||||
import { MockBufferService, MockOptionsService, MockCoreService, MockMouseStateService, createCellData } from 'common/TestUtils.test';
|
||||
import { BufferLine } from 'common/buffer/BufferLine';
|
||||
import { BufferLineStringCache } from 'common/buffer/BufferLineStringCache';
|
||||
import { IBufferService, IOptionsService } from 'common/services/Services';
|
||||
@@ -22,9 +22,10 @@ class TestSelectionService extends SelectionService {
|
||||
constructor(
|
||||
bufferService: IBufferService,
|
||||
optionsService: IOptionsService,
|
||||
renderService: IRenderService
|
||||
renderService: IRenderService,
|
||||
public readonly mouseStateService: MockMouseStateService
|
||||
) {
|
||||
super(null!, null!, null!, bufferService, new MockCoreService(), new MockMouseService(), optionsService, renderService, new MockCoreBrowserService());
|
||||
super(null!, null!, null!, bufferService, new MockCoreService(), new MockMouseService(), optionsService, mouseStateService, renderService, new MockCoreBrowserService());
|
||||
}
|
||||
|
||||
public get model(): SelectionModel { return this._model; }
|
||||
@@ -45,16 +46,18 @@ describe('SelectionService', () => {
|
||||
let buffer: IBuffer;
|
||||
let bufferService: IBufferService;
|
||||
let optionsService: IOptionsService;
|
||||
let mouseStateService: MockMouseStateService;
|
||||
let selectionService: TestSelectionService;
|
||||
|
||||
beforeEach(() => {
|
||||
optionsService = new MockOptionsService();
|
||||
mouseStateService = new MockMouseStateService();
|
||||
bufferService = new MockBufferService(20, 20, optionsService);
|
||||
buffer = bufferService.buffer;
|
||||
const renderService = new MockRenderService();
|
||||
renderService.dimensions.css.canvas.height = 10 * 20;
|
||||
renderService.dimensions.css.canvas.width = 10 * 20;
|
||||
selectionService = new TestSelectionService(bufferService, optionsService, renderService);
|
||||
selectionService = new TestSelectionService(bufferService, optionsService, renderService, mouseStateService);
|
||||
});
|
||||
|
||||
function stringToRow(text: string): IBufferLine {
|
||||
@@ -499,5 +502,21 @@ describe('SelectionService', () => {
|
||||
assert.isFalse(selectionService.areCoordsInSelection([2, 1], [2, 0], [2, 1]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldForceSelection', () => {
|
||||
it('should force selection without alt when mouseEventsRequireAlt is enabled', () => {
|
||||
optionsService.options.mouseEventsRequireAlt = true;
|
||||
mouseStateService.areMouseEventsActive = true;
|
||||
assert.isTrue(selectionService.shouldForceSelection({ altKey: false } as MouseEvent));
|
||||
assert.isFalse(selectionService.shouldForceSelection({ altKey: true } as MouseEvent));
|
||||
});
|
||||
|
||||
it('should take precedence over macOptionClickForcesSelection', () => {
|
||||
optionsService.options.mouseEventsRequireAlt = true;
|
||||
optionsService.options.macOptionClickForcesSelection = true;
|
||||
mouseStateService.areMouseEventsActive = true;
|
||||
assert.isFalse(selectionService.shouldForceSelection({ altKey: true } as MouseEvent));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { IBufferLine, ICellData, IDisposable } from 'common/Types';
|
||||
import { getRangeLength } from 'common/buffer/BufferRange';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { IBuffer } from 'common/buffer/Types';
|
||||
import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services';
|
||||
import { IBufferService, ICoreService, IMouseStateService, IOptionsService } from 'common/services/Services';
|
||||
import { Emitter } from 'common/Event';
|
||||
|
||||
const enum Constants {
|
||||
@@ -127,6 +127,7 @@ export class SelectionService extends Disposable implements ISelectionService {
|
||||
@ICoreService private readonly _coreService: ICoreService,
|
||||
@IMouseCoordsService private readonly _mouseCoordsService: IMouseCoordsService,
|
||||
@IOptionsService private readonly _optionsService: IOptionsService,
|
||||
@IMouseStateService private readonly _mouseStateService: IMouseStateService,
|
||||
@IRenderService private readonly _renderService: IRenderService,
|
||||
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService
|
||||
) {
|
||||
@@ -434,6 +435,10 @@ export class SelectionService extends Disposable implements ISelectionService {
|
||||
* @param event The mouse event.
|
||||
*/
|
||||
public shouldForceSelection(event: MouseEvent): boolean {
|
||||
if (this._optionsService.rawOptions.mouseEventsRequireAlt && this._mouseStateService.areMouseEventsActive) {
|
||||
return !event.altKey;
|
||||
}
|
||||
|
||||
if (Browser.isMac) {
|
||||
return event.altKey && this._optionsService.rawOptions.macOptionClickForcesSelection;
|
||||
}
|
||||
@@ -458,6 +463,10 @@ export class SelectionService extends Disposable implements ISelectionService {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._optionsService.rawOptions.mouseEventsRequireAlt && this._mouseStateService.areMouseEventsActive && event.altKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow selection when using a specific modifier key, even when disabled
|
||||
if (!this._enabled) {
|
||||
if (!this.shouldForceSelection(event)) {
|
||||
@@ -596,6 +605,9 @@ export class SelectionService extends Disposable implements ISelectionService {
|
||||
* @param event the mouse or keyboard event
|
||||
*/
|
||||
public shouldColumnSelect(event: KeyboardEvent | MouseEvent): boolean {
|
||||
if (this._optionsService.rawOptions.mouseEventsRequireAlt && this._mouseStateService.areMouseEventsActive) {
|
||||
return false;
|
||||
}
|
||||
return event.altKey && !(Browser.isMac && this._optionsService.rawOptions.macOptionClickForcesSelection);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ export const DEFAULT_OPTIONS: Readonly<Required<ITerminalOptions>> = {
|
||||
macOptionIsMeta: false,
|
||||
macOptionClickForcesSelection: false,
|
||||
minimumContrastRatio: 1,
|
||||
mouseEventsRequireAlt: false,
|
||||
disableStdin: false,
|
||||
allowProposedApi: false,
|
||||
allowTransparency: false,
|
||||
|
||||
@@ -234,6 +234,7 @@ export interface ITerminalOptions {
|
||||
macOptionIsMeta?: boolean;
|
||||
macOptionClickForcesSelection?: boolean;
|
||||
minimumContrastRatio?: number;
|
||||
mouseEventsRequireAlt?: boolean;
|
||||
reflowCursorLine?: boolean;
|
||||
rescaleOverlappingGlyphs?: boolean;
|
||||
rightClickSelectsWord?: boolean;
|
||||
|
||||
Vendored
+11
@@ -136,6 +136,17 @@ declare module '@xterm/headless' {
|
||||
*/
|
||||
minimumContrastRatio?: number;
|
||||
|
||||
/**
|
||||
* When enabled and the terminal is in mouse events mode, mouse click, drag,
|
||||
* and move events are only sent to the underlying application when the alt
|
||||
* key is held. The alt key is not included in the mouse reports sent to the
|
||||
* application. Wheel events are not affected. This allows normal text
|
||||
* selection by default while still supporting application mouse interaction
|
||||
* and scrolling when holding alt. When enabled, this takes precedence over
|
||||
* `macOptionClickForcesSelection`.
|
||||
*/
|
||||
mouseEventsRequireAlt?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to reflow the line containing the cursor when the terminal is
|
||||
* resized. Defaults to false, because shells usually handle this
|
||||
|
||||
Vendored
+11
@@ -206,6 +206,17 @@ declare module '@xterm/xterm' {
|
||||
*/
|
||||
minimumContrastRatio?: number;
|
||||
|
||||
/**
|
||||
* When enabled and the terminal is in mouse events mode, mouse click, drag,
|
||||
* and move events are only sent to the underlying application when the alt
|
||||
* key is held. The alt key is not included in the mouse reports sent to the
|
||||
* application. Wheel events are not affected. This allows normal text
|
||||
* selection by default while still supporting application mouse interaction
|
||||
* and scrolling when holding alt. When enabled, this takes precedence over
|
||||
* `macOptionClickForcesSelection`.
|
||||
*/
|
||||
mouseEventsRequireAlt?: boolean;
|
||||
|
||||
/**
|
||||
* Control various quirks features that are either non-standard or standard
|
||||
* in but generally rejected in modern terminals.
|
||||
|
||||
Reference in New Issue
Block a user