Skip to content

Title-bar tooltips: anchor to cursor position instead of trigger rect (closer to native macOS) #532

@Kosinkadink

Description

@Kosinkadink

Follow-up to #530 (the macOS title-bar hover-tooltip fix).

Right now the bubble anchors to the trigger element's left edge and grows rightward (with a fallback to right-aligned on overflow). That's stable and predictable, but it doesn't match native macOS behaviour, where the tooltip appears near the cursor instead of the control's geometric edge.

Proposed behaviour

Pin-at-show-time (option 1 from the design discussion in T-019e156c-969d-76f9-970e-221951a7fd4c):

  • When the show-timer fires (or the hover-handoff fast path triggers), snapshot the current cursor coordinates.
  • Position the bubble at (cursorX + CURSOR_OFFSET_X, cursorY + CURSOR_OFFSET_Y) — roughly +12 / +18 to clear the pointer, matching Cocoa's offsets.
  • Once shown, the bubble does NOT follow further pointer moves inside the same trigger. macOS native tooltips behave this way too — they freeze on appearance.
  • Right-overflow fallback: if cursorX + offset + bubbleWidth > parent.right, anchor to the LEFT of the cursor instead (cursorX - offset - bubbleWidth).

Implementation sketch

Renderer (TitleBarApp.vue):

  • handleTooltipPointer already has event.clientX / clientY — store them in a lastCursor ref updated on every move.
  • fireShowTooltip reads lastCursor at call time so the snapshot is always the cursor's position when the tooltip actually shows (covers both the 400 ms delayed first-show and the immediate hover-handoff path).
  • Bridge payload: replace leftX / rightX / bottomY with cursorX / cursorY. Keep leftX / rightX only if we still want the trigger rect for the right-overflow fallback (otherwise compute it purely from cursor + parent bounds).

Preload + bridge type (comfyTitleBarPreload.ts): payload shape change.

Main (positionTooltipPopup in src/main/index.ts):

  • x = cursorX + CURSOR_OFFSET_X - SHADOW_GUTTER by default
  • Right-overflow fallback to left-of-cursor
  • Drop TOOLTIP_VERTICAL_GAP / bottomY plumbing — replaced by cursorY + CURSOR_OFFSET_Y

Tests (TitleBarApp.test.ts): signature update + an assertion that the x/y forwarded to the bridge are derived from the synthetic PointerEvent's clientX / clientY.

Why follow-up, not in #530

The trigger-anchored layout is already a clear improvement over the original centered version, and the cursor-anchored variant has its own design questions (offset constants, exact overflow strategy, possible interaction with the hover-handoff window). Worth a separate, focused PR.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions