Repository navigation
fix(ui): release a stale pane mouse gesture when its button is pressed again - #56
Conversation
…d again When the host terminal never delivers a release, the pane mouse gesture stays open: the next press is swallowed and its drag and release go to the old pane. A press of the button the gesture holds can only follow a lost release, so end the stale gesture where it was last seen, as focus loss already does, and handle the press normally. Presses of other buttons stay swallowed so chords keep working; replayed link-click events never count. refs #53
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (3)
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 SummarySummary by CodeRabbit
Walkthrough同じボタンの再押下時に、保持中のマウスジェスチャーを最後の位置で解放してから新しい押下を処理します。ジェスチャーの解放処理を共通化し、ペイン、ポップアップ、URLクリック再生に関するテストを追加します。 Changesマウスジェスチャーの解放
Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to The change releases a stale mouse gesture when the same button is pressed again, which fixes the swallowed press after a lost release. No merge-blocking risk was identified. Security Architecture ReviewSecurity architecture risk: ⚪ Minimal · up to The change releases an abandoned mouse interaction before accepting another click, preserving the original destination and event order. No new privileges, broader input access, or material security regression were identified. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 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 |
After fork.10, selections still followed the pointer after release in Ghostty, but the same herdr behaved in Terminal.app and a Ghostty restart cleared it. Note under #56 that the lost releases come from Ghostty 1.3.1 on macOS (ghostty-org/ghostty#10974), why herdr cannot tell them from a real drag, and how to recover when it recurs.
マウスを捕捉するペインで「離した」が届かなかったとき、残ったジェスチャーが次のクリックを飲み込む不具合を直す。
何が動いていなかったか
マウスを捕捉するペイン(Claude Code の全画面、lazygit など)で押下(Down)が届き、離す(Up)が届かないと
pane_mouse_gestureが残り続けていた。handle_mouseのジェスチャー処理は、握っているボタンの Drag/Up だけを元のペインへ転送し、それ以外の Down/Drag/Up はすべて捨てる。そのため次のことが起きていた。修正
src/client/shell/mouse.rs:handle_mouseのジェスチャー処理の直前に、「ジェスチャーが握っているボタンの Down が来たら、まず残ったジェスチャーを解放する」判定を足した。既存のジェスチャー処理は変えていない。PaneFocusがいつもどおり走る。replaying_url_click)は対象外にした。今押している本物のジェスチャーを解放しないためである。resize_invalidation_drops_stale_hits_but_preserves_gesture_releaseがこれを要求している。src/client/shell/input.rsのrelease_input_leases)をそのままrelease_pane_mouse_gestureとしてmouse.rsに移し、両方から呼ぶ。保存済みのhitとlast_position(最後に見えた位置)に Up を送り、ピクセル座標と popup の扱いも同じ。フォーカス喪失時の順序(Up → focus-lost 通知)は変わらない。検証
単体テスト(
src/client/shell/tests/mouse_selection.rsに 4 件追加)pressing_the_held_button_on_another_pane_releases_the_stale_gesture_first:pane_1 で Down→Drag の後、Up なしで pane_2 に Down。requestsは[PaneInput{pane_1, [Up(Left)@(2,1)]}, PaneInput{pane_2, [Down(Left)@(1,0)]}]、actionsにPaneFocus(pane_2)、続く Up は pane_2 に届く。pressing_the_held_button_again_in_the_same_pane_releases_then_presses:同じペインでは[Up@旧位置, Down@新位置]が 1 メッセージにまとまる。pressing_the_held_button_again_in_the_popup_releases_then_presses:popup でもPopupInput{[Up, Down]}になる。a_replayed_link_click_press_leaves_the_held_gesture_alone:再生された Down では何も送らず、ジェスチャーも変わらない。修正を外すと前 3 件が失敗し(押下が捨てられて
requests == [])、!replaying_url_clickの条件を外すと 4 件目が失敗することを確認した。全体
cargo fmt --check:OKcargo clippy --all-targets --locked -- -D warnings:OKcargo nextest run --locked --no-fail-fast:3351 件中 3349 件成功、2 件失敗。失敗はlive_handoff::live_handoff_preserves_pane_process_ioとlive_handoff::live_handoff_keeps_unmanaged_agent_name_bound_to_saved_sessionで、どちらもdocs/fork/FORK_WORKFLOW.md§0 の環境依存の既知失敗。uv run python -m unittest scripts.test_ui_hot_path_architecture:6 件 OKPTY ハーネス
隔離した herdr セッションに SGR マウス報告を流して確かめた。修正前は 0.9.0-fork.9、修正後はこのブランチの release ビルドである。
orphan --rounds 4(「離した」が欠けた押下の後、別ペインの 1 回目のクリックでフォーカスが移るか)orphan-drag(「離した」が欠けた押下の後のドラッグ選択で、正しい範囲がコピーされるか)click --rounds 12 --app-in all --human --pre-motion 10 --timeout 1.5real --rounds 6 --panes 3 --app-fps 10 --app-any-motion --app-render-on-mouse --drag-step 0.012 --click-delay 0.15 --timeout 1.5popup --rounds 2 --drag --drag-step 0.03 --click-delay 0.2 --timeout 2bcdefghibcdefghiorphan-dragで、修正後にアプリが受け取ったイベント列は次のとおり。release@(2,1)→press@(6,3)→ drag … →release@(20,4)。残ったジェスチャーを最後に見えた位置で閉じてから押下が届く。release@(2,1)の 1 件だけが届き、新しいペインにはpress@(6,3)…release@(20,4)が届く。修正前は、同じペインでは押下が捨てられて選択が古い押下位置
(2,1)から伸びていた。別のペインでは新しいペインに何も届かず、元のペインに新しいペインの座標のままrelease@(61,4)が届いていた。なお、ハーネスの
orphan-dragの判定は「ドラッグしたペインの最初のイベントが press であること」だった。同じペインのケースでは先頭にrelease@(2,1)が来るため、コピー内容が正しくても WRONG と出る。表のorphan-dragの数字は、同じペインのときに限り先頭にその release を許すよう判定だけを直したハーネスの写しで取った。残課題(今回は直さない)
src/client/shell/input.rsのhandle_pixel_mouseで、セルに写せない座標は return する)。このときもジェスチャーは残るが、同じボタンを押し直せば今回の修正で解放される。refs #53
🤖 Generated with Claude Code