diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index f8960556738..089558e76c1 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -5,12 +5,11 @@ import * as dom from 'vs/base/browser/dom'; import { StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; -import { TimeoutTimer } from 'vs/base/common/async'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; import { HitTestContext, MouseTarget, MouseTargetFactory, PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget'; -import { IMouseTarget, IMouseTargetViewZoneData, MouseTargetType } from 'vs/editor/browser/editorBrowser'; -import { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorPointerMoveMonitor, createEditorPagePosition, createCoordinatesRelativeToEditor } from 'vs/editor/browser/editorDom'; +import { IMouseTarget, IMouseTargetOutsideEditor, IMouseTargetViewZoneData, MouseTargetType } from 'vs/editor/browser/editorBrowser'; +import { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorPointerMoveMonitor, createEditorPagePosition, createCoordinatesRelativeToEditor, PageCoordinates } from 'vs/editor/browser/editorDom'; import { ViewController } from 'vs/editor/browser/view/viewController'; import { EditorZoom } from 'vs/editor/common/config/editorZoom'; import { Position } from 'vs/editor/common/core/position'; @@ -20,6 +19,7 @@ import { ViewContext } from 'vs/editor/common/viewModel/viewContext'; import * as viewEvents from 'vs/editor/common/viewEvents'; import { ViewEventHandler } from 'vs/editor/common/viewEventHandler'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { NavigationCommandRevealType } from 'vs/editor/browser/coreCommands'; export interface IPointerHandlerHelper { viewDomNode: HTMLElement; @@ -34,6 +34,11 @@ export interface IPointerHandlerHelper { */ getLastRenderData(): PointerHandlerLastRenderData; + /** + * Render right now + */ + renderNow(): void; + shouldSuppressMouseDownOnViewZone(viewZoneId: string): boolean; shouldSuppressMouseDownOnWidget(widgetId: string): boolean; @@ -69,6 +74,7 @@ export class MouseHandler extends ViewEventHandler { this._context, this.viewController, this.viewHelper, + this.mouseTargetFactory, (e, testEventTarget) => this._createMouseTarget(e, testEventTarget), (e) => this._getMouseColumn(e) )); @@ -177,10 +183,6 @@ export class MouseHandler extends ViewEventHandler { public override onFocusChanged(e: viewEvents.ViewFocusChangedEvent): boolean { return false; } - public override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean { - this._mouseDownOperation.onScrollChanged(); - return false; - } // --- end event handlers public getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget | null { @@ -313,14 +315,11 @@ export class MouseHandler extends ViewEventHandler { class MouseDownOperation extends Disposable { - private readonly _context: ViewContext; - private readonly _viewController: ViewController; - private readonly _viewHelper: IPointerHandlerHelper; private readonly _createMouseTarget: (e: EditorMouseEvent, testEventTarget: boolean) => IMouseTarget; private readonly _getMouseColumn: (e: EditorMouseEvent) => number; private readonly _mouseMoveMonitor: GlobalEditorPointerMoveMonitor; - private readonly _onScrollTimeout: TimeoutTimer; + private readonly _topBottomDragScrolling: TopBottomDragScrolling; private readonly _mouseState: MouseDownState; private _currentSelection: Selection; @@ -328,21 +327,24 @@ class MouseDownOperation extends Disposable { private _lastMouseEvent: EditorMouseEvent | null; constructor( - context: ViewContext, - viewController: ViewController, - viewHelper: IPointerHandlerHelper, + private readonly _context: ViewContext, + private readonly _viewController: ViewController, + private readonly _viewHelper: IPointerHandlerHelper, + private readonly _mouseTargetFactory: MouseTargetFactory, createMouseTarget: (e: EditorMouseEvent, testEventTarget: boolean) => IMouseTarget, getMouseColumn: (e: EditorMouseEvent) => number ) { super(); - this._context = context; - this._viewController = viewController; - this._viewHelper = viewHelper; this._createMouseTarget = createMouseTarget; this._getMouseColumn = getMouseColumn; this._mouseMoveMonitor = this._register(new GlobalEditorPointerMoveMonitor(this._viewHelper.viewDomNode)); - this._onScrollTimeout = this._register(new TimeoutTimer()); + this._topBottomDragScrolling = this._register(new TopBottomDragScrolling( + this._context, + this._viewHelper, + this._mouseTargetFactory, + (position, inSelectionMode, revealType) => this._dispatchMouse(position, inSelectionMode, revealType) + )); this._mouseState = new MouseDownState(); this._currentSelection = new Selection(1, 1, 1, 1); @@ -374,7 +376,12 @@ class MouseDownOperation extends Disposable { target: position }); } else { - this._dispatchMouse(position, true); + if (position.type === MouseTargetType.OUTSIDE_EDITOR) { + this._topBottomDragScrolling.start(position, e); + } else { + this._topBottomDragScrolling.stop(); + this._dispatchMouse(position, true, NavigationCommandRevealType.Minimal); + } } } @@ -436,7 +443,7 @@ class MouseDownOperation extends Disposable { } this._mouseState.isDragAndDrop = false; - this._dispatchMouse(position, e.shiftKey); + this._dispatchMouse(position, e.shiftKey, NavigationCommandRevealType.Minimal); if (!this._isActive) { this._isActive = true; @@ -452,7 +459,7 @@ class MouseDownOperation extends Disposable { private _stop(): void { this._isActive = false; - this._onScrollTimeout.cancel(); + this._topBottomDragScrolling.stop(); } public onHeightChanged(): void { @@ -463,27 +470,6 @@ class MouseDownOperation extends Disposable { this._mouseMoveMonitor.stopMonitoring(); } - public onScrollChanged(): void { - if (!this._isActive) { - return; - } - this._onScrollTimeout.setIfNotSet(() => { - if (!this._lastMouseEvent) { - return; - } - const position = this._findMousePosition(this._lastMouseEvent, false); - if (!position) { - // Ignoring because position is unknown - return; - } - if (this._mouseState.isDragAndDrop) { - // Ignoring because users are dragging the text - return; - } - this._dispatchMouse(position, true); - }, 10); - } - public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): void { this._currentSelection = e.selections[0]; } @@ -578,7 +564,7 @@ class MouseDownOperation extends Disposable { return null; } - private _dispatchMouse(position: IMouseTarget, inSelectionMode: boolean): void { + private _dispatchMouse(position: IMouseTarget, inSelectionMode: boolean, revealType: NavigationCommandRevealType): void { if (!position.position) { return; } @@ -586,6 +572,7 @@ class MouseDownOperation extends Disposable { position: position.position, mouseColumn: position.mouseColumn, startedOnLineNumbers: this._mouseState.startedOnLineNumbers, + revealType, inSelectionMode: inSelectionMode, mouseDownCount: this._mouseState.count, @@ -602,6 +589,134 @@ class MouseDownOperation extends Disposable { } } +class TopBottomDragScrolling extends Disposable { + + private _operation: TopBottomDragScrollingOperation | null; + + constructor( + private readonly _context: ViewContext, + private readonly _viewHelper: IPointerHandlerHelper, + private readonly _mouseTargetFactory: MouseTargetFactory, + private readonly _dispatchMouse: (position: IMouseTarget, inSelectionMode: boolean, revealType: NavigationCommandRevealType) => void, + ) { + super(); + this._operation = null; + } + + public override dispose(): void { + super.dispose(); + this.stop(); + } + + public start(position: IMouseTargetOutsideEditor, mouseEvent: EditorMouseEvent): void { + if (this._operation) { + this._operation.setPosition(position, mouseEvent); + } else { + this._operation = new TopBottomDragScrollingOperation(this._context, this._viewHelper, this._mouseTargetFactory, this._dispatchMouse, position, mouseEvent); + } + } + + public stop(): void { + if (this._operation) { + this._operation.dispose(); + this._operation = null; + } + } +} + +class TopBottomDragScrollingOperation extends Disposable { + + private _position: IMouseTargetOutsideEditor; + private _mouseEvent: EditorMouseEvent; + private _lastTime: number; + private _animationFrameDisposable: IDisposable; + + constructor( + private readonly _context: ViewContext, + private readonly _viewHelper: IPointerHandlerHelper, + private readonly _mouseTargetFactory: MouseTargetFactory, + private readonly _dispatchMouse: (position: IMouseTarget, inSelectionMode: boolean, revealType: NavigationCommandRevealType) => void, + position: IMouseTargetOutsideEditor, + mouseEvent: EditorMouseEvent + ) { + super(); + this._position = position; + this._mouseEvent = mouseEvent; + this._lastTime = Date.now(); + this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute()); + } + + public override dispose(): void { + this._animationFrameDisposable.dispose(); + } + + public setPosition(position: IMouseTargetOutsideEditor, mouseEvent: EditorMouseEvent): void { + this._position = position; + this._mouseEvent = mouseEvent; + } + + /** + * update internal state and return elapsed ms since last time + */ + private _tick(): number { + const now = Date.now(); + const elapsed = now - this._lastTime; + this._lastTime = now; + return elapsed; + } + + /** + * get the number of lines per second to auto-scroll + */ + private _getScrollSpeed(): number { + const lineHeight = this._context.configuration.options.get(EditorOption.lineHeight); + const viewportInLines = this._context.configuration.options.get(EditorOption.layoutInfo).height / lineHeight; + const outsideDistanceInLines = this._position.outsideDistance / lineHeight; + + if (outsideDistanceInLines <= 1.5) { + return Math.max(30, viewportInLines * (1 + outsideDistanceInLines)); + } + if (outsideDistanceInLines <= 3) { + return Math.max(60, viewportInLines * (2 + outsideDistanceInLines)); + } + return Math.max(200, viewportInLines * (7 + outsideDistanceInLines)); + } + + private _execute(): void { + const lineHeight = this._context.configuration.options.get(EditorOption.lineHeight); + const scrollSpeedInLines = this._getScrollSpeed(); + const elapsed = this._tick(); + const scrollInPixels = scrollSpeedInLines * (elapsed / 1000) * lineHeight; + const scrollValue = (this._position.outsidePosition === 'above' ? -scrollInPixels : scrollInPixels); + + this._context.viewModel.viewLayout.deltaScrollNow(0, scrollValue); + this._viewHelper.renderNow(); + + const viewportData = this._context.viewLayout.getLinesViewportData(); + const edgeLineNumber = (this._position.outsidePosition === 'above' ? viewportData.startLineNumber : viewportData.endLineNumber); + + // First, try to find a position that matches the horizontal position of the mouse + let mouseTarget: IMouseTarget; + { + const editorPos = createEditorPagePosition(this._viewHelper.viewDomNode); + const horizontalScrollbarHeight = this._context.configuration.options.get(EditorOption.layoutInfo).horizontalScrollbarHeight; + const pos = new PageCoordinates(this._mouseEvent.pos.x, editorPos.y + editorPos.height - horizontalScrollbarHeight - 0.1); + const relativePos = createCoordinatesRelativeToEditor(this._viewHelper.viewDomNode, editorPos, pos); + mouseTarget = this._mouseTargetFactory.createMouseTarget(this._viewHelper.getLastRenderData(), editorPos, pos, relativePos, null); + } + if (!mouseTarget.position || mouseTarget.position.lineNumber !== edgeLineNumber) { + if (this._position.outsidePosition === 'above') { + mouseTarget = MouseTarget.createOutsideEditor(this._position.mouseColumn, new Position(edgeLineNumber, 1), 'above', this._position.outsideDistance); + } else { + mouseTarget = MouseTarget.createOutsideEditor(this._position.mouseColumn, new Position(edgeLineNumber, this._context.viewModel.getLineMaxColumn(edgeLineNumber)), 'below', this._position.outsideDistance); + } + } + + this._dispatchMouse(mouseTarget, true, NavigationCommandRevealType.None); + this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute()); + } +} + class MouseDownState { private static readonly CLEAR_MOUSE_DOWN_COUNT_TIME = 400; // ms diff --git a/src/vs/editor/browser/controller/pointerHandler.ts b/src/vs/editor/browser/controller/pointerHandler.ts index 1fd1525a4c2..25155f1336d 100644 --- a/src/vs/editor/browser/controller/pointerHandler.ts +++ b/src/vs/editor/browser/controller/pointerHandler.ts @@ -14,6 +14,7 @@ import { ViewController } from 'vs/editor/browser/view/viewController'; import { ViewContext } from 'vs/editor/common/viewModel/viewContext'; import { BrowserFeatures } from 'vs/base/browser/canIUse'; import { TextAreaSyntethicEvents } from 'vs/editor/browser/controller/textAreaInput'; +import { NavigationCommandRevealType } from 'vs/editor/browser/coreCommands'; /** * Currently only tested on iOS 13/ iPadOS. @@ -66,6 +67,7 @@ export class PointerEventHandler extends MouseHandler { position: target.position, mouseColumn: target.position.column, startedOnLineNumbers: false, + revealType: NavigationCommandRevealType.Minimal, mouseDownCount: event.tapCount, inSelectionMode: false, altKey: false, @@ -120,7 +122,7 @@ class TouchHandler extends MouseHandler { event.initEvent(TextAreaSyntethicEvents.Tap, false, true); this.viewHelper.dispatchTextAreaEvent(event); - this.viewController.moveTo(target.position); + this.viewController.moveTo(target.position, NavigationCommandRevealType.Minimal); } } diff --git a/src/vs/editor/browser/coreCommands.ts b/src/vs/editor/browser/coreCommands.ts index de59a8b7f6e..6fa113c75ee 100644 --- a/src/vs/editor/browser/coreCommands.ts +++ b/src/vs/editor/browser/coreCommands.ts @@ -33,7 +33,7 @@ import { ISelection } from 'vs/editor/common/core/selection'; const CORE_WEIGHT = KeybindingWeight.EditorCore; export abstract class CoreEditorCommand extends EditorCommand { - public runEditorCommand(accessor: ServicesAccessor | null, editor: ICodeEditor, args?: T | null): void { + public runEditorCommand(accessor: ServicesAccessor | null, editor: ICodeEditor, args?: Partial | null): void { const viewModel = editor._getViewModel(); if (!viewModel) { // the editor has no view => has no cursors @@ -331,6 +331,21 @@ abstract class EditorOrNativeTextInputCommand { public abstract runEditorCommand(accessor: ServicesAccessor | null, editor: ICodeEditor, args: unknown): void | Promise; } +export const enum NavigationCommandRevealType { + /** + * Do regular revealing. + */ + Regular = 0, + /** + * Do only minimal revealing. + */ + Minimal = 1, + /** + * Do not reveal the position. + */ + None = 2 +} + export namespace CoreNavigationCommands { export interface BaseCommandOptions { @@ -340,16 +355,15 @@ export namespace CoreNavigationCommands { export interface MoveCommandOptions extends BaseCommandOptions { position: IPosition; viewPosition?: IPosition; + revealType: NavigationCommandRevealType; } class BaseMoveToCommand extends CoreEditorCommand { - private readonly _minimalReveal: boolean; private readonly _inSelectionMode: boolean; - constructor(opts: ICommandOptions & { minimalReveal: boolean; inSelectionMode: boolean }) { + constructor(opts: ICommandOptions & { inSelectionMode: boolean }) { super(opts); - this._minimalReveal = opts.minimalReveal; this._inSelectionMode = opts.inSelectionMode; } @@ -365,22 +379,20 @@ export namespace CoreNavigationCommands { CursorMoveCommands.moveTo(viewModel, viewModel.getPrimaryCursorState(), this._inSelectionMode, args.position, args.viewPosition) ] ); - if (cursorStateChanged) { - viewModel.revealPrimaryCursor(args.source, true, this._minimalReveal); + if (cursorStateChanged && args.revealType !== NavigationCommandRevealType.None) { + viewModel.revealPrimaryCursor(args.source, true, true); } } } export const MoveTo: CoreEditorCommand = registerEditorCommand(new BaseMoveToCommand({ id: '_moveTo', - minimalReveal: true, inSelectionMode: false, precondition: undefined })); export const MoveToSelect: CoreEditorCommand = registerEditorCommand(new BaseMoveToCommand({ id: '_moveToSelect', - minimalReveal: false, inSelectionMode: true, precondition: undefined })); @@ -415,8 +427,8 @@ export namespace CoreNavigationCommands { export interface ColumnSelectCommandOptions extends BaseCommandOptions { position: IPosition; viewPosition: IPosition; - doColumnSelect: boolean; mouseColumn: number; + doColumnSelect: boolean; } export const ColumnSelect: CoreEditorCommand = registerEditorCommand(new class extends ColumnSelectCommand { @@ -1501,11 +1513,7 @@ export namespace CoreNavigationCommands { } }); - export interface WordCommandOptions extends BaseCommandOptions { - position: IPosition; - } - - class WordCommand extends CoreEditorCommand { + class WordCommand extends CoreEditorCommand { private readonly _inSelectionMode: boolean; @@ -1514,7 +1522,7 @@ export namespace CoreNavigationCommands { this._inSelectionMode = opts.inSelectionMode; } - public runCoreEditorCommand(viewModel: IViewModel, args: Partial): void { + public runCoreEditorCommand(viewModel: IViewModel, args: Partial): void { if (!args.position) { return; } @@ -1526,23 +1534,25 @@ export namespace CoreNavigationCommands { CursorMoveCommands.word(viewModel, viewModel.getPrimaryCursorState(), this._inSelectionMode, args.position) ] ); - viewModel.revealPrimaryCursor(args.source, true); + if (args.revealType !== NavigationCommandRevealType.None) { + viewModel.revealPrimaryCursor(args.source, true, true); + } } } - export const WordSelect: CoreEditorCommand = registerEditorCommand(new WordCommand({ + export const WordSelect: CoreEditorCommand = registerEditorCommand(new WordCommand({ inSelectionMode: false, id: '_wordSelect', precondition: undefined })); - export const WordSelectDrag: CoreEditorCommand = registerEditorCommand(new WordCommand({ + export const WordSelectDrag: CoreEditorCommand = registerEditorCommand(new WordCommand({ inSelectionMode: true, id: '_wordSelectDrag', precondition: undefined })); - export const LastCursorWordSelect: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand { + export const LastCursorWordSelect: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand { constructor() { super({ id: 'lastCursorWordSelect', @@ -1550,7 +1560,7 @@ export namespace CoreNavigationCommands { }); } - public runCoreEditorCommand(viewModel: IViewModel, args: Partial): void { + public runCoreEditorCommand(viewModel: IViewModel, args: Partial): void { if (!args.position) { return; } @@ -1590,7 +1600,9 @@ export namespace CoreNavigationCommands { CursorMoveCommands.line(viewModel, viewModel.getPrimaryCursorState(), this._inSelectionMode, args.position, args.viewPosition) ] ); - viewModel.revealPrimaryCursor(args.source, false); + if (args.revealType !== NavigationCommandRevealType.None) { + viewModel.revealPrimaryCursor(args.source, false, true); + } } } diff --git a/src/vs/editor/browser/view.ts b/src/vs/editor/browser/view.ts index a05fae66338..6ee27a31b3f 100644 --- a/src/vs/editor/browser/view.ts +++ b/src/vs/editor/browser/view.ts @@ -245,6 +245,9 @@ export class View extends ViewEventHandler { const lastTextareaPosition = this._textAreaHandler.getLastRenderData(); return new PointerHandlerLastRenderData(lastViewCursorsRenderData, lastTextareaPosition); }, + renderNow: (): void => { + this.render(true, false); + }, shouldSuppressMouseDownOnViewZone: (viewZoneId: string) => { return this._viewZones.shouldSuppressMouseDownOnViewZone(viewZoneId); }, diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index 41d9b58a129..b6b8ebdd698 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { CoreNavigationCommands } from 'vs/editor/browser/coreCommands'; +import { CoreNavigationCommands, NavigationCommandRevealType } from 'vs/editor/browser/coreCommands'; import { IEditorMouseEvent, IPartialEditorMouseEvent } from 'vs/editor/browser/editorBrowser'; import { ViewUserInputEvents } from 'vs/editor/browser/view/viewUserInputEvents'; import { Position } from 'vs/editor/common/core/position'; @@ -21,6 +21,7 @@ export interface IMouseDispatchData { * Desired mouse column (e.g. when position.column gets clamped to text length -- clicking after text on a line). */ mouseColumn: number; + revealType: NavigationCommandRevealType; startedOnLineNumbers: boolean; inSelectionMode: boolean; @@ -138,15 +139,15 @@ export class ViewController { // If the dragging started on the gutter, then have operations work on the entire line if (this._hasMulticursorModifier(data)) { if (data.inSelectionMode) { - this._lastCursorLineSelect(data.position); + this._lastCursorLineSelect(data.position, data.revealType); } else { this._createCursor(data.position, true); } } else { if (data.inSelectionMode) { - this._lineSelectDrag(data.position); + this._lineSelectDrag(data.position, data.revealType); } else { - this._lineSelect(data.position); + this._lineSelect(data.position, data.revealType); } } } else if (data.mouseDownCount >= 4) { @@ -154,26 +155,26 @@ export class ViewController { } else if (data.mouseDownCount === 3) { if (this._hasMulticursorModifier(data)) { if (data.inSelectionMode) { - this._lastCursorLineSelectDrag(data.position); + this._lastCursorLineSelectDrag(data.position, data.revealType); } else { - this._lastCursorLineSelect(data.position); + this._lastCursorLineSelect(data.position, data.revealType); } } else { if (data.inSelectionMode) { - this._lineSelectDrag(data.position); + this._lineSelectDrag(data.position, data.revealType); } else { - this._lineSelect(data.position); + this._lineSelect(data.position, data.revealType); } } } else if (data.mouseDownCount === 2) { if (!data.onInjectedText) { if (this._hasMulticursorModifier(data)) { - this._lastCursorWordSelect(data.position); + this._lastCursorWordSelect(data.position, data.revealType); } else { if (data.inSelectionMode) { - this._wordSelectDrag(data.position); + this._wordSelectDrag(data.position, data.revealType); } else { - this._wordSelect(data.position); + this._wordSelect(data.position, data.revealType); } } } @@ -185,7 +186,7 @@ export class ViewController { } else { // Do multi-cursor operations only when purely alt is pressed if (data.inSelectionMode) { - this._lastCursorMoveToSelect(data.position); + this._lastCursorMoveToSelect(data.position, data.revealType); } else { this._createCursor(data.position, false); } @@ -199,31 +200,32 @@ export class ViewController { if (columnSelection) { this._columnSelect(data.position, data.mouseColumn, true); } else { - this._moveToSelect(data.position); + this._moveToSelect(data.position, data.revealType); } } } else { - this.moveTo(data.position); + this.moveTo(data.position, data.revealType); } } } } - private _usualArgs(viewPosition: Position) { + private _usualArgs(viewPosition: Position, revealType: NavigationCommandRevealType): CoreNavigationCommands.MoveCommandOptions { viewPosition = this._validateViewColumn(viewPosition); return { source: 'mouse', position: this._convertViewToModelPosition(viewPosition), - viewPosition: viewPosition + viewPosition, + revealType }; } - public moveTo(viewPosition: Position): void { - CoreNavigationCommands.MoveTo.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + public moveTo(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.MoveTo.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } - private _moveToSelect(viewPosition: Position): void { - CoreNavigationCommands.MoveToSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + private _moveToSelect(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.MoveToSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } private _columnSelect(viewPosition: Position, mouseColumn: number, doColumnSelect: boolean): void { @@ -247,36 +249,36 @@ export class ViewController { }); } - private _lastCursorMoveToSelect(viewPosition: Position): void { - CoreNavigationCommands.LastCursorMoveToSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + private _lastCursorMoveToSelect(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.LastCursorMoveToSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } - private _wordSelect(viewPosition: Position): void { - CoreNavigationCommands.WordSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + private _wordSelect(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.WordSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } - private _wordSelectDrag(viewPosition: Position): void { - CoreNavigationCommands.WordSelectDrag.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + private _wordSelectDrag(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.WordSelectDrag.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } - private _lastCursorWordSelect(viewPosition: Position): void { - CoreNavigationCommands.LastCursorWordSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + private _lastCursorWordSelect(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.LastCursorWordSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } - private _lineSelect(viewPosition: Position): void { - CoreNavigationCommands.LineSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + private _lineSelect(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.LineSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } - private _lineSelectDrag(viewPosition: Position): void { - CoreNavigationCommands.LineSelectDrag.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + private _lineSelectDrag(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.LineSelectDrag.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } - private _lastCursorLineSelect(viewPosition: Position): void { - CoreNavigationCommands.LastCursorLineSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + private _lastCursorLineSelect(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.LastCursorLineSelect.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } - private _lastCursorLineSelectDrag(viewPosition: Position): void { - CoreNavigationCommands.LastCursorLineSelectDrag.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition)); + private _lastCursorLineSelectDrag(viewPosition: Position, revealType: NavigationCommandRevealType): void { + CoreNavigationCommands.LastCursorLineSelectDrag.runCoreEditorCommand(this.viewModel, this._usualArgs(viewPosition, revealType)); } private _selectAll(): void { diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index 805395c190b..8ca24cfe42b 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -102,7 +102,6 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, private _typicalHalfwidthCharacterWidth: number; private _isViewportWrapping: boolean; private _revealHorizontalRightPadding: number; - private _horizontalScrollbarHeight: number; private _cursorSurroundingLines: number; private _cursorSurroundingLinesStyle: 'default' | 'all'; private _canUseLayerHinting: boolean; @@ -131,13 +130,11 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, const options = this._context.configuration.options; const fontInfo = options.get(EditorOption.fontInfo); const wrappingInfo = options.get(EditorOption.wrappingInfo); - const layoutInfo = options.get(EditorOption.layoutInfo); this._lineHeight = options.get(EditorOption.lineHeight); this._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth; this._isViewportWrapping = wrappingInfo.isViewportWrapping; this._revealHorizontalRightPadding = options.get(EditorOption.revealHorizontalRightPadding); - this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight; this._cursorSurroundingLines = options.get(EditorOption.cursorSurroundingLines); this._cursorSurroundingLinesStyle = options.get(EditorOption.cursorSurroundingLinesStyle); this._canUseLayerHinting = !options.get(EditorOption.disableLayerHinting); @@ -194,13 +191,11 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, const options = this._context.configuration.options; const fontInfo = options.get(EditorOption.fontInfo); const wrappingInfo = options.get(EditorOption.wrappingInfo); - const layoutInfo = options.get(EditorOption.layoutInfo); this._lineHeight = options.get(EditorOption.lineHeight); this._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth; this._isViewportWrapping = wrappingInfo.isViewportWrapping; this._revealHorizontalRightPadding = options.get(EditorOption.revealHorizontalRightPadding); - this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight; this._cursorSurroundingLines = options.get(EditorOption.cursorSurroundingLines); this._cursorSurroundingLinesStyle = options.get(EditorOption.cursorSurroundingLinesStyle); this._canUseLayerHinting = !options.get(EditorOption.disableLayerHinting); @@ -697,9 +692,11 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost, paddingTop = this._lineHeight; } } - if (verticalType === viewEvents.VerticalRevealType.Simple || verticalType === viewEvents.VerticalRevealType.Bottom) { - // Reveal one line more when the last line would be covered by the scrollbar - arrow down case or revealing a line explicitly at bottom - paddingBottom += (minimalReveal ? this._horizontalScrollbarHeight : this._lineHeight); + if (!minimalReveal) { + if (verticalType === viewEvents.VerticalRevealType.Simple || verticalType === viewEvents.VerticalRevealType.Bottom) { + // Reveal one line more when the last line would be covered by the scrollbar - arrow down case or revealing a line explicitly at bottom + paddingBottom += this._lineHeight; + } } boxStartY -= paddingTop;