mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #4920 from Tyriar/tyriar/bg_blend
Add bg+powerline background blend behavior
This commit is contained in:
@@ -28,5 +28,10 @@ test.describe('Canvas Renderer Integration Tests', () => {
|
||||
test.skip(({ browserName }) => browserName === 'webkit');
|
||||
|
||||
injectSharedRendererTests(ctxWrapper);
|
||||
injectSharedRendererTestsStandalone(ctxWrapper);
|
||||
injectSharedRendererTestsStandalone(ctxWrapper, async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.addon = new window.CanvasAddon(true);
|
||||
window.term.loadAddon(window.addon);
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,5 +29,10 @@ test.describe('WebGL Renderer Integration Tests', async () => {
|
||||
}
|
||||
|
||||
injectSharedRendererTests(ctxWrapper);
|
||||
injectSharedRendererTestsStandalone(ctxWrapper);
|
||||
injectSharedRendererTestsStandalone(ctxWrapper, async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.addon = new window.WebglAddon(true);
|
||||
window.term.loadAddon(window.addon);
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ import { ICoreService, IDecorationService, IOptionsService } from 'common/servic
|
||||
import { color, rgba } from 'common/Color';
|
||||
import { ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
||||
import { JoinedCellData } from 'browser/services/CharacterJoinerService';
|
||||
import { excludeFromContrastRatioDemands } from 'browser/renderer/shared/RendererUtils';
|
||||
import { treatGlyphAsBackgroundColor } from 'browser/renderer/shared/RendererUtils';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { WidthCache } from 'browser/renderer/dom/WidthCache';
|
||||
import { IColorContrastCache } from 'browser/Types';
|
||||
@@ -458,7 +458,7 @@ export class DomRendererRowFactory {
|
||||
}
|
||||
|
||||
private _applyMinimumContrast(element: HTMLElement, bg: IColor, fg: IColor, cell: ICellData, bgOverride: IColor | undefined, fgOverride: IColor | undefined): boolean {
|
||||
if (this._optionsService.rawOptions.minimumContrastRatio === 1 || excludeFromContrastRatioDemands(cell.getCode())) {
|
||||
if (this._optionsService.rawOptions.minimumContrastRatio === 1 || treatGlyphAsBackgroundColor(cell.getCode())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import { Attributes, BgFlags, ExtFlags, FgFlags, NULL_CELL_CODE, UnderlineStyle
|
||||
import { IDecorationService, IOptionsService } from 'common/services/Services';
|
||||
import { ICellData } from 'common/Types';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import { rgba } from 'common/Color';
|
||||
import { treatGlyphAsBackgroundColor } from 'browser/renderer/shared/RendererUtils';
|
||||
|
||||
// Work variables to avoid garbage collection
|
||||
let $fg = 0;
|
||||
@@ -65,11 +67,11 @@ export class CellColorResolver {
|
||||
// Apply decorations on the bottom layer
|
||||
this._decorationService.forEachDecorationAtCell(x, y, 'bottom', d => {
|
||||
if (d.backgroundColorRGB) {
|
||||
$bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF;
|
||||
$bg = d.backgroundColorRGB.rgba >> 8 & Attributes.RGB_MASK;
|
||||
$hasBg = true;
|
||||
}
|
||||
if (d.foregroundColorRGB) {
|
||||
$fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF;
|
||||
$fg = d.foregroundColorRGB.rgba >> 8 & Attributes.RGB_MASK;
|
||||
$hasFg = true;
|
||||
}
|
||||
});
|
||||
@@ -77,10 +79,94 @@ export class CellColorResolver {
|
||||
// Apply the selection color if needed
|
||||
$isSelected = this._selectionRenderModel.isCellSelected(this._terminal, x, y);
|
||||
if ($isSelected) {
|
||||
$bg = (this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba >> 8 & 0xFFFFFF;
|
||||
// If the cell has a bg color, retain the color by blending it with the selection color
|
||||
if (
|
||||
(this.result.fg & FgFlags.INVERSE) ||
|
||||
(this.result.bg & Attributes.CM_MASK) !== Attributes.CM_DEFAULT
|
||||
) {
|
||||
// Resolve the standard bg color
|
||||
if (this.result.fg & FgFlags.INVERSE) {
|
||||
switch (this.result.fg & Attributes.CM_MASK) {
|
||||
case Attributes.CM_P16:
|
||||
case Attributes.CM_P256:
|
||||
$bg = this._themeService.colors.ansi[this.result.fg & Attributes.PCOLOR_MASK].rgba;
|
||||
break;
|
||||
case Attributes.CM_RGB:
|
||||
$bg = (this.result.fg & Attributes.RGB_MASK) << 8 | 0xFF;
|
||||
break;
|
||||
case Attributes.CM_DEFAULT:
|
||||
default:
|
||||
$bg = this._themeService.colors.foreground.rgba;
|
||||
}
|
||||
} else {
|
||||
switch (this.result.bg & Attributes.CM_MASK) {
|
||||
case Attributes.CM_P16:
|
||||
case Attributes.CM_P256:
|
||||
$bg = this._themeService.colors.ansi[this.result.bg & Attributes.PCOLOR_MASK].rgba;
|
||||
break;
|
||||
case Attributes.CM_RGB:
|
||||
$bg = this.result.bg & Attributes.RGB_MASK << 8 | 0xFF;
|
||||
break;
|
||||
// No need to consider default bg color here as it's not possible
|
||||
}
|
||||
}
|
||||
// Blend with selection bg color
|
||||
$bg = rgba.blend(
|
||||
$bg,
|
||||
((this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba & 0xFFFFFF00) | 0x80
|
||||
) >> 8 & Attributes.RGB_MASK;
|
||||
} else {
|
||||
$bg = (this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba >> 8 & Attributes.RGB_MASK;
|
||||
}
|
||||
$hasBg = true;
|
||||
|
||||
// Apply explicit selection foreground if present
|
||||
if ($colors.selectionForeground) {
|
||||
$fg = $colors.selectionForeground.rgba >> 8 & 0xFFFFFF;
|
||||
$fg = $colors.selectionForeground.rgba >> 8 & Attributes.RGB_MASK;
|
||||
$hasFg = true;
|
||||
}
|
||||
|
||||
// Overwrite fg as bg if it's a special decorative glyph (eg. powerline)
|
||||
if (treatGlyphAsBackgroundColor(cell.getCode())) {
|
||||
// Inverse default background should be treated as transparent
|
||||
if (
|
||||
(this.result.fg & FgFlags.INVERSE) &&
|
||||
(this.result.bg & Attributes.CM_MASK) === Attributes.CM_DEFAULT
|
||||
) {
|
||||
$fg = (this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba >> 8 & Attributes.RGB_MASK;
|
||||
} else {
|
||||
|
||||
if (this.result.fg & FgFlags.INVERSE) {
|
||||
switch (this.result.bg & Attributes.CM_MASK) {
|
||||
case Attributes.CM_P16:
|
||||
case Attributes.CM_P256:
|
||||
$fg = this._themeService.colors.ansi[this.result.bg & Attributes.PCOLOR_MASK].rgba;
|
||||
break;
|
||||
case Attributes.CM_RGB:
|
||||
$fg = this.result.bg & Attributes.RGB_MASK << 8 | 0xFF;
|
||||
break;
|
||||
// No need to consider default bg color here as it's not possible
|
||||
}
|
||||
} else {
|
||||
switch (this.result.fg & Attributes.CM_MASK) {
|
||||
case Attributes.CM_P16:
|
||||
case Attributes.CM_P256:
|
||||
$fg = this._themeService.colors.ansi[this.result.fg & Attributes.PCOLOR_MASK].rgba;
|
||||
break;
|
||||
case Attributes.CM_RGB:
|
||||
$fg = (this.result.fg & Attributes.RGB_MASK) << 8 | 0xFF;
|
||||
break;
|
||||
case Attributes.CM_DEFAULT:
|
||||
default:
|
||||
$fg = this._themeService.colors.foreground.rgba;
|
||||
}
|
||||
}
|
||||
|
||||
$fg = rgba.blend(
|
||||
$fg,
|
||||
((this._coreBrowserService.isFocused ? $colors.selectionBackgroundOpaque : $colors.selectionInactiveBackgroundOpaque).rgba & 0xFFFFFF00) | 0x80
|
||||
) >> 8 & Attributes.RGB_MASK;
|
||||
}
|
||||
$hasFg = true;
|
||||
}
|
||||
}
|
||||
@@ -88,11 +174,11 @@ export class CellColorResolver {
|
||||
// Apply decorations on the top layer
|
||||
this._decorationService.forEachDecorationAtCell(x, y, 'top', d => {
|
||||
if (d.backgroundColorRGB) {
|
||||
$bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF;
|
||||
$bg = d.backgroundColorRGB.rgba >> 8 & Attributes.RGB_MASK;
|
||||
$hasBg = true;
|
||||
}
|
||||
if (d.foregroundColorRGB) {
|
||||
$fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF;
|
||||
$fg = d.foregroundColorRGB.rgba >> 8 & Attributes.RGB_MASK;
|
||||
$hasFg = true;
|
||||
}
|
||||
});
|
||||
@@ -119,7 +205,7 @@ export class CellColorResolver {
|
||||
if ($hasBg && !$hasFg) {
|
||||
// Resolve bg color type (default color has a different meaning in fg vs bg)
|
||||
if ((this.result.bg & Attributes.CM_MASK) === Attributes.CM_DEFAULT) {
|
||||
$fg = (this.result.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | (($colors.background.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB;
|
||||
$fg = (this.result.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | (($colors.background.rgba >> 8 & Attributes.RGB_MASK) & Attributes.RGB_MASK) | Attributes.CM_RGB;
|
||||
} else {
|
||||
$fg = (this.result.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | this.result.bg & (Attributes.RGB_MASK | Attributes.CM_MASK);
|
||||
}
|
||||
@@ -128,7 +214,7 @@ export class CellColorResolver {
|
||||
if (!$hasBg && $hasFg) {
|
||||
// Resolve bg color type (default color has a different meaning in fg vs bg)
|
||||
if ((this.result.fg & Attributes.CM_MASK) === Attributes.CM_DEFAULT) {
|
||||
$bg = (this.result.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | (($colors.foreground.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB;
|
||||
$bg = (this.result.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | (($colors.foreground.rgba >> 8 & Attributes.RGB_MASK) & Attributes.RGB_MASK) | Attributes.CM_RGB;
|
||||
} else {
|
||||
$bg = (this.result.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | this.result.fg & (Attributes.RGB_MASK | Attributes.CM_MASK);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ function isBoxOrBlockGlyph(codepoint: number): boolean {
|
||||
return 0x2500 <= codepoint && codepoint <= 0x259F;
|
||||
}
|
||||
|
||||
export function excludeFromContrastRatioDemands(codepoint: number): boolean {
|
||||
export function treatGlyphAsBackgroundColor(codepoint: number): boolean {
|
||||
return isPowerlineGlyph(codepoint) || isBoxOrBlockGlyph(codepoint);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { IColorContrastCache } from 'browser/Types';
|
||||
import { DIM_OPACITY, TEXT_BASELINE } from 'browser/renderer/shared/Constants';
|
||||
import { tryDrawCustomChar } from 'browser/renderer/shared/CustomGlyphs';
|
||||
import { computeNextVariantOffset, excludeFromContrastRatioDemands, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||
import { computeNextVariantOffset, treatGlyphAsBackgroundColor, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||
import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from 'browser/renderer/shared/Types';
|
||||
import { NULL_COLOR, color, rgba } from 'common/Color';
|
||||
import { EventEmitter } from 'common/EventEmitter';
|
||||
@@ -490,7 +490,7 @@ export class TextureAtlas implements ITextureAtlas {
|
||||
|
||||
const powerlineGlyph = chars.length === 1 && isPowerlineGlyph(chars.charCodeAt(0));
|
||||
const restrictedPowerlineGlyph = chars.length === 1 && isRestrictedPowerlineGlyph(chars.charCodeAt(0));
|
||||
const foregroundColor = this._getForegroundColor(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, dim, bold, excludeFromContrastRatioDemands(chars.charCodeAt(0)));
|
||||
const foregroundColor = this._getForegroundColor(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, dim, bold, treatGlyphAsBackgroundColor(chars.charCodeAt(0)));
|
||||
this._tmpCtx.fillStyle = foregroundColor.css;
|
||||
|
||||
// For powerline glyphs left/top padding is excluded (https://github.com/microsoft/vscode/issues/120129)
|
||||
|
||||
@@ -271,6 +271,27 @@ describe('Color', () => {
|
||||
});
|
||||
|
||||
describe('rgba', () => {
|
||||
describe('blend', () => {
|
||||
it('should blend colors based on the alpha channel', () => {
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF00), 0x000000FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF10), 0x101010FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF20), 0x202020FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF30), 0x303030FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF40), 0x404040FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF50), 0x505050FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF60), 0x606060FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF70), 0x707070FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF80), 0x808080FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFF90), 0x909090FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFFA0), 0xA0A0A0FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFFB0), 0xB0B0B0FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFFC0), 0xC0C0C0FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFFD0), 0xD0D0D0FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFFE0), 0xE0E0E0FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFFF0), 0xF0F0F0FF);
|
||||
assert.deepEqual(rgba.blend(0x000000FF, 0xFFFFFFFF), 0xFFFFFFFF);
|
||||
});
|
||||
});
|
||||
describe('ensureContrastRatio', () => {
|
||||
it('should return undefined if the color already meets the contrast ratio (black bg)', () => {
|
||||
assert.equal(rgba.ensureContrastRatio(0x000000ff, 0x606060ff, 1), undefined);
|
||||
|
||||
@@ -245,6 +245,23 @@ export namespace rgb {
|
||||
* Helper functions where the source type is "rgba" (number: 0xrrggbbaa).
|
||||
*/
|
||||
export namespace rgba {
|
||||
export function blend(bg: number, fg: number): number {
|
||||
$a = (fg & 0xFF) / 0xFF;
|
||||
if ($a === 1) {
|
||||
return fg;
|
||||
}
|
||||
const fgR = (fg >> 24) & 0xFF;
|
||||
const fgG = (fg >> 16) & 0xFF;
|
||||
const fgB = (fg >> 8) & 0xFF;
|
||||
const bgR = (bg >> 24) & 0xFF;
|
||||
const bgG = (bg >> 16) & 0xFF;
|
||||
const bgB = (bg >> 8) & 0xFF;
|
||||
$r = bgR + Math.round((fgR - bgR) * $a);
|
||||
$g = bgG + Math.round((fgG - bgG) * $a);
|
||||
$b = bgB + Math.round((fgB - bgB) * $a);
|
||||
return channels.toRgba($r, $g, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a foreground color and a background color, either increase or reduce the luminance of the
|
||||
* foreground color until the specified contrast ratio is met. If pure white or black is hit
|
||||
|
||||
@@ -8,7 +8,10 @@ import { ITestContext, createTestContext, openTerminal } from './TestUtils';
|
||||
import { ISharedRendererTestContext, injectSharedRendererTestsStandalone, injectSharedRendererTests } from './SharedRendererTests';
|
||||
|
||||
let ctx: ITestContext;
|
||||
const ctxWrapper: ISharedRendererTestContext = { value: undefined } as any;
|
||||
const ctxWrapper: ISharedRendererTestContext = {
|
||||
value: undefined,
|
||||
skipDomExceptions: true
|
||||
} as any;
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
ctx = await createTestContext(browser);
|
||||
ctxWrapper.value = ctx;
|
||||
@@ -18,5 +21,5 @@ test.afterAll(async () => await ctx.page.close());
|
||||
|
||||
test.describe('DOM Renderer Integration Tests', () => {
|
||||
injectSharedRendererTests(ctxWrapper);
|
||||
injectSharedRendererTestsStandalone(ctxWrapper);
|
||||
injectSharedRendererTestsStandalone(ctxWrapper, () => {});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ITestContext, MaybeAsync, openTerminal, pollFor, pollForApproximate } f
|
||||
export interface ISharedRendererTestContext {
|
||||
value: ITestContext;
|
||||
skipCanvasExceptions?: boolean;
|
||||
skipDomExceptions?: boolean;
|
||||
}
|
||||
|
||||
export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void {
|
||||
@@ -945,7 +946,7 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 255, 0, 255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [255, 0, 0, 255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [0, 255, 0, 255]);
|
||||
await ctx.value.page.evaluate(`window.term.selectAll()`);
|
||||
await ctx.value.proxy.selectAll();
|
||||
frameDetails = undefined;
|
||||
// Selection only cell needs to be first to ensure renderer has kicked in
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
|
||||
@@ -965,7 +966,7 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
|
||||
// Check both the cursor line and another line
|
||||
await ctx.value.proxy.writeln('_ ');
|
||||
await ctx.value.proxy.write('_ ');
|
||||
await ctx.value.page.evaluate(`window.term.selectAll()`);
|
||||
await ctx.value.proxy.selectAll();
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [128, 0, 0, 255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [128, 0, 0, 255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [128, 0, 0, 255]);
|
||||
@@ -980,6 +981,44 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
|
||||
});
|
||||
});
|
||||
|
||||
(ctx.skipCanvasExceptions || ctx.skipDomExceptions ? test.describe.skip : test.describe)('selection blending', () => {
|
||||
test('background', async () => {
|
||||
const theme: ITheme = {
|
||||
red: '#CC0000',
|
||||
selectionBackground: '#FFFFFF'
|
||||
};
|
||||
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
||||
await ctx.value.proxy.focus();
|
||||
await ctx.value.proxy.writeln('\x1b[41m red bg');
|
||||
await ctx.value.proxy.writeln('\x1b[7m inverse');
|
||||
await ctx.value.proxy.writeln('\x1b[31;7m red fg inverse');
|
||||
await ctx.value.proxy.selectAll();
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [230,128,128,255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [255,255,255,255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 3), [230,128,128,255]);
|
||||
});
|
||||
test('powerline decorative symbols', async () => {
|
||||
const theme: ITheme = {
|
||||
red: '#CC0000',
|
||||
green: '#00CC00',
|
||||
selectionBackground: '#FFFFFF'
|
||||
};
|
||||
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
||||
await ctx.value.proxy.focus();
|
||||
await ctx.value.proxy.writeln('\u{E0B4} plain\x1b[0m');
|
||||
await ctx.value.proxy.writeln('\x1b[31;42m\u{E0B4} red fg green bg\x1b[0m');
|
||||
await ctx.value.proxy.writeln('\x1b[32;41m\u{E0B4} green fg red bg\x1b[0m');
|
||||
await ctx.value.proxy.writeln('\x1b[31;42;7m\u{E0B4} red fg green bg inverse\x1b[0m');
|
||||
await ctx.value.proxy.writeln('\x1b[32;41;7m\u{E0B4} green fg red bg inverse\x1b[0m');
|
||||
await ctx.value.proxy.selectAll();
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255,255,255,255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [230, 128, 128, 255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 3), [128, 230, 128, 255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 4), [128, 230, 128, 255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 5), [230, 128, 128, 255]);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('allowTransparency', async () => {
|
||||
test.beforeEach(() => ctx.value.page.evaluate(`term.options.allowTransparency = true`));
|
||||
|
||||
@@ -1003,7 +1042,7 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
|
||||
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
||||
const data = `\x1b[7m■\x1b[0m`;
|
||||
await ctx.value.proxy.write( data);
|
||||
await ctx.value.page.evaluate(`window.term.selectAll()`);
|
||||
await ctx.value.proxy.selectAll();
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255, 0, 0, 255]);
|
||||
});
|
||||
});
|
||||
@@ -1092,7 +1131,7 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
|
||||
});
|
||||
|
||||
test.describe('regression tests', () => {
|
||||
test('#4736: inactive selection background should replace regular cell background color', async () => {
|
||||
(ctx.skipCanvasExceptions ? test.skip : test)('#4736: inactive selection background should replace regular cell background color', async () => {
|
||||
const theme: ITheme = {
|
||||
selectionBackground: '#FF0000',
|
||||
selectionInactiveBackground: '#0000FF'
|
||||
@@ -1126,7 +1165,8 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [0, 0, 0, 255]);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [0, 0, 0, 255]);
|
||||
});
|
||||
test('#4759: minimum contrast ratio should be respected on inverse text', async () => {
|
||||
// HACK: It's not clear why DOM is failing here
|
||||
(ctx.skipDomExceptions ? test.skip : test)('#4759: minimum contrast ratio should be respected on inverse text', async () => {
|
||||
const theme: ITheme = {
|
||||
foreground: '#aaaaaa',
|
||||
background: '#333333'
|
||||
@@ -1205,31 +1245,34 @@ enum CellColorPosition {
|
||||
* This is much slower than just calling `Terminal.reset` but testing some features needs this
|
||||
* treatment.
|
||||
*/
|
||||
export function injectSharedRendererTestsStandalone(ctx: ISharedRendererTestContext): void {
|
||||
test.beforeEach(async () => {
|
||||
// Recreate terminal
|
||||
await openTerminal(ctx.value);
|
||||
ctx.value.page.evaluate(`
|
||||
window.term.options.minimumContrastRatio = 1;
|
||||
window.term.options.allowTransparency = false;
|
||||
window.term.options.theme = undefined;
|
||||
`);
|
||||
// Clear the cached screenshot before each test
|
||||
frameDetails = undefined;
|
||||
});
|
||||
test.describe('regression tests', () => {
|
||||
test('#4790: cursor should not be displayed before focusing', async () => {
|
||||
const theme: ITheme = {
|
||||
cursor: '#0000FF'
|
||||
};
|
||||
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 255]);
|
||||
await ctx.value.proxy.focus();
|
||||
export function injectSharedRendererTestsStandalone(ctx: ISharedRendererTestContext, setupCb: () => Promise<void> | void): void {
|
||||
test.describe('standalone tests', () => {
|
||||
test.beforeEach(async () => {
|
||||
// Recreate terminal
|
||||
await openTerminal(ctx.value);
|
||||
await ctx.value.page.evaluate(`
|
||||
window.term.options.minimumContrastRatio = 1;
|
||||
window.term.options.allowTransparency = false;
|
||||
window.term.options.theme = undefined;
|
||||
`);
|
||||
await setupCb();
|
||||
// Clear the cached screenshot before each test
|
||||
frameDetails = undefined;
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
|
||||
await ctx.value.proxy.blur();
|
||||
frameDetails = undefined;
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 255]);
|
||||
});
|
||||
test.describe('regression tests', () => {
|
||||
test('#4790: cursor should not be displayed before focusing', async () => {
|
||||
const theme: ITheme = {
|
||||
cursor: '#0000FF'
|
||||
};
|
||||
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 255]);
|
||||
await ctx.value.proxy.focus();
|
||||
frameDetails = undefined;
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
|
||||
await ctx.value.proxy.blur();
|
||||
frameDetails = undefined;
|
||||
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 255]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user