Skip to content

Commit ee30d44

Browse files
authored
use mousewheel to dismiss contextmenu in monaco (microsoft#71623)
* use mousewheel to dismiss contextmenu in monaco fixes microsoft#54594 * make internal * fixes scrollbar clicking to dismiss in monaco also handles glyph margin issue microsoft#70388 * data=true
1 parent 550ecb8 commit ee30d44

8 files changed

Lines changed: 63 additions & 5 deletions

File tree

src/vs/base/browser/mouseEvent.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,13 @@ export class DragMouseEvent extends StandardMouseEvent {
115115

116116
export interface IMouseWheelEvent extends MouseEvent {
117117
readonly wheelDelta: number;
118+
readonly wheelDeltaX: number;
119+
readonly wheelDeltaY: number;
120+
121+
readonly deltaX: number;
122+
readonly deltaY: number;
123+
readonly deltaZ: number;
124+
readonly deltaMode: number;
118125
}
119126

120127
interface IWebKitMouseWheelEvent {

src/vs/editor/browser/controller/mouseHandler.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ export class MouseHandler extends ViewEventHandler {
109109
this._register(mouseEvents.onMouseDown(this.viewHelper.viewDomNode, (e) => this._onMouseDown(e)));
110110

111111
const onMouseWheel = (browserEvent: IMouseWheelEvent) => {
112+
this.viewController.emitMouseWheel(browserEvent);
113+
112114
if (!this._context.configuration.editor.viewInfo.mouseWheelZoom) {
113115
return;
114116
}
@@ -259,6 +261,10 @@ export class MouseHandler extends ViewEventHandler {
259261
target: t
260262
});
261263
}
264+
265+
public _onMouseWheel(e: IMouseWheelEvent): void {
266+
this.viewController.emitMouseWheel(e);
267+
}
262268
}
263269

264270
class MouseDownOperation extends Disposable {

src/vs/editor/browser/editorBrowser.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
7-
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
7+
import { IMouseEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
88
import { IDisposable } from 'vs/base/common/lifecycle';
99
import * as editorOptions from 'vs/editor/common/config/editorOptions';
1010
import { ICursors } from 'vs/editor/common/controller/cursorCommon';
@@ -461,6 +461,12 @@ export interface ICodeEditor extends editorCommon.IEditor {
461461
* @event
462462
*/
463463
onMouseLeave(listener: (e: IPartialEditorMouseEvent) => void): IDisposable;
464+
/**
465+
* An event emitted on a "mousewheel"
466+
* @event
467+
* @internal
468+
*/
469+
onMouseWheel(listener: (e: IMouseWheelEvent) => void): IDisposable;
464470
/**
465471
* An event emitted on a "keyup".
466472
* @event

src/vs/editor/browser/view/viewController.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Position } from 'vs/editor/common/core/position';
1111
import { Selection } from 'vs/editor/common/core/selection';
1212
import { IConfiguration } from 'vs/editor/common/editorCommon';
1313
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
14+
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
1415

1516
export interface IMouseDispatchData {
1617
position: Position;
@@ -316,4 +317,8 @@ export class ViewController {
316317
public emitMouseDrop(e: IPartialEditorMouseEvent): void {
317318
this.outgoingEvents.emitMouseDrop(e);
318319
}
320+
321+
public emitMouseWheel(e: IMouseWheelEvent): void {
322+
this.outgoingEvents.emitMouseWheel(e);
323+
}
319324
}

src/vs/editor/browser/view/viewOutgoingEvents.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Range } from 'vs/editor/common/core/range';
1212
import { IScrollEvent } from 'vs/editor/common/editorCommon';
1313
import * as viewEvents from 'vs/editor/common/view/viewEvents';
1414
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
15+
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
1516

1617
export interface EventCallback<T> {
1718
(event: T): void;
@@ -31,6 +32,7 @@ export class ViewOutgoingEvents extends Disposable {
3132
public onMouseDown: EventCallback<IEditorMouseEvent> | null = null;
3233
public onMouseDrag: EventCallback<IEditorMouseEvent> | null = null;
3334
public onMouseDrop: EventCallback<IPartialEditorMouseEvent> | null = null;
35+
public onMouseWheel: EventCallback<IMouseWheelEvent> | null = null;
3436

3537
private readonly _viewModel: IViewModel;
3638

@@ -111,6 +113,12 @@ export class ViewOutgoingEvents extends Disposable {
111113
}
112114
}
113115

116+
public emitMouseWheel(e: IMouseWheelEvent): void {
117+
if (this.onMouseWheel) {
118+
this.onMouseWheel(e);
119+
}
120+
}
121+
114122
private _convertViewToModelMouseEvent(e: IEditorMouseEvent): IEditorMouseEvent;
115123
private _convertViewToModelMouseEvent(e: IPartialEditorMouseEvent): IPartialEditorMouseEvent;
116124
private _convertViewToModelMouseEvent(e: IEditorMouseEvent | IPartialEditorMouseEvent): IEditorMouseEvent | IPartialEditorMouseEvent {

src/vs/editor/browser/widget/codeEditorWidget.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import 'vs/css!./media/tokens';
88
import * as nls from 'vs/nls';
99
import * as dom from 'vs/base/browser/dom';
1010
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
11-
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
11+
import { IMouseEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
1212
import { Color } from 'vs/base/common/color';
1313
import { onUnexpectedError } from 'vs/base/common/errors';
1414
import { Emitter, Event } from 'vs/base/common/event';
@@ -186,6 +186,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
186186
private readonly _onMouseLeave: Emitter<editorBrowser.IPartialEditorMouseEvent> = this._register(new Emitter<editorBrowser.IPartialEditorMouseEvent>());
187187
public readonly onMouseLeave: Event<editorBrowser.IPartialEditorMouseEvent> = this._onMouseLeave.event;
188188

189+
private readonly _onMouseWheel: Emitter<IMouseWheelEvent> = this._register(new Emitter<IMouseWheelEvent>());
190+
public readonly onMouseWheel: Event<IMouseWheelEvent> = this._onMouseWheel.event;
191+
189192
private readonly _onKeyUp: Emitter<IKeyboardEvent> = this._register(new Emitter<IKeyboardEvent>());
190193
public readonly onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event;
191194

@@ -1442,6 +1445,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
14421445
// In IE, the focus is not synchronous, so we give it a little help
14431446
this._editorWidgetFocus.setValue(true);
14441447
};
1448+
14451449
viewOutgoingEvents.onDidScroll = (e) => this._onDidScrollChange.fire(e);
14461450
viewOutgoingEvents.onDidLoseFocus = () => this._editorTextFocus.setValue(false);
14471451
viewOutgoingEvents.onContextMenu = (e) => this._onContextMenu.fire(e);
@@ -1452,6 +1456,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
14521456
viewOutgoingEvents.onKeyUp = (e) => this._onKeyUp.fire(e);
14531457
viewOutgoingEvents.onMouseMove = (e) => this._onMouseMove.fire(e);
14541458
viewOutgoingEvents.onMouseLeave = (e) => this._onMouseLeave.fire(e);
1459+
viewOutgoingEvents.onMouseWheel = (e) => this._onMouseWheel.fire(e);
14551460
viewOutgoingEvents.onKeyDown = (e) => this._onKeyDown.fire(e);
14561461

14571462
const view = new View(

src/vs/editor/contrib/contextmenu/contextmenu.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ import { KeyCode, KeyMod, ResolvedKeybinding } from 'vs/base/common/keyCodes';
1313
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
1414
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
1515
import { EditorAction, ServicesAccessor, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
16-
import { IEditorContribution, IScrollEvent, ScrollType } from 'vs/editor/common/editorCommon';
16+
import { IEditorContribution, ScrollType } from 'vs/editor/common/editorCommon';
1717
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
1818
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
1919
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
2020
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
2121
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
2222
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
2323
import { ITextModel } from 'vs/editor/common/model';
24+
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
2425

2526
export class ContextMenuController implements IEditorContribution {
2627

@@ -45,8 +46,8 @@ export class ContextMenuController implements IEditorContribution {
4546
this._editor = editor;
4647

4748
this._toDispose.push(this._editor.onContextMenu((e: IEditorMouseEvent) => this._onContextMenu(e)));
48-
this._toDispose.push(this._editor.onDidScrollChange((e: IScrollEvent) => {
49-
if (this._contextMenuIsBeingShownCount > 0 && e.scrollTopChanged) {
49+
this._toDispose.push(this._editor.onMouseWheel((e: IMouseWheelEvent) => {
50+
if (this._contextMenuIsBeingShownCount > 0) {
5051
this._contextViewService.hideContextView();
5152
}
5253
}));

src/vs/platform/contextview/browser/contextMenuHandler.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
1717
import { EventType, $, removeNode } from 'vs/base/browser/dom';
1818
import { attachMenuStyler } from 'vs/platform/theme/common/styler';
1919
import { domEvent } from 'vs/base/browser/event';
20+
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
2021

2122
export interface IContextMenuHandlerOptions {
2223
blockMouse: boolean;
@@ -83,6 +84,25 @@ export class ContextMenuHandler {
8384
menu.onDidCancel(() => this.contextViewService.hideContextView(true), null, menuDisposables);
8485
menu.onDidBlur(() => this.contextViewService.hideContextView(true), null, menuDisposables);
8586
domEvent(window, EventType.BLUR)(() => { this.contextViewService.hideContextView(true); }, null, menuDisposables);
87+
domEvent(window, EventType.MOUSE_DOWN)((e: MouseEvent) => {
88+
let event = new StandardMouseEvent(e);
89+
let element: HTMLElement | null = event.target;
90+
91+
// Don't do anything as we are likely creating a context menu
92+
if (event.rightButton) {
93+
return;
94+
}
95+
96+
while (element) {
97+
if (element === container) {
98+
return;
99+
}
100+
101+
element = element.parentElement;
102+
}
103+
104+
this.contextViewService.hideContextView(true);
105+
}, null, menuDisposables);
86106

87107
return combinedDisposable([...menuDisposables, menu]);
88108
},

0 commit comments

Comments
 (0)