Description
On macOS 15+ (Sequoia / Darwin 24+), status bar item tracking routed through FrontBoardServices and NSSceneStatusItem delivers NSEventTypeAppKitDefined (type 13, printed as KitDefined) events when interacting with the menu bar icon.
When Qt's Cocoa platform plugin (libqcocoa.dylib in QCocoaSystemTrayIcon) receives the internal notification from NSMenuTrackingSession, it directly invokes [NSApp.currentEvent clickCount] without verifying whether the event is actually a mouse event. In AppKit, invoking -[NSEvent clickCount] on a non-mouse event raises an NSInternalInconsistencyException, terminating Sunshine with an unhandled exception abort:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid message sent to event "NSEvent: type=KitDefined loc=(0,900) time=555614.8 flags=0x40 win=0x0 winNum=0 ctxt=0x0 subtype=2 data1=0 data2=64"'
*** First throw call stack:
(
0 CoreFoundation 0x000000018fb3a8c0 __exceptionPreprocess + 176
1 libobjc.A.dylib 0x000000018f59860c objc_exception_throw + 88
2 Foundation 0x00000001912814d8 -[NSCalendarDate initWithCoder:] + 0
3 AppKit 0x0000000194218f80 -[NSEvent clickCount] + 152
4 libqcocoa.dylib 0x00000001076bb49c qt_plugin_instance + 186712
5 CoreFoundation 0x000000018fabf1a0 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 148
6 CoreFoundation 0x000000018fb4e394 ___CFXRegistrationPost_block_invoke + 92
7 CoreFoundation 0x000000018fb4e2d8 _CFXRegistrationPost + 440
8 CoreFoundation 0x000000018fa8b3d0 _CFXNotificationPost + 688
9 Foundation 0x000000019117c38c -[NSNotificationCenter postNotificationName:object:userInfo:] + 88
10 AppKit 0x000000019462d154 -[NSMenuTrackingSession sendBeginTrackingNotifications] + 188
11 AppKit 0x0000000194634b98 -[NSMenuTrackingSession beginTrackingSession:] + 644
12 AppKit 0x00000001945e1bac +[NSContextMenuImpl presentPopup:fromView:withContext:animated:async:completionBlock:] + 432
13 AppKit 0x0000000194926880 _NSPopUpMenu + 1992
14 AppKit 0x0000000194925fe0 -[NSCocoaMenuImpl popUpMenu:atLocation:width:view:selectedItemIndexProvider:font:positioningRect:flags:options:] + 432
15 AppKit 0x0000000194925e08 -[NSCocoaMenuImpl popUpMenu:atLocation:width:forView:withSelectedItem:withFont:withFlags:withOptions:] + 96
16 AppKit 0x00000001948e682c +[NSStatusBarButtonCell popUpStatusBarMenu:ofItem:ofBar:inRect:ofView:withEvent:] + 744
17 AppKit 0x00000001948eed1c -[NSStatusItem popUpStatusItemMenu:] + 108
18 AppKit 0x00000001948ef348 -[NSStatusItem _beginExpandedInterfaceSession:] + 600
19 AppKit 0x00000001946ba60c -[NSSceneStatusItem _beginExpandedInterfaceSession:] + 192
20 AppKit 0x00000001946b91b0 __33-[NSSceneStatusItem _setupScene:]_block_invoke.25 + 320
21 AppKit 0x0000000194f06618 __swift_closure_destructor.106 + 28764
22 AppKit 0x0000000194f06794 __swift_closure_destructor.106 + 29144
23 FrontBoardServices 0x00000001ac1a7cc8 -[FBSSceneObserver scene:handlePrivateActions:] + 80
24 FrontBoardServices 0x00000001ac16b864 -[FBSScene updater:didReceiveActions:forExtension:] + 736
25 FrontBoardServices 0x00000001ac193e28 __71-[FBSWorkspaceScenesClient sceneID:sendActions:toExtension:completion:]_block_invoke + 204
26 FrontBoardServices 0x00000001ac14ebbc -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 180
27 libdispatch.dylib 0x000000018f8625a0 _dispatch_client_callout + 16
28 libdispatch.dylib 0x000000018f84d700 _dispatch_block_invoke_direct + 284
29 BoardServices 0x00000001ac236ca4 __BSSERVICEMAINRUNLOOPQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 48
30 BoardServices 0x00000001ac235ac8 BSServiceMainRunLoopSourceHandler + 232
31 CoreFoundation 0x000000018faca944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
32 CoreFoundation 0x000000018faca8d8 __CFRunLoopDoSource0 + 224
33 CoreFoundation 0x000000018faca610 __CFRunLoopDoSources0 + 232
34 CoreFoundation 0x000000018fac91e0 __CFRunLoopRun + 832
35 CoreFoundation 0x000000018fba382c _CFRunLoopRunSpecificWithOptions + 536
36 HIToolbox 0x000000019cefc590 RunCurrentEventLoopInMode + 320
37 HIToolbox 0x000000019ceff91c ReceiveNextEventCommon + 492
38 HIToolbox 0x000000019d082380 _BlockUntilNextEventMatchingListInMode + 48
39 AppKit 0x00000001943c329c _DPSBlockUntilNextEventMatchingListInMode + 292
40 AppKit 0x00000001940804fc _DPSNextEvent + 580
41 AppKit 0x00000001948f8748 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 780
42 AppKit 0x00000001948f826c -[NSApplication(NSEventRouting) nextEventMatchingMask:untilDate:inMode:dequeue:] + 292
43 AppKit 0x000000019407390c -[NSApplication run] + 396
44 libqcocoa.dylib 0x000000010769b99c qt_plugin_instance + 56920
45 QtCore 0x00000001071a6ba0 _ZN10QEventLoop4execE6QFlagsINS_17ProcessEventsFlagEE + 588
46 QtCore 0x000000010719d1a8 _ZN16QCoreApplication4execEv + 228
47 Sunshine 0x0000000105028110 _ZN10QtTrayMenu4loopEi + 232
48 Sunshine 0x000000010456f53c _Z14mainThreadLoopRKNSt3__110shared_ptrIN4safe7event_tIbEEEE + 212
49 Sunshine 0x0000000104570d90 main + 5668
50 dyld 0x000000018f633e80 start + 6688
)
libc++abi: terminating due to uncaught exception of type NSExceptionThis PR resolves the crash by:
- Adding
platf::install_event_compatibility_fixes()insrc/platform/macos/misc.mm, which swizzles-[NSEvent clickCount]using an Objective-C category. - For mouse event types (
LeftMouseDown/Up,RightMouseDown/Up,OtherMouseDown/Up), the original implementation is called with@try / @catchfallback. - For non-mouse events (such as
NSEventTypeAppKitDefined), it immediately returns1instead of throwing. - Calling
platf::install_event_compatibility_fixes()early insrc/main.cppand prior totray_init()insrc/system_tray.cpp.
Screenshot
Issues Fixed or Closed
Roadmap Issues
Testing
Added automated unit regression tests in tests/unit/platform/macos/test_event_compat.mm (MacosEventCompatTest):
IdempotentInstallation: Verifies safe idempotent execution across multiple setup calls.NonMouseEventClickCountReturnsFallbackWithoutThrowing: Verifies that queryingclickCountonNSEventTypeAppKitDefinedandNSEventTypeSystemDefinedevents returns1without throwingNSInternalInconsistencyException.MouseEventClickCountPreserved: Verifies that single, double, and right-click counts are correctly preserved for mouse events.
Commands run:
cmake --build cmake-build-debug --target test_sunshine -j8
./cmake-build-debug/tests/test_sunshine --gtest_filter="Macos*:SystemTrayTest.*"
uv run --locked lb-update-clang-formatAll 16 tests in MacosPermissionsTest, SystemTrayTest, MacosAudioPermissionTest, and MacosEventCompatTest passed.
Type of Change
- feat: New feature (non-breaking change which adds functionality)
- fix: Bug fix (non-breaking change which fixes an issue)
- docs: Documentation only changes
- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
- refactor: Code change that neither fixes a bug nor adds a feature
- perf: Code change that improves performance
- test: Adding missing tests or correcting existing tests
- build: Changes that affect the build system or external dependencies
- ci: Changes to CI configuration files and scripts
- chore: Other changes that don't modify src or test files
- revert: Reverts a previous commit
- BREAKING CHANGE: Introduces a breaking change (can be combined with any type above)
Checklist
- Code follows the style guidelines of this project
- Code has been self-reviewed
- Code has been commented, particularly in hard-to-understand areas
- Code docstring/documentation-blocks for new or existing methods/components have been added or updated
- Tests have been added or updated for new or modified functionality, including regression tests for bug fixes
AI Usage
See our AI usage policy.
- AI tools were used while preparing this PR
AI assisted in analyzing the macOS NSInternalInconsistencyException crash call stack, implementing the AppKit swizzle compatibility shim, and developing unit tests.
This pull request was generated by Antigravity, Gemini 3.8 Flash, high thinking level.
❌ The last analysis has failed.
See analysis details on SonarQube Cloud