Skip to content

macOS menubar: right-click context menu flashes and/or scrolls away on mouse move #802

Description

@hyknerf

Summary

On macOS (reproduced on macOS 27 beta with menubar 0.9.19), right-clicking the CodeBurn status item either:

  1. Flashes the context menu for a few ms then dismisses it, and/or
  2. Opens the menu but jumps/scrolls on the first mouse move — the top "Today · $X · N calls" row slides away under a ^ chevron.

Settings / Refresh / Updates / About / Quit are effectively unreachable or hard to use.

Left-click → popover is unaffected.

Environment

Related history

Change What it did Gap
#472 Restored right-click on macOS 27 via global rightMouseDown monitor + NSMenu.popUp Menu can appear but presentation timing/positioning is wrong
#509 Polished menu; anchored popUp at height + 6 to "clear the menu bar" Scroll-on-hover still happens on 27; coordinate comment assumed non-flipped geometry

There is no open issue tracking the flash or the jump after #472/#509.

Root causes

1. Flash — present on rightMouseDown

#472's global monitor listens for rightMouseDown, then DispatchQueue.main.async { popUp(...) }.

popUp starts menu tracking immediately. The matching rightMouseUp is treated as an outside click → menu dismisses in milliseconds.

Fix: monitor rightMouseUp instead. Present only after the click completes.

  • macOS ≤26: legacy button action already fires on rightMouseUp; global monitor also fires → existing 0.3s debounce keeps a single present.
  • macOS 27: legacy path still dead; global monitor on up is the only path (and no longer races mouse-up dismissal).

2. Jump — manual NSMenu.popUp(at:in:)

Even when the menu stays open, popUp(positioning:at:in: button) is a poor fit for status items:

  • NSStatusBarButton.isFlipped == true (verified): y = 0 is the top of the button, y = height is the bottom. feat(menubar): polish status-item menu + About tab (Star/Sponsor) #509's height + 6 is the right direction, but manual popUp still tracks against a point while the cursor sits on the status item above the menu.
  • First mouse move engages AppKit scroll mode^ chevron, first row ("Today · …") scrolls away.

Fix: stop using manual popUp for this menu. Use the status item's own menu slot so AppKit positions and tracks it:

menu.delegate = self
statusItem.menu = menu
button.performClick(nil)
// menuDidClose: statusItem.menu = nil  // restore left-click → popover action

#472 avoided statusItem.menu + performClick because assigning the menu from the right-mouse action never ran on 27. That is still true. We open from the global rightMouseUp monitor (or legacy action on ≤26), then attach statusItem.menu and performClick. At that point performClick is only "open the attached menu" and works on 27.

Clear statusItem.menu in menuDidClose so the next left-click hits the popover action again.

Proposed change

Single file: mac/Sources/CodeBurnMenubar/CodeBurnApp.swift

  1. Global monitor: .rightMouseDown.rightMouseUp
  2. showContextMenu: statusItem.menu = menu; button.performClick(nil) instead of menu.popUp(...)
  3. Conform to NSMenuDelegate; menuDidClose clears statusItem.menu
  4. Keep 0.3s debounce and legacy rightMouseUp action path for ≤26
  5. Close an open popover before presenting the menu

Testing

  • swift build / mac/Scripts/package-app.sh with full Xcode (SwiftUI macros)
  • Binary contains mov w2, #0x10 (rightMouseUp mask) and performClick
  • Manual on macOS 27: right-click stays open; mouse move does not scroll; Today row stable; Settings/Quit work
  • Manual on macOS 27: left-click still opens popover after using the context menu
  • Smoke on macOS ≤26 (if available): right-click presents exactly once (debounce); no flash; no jump

Workarounds (until released)

None in shipping 0.9.19. Local fix is built/installed as a dev menubar build from source.

Notes for reviewers

  • Do not "fix" the jump by switching to y: 0 in view coords — button is flipped; that anchors into the menu bar and makes clipping worse.
  • Screen-coordinate popUp(in: nil) is a reasonable fallback but still inferior to statusItem.menu for tracking.
  • fix(mac): restore right-click status-item menu on macOS 27 #472 author only verified on 27; ≤26 path relies on debounce — call that out in the PR the same way they did.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions