diff --git a/Sources/ContentView.swift b/Sources/ContentView.swift index dbbf15f57461..8ff416373c82 100644 --- a/Sources/ContentView.swift +++ b/Sources/ContentView.swift @@ -2055,6 +2055,30 @@ struct ContentView: View { return -max(0, min(titlebarPadding, hostingSafeAreaTop)) } + nonisolated static func customTitlebarLeadingPadding( + isFullScreen: Bool, + isSidebarVisible: Bool, + sidebarWidth: CGFloat, + minimumSidebarWidth: CGFloat, + titlebarLeadingInset: CGFloat + ) -> CGFloat { + if isFullScreen && !isSidebarVisible { + return 8 + } + + let minimumSidebarTitleInset = max(titlebarLeadingInset, minimumSidebarWidth + 12) + guard isSidebarVisible else { + return minimumSidebarTitleInset + } + + let visibleSidebarTitleInset = sidebarWidth + 12 + // Absorb floating-point drift around the minimum-width clamp. + guard sidebarWidth > minimumSidebarWidth + 0.5 else { + return minimumSidebarTitleInset + } + return max(titlebarLeadingInset, visibleSidebarTitleInset) + } + private func terminalContent(appearance: WindowAppearanceSnapshot) -> some View { let mountedWorkspaceIdSet = Set(mountedWorkspaceIds) let mountedWorkspaces = tabManager.tabs.filter { mountedWorkspaceIdSet.contains($0.id) } @@ -2334,6 +2358,13 @@ struct ContentView: View { private func customTitlebar(appearance: WindowAppearanceSnapshot) -> some View { let titlebarContentHeight = max(1, WindowChromeMetrics.appTitlebarHeight - 2) + let leadingPadding = Self.customTitlebarLeadingPadding( + isFullScreen: isFullScreen, + isSidebarVisible: sidebarState.isVisible, + sidebarWidth: sidebarWidth, + minimumSidebarWidth: minimumSidebarWidth, + titlebarLeadingInset: titlebarLeadingInset + ) return ZStack { // Enable window dragging from the titlebar strip without making the entire content // view draggable (which breaks drag gestures like tab reordering). @@ -2365,7 +2396,7 @@ struct ContentView: View { } .frame(height: titlebarContentHeight) .padding(.top, 2) - .padding(.leading, (isFullScreen && !sidebarState.isVisible) ? 8 : (sidebarState.isVisible ? sidebarWidth + 12 : titlebarLeadingInset)) + .padding(.leading, leadingPadding) .padding(.trailing, 8) } .frame(height: WindowChromeMetrics.appTitlebarHeight) diff --git a/cmuxTests/WindowAndDragTests.swift b/cmuxTests/WindowAndDragTests.swift index 626b64658077..929eb6cecb81 100644 --- a/cmuxTests/WindowAndDragTests.swift +++ b/cmuxTests/WindowAndDragTests.swift @@ -3,6 +3,7 @@ import AppKit import Carbon.HIToolbox import Darwin import PDFKit +import Testing import SwiftUI import UniformTypeIdentifiers import WebKit @@ -1958,6 +1959,73 @@ final class TitlebarLeadingInsetPassthroughViewTests: XCTestCase { } +@Suite("Custom titlebar leading padding") +struct CustomTitlebarLeadingPaddingTests { + @Test func hiddenSidebarUsesMinimumSidebarTitleInset() { + #expect( + ContentView.customTitlebarLeadingPadding( + isFullScreen: false, + isSidebarVisible: false, + sidebarWidth: 216, + minimumSidebarWidth: 216, + titlebarLeadingInset: 82 + ) == 228 + ) + } + + @Test func minimumWidthVisibleSidebarMatchesHiddenSidebarTitleInset() { + let hidden = ContentView.customTitlebarLeadingPadding( + isFullScreen: false, + isSidebarVisible: false, + sidebarWidth: 216, + minimumSidebarWidth: 216, + titlebarLeadingInset: 82 + ) + let visible = ContentView.customTitlebarLeadingPadding( + isFullScreen: false, + isSidebarVisible: true, + sidebarWidth: 216, + minimumSidebarWidth: 216, + titlebarLeadingInset: 82 + ) + + #expect(visible == hidden) + } + + @Test func widerSidebarPushesTitlebarContentRight() { + let hidden = ContentView.customTitlebarLeadingPadding( + isFullScreen: false, + isSidebarVisible: false, + sidebarWidth: 216, + minimumSidebarWidth: 216, + titlebarLeadingInset: 82 + ) + let visible = ContentView.customTitlebarLeadingPadding( + isFullScreen: false, + isSidebarVisible: true, + sidebarWidth: 320, + minimumSidebarWidth: 216, + titlebarLeadingInset: 82 + ) + + #expect(visible > hidden) + #expect(visible == 332) + } + + @Test func fullscreenHiddenSidebarKeepsCompactInset() { + #expect( + ContentView.customTitlebarLeadingPadding( + isFullScreen: true, + isSidebarVisible: false, + sidebarWidth: 216, + minimumSidebarWidth: 216, + titlebarLeadingInset: 82 + ) == 8 + ) + } +} + + @MainActor final class FolderWindowMoveSuppressionTests: XCTestCase { private func makeWindow() -> NSWindow {