Skip to content

Forward right/middle mouse drags to Ghostty (fixes tmux right-click menu) - #7319

Merged
lawrencecchen merged 3 commits into
mainfrom
fix-right-drag-tmux-menu
Jul 4, 2026
Merged

lawrencecchen merged 3 commits into
mainfrom
fix-right-drag-tmux-menu

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jul 4, 2026 •

Copy link
Copy Markdown
Contributor

What

In real Ghostty, right-click + drag + release drives tmux's right-click context
menu (open on press, highlight on drag, select on release). In cmux the menu
opened but dragging produced no hover highlight and release selected nothing.

How

cmux overrode mouseDragged (left button) but not rightMouseDragged or
otherMouseDragged, so pointer motion during a right- or middle-button drag was
never forwarded to libghostty via ghostty_surface_mouse_pos. Under an app with
mouse reporting on (tmux), the app never saw the drag. Add both overrides,
funneling to mouseDragged the same way upstream Ghostty funnels every drag
variant to one position-forwarding path (rightMouseDragged/otherMouseDragged
-> mouseMoved). Middle-button drags are gated on buttonNumber == 2 to match
the existing otherMouseDown/otherMouseUp.

Test

In cmux, tmux with set -g mouse on, then right-click a pane: the tmux
context menu opens, dragging highlights items (hover), releasing selects the
highlighted item. Previously no highlight/selection.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Note

Low Risk
Small, localized input-event forwarding in the terminal view with no auth, data, or API surface changes.

Overview
GhosttyTerminalView now forwards right-button and middle-button drag motion to libghostty the same way left-button drags already did, by adding rightMouseDragged and otherMouseDragged overrides that call into the existing mouseDragged / ghostty_surface_mouse_pos path.

That closes a gap where mouse-reporting programs (notably tmux with mouse on) saw press/release but not pointer motion during a right-click menu drag, so hover highlight and release-to-select did not work. Middle-button drags are limited to buttonNumber == 2, consistent with the existing otherMouseDown / otherMouseUp handling.

The Swift file length budget for Sources/GhosttyTerminalView.swift is bumped slightly for the new lines.

Reviewed by Cursor Bugbot for commit 6785a84. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Forward right- and middle-button drag events to Ghostty so mouse-reporting apps (e.g., tmux) receive pointer motion during drags. Fixes tmux right-click menu hover/select and updates the Swift file-length budget for Sources/GhosttyTerminalView.swift.

  • Bug Fixes
    • Override rightMouseDragged to delegate to mouseDragged.
    • Override otherMouseDragged for middle button only (buttonNumber == 2), delegating to mouseDragged.

Written for commit 63e0b17. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Improved mouse drag handling in the terminal view so right-button drags consistently update the pointer position.
    • Improved middle-button drag behavior (via secondary/other mouse drags) so pointer position updates are more reliable, while non-middle other-button drags retain the default app behavior.

cmux overrode mouseDragged (left button) but not rightMouseDragged or
otherMouseDragged, so pointer motion during a right- or middle-button drag
was never forwarded to libghostty. Under an app that enables mouse reporting
(e.g. tmux), this broke the right-click context menu: right-press opened it,
but dragging to a menu item produced no hover highlight and release selected
nothing. Add both overrides, funneling to mouseDragged the same way upstream
Ghostty funnels every drag variant to one position-forwarding path.
@vercel

vercel Bot commented Jul 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jul 4, 2026 2:58pm

@coderabbitai

coderabbitai Bot commented Jul 4, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c94938da-bf25-486a-90c1-9c92666e052e

📥 Commits

Reviewing files that changed from the base of the PR and between d1d9b49 and 63e0b17.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (1)
  • Sources/GhosttyTerminalView.swift

📝 Walkthrough

Walkthrough

This change adds rightMouseDragged and otherMouseDragged overrides in GhosttyNSView, forwarding right-button and middle-button drag events into the existing mouseDragged handling path.

Changes

Mouse Drag Event Forwarding

Layer / File(s) Summary
Add drag forwarding overrides
Sources/GhosttyTerminalView.swift
Adds rightMouseDragged forwarding to mouseDragged, and otherMouseDragged forwarding only middle-button drags to mouseDragged while other buttons defer to super.

Estimated code review effort: 1 (Trivial) | ~5 minutes

🚥 Pre-merge checks | ✅ 25
✅ Passed checks (25 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed The new drag overrides live in an existing @MainActor NSView and only forward to the same mouseDragged path; no new Sendable, shared mutable, or background access issues.
Cmux Swift Blocking Runtime ✅ Passed The added drag overrides only forward events to mouseDragged; no semaphores, sleeps, sync waits, or new locks were introduced.
Cmux Browser Automation Off-Main ✅ Passed Diff only adds right/other drag forwarding in Sources/GhosttyTerminalView.swift; no browser.* socket commands, worker routing, or policy tests changed.
Cmux Expensive Synchronous Load ✅ Passed PASS: The diff only adds drag-event forwarding in GhosttyNSView; no agent-history loaders, JSON scans, or main-thread sync loads were introduced.
Cmux Cache Substitution Correctness ✅ Passed The change only adds transient mouse-drag forwarding in GhosttyNSView; no cache, persistence, history, undo, or snapshot substitution is involved.
Cmux No Hacky Sleeps ✅ Passed PR only adds Swift drag-forwarding handlers; no new sleeps, timers, polling, or async waits were introduced, and the runtime-no-hacky-sleeps rule is out of scope for Swift.
Cmux Algorithmic Complexity ✅ Passed GhosttyNSView only adds drag-forwarding overrides; no collection scans, sorting, or batch work on scalable data paths.
Cmux Swift Concurrency ✅ Passed The change only adds AppKit drag-event overrides that forward mouse motion; it introduces no new DispatchQueue, Combine, completion-handler, or fire-and-forget Task patterns.
Cmux Swift @Concurrent ✅ Passed The change only adds synchronous NSView drag overrides; no @concurrent/nonisolated async code or actor-isolation misuse was introduced.
Cmux Swift File And Package Boundaries ✅ Passed Small AppKit/Ghostty glue fix in an existing 12,232-line app file; adds ~20 lines, far below the >250-line expansion threshold and fits the allowed bug-fix case.
Cmux Swiftpm Lockfiles ✅ Passed Only Sources/GhosttyTerminalView.swift changed; no .gitignore, Package.swift, project, or Package.resolved diffs to review.
Cmux Swift Logging ✅ Passed The diff only adds drag-handler forwarding and comments; it introduces no print/debugPrint/dump/NSLog, Logger changes, or sensitive logging.
Cmux User-Facing Error Privacy ✅ Passed The change only adds drag-forwarding overrides and comments in GhosttyNSView; no user-facing errors, alerts, output, or sensitive details were introduced.
Cmux Full Internationalization ✅ Passed The diff only adds drag-event handlers and developer comments; no user-facing Swift text, catalogs, or locale data changed.
Cmux Swiftui State Layout ✅ Passed Only drag event overrides were added in an AppKit NSView bridge; no new SwiftUI state, GeometryReader, lazy-row store refs, or render-time mutation.
Cmux Architecture Rethink ✅ Passed Adds AppKit drag callbacks that forward into the existing mouseDragged path; no sleeps, polling, new state owners, or split lifecycle ownership.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR only adds drag forwarding in GhosttyNSView; no NSWindow/NSPanel/WindowGroup or cmuxAuxiliaryWindowIdentifiers changes are present.
Cmux Source Artifacts ✅ Passed Only Sources/GhosttyTerminalView.swift changed; it's hand-written source and not any artifact/cache/build path forbidden by the rule.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Adds production drag forwarding only; no new #if DEBUG seam, test-hook name, or visibility-widened wrapper was introduced.
Cmux No Ambient Global State ✅ Passed The added drag handlers are instance overrides inside GhosttyNSView, not new top-level funcs, vars, namespaces, or singletons.
Title check ✅ Passed The title clearly matches the change: forwarding right/middle mouse drags to Ghostty and the tmux right-click menu fix.
Description check ✅ Passed The description covers the change, why it was needed, and manual testing, but omits the demo video, review trigger, and checklist sections.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-right-drag-tmux-menu

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 4, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds rightMouseDragged and otherMouseDragged overrides to GhosttyNSView so that pointer motion during a right- or middle-button drag is forwarded to libghostty via ghostty_surface_mouse_pos, fixing hover highlighting and release-to-select in the tmux right-click context menu.

  • rightMouseDragged delegates unconditionally to mouseDragged, forwarding drag position to libghostty.
  • otherMouseDragged mirrors the existing otherMouseDown/otherMouseUp pattern, guarding on buttonNumber == 2 before forwarding.
  • The swift-file-length-budget.tsv entry for GhosttyTerminalView.swift is bumped by 20 lines to reflect the additions.

Confidence Score: 5/5

Safe to merge — the change is a narrow, well-scoped addition of two NSView drag-event overrides with no auth, data, or concurrency surface touched.

Both new methods follow the established delegate-to-mouseDragged pattern used by the rest of the drag handling in this class. The only nuance is that rightMouseDragged omits the ghostty_surface_mouse_captured guard present in rightMouseDown/rightMouseUp, which is a minor inconsistency flagged as a suggestion; it does not cause incorrect behavior in the primary use case (mouse reporting on) and is unlikely to produce visible side-effects when reporting is off. The budget file is updated correctly to match the added lines.

Sources/GhosttyTerminalView.swift — specifically the new rightMouseDragged override and its relationship to the capture-guard pattern used by rightMouseDown and rightMouseUp.

Important Files Changed

Filename Overview
Sources/GhosttyTerminalView.swift Adds rightMouseDragged and otherMouseDragged overrides; rightMouseDragged delegates to mouseDragged without the ghostty_surface_mouse_captured guard that rightMouseDown uses, which is a minor inconsistency worth noting.
.github/swift-file-length-budget.tsv Budget line for GhosttyTerminalView.swift bumped by 20 lines to account for the new methods; consistent with the diff size.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant macOS as macOS Event System
    participant NSView as GhosttyNSView
    participant lib as libghostty

    Note over macOS,lib: Right-button drag (before fix)
    macOS->>NSView: rightMouseDown
    NSView->>lib: ghostty_surface_mouse_button(PRESS, RIGHT)
    macOS--xNSView: rightMouseDragged (not overridden — dropped)
    macOS->>NSView: rightMouseUp
    NSView->>lib: ghostty_surface_mouse_button(RELEASE, RIGHT)

    Note over macOS,lib: Right-button drag (after fix)
    macOS->>NSView: rightMouseDown
    NSView->>lib: ghostty_surface_mouse_button(PRESS, RIGHT)
    macOS->>NSView: rightMouseDragged
    NSView->>NSView: mouseDragged(with: event)
    NSView->>lib: ghostty_surface_mouse_pos(x, y, mods)
    macOS->>NSView: rightMouseUp
    NSView->>lib: ghostty_surface_mouse_button(RELEASE, RIGHT)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant macOS as macOS Event System
    participant NSView as GhosttyNSView
    participant lib as libghostty

    Note over macOS,lib: Right-button drag (before fix)
    macOS->>NSView: rightMouseDown
    NSView->>lib: ghostty_surface_mouse_button(PRESS, RIGHT)
    macOS--xNSView: rightMouseDragged (not overridden — dropped)
    macOS->>NSView: rightMouseUp
    NSView->>lib: ghostty_surface_mouse_button(RELEASE, RIGHT)

    Note over macOS,lib: Right-button drag (after fix)
    macOS->>NSView: rightMouseDown
    NSView->>lib: ghostty_surface_mouse_button(PRESS, RIGHT)
    macOS->>NSView: rightMouseDragged
    NSView->>NSView: mouseDragged(with: event)
    NSView->>lib: ghostty_surface_mouse_pos(x, y, mods)
    macOS->>NSView: rightMouseUp
    NSView->>lib: ghostty_surface_mouse_button(RELEASE, RIGHT)
Loading

Reviews (3): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

@lawrencecchen
lawrencecchen merged commit 677479d into main Jul 4, 2026
7 of 10 checks passed
@lawrencecchen
lawrencecchen deleted the fix-right-drag-tmux-menu branch July 4, 2026 09:33
azooz2003-bit added a commit that referenced this pull request Jul 4, 2026
…ng, themes)

Delta: #7318/#7319 mouse cursor-shape + right/middle drag forwarding, #7320 ghostty
upstream, #6664 iOS themes, #7196 iOS scroll, #7257/#7307 web, #7329 CLI suggestions,
#7222 codex resume update-suppression. Conflicts resolved keeping HEAD structure:
- GhosttyTerminalView.swift: took main's viewDidEndLiveResize + resetCursorRects
  (cursor-shape #7318; ghosttyMouseShape/ghosttyMouseCursor already in HEAD).
- Mobile/MobileHostService.swift: union (kept HEAD sharedRequestActivity +
  main publicStatusPayload theme payload #6664).
- project.pbxproj: union-dedup, normalized; test-wiring green.
- swift-file-length-budget.tsv regenerated.

#7222 (codex update-check suppression) partially landed: the CMUXAgentLaunch package
part (AgentResumeArgv.codexUpdateCheckSuppressionOverride) auto-merged and is present;
the app-target files (+CodexUpdateCheck.swift + test) extend SurfaceResumeCommandCanonicalizer,
a type HEAD dissolved into the CmuxWorkspaces package, so they can't compile and the
suppression was never wired (call site was in the HEAD-deleted +PortableAgentExecutable).
Removed those two files; re-wire recorded in merge-deferred-gaps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lawrencecchen
lawrencecchen restored the fix-right-drag-tmux-menu branch July 18, 2026 10:24

This branch was successfully deployed

1 active deployment
Preview – cmux — 63e0b171 Deployed Jul 4, 2026 by vercel[bot]
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.

1 participant