Skip to content

Commit 4036ab7

Browse files
authored
Merge pull request xtermjs#4837 from tisilent/fix-dom-renderer-selection
handle selection when resizing
2 parents 139bf36 + b6a09d6 commit 4036ab7

File tree

6 files changed

+30
-17
lines changed

6 files changed

+30
-17
lines changed

addons/addon-canvas/src/BaseRenderLayer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
9191
public handleGridChanged(startRow: number, endRow: number): void {}
9292

9393
public handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void {
94-
this._selectionModel.update(this._terminal, start, end, columnSelectMode);
94+
this._selectionModel.update((this._terminal as any)._core, start, end, columnSelectMode);
9595
}
9696

9797
protected _setTransparency(alpha: boolean): void {

addons/addon-webgl/src/WebglRenderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
219219
for (const l of this._renderLayers) {
220220
l.handleSelectionChanged(this._terminal, start, end, columnSelectMode);
221221
}
222-
this._model.selection.update(this._terminal, start, end, columnSelectMode);
222+
this._model.selection.update(this._core, start, end, columnSelectMode);
223223
this._requestRedrawViewport();
224224
}
225225

src/browser/Terminal.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
575575
}
576576

577577
private _createRenderer(): IRenderer {
578-
return this._instantiationService.createInstance(DomRenderer, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier2);
578+
return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier2);
579579
}
580580

581581
/**

src/browser/renderer/dom/DomRenderer.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import { DomRendererRowFactory, RowCss } from 'browser/renderer/dom/DomRendererR
77
import { WidthCache } from 'browser/renderer/dom/WidthCache';
88
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
99
import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';
10-
import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/shared/Types';
10+
import { createSelectionRenderModel } from 'browser/renderer/shared/SelectionRenderModel';
11+
import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ISelectionRenderModel } from 'browser/renderer/shared/Types';
1112
import { ICharSizeService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
12-
import { ILinkifier2, ILinkifierEvent, ReadonlyColorSet } from 'browser/Types';
13+
import { ILinkifier2, ILinkifierEvent, ITerminal, ReadonlyColorSet } from 'browser/Types';
1314
import { color } from 'common/Color';
1415
import { EventEmitter } from 'common/EventEmitter';
1516
import { Disposable, toDisposable } from 'common/Lifecycle';
@@ -25,7 +26,6 @@ const SELECTION_CLASS = 'xterm-selection';
2526

2627
let nextTerminalId = 1;
2728

28-
2929
/**
3030
* A fallback renderer for when canvas is slow. This is not meant to be
3131
* particularly fast or feature complete, more just stable and usable for when
@@ -41,12 +41,14 @@ export class DomRenderer extends Disposable implements IRenderer {
4141
private _rowElements: HTMLElement[] = [];
4242
private _selectionContainer: HTMLElement;
4343
private _widthCache: WidthCache;
44+
private _selectionRenderModel: ISelectionRenderModel = createSelectionRenderModel();
4445

4546
public dimensions: IRenderDimensions;
4647

4748
public readonly onRequestRedraw = this.register(new EventEmitter<IRequestRedrawEvent>()).event;
4849

4950
constructor(
51+
private readonly _terminal: ITerminal,
5052
private readonly _document: Document,
5153
private readonly _element: HTMLElement,
5254
private readonly _screenElement: HTMLElement,
@@ -291,6 +293,7 @@ export class DomRenderer extends Disposable implements IRenderer {
291293
public handleResize(cols: number, rows: number): void {
292294
this._refreshRowElements(cols, rows);
293295
this._updateDimensions();
296+
this.handleSelectionChanged(this._selectionRenderModel.selectionStart, this._selectionRenderModel.selectionEnd, this._selectionRenderModel.columnSelectMode);
294297
}
295298

296299
public handleCharSizeChanged(): void {
@@ -320,11 +323,13 @@ export class DomRenderer extends Disposable implements IRenderer {
320323
return;
321324
}
322325

326+
this._selectionRenderModel.update(this._terminal, start, end, columnSelectMode);
327+
323328
// Translate from buffer position to viewport position
324-
const viewportStartRow = start[1] - this._bufferService.buffer.ydisp;
325-
const viewportEndRow = end[1] - this._bufferService.buffer.ydisp;
326-
const viewportCappedStartRow = Math.max(viewportStartRow, 0);
327-
const viewportCappedEndRow = Math.min(viewportEndRow, this._bufferService.rows - 1);
329+
const viewportStartRow = this._selectionRenderModel.viewportStartRow;
330+
const viewportEndRow = this._selectionRenderModel.viewportEndRow;
331+
const viewportCappedStartRow = this._selectionRenderModel.viewportCappedStartRow;
332+
const viewportCappedEndRow = this._selectionRenderModel.viewportCappedEndRow;
328333

329334
// No need to draw the selection
330335
if (viewportCappedStartRow >= this._bufferService.rows || viewportCappedEndRow < 0) {
@@ -365,10 +370,16 @@ export class DomRenderer extends Disposable implements IRenderer {
365370
*/
366371
private _createSelectionElement(row: number, colStart: number, colEnd: number, rowCount: number = 1): HTMLElement {
367372
const element = this._document.createElement('div');
373+
const left = colStart * this.dimensions.css.cell.width;
374+
let width = this.dimensions.css.cell.width * (colEnd - colStart);
375+
if (left + width > this.dimensions.css.canvas.width) {
376+
width = this.dimensions.css.canvas.width - left;
377+
}
378+
368379
element.style.height = `${rowCount * this.dimensions.css.cell.height}px`;
369380
element.style.top = `${row * this.dimensions.css.cell.height}px`;
370-
element.style.left = `${colStart * this.dimensions.css.cell.width}px`;
371-
element.style.width = `${this.dimensions.css.cell.width * (colEnd - colStart)}px`;
381+
element.style.left = `${left}px`;
382+
element.style.width = `${width}px`;
372383
return element;
373384
}
374385

src/browser/renderer/shared/SelectionRenderModel.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* @license MIT
44
*/
55

6+
import { ITerminal } from 'browser/Types';
67
import { ISelectionRenderModel } from 'browser/renderer/shared/Types';
78
import { Terminal } from '@xterm/xterm';
89

@@ -35,7 +36,7 @@ class SelectionRenderModel implements ISelectionRenderModel {
3536
this.selectionEnd = undefined;
3637
}
3738

38-
public update(terminal: Terminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void {
39+
public update(terminal: ITerminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void {
3940
this.selectionStart = start;
4041
this.selectionEnd = end;
4142
// Selection does not exist
@@ -45,8 +46,9 @@ class SelectionRenderModel implements ISelectionRenderModel {
4546
}
4647

4748
// Translate from buffer position to viewport position
48-
const viewportStartRow = start[1] - terminal.buffer.active.viewportY;
49-
const viewportEndRow = end[1] - terminal.buffer.active.viewportY;
49+
const viewportY = terminal.buffers.active.ydisp;
50+
const viewportStartRow = start[1] - viewportY;
51+
const viewportEndRow = end[1] - viewportY;
5052
const viewportCappedStartRow = Math.max(viewportStartRow, 0);
5153
const viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1);
5254

src/browser/renderer/shared/Types.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import { FontWeight, Terminal } from '@xterm/xterm';
7-
import { IColorSet } from 'browser/Types';
7+
import { IColorSet, ITerminal } from 'browser/Types';
88
import { IDisposable } from 'common/Types';
99
import { IEvent } from 'common/EventEmitter';
1010

@@ -168,6 +168,6 @@ export interface ISelectionRenderModel {
168168
readonly selectionStart: [number, number] | undefined;
169169
readonly selectionEnd: [number, number] | undefined;
170170
clear(): void;
171-
update(terminal: Terminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode?: boolean): void;
171+
update(terminal: ITerminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode?: boolean): void;
172172
isCellSelected(terminal: Terminal, x: number, y: number): boolean;
173173
}

0 commit comments

Comments
 (0)