mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-09-04 05:10:27 +00:00
Fixes #13293 Treat Core Video display link creation as optional when macOS has no active displays. The previous error path reported every creation failure as out of memory and aborted renderer initialization. This also resyncs the display link on any display change so when a display becomes available it re-adds itself. Tabs created while the session is locked now initialize normally and fall back to event-driven rendering without vsync.
85 lines
2.6 KiB
Zig
85 lines
2.6 KiB
Zig
const c = @import("c.zig").c;
|
|
|
|
pub const DisplayLink = opaque {
|
|
pub const Error = error{
|
|
CreationFailed,
|
|
InvalidOperation,
|
|
};
|
|
|
|
pub fn createWithActiveCGDisplays() Error!*DisplayLink {
|
|
var result: ?*DisplayLink = null;
|
|
if (c.CVDisplayLinkCreateWithActiveCGDisplays(
|
|
@ptrCast(&result),
|
|
) != c.kCVReturnSuccess)
|
|
return error.CreationFailed;
|
|
|
|
return result orelse error.CreationFailed;
|
|
}
|
|
|
|
pub fn release(self: *DisplayLink) void {
|
|
c.CVDisplayLinkRelease(@ptrCast(self));
|
|
}
|
|
|
|
pub fn start(self: *DisplayLink) Error!void {
|
|
if (c.CVDisplayLinkStart(@ptrCast(self)) != c.kCVReturnSuccess)
|
|
return error.InvalidOperation;
|
|
}
|
|
|
|
pub fn stop(self: *DisplayLink) Error!void {
|
|
if (c.CVDisplayLinkStop(@ptrCast(self)) != c.kCVReturnSuccess)
|
|
return error.InvalidOperation;
|
|
}
|
|
|
|
pub fn isRunning(self: *DisplayLink) bool {
|
|
return c.CVDisplayLinkIsRunning(@ptrCast(self)) != 0;
|
|
}
|
|
|
|
pub fn setCurrentCGDisplay(
|
|
self: *DisplayLink,
|
|
display_id: c.CGDirectDisplayID,
|
|
) Error!void {
|
|
if (c.CVDisplayLinkSetCurrentCGDisplay(
|
|
@ptrCast(self),
|
|
display_id,
|
|
) != c.kCVReturnSuccess)
|
|
return error.InvalidOperation;
|
|
}
|
|
|
|
// Note: this purposely throws away a ton of arguments I didn't need.
|
|
// It would be trivial to refactor this into Zig types and properly
|
|
// pass this through.
|
|
pub fn setOutputCallback(
|
|
self: *DisplayLink,
|
|
comptime Userdata: type,
|
|
comptime callbackFn: *const fn (*DisplayLink, ?*Userdata) void,
|
|
userinfo: ?*Userdata,
|
|
) Error!void {
|
|
if (c.CVDisplayLinkSetOutputCallback(
|
|
@ptrCast(self),
|
|
@ptrCast(&(struct {
|
|
fn callback(
|
|
displayLink: *DisplayLink,
|
|
inNow: *const c.CVTimeStamp,
|
|
inOutputTime: *const c.CVTimeStamp,
|
|
flagsIn: c.CVOptionFlags,
|
|
flagsOut: *c.CVOptionFlags,
|
|
inner_userinfo: ?*anyopaque,
|
|
) callconv(.c) c.CVReturn {
|
|
_ = inNow;
|
|
_ = inOutputTime;
|
|
_ = flagsIn;
|
|
_ = flagsOut;
|
|
|
|
callbackFn(
|
|
displayLink,
|
|
@ptrCast(@alignCast(inner_userinfo)),
|
|
);
|
|
return c.kCVReturnSuccess;
|
|
}
|
|
}).callback),
|
|
userinfo,
|
|
) != c.kCVReturnSuccess)
|
|
return error.InvalidOperation;
|
|
}
|
|
};
|