Skip to content

Commit

Permalink
Cancel pending hover on mouse exit
Browse files Browse the repository at this point in the history
If the mouse exits before the HoverService has rendered its pop-up,
cancel the pending presentation of that pop-up.

Fixes eclipse-theia#14532

Signed-off-by: Christian W. Damus <[email protected]>
  • Loading branch information
cdamus committed Nov 26, 2024
1 parent 55e29ed commit aaad3aa
Showing 1 changed file with 26 additions and 1 deletion.
27 changes: 26 additions & 1 deletion packages/core/src/browser/hover-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,19 @@ export class HoverService {
return this._hoverHost;
}
protected pendingTimeout: Disposable | undefined;
protected pendingHoverCancellation: Disposable | undefined;
protected hoverTarget: HTMLElement | undefined;
protected lastHidHover = Date.now();
protected readonly disposeOnHide = new DisposableCollection();

requestHover(request: HoverRequest): void {
if (request.target !== this.hoverTarget) {
this.cancelHover();
this.pendingTimeout = disposableTimeout(() => this.renderHover(request), this.getHoverDelay());
const hoverDelay = this.getHoverDelay();
this.pendingTimeout = disposableTimeout(() => this.renderHover(request), hoverDelay);
if (hoverDelay > 0) {
this.cancelHoverOnMouseOut(request);
}
}
}

Expand All @@ -110,6 +115,8 @@ export class HoverService {
}

protected async renderHover(request: HoverRequest): Promise<void> {
this.cancelPendingHoverCancellation();

const host = this.hoverHost;
let firstChild: HTMLElement | undefined;
const { target, content, position, cssClasses } = request;
Expand Down Expand Up @@ -194,6 +201,12 @@ export class HoverService {
return position;
}

/** Cancel the pending cancellation of hover. */
protected cancelPendingHoverCancellation(): void {
this.pendingHoverCancellation?.dispose();
this.pendingHoverCancellation = undefined;
}

protected listenForMouseOut(): void {
const handleMouseMove = (e: MouseEvent) => {
if (e.target instanceof Node && !this.hoverHost.contains(e.target) && !this.hoverTarget?.contains(e.target)) {
Expand All @@ -204,6 +217,18 @@ export class HoverService {
this.disposeOnHide.push({ dispose: () => document.removeEventListener('mousemove', handleMouseMove) });
}

protected cancelHoverOnMouseOut(request: HoverRequest): void {
this.cancelPendingHoverCancellation();
const target = request.target;
const handleMouseLeave = (): void => {
this.cancelHover();
this.cancelPendingHoverCancellation();
};
target.addEventListener('mouseleave', handleMouseLeave);
this.pendingHoverCancellation = this.disposeOnHide.push(
Disposable.create(() => target.removeEventListener('mouseleave', handleMouseLeave)));
}

cancelHover(): void {
this.pendingTimeout?.dispose();
this.unRenderHover();
Expand Down

0 comments on commit aaad3aa

Please sign in to comment.