mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
Merge pull request #2429 from ghostty-org/push-svonxsqwnumx
macos: change our minimum version to macOS 13
This commit is contained in:
@ -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) | |
|
||||
|
@ -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,
|
||||
} },
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user