mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-04-20 00:18:53 +03:00
113 lines
3.8 KiB
Swift
113 lines
3.8 KiB
Swift
import Foundation
|
|
import Cocoa
|
|
import SwiftUI
|
|
import GhosttyKit
|
|
|
|
class TerminalController: NSWindowController, NSWindowDelegate, TerminalViewDelegate {
|
|
override var windowNibName: NSNib.Name? { "Terminal" }
|
|
|
|
/// The app instance that this terminal view will represent.
|
|
let ghostty: Ghostty.AppState
|
|
|
|
/// The currently focused surface.
|
|
var focusedSurface: Ghostty.SurfaceView? = nil
|
|
|
|
/// Fullscreen state management.
|
|
private let fullscreenHandler = FullScreenHandler()
|
|
|
|
init(_ ghostty: Ghostty.AppState) {
|
|
self.ghostty = ghostty
|
|
super.init(window: nil)
|
|
|
|
let center = NotificationCenter.default
|
|
center.addObserver(
|
|
self,
|
|
selector: #selector(onToggleFullscreen),
|
|
name: Ghostty.Notification.ghosttyToggleFullscreen,
|
|
object: nil)
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) is not supported for this view")
|
|
}
|
|
|
|
deinit {
|
|
// Remove all of our notificationcenter subscriptions
|
|
let center = NotificationCenter.default
|
|
center.removeObserver(self)
|
|
}
|
|
|
|
//MARK: - NSWindowController
|
|
|
|
override func windowWillLoad() {
|
|
// We want every new terminal window to cascade so they don't directly overlap.
|
|
shouldCascadeWindows = true
|
|
}
|
|
|
|
override func windowDidLoad() {
|
|
guard let window = window else { return }
|
|
|
|
// Terminals typically operate in sRGB color space and macOS defaults
|
|
// to "native" which is typically P3. There is a lot more resources
|
|
// covered in thie GitHub issue: https://github.com/mitchellh/ghostty/pull/376
|
|
window.colorSpace = NSColorSpace.sRGB
|
|
|
|
// Center the window to start, we'll move the window frame automatically
|
|
// when cascading.
|
|
window.center()
|
|
|
|
// Initialize our content view to the SwiftUI root
|
|
window.contentView = NSHostingView(rootView: TerminalView(
|
|
ghostty: self.ghostty,
|
|
delegate: self
|
|
))
|
|
}
|
|
|
|
// Shows the "+" button in the tab bar, responds to that click.
|
|
override func newWindowForTab(_ sender: Any?) {
|
|
// Trigger the ghostty core event logic for a new tab.
|
|
guard let surface = self.focusedSurface?.surface else { return }
|
|
ghostty.newTab(surface: surface)
|
|
}
|
|
|
|
//MARK: - NSWindowDelegate
|
|
|
|
func windowWillClose(_ notification: Notification) {
|
|
}
|
|
|
|
//MARK: - TerminalViewDelegate
|
|
|
|
func focusedSurfaceDidChange(to: Ghostty.SurfaceView?) {
|
|
self.focusedSurface = to
|
|
}
|
|
|
|
func titleDidChange(to: String) {
|
|
self.window?.title = to
|
|
}
|
|
|
|
func cellSizeDidChange(to: NSSize) {
|
|
guard ghostty.windowStepResize else { return }
|
|
self.window?.contentResizeIncrements = to
|
|
}
|
|
|
|
//MARK: - Notifications
|
|
|
|
@objc private func onToggleFullscreen(notification: SwiftUI.Notification) {
|
|
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
|
guard target == self.focusedSurface else { return }
|
|
|
|
// We need a window to fullscreen
|
|
guard let window = self.window else { return }
|
|
|
|
// Check whether we use non-native fullscreen
|
|
guard let useNonNativeFullscreenAny = notification.userInfo?[Ghostty.Notification.NonNativeFullscreenKey] else { return }
|
|
guard let useNonNativeFullscreen = useNonNativeFullscreenAny as? ghostty_non_native_fullscreen_e else { return }
|
|
self.fullscreenHandler.toggleFullscreen(window: window, nonNativeFullscreen: useNonNativeFullscreen)
|
|
|
|
// For some reason focus always gets lost when we toggle fullscreen, so we set it back.
|
|
if let focusedSurface {
|
|
Ghostty.moveFocus(to: focusedSurface)
|
|
}
|
|
}
|
|
}
|