From eec77e271c2a07c3556800e12f6a6189e1e963ca Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 9 Oct 2024 14:35:23 -0700 Subject: [PATCH] macos: change our minimum version to macOS 13 macOS 12 is officially EOL by Apple and the project only supports officially supported versions of macOS. Once publicly released, users on older macOS versions will have to use older released builds. --- README.md | 2 +- build.zig | 8 +-- macos/Ghostty.xcodeproj/project.pbxproj | 6 +- .../Features/Terminal/TerminalToolbar.swift | 7 +-- .../Ghostty/Ghostty.TerminalSplit.swift | 13 ---- macos/Sources/Ghostty/Package.swift | 4 -- macos/Sources/Ghostty/SurfaceView.swift | 59 +++---------------- .../Sources/Ghostty/SurfaceView_AppKit.swift | 8 +-- macos/Sources/Ghostty/SurfaceView_UIKit.swift | 8 +-- macos/Sources/Helpers/Backport.swift | 8 +-- .../Sources/Helpers/NSScreen+Extension.swift | 6 +- src/apprt/glfw.zig | 21 +------ 12 files changed, 24 insertions(+), 126 deletions(-) diff --git a/README.md b/README.md index bac9bd9d9..1e83824ab 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ beta users using Ghostty as their primary terminal. See more in | Platform / Package | Links | Notes | | ------------------ | -------------------------------------------------------------------------- | -------------------------- | -| macOS | [Tip ("Nightly")](https://github.com/ghostty-org/ghostty/releases/tag/tip) | MacOS 12+ Universal Binary | +| macOS | [Tip ("Nightly")](https://github.com/ghostty-org/ghostty/releases/tag/tip) | MacOS 13+ Universal Binary | | Linux | [Build from Source](#developing-ghostty) | | | Linux (NixOS/Nix) | [Use the Flake](#nix-package) | | | Linux (Arch) | [Use the AUR package](https://aur.archlinux.org/packages/ghostty-git) | | diff --git a/build.zig b/build.zig index e272932e5..0c9cc9441 100644 --- a/build.zig +++ b/build.zig @@ -759,12 +759,10 @@ pub fn build(b: *std.Build) !void { /// be used generally, it should only be used for Darwin-based OS currently. fn osVersionMin(tag: std.Target.Os.Tag) ?std.Target.Query.OsVersion { return switch (tag) { - // The lowest supported version of macOS is 12.x because - // this is the first version to support Apple Silicon so it is - // the earliest version we can virtualize to test (I only have - // an Apple Silicon machine for macOS). + // We support back to the earliest officially supported version + // of macOS by Apple. EOL versions are not supported. .macos => .{ .semver = .{ - .major = 12, + .major = 13, .minor = 0, .patch = 0, } }, diff --git a/macos/Ghostty.xcodeproj/project.pbxproj b/macos/Ghostty.xcodeproj/project.pbxproj index 502eb3e6a..b60eb11f5 100644 --- a/macos/Ghostty.xcodeproj/project.pbxproj +++ b/macos/Ghostty.xcodeproj/project.pbxproj @@ -731,7 +731,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 13.0; MARKETING_VERSION = 0.1; "OTHER_LDFLAGS[arch=*]" = "-lstdc++"; PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; @@ -898,7 +898,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 13.0; MARKETING_VERSION = 0.1; "OTHER_LDFLAGS[arch=*]" = "-lstdc++"; PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty.debug; @@ -951,7 +951,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 13.0; MARKETING_VERSION = 0.1; "OTHER_LDFLAGS[arch=*]" = "-lstdc++"; PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; diff --git a/macos/Sources/Features/Terminal/TerminalToolbar.swift b/macos/Sources/Features/Terminal/TerminalToolbar.swift index a9f3b530e..ba6906a77 100644 --- a/macos/Sources/Features/Terminal/TerminalToolbar.swift +++ b/macos/Sources/Features/Terminal/TerminalToolbar.swift @@ -29,12 +29,7 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate { super.init(identifier: identifier) delegate = self - - if #available(macOS 13.0, *) { - centeredItemIdentifiers.insert(.titleText) - } else { - centeredItemIdentifier = .titleText - } + centeredItemIdentifiers.insert(.titleText) } func toolbar(_ toolbar: NSToolbar, diff --git a/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift b/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift index 6d288b434..d4f82620c 100644 --- a/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift +++ b/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift @@ -447,19 +447,6 @@ extension Ghostty { } window.makeFirstResponder(to) - - // On newer versions of macOS everything above works great so we're done. - if #available(macOS 13, *) { return } - - // On macOS 12, splits do not properly gain focus. I don't know why, but - // it seems like the `focused` SwiftUI method doesn't work. We use - // NotificationCenter as a blunt force instrument to make it work. - if #available(macOS 12, *) { - NotificationCenter.default.post( - name: Notification.didBecomeFocusedSurface, - object: to - ) - } } } } diff --git a/macos/Sources/Ghostty/Package.swift b/macos/Sources/Ghostty/Package.swift index 63a41596a..f6fab532e 100644 --- a/macos/Sources/Ghostty/Package.swift +++ b/macos/Sources/Ghostty/Package.swift @@ -230,10 +230,6 @@ extension Ghostty.Notification { static let ghosttyToggleFullscreen = Notification.Name("com.mitchellh.ghostty.toggleFullscreen") static let FullscreenModeKey = ghosttyToggleFullscreen.rawValue - /// Notification that a surface is becoming focused. This is only sent on macOS 12 to - /// work around bugs. macOS 13+ should use the ".focused()" attribute. - static let didBecomeFocusedSurface = Notification.Name("com.mitchellh.ghostty.didBecomeFocusedSurface") - /// Notification sent to toggle split maximize/unmaximize. static let didToggleSplitZoom = Notification.Name("com.mitchellh.ghostty.didToggleSplitZoom") diff --git a/macos/Sources/Ghostty/SurfaceView.swift b/macos/Sources/Ghostty/SurfaceView.swift index b7643aada..738c6331f 100644 --- a/macos/Sources/Ghostty/SurfaceView.swift +++ b/macos/Sources/Ghostty/SurfaceView.swift @@ -84,10 +84,6 @@ extension Ghostty { // is up to date. See TerminalSurfaceView for why we don't use the NSView // resize callback. GeometryReader { geo in - // We use these notifications to determine when the window our surface is - // attached to is or is not focused. - let pubBecomeFocused = center.publisher(for: Notification.didBecomeFocusedSurface, object: surfaceView) - #if canImport(AppKit) let pubBecomeKey = center.publisher(for: NSWindow.didBecomeKeyNotification) let pubResign = center.publisher(for: NSWindow.didResignKeyNotification) @@ -130,45 +126,6 @@ extension Ghostty { return true } #endif - .onReceive(pubBecomeFocused) { notification in - // We only want to run this on older macOS versions where the .focused - // method doesn't work properly. See the dispatch of this notification - // for more information. - if #available(macOS 13, *) { return } - - DispatchQueue.main.async { - surfaceFocus = true - } - } - .onAppear() { - // Welcome to the SwiftUI bug house of horrors. On macOS 12 (at least - // 12.5.1, didn't test other versions), the order in which the view - // is added to the window hierarchy is such that $surfaceFocus is - // not set to true for the first surface in a window. As a result, - // new windows are key (they have window focus) but the terminal surface - // does not have surface until the user clicks. Bad! - // - // There is a very real chance that I am doing something wrong, but it - // works great as-is on macOS 13, so I've instead decided to make the - // older macOS hacky. A workaround is on initial appearance to "steal - // focus" under certain conditions that seem to imply we're in the - // screwy state. - if #available(macOS 13, *) { - // If we're on a more modern version of macOS, do nothing. - return - } - if #available(macOS 12, *) { - // On macOS 13, the view is attached to a window at this point, - // so this is one extra check that we're a new view and behaving odd. - guard surfaceView.window == nil else { return } - DispatchQueue.main.async { - surfaceFocus = true - } - } - - // I don't know how older macOS versions behave but Ghostty only - // supports back to macOS 12 so its moot. - } // If our geo size changed then we show the resize overlay as configured. if let surfaceSize = surfaceView.surfaceSize { @@ -338,7 +295,7 @@ extension Ghostty { let overlay: Ghostty.Config.ResizeOverlay let position: Ghostty.Config.ResizeOverlayPosition let duration: UInt - let focusInstant: Any? + let focusInstant: ContinuousClock.Instant? // This is the last size that we processed. This is how we handle our // timer state. @@ -361,14 +318,12 @@ extension Ghostty { // If we were focused recently we hide it as well. This avoids showing // the resize overlay when SwiftUI is lazily resizing. - if #available(macOS 13, iOS 16, *) { - if let instant = focusInstant as? ContinuousClock.Instant { - let d = instant.duration(to: ContinuousClock.now) - if (d < .milliseconds(500)) { - // Avoid this size completely. - lastSize = geoSize - return true; - } + if let instant = focusInstant { + let d = instant.duration(to: ContinuousClock.now) + if (d < .milliseconds(500)) { + // Avoid this size completely. + lastSize = geoSize + return true; } } diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift index 3b96ac012..c59c47e16 100644 --- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift +++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift @@ -35,7 +35,7 @@ extension Ghostty { // The time this surface last became focused. This is a ContinuousClock.Instant // on supported platforms. - @Published var focusInstant: Any? = nil + @Published var focusInstant: ContinuousClock.Instant? = nil // Returns sizing information for the surface. This is the raw C // structure because I'm lazy. @@ -232,10 +232,8 @@ extension Ghostty { } // On macOS 13+ we can store our continuous clock... - if #available(macOS 13, iOS 16, *) { - if (focused) { - focusInstant = ContinuousClock.now - } + if (focused) { + focusInstant = ContinuousClock.now } } diff --git a/macos/Sources/Ghostty/SurfaceView_UIKit.swift b/macos/Sources/Ghostty/SurfaceView_UIKit.swift index b8c58caaa..1c2357960 100644 --- a/macos/Sources/Ghostty/SurfaceView_UIKit.swift +++ b/macos/Sources/Ghostty/SurfaceView_UIKit.swift @@ -30,7 +30,7 @@ extension Ghostty { // The time this surface last became focused. This is a ContinuousClock.Instant // on supported platforms. - @Published var focusInstant: Any? = nil + @Published var focusInstant: ContinuousClock.Instant? = nil // Returns sizing information for the surface. This is the raw C // structure because I'm lazy. @@ -73,10 +73,8 @@ extension Ghostty { ghostty_surface_set_focus(surface, focused) // On macOS 13+ we can store our continuous clock... - if #available(macOS 13, iOS 16, *) { - if (focused) { - focusInstant = ContinuousClock.now - } + if (focused) { + focusInstant = ContinuousClock.now } } diff --git a/macos/Sources/Helpers/Backport.swift b/macos/Sources/Helpers/Backport.swift index 8c3c10502..a28be15ae 100644 --- a/macos/Sources/Helpers/Backport.swift +++ b/macos/Sources/Helpers/Backport.swift @@ -15,13 +15,7 @@ extension Scene { } extension Backport where Content: Scene { - func defaultSize(width: CGFloat, height: CGFloat) -> some Scene { - if #available(macOS 13, *) { - return content.defaultSize(width: width, height: height) - } else { - return content - } - } + // None currently } extension Backport where Content: View { diff --git a/macos/Sources/Helpers/NSScreen+Extension.swift b/macos/Sources/Helpers/NSScreen+Extension.swift index 1091436dd..ef2c02908 100644 --- a/macos/Sources/Helpers/NSScreen+Extension.swift +++ b/macos/Sources/Helpers/NSScreen+Extension.swift @@ -29,11 +29,7 @@ extension NSScreen { // We need to see if our visible frame height is less than the full // screen height minus the menu and notch and such. let menuHeight = NSApp.mainMenu?.menuBarHeight ?? 0 - let notchInset: CGFloat = if #available(macOS 12, *) { - safeAreaInsets.top - } else { - 0 - } + let notchInset: CGFloat = safeAreaInsets.top let boundaryAreaPadding = 5.0 return visibleFrame.height < (frame.height - max(menuHeight, notchInset) - boundaryAreaPadding) diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 980c2dba3..cbb9b7e48 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -559,25 +559,15 @@ pub const Surface = struct { // Clean up our core surface so that all the rendering and IO stop. self.core_surface.deinit(); - var tabgroup_opt: if (App.Darwin.enabled) ?objc.Object else void = undefined; if (App.Darwin.enabled) { const nswindow = objc.Object.fromId(glfwNative.getCocoaWindow(self.window).?); const tabgroup = nswindow.getProperty(objc.Object, "tabGroup"); - - // On macOS versions prior to Ventura, we lose window focus on tab close - // for some reason. We manually fix this by keeping track of the tab - // group and just selecting the next window. - if (internal_os.macosVersionAtLeast(13, 0, 0)) - tabgroup_opt = null - else - tabgroup_opt = tabgroup; - const windows = tabgroup.getProperty(objc.Object, "windows"); switch (windows.getProperty(usize, "count")) { // If we're going down to one window our tab bar is going to be // destroyed so unset it so that the later logic doesn't try to // use it. - 1 => tabgroup_opt = null, + 1 => {}, // If our tab bar is visible and we are going down to 1 window, // hide the tab bar. The check is "2" because our current window @@ -597,15 +587,6 @@ pub const Surface = struct { c.destroy(); self.cursor = null; } - - // If we have a tabgroup set, we want to manually focus the next window. - // We should NOT have to do this usually, see the comments above. - if (App.Darwin.enabled) { - if (tabgroup_opt) |tabgroup| { - const selected = tabgroup.getProperty(objc.Object, "selectedWindow"); - selected.msgSend(void, objc.sel("makeKeyWindow"), .{}); - } - } } /// Checks if the glfw window is in fullscreen.