mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Fix selection wrapping to end when not beyond viewport
This was happening as the devicePixelRatio wasn't being taken into account, the fix was to rely on IRenderService to get the right canvas height. Fixes #2833
This commit is contained in:
@@ -4,7 +4,9 @@
|
||||
*/
|
||||
|
||||
import { IEvent, EventEmitter } from 'common/EventEmitter';
|
||||
import { ICharSizeService, IMouseService } from 'browser/services/Services';
|
||||
import { ICharSizeService, IMouseService, IRenderService } from 'browser/services/Services';
|
||||
import { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types';
|
||||
import { IColorSet } from 'browser/Types';
|
||||
|
||||
export class MockCharSizeService implements ICharSizeService {
|
||||
serviceBrand: any;
|
||||
@@ -24,3 +26,72 @@ export class MockMouseService implements IMouseService {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
}
|
||||
|
||||
export class MockRenderService implements IRenderService {
|
||||
serviceBrand: any;
|
||||
onDimensionsChange: IEvent<IRenderDimensions> = new EventEmitter<IRenderDimensions>().event;
|
||||
onRender: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event;
|
||||
onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event;
|
||||
dimensions: IRenderDimensions = {
|
||||
scaledCharWidth: 0,
|
||||
scaledCharHeight: 0,
|
||||
scaledCellWidth: 0,
|
||||
scaledCellHeight: 0,
|
||||
scaledCharLeft: 0,
|
||||
scaledCharTop: 0,
|
||||
scaledCanvasWidth: 0,
|
||||
scaledCanvasHeight: 0,
|
||||
canvasWidth: 0,
|
||||
canvasHeight: 0,
|
||||
actualCellWidth: 0,
|
||||
actualCellHeight: 0
|
||||
};
|
||||
refreshRows(start: number, end: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
resize(cols: number, rows: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
changeOptions(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
setRenderer(renderer: IRenderer): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
setColors(colors: IColorSet): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
onDevicePixelRatioChange(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
onResize(cols: number, rows: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
onCharSizeChanged(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
onBlur(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
onFocus(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
onCursorMove(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
clear(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
registerCharacterJoiner(handler: CharacterJoinerHandler): number {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
deregisterCharacterJoiner(joinerId: number): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
dispose(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,16 +10,18 @@ import { IBufferLine } from 'common/Types';
|
||||
import { MockBufferService, MockOptionsService, MockCoreService } from 'common/TestUtils.test';
|
||||
import { BufferLine } from 'common/buffer/BufferLine';
|
||||
import { IBufferService, IOptionsService } from 'common/services/Services';
|
||||
import { MockCharSizeService, MockMouseService } from 'browser/TestUtils.test';
|
||||
import { MockMouseService, MockRenderService } from 'browser/TestUtils.test';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { IBuffer } from 'common/buffer/Types';
|
||||
import { IRenderService } from 'browser/services/Services';
|
||||
|
||||
class TestSelectionService extends SelectionService {
|
||||
constructor(
|
||||
bufferService: IBufferService,
|
||||
optionsService: IOptionsService
|
||||
optionsService: IOptionsService,
|
||||
renderService: IRenderService
|
||||
) {
|
||||
super(() => {}, null!, null!, new MockCharSizeService(10, 10), bufferService, new MockCoreService(), new MockMouseService(), optionsService);
|
||||
super(() => {}, null!, null!, bufferService, new MockCoreService(), new MockMouseService(), optionsService, renderService);
|
||||
}
|
||||
|
||||
public get model(): SelectionModel { return this._model; }
|
||||
@@ -46,7 +48,10 @@ describe('SelectionService', () => {
|
||||
optionsService = new MockOptionsService();
|
||||
bufferService = new MockBufferService(20, 20, optionsService);
|
||||
buffer = bufferService.buffer;
|
||||
selectionService = new TestSelectionService(bufferService, optionsService);
|
||||
const renderService = new MockRenderService();
|
||||
renderService.dimensions.canvasHeight = 10 * 20;
|
||||
renderService.dimensions.canvasWidth = 10 * 20;
|
||||
selectionService = new TestSelectionService(bufferService, optionsService, renderService);
|
||||
});
|
||||
|
||||
function stringToRow(text: string): IBufferLine {
|
||||
|
||||
@@ -10,7 +10,7 @@ import * as Browser from 'common/Platform';
|
||||
import { SelectionModel } from 'browser/selection/SelectionModel';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||
import { ICharSizeService, IMouseService, ISelectionService } from 'browser/services/Services';
|
||||
import { ICharSizeService, IMouseService, ISelectionService, IRenderService } from 'browser/services/Services';
|
||||
import { IBufferService, IOptionsService, ICoreService } from 'common/services/Services';
|
||||
import { getCoordsRelativeToElement } from 'browser/input/Mouse';
|
||||
import { moveToCellSequence } from 'browser/input/MoveToCell';
|
||||
@@ -116,11 +116,11 @@ export class SelectionService implements ISelectionService {
|
||||
private readonly _scrollLines: (amount: number, suppressEvent: boolean) => void,
|
||||
private readonly _element: HTMLElement,
|
||||
private readonly _screenElement: HTMLElement,
|
||||
@ICharSizeService private readonly _charSizeService: ICharSizeService,
|
||||
@IBufferService private readonly _bufferService: IBufferService,
|
||||
@ICoreService private readonly _coreService: ICoreService,
|
||||
@IMouseService private readonly _mouseService: IMouseService,
|
||||
@IOptionsService private readonly _optionsService: IOptionsService
|
||||
@IOptionsService private readonly _optionsService: IOptionsService,
|
||||
@IRenderService private readonly _renderService: IRenderService
|
||||
) {
|
||||
// Init listeners
|
||||
this._mouseMoveListener = event => this._onMouseMove(<MouseEvent>event);
|
||||
@@ -374,7 +374,7 @@ export class SelectionService implements ISelectionService {
|
||||
*/
|
||||
private _getMouseEventScrollAmount(event: MouseEvent): number {
|
||||
let offset = getCoordsRelativeToElement(event, this._screenElement)[1];
|
||||
const terminalHeight = this._bufferService.rows * Math.ceil(this._charSizeService.height * this._optionsService.options.lineHeight);
|
||||
const terminalHeight = this._renderService.dimensions.canvasHeight;
|
||||
if (offset >= 0 && offset <= terminalHeight) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user