From ee30d44427cff2ccc0c7a012d44f58a88a781d99 Mon Sep 17 00:00:00 2001 From: SteVen Batten <6561887+sbatten@users.noreply.github.com> Date: Tue, 9 Apr 2019 11:13:34 -0700 Subject: [PATCH] use mousewheel to dismiss contextmenu in monaco (#71623) * use mousewheel to dismiss contextmenu in monaco fixes #54594 * make internal * fixes scrollbar clicking to dismiss in monaco also handles glyph margin issue #70388 * data=true --- src/vs/base/browser/mouseEvent.ts | 7 +++++++ .../editor/browser/controller/mouseHandler.ts | 6 ++++++ src/vs/editor/browser/editorBrowser.ts | 8 +++++++- src/vs/editor/browser/view/viewController.ts | 5 +++++ .../editor/browser/view/viewOutgoingEvents.ts | 8 ++++++++ .../editor/browser/widget/codeEditorWidget.ts | 7 ++++++- .../editor/contrib/contextmenu/contextmenu.ts | 7 ++++--- .../contextview/browser/contextMenuHandler.ts | 20 +++++++++++++++++++ 8 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/vs/base/browser/mouseEvent.ts b/src/vs/base/browser/mouseEvent.ts index 89ff65ec499..dee572ce892 100644 --- a/src/vs/base/browser/mouseEvent.ts +++ b/src/vs/base/browser/mouseEvent.ts @@ -115,6 +115,13 @@ export class DragMouseEvent extends StandardMouseEvent { export interface IMouseWheelEvent extends MouseEvent { readonly wheelDelta: number; + readonly wheelDeltaX: number; + readonly wheelDeltaY: number; + + readonly deltaX: number; + readonly deltaY: number; + readonly deltaZ: number; + readonly deltaMode: number; } interface IWebKitMouseWheelEvent { diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index b3b447201c6..4a2dc7661c9 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -109,6 +109,8 @@ export class MouseHandler extends ViewEventHandler { this._register(mouseEvents.onMouseDown(this.viewHelper.viewDomNode, (e) => this._onMouseDown(e))); const onMouseWheel = (browserEvent: IMouseWheelEvent) => { + this.viewController.emitMouseWheel(browserEvent); + if (!this._context.configuration.editor.viewInfo.mouseWheelZoom) { return; } @@ -259,6 +261,10 @@ export class MouseHandler extends ViewEventHandler { target: t }); } + + public _onMouseWheel(e: IMouseWheelEvent): void { + this.viewController.emitMouseWheel(e); + } } class MouseDownOperation extends Disposable { diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 2cac1dc82d9..496e9cae7ab 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { IMouseEvent } from 'vs/base/browser/mouseEvent'; +import { IMouseEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { IDisposable } from 'vs/base/common/lifecycle'; import * as editorOptions from 'vs/editor/common/config/editorOptions'; import { ICursors } from 'vs/editor/common/controller/cursorCommon'; @@ -461,6 +461,12 @@ export interface ICodeEditor extends editorCommon.IEditor { * @event */ onMouseLeave(listener: (e: IPartialEditorMouseEvent) => void): IDisposable; + /** + * An event emitted on a "mousewheel" + * @event + * @internal + */ + onMouseWheel(listener: (e: IMouseWheelEvent) => void): IDisposable; /** * An event emitted on a "keyup". * @event diff --git a/src/vs/editor/browser/view/viewController.ts b/src/vs/editor/browser/view/viewController.ts index 7c7db40a3cf..d2389995052 100644 --- a/src/vs/editor/browser/view/viewController.ts +++ b/src/vs/editor/browser/view/viewController.ts @@ -11,6 +11,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Selection } from 'vs/editor/common/core/selection'; import { IConfiguration } from 'vs/editor/common/editorCommon'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; +import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; export interface IMouseDispatchData { position: Position; @@ -316,4 +317,8 @@ export class ViewController { public emitMouseDrop(e: IPartialEditorMouseEvent): void { this.outgoingEvents.emitMouseDrop(e); } + + public emitMouseWheel(e: IMouseWheelEvent): void { + this.outgoingEvents.emitMouseWheel(e); + } } diff --git a/src/vs/editor/browser/view/viewOutgoingEvents.ts b/src/vs/editor/browser/view/viewOutgoingEvents.ts index ca110d888c8..dce98187295 100644 --- a/src/vs/editor/browser/view/viewOutgoingEvents.ts +++ b/src/vs/editor/browser/view/viewOutgoingEvents.ts @@ -12,6 +12,7 @@ import { Range } from 'vs/editor/common/core/range'; import { IScrollEvent } from 'vs/editor/common/editorCommon'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; +import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; export interface EventCallback { (event: T): void; @@ -31,6 +32,7 @@ export class ViewOutgoingEvents extends Disposable { public onMouseDown: EventCallback | null = null; public onMouseDrag: EventCallback | null = null; public onMouseDrop: EventCallback | null = null; + public onMouseWheel: EventCallback | null = null; private readonly _viewModel: IViewModel; @@ -111,6 +113,12 @@ export class ViewOutgoingEvents extends Disposable { } } + public emitMouseWheel(e: IMouseWheelEvent): void { + if (this.onMouseWheel) { + this.onMouseWheel(e); + } + } + private _convertViewToModelMouseEvent(e: IEditorMouseEvent): IEditorMouseEvent; private _convertViewToModelMouseEvent(e: IPartialEditorMouseEvent): IPartialEditorMouseEvent; private _convertViewToModelMouseEvent(e: IEditorMouseEvent | IPartialEditorMouseEvent): IEditorMouseEvent | IPartialEditorMouseEvent { diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 4d63f087c89..8db9d0ab91c 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -8,7 +8,7 @@ import 'vs/css!./media/tokens'; import * as nls from 'vs/nls'; import * as dom from 'vs/base/browser/dom'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { IMouseEvent } from 'vs/base/browser/mouseEvent'; +import { IMouseEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { Color } from 'vs/base/common/color'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; @@ -186,6 +186,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE private readonly _onMouseLeave: Emitter = this._register(new Emitter()); public readonly onMouseLeave: Event = this._onMouseLeave.event; + private readonly _onMouseWheel: Emitter = this._register(new Emitter()); + public readonly onMouseWheel: Event = this._onMouseWheel.event; + private readonly _onKeyUp: Emitter = this._register(new Emitter()); public readonly onKeyUp: Event = this._onKeyUp.event; @@ -1442,6 +1445,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE // In IE, the focus is not synchronous, so we give it a little help this._editorWidgetFocus.setValue(true); }; + viewOutgoingEvents.onDidScroll = (e) => this._onDidScrollChange.fire(e); viewOutgoingEvents.onDidLoseFocus = () => this._editorTextFocus.setValue(false); viewOutgoingEvents.onContextMenu = (e) => this._onContextMenu.fire(e); @@ -1452,6 +1456,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE viewOutgoingEvents.onKeyUp = (e) => this._onKeyUp.fire(e); viewOutgoingEvents.onMouseMove = (e) => this._onMouseMove.fire(e); viewOutgoingEvents.onMouseLeave = (e) => this._onMouseLeave.fire(e); + viewOutgoingEvents.onMouseWheel = (e) => this._onMouseWheel.fire(e); viewOutgoingEvents.onKeyDown = (e) => this._onKeyDown.fire(e); const view = new View( diff --git a/src/vs/editor/contrib/contextmenu/contextmenu.ts b/src/vs/editor/contrib/contextmenu/contextmenu.ts index dde109aa26f..8fa07282fd8 100644 --- a/src/vs/editor/contrib/contextmenu/contextmenu.ts +++ b/src/vs/editor/contrib/contextmenu/contextmenu.ts @@ -13,7 +13,7 @@ import { KeyCode, KeyMod, ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { EditorAction, ServicesAccessor, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; -import { IEditorContribution, IScrollEvent, ScrollType } from 'vs/editor/common/editorCommon'; +import { IEditorContribution, ScrollType } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { IMenuService, MenuId } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -21,6 +21,7 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ITextModel } from 'vs/editor/common/model'; +import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; export class ContextMenuController implements IEditorContribution { @@ -45,8 +46,8 @@ export class ContextMenuController implements IEditorContribution { this._editor = editor; this._toDispose.push(this._editor.onContextMenu((e: IEditorMouseEvent) => this._onContextMenu(e))); - this._toDispose.push(this._editor.onDidScrollChange((e: IScrollEvent) => { - if (this._contextMenuIsBeingShownCount > 0 && e.scrollTopChanged) { + this._toDispose.push(this._editor.onMouseWheel((e: IMouseWheelEvent) => { + if (this._contextMenuIsBeingShownCount > 0) { this._contextViewService.hideContextView(); } })); diff --git a/src/vs/platform/contextview/browser/contextMenuHandler.ts b/src/vs/platform/contextview/browser/contextMenuHandler.ts index 8290247bf82..3b7a0c51d5b 100644 --- a/src/vs/platform/contextview/browser/contextMenuHandler.ts +++ b/src/vs/platform/contextview/browser/contextMenuHandler.ts @@ -17,6 +17,7 @@ import { IContextMenuDelegate } from 'vs/base/browser/contextmenu'; import { EventType, $, removeNode } from 'vs/base/browser/dom'; import { attachMenuStyler } from 'vs/platform/theme/common/styler'; import { domEvent } from 'vs/base/browser/event'; +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; export interface IContextMenuHandlerOptions { blockMouse: boolean; @@ -83,6 +84,25 @@ export class ContextMenuHandler { menu.onDidCancel(() => this.contextViewService.hideContextView(true), null, menuDisposables); menu.onDidBlur(() => this.contextViewService.hideContextView(true), null, menuDisposables); domEvent(window, EventType.BLUR)(() => { this.contextViewService.hideContextView(true); }, null, menuDisposables); + domEvent(window, EventType.MOUSE_DOWN)((e: MouseEvent) => { + let event = new StandardMouseEvent(e); + let element: HTMLElement | null = event.target; + + // Don't do anything as we are likely creating a context menu + if (event.rightButton) { + return; + } + + while (element) { + if (element === container) { + return; + } + + element = element.parentElement; + } + + this.contextViewService.hideContextView(true); + }, null, menuDisposables); return combinedDisposable([...menuDisposables, menu]); }, -- GitLab