Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Makes mouse/left/right navigation skip injected text. Also fixes bracket decoration bug. #128140

Merged
merged 7 commits into from
Jul 8, 2021
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
37 changes: 35 additions & 2 deletions src/vs/editor/common/controller/oneCursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { CursorContext, CursorState, SingleCursorState } from 'vs/editor/common/controller/cursorCommon';
import { CursorContext, CursorState, ICursorSimpleModel, SingleCursorState } from 'vs/editor/common/controller/cursorCommon';
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 @@ -77,7 +77,40 @@ export class Cursor {
this._setState(context, modelState, viewState);
}

private static _validatePositionWithCache(viewModel: ICursorSimpleModel, position: Position, cacheInput: Position, cacheOutput: Position): Position {
if (position.equals(cacheInput)) {
return cacheOutput;
}
return viewModel.normalizePosition(position, PositionAffinity.None);
}

private static _validateViewState(viewModel: ICursorSimpleModel, viewState: SingleCursorState): SingleCursorState {
const position = viewState.position;
const sStartPosition = viewState.selectionStart.getStartPosition();
const sEndPosition = viewState.selectionStart.getEndPosition();

const validPosition = viewModel.normalizePosition(position, PositionAffinity.None);
const validSStartPosition = this._validatePositionWithCache(viewModel, sStartPosition, position, validPosition);
const validSEndPosition = this._validatePositionWithCache(viewModel, sEndPosition, sStartPosition, validSStartPosition);

if (position.equals(validPosition) && sStartPosition.equals(validSStartPosition) && sEndPosition.equals(validSEndPosition)) {
// fast path: the state is valid
return viewState;
}

return new SingleCursorState(
Range.fromPositions(validSStartPosition, validSEndPosition),
viewState.selectionStartLeftoverVisibleColumns + sStartPosition.column - validSStartPosition.column,
validPosition,
viewState.leftoverVisibleColumns + position.column - validPosition.column,
);
}

private _setState(context: CursorContext, modelState: SingleCursorState | null, viewState: SingleCursorState | null): void {
if (viewState) {
viewState = Cursor._validateViewState(context.viewModel, viewState);
}

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