Skip to content

Defer merged icon redraws during menu tracking - #1409

Merged
steipete merged 2 commits into
steipete:mainfrom
kiranmagic7:kiran/merged-menu-icon-quiescence
Jun 11, 2026
Merged

Defer merged icon redraws during menu tracking#1409
steipete merged 2 commits into
steipete:mainfrom
kiranmagic7:kiran/merged-menu-icon-quiescence

Conversation

@kiranmagic7

@kiranmagic7 kiranmagic7 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Defer merged status-icon redraws while the merged dropdown is actively tracking, then apply one latest redraw after the dropdown closes. This reduces one source of in-tracking UI churn called out in #1399 without changing menu content, provider switching, or icon rendering semantics while the menu is closed.

Context

#1399 and the follow-up bisection around #1408 split the merged-menu freeze evidence into two drivers:

  1. The switcher event monitor caused the felt input starvation and is addressed by Gate switcher event monitor pump on hardware event counters #1408.
  2. WindowServer datagram-buffer overflow persisted with stock churn and disappeared only when all in-tracking UI churn was suppressed.

This PR targets a narrow part of the second bucket: status-item icon redraws requested while the merged menu is open. Those redraws are not user-visible until the menu closes, so the work can be coalesced safely.

Change

  • Skip merged status-icon rendering while shouldMergeIcons and isMergedMenuOpen are both true.
  • Remember that a merged icon render was deferred.
  • Apply one latest icon render after the merged menu closes.
  • Keep animation/blink lifecycle reconciliation active while redraws are deferred.
  • Preserve quota-warning onset and expiration timing with one event-driven bypass per transition.
  • Reconcile the current logical provider when a warning event arrives during a provider/display mismatch.
  • Clear the deferred flag during shutdown teardown.
  • Add focused regression coverage for deferral, close flushing, animation timeout, warning timing, and provider mismatch.
  • Add a changelog entry under 0.32.6 Unreleased.

Validation

  • swift test --filter StatusItemAnimationSignatureTests passes: 6 tests.
  • Full swift test passes: 3528 tests in 402 suites.
  • make check passes: SwiftFormat clean, SwiftLint found 0 violations in 1038 files.
  • git diff --check passes.
  • Final autoreview is clean with no accepted/actionable findings.
  • Ad-hoc packaged bundle reports exact head 841c92d1.
  • Peekaboo: 12 merged-menu open cycles completed in 0.09-0.21s; 20 sustained provider-switch input pairs completed with a 0.101s maximum.

Scope notes

This is intentionally not presented as a full fix for #1399. It complements #1408 by reducing one remaining in-tracking churn source that aligns with the WindowServer-overflow evidence.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ca0e327666

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@discardableResult
func applyIcon(phase: Double?) -> Bool {
guard let button = self.statusItem.button else { return false }
if self.deferMergedIconRenderDuringMenuTrackingIfNeeded() { return true }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Run animation-state updates when deferring merged renders

When a store/icon change arrives while the merged menu is open, this new early return makes applyIcon report a skipped render, and updateIcons() immediately returns on that value before reaching its existing updateAnimationState()/updateBlinkingState() calls. In the inspected updateIcons() path, that means a refresh completion during menu tracking no longer stops the loading display-link driver (or a refresh start no longer starts it); after the menu closes the deferred icon is applied, but the stale animation driver can keep ticking/redrawing until the 30s timeout or another icon update happens. The render work can be deferred, but the animation/blink state still needs to be updated for changes observed while tracking.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the kiran/merged-menu-icon-quiescence branch from ca0e327 to 841c92d Compare June 11, 2026 00:07
@steipete
steipete merged commit b7772b2 into steipete:main Jun 11, 2026
4 checks passed
@steipete

Copy link
Copy Markdown
Owner

Landed as b7772b2.

Proof:

  • Focused merged-icon redraw tests: 6 passed.
  • Full local suite: 3,528 tests in 402 suites passed.
  • make check: passed with zero lint violations.
  • Auto Review: clean; no accepted/actionable findings.
  • Fresh packaged app: 12 menu-open cycles measured 0.09-0.21s; 20 provider-switch pairs measured at or below 0.101s with Peekaboo.
  • Exact head 841c92d: macOS CI, Linux x64, Linux arm64, and GitGuardian all passed.

Caveat: this is the bounded redraw mitigation for #1399; the broader WindowServer report remains open for further evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants