mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
add app runtime option, add gtk backend
This commit is contained in:
43
build.zig
43
build.zig
@ -3,6 +3,7 @@ const builtin = @import("builtin");
|
||||
const fs = std.fs;
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjStep = std.build.LibExeObjStep;
|
||||
const apprt = @import("src/apprt.zig");
|
||||
const glfw = @import("vendor/mach/libs/glfw/build.zig");
|
||||
const fontconfig = @import("pkg/fontconfig/build.zig");
|
||||
const freetype = @import("pkg/freetype/build.zig");
|
||||
@ -45,6 +46,7 @@ comptime {
|
||||
var tracy: bool = false;
|
||||
var enable_coretext: bool = false;
|
||||
var enable_fontconfig: bool = false;
|
||||
var app_runtime: apprt.Runtime = .none;
|
||||
|
||||
pub fn build(b: *std.build.Builder) !void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
@ -77,6 +79,12 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
"Enable fontconfig for font discovery (default true on Linux)",
|
||||
) orelse target.isLinux();
|
||||
|
||||
app_runtime = b.option(
|
||||
apprt.Runtime,
|
||||
"app-runtime",
|
||||
"The app runtime to use. Not all values supported on all platforms.",
|
||||
) orelse apprt.Runtime.default(target);
|
||||
|
||||
const static = b.option(
|
||||
bool,
|
||||
"static",
|
||||
@ -111,6 +119,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
exe_options.addOption(bool, "tracy_enabled", tracy);
|
||||
exe_options.addOption(bool, "coretext", enable_coretext);
|
||||
exe_options.addOption(bool, "fontconfig", enable_fontconfig);
|
||||
exe_options.addOption(apprt.Runtime, "app_runtime", app_runtime);
|
||||
|
||||
// Exe
|
||||
{
|
||||
@ -120,7 +129,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
}
|
||||
|
||||
exe.addOptions("build_options", exe_options);
|
||||
exe.install();
|
||||
if (app_runtime != .none) exe.install();
|
||||
|
||||
// Add the shared dependencies
|
||||
_ = try addDeps(b, exe, static);
|
||||
@ -134,7 +143,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
b.installFile("dist/macos/Ghostty.icns", "Ghostty.app/Contents/Resources/Ghostty.icns");
|
||||
}
|
||||
|
||||
// On Mac we can build the app.
|
||||
// On Mac we can build the embedding library.
|
||||
if (builtin.target.isDarwin()) {
|
||||
const static_lib_aarch64 = lib: {
|
||||
const lib = b.addStaticLibrary(.{
|
||||
@ -539,22 +548,30 @@ fn addDeps(
|
||||
}
|
||||
|
||||
if (!lib) {
|
||||
step.addModule("glfw", glfw.module(b));
|
||||
|
||||
// We always statically compile glad
|
||||
step.addIncludePath("vendor/glad/include/");
|
||||
step.addCSourceFile("vendor/glad/src/gl.c", &.{});
|
||||
|
||||
// Glfw
|
||||
const glfw_opts: glfw.Options = .{
|
||||
.metal = step.target.isDarwin(),
|
||||
.opengl = false,
|
||||
};
|
||||
try glfw.link(b, step, glfw_opts);
|
||||
switch (app_runtime) {
|
||||
.none => {},
|
||||
|
||||
// Imgui
|
||||
const imgui_step = try imgui.link(b, step, imgui_opts);
|
||||
try glfw.link(b, imgui_step, glfw_opts);
|
||||
.glfw => {
|
||||
step.addModule("glfw", glfw.module(b));
|
||||
const glfw_opts: glfw.Options = .{
|
||||
.metal = step.target.isDarwin(),
|
||||
.opengl = false,
|
||||
};
|
||||
try glfw.link(b, step, glfw_opts);
|
||||
|
||||
// Must also link to imgui
|
||||
const imgui_step = try imgui.link(b, step, imgui_opts);
|
||||
try glfw.link(b, imgui_step, glfw_opts);
|
||||
},
|
||||
|
||||
.gtk => {
|
||||
step.linkSystemLibrary("gtk4");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return static_libs;
|
||||
|
@ -22,6 +22,7 @@
|
||||
, expat
|
||||
, fontconfig
|
||||
, freetype
|
||||
, gtk4
|
||||
, harfbuzz
|
||||
, libpng
|
||||
, libGL
|
||||
@ -53,6 +54,8 @@ let
|
||||
libXcursor
|
||||
libXi
|
||||
libXrandr
|
||||
|
||||
gtk4
|
||||
];
|
||||
in mkShell rec {
|
||||
name = "ghostty";
|
||||
@ -102,6 +105,9 @@ in mkShell rec {
|
||||
libXi
|
||||
libXinerama
|
||||
libXrandr
|
||||
|
||||
# Only needed for GTK builds
|
||||
gtk4
|
||||
];
|
||||
|
||||
# This should be set onto the rpath of the ghostty binary if you want
|
||||
|
@ -8,21 +8,49 @@
|
||||
//! The goal is to have different implementations share as much of the core
|
||||
//! logic as possible, and to only reach out to platform-specific implementation
|
||||
//! code when absolutely necessary.
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const build_config = @import("build_config.zig");
|
||||
|
||||
pub usingnamespace @import("apprt/structs.zig");
|
||||
pub const glfw = @import("apprt/glfw.zig");
|
||||
pub const gtk = @import("apprt/gtk.zig");
|
||||
pub const browser = @import("apprt/browser.zig");
|
||||
pub const embedded = @import("apprt/embedded.zig");
|
||||
pub const Window = @import("apprt/Window.zig");
|
||||
|
||||
/// Runtime is the runtime to use for Ghostty. All runtimes do not provide
|
||||
/// equivalent feature sets. For example, GTK offers tabbing and more features
|
||||
/// that glfw does not provide. However, glfw may require many less
|
||||
/// dependencies.
|
||||
pub const Runtime = enum {
|
||||
/// Will not produce an executable at all when `zig build` is called.
|
||||
/// This is only useful if you're only interested in the lib only (macOS).
|
||||
none,
|
||||
|
||||
/// Glfw-backed. Very simple. Glfw is statically linked. Tabbing and
|
||||
/// other rich windowing features are not supported.
|
||||
glfw,
|
||||
|
||||
/// GTK-backed. Rich windowed application. GTK is dynamically linked.
|
||||
gtk,
|
||||
|
||||
pub fn default(target: std.zig.CrossTarget) Runtime {
|
||||
_ = target;
|
||||
return .glfw;
|
||||
}
|
||||
};
|
||||
|
||||
/// The implementation to use for the app runtime. This is comptime chosen
|
||||
/// so that every build has exactly one application runtime implementation.
|
||||
/// Note: it is very rare to use Runtime directly; most usage will use
|
||||
/// Window or something.
|
||||
pub const runtime = switch (build_config.artifact) {
|
||||
.exe => glfw,
|
||||
.exe => switch (build_config.app_runtime) {
|
||||
.none => @compileError("exe with no runtime not allowed"),
|
||||
.glfw => glfw,
|
||||
.gtk => gtk,
|
||||
},
|
||||
.lib => embedded,
|
||||
.wasm_module => browser,
|
||||
};
|
||||
|
45
src/apprt/gtk.zig
Normal file
45
src/apprt/gtk.zig
Normal file
@ -0,0 +1,45 @@
|
||||
//! Application runtime that uses GTK4.
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub const c = @cImport({
|
||||
@cInclude("gtk/gtk.h");
|
||||
});
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
pub const App = struct {
|
||||
pub const Options = struct {
|
||||
/// GTK app ID
|
||||
id: [:0]const u8 = "com.mitchellh.ghostty",
|
||||
};
|
||||
|
||||
pub fn init(opts: Options) !App {
|
||||
const app = c.gtk_application_new(opts.id.ptr, c.G_APPLICATION_DEFAULT_FLAGS);
|
||||
errdefer c.g_object_unref(app);
|
||||
return .{};
|
||||
}
|
||||
|
||||
pub fn terminate(self: App) void {
|
||||
_ = self;
|
||||
}
|
||||
|
||||
pub fn wakeup(self: App) !void {
|
||||
_ = self;
|
||||
}
|
||||
|
||||
pub fn wait(self: App) !void {
|
||||
_ = self;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Window = struct {
|
||||
pub const Options = struct {};
|
||||
|
||||
pub fn deinit(self: *Window) void {
|
||||
_ = self;
|
||||
}
|
||||
};
|
@ -4,15 +4,19 @@
|
||||
//! to shim logic and values into them later.
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const options = @import("build_options");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
/// The artifact we're producing. This can be used to determine if we're
|
||||
/// building a standalone exe, an embedded lib, etc.
|
||||
pub const artifact = Artifact.detect();
|
||||
|
||||
/// The runtime to back exe artifacts with.
|
||||
pub const app_runtime = options.app_runtime;
|
||||
|
||||
/// Whether our devmode UI is enabled or not. This requires imgui to be
|
||||
/// compiled.
|
||||
pub const devmode_enabled = artifact == .exe;
|
||||
pub const devmode_enabled = artifact == .exe and app_runtime == .glfw;
|
||||
|
||||
pub const Artifact = enum {
|
||||
/// Standalone executable
|
||||
|
12
src/main.zig
12
src/main.zig
@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const build_config = @import("build_config.zig");
|
||||
const options = @import("build_options");
|
||||
const glfw = @import("glfw");
|
||||
const macos = @import("macos");
|
||||
@ -88,12 +89,19 @@ pub fn main() !void {
|
||||
try config.finalize();
|
||||
std.log.debug("config={}", .{config});
|
||||
|
||||
// We want to log all our errors
|
||||
glfw.setErrorCallback(glfwErrorCallback);
|
||||
switch (build_config.app_runtime) {
|
||||
.none => {},
|
||||
.glfw => {
|
||||
// We want to log all our errors
|
||||
glfw.setErrorCallback(glfwErrorCallback);
|
||||
},
|
||||
.gtk => {},
|
||||
}
|
||||
|
||||
// Run our app with a single initial window to start.
|
||||
var app = try App.create(alloc, .{}, &config);
|
||||
defer app.destroy();
|
||||
if (build_config.app_runtime == .gtk) return;
|
||||
_ = try app.newWindow(.{});
|
||||
try app.run();
|
||||
}
|
||||
|
@ -420,6 +420,7 @@ pub fn deinitDevMode(self: *const OpenGL) void {
|
||||
/// Callback called by renderer.Thread when it begins.
|
||||
pub fn threadEnter(self: *const OpenGL, win: apprt.runtime.Window) !void {
|
||||
_ = self;
|
||||
if (apprt.runtime == apprt.gtk) @panic("TODO");
|
||||
|
||||
// We need to make the OpenGL context current. OpenGL requires
|
||||
// that a single thread own the a single OpenGL context (if any). This
|
||||
@ -1066,7 +1067,8 @@ pub fn setScreenSize(self: *OpenGL, dim: renderer.ScreenSize) !void {
|
||||
// Apply our padding
|
||||
const padding = self.padding.explicit.add(if (self.padding.balance)
|
||||
renderer.Padding.balanced(dim, grid_size, self.cell_size)
|
||||
else .{});
|
||||
else
|
||||
.{});
|
||||
const padded_dim = dim.subPadding(padding);
|
||||
|
||||
log.debug("screen size padded={} screen={} grid={} cell={} padding={}", .{
|
||||
|
Reference in New Issue
Block a user