Merge pull request #2429 from ghostty-org/push-svonxsqwnumx

macos: change our minimum version to macOS 13
This commit is contained in:
Mitchell Hashimoto
2024-10-09 15:19:12 -07:00
committed by GitHub
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 | | 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 | [Build from Source](#developing-ghostty) | |
| Linux (NixOS/Nix) | [Use the Flake](#nix-package) | | | Linux (NixOS/Nix) | [Use the Flake](#nix-package) | |
| Linux (Arch) | [Use the AUR package](https://aur.archlinux.org/packages/ghostty-git) | | | 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. /// be used generally, it should only be used for Darwin-based OS currently.
fn osVersionMin(tag: std.Target.Os.Tag) ?std.Target.Query.OsVersion { fn osVersionMin(tag: std.Target.Os.Tag) ?std.Target.Query.OsVersion {
return switch (tag) { return switch (tag) {
// The lowest supported version of macOS is 12.x because // We support back to the earliest officially supported version
// this is the first version to support Apple Silicon so it is // of macOS by Apple. EOL versions are not supported.
// the earliest version we can virtualize to test (I only have
// an Apple Silicon machine for macOS).
.macos => .{ .semver = .{ .macos => .{ .semver = .{
.major = 12, .major = 13,
.minor = 0, .minor = 0,
.patch = 0, .patch = 0,
} }, } },

View File

@ -731,7 +731,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 0.1; MARKETING_VERSION = 0.1;
"OTHER_LDFLAGS[arch=*]" = "-lstdc++"; "OTHER_LDFLAGS[arch=*]" = "-lstdc++";
PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty;
@ -898,7 +898,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 0.1; MARKETING_VERSION = 0.1;
"OTHER_LDFLAGS[arch=*]" = "-lstdc++"; "OTHER_LDFLAGS[arch=*]" = "-lstdc++";
PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty.debug; PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty.debug;
@ -951,7 +951,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 0.1; MARKETING_VERSION = 0.1;
"OTHER_LDFLAGS[arch=*]" = "-lstdc++"; "OTHER_LDFLAGS[arch=*]" = "-lstdc++";
PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty;

View File

@ -29,12 +29,7 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate {
super.init(identifier: identifier) super.init(identifier: identifier)
delegate = self delegate = self
centeredItemIdentifiers.insert(.titleText)
if #available(macOS 13.0, *) {
centeredItemIdentifiers.insert(.titleText)
} else {
centeredItemIdentifier = .titleText
}
} }
func toolbar(_ toolbar: NSToolbar, func toolbar(_ toolbar: NSToolbar,

View File

@ -447,19 +447,6 @@ extension Ghostty {
} }
window.makeFirstResponder(to) 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 ghosttyToggleFullscreen = Notification.Name("com.mitchellh.ghostty.toggleFullscreen")
static let FullscreenModeKey = ghosttyToggleFullscreen.rawValue 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. /// Notification sent to toggle split maximize/unmaximize.
static let didToggleSplitZoom = Notification.Name("com.mitchellh.ghostty.didToggleSplitZoom") 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 // is up to date. See TerminalSurfaceView for why we don't use the NSView
// resize callback. // resize callback.
GeometryReader { geo in 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) #if canImport(AppKit)
let pubBecomeKey = center.publisher(for: NSWindow.didBecomeKeyNotification) let pubBecomeKey = center.publisher(for: NSWindow.didBecomeKeyNotification)
let pubResign = center.publisher(for: NSWindow.didResignKeyNotification) let pubResign = center.publisher(for: NSWindow.didResignKeyNotification)
@ -130,45 +126,6 @@ extension Ghostty {
return true return true
} }
#endif #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 our geo size changed then we show the resize overlay as configured.
if let surfaceSize = surfaceView.surfaceSize { if let surfaceSize = surfaceView.surfaceSize {
@ -338,7 +295,7 @@ extension Ghostty {
let overlay: Ghostty.Config.ResizeOverlay let overlay: Ghostty.Config.ResizeOverlay
let position: Ghostty.Config.ResizeOverlayPosition let position: Ghostty.Config.ResizeOverlayPosition
let duration: UInt let duration: UInt
let focusInstant: Any? let focusInstant: ContinuousClock.Instant?
// This is the last size that we processed. This is how we handle our // This is the last size that we processed. This is how we handle our
// timer state. // timer state.
@ -361,14 +318,12 @@ extension Ghostty {
// If we were focused recently we hide it as well. This avoids showing // If we were focused recently we hide it as well. This avoids showing
// the resize overlay when SwiftUI is lazily resizing. // the resize overlay when SwiftUI is lazily resizing.
if #available(macOS 13, iOS 16, *) { if let instant = focusInstant {
if let instant = focusInstant as? ContinuousClock.Instant { let d = instant.duration(to: ContinuousClock.now)
let d = instant.duration(to: ContinuousClock.now) if (d < .milliseconds(500)) {
if (d < .milliseconds(500)) { // Avoid this size completely.
// Avoid this size completely. lastSize = geoSize
lastSize = geoSize return true;
return true;
}
} }
} }

View File

@ -35,7 +35,7 @@ extension Ghostty {
// The time this surface last became focused. This is a ContinuousClock.Instant // The time this surface last became focused. This is a ContinuousClock.Instant
// on supported platforms. // 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 // Returns sizing information for the surface. This is the raw C
// structure because I'm lazy. // structure because I'm lazy.
@ -232,10 +232,8 @@ extension Ghostty {
} }
// On macOS 13+ we can store our continuous clock... // On macOS 13+ we can store our continuous clock...
if #available(macOS 13, iOS 16, *) { if (focused) {
if (focused) { focusInstant = ContinuousClock.now
focusInstant = ContinuousClock.now
}
} }
} }

View File

@ -30,7 +30,7 @@ extension Ghostty {
// The time this surface last became focused. This is a ContinuousClock.Instant // The time this surface last became focused. This is a ContinuousClock.Instant
// on supported platforms. // 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 // Returns sizing information for the surface. This is the raw C
// structure because I'm lazy. // structure because I'm lazy.
@ -73,10 +73,8 @@ extension Ghostty {
ghostty_surface_set_focus(surface, focused) ghostty_surface_set_focus(surface, focused)
// On macOS 13+ we can store our continuous clock... // On macOS 13+ we can store our continuous clock...
if #available(macOS 13, iOS 16, *) { if (focused) {
if (focused) { focusInstant = ContinuousClock.now
focusInstant = ContinuousClock.now
}
} }
} }

View File

@ -15,13 +15,7 @@ extension Scene {
} }
extension Backport where Content: Scene { extension Backport where Content: Scene {
func defaultSize(width: CGFloat, height: CGFloat) -> some Scene { // None currently
if #available(macOS 13, *) {
return content.defaultSize(width: width, height: height)
} else {
return content
}
}
} }
extension Backport where Content: View { 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 // We need to see if our visible frame height is less than the full
// screen height minus the menu and notch and such. // screen height minus the menu and notch and such.
let menuHeight = NSApp.mainMenu?.menuBarHeight ?? 0 let menuHeight = NSApp.mainMenu?.menuBarHeight ?? 0
let notchInset: CGFloat = if #available(macOS 12, *) { let notchInset: CGFloat = safeAreaInsets.top
safeAreaInsets.top
} else {
0
}
let boundaryAreaPadding = 5.0 let boundaryAreaPadding = 5.0
return visibleFrame.height < (frame.height - max(menuHeight, notchInset) - boundaryAreaPadding) 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. // Clean up our core surface so that all the rendering and IO stop.
self.core_surface.deinit(); self.core_surface.deinit();
var tabgroup_opt: if (App.Darwin.enabled) ?objc.Object else void = undefined;
if (App.Darwin.enabled) { if (App.Darwin.enabled) {
const nswindow = objc.Object.fromId(glfwNative.getCocoaWindow(self.window).?); const nswindow = objc.Object.fromId(glfwNative.getCocoaWindow(self.window).?);
const tabgroup = nswindow.getProperty(objc.Object, "tabGroup"); 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"); const windows = tabgroup.getProperty(objc.Object, "windows");
switch (windows.getProperty(usize, "count")) { switch (windows.getProperty(usize, "count")) {
// If we're going down to one window our tab bar is going to be // 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 // destroyed so unset it so that the later logic doesn't try to
// use it. // use it.
1 => tabgroup_opt = null, 1 => {},
// If our tab bar is visible and we are going down to 1 window, // 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 // hide the tab bar. The check is "2" because our current window
@ -597,15 +587,6 @@ pub const Surface = struct {
c.destroy(); c.destroy();
self.cursor = null; 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. /// Checks if the glfw window is in fullscreen.