macOS: fix tab context menu opens on macOS 26 with titlebar tabs (#9831)

Description:
Context menu works on tabs with titlebar-style=tabs on MacOS Tahoe 26

Closes #9817 

Demo:


https://github.com/user-attachments/assets/60eaae6e-a3ff-41eb-8c86-ba700490d6e2



Note:
- Tried first a passthrough-views approach, but AppKit’s internal
toolbar subviews continued intercepting right-clicks.
- Runtime subclassing proposed by Claude also worked but was rejected as
too fragile.
- Final solution routes secondary-click events at the window level using
sendEvent(_:), forwarding them to the tab bar only when the click is
visually within its bounds.

AI Disclosure:
AI (Claude Code and Codex) assisted with early explorations, but final
implementation was developed manually after evaluating and discarding
the unsafe subclassing approach proposed by Claude.
pull/9869/head
Mitchell Hashimoto 2025-12-10 20:12:30 -08:00 committed by GitHub
commit 894e8d91ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 32 additions and 0 deletions

View File

@ -67,6 +67,38 @@ class TitlebarTabsTahoeTerminalWindow: TransparentTitlebarTerminalWindow, NSTool
viewModel.isMainWindow = false
}
/// On our Tahoe titlebar tabs, we need to fix up right click events because they don't work
/// naturally due to whatever mess we made.
override func sendEvent(_ event: NSEvent) {
guard viewModel.hasTabBar else {
super.sendEvent(event)
return
}
let isRightClick =
event.type == .rightMouseDown ||
(event.type == .otherMouseDown && event.buttonNumber == 2) ||
(event.type == .leftMouseDown && event.modifierFlags.contains(.control))
guard isRightClick else {
super.sendEvent(event)
return
}
guard let tabBarView = findTabBar() else {
super.sendEvent(event)
return
}
let locationInTabBar = tabBarView.convert(event.locationInWindow, from: nil)
guard tabBarView.bounds.contains(locationInTabBar) else {
super.sendEvent(event)
return
}
tabBarView.rightMouseDown(with: event)
}
// This is called by macOS for native tabbing in order to add the tab bar. We hook into
// this, detect the tab bar being added, and override its behavior.
override func addTitlebarAccessoryViewController(_ childViewController: NSTitlebarAccessoryViewController) {