diff --git a/build.zig b/build.zig index 0a923b208..344a9d3a5 100644 --- a/build.zig +++ b/build.zig @@ -405,7 +405,7 @@ pub fn build(b: *std.Build) !void { } // App (Linux) - if (target.result.os.tag == .linux) { + if (target.result.os.tag == .linux and config.app_runtime != .none) { // https://developer.gnome.org/documentation/guidelines/maintainer/integrating.html // Desktop file so that we have an icon and other metadata @@ -428,6 +428,24 @@ pub fn build(b: *std.Build) !void { b.installFile("images/icons/icon_256x256@2x@2x.png", "share/icons/hicolor/256x256@2/apps/com.mitchellh.ghostty.png"); } + // libghostty (non-Darwin) + if (!builtin.target.isDarwin() and config.app_runtime == .none) { + const lib = b.addSharedLibrary(.{ + .name = "ghostty", + .root_source_file = .{ .path = "src/main_c.zig" }, + .optimize = optimize, + .target = target, + }); + lib.root_module.addOptions("build_options", exe_options); + _ = try addDeps(b, lib, config); + + const lib_install = b.addInstallLibFile( + lib.getEmittedBin(), + "libghostty.so", + ); + b.getInstallStep().dependOn(&lib_install.step); + } + // On Mac we can build the embedding library. This only handles the macOS lib. if (builtin.target.isDarwin() and target.result.os.tag == .macos) { // Create the universal macOS lib. diff --git a/include/ghostty.h b/include/ghostty.h index ff4056778..63668a4c3 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -30,6 +30,10 @@ typedef void *ghostty_surface_t; typedef void *ghostty_inspector_t; // Enums are up top so we can reference them later. +typedef enum { + GHOSTTY_PLATFORM_MACOS, +} ghostty_platform_e; + typedef enum { GHOSTTY_CLIPBOARD_STANDARD, GHOSTTY_CLIPBOARD_SELECTION, diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index ed27fe8b8..db3fe422e 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -231,9 +231,49 @@ pub const App = struct { } }; +/// Platform-specific configuration for libghostty. +pub const Platform = union(PlatformTag) { + macos: MacOS, + + // If our build target for libghostty is not darwin then we do + // not include macos support at all. + pub const MacOS = if (builtin.target.isDarwin()) struct { + /// The view to render the surface on. + nsview: objc.Object, + } else void; + + // The C ABI compatible version of this union. The tag is expected + // to be stored elsewhere. + pub const C = extern union { + macos: extern struct { + nsview: ?*anyopaque, + }, + }; + + /// Initialize a Platform a tag and configuration from the C ABI. + pub fn init(tag_int: c_int, c_platform: C) !Platform { + const tag = try std.meta.intToEnum(PlatformTag, tag_int); + return switch (tag) { + .macos => if (MacOS != void) macos: { + const config = c_platform.macos; + const nsview = objc.Object.fromId(config.nsview orelse + break :macos error.NSViewMustBeSet); + break :macos .{ .macos = .{ .nsview = nsview } }; + } else error.UnsupportedPlatform, + }; + } +}; + +pub const PlatformTag = enum(c_int) { + // "0" is reserved for invalid so we can detect unset values + // from the C API. + + macos = 1, +}; + pub const Surface = struct { app: *App, - nsview: objc.Object, + platform: Platform, core_surface: CoreSurface, content_scale: apprt.ContentScale, size: apprt.SurfaceSize, @@ -246,8 +286,10 @@ pub const Surface = struct { /// Userdata passed to some of the callbacks. userdata: ?*anyopaque = null, - /// The pointer to the backing NSView for the surface. - nsview: ?*anyopaque = null, + /// The platform that this surface is being initialized for and + /// the associated platform-specific configuration. + platform_tag: c_int = 0, + platform: Platform.C = undefined, /// The scale factor of the screen. scale_factor: f64 = 1, @@ -279,13 +321,10 @@ pub const Surface = struct { }; pub fn init(self: *Surface, app: *App, opts: Options) !void { - const nsview = objc.Object.fromId(opts.nsview orelse - return error.NSViewMustBeSet); - self.* = .{ .app = app, + .platform = try Platform.init(opts.platform_tag, opts.platform), .core_surface = undefined, - .nsview = nsview, .content_scale = .{ .x = @floatCast(opts.scale_factor), .y = @floatCast(opts.scale_factor), @@ -1584,30 +1623,33 @@ pub const CAPI = struct { ptr.freeInspector(); } - export fn ghostty_inspector_metal_init(ptr: *Inspector, device: objc.c.id) bool { - return ptr.initMetal(objc.Object.fromId(device)); - } - - export fn ghostty_inspector_metal_render( - ptr: *Inspector, - command_buffer: objc.c.id, - descriptor: objc.c.id, - ) void { - return ptr.renderMetal( - objc.Object.fromId(command_buffer), - objc.Object.fromId(descriptor), - ) catch |err| { - log.err("error rendering inspector err={}", .{err}); - return; - }; - } - - export fn ghostty_inspector_metal_shutdown(ptr: *Inspector) void { - if (ptr.backend) |v| { - v.deinit(); - ptr.backend = null; + // Inspector Metal APIs are only available on Apple systems + usingnamespace if (builtin.target.isDarwin()) struct { + export fn ghostty_inspector_metal_init(ptr: *Inspector, device: objc.c.id) bool { + return ptr.initMetal(objc.Object.fromId(device)); } - } + + export fn ghostty_inspector_metal_render( + ptr: *Inspector, + command_buffer: objc.c.id, + descriptor: objc.c.id, + ) void { + return ptr.renderMetal( + objc.Object.fromId(command_buffer), + objc.Object.fromId(descriptor), + ) catch |err| { + log.err("error rendering inspector err={}", .{err}); + return; + }; + } + + export fn ghostty_inspector_metal_shutdown(ptr: *Inspector) void { + if (ptr.backend) |v| { + v.deinit(); + ptr.backend = null; + } + } + } else struct {}; export fn ghostty_inspector_set_size(ptr: *Inspector, w: u32, h: u32) void { ptr.updateSize(w, h); diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index b4ebfb476..8b74167a3 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -422,6 +422,12 @@ pub fn surfaceInit(surface: *apprt.Surface) !void { }, apprt.glfw => try self.threadEnter(surface), + + apprt.embedded => { + // TODO(mitchellh): this does nothing today to allow libghostty + // to compile for OpenGL targets but libghostty is strictly + // broken for rendering on this platforms. + }, } // These are very noisy so this is commented, but easy to uncomment @@ -529,6 +535,12 @@ pub fn threadEnter(self: *const OpenGL, surface: *apprt.Surface) !void { gl.glad.versionMinor(@intCast(version)), }); }, + + apprt.embedded => { + // TODO(mitchellh): this does nothing today to allow libghostty + // to compile for OpenGL targets but libghostty is strictly + // broken for rendering on this platforms. + }, } } @@ -548,6 +560,10 @@ pub fn threadExit(self: *const OpenGL) void { gl.glad.unload(); glfw.makeContextCurrent(null); }, + + apprt.embedded => { + // TODO: see threadEnter + }, } } @@ -1815,6 +1831,7 @@ pub fn drawFrame(self: *OpenGL, surface: *apprt.Surface) !void { switch (apprt.runtime) { apprt.glfw => surface.window.swapBuffers(), apprt.gtk => {}, + apprt.embedded => {}, else => @compileError("unsupported runtime"), } }