diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 6d84bd26..c42c0067 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -412,18 +412,32 @@ export class WebglRenderer extends Disposable implements IRenderer { // ahead of time in order to use the correct cache key if (bgOverride !== undefined) { // Non-RGB attributes from model + override + force RGB color mode - if (this._workColors.fg & FgFlags.INVERSE) { - bgOverride = (this._workColors.bg & ~Attributes.RGB_MASK) | (fgOverride !== undefined ? fgOverride : this._workColors.fg) | Attributes.CM_RGB; - } else { - bgOverride = (this._workColors.bg & ~Attributes.RGB_MASK) | bgOverride | Attributes.CM_RGB; - } + bgOverride = (this._workCell.bg & ~Attributes.RGB_MASK) | bgOverride | Attributes.CM_RGB; } if (fgOverride !== undefined) { // Non-RGB attributes from model + force disable inverse + override + force RGB color mode - if (this._workColors.fg & FgFlags.INVERSE) { - fgOverride = (this._workColors.fg & ~Attributes.RGB_MASK & ~FgFlags.INVERSE) | (bgOverride !== undefined ? bgOverride : this._workColors.bg) | Attributes.CM_RGB; - } else { - fgOverride = (this._workColors.fg & ~Attributes.RGB_MASK & ~FgFlags.INVERSE) | fgOverride | Attributes.CM_RGB; + fgOverride = (this._workCell.fg & ~Attributes.RGB_MASK & ~FgFlags.INVERSE) | fgOverride | Attributes.CM_RGB; + } + + // Handle case where inverse was specified by only one of bgOverride or fgOverride was set, + // resolving the other inverse color and setting the inverse flag if needed. + if (this._workColors.fg & FgFlags.INVERSE) { + if (bgOverride !== undefined && fgOverride === undefined) { + // Resolve bg color type (default color has a different meaning in fg vs bg) + debugger; + if ((this._workColors.bg & Attributes.CM_MASK) === Attributes.CM_DEFAULT) { + fgOverride = (this._workColors.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | ((this._colors.background.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB; + } else { + fgOverride = (this._workColors.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | this._workColors.bg & (Attributes.RGB_MASK | Attributes.CM_MASK); + } + } + if (bgOverride === undefined && fgOverride !== undefined) { + // Resolve bg color type (default color has a different meaning in fg vs bg) + if ((this._workColors.fg & Attributes.CM_MASK) === Attributes.CM_DEFAULT) { + bgOverride = (this._workColors.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | ((this._colors.foreground.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB; + } else { + bgOverride = (this._workColors.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | this._workColors.fg & (Attributes.RGB_MASK | Attributes.CM_MASK); + } } } diff --git a/addons/xterm-addon-webgl/test/WebglRenderer.api.ts b/addons/xterm-addon-webgl/test/WebglRenderer.api.ts index 15359409..cec1e3b1 100644 --- a/addons/xterm-addon-webgl/test/WebglRenderer.api.ts +++ b/addons/xterm-addon-webgl/test/WebglRenderer.api.ts @@ -875,9 +875,9 @@ describe('WebGL Renderer Integration Tests', async () => { }); }); - describe.only('decoration color overrides', async () => { + describe('decoration color overrides', async () => { if (areTestsEnabled) { - before(async () => setupBrowser({ rendererType: 'dom', allowTransparency: true })); + before(async () => setupBrowser({ rendererType: 'dom' })); after(async () => browser.close()); beforeEach(async () => page.evaluate(`window.term.reset()`)); } @@ -904,10 +904,24 @@ describe('WebGL Renderer Integration Tests', async () => { backgroundColor: '#0000ff' }); `); - const data = `\\x1b[7m█\\x1b0m`; + const data = `\\x1b[7m█\\x1b[0m`; await writeSync(page, data); await pollFor(page, () => getCellColor(1, 1), [255, 0, 0, 255]); }); + itWebgl('foregroundColor should ignore inverse (only fg on decoration)', async () => { + await page.evaluate(` + const marker = window.term.registerMarker(-window.term.buffer.active.cursorY); + window.term.registerDecoration({ + marker, + width: 2, + foregroundColor: '#ff0000' + }); + `); + const data = `\\x1b[7m█ \\x1b[0m`; + await writeSync(page, data); + await pollFor(page, () => getCellColor(1, 1), [255, 0, 0, 255]); // inverse foreground of '█' should be decoration fg override + await pollFor(page, () => getCellColor(2, 1), [255, 255, 255, 255]); // inverse background of ' ' should be default foreground + }); itWebgl('backgroundColor', async () => { await page.evaluate(` const marker = window.term.registerMarker(-window.term.buffer.active.cursorY); @@ -930,10 +944,24 @@ describe('WebGL Renderer Integration Tests', async () => { backgroundColor: '#0000ff' }); `); - const data = `\\x1b[7m \\x1b0m`; + const data = `\\x1b[7m \\x1b[0m`; await writeSync(page, data); await pollFor(page, () => getCellColor(1, 1), [0, 0, 255, 255]); }); + itWebgl('backgroundColor should ignore inverse (only bg on decoration)', async () => { + const data = `\\x1b[7m█ \\x1b[0m`; + await writeSync(page, data); + await page.evaluate(` + const marker = window.term.registerMarker(-window.term.buffer.active.cursorY); + window.term.registerDecoration({ + marker, + width: 2, + backgroundColor: '#0000ff' + }); + `); + await pollFor(page, () => getCellColor(1, 1), [0, 0, 0, 255]); // inverse foreground of '█' should be default + await pollFor(page, () => getCellColor(2, 1), [0, 0, 255, 255]); // inverse background of ' ' should be decoration bg override + }); }); });