import AppKit class HiddenTitlebarTerminalWindow: TerminalWindow { override func awakeFromNib() { super.awakeFromNib() // Setup our initial style reapplyHiddenStyle() // Notifications NotificationCenter.default.addObserver( self, selector: #selector(fullscreenDidExit(_:)), name: .fullscreenDidExit, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } // We override this so that with the hidden titlebar style the titlebar // area is not draggable. override var contentLayoutRect: CGRect { var rect = super.contentLayoutRect rect.origin.y = 0 rect.size.height = self.frame.height return rect } /// Apply the hidden titlebar style. private func reapplyHiddenStyle() { styleMask = [ // We need `titled` in the mask to get the normal window frame .titled, // Full size content view so we can extend // content in to the hidden titlebar's area .fullSizeContentView, .resizable, .closable, .miniaturizable, ] // Hide the title titleVisibility = .hidden titlebarAppearsTransparent = true // Hide the traffic lights (window control buttons) standardWindowButton(.closeButton)?.isHidden = true standardWindowButton(.miniaturizeButton)?.isHidden = true standardWindowButton(.zoomButton)?.isHidden = true // Disallow tabbing if the titlebar is hidden, since that will (should) also hide the tab bar. tabbingMode = .disallowed // Nuke it from orbit -- hide the titlebar container entirely, just in case. There are // some operations that appear to bring back the titlebar visibility so this ensures // it is gone forever. if let themeFrame = contentView?.superview, let titleBarContainer = themeFrame.firstDescendant(withClassName: "NSTitlebarContainerView") { titleBarContainer.isHidden = true } } // MARK: Notifications @objc private func fullscreenDidExit(_ notification: Notification) { // Make sure they're talking about our window guard let fullscreen = notification.object as? FullscreenBase else { return } guard fullscreen.window == self else { return } // On exit we need to reapply the style because macOS breaks it usually. // This is safe to call repeatedly so if its not broken its still safe. reapplyHiddenStyle() } }