From 3d929a1db0e01f94b3bd1c4f02d538ac5ea454ae Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 6 Jun 2026 09:18:47 -0700 Subject: [PATCH] fix(selection): drag-scroll end row and trim start clamp (#5993) * fix(selection): drag-scroll end row matches last visible line Use ydisp + rows - 1 for selectionEnd when scrolling down during drag, consistent with finalSelectionEnd for select-all. Co-authored-by: Daniel Imms * fix(selection): reset start to origin when start row is trimmed When handleTrim removes the selection start row, clamp to [0,0] and refresh; do not keep a stale column on row 0. Co-authored-by: Daniel Imms --------- Co-authored-by: Cursor Agent Co-authored-by: Daniel Imms --- src/browser/selection/SelectionModel.test.ts | 7 +++++++ src/browser/selection/SelectionModel.ts | 5 +++-- src/browser/services/SelectionService.ts | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/browser/selection/SelectionModel.test.ts b/src/browser/selection/SelectionModel.test.ts index 5f813d7ee..10ca79a34 100644 --- a/src/browser/selection/SelectionModel.test.ts +++ b/src/browser/selection/SelectionModel.test.ts @@ -64,6 +64,13 @@ describe('SelectionModel', () => { assert.deepEqual(model.finalSelectionStart, undefined); assert.deepEqual(model.finalSelectionEnd, undefined); }); + it('should reset selection start to origin when start row is trimmed', () => { + model.selectionStart = [50, 0]; + model.selectionEnd = [10, 2]; + assert.equal(model.handleTrim(1), true); + assert.deepEqual(model.finalSelectionStart, [0, 0]); + assert.deepEqual(model.finalSelectionEnd, [10, 1]); + }); }); describe('finalSelectionStart', () => { diff --git a/src/browser/selection/SelectionModel.ts b/src/browser/selection/SelectionModel.ts index 7b62b230b..8f87f17e2 100644 --- a/src/browser/selection/SelectionModel.ts +++ b/src/browser/selection/SelectionModel.ts @@ -135,9 +135,10 @@ export class SelectionModel { return true; } - // If the selection start is trimmed, ensure the start column is 0. + // If the selection start row is trimmed away, reset to the buffer origin. if (this.selectionStart && this.selectionStart[1] < 0) { - this.selectionStart[1] = 0; + this.selectionStart = [0, 0]; + return true; } return false; } diff --git a/src/browser/services/SelectionService.ts b/src/browser/services/SelectionService.ts index 576bdc525..39d8dd76b 100644 --- a/src/browser/services/SelectionService.ts +++ b/src/browser/services/SelectionService.ts @@ -704,7 +704,7 @@ export class SelectionService extends Disposable implements ISelectionService { if (this._activeSelectionMode !== SelectionMode.COLUMN) { this._model.selectionEnd[0] = this._bufferService.cols; } - this._model.selectionEnd[1] = Math.min(buffer.ydisp + this._bufferService.rows, buffer.lines.length - 1); + this._model.selectionEnd[1] = Math.min(buffer.ydisp + this._bufferService.rows - 1, buffer.lines.length - 1); } else { if (this._activeSelectionMode !== SelectionMode.COLUMN) { this._model.selectionEnd[0] = 0;