未验证 提交 50895031 编写于 作者: A Alex Dima

Fixes #83150: Handle case where the mouse is hitting the textarea when the...

Fixes #83150: Handle case where the mouse is hitting the textarea when the textarea is rendered at the cursor
上级 e038d4a6
......@@ -9,11 +9,10 @@ import { StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent
import { RunOnceScheduler, TimeoutTimer } from 'vs/base/common/async';
import { Disposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
import { HitTestContext, IViewZoneData, MouseTarget, MouseTargetFactory } from 'vs/editor/browser/controller/mouseTarget';
import { HitTestContext, IViewZoneData, MouseTarget, MouseTargetFactory, PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorMouseMoveMonitor, createEditorPagePosition } from 'vs/editor/browser/editorDom';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
import { Position } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
......@@ -46,9 +45,9 @@ export interface IPointerHandlerHelper {
focusTextArea(): void;
/**
* Get the last rendered information of the cursors.
* Get the last rendered information for cursors & textarea.
*/
getLastViewCursorsRenderData(): IViewCursorRenderData[];
getLastRenderData(): PointerHandlerLastRenderData;
shouldSuppressMouseDownOnViewZone(viewZoneId: string): boolean;
shouldSuppressMouseDownOnWidget(widgetId: string): boolean;
......@@ -158,13 +157,11 @@ export class MouseHandler extends ViewEventHandler {
return null;
}
const lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData();
return this.mouseTargetFactory.createMouseTarget(lastViewCursorsRenderData, editorPos, pos, null);
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), editorPos, pos, null);
}
protected _createMouseTarget(e: EditorMouseEvent, testEventTarget: boolean): editorBrowser.IMouseTarget {
const lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData();
return this.mouseTargetFactory.createMouseTarget(lastViewCursorsRenderData, e.editorPos, e.pos, testEventTarget ? e.target : null);
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), e.editorPos, e.pos, testEventTarget ? e.target : null);
}
private _getMouseColumn(e: EditorMouseEvent): number {
......
......@@ -89,6 +89,13 @@ interface IHitTestResult {
hitTarget: Element | null;
}
export class PointerHandlerLastRenderData {
constructor(
public readonly lastViewCursorsRenderData: IViewCursorRenderData[],
public readonly lastTextareaPosition: Position | null
) { }
}
export class MouseTarget implements IMouseTarget {
public readonly element: Element | null;
......@@ -232,19 +239,19 @@ export class HitTestContext {
public readonly viewDomNode: HTMLElement;
public readonly lineHeight: number;
public readonly typicalHalfwidthCharacterWidth: number;
public readonly lastViewCursorsRenderData: IViewCursorRenderData[];
public readonly lastRenderData: PointerHandlerLastRenderData;
private readonly _context: ViewContext;
private readonly _viewHelper: IPointerHandlerHelper;
constructor(context: ViewContext, viewHelper: IPointerHandlerHelper, lastViewCursorsRenderData: IViewCursorRenderData[]) {
constructor(context: ViewContext, viewHelper: IPointerHandlerHelper, lastRenderData: PointerHandlerLastRenderData) {
this.model = context.model;
const options = context.configuration.options;
this.layoutInfo = options.get(EditorOption.layoutInfo);
this.viewDomNode = viewHelper.viewDomNode;
this.lineHeight = options.get(EditorOption.lineHeight);
this.typicalHalfwidthCharacterWidth = options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth;
this.lastViewCursorsRenderData = lastViewCursorsRenderData;
this.lastRenderData = lastRenderData;
this._context = context;
this._viewHelper = viewHelper;
}
......@@ -462,8 +469,8 @@ export class MouseTargetFactory {
return false;
}
public createMouseTarget(lastViewCursorsRenderData: IViewCursorRenderData[], editorPos: EditorPagePosition, pos: PageCoordinates, target: HTMLElement | null): IMouseTarget {
const ctx = new HitTestContext(this._context, this._viewHelper, lastViewCursorsRenderData);
public createMouseTarget(lastRenderData: PointerHandlerLastRenderData, editorPos: EditorPagePosition, pos: PageCoordinates, target: HTMLElement | null): IMouseTarget {
const ctx = new HitTestContext(this._context, this._viewHelper, lastRenderData);
const request = new HitTestRequest(ctx, editorPos, pos, target);
try {
const r = MouseTargetFactory._createMouseTarget(ctx, request, false);
......@@ -544,7 +551,7 @@ export class MouseTargetFactory {
if (request.target) {
// Check if we've hit a painted cursor
const lastViewCursorsRenderData = ctx.lastViewCursorsRenderData;
const lastViewCursorsRenderData = ctx.lastRenderData.lastViewCursorsRenderData;
for (const d of lastViewCursorsRenderData) {
......@@ -560,7 +567,7 @@ export class MouseTargetFactory {
// first or last rendered view line dom node, therefore help it out
// and first check if we are on top of a cursor
const lastViewCursorsRenderData = ctx.lastViewCursorsRenderData;
const lastViewCursorsRenderData = ctx.lastRenderData.lastViewCursorsRenderData;
const mouseContentHorizontalOffset = request.mouseContentHorizontalOffset;
const mouseVerticalOffset = request.mouseVerticalOffset;
......@@ -602,7 +609,10 @@ export class MouseTargetFactory {
private static _hitTestTextArea(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
// Is it the textarea?
if (ElementPath.isTextArea(request.targetPath)) {
return request.fulfill(MouseTargetType.TEXTAREA);
if (ctx.lastRenderData.lastTextareaPosition) {
return request.fulfill(MouseTargetType.CONTENT_TEXT, ctx.lastRenderData.lastTextareaPosition);
}
return request.fulfill(MouseTargetType.TEXTAREA, ctx.lastRenderData.lastTextareaPosition);
}
return null;
}
......
......@@ -77,6 +77,12 @@ export class TextAreaHandler extends ViewPart {
private _visibleTextArea: VisibleTextAreaData | null;
private _selections: Selection[];
/**
* The position at which the textarea was rendered.
* This is useful for hit-testing and determining the mouse position.
*/
private _lastRenderPosition: Position | null;
public readonly textArea: FastDomNode<HTMLTextAreaElement>;
public readonly textAreaCover: FastDomNode<HTMLElement>;
private readonly _textAreaInput: TextAreaInput;
......@@ -104,6 +110,7 @@ export class TextAreaHandler extends ViewPart {
this._visibleTextArea = null;
this._selections = [new Selection(1, 1, 1, 1)];
this._lastRenderPosition = null;
// Text Area (The focus will always be in the textarea when the cursor is blinking)
this.textArea = createFastDomNode(document.createElement('textarea'));
......@@ -413,13 +420,18 @@ export class TextAreaHandler extends ViewPart {
this._textAreaInput.refreshFocusState();
}
public getLastRenderData(): Position | null {
return this._lastRenderPosition;
}
// --- end view API
private _primaryCursorPosition: Position = new Position(1, 1);
private _primaryCursorVisibleRange: HorizontalPosition | null = null;
public prepareRender(ctx: RenderingContext): void {
const primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(primaryCursorPosition);
this._primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(this._primaryCursorPosition);
}
public render(ctx: RestrictedRenderingContext): void {
......@@ -431,6 +443,7 @@ export class TextAreaHandler extends ViewPart {
if (this._visibleTextArea) {
// The text area is visible for composition reasons
this._renderInsideEditor(
null,
this._visibleTextArea.top - this._scrollTop,
this._contentLeft + this._visibleTextArea.left - this._scrollLeft,
this._visibleTextArea.width,
......@@ -465,6 +478,7 @@ export class TextAreaHandler extends ViewPart {
// For the popup emoji input, we will make the text area as high as the line height
// We will also make the fontSize and lineHeight the correct dimensions to help with the placement of these pickers
this._renderInsideEditor(
this._primaryCursorPosition,
top, left,
canUseZeroSizeTextarea ? 0 : 1, this._lineHeight
);
......@@ -472,12 +486,14 @@ export class TextAreaHandler extends ViewPart {
}
this._renderInsideEditor(
this._primaryCursorPosition,
top, left,
canUseZeroSizeTextarea ? 0 : 1, canUseZeroSizeTextarea ? 0 : 1
);
}
private _renderInsideEditor(top: number, left: number, width: number, height: number): void {
private _renderInsideEditor(renderedPosition: Position | null, top: number, left: number, width: number, height: number): void {
this._lastRenderPosition = renderedPosition;
const ta = this.textArea;
const tac = this.textAreaCover;
......@@ -495,6 +511,7 @@ export class TextAreaHandler extends ViewPart {
}
private _renderAtTopLeft(): void {
this._lastRenderPosition = null;
const ta = this.textArea;
const tac = this.textAreaCover;
......
......@@ -48,6 +48,7 @@ import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { IThemeService, getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget';
export interface IContentWidgetData {
......@@ -244,8 +245,10 @@ export class View extends ViewEventHandler {
this.focus();
},
getLastViewCursorsRenderData: () => {
return this.viewCursors.getLastRenderData() || [];
getLastRenderData: (): PointerHandlerLastRenderData => {
const lastViewCursorsRenderData = this.viewCursors.getLastRenderData() || [];
const lastTextareaPosition = this._textAreaHandler.getLastRenderData();
return new PointerHandlerLastRenderData(lastViewCursorsRenderData, lastTextareaPosition);
},
shouldSuppressMouseDownOnViewZone: (viewZoneId: string) => {
return this.viewZones.shouldSuppressMouseDownOnViewZone(viewZoneId);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册