mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-04-23 18:08:39 +03:00
gtk/x11: link directly to libX11, no more dlopen
This commit is contained in:
@ -1427,6 +1427,7 @@ fn addDeps(
|
|||||||
.gtk => {
|
.gtk => {
|
||||||
step.linkSystemLibrary2("gtk4", dynamic_link_opts);
|
step.linkSystemLibrary2("gtk4", dynamic_link_opts);
|
||||||
if (config.adwaita) step.linkSystemLibrary2("adwaita-1", dynamic_link_opts);
|
if (config.adwaita) step.linkSystemLibrary2("adwaita-1", dynamic_link_opts);
|
||||||
|
if (config.x11) step.linkSystemLibrary2("X11", dynamic_link_opts);
|
||||||
|
|
||||||
{
|
{
|
||||||
const gresource = @import("src/apprt/gtk/gresource.zig");
|
const gresource = @import("src/apprt/gtk/gresource.zig");
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
pandoc,
|
pandoc,
|
||||||
revision ? "dirty",
|
revision ? "dirty",
|
||||||
optimize ? "Debug",
|
optimize ? "Debug",
|
||||||
x11 ? false,
|
x11 ? true,
|
||||||
}: let
|
}: let
|
||||||
# The Zig hook has no way to select the release type without actual
|
# The Zig hook has no way to select the release type without actual
|
||||||
# overriding of the default flags.
|
# overriding of the default flags.
|
||||||
@ -151,7 +151,7 @@ in
|
|||||||
|
|
||||||
dontConfigure = true;
|
dontConfigure = true;
|
||||||
|
|
||||||
zigBuildFlags = "-Dversion-string=${finalAttrs.version}-${revision}-nix";
|
zigBuildFlags = "-Dversion-string=${finalAttrs.version}-${revision}-nix -Dgtk-x11=${lib.boolToString x11}";
|
||||||
|
|
||||||
preBuild = ''
|
preBuild = ''
|
||||||
rm -rf $ZIG_GLOBAL_CACHE_DIR
|
rm -rf $ZIG_GLOBAL_CACHE_DIR
|
||||||
@ -190,10 +190,6 @@ in
|
|||||||
echo "$vim" >> "$out/nix-support/propagated-user-env-packages"
|
echo "$vim" >> "$out/nix-support/propagated-user-env-packages"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
postFixup = lib.optionalString x11 ''
|
|
||||||
patchelf --add-rpath "${lib.makeLibraryPath [libX11]}" "$out/bin/.ghostty-wrapped"
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
homepage = "https://github.com/ghostty-org/ghostty";
|
homepage = "https://github.com/ghostty-org/ghostty";
|
||||||
license = lib.licenses.mit;
|
license = lib.licenses.mit;
|
||||||
|
@ -22,13 +22,14 @@ pub fn is_current_display_server() bool {
|
|||||||
return is_display(display);
|
return is_display(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Xkb = if (build_options.x11) struct {
|
pub const Xkb = struct {
|
||||||
base_event_code: c_int,
|
base_event_code: c_int,
|
||||||
funcs: Funcs,
|
|
||||||
|
|
||||||
/// Initialize an Xkb struct, for the given GDK display. If the display
|
/// Initialize an Xkb struct for the given GDK display. If the display isn't
|
||||||
/// isn't backed by X then this will return null.
|
/// backed by X then this will return null.
|
||||||
pub fn init(display_: ?*c.GdkDisplay) !?Xkb {
|
pub fn init(display_: ?*c.GdkDisplay) !?Xkb {
|
||||||
|
if (comptime !build_options.x11) return null;
|
||||||
|
|
||||||
// Display should never be null but we just treat that as a non-X11
|
// Display should never be null but we just treat that as a non-X11
|
||||||
// display so that the caller can just ignore it and not unwrap it.
|
// display so that the caller can just ignore it and not unwrap it.
|
||||||
const display = display_ orelse return null;
|
const display = display_ orelse return null;
|
||||||
@ -40,7 +41,6 @@ pub const Xkb = if (build_options.x11) struct {
|
|||||||
const xdisplay = c.gdk_x11_display_get_xdisplay(display);
|
const xdisplay = c.gdk_x11_display_get_xdisplay(display);
|
||||||
var result: Xkb = .{
|
var result: Xkb = .{
|
||||||
.base_event_code = 0,
|
.base_event_code = 0,
|
||||||
.funcs = try Funcs.init(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
log.debug("Xkb.init: running XkbQueryExtension", .{});
|
log.debug("Xkb.init: running XkbQueryExtension", .{});
|
||||||
@ -48,7 +48,7 @@ pub const Xkb = if (build_options.x11) struct {
|
|||||||
var base_error_code: c_int = 0;
|
var base_error_code: c_int = 0;
|
||||||
var major = c.XkbMajorVersion;
|
var major = c.XkbMajorVersion;
|
||||||
var minor = c.XkbMinorVersion;
|
var minor = c.XkbMinorVersion;
|
||||||
if (result.funcs.XkbQueryExtension(
|
if (c.XkbQueryExtension(
|
||||||
xdisplay,
|
xdisplay,
|
||||||
&opcode,
|
&opcode,
|
||||||
&result.base_event_code,
|
&result.base_event_code,
|
||||||
@ -61,7 +61,7 @@ pub const Xkb = if (build_options.x11) struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.debug("Xkb.init: running XkbSelectEventDetails", .{});
|
log.debug("Xkb.init: running XkbSelectEventDetails", .{});
|
||||||
if (result.funcs.XkbSelectEventDetails(
|
if (c.XkbSelectEventDetails(
|
||||||
xdisplay,
|
xdisplay,
|
||||||
c.XkbUseCoreKbd,
|
c.XkbUseCoreKbd,
|
||||||
c.XkbStateNotify,
|
c.XkbStateNotify,
|
||||||
@ -86,15 +86,17 @@ pub const Xkb = if (build_options.x11) struct {
|
|||||||
/// back to the standard GDK modifier state (this likely means the key
|
/// back to the standard GDK modifier state (this likely means the key
|
||||||
/// event did not result in a modifier change).
|
/// event did not result in a modifier change).
|
||||||
pub fn modifier_state_from_notify(self: Xkb, display_: ?*c.GdkDisplay) ?input.Mods {
|
pub fn modifier_state_from_notify(self: Xkb, display_: ?*c.GdkDisplay) ?input.Mods {
|
||||||
|
if (comptime !build_options.x11) return null;
|
||||||
|
|
||||||
const display = display_ orelse return null;
|
const display = display_ orelse return null;
|
||||||
|
|
||||||
// Shoutout to Mozilla for figuring out a clean way to do this, this is
|
// Shoutout to Mozilla for figuring out a clean way to do this, this is
|
||||||
// paraphrased from Firefox/Gecko in widget/gtk/nsGtkKeyUtils.cpp.
|
// paraphrased from Firefox/Gecko in widget/gtk/nsGtkKeyUtils.cpp.
|
||||||
const xdisplay = c.gdk_x11_display_get_xdisplay(display);
|
const xdisplay = c.gdk_x11_display_get_xdisplay(display);
|
||||||
if (self.funcs.XEventsQueued(xdisplay, c.QueuedAfterReading) == 0) return null;
|
if (c.XEventsQueued(xdisplay, c.QueuedAfterReading) == 0) return null;
|
||||||
|
|
||||||
var nextEvent: c.XEvent = undefined;
|
var nextEvent: c.XEvent = undefined;
|
||||||
_ = self.funcs.XPeekEvent(xdisplay, &nextEvent);
|
_ = c.XPeekEvent(xdisplay, &nextEvent);
|
||||||
if (nextEvent.type != self.base_event_code) return null;
|
if (nextEvent.type != self.base_event_code) return null;
|
||||||
|
|
||||||
const xkb_event: *c.XkbEvent = @ptrCast(&nextEvent);
|
const xkb_event: *c.XkbEvent = @ptrCast(&nextEvent);
|
||||||
@ -114,40 +116,4 @@ pub const Xkb = if (build_options.x11) struct {
|
|||||||
|
|
||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
} else struct {};
|
|
||||||
|
|
||||||
/// The functions that we load dynamically from libX11.so.
|
|
||||||
const Funcs = struct {
|
|
||||||
XkbQueryExtension: XkbQueryExtensionType,
|
|
||||||
XkbSelectEventDetails: XkbSelectEventDetailsType,
|
|
||||||
XEventsQueued: XEventsQueuedType,
|
|
||||||
XPeekEvent: XPeekEventType,
|
|
||||||
|
|
||||||
const XkbQueryExtensionType = *const fn (?*c.struct__XDisplay, [*c]c_int, [*c]c_int, [*c]c_int, [*c]c_int, [*c]c_int) callconv(.C) c_int;
|
|
||||||
const XkbSelectEventDetailsType = *const fn (?*c.struct__XDisplay, c_uint, c_uint, c_ulong, c_ulong) callconv(.C) c_int;
|
|
||||||
const XEventsQueuedType = *const fn (?*c.struct__XDisplay, c_int) callconv(.C) c_int;
|
|
||||||
const XPeekEventType = *const fn (?*c.struct__XDisplay, [*c]c.union__XEvent) callconv(.C) c_int;
|
|
||||||
|
|
||||||
pub fn init() !Funcs {
|
|
||||||
var libX11 = try std.DynLib.open("libX11.so");
|
|
||||||
defer libX11.close();
|
|
||||||
|
|
||||||
var result: Funcs = undefined;
|
|
||||||
inline for (@typeInfo(Funcs).Struct.fields) |field| {
|
|
||||||
const name = comptime name: {
|
|
||||||
const null_term = field.name ++ .{0};
|
|
||||||
break :name null_term[0..field.name.len :0];
|
|
||||||
};
|
|
||||||
|
|
||||||
@field(result, field.name) = libX11.lookup(
|
|
||||||
field.type,
|
|
||||||
name,
|
|
||||||
) orelse {
|
|
||||||
log.err(" error dynamic loading libX11: missing symbol {s}", .{field.name});
|
|
||||||
return error.XkbInitializationError;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user