Fix issue #185 overlay recursion hardening and scroll regression (#193)

This commit is contained in:
Austin Wang 2026-02-20 14:51:44 -08:00 committed by GitHub
parent 94d44fefd2
commit f455af4541
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 4 deletions

View file

@ -171,6 +171,7 @@ final class SidebarState: ObservableObject {
final class FileDropOverlayView: NSView {
/// Fallback handler when no terminal is found under the drop point.
var onDrop: (([URL]) -> Bool)?
private var isForwardingMouseEvent = false
override var acceptsFirstResponder: Bool { false }
@ -207,12 +208,19 @@ final class FileDropOverlayView: NSView {
// window.sendEvent(), which caches the mouse target and causes infinite recursion.
private func forwardEvent(_ event: NSEvent) {
guard !isForwardingMouseEvent else { return }
guard let window, let contentView = window.contentView else { return }
isForwardingMouseEvent = true
isHidden = true
defer {
isHidden = false
isForwardingMouseEvent = false
}
let point = contentView.convert(event.locationInWindow, from: nil)
let target = contentView.hitTest(point)
isHidden = false
guard let target else { return }
guard let target, target !== self else { return }
switch event.type {
case .leftMouseDown: target.mouseDown(with: event)
@ -273,9 +281,9 @@ final class FileDropOverlayView: NSView {
guard let window, let contentView = window.contentView else { return nil }
isHidden = true
defer { isHidden = false }
let point = contentView.convert(windowPoint, from: nil)
let hitView = contentView.hitTest(point)
isHidden = false
var current: NSView? = hitView
while let view = current {

View file

@ -104,6 +104,34 @@ up?.post(tap: .cghidEventTap)
)
def post_scroll_with_cgevent(x: float, y: float, delta_y: int = 3) -> None:
ix = int(round(x))
iy = int(round(y))
code = f"""
import CoreGraphics
let p = CGPoint(x: {ix}, y: {iy})
let source = CGEventSource(stateID: .hidSystemState)
if let scroll = CGEvent(
scrollWheelEvent2Source: source,
units: .line,
wheelCount: 1,
wheel1: Int32({delta_y}),
wheel2: 0,
wheel3: 0
) {{
scroll.location = p
scroll.post(tap: .cghidEventTap)
}}
"""
subprocess.run(
["swift", "-e", code],
check=True,
capture_output=True,
text=True,
timeout=10,
)
def pick_top_bottom_terminal_panels(layout: dict) -> tuple[dict, dict]:
candidates = []
for panel in layout.get("selectedPanels", []):
@ -282,7 +310,14 @@ def main() -> int:
print("FAIL: real right click disrupted terminal focus routing")
return 1
print("PASS: stale file-drag overlay forwards real left/right clicks")
for _ in range(6):
post_scroll_with_cgevent(click_x, click_y, delta_y=2)
time.sleep(0.25)
if not client.is_terminal_focused(bottom_id):
print("FAIL: real scroll wheel disrupted terminal focus routing")
return 1
print("PASS: stale file-drag overlay forwards real left/right clicks and scroll")
print(f" focused_panel={bottom_id}")
return 0
finally: