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.
This commit is contained in:
Mitchell Hashimoto
2024-10-09 14:35:23 -07:00
parent 2f009b7262
commit eec77e271c
12 changed files with 24 additions and 126 deletions

View File

@ -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) | |

View File

@ -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,
} },

View File

@ -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;

View File

@ -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
}
}
func toolbar(_ toolbar: NSToolbar,

View File

@ -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
)
}
}
}
}

View File

@ -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")

View File

@ -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,8 +318,7 @@ 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 {
if let instant = focusInstant {
let d = instant.duration(to: ContinuousClock.now)
if (d < .milliseconds(500)) {
// Avoid this size completely.
@ -370,7 +326,6 @@ extension Ghostty {
return true;
}
}
}
// Hidden depending on overlay config
switch (overlay) {

View File

@ -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,12 +232,10 @@ extension Ghostty {
}
// On macOS 13+ we can store our continuous clock...
if #available(macOS 13, iOS 16, *) {
if (focused) {
focusInstant = ContinuousClock.now
}
}
}
func sizeDidChange(_ size: CGSize) {
// Ghostty wants to know the actual framebuffer size... It is very important

View File

@ -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,12 +73,10 @@ 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
}
}
}
func sizeDidChange(_ size: CGSize) {
guard let surface = self.surface else { return }

View File

@ -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 {

View File

@ -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)

View File

@ -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.