Merge branch 'master' into patch-1

This commit is contained in:
An Phi
2025-01-06 10:28:27 -05:00
committed by GitHub
14 changed files with 111 additions and 71 deletions
+3 -1
View File
@@ -437,7 +437,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
this.screenElement.appendChild(this._helperContainer);
fragment.appendChild(this.screenElement);
this.textarea = this._document.createElement('textarea');
const textarea = this.textarea = this._document.createElement('textarea');
this.textarea.classList.add('xterm-helper-textarea');
this.textarea.setAttribute('aria-label', Strings.promptLabel.get());
if (!Browser.isChromeOS) {
@@ -449,6 +449,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
this.textarea.setAttribute('autocapitalize', 'off');
this.textarea.setAttribute('spellcheck', 'false');
this.textarea.tabIndex = 0;
this._register(this.optionsService.onSpecificOptionChange('disableStdin', () => textarea.readOnly = this.optionsService.rawOptions.disableStdin));
this.textarea.readOnly = this.optionsService.rawOptions.disableStdin;
// 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.
+8 -3
View File
@@ -13,7 +13,7 @@ import { ICharSizeService, ICoreBrowserService, IThemeService } from 'browser/se
import { ILinkifier2, ILinkifierEvent, ITerminal, ReadonlyColorSet } from 'browser/Types';
import { color } from 'common/Color';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IBufferService, IInstantiationService, IOptionsService } from 'common/services/Services';
import { IBufferService, ICoreService, IInstantiationService, IOptionsService } from 'common/services/Services';
import { Emitter } from 'vs/base/common/event';
@@ -59,6 +59,7 @@ export class DomRenderer extends Disposable implements IRenderer {
@ICharSizeService private readonly _charSizeService: ICharSizeService,
@IOptionsService private readonly _optionsService: IOptionsService,
@IBufferService private readonly _bufferService: IBufferService,
@ICoreService private readonly _coreService: ICoreService,
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
@IThemeService private readonly _themeService: IThemeService
) {
@@ -161,6 +162,10 @@ export class DomRenderer extends Disposable implements IRenderer {
// Base CSS
let styles =
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} {` +
// Disabling pointer events circumvents a browser behavior that prevents `click` events from
// being delivered if the target element is replaced during the click. This happened due to
// refresh() being called during the mousedown handler to start a selection.
` pointer-events: none;` +
` color: ${colors.foreground.css};` +
` font-family: ${this._optionsService.rawOptions.fontFamily};` +
` font-size: ${this._optionsService.rawOptions.fontSize}px;` +
@@ -437,8 +442,8 @@ export class DomRenderer extends Disposable implements IRenderer {
const buffer = this._bufferService.buffer;
const cursorAbsoluteY = buffer.ybase + buffer.y;
const cursorX = Math.min(buffer.x, this._bufferService.cols - 1);
const cursorBlink = this._optionsService.rawOptions.cursorBlink;
const cursorStyle = this._optionsService.rawOptions.cursorStyle;
const cursorBlink = this._coreService.decPrivateModes.cursorBlink ?? this._optionsService.rawOptions.cursorBlink;
const cursorStyle = this._coreService.decPrivateModes.cursorStyle ?? this._optionsService.rawOptions.cursorStyle;
const cursorInactiveStyle = this._optionsService.rawOptions.cursorInactiveStyle;
for (let y = start; y <= end; y++) {
+2 -2
View File
@@ -82,8 +82,8 @@ export class ThemeService extends Disposable implements IThemeService {
const colors = this._colors;
colors.foreground = parseColor(theme.foreground, DEFAULT_FOREGROUND);
colors.background = parseColor(theme.background, DEFAULT_BACKGROUND);
colors.cursor = parseColor(theme.cursor, DEFAULT_CURSOR);
colors.cursorAccent = parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT);
colors.cursor = color.blend(colors.background, parseColor(theme.cursor, DEFAULT_CURSOR));
colors.cursorAccent = color.blend(colors.background, parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT));
colors.selectionBackgroundTransparent = parseColor(theme.selectionBackground, DEFAULT_SELECTION);
colors.selectionBackgroundOpaque = color.blend(colors.background, colors.selectionBackgroundTransparent);
colors.selectionInactiveBackgroundTransparent = parseColor(theme.selectionInactiveBackground, colors.selectionBackgroundTransparent);
+14 -14
View File
@@ -202,38 +202,38 @@ describe('InputHandler', () => {
describe('setCursorStyle', () => {
it('should call Terminal.setOption with correct params', () => {
inputHandler.setCursorStyle(Params.fromArray([0]));
assert.equal(optionsService.options['cursorStyle'], 'block');
assert.equal(optionsService.options['cursorBlink'], true);
assert.equal(coreService.decPrivateModes.cursorStyle, undefined);
assert.equal(coreService.decPrivateModes.cursorBlink, undefined);
optionsService.options = clone(DEFAULT_OPTIONS);
inputHandler.setCursorStyle(Params.fromArray([1]));
assert.equal(optionsService.options['cursorStyle'], 'block');
assert.equal(optionsService.options['cursorBlink'], true);
assert.equal(coreService.decPrivateModes.cursorStyle, 'block');
assert.equal(coreService.decPrivateModes.cursorBlink, true);
optionsService.options = clone(DEFAULT_OPTIONS);
inputHandler.setCursorStyle(Params.fromArray([2]));
assert.equal(optionsService.options['cursorStyle'], 'block');
assert.equal(optionsService.options['cursorBlink'], false);
assert.equal(coreService.decPrivateModes.cursorStyle, 'block');
assert.equal(coreService.decPrivateModes.cursorBlink, false);
optionsService.options = clone(DEFAULT_OPTIONS);
inputHandler.setCursorStyle(Params.fromArray([3]));
assert.equal(optionsService.options['cursorStyle'], 'underline');
assert.equal(optionsService.options['cursorBlink'], true);
assert.equal(coreService.decPrivateModes.cursorStyle, 'underline');
assert.equal(coreService.decPrivateModes.cursorBlink, true);
optionsService.options = clone(DEFAULT_OPTIONS);
inputHandler.setCursorStyle(Params.fromArray([4]));
assert.equal(optionsService.options['cursorStyle'], 'underline');
assert.equal(optionsService.options['cursorBlink'], false);
assert.equal(coreService.decPrivateModes.cursorStyle, 'underline');
assert.equal(coreService.decPrivateModes.cursorBlink, false);
optionsService.options = clone(DEFAULT_OPTIONS);
inputHandler.setCursorStyle(Params.fromArray([5]));
assert.equal(optionsService.options['cursorStyle'], 'bar');
assert.equal(optionsService.options['cursorBlink'], true);
assert.equal(coreService.decPrivateModes.cursorStyle, 'bar');
assert.equal(coreService.decPrivateModes.cursorBlink, true);
optionsService.options = clone(DEFAULT_OPTIONS);
inputHandler.setCursorStyle(Params.fromArray([6]));
assert.equal(optionsService.options['cursorStyle'], 'bar');
assert.equal(optionsService.options['cursorBlink'], false);
assert.equal(coreService.decPrivateModes.cursorStyle, 'bar');
assert.equal(coreService.decPrivateModes.cursorBlink, false);
});
});
describe('setMode', () => {
+29 -23
View File
@@ -2714,7 +2714,7 @@ export class InputHandler extends Disposable implements IInputHandler {
/**
* CSI Ps SP q Set cursor style (DECSCUSR, VT520).
* Ps = 0 -> blinking block.
* Ps = 0 -> reset to option.
* Ps = 1 -> blinking block (default).
* Ps = 2 -> steady block.
* Ps = 3 -> blinking underline.
@@ -2724,31 +2724,37 @@ export class InputHandler extends Disposable implements IInputHandler {
*
* @vt: #Y CSI DECSCUSR "Set Cursor Style" "CSI Ps SP q" "Set cursor style."
* Supported cursor styles:
* - empty, 0 or 1: steady block
* - 2: blink block
* - 3: steady underline
* - 4: blink underline
* - 5: steady bar
* - 6: blink bar
* - 0: reset to option
* - empty, 1: blinking block
* - 2: steady block
* - 3: blinking underline
* - 4: steady underline
* - 5: blinking bar
* - 6: steady bar
*/
public setCursorStyle(params: IParams): boolean {
const param = params.params[0] || 1;
switch (param) {
case 1:
case 2:
this._optionsService.options.cursorStyle = 'block';
break;
case 3:
case 4:
this._optionsService.options.cursorStyle = 'underline';
break;
case 5:
case 6:
this._optionsService.options.cursorStyle = 'bar';
break;
const param = params.length === 0 ? 1 : params.params[0];
if (param === 0) {
this._coreService.decPrivateModes.cursorStyle = undefined;
this._coreService.decPrivateModes.cursorBlink = undefined;
} else {
switch (param) {
case 1:
case 2:
this._coreService.decPrivateModes.cursorStyle = 'block';
break;
case 3:
case 4:
this._coreService.decPrivateModes.cursorStyle = 'underline';
break;
case 5:
case 6:
this._coreService.decPrivateModes.cursorStyle = 'bar';
break;
}
const isBlinking = param % 2 === 1;
this._coreService.decPrivateModes.cursorBlink = isBlinking;
}
const isBlinking = param % 2 === 1;
this._optionsService.options.cursorBlink = isBlinking;
return true;
}
+2
View File
@@ -89,6 +89,8 @@ export class MockCoreService implements ICoreService {
applicationCursorKeys: false,
applicationKeypad: false,
bracketedPasteMode: false,
cursorBlink: undefined,
cursorStyle: undefined,
origin: false,
reverseWraparound: false,
sendFocus: false,
+2
View File
@@ -268,6 +268,8 @@ export interface IDecPrivateModes {
applicationCursorKeys: boolean;
applicationKeypad: boolean;
bracketedPasteMode: boolean;
cursorBlink: boolean | undefined;
cursorStyle: CursorStyle | undefined;
origin: boolean;
reverseWraparound: boolean;
sendFocus: boolean;
+2
View File
@@ -17,6 +17,8 @@ const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({
applicationCursorKeys: false,
applicationKeypad: false,
bracketedPasteMode: false,
cursorBlink: undefined,
cursorStyle: undefined,
origin: false,
reverseWraparound: false,
sendFocus: false,
+1 -1
View File
@@ -67,7 +67,7 @@ export class InstantiationService implements IInstantiationService {
for (const dependency of serviceDependencies) {
const service = this._services.get(dependency.id);
if (!service) {
throw new Error(`[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id}.`);
throw new Error(`[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id._id}.`);
}
serviceArgs.push(service);
}
+1 -1
View File
@@ -33,7 +33,7 @@ export function createDecorator<T>(id: string): IServiceIdentifier<T> {
storeServiceDependency(decorator, target, index);
};
decorator.toString = () => id;
decorator._id = id;
serviceRegistry.set(id, decorator);
return decorator;
+1
View File
@@ -124,6 +124,7 @@ export interface ICharsetService {
export interface IServiceIdentifier<T> {
(...args: any[]): void;
type: T;
_id: string;
}
export interface IBrandedService {