mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Add bg+powerline background blend behavior
When a with bg is selected, the cell's regular background will be blended with 50% opacity selectionBackground in order to retain the bg color info as well as getting the color to change and getting decent contrast. This commit also fixes a terrible, nasty bug where the standalone shared renderer tests were causing the terminal to open multiple times and not get the WebGL addon activated the second time. So some tests were actually testing the DOM renderer :o Fixes #4918
This commit is contained in:
@@ -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';
|
||||
@@ -492,7 +492,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,
|
||||
skipCanvasExceptions: true
|
||||
} as any;
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
ctx = await createTestContext(browser);
|
||||
ctxWrapper.value = ctx;
|
||||
|
||||
@@ -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]);
|
||||
});
|
||||
});
|
||||
@@ -1206,30 +1245,32 @@ enum CellColorPosition {
|
||||
* 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();
|
||||
test.describe('standalone tests', () => {
|
||||
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;
|
||||
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