diff --git a/Sources/WindowDecorationsController.swift b/Sources/WindowDecorationsController.swift index b926a7571c7a..03229727b753 100644 --- a/Sources/WindowDecorationsController.swift +++ b/Sources/WindowDecorationsController.swift @@ -3,7 +3,6 @@ import AppKit final class WindowDecorationsController { private var observers: [NSObjectProtocol] = [] private var didStart = false - private var trafficLightBaseFrames: [ObjectIdentifier: [NSWindow.ButtonType: NSRect]] = [:] private var minimalModeSidebarChromeHoverMonitor: Any? private var lastMinimalModeTitlebarClick: MinimalModeTitlebarClickRecord? private var lastKnownPresentationMode = WorkspacePresentationModeSettings.mode() @@ -43,7 +42,6 @@ final class WindowDecorationsController { } let shouldHideButtons = shouldHideTrafficLights(for: window) hideStandardButtons(on: window, hidden: shouldHideButtons) - applyTrafficLightOffset(on: window, hidden: shouldHideButtons) applyMinimalModeSidebarTitlebarClickTarget(to: window) } @@ -359,34 +357,6 @@ final class WindowDecorationsController { window.standardWindowButton(.zoomButton)?.isHidden = hidden } - private func applyTrafficLightOffset(on window: NSWindow, hidden: Bool) { - DispatchQueue.main.async { [weak self, weak window] in - guard let self, let window else { return } - let offset = hidden ? NSPoint.zero : self.trafficLightOffset(for: window) - self.applyTrafficLightOffsetNow(on: window, offset: offset) - } - } - - private func applyTrafficLightOffsetNow(on window: NSWindow, offset: NSPoint) { - let key = ObjectIdentifier(window) - let buttonTypes: [NSWindow.ButtonType] = [.closeButton, .miniaturizeButton, .zoomButton] - var baseFrames = trafficLightBaseFrames[key] ?? [:] - - for type in buttonTypes { - guard let button = window.standardWindowButton(type) else { continue } - if baseFrames[type] == nil || (baseFrames[type]?.isEmpty ?? true) { - baseFrames[type] = button.frame - } - } - - trafficLightBaseFrames[key] = baseFrames - - for type in buttonTypes { - guard let button = window.standardWindowButton(type), let base = baseFrames[type] else { continue } - button.setFrameOrigin(NSPoint(x: base.origin.x + offset.x, y: base.origin.y + offset.y)) - } - } - private func applyMinimalModeSidebarTitlebarClickTarget(to window: NSWindow) { let shouldInstall = isMainWorkspaceWindow(window) && WorkspacePresentationModeSettings.isMinimal() @@ -460,10 +430,6 @@ final class WindowDecorationsController { minimalModeSidebarTitlebarClickTargets.removeObject(forKey: window) } - private func trafficLightOffset(for window: NSWindow) -> NSPoint { - return .zero - } - private func shouldHideTrafficLights(for window: NSWindow) -> Bool { if window.isSheet { return true diff --git a/Sources/cmuxApp.swift b/Sources/cmuxApp.swift index 9aeaea30ef9f..1f069b9376b0 100644 --- a/Sources/cmuxApp.swift +++ b/Sources/cmuxApp.swift @@ -2490,6 +2490,7 @@ enum SettingsWindowPresenter { static let windowID = "settings" static let windowIdentifier = "cmux.settings" static let minimumSize = NSSize(width: 820, height: 540) + private static let visibleAreaInset: CGFloat = 18 private static var openWindow: (@MainActor () -> Void)? private static weak var settingsWindow: NSWindow? @@ -2507,8 +2508,10 @@ enum SettingsWindowPresenter { static func configure(window: NSWindow) { settingsWindow = window window.identifier = NSUserInterfaceItemIdentifier(windowIdentifier) + window.isRestorable = false window.minSize = minimumSize window.contentMinSize = minimumSize + clampToVisibleAreaIfNeeded(window) } static func show(navigationTarget: SettingsNavigationTarget? = nil) { @@ -2561,10 +2564,29 @@ enum SettingsWindowPresenter { if window.isMiniaturized { window.deminiaturize(nil) } + clampToVisibleAreaIfNeeded(window) NSRunningApplication.current.activate(options: [.activateAllWindows]) window.makeKeyAndOrderFront(nil) window.orderFrontRegardless() } + + private static func clampToVisibleAreaIfNeeded(_ window: NSWindow) { + guard let screen = window.screen ?? NSScreen.main else { return } + var frame = window.frame + let visibleFrame = screen.visibleFrame + let minX = visibleFrame.minX + visibleAreaInset + let minY = visibleFrame.minY + visibleAreaInset + let maxX = max(minX, visibleFrame.maxX - visibleAreaInset - frame.width) + let maxY = max(minY, visibleFrame.maxY - visibleAreaInset - frame.height) + let clampedOrigin = NSPoint( + x: min(max(frame.origin.x, minX), maxX), + y: min(max(frame.origin.y, minY), maxY) + ) + + guard clampedOrigin != frame.origin else { return } + frame.origin = clampedOrigin + window.setFrame(frame, display: true) + } } // MARK: - File Explorer Style Debug