Skip to content

Commit

Permalink
Prevents cursor to move into injected text. Fixes bracket decoration …
Browse files Browse the repository at this point in the history
…bug.
  • Loading branch information
hediet committed Jul 7, 2021
1 parent c9aea49 commit c8118a4
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 58 deletions.
7 changes: 7 additions & 0 deletions src/vs/editor/browser/controller/mouseTarget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { CursorColumns } from 'vs/editor/common/controller/cursorCommon';
import * as dom from 'vs/base/browser/dom';
import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations';
import { PositionAffinity } from 'vs/editor/common/model';

export interface IViewZoneData {
viewZoneId: string;
Expand Down Expand Up @@ -955,6 +956,12 @@ export class MouseTargetFactory {
} else if ((<any>document).caretPositionFromPoint) {
result = this._doHitTestWithCaretPositionFromPoint(ctx, request.pos.toClientCoordinates());
}
if (result.type === HitTestResultType.Content) {
const normalizedPosition = ctx.model.normalizePosition(result.position, PositionAffinity.None);
if (!normalizedPosition.equals(result.position)) {
result = new ContentHitTestResult(normalizedPosition, result.spanNode);
}
}
// Snap to the nearest soft tab boundary if atomic soft tabs are enabled.
if (result.type === HitTestResultType.Content && ctx.stickyTabStops) {
result = new ContentHitTestResult(this._snapToSoftTabBoundary(result.position, ctx.model), result.spanNode);
Expand Down
4 changes: 2 additions & 2 deletions src/vs/editor/common/controller/cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export class CursorsController extends Disposable {
this._knownModelVersionId = this._model.getVersionId();
this._viewModel = viewModel;
this._coordinatesConverter = coordinatesConverter;
this.context = new CursorContext(this._model, this._coordinatesConverter, cursorConfig);
this.context = new CursorContext(this._model, this._viewModel, this._coordinatesConverter, cursorConfig);
this._cursors = new CursorCollection(this.context);

this._hasFocus = false;
Expand All @@ -163,7 +163,7 @@ export class CursorsController extends Disposable {
}

public updateConfiguration(cursorConfig: CursorConfiguration): void {
this.context = new CursorContext(this._model, this._coordinatesConverter, cursorConfig);
this.context = new CursorContext(this._model, this._viewModel, this._coordinatesConverter, cursorConfig);
this._cursors.updateContext(this.context);
}

Expand Down
9 changes: 6 additions & 3 deletions src/vs/editor/common/controller/cursorCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { ISelection, Selection } from 'vs/editor/common/core/selection';
import { ICommand, IConfiguration } from 'vs/editor/common/editorCommon';
import { ITextModel, PositionNormalizationAffinity, TextModelResolvedOptions } from 'vs/editor/common/model';
import { ITextModel, PositionAffinity, TextModelResolvedOptions } from 'vs/editor/common/model';
import { TextModel } from 'vs/editor/common/model/textModel';
import { LanguageIdentifier } from 'vs/editor/common/modes';
import { AutoClosingPairs, IAutoClosingPair } from 'vs/editor/common/modes/languageConfiguration';
Expand Down Expand Up @@ -221,7 +221,8 @@ export interface ICursorSimpleModel {
getLineMaxColumn(lineNumber: number): number;
getLineFirstNonWhitespaceColumn(lineNumber: number): number;
getLineLastNonWhitespaceColumn(lineNumber: number): number;
normalizePosition(position: Position, affinity: PositionNormalizationAffinity): Position;
normalizePosition(position: Position, affinity: PositionAffinity): Position;

/**
* Gets the column at which indentation stops at a given line.
* @internal
Expand Down Expand Up @@ -321,11 +322,13 @@ export class CursorContext {
_cursorContextBrand: void = undefined;

public readonly model: ITextModel;
public readonly viewModel: ICursorSimpleModel;
public readonly coordinatesConverter: ICoordinatesConverter;
public readonly cursorConfig: CursorConfiguration;

constructor(model: ITextModel, coordinatesConverter: ICoordinatesConverter, cursorConfig: CursorConfiguration) {
constructor(model: ITextModel, viewModel: ICursorSimpleModel, coordinatesConverter: ICoordinatesConverter, cursorConfig: CursorConfiguration) {
this.model = model;
this.viewModel = viewModel;
this.coordinatesConverter = coordinatesConverter;
this.cursorConfig = cursorConfig;
}
Expand Down
6 changes: 3 additions & 3 deletions src/vs/editor/common/controller/cursorMoveOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Range } from 'vs/editor/common/core/range';
import * as strings from 'vs/base/common/strings';
import { Constants } from 'vs/base/common/uint';
import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations';
import { PositionNormalizationAffinity } from 'vs/editor/common/model';
import { PositionAffinity } from 'vs/editor/common/model';

export class CursorPosition {
_cursorPositionBrand: void = undefined;
Expand Down Expand Up @@ -75,7 +75,7 @@ export class MoveOperations {
const pos = cursor.position.delta(undefined, -(noOfColumns - 1));
// We clip the position before normalization, as normalization is not defined
// for possibly negative columns.
const normalizedPos = model.normalizePosition(MoveOperations.clipPositionColumn(pos, model), PositionNormalizationAffinity.Left);
const normalizedPos = model.normalizePosition(MoveOperations.clipPositionColumn(pos, model), PositionAffinity.Left);
const p = MoveOperations.left(config, model, normalizedPos);

lineNumber = p.lineNumber;
Expand Down Expand Up @@ -144,7 +144,7 @@ export class MoveOperations {
column = cursor.selection.endColumn;
} else {
const pos = cursor.position.delta(undefined, noOfColumns - 1);
const normalizedPos = model.normalizePosition(MoveOperations.clipPositionColumn(pos, model), PositionNormalizationAffinity.Right);
const normalizedPos = model.normalizePosition(MoveOperations.clipPositionColumn(pos, model), PositionAffinity.Right);
const r = MoveOperations.right(config, model, normalizedPos);
lineNumber = r.lineNumber;
column = r.column;
Expand Down
29 changes: 28 additions & 1 deletion src/vs/editor/common/controller/oneCursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CursorContext, CursorState, SingleCursorState } from 'vs/editor/common/
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection, SelectionDirection } from 'vs/editor/common/core/selection';
import { TrackedRangeStickiness } from 'vs/editor/common/model';
import { PositionAffinity, TrackedRangeStickiness } from 'vs/editor/common/model';

/**
* Represents a single cursor.
Expand Down Expand Up @@ -78,6 +78,33 @@ export class Cursor {
}

private _setState(context: CursorContext, modelState: SingleCursorState | null, viewState: SingleCursorState | null): void {
if (viewState) {
const cache = new Map<string, Position>();
function normalize(pos: Position): Position {
const existing = cache.get(pos.toString());
if (existing) {
return existing;
}
const result = context.viewModel.normalizePosition(pos, PositionAffinity.None);
cache.set(pos.toString(), result);
return result;
}
const normalizedPosition = normalize(viewState.position);
const columnDelta = viewState.position.column - normalizedPosition.column;

const updatedState = new SingleCursorState(
Selection.fromPositions(
normalize(viewState.selectionStart.getStartPosition()),
normalize(viewState.selectionStart.getEndPosition())
),
viewState.selectionStartLeftoverVisibleColumns + columnDelta,
normalizedPosition,
viewState.leftoverVisibleColumns + columnDelta,
);

viewState = updatedState;
}

if (!modelState) {
if (!viewState) {
return;
Expand Down
17 changes: 15 additions & 2 deletions src/vs/editor/common/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1293,9 +1293,16 @@ export interface ITextModel {
/**
* Among all positions that are projected to the same position in the underlying text model as
* the given position, select a unique position as indicated by the affinity.
*
* PositionAffinity.Left:
* The normalized position must be equal or left to the requested position.
*
* PositionAffinity.Right:
* The normalized position must be equal or right to the requested position.
*
* @internal
*/
normalizePosition(position: Position, affinity: PositionNormalizationAffinity): Position;
normalizePosition(position: Position, affinity: PositionAffinity): Position;

/**
* Gets the column at which indentation stops at a given line.
Expand All @@ -1307,15 +1314,21 @@ export interface ITextModel {
/**
* @internal
*/
export const enum PositionNormalizationAffinity {
export const enum PositionAffinity {
/**
* Prefers the left most position.
*/
Left = 0,

/**
* Prefers the right most position.
*/
Right = 1,

/**
* No preference.
*/
None = 2,
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/vs/editor/common/model/textModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3122,7 +3122,7 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
}

//#endregion
normalizePosition(position: Position, affinity: model.PositionNormalizationAffinity): Position {
normalizePosition(position: Position, affinity: model.PositionAffinity): Position {
return position;
}

Expand Down
Loading

0 comments on commit c8118a4

Please sign in to comment.