mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
pkg/objc: properties
This commit is contained in:
@ -14,6 +14,21 @@ pub const Class = struct {
|
|||||||
.value = c.objc_getClass(name.ptr) orelse return null,
|
.value = c.objc_getClass(name.ptr) orelse return null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a property with a given name of a given class.
|
||||||
|
pub fn getProperty(self: Class, name: [:0]const u8) ?objc.Property {
|
||||||
|
return objc.Property{
|
||||||
|
.value = c.class_getProperty(self.value, name.ptr) orelse return null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Describes the properties declared by a class. This must be freed.
|
||||||
|
pub fn copyPropertyList(self: Class) []objc.Property {
|
||||||
|
var count: c_uint = undefined;
|
||||||
|
const list = @ptrCast([*c]objc.Property, c.class_copyPropertyList(self.value, &count));
|
||||||
|
if (count == 0) return list[0..0];
|
||||||
|
return list[0..count];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
test "getClass" {
|
test "getClass" {
|
||||||
@ -40,3 +55,20 @@ test "msgSend" {
|
|||||||
try testing.expect(obj.value != null);
|
try testing.expect(obj.value != null);
|
||||||
obj.msgSend(void, objc.sel("dealloc"), .{});
|
obj.msgSend(void, objc.sel("dealloc"), .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "getProperty" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const NSObject = Class.getClass("NSObject").?;
|
||||||
|
|
||||||
|
try testing.expect(NSObject.getProperty("className") != null);
|
||||||
|
try testing.expect(NSObject.getProperty("nope") == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "copyProperyList" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const NSObject = Class.getClass("NSObject").?;
|
||||||
|
|
||||||
|
const list = NSObject.copyPropertyList();
|
||||||
|
defer objc.free(list);
|
||||||
|
try testing.expect(list.len > 20);
|
||||||
|
}
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
pub const c = @import("c.zig");
|
pub const c = @import("c.zig");
|
||||||
pub usingnamespace @import("class.zig");
|
pub usingnamespace @import("class.zig");
|
||||||
pub usingnamespace @import("object.zig");
|
pub usingnamespace @import("object.zig");
|
||||||
|
pub usingnamespace @import("property.zig");
|
||||||
pub usingnamespace @import("sel.zig");
|
pub usingnamespace @import("sel.zig");
|
||||||
|
|
||||||
test {
|
/// This just calls the C allocator free. Some things need to be freed
|
||||||
@import("std").testing.refAllDecls(@This());
|
/// and this is how they can be freed for objc.
|
||||||
|
pub inline fn free(ptr: anytype) void {
|
||||||
// TODO: remove once we integrate this
|
std.heap.c_allocator.free(ptr);
|
||||||
_ = @import("msg_send.zig");
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,10 @@ pub fn MsgSend(comptime T: type) type {
|
|||||||
// This lets msgSend magically work with Object and so on.
|
// This lets msgSend magically work with Object and so on.
|
||||||
const is_pkg_struct = comptime is_pkg_struct: {
|
const is_pkg_struct = comptime is_pkg_struct: {
|
||||||
for (@typeInfo(objc).Struct.decls) |decl| {
|
for (@typeInfo(objc).Struct.decls) |decl| {
|
||||||
if (decl.is_pub and Return == @field(objc, decl.name)) {
|
if (decl.is_pub and
|
||||||
|
@TypeOf(@field(objc, decl.name)) == type and
|
||||||
|
Return == @field(objc, decl.name))
|
||||||
|
{
|
||||||
break :is_pkg_struct true;
|
break :is_pkg_struct true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,3 +8,13 @@ pub const Object = struct {
|
|||||||
|
|
||||||
pub usingnamespace MsgSend(Object);
|
pub usingnamespace MsgSend(Object);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
test {
|
||||||
|
const testing = std.testing;
|
||||||
|
const NSObject = objc.Class.getClass("NSObject").?;
|
||||||
|
|
||||||
|
// Should work with our wrappers
|
||||||
|
const obj = NSObject.msgSend(objc.Object, objc.Sel.registerName("alloc"), .{});
|
||||||
|
try testing.expect(obj.value != null);
|
||||||
|
obj.msgSend(void, objc.sel("dealloc"), .{});
|
||||||
|
}
|
||||||
|
27
pkg/objc/property.zig
Normal file
27
pkg/objc/property.zig
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const objc = @import("main.zig");
|
||||||
|
|
||||||
|
pub const Property = extern struct {
|
||||||
|
value: c.objc_property_t,
|
||||||
|
|
||||||
|
/// Returns the name of a property.
|
||||||
|
pub fn getName(self: Property) [:0]const u8 {
|
||||||
|
return std.mem.sliceTo(c.property_getName(self.value), 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test {
|
||||||
|
// Critical properties because we ptrCast C pointers to this.
|
||||||
|
const testing = std.testing;
|
||||||
|
try testing.expect(@sizeOf(Property) == @sizeOf(c.objc_property_t));
|
||||||
|
try testing.expect(@alignOf(Property) == @alignOf(c.objc_property_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
const testing = std.testing;
|
||||||
|
const NSObject = objc.Class.getClass("NSObject").?;
|
||||||
|
|
||||||
|
const prop = NSObject.getProperty("className").?;
|
||||||
|
try testing.expectEqualStrings("className", prop.getName());
|
||||||
|
}
|
Reference in New Issue
Block a user