fix(systray): recover click type on macOS 27 - #5919
Conversation
On macOS 27 Golden Gate, [NSApp currentEvent] inside an NSStatusItem action selector no longer reflects the originating mouse-down, so processClick's left/right switch dropped the event. Coerce via [NSEvent pressedMouseButtons] as a fallback. Behaviour on macOS <=26 is unchanged (the coercion is a no-op when the raw event type is already a mouse-down). Adds a table-driven regression test. Closes wailsapp#5752
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
WalkthroughThe Darwin status item callback now coerces macOS event types using the pressed-button state before dispatch. A Go wrapper exposes the C helper for testing. Darwin regression tests cover legacy and macOS 27 event types. ChangesDarwin status item event handling
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This localized macOS system tray fix restores left-click handling while preserving existing right-click behavior, with no actionable merge-blocking risk remaining beyond normal checks and review. Sequence Diagram(s)sequenceDiagram
participant AppKitStatusItem
participant systemTrayCoerceEventType
participant systrayClickCallback
AppKitStatusItem->>systemTrayCoerceEventType: raw event type and pressed mouse buttons
systemTrayCoerceEventType->>systrayClickCallback: coerced event type
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
3563e45 to
cbe84c2
Compare
Closing the window quit the process, which ends the background sampling the collector now does. Intercept WindowClosing and hide the window instead, so the app stays resident and keeps collecting. A new closeBehavior setting under Settings > General picks between minimising to the tray and quitting outright, defaulting to the tray. Because the hook must decide before the window is destroyed, the choice is read in Go; the renderer only skips its own quit confirmation when the window will merely hide. The tray menu restores the window, jumps to a page, opens settings, or quits. Page jumps travel as a tray:navigate event the renderer turns into a sidebar selection. Its labels cannot come from the frontend i18n bundles, which the Go process never loads, so the handful of strings live in the tray package and follow the language setting through a new change listener on the configuration service. Two Wails constraints shaped this. The native menu is bound once when the tray starts and never rebound, so the menu is built up front and only relabelled afterwards. And a tray click only reaches native menu tracking while no click handler is registered, so none is - registering one silently falls back to a path where the left button does nothing. Note that macOS 26+ breaks the left button regardless: the status item action no longer sees the originating mouse-down, so the click type Wails dispatches on is one its switch does not handle. Right-click works. Upstream fix: wailsapp/wails#5919.
|
Upvote for this one :) |
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
Works like a charm. Can we get this reviewed and merged? |
|
Hi maintainers, would be great to have that in before the release of Mac OSX 27, works like a charm! :-) |
There was a problem hiding this comment.
Pull request overview
This PR addresses a macOS 27 (Golden Gate) behavior change where -[NSApp currentEvent] inside an NSStatusItem action can no longer be relied on to determine whether the status item was left- or right-clicked. It adds a small native helper to coerce the event type using +[NSEvent pressedMouseButtons], and pins the behavior with a darwin-only regression test.
Changes:
- Added
systemTrayCoerceEventType(ObjC/C) to map non-mouse-downcurrentEventtypes to left/right mouse-down using pressed mouse button state. - Updated
statusItemClicked:to send the coerced event type to the Go callback. - Added a darwin regression test to lock in the macOS 27 click-type recovery behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
v3/pkg/application/systemtray_darwin.m |
Adds the event-type coercion helper and uses it when dispatching tray click callbacks. |
v3/pkg/application/systemtray_darwin.h |
Documents and exposes systemTrayCoerceEventType for regression testing. |
v3/pkg/application/systemtray_darwin.go |
Adds a small Go wrapper for the C helper to make it callable from tests. |
v3/pkg/application/systemtray_darwin_test.go |
Adds darwin-only regression coverage for macOS 27 event coercion behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
Thanks all for testing! |
Description
Context
macOS 27 Golden Gate (currently in developer beta) rebuilds the menu bar and NSStatusItem
internals substantially. Apple has publicly acknowledged the direction of travel on developer forums thread 832823
(https://developer.apple.com/forums/thread/832823): "Local event monitors are no longer the
recommended way of scanning for events on status items." The wider menu-bar-app ecosystem
(Ice, BetterDisplay, Deskflow, SaneBar, …) is hitting parallel issues. This PR is a tactical
fix for one specific symptom in Wails
Info: a broader review of the local-event-monitor pattern in systemtray_darwin.m is a reasonable follow-up. This is partially already started in #5760.
Problem
On macOS 27 Golden Gate, left-clicking a Wails system tray icon does nothing (#5752).
Right-click still works.
The root cause is a behaviour change in AppKit's event dispatch:
button's sendActionOn: handler.
NSEventTypeLeftMouseDown / NSEventTypeRightMouseDown.
Fix
Introduce a small C helper, systemTrayCoerceEventType, that maps the raw event type to a
button processClick can dispatch on:
path), pass it through unchanged.
(left), matching existing right-click-takes-precedence semantics.
click, so something triggered it.
statusItemClicked: sends the coerced value to Go instead of raw event.type. The Go switch is
untouched, so macOS ≤26 behaviour is unchanged.
Fixes #5752.
Type of change
Please select the option that is relevant.
How Has This Been Tested?
Was tested on macOS 27.0 beta(26A5388g) and on macOS 26.5.2 (25F84).
Test Configuration
Wails v3.0.0-beta.4 › Wails Doctor # System ┌────────────────────────────┐ | Name | MacOS | | Version | 27.0 | | ID | 26A5388g | | Branding | MacOS 27.0 | | Platform | darwin | | Architecture | arm64 | | Apple Silicon | true | | CPU | Apple M3 | | CPU | Apple M3 | | GPU | 10 cores | | Memory | 16 GB | └────────────────────────────┘ # Build Environment ┌──────────────────────────────────────────────────────────────────────┐ | Wails CLI | v3.0.0-beta.4 | | Go Version | go1.26.5 | | -buildmode | exe | | -compiler | gc | | CGO_CFLAGS | | | CGO_CPPFLAGS | | | CGO_CXXFLAGS | | | CGO_ENABLED | 1 | | CGO_LDFLAGS | | | DefaultGODEBUG | cryptocustomrand=1,tlssecpmlkem=0,urlstrictcolons=0 | | GOARCH | arm64 | | GOARM64 | v8.0 | | GOOS | darwin | └──────────────────────────────────────────────────────────────────────┘ # Dependencies ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐ | *Android SDK | Not found. Set ANDROID_HOME (install via Android Studio or the command-line tools). | | *NSIS | Not Installed. Install with `brew install makensis`. | | *Xcode (iOS) | Not installed. iOS builds need full Xcode (App Store), not just the CLI tools. | | *iOS Device SDK | Not found | | *iOS Simulator SDK | Not found | | Xcode cli tools | 2417 | | npm | 10.9.8 | | docker | *Not installed (optional - for cross-compilation) | | | └──────────────────────────────────────── * - Optional Dependency ─────────────────────────────────────────┘ # Signing ┌────────────────────────────────────────┐ | macOS Signing | Not configured | | Windows Signing | Not configured | | Linux Signing | Not configured (GPG) | └────────────────────────────────────────┘ # Checking for issues SUCCESS No issues found # Diagnosis SUCCESS Your system is ready for Wails development!Checklist:
website/src/pages/changelog.mdxwith details of this PR (v3 changelog entries are added automatically)Summary by CodeRabbit