src/vs/base/browser/ui/iconLabel/iconLabelHover.ts/mouseMove
export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTMLElement, markdownTooltip: string | IIconLabelMarkdownString | undefined): IDisposable | undefined {
	if (!markdownTooltip) {
		return undefined;
	}

	const tooltip = getTooltipForCustom(markdownTooltip);

	let hoverPreparation: IDisposable | undefined;

	let hoverWidget: IDisposable | undefined;

	const mouseEnter = (e: MouseEvent) => {
		if (hoverPreparation) {
			return;
		}

		const tokenSource = new CancellationTokenSource();

		const mouseLeaveOrDown = (e: MouseEvent) => {
			const isMouseDown = e.type === dom.EventType.MOUSE_DOWN;
			if (isMouseDown) {
				hoverWidget?.dispose();
				hoverWidget = undefined;
			}
			if (isMouseDown || (<any>e).fromElement === htmlElement) {
				hoverPreparation?.dispose();
				hoverPreparation = undefined;
			}
		};
		const mouseLeaveDomListener = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_LEAVE, mouseLeaveOrDown, true);
		const mouseDownDownListener = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_DOWN, mouseLeaveOrDown, true);

		const target: IHoverDelegateTarget = {
			targetElements: [htmlElement],
			dispose: () => { }
		};

		let mouseMoveDomListener: IDisposable | undefined;
		if (hoverDelegate.placement === undefined || hoverDelegate.placement === 'mouse') {
			const mouseMove = (e: MouseEvent) => target.x = e.x + 10;
			mouseMoveDomListener = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_MOVE, mouseMove, true);
		}

		const showHover = async () => {
			if (hoverPreparation) {

				const hoverOptions = {
					text: localize('iconLabel.loading', "Loading..."),
					target,
					hoverPosition: HoverPosition.BELOW
				};
				hoverWidget?.dispose();
				hoverWidget = hoverDelegate.showHover(hoverOptions);

				const resolvedTooltip = (await tooltip(tokenSource.token)) ?? (!isString(markdownTooltip) ? markdownTooltip.markdownNotSupportedFallback : undefined);

				hoverWidget?.dispose();
				hoverWidget = undefined;

				// awaiting the tooltip could take a while. Make sure we're still preparing to hover.
				if (resolvedTooltip && hoverPreparation) {
					const hoverOptions = {
						text: resolvedTooltip,
						target,
						showPointer: hoverDelegate.placement === 'element',
						hoverPosition: HoverPosition.BELOW
					};

					hoverWidget = hoverDelegate.showHover(hoverOptions);
				}

			}
			mouseMoveDomListener?.dispose();
		};
		const timeout = new RunOnceScheduler(showHover, hoverDelegate.delay);
		timeout.schedule();

		hoverPreparation = toDisposable(() => {
			timeout.dispose();
			mouseMoveDomListener?.dispose();
			mouseDownDownListener.dispose();
			mouseLeaveDomListener.dispose();
			tokenSource.dispose(true);
		});
	};
	const mouseOverDomEmitter = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_OVER, mouseEnter, true);
	return toDisposable(() => {
		mouseOverDomEmitter.dispose();
		hoverPreparation?.dispose();
		hoverWidget?.dispose();
	});
}