Something went wrong. Try again.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178const std = @import("std");const builtin = @import("builtin");const build_config = @import("../build_config.zig");const assert = @import("../quirks.zig").inlineAssert;const objc = @import("objc");const Allocator = std.mem.Allocator;
/// Verifies that the running macOS system version is at least the given version.pub fn isAtLeastVersion(major: i64, minor: i64, patch: i64) bool { comptime assert(builtin.target.os.tag.isDarwin());
const NSProcessInfo = objc.getClass("NSProcessInfo").?; const info = NSProcessInfo.msgSend(objc.Object, objc.sel("processInfo"), .{}); return info.msgSend(bool, objc.sel("isOperatingSystemAtLeastVersion:"), .{ NSOperatingSystemVersion{ .major = major, .minor = minor, .patch = patch }, });}
pub const AppSupportDirError = Allocator.Error || error{AppleAPIFailed};
/// Return the path to the application support directory for Ghostty/// with the given sub path joined. This allocates the result using the/// given allocator.pub fn appSupportDir( alloc: Allocator, sub_path: []const u8,) AppSupportDirError![]const u8 { return try commonDir( alloc, .NSApplicationSupportDirectory, &.{ build_config.bundle_id, sub_path }, );}
pub const CacheDirError = Allocator.Error || error{AppleAPIFailed};
/// Return the path to the system cache directory with the given sub path joined./// This allocates the result using the given allocator.pub fn cacheDir( alloc: Allocator, sub_path: []const u8,) CacheDirError![]const u8 { return try commonDir( alloc, .NSCachesDirectory, &.{ build_config.bundle_id, sub_path }, );}
pub const SetQosClassError = error{ // The thread can't have its QoS class changed usually because // a different pthread API was called that makes it an invalid // target. ThreadIncompatible,};
/// Set the QoS class of the running thread.////// https://developer.apple.com/documentation/apple-silicon/tuning-your-code-s-performance-for-apple-silicon?preferredLanguage=occpub fn setQosClass(class: QosClass) !void { return switch (std.posix.errno(pthread_set_qos_class_self_np( class, 0, ))) { .SUCCESS => {}, .PERM => error.ThreadIncompatible,
// EPERM is the only known error that can happen based on // the man pages for pthread_set_qos_class_self_np. I haven't // checked the XNU source code to see if there are other // possible errors. else => @panic("unexpected pthread_set_qos_class_self_np error"), };}
/// https://developer.apple.com/library/archive/documentation/Performance/Conceptual/power_efficiency_guidelines_osx/PrioritizeWorkAtTheTaskLevel.html#//apple_ref/doc/uid/TP40013929-CH35-SW1pub const QosClass = enum(c_uint) { user_interactive = 0x21, user_initiated = 0x19, default = 0x15, utility = 0x11, background = 0x09, unspecified = 0x00,};
extern "c" fn pthread_set_qos_class_self_np( qos_class: QosClass, relative_priority: c_int,) c_int;
pub extern "c" fn pthread_setname_np( name: [*:0]const u8,) void;
pub const NSOperatingSystemVersion = extern struct { major: i64, minor: i64, patch: i64,};
pub const NSSearchPathDirectory = enum(c_ulong) { NSCachesDirectory = 13, NSApplicationSupportDirectory = 14,};
pub const NSSearchPathDomainMask = enum(c_ulong) { NSUserDomainMask = 1,};
fn commonDir( alloc: Allocator, directory: NSSearchPathDirectory, sub_paths: []const []const u8,) (error{AppleAPIFailed} || Allocator.Error)![]const u8 { comptime assert(builtin.target.os.tag.isDarwin());
const NSFileManager = objc.getClass("NSFileManager").?; const manager = NSFileManager.msgSend( objc.Object, objc.sel("defaultManager"), .{}, );
const url = manager.msgSend( objc.Object, objc.sel("URLForDirectory:inDomain:appropriateForURL:create:error:"), .{ directory, NSSearchPathDomainMask.NSUserDomainMask, @as(?*anyopaque, null), true, @as(?*anyopaque, null), }, );
if (url.value == null) return error.AppleAPIFailed;
const path = url.getProperty(objc.Object, "path"); const c_str = path.getProperty(?[*:0]const u8, "UTF8String") orelse return error.AppleAPIFailed; const base_dir = std.mem.sliceTo(c_str, 0);
// Create a new array with base_dir as the first element var paths = try alloc.alloc([]const u8, sub_paths.len + 1); paths[0] = base_dir; @memcpy(paths[1..], sub_paths); defer alloc.free(paths);
return try std.fs.path.join(alloc, paths);}
test "cacheDir paths" { if (!builtin.target.os.tag.isDarwin()) return;
const testing = std.testing; const alloc = testing.allocator;
// Test base path { const cache_path = try cacheDir(alloc, ""); defer alloc.free(cache_path); try testing.expect(std.mem.indexOf(u8, cache_path, "Caches") != null); try testing.expect(std.mem.indexOf(u8, cache_path, build_config.bundle_id) != null); }
// Test with subdir { const cache_path = try cacheDir(alloc, "test"); defer alloc.free(cache_path); try testing.expect(std.mem.indexOf(u8, cache_path, "Caches") != null); try testing.expect(std.mem.indexOf(u8, cache_path, build_config.bundle_id) != null);
const bundle_path = try std.fmt.allocPrint(alloc, "{s}/test", .{build_config.bundle_id}); defer alloc.free(bundle_path); try testing.expect(std.mem.indexOf(u8, cache_path, bundle_path) != null); }}