mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-17 01:06:08 +03:00
renderer/metal: API to handle macOS display ID changing
This commit is contained in:
@ -542,6 +542,10 @@ uintptr_t ghostty_surface_pwd(ghostty_surface_t, char*, uintptr_t);
|
||||
bool ghostty_surface_has_selection(ghostty_surface_t);
|
||||
uintptr_t ghostty_surface_selection(ghostty_surface_t, char*, uintptr_t);
|
||||
|
||||
#ifdef __APPLE__
|
||||
void ghostty_surface_set_display_id(ghostty_surface_t, uint32_t);
|
||||
#endif
|
||||
|
||||
ghostty_inspector_t ghostty_surface_inspector(ghostty_surface_t);
|
||||
void ghostty_inspector_free(ghostty_surface_t);
|
||||
void ghostty_inspector_set_focus(ghostty_inspector_t, bool);
|
||||
|
@ -112,6 +112,11 @@ extension Ghostty {
|
||||
selector: #selector(onUpdateRendererHealth),
|
||||
name: Ghostty.Notification.didUpdateRendererHealth,
|
||||
object: self)
|
||||
center.addObserver(
|
||||
self,
|
||||
selector: #selector(windowDidChangeScreen),
|
||||
name: NSWindow.didChangeScreenNotification,
|
||||
object: nil)
|
||||
|
||||
// Setup our surface. This will also initialize all the terminal IO.
|
||||
let surface_cfg = baseConfig ?? SurfaceConfiguration()
|
||||
@ -322,6 +327,19 @@ extension Ghostty {
|
||||
healthy = health == GHOSTTY_RENDERER_HEALTH_OK
|
||||
}
|
||||
|
||||
@objc private func windowDidChangeScreen(notification: SwiftUI.Notification) {
|
||||
guard let window = self.window else { return }
|
||||
guard let object = notification.object as? NSWindow, window == object else { return }
|
||||
guard let screen = window.screen else { return }
|
||||
guard let surface = self.surface else { return }
|
||||
|
||||
// When the window changes screens, we need to update libghostty with the screen
|
||||
// ID. If vsync is enabled, this will be used with the CVDisplayLink to ensure
|
||||
// the proper refresh rate is going.
|
||||
let id = (screen.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as! NSNumber).uint32Value
|
||||
ghostty_surface_set_display_id(surface, id)
|
||||
}
|
||||
|
||||
// MARK: - NSView
|
||||
|
||||
override func viewDidMoveToWindow() {
|
||||
|
@ -1737,6 +1737,15 @@ pub const CAPI = struct {
|
||||
|
||||
// Inspector Metal APIs are only available on Apple systems
|
||||
usingnamespace if (builtin.target.isDarwin()) struct {
|
||||
export fn ghostty_surface_set_display_id(ptr: *Surface, display_id: u32) void {
|
||||
const surface = &ptr.core_surface;
|
||||
_ = surface.renderer_thread.mailbox.push(
|
||||
.{ .macos_display_id = display_id },
|
||||
.{ .forever = {} },
|
||||
);
|
||||
surface.renderer_thread.wakeup.notify() catch {};
|
||||
}
|
||||
|
||||
export fn ghostty_inspector_metal_init(ptr: *Inspector, device: objc.c.id) bool {
|
||||
return ptr.initMetal(objc.Object.fromId(device));
|
||||
}
|
||||
|
@ -561,10 +561,14 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
||||
var cells = try mtl_cell.Contents.init(alloc);
|
||||
errdefer cells.deinit(alloc);
|
||||
|
||||
const display_link: ?DisplayLink = switch (builtin.os.tag) {
|
||||
.macos => try macos.video.DisplayLink.createWithActiveCGDisplays(),
|
||||
else => null,
|
||||
};
|
||||
const display_link: ?DisplayLink = null;
|
||||
// Note(mitchellh): if/when we ever want to add vsync, we can use this
|
||||
// display link to trigger rendering. We don't need this if vsync is off
|
||||
// because any change will trigger a redraw immediately.
|
||||
// const display_link: ?DisplayLink = switch (builtin.os.tag) {
|
||||
// .macos => try macos.video.DisplayLink.createWithActiveCGDisplays(),
|
||||
// else => null,
|
||||
// };
|
||||
errdefer if (display_link) |v| v.release();
|
||||
|
||||
return Metal{
|
||||
@ -701,6 +705,16 @@ fn displayLinkCallback(
|
||||
};
|
||||
}
|
||||
|
||||
/// Called when we get an updated display ID for our display link.
|
||||
pub fn setMacOSDisplayID(self: *Metal, id: u32) !void {
|
||||
if (comptime DisplayLink == void) return;
|
||||
const display_link = self.display_link orelse return;
|
||||
log.info("updating display link display id={}", .{id});
|
||||
display_link.setCurrentCGDisplay(id) catch |err| {
|
||||
log.warn("error setting display link display id err={}", .{err});
|
||||
};
|
||||
}
|
||||
|
||||
/// True if our renderer has animations so that a higher frequency
|
||||
/// timer is used.
|
||||
pub fn hasAnimations(self: *const Metal) bool {
|
||||
|
@ -375,6 +375,12 @@ fn drainMailbox(self: *Thread) !void {
|
||||
},
|
||||
|
||||
.inspector => |v| self.flags.has_inspector = v,
|
||||
|
||||
.macos_display_id => |v| {
|
||||
if (@hasDecl(renderer.Renderer, "setMacOSDisplayID")) {
|
||||
try self.renderer.setMacOSDisplayID(v);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,9 @@ pub const Message = union(enum) {
|
||||
/// Activate or deactivate the inspector.
|
||||
inspector: bool,
|
||||
|
||||
/// The macOS display ID has changed for the window.
|
||||
macos_display_id: u32,
|
||||
|
||||
/// Initialize a change_config message.
|
||||
pub fn initChangeConfig(alloc: Allocator, config: *const configpkg.Config) !Message {
|
||||
const thread_ptr = try alloc.create(renderer.Thread.DerivedConfig);
|
||||
|
Reference in New Issue
Block a user