mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-04-12 10:48:39 +03:00
gtk: add option to not link against libX11
This commit is contained in:
9
.github/workflows/test.yml
vendored
9
.github/workflows/test.yml
vendored
@ -332,6 +332,15 @@ jobs:
|
||||
- name: Test GTK Build (No Libadwaita)
|
||||
run: nix develop -c zig build -Dapp-runtime=gtk -Dgtk-adwaita=false -Demit-docs
|
||||
|
||||
- name: Test GTK build with explicit X11
|
||||
run: nix develop -c zig build -Dapp-runtime=gtk -Dgtk-adwaita=true -Demit-docs -Dgtk-x11=true
|
||||
|
||||
- name: Test GTK build with no X11
|
||||
run: nix develop -c zig build -Dapp-runtime=gtk -Dgtk-adwaita=true -Demit-docs -Dgtk-x11=false
|
||||
|
||||
- name: Test GTK build with no Adwaita and no X11
|
||||
run: nix develop -c zig build -Dapp-runtime=gtk -Dgtk-adwaita=false -Demit-docs -Dgtk-x11=false
|
||||
|
||||
- name: Test GLFW Build
|
||||
run: nix develop -c zig build -Dapp-runtime=glfw
|
||||
|
||||
|
47
build.zig
47
build.zig
@ -105,6 +105,53 @@ pub fn build(b: *std.Build) !void {
|
||||
"Enables the use of Adwaita when using the GTK rendering backend.",
|
||||
) orelse true;
|
||||
|
||||
config.x11 = b.option(
|
||||
bool,
|
||||
"gtk-x11",
|
||||
"Enables linking against X11 libraries when using the GTK rendering backend.",
|
||||
) orelse x11: {
|
||||
if (target.result.os.tag != .linux) break :x11 false;
|
||||
|
||||
var pkgconfig = std.process.Child.init(&.{ "pkg-config", "--variable=targets", "gtk4" }, b.allocator);
|
||||
|
||||
pkgconfig.stdout_behavior = .Pipe;
|
||||
pkgconfig.stderr_behavior = .Pipe;
|
||||
|
||||
try pkgconfig.spawn();
|
||||
|
||||
const output_max_size = 50 * 1024;
|
||||
|
||||
var stdout = std.ArrayList(u8).init(b.allocator);
|
||||
var stderr = std.ArrayList(u8).init(b.allocator);
|
||||
defer {
|
||||
stdout.deinit();
|
||||
stderr.deinit();
|
||||
}
|
||||
|
||||
try pkgconfig.collectOutput(&stdout, &stderr, output_max_size);
|
||||
|
||||
const term = try pkgconfig.wait();
|
||||
|
||||
if (stderr.items.len > 0) {
|
||||
std.log.warn("pkg-config had errors:\n{s}", .{stderr.items});
|
||||
}
|
||||
|
||||
switch (term) {
|
||||
.Exited => |code| {
|
||||
if (code == 0) {
|
||||
if (std.mem.indexOf(u8, stdout.items, "x11")) |_| break :x11 true;
|
||||
break :x11 false;
|
||||
}
|
||||
std.log.warn("pkg-config: {s} with code {d}", .{ @tagName(term), code });
|
||||
return error.Unexpected;
|
||||
},
|
||||
inline else => |code| {
|
||||
std.log.warn("pkg-config: {s} with code {d}", .{ @tagName(term), code });
|
||||
return error.Unexpected;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const pie = b.option(
|
||||
bool,
|
||||
"pie",
|
||||
|
@ -26,6 +26,7 @@
|
||||
pandoc,
|
||||
revision ? "dirty",
|
||||
optimize ? "Debug",
|
||||
x11 ? false,
|
||||
}: let
|
||||
# The Zig hook has no way to select the release type without actual
|
||||
# overriding of the default flags.
|
||||
@ -136,15 +137,16 @@ in
|
||||
oniguruma
|
||||
zlib
|
||||
|
||||
libX11
|
||||
libXcursor
|
||||
libXi
|
||||
libXrandr
|
||||
|
||||
libadwaita
|
||||
gtk4
|
||||
glib
|
||||
gsettings-desktop-schemas
|
||||
]
|
||||
++ lib.optionals x11 [
|
||||
libX11
|
||||
libXcursor
|
||||
libXi
|
||||
libXrandr
|
||||
];
|
||||
|
||||
dontConfigure = true;
|
||||
@ -157,7 +159,12 @@ in
|
||||
chmod u+rwX -R $ZIG_GLOBAL_CACHE_DIR
|
||||
'';
|
||||
|
||||
outputs = ["out" "terminfo" "shell_integration" "vim"];
|
||||
outputs = [
|
||||
"out"
|
||||
"terminfo"
|
||||
"shell_integration"
|
||||
"vim"
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
terminfo_src=${
|
||||
@ -183,14 +190,17 @@ in
|
||||
echo "$vim" >> "$out/nix-support/propagated-user-env-packages"
|
||||
'';
|
||||
|
||||
postFixup = ''
|
||||
postFixup = lib.optionalString x11 ''
|
||||
patchelf --add-rpath "${lib.makeLibraryPath [libX11]}" "$out/bin/.ghostty-wrapped"
|
||||
'';
|
||||
|
||||
meta = {
|
||||
homepage = "https://github.com/ghostty-org/ghostty";
|
||||
license = lib.licenses.mit;
|
||||
platforms = ["x86_64-linux" "aarch64-linux"];
|
||||
platforms = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
mainProgram = "ghostty";
|
||||
};
|
||||
})
|
||||
|
@ -15,6 +15,7 @@ const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const builtin = @import("builtin");
|
||||
const build_config = @import("../../build_config.zig");
|
||||
const build_options = @import("build_options");
|
||||
const apprt = @import("../../apprt.zig");
|
||||
const configpkg = @import("../../config.zig");
|
||||
const input = @import("../../input.zig");
|
||||
@ -360,6 +361,7 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
|
||||
// keyboard state but the block does more than that (i.e. setting up
|
||||
// WM_CLASS).
|
||||
const x11_xkb: ?x11.Xkb = x11_xkb: {
|
||||
if (comptime !build_options.x11) break :x11_xkb null;
|
||||
if (!x11.is_display(display)) break :x11_xkb null;
|
||||
|
||||
// Set the X11 window class property (WM_CLASS) if are are on an X11
|
||||
|
@ -6,6 +6,7 @@ const Surface = @This();
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const build_config = @import("../../build_config.zig");
|
||||
const build_options = @import("build_options");
|
||||
const configpkg = @import("../../config.zig");
|
||||
const apprt = @import("../../apprt.zig");
|
||||
const font = @import("../../font/main.zig");
|
||||
@ -1183,7 +1184,7 @@ fn showContextMenu(self: *Surface, x: f32, y: f32) void {
|
||||
@ptrCast(window.window),
|
||||
&c.GRAPHENE_POINT_INIT(point.x, point.y),
|
||||
@ptrCast(&point),
|
||||
) == c.False) {
|
||||
) == 0) {
|
||||
log.warn("failed computing point for context menu", .{});
|
||||
return;
|
||||
}
|
||||
@ -1899,7 +1900,7 @@ pub fn dimSurface(self: *Surface) void {
|
||||
// Don't dim surface if context menu is open.
|
||||
// This means we got unfocused due to it opening.
|
||||
const context_menu_open = c.gtk_widget_get_visible(window.context_menu);
|
||||
if (context_menu_open == c.True) return;
|
||||
if (context_menu_open == 1) return;
|
||||
|
||||
if (self.unfocused_widget != null) return;
|
||||
self.unfocused_widget = c.gtk_drawing_area_new();
|
||||
|
@ -257,7 +257,7 @@ pub fn init(self: *Window, app: *App) !void {
|
||||
|
||||
self.context_menu = c.gtk_popover_menu_new_from_model(@ptrCast(@alignCast(self.app.context_menu)));
|
||||
c.gtk_widget_set_parent(self.context_menu, window);
|
||||
c.gtk_popover_set_has_arrow(@ptrCast(@alignCast(self.context_menu)), c.False);
|
||||
c.gtk_popover_set_has_arrow(@ptrCast(@alignCast(self.context_menu)), 0);
|
||||
c.gtk_widget_set_halign(self.context_menu, c.GTK_ALIGN_START);
|
||||
|
||||
// If we are in fullscreen mode, new windows start fullscreen.
|
||||
|
@ -1,15 +1,19 @@
|
||||
const build_options = @import("build_options");
|
||||
|
||||
/// Imported C API directly from header files
|
||||
pub const c = @cImport({
|
||||
@cInclude("gtk/gtk.h");
|
||||
if (@import("build_options").adwaita) {
|
||||
if (build_options.adwaita) {
|
||||
@cInclude("libadwaita-1/adwaita.h");
|
||||
}
|
||||
|
||||
// Add in X11-specific GDK backend which we use for specific things
|
||||
// (e.g. X11 window class).
|
||||
@cInclude("gdk/x11/gdkx.h");
|
||||
// Xkb for X11 state handling
|
||||
@cInclude("X11/XKBlib.h");
|
||||
if (build_options.x11) {
|
||||
// Add in X11-specific GDK backend which we use for specific things
|
||||
// (e.g. X11 window class).
|
||||
@cInclude("gdk/x11/gdkx.h");
|
||||
// Xkb for X11 state handling
|
||||
@cInclude("X11/XKBlib.h");
|
||||
}
|
||||
|
||||
// generated header files
|
||||
@cInclude("ghostty_resources.h");
|
||||
|
@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const build_options = @import("build_options");
|
||||
const input = @import("../../input.zig");
|
||||
const c = @import("c.zig").c;
|
||||
const x11 = @import("x11.zig");
|
||||
@ -111,21 +112,25 @@ pub fn eventMods(
|
||||
x11_xkb: ?*x11.Xkb,
|
||||
) input.Mods {
|
||||
const device = c.gdk_event_get_device(event);
|
||||
const display = c.gtk_widget_get_display(widget);
|
||||
|
||||
var mods = if (x11_xkb) |xkb|
|
||||
// Add any modifier state events from Xkb if we have them (X11
|
||||
// only). Null back from the Xkb call means there was no modifier
|
||||
// event to read. This likely means that the key event did not
|
||||
// result in a modifier change and we can safely rely on the GDK
|
||||
// state.
|
||||
xkb.modifier_state_from_notify(display) orelse
|
||||
translateMods(gtk_mods)
|
||||
else
|
||||
var mods = mods: {
|
||||
if (comptime build_options.x11) {
|
||||
const display = c.gtk_widget_get_display(widget);
|
||||
if (x11_xkb) |xkb| {
|
||||
// Add any modifier state events from Xkb if we have them (X11
|
||||
// only). Null back from the Xkb call means there was no modifier
|
||||
// event to read. This likely means that the key event did not
|
||||
// result in a modifier change and we can safely rely on the GDK
|
||||
// state.
|
||||
if (xkb.modifier_state_from_notify(display)) |x11_mods| break :mods x11_mods;
|
||||
break :mods translateMods(gtk_mods);
|
||||
}
|
||||
}
|
||||
// On Wayland, we have to use the GDK device because the mods sent
|
||||
// to this event do not have the modifier key applied if it was
|
||||
// presssed (i.e. left control).
|
||||
translateMods(c.gdk_device_get_modifier_state(device));
|
||||
break :mods translateMods(c.gdk_device_get_modifier_state(device));
|
||||
};
|
||||
|
||||
mods.num_lock = c.gdk_device_get_num_lock_state(device) == 1;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/// Utility functions for X11 handling.
|
||||
const std = @import("std");
|
||||
const build_options = @import("build_options");
|
||||
const c = @import("c.zig").c;
|
||||
const input = @import("../../input.zig");
|
||||
|
||||
@ -7,6 +8,7 @@ const log = std.log.scoped(.gtk_x11);
|
||||
|
||||
/// Returns true if the passed in display is an X11 display.
|
||||
pub fn is_display(display: ?*c.GdkDisplay) bool {
|
||||
if (comptime !build_options.x11) return false;
|
||||
return c.g_type_check_instance_is_a(
|
||||
@ptrCast(@alignCast(display orelse return false)),
|
||||
c.gdk_x11_display_get_type(),
|
||||
@ -15,11 +17,12 @@ pub fn is_display(display: ?*c.GdkDisplay) bool {
|
||||
|
||||
/// Returns true if the app is running on X11
|
||||
pub fn is_current_display_server() bool {
|
||||
if (comptime !build_options.x11) return false;
|
||||
const display = c.gdk_display_get_default();
|
||||
return is_display(display);
|
||||
}
|
||||
|
||||
pub const Xkb = struct {
|
||||
pub const Xkb = if (build_options.x11) struct {
|
||||
base_event_code: c_int,
|
||||
funcs: Funcs,
|
||||
|
||||
@ -111,7 +114,7 @@ pub const Xkb = struct {
|
||||
|
||||
return mods;
|
||||
}
|
||||
};
|
||||
} else struct {};
|
||||
|
||||
/// The functions that we load dynamically from libX11.so.
|
||||
const Funcs = struct {
|
||||
|
@ -22,6 +22,7 @@ pub const BuildConfig = struct {
|
||||
version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 },
|
||||
flatpak: bool = false,
|
||||
adwaita: bool = false,
|
||||
x11: bool = false,
|
||||
app_runtime: apprt.Runtime = .none,
|
||||
renderer: rendererpkg.Impl = .opengl,
|
||||
font_backend: font.Backend = .freetype,
|
||||
@ -41,6 +42,7 @@ pub const BuildConfig = struct {
|
||||
// support all types.
|
||||
step.addOption(bool, "flatpak", self.flatpak);
|
||||
step.addOption(bool, "adwaita", self.adwaita);
|
||||
step.addOption(bool, "x11", self.x11);
|
||||
step.addOption(apprt.Runtime, "app_runtime", self.app_runtime);
|
||||
step.addOption(font.Backend, "font_backend", self.font_backend);
|
||||
step.addOption(rendererpkg.Impl, "renderer", self.renderer);
|
||||
|
@ -61,6 +61,11 @@ pub fn run(alloc: Allocator) !u8 {
|
||||
} else {
|
||||
try stdout.print(" - libadwaita : disabled\n", .{});
|
||||
}
|
||||
if (comptime build_options.x11) {
|
||||
try stdout.print(" - libX11 : enabled\n", .{});
|
||||
} else {
|
||||
try stdout.print(" - libX11 : disabled\n", .{});
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user