diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index 1549b130..c89cee62 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -183,14 +183,23 @@ export class DomRenderer extends Disposable implements IRenderer { ` font-style: italic;` + `}`; // Blink animation + const blinkAnimationUnderlineId = `blink_underline_${this._terminalClass}`; + const blinkAnimationBarId = `blink_bar_${this._terminalClass}`; + const blinkAnimationBlockId = `blink_block_${this._terminalClass}`; styles += - `@keyframes blink_box_shadow` + `_` + this._terminalClass + ` {` + + `@keyframes ${blinkAnimationUnderlineId} {` + ` 50% {` + ` border-bottom-style: hidden;` + ` }` + `}`; styles += - `@keyframes blink_block` + `_` + this._terminalClass + ` {` + + `@keyframes ${blinkAnimationBarId} {` + + ` 50% {` + + ` box-shadow: none;` + + ` }` + + `}`; + styles += + `@keyframes ${blinkAnimationBlockId} {` + ` 0% {` + ` background-color: ${colors.cursor.css};` + ` color: ${colors.cursorAccent.css};` + @@ -202,13 +211,23 @@ export class DomRenderer extends Disposable implements IRenderer { `}`; // Cursor styles += - `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}:not(.${RowCss.CURSOR_STYLE_BLOCK_CLASS}) {` + - ` animation: blink_box_shadow` + `_` + this._terminalClass + ` 1s step-end infinite;` + + `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` + + ` animation: ${blinkAnimationUnderlineId} 1s step-end infinite;` + + `}` + + `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` + + ` animation: ${blinkAnimationBarId} 1s step-end infinite;` + `}` + `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` + - ` animation: blink_block` + `_` + this._terminalClass + ` 1s step-end infinite;` + + ` animation: ${blinkAnimationBlockId} 1s step-end infinite;` + `}` + + // !important helps fix an issue where the cursor will not render on top of the selection, + // however it's very hard to fix this issue and retain the blink animation without the use of + // !important. So this edge case fails when cursor blink is on. `${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` + + ` background-color: ${colors.cursor.css};` + + ` color: ${colors.cursorAccent.css};` + + `}` + + `${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS}:not(.${RowCss.CURSOR_BLINK_CLASS}) {` + ` background-color: ${colors.cursor.css} !important;` + ` color: ${colors.cursorAccent.css} !important;` + `}` + diff --git a/test/playwright/SharedRendererTests.ts b/test/playwright/SharedRendererTests.ts index 29dc51c3..c4b66536 100644 --- a/test/playwright/SharedRendererTests.ts +++ b/test/playwright/SharedRendererTests.ts @@ -6,7 +6,7 @@ import { IImage32, decodePng } from '@lunapaint/png-codec'; import { LocatorScreenshotOptions, test } from '@playwright/test'; import { ITheme } from '@xterm/xterm'; -import { ITestContext, MaybeAsync, openTerminal, pollFor, pollForApproximate, timeout } from './TestUtils'; +import { ITestContext, MaybeAsync, openTerminal, pollFor, pollForApproximate } from './TestUtils'; export interface ISharedRendererTestContext { value: ITestContext;