diff --git a/macos/Ghostty.xcodeproj/project.pbxproj b/macos/Ghostty.xcodeproj/project.pbxproj index 2847bac6c..9fef6281e 100644 --- a/macos/Ghostty.xcodeproj/project.pbxproj +++ b/macos/Ghostty.xcodeproj/project.pbxproj @@ -8,11 +8,11 @@ /* Begin PBXBuildFile section */ 8503D7C72A549C66006CFF3D /* FullScreenHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8503D7C62A549C66006CFF3D /* FullScreenHandler.swift */; }; - 85102A1A2A6E32720084AB3E /* WindowService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85102A192A6E32720084AB3E /* WindowService.swift */; }; - 85102A1C2A6E32890084AB3E /* WindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85102A1B2A6E32890084AB3E /* WindowController.swift */; }; - 852655222A597CA900E4F7AD /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852655212A597CA900E4F7AD /* main.swift */; }; + 85102A1C2A6E32890084AB3E /* PrimaryWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85102A1B2A6E32890084AB3E /* PrimaryWindowController.swift */; }; 857F63812A5E64F200CA4815 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 857F63802A5E64F200CA4815 /* MainMenu.xib */; }; - 85DE1C922A6A3DCA00493853 /* CustomWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DE1C912A6A3DCA00493853 /* CustomWindow.swift */; }; + 85DE1C922A6A3DCA00493853 /* PrimaryWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DE1C912A6A3DCA00493853 /* PrimaryWindow.swift */; }; + A53426352A7DA53D00EBB7A2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */; }; + A53426392A7DC55C00EBB7A2 /* PrimaryWindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53426382A7DC55C00EBB7A2 /* PrimaryWindowManager.swift */; }; A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A535B9D9299C569B0017E2E4 /* ErrorView.swift */; }; A545D1A22A5772CE006E0AE4 /* shell-integration in Resources */ = {isa = PBXBuildFile; fileRef = A545D1A12A5772CE006E0AE4 /* shell-integration */; }; A55685E029A03A9F004303CE /* AppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55685DF29A03A9F004303CE /* AppError.swift */; }; @@ -23,7 +23,6 @@ A571AB1D2A206FCF00248498 /* GhosttyKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */; }; A59444F729A2ED5200725BBA /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59444F629A2ED5200725BBA /* SettingsView.swift */; }; A5A1F8852A489D6800D1E8BC /* terminfo in Resources */ = {isa = PBXBuildFile; fileRef = A5A1F8842A489D6800D1E8BC /* terminfo */; }; - A5B30535299BEAAA0047F10C /* GhosttyAppController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B30534299BEAAA0047F10C /* GhosttyAppController.swift */; }; A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A5B30538299BEAAB0047F10C /* Assets.xcassets */; }; A5CEAFDC29B8009000646FDA /* SplitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFDB29B8009000646FDA /* SplitView.swift */; }; A5CEAFDE29B8058B00646FDA /* SplitView.Divider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFDD29B8058B00646FDA /* SplitView.Divider.swift */; }; @@ -34,11 +33,11 @@ /* Begin PBXFileReference section */ 8503D7C62A549C66006CFF3D /* FullScreenHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FullScreenHandler.swift; sourceTree = ""; }; - 85102A192A6E32720084AB3E /* WindowService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowService.swift; sourceTree = ""; }; - 85102A1B2A6E32890084AB3E /* WindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowController.swift; sourceTree = ""; }; - 852655212A597CA900E4F7AD /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + 85102A1B2A6E32890084AB3E /* PrimaryWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimaryWindowController.swift; sourceTree = ""; }; 857F63802A5E64F200CA4815 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; - 85DE1C912A6A3DCA00493853 /* CustomWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomWindow.swift; sourceTree = ""; }; + 85DE1C912A6A3DCA00493853 /* PrimaryWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimaryWindow.swift; sourceTree = ""; }; + A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + A53426382A7DC55C00EBB7A2 /* PrimaryWindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimaryWindowManager.swift; sourceTree = ""; }; A535B9D9299C569B0017E2E4 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = ""; }; A545D1A12A5772CE006E0AE4 /* shell-integration */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "shell-integration"; path = "../zig-out/share/shell-integration"; sourceTree = ""; }; A55685DF29A03A9F004303CE /* AppError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppError.swift; sourceTree = ""; }; @@ -50,7 +49,6 @@ A59444F629A2ED5200725BBA /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; A5A1F8842A489D6800D1E8BC /* terminfo */ = {isa = PBXFileReference; lastKnownFileType = folder; name = terminfo; path = "../zig-out/share/terminfo"; sourceTree = ""; }; A5B30531299BEAAA0047F10C /* Ghostty.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ghostty.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A5B30534299BEAAA0047F10C /* GhosttyAppController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhosttyAppController.swift; sourceTree = ""; }; A5B30538299BEAAB0047F10C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; A5B3053D299BEAAB0047F10C /* Ghostty.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Ghostty.entitlements; sourceTree = ""; }; A5CEAFDB29B8009000646FDA /* SplitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitView.swift; sourceTree = ""; }; @@ -73,14 +71,39 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + A53426362A7DC53000EBB7A2 /* Features */ = { + isa = PBXGroup; + children = ( + A53426372A7DC53A00EBB7A2 /* Primary Window */, + ); + path = Features; + sourceTree = ""; + }; + A53426372A7DC53A00EBB7A2 /* Primary Window */ = { + isa = PBXGroup; + children = ( + A53426382A7DC55C00EBB7A2 /* PrimaryWindowManager.swift */, + 85102A1B2A6E32890084AB3E /* PrimaryWindowController.swift */, + 85DE1C912A6A3DCA00493853 /* PrimaryWindow.swift */, + ); + path = "Primary Window"; + sourceTree = ""; + }; + A534263A2A7DC61B00EBB7A2 /* Core */ = { + isa = PBXGroup; + children = ( + A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */, + ); + path = Core; + sourceTree = ""; + }; A54CD6ED299BEB14008C95BB /* Sources */ = { isa = PBXGroup; children = ( - A5D495A0299BEC2200DD1313 /* Preview Content */, + A534263A2A7DC61B00EBB7A2 /* Core */, + A53426362A7DC53000EBB7A2 /* Features */, A5CEAFDA29B8005900646FDA /* SplitView */, A55B7BB429B6F4410055DE60 /* Ghostty */, - A5B30534299BEAAA0047F10C /* GhosttyAppController.swift */, - 85DE1C912A6A3DCA00493853 /* CustomWindow.swift */, 857F63802A5E64F200CA4815 /* MainMenu.xib */, A535B9D9299C569B0017E2E4 /* ErrorView.swift */, A55685DF29A03A9F004303CE /* AppError.swift */, @@ -89,9 +112,6 @@ A5FECBD629D1FC3900022361 /* ContentView.swift */, A5FECBD829D2010400022361 /* WindowAccessor.swift */, 8503D7C62A549C66006CFF3D /* FullScreenHandler.swift */, - 852655212A597CA900E4F7AD /* main.swift */, - 85102A192A6E32720084AB3E /* WindowService.swift */, - 85102A1B2A6E32890084AB3E /* WindowController.swift */, ); path = Sources; sourceTree = ""; @@ -146,13 +166,6 @@ path = SplitView; sourceTree = ""; }; - A5D495A0299BEC2200DD1313 /* Preview Content */ = { - isa = PBXGroup; - children = ( - ); - path = "Preview Content"; - sourceTree = ""; - }; A5D495A3299BECBA00DD1313 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -233,8 +246,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 85102A1A2A6E32720084AB3E /* WindowService.swift in Sources */, - 85DE1C922A6A3DCA00493853 /* CustomWindow.swift in Sources */, + A53426392A7DC55C00EBB7A2 /* PrimaryWindowManager.swift in Sources */, + 85DE1C922A6A3DCA00493853 /* PrimaryWindow.swift in Sources */, + A53426352A7DA53D00EBB7A2 /* AppDelegate.swift in Sources */, A55B7BBC29B6FC330055DE60 /* SurfaceView.swift in Sources */, A59444F729A2ED5200725BBA /* SettingsView.swift in Sources */, A5FECBD729D1FC3900022361 /* ContentView.swift in Sources */, @@ -245,9 +259,7 @@ A55685E029A03A9F004303CE /* AppError.swift in Sources */, A5FECBD929D2010400022361 /* WindowAccessor.swift in Sources */, A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */, - A5B30535299BEAAA0047F10C /* GhosttyAppController.swift in Sources */, - 85102A1C2A6E32890084AB3E /* WindowController.swift in Sources */, - 852655222A597CA900E4F7AD /* main.swift in Sources */, + 85102A1C2A6E32890084AB3E /* PrimaryWindowController.swift in Sources */, A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */, 8503D7C72A549C66006CFF3D /* FullScreenHandler.swift in Sources */, A5CEAFDE29B8058B00646FDA /* SplitView.Divider.swift in Sources */, @@ -381,7 +393,6 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"Sources/Preview Content\""; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; @@ -415,7 +426,6 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"Sources/Preview Content\""; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; diff --git a/macos/Sources/GhosttyAppController.swift b/macos/Sources/Core/AppDelegate.swift similarity index 85% rename from macos/Sources/GhosttyAppController.swift rename to macos/Sources/Core/AppDelegate.swift index cec0fa12a..a986eb423 100644 --- a/macos/Sources/GhosttyAppController.swift +++ b/macos/Sources/Core/AppDelegate.swift @@ -1,36 +1,82 @@ -import OSLog -import SwiftUI import AppKit +import OSLog import GhosttyKit -class GhosttyAppController: NSObject { - @IBOutlet weak fileprivate var mainMenu: NSMenu! - +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { + // The application logger. We should probably move this at some point to a dedicated + // class/struct but for now it lives here! 🤷‍♂️ static let logger = Logger( subsystem: Bundle.main.bundleIdentifier!, category: String(describing: AppDelegate.self) ) + // confirmQuit published so other views can check whether quit needs to be confirmed. + @Published var confirmQuit: Bool = false + /// The ghostty global state. Only one per process. - var ghostty: Ghostty.AppState = Ghostty.AppState() + private var ghostty: Ghostty.AppState = Ghostty.AppState() /// Manages windows and tabs, ensuring they're allocated/deallocated correctly - var windowService: WindowService! + private var windowManager: PrimaryWindowManager! override init() { super.init() - // We're initialized through the MainMenu, because we're a referenced objected. - // So when we're here, we initialize the WindowService, which will open first window. - windowService = WindowService(ghostty: self.ghostty) + windowManager = PrimaryWindowManager(ghostty: self.ghostty) + } + + func applicationDidFinishLaunching(_ notification: Notification) { + // System settings overrides + UserDefaults.standard.register(defaults: [ + // Disable this so that repeated key events make it through to our terminal views. + "ApplePressAndHoldEnabled": false, + ]) + + // Let's launch our first window. + // TODO: we should detect if we restored windows and if so not launch a new window. + windowManager.addInitialWindow() + } + + func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { + let windows = NSApplication.shared.windows + if (windows.isEmpty) { return .terminateNow } + + // This probably isn't fully safe. The isEmpty check above is aspirational, it doesn't + // quite work with SwiftUI because windows are retained on close. So instead we check + // if there are any that are visible. I'm guessing this breaks under certain scenarios. + if (windows.allSatisfy { !$0.isVisible }) { return .terminateNow } + + // If the user is shutting down, restarting, or logging out, we don't confirm quit. + if let event = NSAppleEventManager.shared().currentAppleEvent { + if let why = event.attributeDescriptor(forKeyword: AEKeyword("why?")!) { + switch (why.typeCodeValue) { + case kAEShutDown: + fallthrough + + case kAERestart: + fallthrough + + case kAEReallyLogOut: + return .terminateNow + + default: + break + } + } + } + + // We have some visible window, and all our windows will watch the confirmQuit. + confirmQuit = true + return .terminateLater } @IBAction func newWindow(_ sender: Any?) { - windowService.addNewWindow() + windowManager.addNewWindow() } @IBAction func newTab(_ sender: Any?) { - windowService.addNewTab() + windowManager.addNewTab() } @IBAction func closeWindow(_ sender: Any) { @@ -48,7 +94,7 @@ class GhosttyAppController: NSObject { } private func focusedSurface() -> ghostty_surface_t? { - guard let window = NSApp.keyWindow as? CustomWindow else { return nil } + guard let window = NSApp.keyWindow as? PrimaryWindow else { return nil } return window.focusedSurfaceWrapper.surface } @@ -91,48 +137,3 @@ class GhosttyAppController: NSObject { ghostty.splitMoveFocus(surface: surface, direction: direction) } } - -class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { - // confirmQuit published so other views can check whether quit needs to be confirmed. - @Published var confirmQuit: Bool = false - - func applicationDidFinishLaunching(_ notification: Notification) { - UserDefaults.standard.register(defaults: [ - // Disable this so that repeated key events make it through to our terminal views. - "ApplePressAndHoldEnabled": false, - ]) - } - - func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { - let windows = NSApplication.shared.windows - if (windows.isEmpty) { return .terminateNow } - - // This probably isn't fully safe. The isEmpty check above is aspirational, it doesn't - // quite work with SwiftUI because windows are retained on close. So instead we check - // if there are any that are visible. I'm guessing this breaks under certain scenarios. - if (windows.allSatisfy { !$0.isVisible }) { return .terminateNow } - - // If the user is shutting down, restarting, or logging out, we don't confirm quit. - if let event = NSAppleEventManager.shared().currentAppleEvent { - if let why = event.attributeDescriptor(forKeyword: AEKeyword("why?")!) { - switch (why.typeCodeValue) { - case kAEShutDown: - fallthrough - - case kAERestart: - fallthrough - - case kAEReallyLogOut: - return .terminateNow - - default: - break - } - } - } - - // We have some visible window, and all our windows will watch the confirmQuit. - confirmQuit = true - return .terminateLater - } -} diff --git a/macos/Sources/CustomWindow.swift b/macos/Sources/Features/Primary Window/PrimaryWindow.swift similarity index 70% rename from macos/Sources/CustomWindow.swift rename to macos/Sources/Features/Primary Window/PrimaryWindow.swift index 58371b40a..90ba15a3c 100644 --- a/macos/Sources/CustomWindow.swift +++ b/macos/Sources/Features/Primary Window/PrimaryWindow.swift @@ -8,18 +8,20 @@ class FocusedSurfaceWrapper { var surface: ghostty_surface_t? } -// CustomWindow exists purely so we can override canBecomeKey and canBecomeMain. -// We need that for the non-native fullscreen. -// If we don't use `CustomWindow` we'll get warning messages in the output to say that -// `makeKeyWindow` was called and returned NO. -class CustomWindow: NSWindow { +// PrimaryWindow is the primary window you'd associate with a terminal: the window +// that contains one or more terminals (splits, and such). +// +// We need to subclass NSWindow so that we can override some methods for features +// such as non-native fullscreen. +class PrimaryWindow: NSWindow { var focusedSurfaceWrapper: FocusedSurfaceWrapper = FocusedSurfaceWrapper() - static func create(ghostty: Ghostty.AppState, appDelegate: AppDelegate) -> CustomWindow { - let window = CustomWindow( + static func create(ghostty: Ghostty.AppState, appDelegate: AppDelegate) -> PrimaryWindow { + let window = PrimaryWindow( contentRect: NSRect(x: 0, y: 0, width: 800, height: 600), styleMask: [.titled, .closable, .miniaturizable, .resizable], - backing: .buffered, defer: false) + backing: .buffered, + defer: false) window.center() window.contentView = NSHostingView(rootView: ContentView( ghostty: ghostty, diff --git a/macos/Sources/Features/Primary Window/PrimaryWindowController.swift b/macos/Sources/Features/Primary Window/PrimaryWindowController.swift new file mode 100644 index 000000000..c0e1961c2 --- /dev/null +++ b/macos/Sources/Features/Primary Window/PrimaryWindowController.swift @@ -0,0 +1,14 @@ +import Cocoa + +class PrimaryWindowController: NSWindowController { + // Keep track of the last point that our window was launched at so that new + // windows "cascade" over each other and don't just launch directly on top + // of each other. + static var lastCascadePoint = NSPoint(x: 0, y: 0) + + static func create(ghosttyApp: Ghostty.AppState, appDelegate: AppDelegate) -> PrimaryWindowController { + let window = PrimaryWindow.create(ghostty: ghosttyApp, appDelegate: appDelegate) + lastCascadePoint = window.cascadeTopLeft(from: lastCascadePoint) + return PrimaryWindowController(window: window) + } +} diff --git a/macos/Sources/WindowService.swift b/macos/Sources/Features/Primary Window/PrimaryWindowManager.swift similarity index 76% rename from macos/Sources/WindowService.swift rename to macos/Sources/Features/Primary Window/PrimaryWindowManager.swift index f751c92fb..67f32e82f 100644 --- a/macos/Sources/WindowService.swift +++ b/macos/Sources/Features/Primary Window/PrimaryWindowManager.swift @@ -1,17 +1,20 @@ import Cocoa import Combine -// WindowService manages the windows and tabs in the application. -// It keeps references to windows and cleans them up when they're cloned. +// PrimaryWindowManager manages the windows and tabs in the primary window +// of the application. It keeps references to windows and cleans them up when +// they're cloned. +// +// If we ever have multiple tabbed window types we can make this generic but +// right now only our primary window is ever duplicated or tabbed so we're not +// doing that. // // It is based on the patterns presented in this blog post: // https://christiantietze.de/posts/2019/07/nswindow-tabbing-multiple-nswindowcontroller/ -class WindowService { +class PrimaryWindowManager { struct ManagedWindow { let windowController: NSWindowController - let window: NSWindow - let closePublisher: AnyCancellable } @@ -20,11 +23,10 @@ class WindowService { init(ghostty: Ghostty.AppState) { self.ghostty = ghostty - - addInitialWindow() } - private func addInitialWindow() { + /// Add the initial window for the application. This should only be called once from the AppDelegate. + func addInitialWindow() { guard let controller = createWindowController() else { return } controller.showWindow(self) let result = addManagedWindow(windowController: controller) @@ -54,12 +56,12 @@ class WindowService { return (mainManagedWindow ?? managedWindows.first).map { $0.window } } - private func createWindowController() -> WindowController? { + private func createWindowController() -> PrimaryWindowController? { guard let appDelegate = NSApplication.shared.delegate as? AppDelegate else { return nil } - return WindowController.create(ghosttyApp: self.ghostty, appDelegate: appDelegate) + return PrimaryWindowController.create(ghosttyApp: self.ghostty, appDelegate: appDelegate) } - private func addManagedWindow(windowController: WindowController) -> ManagedWindow? { + private func addManagedWindow(windowController: PrimaryWindowController) -> ManagedWindow? { guard let window = windowController.window else { return nil } let pubClose = NotificationCenter.default.publisher(for: NSWindow.willCloseNotification, object: window) diff --git a/macos/Sources/Ghostty/AppState.swift b/macos/Sources/Ghostty/AppState.swift index f3e8a64c4..4f5a1358d 100644 --- a/macos/Sources/Ghostty/AppState.swift +++ b/macos/Sources/Ghostty/AppState.swift @@ -38,7 +38,7 @@ extension Ghostty { init() { // Initialize ghostty global state. This happens once per process. guard ghostty_init() == GHOSTTY_SUCCESS else { - GhosttyAppController.logger.critical("ghostty_init failed") + AppDelegate.logger.critical("ghostty_init failed") readiness = .error return } @@ -68,7 +68,7 @@ extension Ghostty { // Create the ghostty app. guard let app = ghostty_app_new(&runtime_cfg, cfg) else { - GhosttyAppController.logger.critical("ghostty_app_new failed") + AppDelegate.logger.critical("ghostty_app_new failed") readiness = .error return } @@ -87,7 +87,7 @@ extension Ghostty { static func reloadConfig() -> ghostty_config_t? { // Initialize the global configuration. guard let cfg = ghostty_config_new() else { - GhosttyAppController.logger.critical("ghostty_config_new failed") + AppDelegate.logger.critical("ghostty_config_new failed") return nil } @@ -189,7 +189,7 @@ extension Ghostty { static func reloadConfig(_ userdata: UnsafeMutableRawPointer?) -> ghostty_config_t? { guard let newConfig = AppState.reloadConfig() else { - GhosttyAppController.logger.warning("failed to reload configuration") + AppDelegate.logger.warning("failed to reload configuration") return nil } diff --git a/macos/Sources/MainMenu.xib b/macos/Sources/MainMenu.xib index 2a7d0c998..36c752c41 100644 --- a/macos/Sources/MainMenu.xib +++ b/macos/Sources/MainMenu.xib @@ -5,15 +5,20 @@ - + + + + + + - + - + @@ -56,34 +61,34 @@ - + - + - + - + - + - + @@ -114,12 +119,12 @@ - + - + @@ -129,25 +134,25 @@ - + - + - + - + @@ -171,10 +176,5 @@ - - - - - diff --git a/macos/Sources/Preview Content/.gitkeep b/macos/Sources/Preview Content/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/macos/Sources/WindowController.swift b/macos/Sources/WindowController.swift deleted file mode 100644 index 1c15158a7..000000000 --- a/macos/Sources/WindowController.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Cocoa - -class WindowController: NSWindowController { - static var lastCascadePoint = NSPoint(x: 0, y: 0) - - static func create(ghosttyApp: Ghostty.AppState, appDelegate: AppDelegate) -> WindowController { - let window = CustomWindow.create(ghostty: ghosttyApp, appDelegate: appDelegate) - lastCascadePoint = window.cascadeTopLeft(from: lastCascadePoint) - return WindowController(window: window) - } -} diff --git a/macos/Sources/main.swift b/macos/Sources/main.swift deleted file mode 100644 index 5d2c0ecaa..000000000 --- a/macos/Sources/main.swift +++ /dev/null @@ -1,7 +0,0 @@ -import AppKit - -let app = NSApplication.shared -let delegate = AppDelegate() -app.delegate = delegate - -_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)