From c7bbb72e098bd096eb611a6c3b2b8a9da8c14fda Mon Sep 17 00:00:00 2001 From: austinpower1258 Date: Wed, 11 Mar 2026 18:26:25 -0700 Subject: [PATCH] Add terminal drop overlay container regression test --- Sources/GhosttyTerminalView.swift | 16 ++++ cmuxTests/CmuxWebViewKeyEquivalentTests.swift | 87 ++++++------------- 2 files changed, 41 insertions(+), 62 deletions(-) diff --git a/Sources/GhosttyTerminalView.swift b/Sources/GhosttyTerminalView.swift index bcbae0ac..3d94bb46 100644 --- a/Sources/GhosttyTerminalView.swift +++ b/Sources/GhosttyTerminalView.swift @@ -6716,6 +6716,22 @@ final class GhosttySurfaceScrollView: NSView { ) } + struct DebugDropZoneOverlayState { + let isHidden: Bool + let frame: CGRect + let isAttachedToHostedView: Bool + let isAttachedToParentContainer: Bool + } + + func debugDropZoneOverlayState() -> DebugDropZoneOverlayState { + DebugDropZoneOverlayState( + isHidden: dropZoneOverlayView.isHidden, + frame: dropZoneOverlayView.frame, + isAttachedToHostedView: dropZoneOverlayView.superview === self, + isAttachedToParentContainer: dropZoneOverlayView.superview === superview + ) + } + func debugHasSearchOverlay() -> Bool { guard let overlay = searchOverlayHostingView else { return false } return overlay.superview === self && !overlay.isHidden diff --git a/cmuxTests/CmuxWebViewKeyEquivalentTests.swift b/cmuxTests/CmuxWebViewKeyEquivalentTests.swift index d109aebd..b6d34560 100644 --- a/cmuxTests/CmuxWebViewKeyEquivalentTests.swift +++ b/cmuxTests/CmuxWebViewKeyEquivalentTests.swift @@ -10683,72 +10683,35 @@ final class GhosttySurfaceOverlayTests: XCTestCase { XCTAssertFalse(hostedView.debugHasKeyboardCopyModeIndicator()) } - func testDropHoverOverlayDefersTerminalResizeUntilHoverEnds() { - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 360, height: 240), - styleMask: [.titled, .closable], - backing: .buffered, - defer: false + @MainActor + func testDropHoverOverlayAttachesToParentContainerInsteadOfHostedTerminalView() { + let container = NSView(frame: NSRect(x: 0, y: 0, width: 240, height: 120)) + let surfaceView = GhosttyNSView(frame: .zero) + let hostedView = GhosttySurfaceScrollView(surfaceView: surfaceView) + hostedView.frame = container.bounds + container.addSubview(hostedView) + + hostedView.setDropZoneOverlay(zone: .right) + container.layoutSubtreeIfNeeded() + + let state = hostedView.debugDropZoneOverlayState() + XCTAssertFalse(state.isHidden) + XCTAssertFalse( + state.isAttachedToHostedView, + "Drop-hover overlay should be mounted outside the hosted terminal view" ) - defer { window.orderOut(nil) } - - guard let contentView = window.contentView else { - XCTFail("Expected content view") - return - } - - let surface = TerminalSurface( - tabId: UUID(), - context: GHOSTTY_SURFACE_CONTEXT_SPLIT, - configTemplate: nil, - workingDirectory: nil - ) - let hostedView = surface.hostedView - hostedView.frame = contentView.bounds - contentView.addSubview(hostedView) - - window.makeKeyAndOrderFront(nil) - window.displayIfNeeded() - contentView.layoutSubtreeIfNeeded() - RunLoop.current.run(until: Date().addingTimeInterval(0.05)) - - let initialPixelSize = surface.debugCurrentPixelSize() - XCTAssertGreaterThan(initialPixelSize.width, 0) - XCTAssertGreaterThan(initialPixelSize.height, 0) - - hostedView.setDropZoneOverlay(zone: .left) - hostedView.frame = NSRect(x: 0, y: 0, width: 440, height: 280) - contentView.layoutSubtreeIfNeeded() - hostedView.layoutSubtreeIfNeeded() - RunLoop.current.run(until: Date().addingTimeInterval(0.05)) - - XCTAssertEqual( - surface.debugCurrentPixelSize().width, - initialPixelSize.width, - "Active drop-hover overlay should not resize the terminal surface before drop" - ) - XCTAssertEqual( - surface.debugCurrentPixelSize().height, - initialPixelSize.height, - "Active drop-hover overlay should keep the terminal surface height stable before drop" + XCTAssertTrue( + state.isAttachedToParentContainer, + "Drop-hover overlay should be mounted in the parent container so it cannot perturb terminal layout" ) + XCTAssertEqual(state.frame.origin.x, 120, accuracy: 0.5) + XCTAssertEqual(state.frame.origin.y, 4, accuracy: 0.5) + XCTAssertEqual(state.frame.size.width, 116, accuracy: 0.5) + XCTAssertEqual(state.frame.size.height, 112, accuracy: 0.5) hostedView.setDropZoneOverlay(zone: nil) - contentView.layoutSubtreeIfNeeded() - hostedView.layoutSubtreeIfNeeded() - RunLoop.current.run(until: Date().addingTimeInterval(0.05)) - - let resizedPixelSize = surface.debugCurrentPixelSize() - XCTAssertGreaterThan( - resizedPixelSize.width, - initialPixelSize.width, - "Clearing the drop-hover overlay should allow the deferred terminal resize to land" - ) - XCTAssertGreaterThan( - resizedPixelSize.height, - initialPixelSize.height, - "Clearing the drop-hover overlay should restore the pending terminal height update" - ) + RunLoop.current.run(until: Date().addingTimeInterval(0.25)) + XCTAssertTrue(hostedView.debugDropZoneOverlayState().isHidden) } func testForceRefreshNoopsAfterSurfaceReleaseDuringGeometryReconcile() throws {