diff --git a/macos/Sources/Features/Terminal/BaseTerminalController.swift b/macos/Sources/Features/Terminal/BaseTerminalController.swift index 5d9d5d527..eca789d47 100644 --- a/macos/Sources/Features/Terminal/BaseTerminalController.swift +++ b/macos/Sources/Features/Terminal/BaseTerminalController.swift @@ -766,7 +766,8 @@ class BaseTerminalController: NSWindowController, ghostty, tree: newTree, position: notification.userInfo?[Notification.Name.ghosttySurfaceDragEndedNoTargetPointKey] as? NSPoint, - confirmUndo: false) + confirmUndo: false, + inheritBackgroundOpacityFrom: self as? TerminalController) } // MARK: Local Events diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift index 56b0b40ad..066e9430c 100644 --- a/macos/Sources/Features/Terminal/TerminalController.swift +++ b/macos/Sources/Features/Terminal/TerminalController.swift @@ -230,6 +230,9 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr // Get our parent. Our parent is the one explicitly given to us, // otherwise the focused terminal, otherwise an arbitrary one. let parent: NSWindow? = explicitParent ?? preferredParent?.window + if let parentController = parent?.windowController as? TerminalController { + c.isBackgroundOpaque = parentController.isBackgroundOpaque + } if let parent, parent.styleMask.contains(.fullScreen) { // If our previous window was fullscreen then we want our new window to @@ -313,8 +316,12 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr tree: SplitTree, position: NSPoint? = nil, confirmUndo: Bool = true, + inheritBackgroundOpacityFrom parentController: TerminalController? = nil ) -> TerminalController { let c = TerminalController.init(ghostty, withSurfaceTree: tree) + if let parentController { + c.isBackgroundOpaque = parentController.isBackgroundOpaque + } // Calculate the target frame based on the tree's view bounds let treeSize: CGSize? = tree.root?.viewBounds() @@ -359,7 +366,11 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr withTarget: ghostty, expiresAfter: target.undoExpiration ) { ghostty in - _ = TerminalController.newWindow(ghostty, tree: tree) + _ = TerminalController.newWindow( + ghostty, + tree: tree, + inheritBackgroundOpacityFrom: parentController + ) } } } @@ -394,6 +405,7 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr // Create a new window and add it to the parent let controller = TerminalController.init(ghostty, withBaseConfig: baseConfig) + controller.isBackgroundOpaque = parentController.isBackgroundOpaque guard let window = controller.window else { return controller } // If the parent is miniaturized, then macOS exhibits really strange behaviors @@ -491,6 +503,30 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr return controller } + override func toggleBackgroundOpacity() { + // Do nothing if config is already fully opaque + guard ghostty.config.backgroundOpacity < 1 else { return } + + // Do nothing if in fullscreen (transparency doesn't apply in fullscreen) + guard let window, !window.styleMask.contains(.fullScreen) else { return } + + let newValue = !isBackgroundOpaque + let controllers: [TerminalController] + + if let tabGroup = window.tabGroup { + controllers = tabGroup.windows.compactMap { + $0.windowController as? TerminalController + } + } else { + controllers = [self] + } + + for controller in controllers { + controller.isBackgroundOpaque = newValue + controller.syncAppearance() + } + } + // MARK: - Methods @objc private func ghosttyConfigDidChange(_ notification: Notification) {