src/vs/editor/browser/controller/mouseHandler.ts/MouseHandler/constructor
class MouseHandler:	constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
		super();

		this._context = context;
		this.viewController = viewController;
		this.viewHelper = viewHelper;
		this.mouseTargetFactory = new MouseTargetFactory(this._context, viewHelper);

		this._mouseDownOperation = this._register(new MouseDownOperation(
			this._context,
			this.viewController,
			this.viewHelper,
			this.mouseTargetFactory,
			(e, testEventTarget) => this._createMouseTarget(e, testEventTarget),
			(e) => this._getMouseColumn(e)
		));

		this.lastMouseLeaveTime = -1;
		this._height = this._context.configuration.options.get(EditorOption.layoutInfo).height;

		const mouseEvents = new EditorMouseEventFactory(this.viewHelper.viewDomNode);

		this._register(mouseEvents.onContextMenu(this.viewHelper.viewDomNode, (e) => this._onContextMenu(e, true)));

		this._register(mouseEvents.onMouseMove(this.viewHelper.viewDomNode, (e) => {
			this._onMouseMove(e);

			// See https://github.com/microsoft/vscode/issues/138789
			// When moving the mouse really quickly, the browser sometimes forgets to
			// send us a `mouseleave` or `mouseout` event. We therefore install here
			// a global `mousemove` listener to manually recover if the mouse goes outside
			// the editor. As soon as the mouse leaves outside of the editor, we
			// remove this listener

			if (!this._mouseLeaveMonitor) {
				this._mouseLeaveMonitor = dom.addDisposableListener(document, 'mousemove', (e) => {
					if (!this.viewHelper.viewDomNode.contains(e.target as Node | null)) {
						// went outside the editor!
						this._onMouseLeave(new EditorMouseEvent(e, false, this.viewHelper.viewDomNode));
					}
				});
			}
		}));

		this._register(mouseEvents.onMouseUp(this.viewHelper.viewDomNode, (e) => this._onMouseUp(e)));

		this._register(mouseEvents.onMouseLeave(this.viewHelper.viewDomNode, (e) => this._onMouseLeave(e)));

		// `pointerdown` events can't be used to determine if there's a double click, or triple click
		// because their `e.detail` is always 0.
		// We will therefore save the pointer id for the mouse and then reuse it in the `mousedown` event
		// for `element.setPointerCapture`.
		let capturePointerId: number = 0;
		this._register(mouseEvents.onPointerDown(this.viewHelper.viewDomNode, (e, pointerId) => {
			capturePointerId = pointerId;
		}));
		// The `pointerup` listener registered by `GlobalEditorPointerMoveMonitor` does not get invoked 100% of the times.
		// I speculate that this is because the `pointerup` listener is only registered during the `mousedown` event, and perhaps
		// the `pointerup` event is already queued for dispatching, which makes it that the new listener doesn't get fired.
		// See https://github.com/microsoft/vscode/issues/146486 for repro steps.
		// To compensate for that, we simply register here a `pointerup` listener and just communicate it.
		this._register(dom.addDisposableListener(this.viewHelper.viewDomNode, dom.EventType.POINTER_UP, (e: PointerEvent) => {
			this._mouseDownOperation.onPointerUp();
		}));
		this._register(mouseEvents.onMouseDown(this.viewHelper.viewDomNode, (e) => this._onMouseDown(e, capturePointerId)));

		const onMouseWheel = (browserEvent: IMouseWheelEvent) => {
			this.viewController.emitMouseWheel(browserEvent);

			if (!this._context.configuration.options.get(EditorOption.mouseWheelZoom)) {
				return;
			}
			const e = new StandardWheelEvent(browserEvent);
			const doMouseWheelZoom = (
				platform.isMacintosh
					// on macOS we support cmd + two fingers scroll (`metaKey` set)
					// and also the two fingers pinch gesture (`ctrKey` set)
					? ((browserEvent.metaKey || browserEvent.ctrlKey) && !browserEvent.shiftKey && !browserEvent.altKey)
					: (browserEvent.ctrlKey && !browserEvent.metaKey && !browserEvent.shiftKey && !browserEvent.altKey)
			);
			if (doMouseWheelZoom) {
				const zoomLevel: number = EditorZoom.getZoomLevel();
				const delta = e.deltaY > 0 ? 1 : -1;
				EditorZoom.setZoomLevel(zoomLevel + delta);
				e.preventDefault();
				e.stopPropagation();
			}
		};
		this._register(dom.addDisposableListener(this.viewHelper.viewDomNode, dom.EventType.MOUSE_WHEEL, onMouseWheel, { capture: true, passive: false }));

		this._context.addEventHandler(this);
	}