diff --git a/src/browser/Decorations/OverviewRulerRenderer.ts b/src/browser/Decorations/OverviewRulerRenderer.ts index 824f27ef6..d497b14b7 100644 --- a/src/browser/Decorations/OverviewRulerRenderer.ts +++ b/src/browser/Decorations/OverviewRulerRenderer.ts @@ -89,11 +89,10 @@ export class OverviewRulerRenderer extends Disposable { this._ctx.lineWidth = 1; this._ctx.fillStyle = decoration.overviewRulerOptions?.color || decoration.options.overviewRulerOptions.color; this._ctx.fillRect( - !decoration.options.overviewRulerOptions.position || decoration.options.overviewRulerOptions.position === 'left' ? 0 : decoration.options.overviewRulerOptions.position === 'right' ? renderSizes[SizeIndex.OUTER_SIZE] + renderSizes[SizeIndex.INNER_SIZE]: renderSizes[SizeIndex.OUTER_SIZE], + decoration.options.overviewRulerOptions.position === 'full' || decoration.options.overviewRulerOptions.position === 'left' ? 0 : decoration.options.overviewRulerOptions.position === 'right' ? renderSizes[SizeIndex.OUTER_SIZE] + renderSizes[SizeIndex.INNER_SIZE]: renderSizes[SizeIndex.OUTER_SIZE], Math.round(this._canvas.height * (decoration.options.marker.line / this._bufferService.buffers.active.lines.length)), - !decoration.options.overviewRulerOptions.position ? this._width : decoration.options.overviewRulerOptions.position === 'center' ? renderSizes[SizeIndex.INNER_SIZE] : renderSizes[SizeIndex.OUTER_SIZE], - // when a position is provided, the element has less width, so increase its height - window.devicePixelRatio * (decoration.options.overviewRulerOptions.position ? 6 : 2) + decoration.options.overviewRulerOptions.position === 'full' ? this._width : decoration.options.overviewRulerOptions.position === 'center' ? renderSizes[SizeIndex.INNER_SIZE] : renderSizes[SizeIndex.OUTER_SIZE], + window.devicePixelRatio * (decoration.options.overviewRulerOptions.position === 'full' ? 2 : 6) ); } diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 0c2f50868..496b8dfa6 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -98,6 +98,12 @@ export class Terminal extends CoreTerminal implements ITerminal { */ private _keyDownHandled: boolean = false; + /** + * Records whether a keydown event has occured since the last keyup event, i.e. whether a key + * is currently "pressed". + */ + private _keyDownSeen: boolean = false; + /** * Records whether the keypress event has already been handled and triggered a data event, if so * the input event should not trigger a data event but should still print to the textarea so @@ -1085,6 +1091,7 @@ export class Terminal extends CoreTerminal implements ITerminal { */ protected _keyDown(event: KeyboardEvent): boolean | undefined { this._keyDownHandled = false; + this._keyDownSeen = true; if (this._customKeyEventHandler && this._customKeyEventHandler(event) === false) { return false; @@ -1170,6 +1177,8 @@ export class Terminal extends CoreTerminal implements ITerminal { } protected _keyUp(ev: KeyboardEvent): void { + this._keyDownSeen = false; + if (this._customKeyEventHandler && this._customKeyEventHandler(ev) === false) { return; } @@ -1243,7 +1252,8 @@ export class Terminal extends CoreTerminal implements ITerminal { protected _inputEvent(ev: InputEvent): boolean { // Only support emoji IMEs when screen reader mode is disabled as the event must bubble up to // support reading out character input which can doubling up input characters - if (ev.data && ev.inputType === 'insertText' && !ev.composed && !this.optionsService.rawOptions.screenReaderMode) { + // Based on these event traces: https://github.com/xtermjs/xterm.js/issues/3679 + if (ev.data && ev.inputType === 'insertText' && (!ev.composed || !this._keyDownSeen) && !this.optionsService.rawOptions.screenReaderMode) { if (this._keyPressHandled) { return false; } diff --git a/src/common/services/DecorationService.ts b/src/common/services/DecorationService.ts index 911fd369c..6c7502361 100644 --- a/src/common/services/DecorationService.ts +++ b/src/common/services/DecorationService.ts @@ -65,6 +65,9 @@ class Decoration extends Disposable implements IInternalDecoration { ) { super(); this.marker = options.marker; + if (this.options.overviewRulerOptions && !this.options.overviewRulerOptions.position) { + this.options.overviewRulerOptions.position = 'full'; + } } public override dispose(): void { this._onDispose.fire(); diff --git a/test/api/Terminal.api.ts b/test/api/Terminal.api.ts index 43f1e97d7..b1582be85 100644 --- a/test/api/Terminal.api.ts +++ b/test/api/Terminal.api.ts @@ -770,8 +770,8 @@ describe('API Integration Tests', function(): void { await page.waitForSelector('.xterm-text-layer'); await page.evaluate(`window.marker1 = window.term.addMarker(1)`); await page.evaluate(`window.marker2 = window.term.addMarker(2)`); - await page.evaluate(`window.term.registerDecoration({ marker: window.marker1, overviewRulerOptions: { color: 'red' } })`); - await page.evaluate(`window.term.registerDecoration({ marker: window.marker2, overviewRulerOptions: { color: 'blue' } })`); + await page.evaluate(`window.term.registerDecoration({ marker: window.marker1, overviewRulerOptions: { color: 'red', position: 'full' } })`); + await page.evaluate(`window.term.registerDecoration({ marker: window.marker2, overviewRulerOptions: { color: 'blue', position: 'full' } })`); await openTerminal(page); await pollFor(page, `document.querySelectorAll('.xterm-decoration-overview-ruler').length`, 0); }); @@ -781,8 +781,8 @@ describe('API Integration Tests', function(): void { await page.waitForSelector('.xterm-text-layer'); await page.evaluate(`window.marker1 = window.term.addMarker(1)`); await page.evaluate(`window.marker2 = window.term.addMarker(2)`); - await page.evaluate(`window.term.registerDecoration({ marker: window.marker1, overviewRulerOptions: { color: 'red' } })`); - await page.evaluate(`window.term.registerDecoration({ marker: window.marker2, overviewRulerOptions: { color: 'blue' } })`); + await page.evaluate(`window.term.registerDecoration({ marker: window.marker1, overviewRulerOptions: { color: 'red', position: 'full' } })`); + await page.evaluate(`window.term.registerDecoration({ marker: window.marker2, overviewRulerOptions: { color: 'blue', position: 'full' } })`); await openTerminal(page); await pollFor(page, `document.querySelectorAll('.xterm-decoration-overview-ruler').length`, 1); }); diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index e963a39ae..d0149c198 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -7,6 +7,8 @@ * to be stable and consumed by external programs. */ +import { IModelDecorationOverviewRulerOptions } from 'vs/editor/common/model'; + /// declare module 'xterm' { @@ -453,7 +455,7 @@ declare module 'xterm' { */ interface IDecorationOverviewRulerOptions { color: string; - position?: 'left' | 'center' | 'right'; + position?: 'left' | 'center' | 'right' | 'full'; } /*