gtk: unify gtk/adwaita version checks, use std.SemanticVersion in all cases (#6797)
commit
69590c80a1
|
|
@ -19,6 +19,7 @@ const gtk = @import("gtk");
|
|||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const builtin = @import("builtin");
|
||||
const build_config = @import("../../build_config.zig");
|
||||
|
|
@ -40,12 +41,11 @@ const ConfigErrorsDialog = @import("ConfigErrorsDialog.zig");
|
|||
const ClipboardConfirmationWindow = @import("ClipboardConfirmationWindow.zig");
|
||||
const CloseDialog = @import("CloseDialog.zig");
|
||||
const Split = @import("Split.zig");
|
||||
const version = @import("version.zig");
|
||||
const inspector = @import("inspector.zig");
|
||||
const key = @import("key.zig");
|
||||
const winprotopkg = @import("winproto.zig");
|
||||
const testing = std.testing;
|
||||
const adwaita = @import("adwaita.zig");
|
||||
const gtk_version = @import("gtk_version.zig");
|
||||
const adw_version = @import("adw_version.zig");
|
||||
|
||||
pub const c = @cImport({
|
||||
// generated header files
|
||||
|
|
@ -103,10 +103,10 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
|
|||
_ = opts;
|
||||
|
||||
// Log our GTK version
|
||||
version.logVersion();
|
||||
gtk_version.logVersion();
|
||||
|
||||
// log the adwaita version
|
||||
adwaita.logVersion();
|
||||
adw_version.logVersion();
|
||||
|
||||
// Set gettext global domain to be our app so that our unqualified
|
||||
// translations map to our translations.
|
||||
|
|
@ -181,11 +181,11 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
|
|||
} = .{};
|
||||
|
||||
environment: {
|
||||
if (version.runtimeAtLeast(4, 18, 0)) {
|
||||
if (gtk_version.runtimeAtLeast(4, 18, 0)) {
|
||||
gdk_disable.@"color-mgmt" = false;
|
||||
}
|
||||
|
||||
if (version.runtimeAtLeast(4, 16, 0)) {
|
||||
if (gtk_version.runtimeAtLeast(4, 16, 0)) {
|
||||
// From gtk 4.16, GDK_DEBUG is split into GDK_DEBUG and GDK_DISABLE.
|
||||
// For the remainder of "why" see the 4.14 comment below.
|
||||
gdk_disable.@"gles-api" = true;
|
||||
|
|
@ -193,7 +193,7 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
|
|||
gdk_debug.@"gl-no-fractional" = true;
|
||||
break :environment;
|
||||
}
|
||||
if (version.runtimeAtLeast(4, 14, 0)) {
|
||||
if (gtk_version.runtimeAtLeast(4, 14, 0)) {
|
||||
// We need to export GDK_DEBUG to run on Wayland after GTK 4.14.
|
||||
// Older versions of GTK do not support these values so it is safe
|
||||
// to always set this. Forwards versions are uncertain so we'll have
|
||||
|
|
@ -247,7 +247,7 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
|
|||
_ = internal_os.setenv("GDK_DISABLE", value[0 .. value.len - 1 :0]);
|
||||
}
|
||||
|
||||
if (version.runtimeAtLeast(4, 14, 0)) {
|
||||
if (gtk_version.runtimeAtLeast(4, 14, 0)) {
|
||||
switch (config.@"gtk-gsk-renderer") {
|
||||
.default => {},
|
||||
else => |renderer| {
|
||||
|
|
@ -1109,7 +1109,7 @@ fn loadRuntimeCss(
|
|||
, .{ .font_family = font_family });
|
||||
}
|
||||
|
||||
if (version.runtimeAtLeast(4, 16, 0)) {
|
||||
if (gtk_version.runtimeAtLeast(4, 16, 0)) {
|
||||
switch (window_theme) {
|
||||
.ghostty => try writer.print(
|
||||
\\:root {{
|
||||
|
|
@ -1224,7 +1224,7 @@ fn loadCustomCss(self: *App) !void {
|
|||
}
|
||||
|
||||
fn loadCssProviderFromData(provider: *gtk.CssProvider, data: [:0]const u8) void {
|
||||
if (version.atLeast(4, 12, 0)) {
|
||||
if (gtk_version.atLeast(4, 12, 0)) {
|
||||
const g_bytes = glib.Bytes.new(data.ptr, data.len);
|
||||
defer g_bytes.unref();
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ const apprt = @import("../../apprt.zig");
|
|||
const CoreSurface = @import("../../Surface.zig");
|
||||
const App = @import("App.zig");
|
||||
const Builder = @import("Builder.zig");
|
||||
const adwaita = @import("adwaita.zig");
|
||||
const adw_version = @import("adw_version.zig");
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
const DialogType = if (adwaita.versionAtLeast(1, 5, 0)) adw.AlertDialog else adw.MessageDialog;
|
||||
const DialogType = if (adw_version.atLeast(1, 5, 0)) adw.AlertDialog else adw.MessageDialog;
|
||||
|
||||
app: *App,
|
||||
dialog: *DialogType,
|
||||
|
|
@ -141,7 +141,7 @@ fn init(
|
|||
dialog.choose(parent, null, gtkChoose, self);
|
||||
},
|
||||
adw.MessageDialog => {
|
||||
if (adwaita.versionAtLeast(1, 3, 0)) {
|
||||
if (adw_version.atLeast(1, 3, 0)) {
|
||||
dialog.choose(null, gtkChoose, self);
|
||||
} else {
|
||||
_ = adw.MessageDialog.signals.response.connect(
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const App = @import("App.zig");
|
|||
const Window = @import("Window.zig");
|
||||
const Tab = @import("Tab.zig");
|
||||
const Surface = @import("Surface.zig");
|
||||
const adwaita = @import("adwaita.zig");
|
||||
const adwaita = @import("adw_version.zig");
|
||||
|
||||
const log = std.log.scoped(.close_dialog);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ const Config = configpkg.Config;
|
|||
const App = @import("App.zig");
|
||||
const Window = @import("Window.zig");
|
||||
const Builder = @import("Builder.zig");
|
||||
const adwaita = @import("adwaita.zig");
|
||||
const adw_version = @import("adw_version.zig");
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
const DialogType = if (adwaita.supportsDialogs()) adw.AlertDialog else adw.MessageDialog;
|
||||
const DialogType = if (adw_version.supportsDialogs()) adw.AlertDialog else adw.MessageDialog;
|
||||
|
||||
builder: Builder,
|
||||
dialog: *DialogType,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ const CloseDialog = @import("CloseDialog.zig");
|
|||
const inspectorpkg = @import("inspector.zig");
|
||||
const gtk_key = @import("key.zig");
|
||||
const Builder = @import("Builder.zig");
|
||||
const adwaita = @import("adwaita.zig");
|
||||
const adw_version = @import("adw_version.zig");
|
||||
|
||||
const log = std.log.scoped(.gtk_surface);
|
||||
|
||||
|
|
@ -1058,7 +1058,7 @@ fn resolveTitle(self: *Surface, title: [:0]const u8) [:0]const u8 {
|
|||
}
|
||||
|
||||
pub fn promptTitle(self: *Surface) !void {
|
||||
if (!adwaita.versionAtLeast(1, 5, 0)) return;
|
||||
if (!adw_version.atLeast(1, 5, 0)) return;
|
||||
const window = self.container.window() orelse return;
|
||||
|
||||
var builder = Builder.init("prompt-title-dialog", 1, 5, .blp);
|
||||
|
|
@ -2381,7 +2381,7 @@ fn g_value_holds(value_: ?*gobject.Value, g_type: gobject.Type) bool {
|
|||
}
|
||||
|
||||
fn gtkPromptTitleResponse(source_object: ?*gobject.Object, result: *gio.AsyncResult, ud: ?*anyopaque) callconv(.C) void {
|
||||
if (!adwaita.versionAtLeast(1, 5, 0)) return;
|
||||
if (!adw_version.supportsDialogs()) return;
|
||||
const dialog = gobject.ext.cast(adw.AlertDialog, source_object.?).?;
|
||||
const self = userdataSelf(ud orelse return);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ const CoreSurface = @import("../../Surface.zig");
|
|||
|
||||
const Surface = @import("Surface.zig");
|
||||
const Window = @import("Window.zig");
|
||||
const adwaita = @import("adwaita.zig");
|
||||
const CloseDialog = @import("CloseDialog.zig");
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const gobject = @import("gobject");
|
|||
|
||||
const Window = @import("Window.zig");
|
||||
const Tab = @import("Tab.zig");
|
||||
const adwaita = @import("adwaita.zig");
|
||||
const adw_version = @import("adw_version.zig");
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ pub fn init(self: *TabView, window: *Window) void {
|
|||
};
|
||||
self.tab_view.as(gtk.Widget).addCssClass("notebook");
|
||||
|
||||
if (adwaita.versionAtLeast(1, 2, 0)) {
|
||||
if (adw_version.atLeast(1, 2, 0)) {
|
||||
// Adwaita enables all of the shortcuts by default.
|
||||
// We want to manage keybindings ourselves.
|
||||
self.tab_view.removeShortcuts(.{
|
||||
|
|
@ -213,7 +213,7 @@ pub fn closeTab(self: *TabView, tab: *Tab) void {
|
|||
// which causes our surface to not properly cleanup. We
|
||||
// unref to force the cleanup. This will trigger a critical
|
||||
// warning from GTK, but I don't know any other workaround.
|
||||
if (!adwaita.versionAtLeast(1, 5, 1)) {
|
||||
if (!adw_version.atLeast(1, 5, 1)) {
|
||||
const box: *gtk.Box = @ptrCast(@alignCast(tab.box));
|
||||
box.as(gobject.Object).unref();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ const Color = configpkg.Config.Color;
|
|||
const Surface = @import("Surface.zig");
|
||||
const Menu = @import("menu.zig").Menu;
|
||||
const Tab = @import("Tab.zig");
|
||||
const adwaita = @import("adwaita.zig");
|
||||
const gtk_key = @import("key.zig");
|
||||
const TabView = @import("TabView.zig");
|
||||
const HeaderBar = @import("headerbar.zig");
|
||||
const CloseDialog = @import("CloseDialog.zig");
|
||||
const version = @import("version.zig");
|
||||
const winprotopkg = @import("winproto.zig");
|
||||
const gtk_version = @import("gtk_version.zig");
|
||||
const adw_version = @import("adw_version.zig");
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||
self.notebook.init(self);
|
||||
|
||||
// If we are using Adwaita, then we can support the tab overview.
|
||||
self.tab_overview = if (adwaita.versionAtLeast(1, 4, 0)) overview: {
|
||||
self.tab_overview = if (adw_version.supportsTabOverview()) overview: {
|
||||
const tab_overview = adw.TabOverview.new();
|
||||
tab_overview.setView(self.notebook.tab_view);
|
||||
tab_overview.setEnableNewTab(1);
|
||||
|
|
@ -214,7 +214,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||
|
||||
// If we're using an AdwWindow then we can support the tab overview.
|
||||
if (self.tab_overview) |tab_overview| {
|
||||
if (!adwaita.versionAtLeast(1, 4, 0)) unreachable;
|
||||
if (!adw_version.supportsTabOverview()) unreachable;
|
||||
const btn = switch (self.config.gtk_tabs_location) {
|
||||
.top, .bottom => btn: {
|
||||
const btn = gtk.ToggleButton.new();
|
||||
|
|
@ -284,7 +284,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||
|
||||
// If Adwaita is enabled and is older than 1.4.0 we don't have the tab overview and so we
|
||||
// need to stick the headerbar into the content box.
|
||||
if (!adwaita.versionAtLeast(1, 4, 0)) {
|
||||
if (!adw_version.supportsTabOverview()) {
|
||||
box.append(self.headerbar.asWidget());
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||
if (comptime std.debug.runtime_safety) {
|
||||
const warning_box = gtk.Box.new(.vertical, 0);
|
||||
const warning_text = i18n._("⚠️ You're running a debug build of Ghostty! Performance will be degraded.");
|
||||
if (adwaita.versionAtLeast(1, 3, 0)) {
|
||||
if (adw_version.supportsBanner()) {
|
||||
const banner = adw.Banner.new(warning_text);
|
||||
banner.setRevealed(1);
|
||||
warning_box.append(banner.as(gtk.Widget));
|
||||
|
|
@ -315,7 +315,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||
|
||||
// If we have a tab overview then we can set it on our notebook.
|
||||
if (self.tab_overview) |tab_overview| {
|
||||
if (!adwaita.versionAtLeast(1, 4, 0)) unreachable;
|
||||
if (!adw_version.supportsTabOverview()) unreachable;
|
||||
tab_overview.setView(self.notebook.tab_view);
|
||||
}
|
||||
|
||||
|
|
@ -359,7 +359,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||
// Our actions for the menu
|
||||
initActions(self);
|
||||
|
||||
if (adwaita.versionAtLeast(1, 4, 0)) {
|
||||
if (adw_version.supportsToolbarView()) {
|
||||
const toolbar_view = adw.ToolbarView.new();
|
||||
toolbar_view.addTopBar(self.headerbar.asWidget());
|
||||
|
||||
|
|
@ -495,11 +495,11 @@ pub fn syncAppearance(self: *Window) !void {
|
|||
toggleCssClass(
|
||||
gtk_widget,
|
||||
"window-theme-ghostty",
|
||||
!version.atLeast(4, 16, 0) and self.config.window_theme == .ghostty,
|
||||
!gtk_version.atLeast(4, 16, 0) and self.config.window_theme == .ghostty,
|
||||
);
|
||||
|
||||
if (self.tab_overview) |tab_overview| {
|
||||
if (!adwaita.versionAtLeast(1, 4, 0)) unreachable;
|
||||
if (!adw_version.supportsTabOverview()) unreachable;
|
||||
|
||||
// Disable the title buttons (close, maximize, minimize, ...)
|
||||
// *inside* the tab overview if CSDs are disabled.
|
||||
|
|
@ -664,7 +664,7 @@ pub fn gotoTab(self: *Window, n: usize) bool {
|
|||
/// Toggle tab overview (if present)
|
||||
pub fn toggleTabOverview(self: *Window) void {
|
||||
if (self.tab_overview) |tab_overview| {
|
||||
if (!adwaita.versionAtLeast(1, 4, 0)) unreachable;
|
||||
if (!adw_version.supportsTabOverview()) unreachable;
|
||||
const is_open = tab_overview.getOpen() != 0;
|
||||
tab_overview.setOpen(@intFromBool(!is_open));
|
||||
}
|
||||
|
|
@ -797,7 +797,7 @@ fn gtkTabNewClick(_: *gtk.Button, self: *Window) callconv(.c) void {
|
|||
/// Create a new tab from the AdwTabOverview. We can't copy gtkTabNewClick
|
||||
/// because we need to return an AdwTabPage from this function.
|
||||
fn gtkNewTabFromOverview(_: *adw.TabOverview, self: *Window) callconv(.c) *adw.TabPage {
|
||||
if (!adwaita.versionAtLeast(1, 4, 0)) unreachable;
|
||||
if (!adw_version.supportsTabOverview()) unreachable;
|
||||
|
||||
const alloc = self.app.core_app.alloc;
|
||||
const surface = self.actionSurface();
|
||||
|
|
@ -810,6 +810,7 @@ fn adwTabOverviewOpen(
|
|||
_: *gobject.ParamSpec,
|
||||
self: *Window,
|
||||
) callconv(.c) void {
|
||||
if (!adw_version.supportsTabOverview()) unreachable;
|
||||
|
||||
// We only care about when the tab overview is closed.
|
||||
if (tab_overview.getOpen() != 0) return;
|
||||
|
|
@ -840,6 +841,7 @@ fn adwTabOverviewOpen(
|
|||
fn adwTabOverviewFocusTimer(
|
||||
ud: ?*anyopaque,
|
||||
) callconv(.C) c_int {
|
||||
if (!adw_version.supportsTabOverview()) unreachable;
|
||||
const self: *Window = @ptrCast(@alignCast(ud orelse return 0));
|
||||
self.adw_tab_overview_focus_timer = null;
|
||||
self.focusCurrentTab();
|
||||
|
|
@ -905,7 +907,7 @@ fn gtkKeyPressed(
|
|||
//
|
||||
// If someone can confidently show or explain that this is not
|
||||
// necessary, please remove this check.
|
||||
if (adwaita.versionAtLeast(1, 4, 0)) {
|
||||
if (adw_version.supportsTabOverview()) {
|
||||
if (self.tab_overview) |tab_overview| {
|
||||
if (tab_overview.getOpen() == 0) return 0;
|
||||
}
|
||||
|
|
@ -930,7 +932,7 @@ fn gtkActionAbout(
|
|||
const icon = "com.mitchellh.ghostty";
|
||||
const website = "https://ghostty.org";
|
||||
|
||||
if (adwaita.versionAtLeast(1, 5, 0)) {
|
||||
if (adw_version.supportsDialogs()) {
|
||||
adw.showAboutDialog(
|
||||
self.window.as(gtk.Widget),
|
||||
"application-name",
|
||||
|
|
@ -1139,7 +1141,7 @@ fn gtkTitlebarMenuActivate(
|
|||
self: *Window,
|
||||
) callconv(.C) void {
|
||||
// debian 12 is stuck on GTK 4.8
|
||||
if (!version.atLeast(4, 10, 0)) return;
|
||||
if (!gtk_version.atLeast(4, 10, 0)) return;
|
||||
const active = btn.getActive() != 0;
|
||||
if (active) {
|
||||
self.titlebar_menu.refresh();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
const std = @import("std");
|
||||
|
||||
// Until the gobject bindings are built at the same time we are building
|
||||
// Ghostty, we need to import `adwaita.h` directly to ensure that the version
|
||||
// macros match the version of `libadwaita` that we are building/linking
|
||||
// against.
|
||||
const c = @cImport({
|
||||
@cInclude("adwaita.h");
|
||||
});
|
||||
|
||||
const adw = @import("adw");
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
pub const comptime_version: std.SemanticVersion = .{
|
||||
.major = c.ADW_MAJOR_VERSION,
|
||||
.minor = c.ADW_MINOR_VERSION,
|
||||
.patch = c.ADW_MICRO_VERSION,
|
||||
};
|
||||
|
||||
pub fn getRuntimeVersion() std.SemanticVersion {
|
||||
return .{
|
||||
.major = adw.getMajorVersion(),
|
||||
.minor = adw.getMinorVersion(),
|
||||
.patch = adw.getMicroVersion(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn logVersion() void {
|
||||
log.info("libadwaita version build={} runtime={}", .{
|
||||
comptime_version,
|
||||
getRuntimeVersion(),
|
||||
});
|
||||
}
|
||||
|
||||
/// Verifies that the running libadwaita version is at least the given
|
||||
/// version. This will return false if Ghostty is configured to not build with
|
||||
/// libadwaita.
|
||||
///
|
||||
/// This can be run in both a comptime and runtime context. If it is run in a
|
||||
/// comptime context, it will only check the version in the headers. If it is
|
||||
/// run in a runtime context, it will check the actual version of the library we
|
||||
/// are linked against. So generally you probably want to do both checks!
|
||||
///
|
||||
/// This is inlined so that the comptime checks will disable the runtime checks
|
||||
/// if the comptime checks fail.
|
||||
pub inline fn atLeast(
|
||||
comptime major: u16,
|
||||
comptime minor: u16,
|
||||
comptime micro: u16,
|
||||
) bool {
|
||||
// If our header has lower versions than the given version, we can return
|
||||
// false immediately. This prevents us from compiling against unknown
|
||||
// symbols and makes runtime checks very slightly faster.
|
||||
if (comptime comptime_version.order(.{
|
||||
.major = major,
|
||||
.minor = minor,
|
||||
.patch = micro,
|
||||
}) == .lt) return false;
|
||||
|
||||
// If we're in comptime then we can't check the runtime version.
|
||||
if (@inComptime()) return true;
|
||||
|
||||
return runtimeAtLeast(major, minor, micro);
|
||||
}
|
||||
|
||||
/// Verifies that the libadwaita version at runtime is at least the given version.
|
||||
///
|
||||
/// This function should be used in cases where the only the runtime behavior
|
||||
/// is affected by the version check. For checks which would affect code
|
||||
/// generation, use `atLeast`.
|
||||
pub inline fn runtimeAtLeast(
|
||||
comptime major: u16,
|
||||
comptime minor: u16,
|
||||
comptime micro: u16,
|
||||
) bool {
|
||||
// We use the functions instead of the constants such as c.GTK_MINOR_VERSION
|
||||
// because the function gets the actual runtime version.
|
||||
const runtime_version = getRuntimeVersion();
|
||||
return runtime_version.order(.{
|
||||
.major = major,
|
||||
.minor = minor,
|
||||
.patch = micro,
|
||||
}) != .lt;
|
||||
}
|
||||
|
||||
test "versionAtLeast" {
|
||||
const testing = std.testing;
|
||||
|
||||
const funs = &.{ atLeast, runtimeAtLeast };
|
||||
inline for (funs) |fun| {
|
||||
try testing.expect(fun(c.ADW_MAJOR_VERSION, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(!fun(c.ADW_MAJOR_VERSION, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION + 1));
|
||||
try testing.expect(!fun(c.ADW_MAJOR_VERSION, c.ADW_MINOR_VERSION + 1, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(!fun(c.ADW_MAJOR_VERSION + 1, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(fun(c.ADW_MAJOR_VERSION - 1, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(fun(c.ADW_MAJOR_VERSION - 1, c.ADW_MINOR_VERSION + 1, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(fun(c.ADW_MAJOR_VERSION - 1, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION + 1));
|
||||
try testing.expect(fun(c.ADW_MAJOR_VERSION, c.ADW_MINOR_VERSION - 1, c.ADW_MICRO_VERSION + 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Whether AdwDialog, AdwAlertDialog, etc. are supported (1.5+)
|
||||
pub inline fn supportsDialogs() bool {
|
||||
return atLeast(1, 5, 0);
|
||||
}
|
||||
|
||||
pub inline fn supportsTabOverview() bool {
|
||||
return atLeast(1, 4, 0);
|
||||
}
|
||||
|
||||
pub inline fn supportsToolbarView() bool {
|
||||
return atLeast(1, 4, 0);
|
||||
}
|
||||
|
||||
pub inline fn supportsBanner() bool {
|
||||
return atLeast(1, 3, 0);
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
const std = @import("std");
|
||||
|
||||
// Until the gobject bindings are built at the same time we are building
|
||||
// Ghostty, we need to import `adwaita.h` directly to ensure that the version
|
||||
// macros match the version of `libadwaita` that we are building/linking
|
||||
// against.
|
||||
const c = @cImport({
|
||||
@cInclude("adwaita.h");
|
||||
});
|
||||
|
||||
const adw = @import("adw");
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
pub fn logVersion() void {
|
||||
log.info("libadwaita version build={s} runtime={}.{}.{}", .{
|
||||
c.ADW_VERSION_S,
|
||||
adw.getMajorVersion(),
|
||||
adw.getMinorVersion(),
|
||||
adw.getMicroVersion(),
|
||||
});
|
||||
}
|
||||
|
||||
/// Verifies that the running libadwaita version is at least the given
|
||||
/// version. This will return false if Ghostty is configured to not build with
|
||||
/// libadwaita.
|
||||
///
|
||||
/// This can be run in both a comptime and runtime context. If it is run in a
|
||||
/// comptime context, it will only check the version in the headers. If it is
|
||||
/// run in a runtime context, it will check the actual version of the library we
|
||||
/// are linked against. So generally you probably want to do both checks!
|
||||
///
|
||||
/// This is inlined so that the comptime checks will disable the runtime checks
|
||||
/// if the comptime checks fail.
|
||||
pub inline fn versionAtLeast(
|
||||
comptime major: u16,
|
||||
comptime minor: u16,
|
||||
comptime micro: u16,
|
||||
) bool {
|
||||
// If our header has lower versions than the given version, we can return
|
||||
// false immediately. This prevents us from compiling against unknown
|
||||
// symbols and makes runtime checks very slightly faster.
|
||||
if (comptime c.ADW_MAJOR_VERSION < major or
|
||||
(c.ADW_MAJOR_VERSION == major and c.ADW_MINOR_VERSION < minor) or
|
||||
(c.ADW_MAJOR_VERSION == major and c.ADW_MINOR_VERSION == minor and c.ADW_MICRO_VERSION < micro))
|
||||
return false;
|
||||
|
||||
// If we're in comptime then we can't check the runtime version.
|
||||
if (@inComptime()) return true;
|
||||
|
||||
// We use the functions instead of the constants such as c.ADW_MINOR_VERSION
|
||||
// because the function gets the actual runtime version.
|
||||
if (adw.getMajorVersion() >= major) {
|
||||
if (adw.getMajorVersion() > major) return true;
|
||||
if (adw.getMinorVersion() >= minor) {
|
||||
if (adw.getMinorVersion() > minor) return true;
|
||||
return adw.getMicroVersion() >= micro;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
test "versionAtLeast" {
|
||||
const testing = std.testing;
|
||||
|
||||
try testing.expect(versionAtLeast(c.ADW_MAJOR_VERSION, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(!versionAtLeast(c.ADW_MAJOR_VERSION, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION + 1));
|
||||
try testing.expect(!versionAtLeast(c.ADW_MAJOR_VERSION, c.ADW_MINOR_VERSION + 1, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(!versionAtLeast(c.ADW_MAJOR_VERSION + 1, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(versionAtLeast(c.ADW_MAJOR_VERSION - 1, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(versionAtLeast(c.ADW_MAJOR_VERSION - 1, c.ADW_MINOR_VERSION + 1, c.ADW_MICRO_VERSION));
|
||||
try testing.expect(versionAtLeast(c.ADW_MAJOR_VERSION - 1, c.ADW_MINOR_VERSION, c.ADW_MICRO_VERSION + 1));
|
||||
try testing.expect(versionAtLeast(c.ADW_MAJOR_VERSION, c.ADW_MINOR_VERSION - 1, c.ADW_MICRO_VERSION + 1));
|
||||
}
|
||||
|
||||
// Whether AdwDialog, AdwAlertDialog, etc. are supported (1.5+)
|
||||
pub fn supportsDialogs() bool {
|
||||
return versionAtLeast(1, 5, 0);
|
||||
}
|
||||
|
|
@ -11,20 +11,24 @@ const gtk = @import("gtk");
|
|||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
pub const version: std.SemanticVersion = .{
|
||||
pub const comptime_version: std.SemanticVersion = .{
|
||||
.major = c.GTK_MAJOR_VERSION,
|
||||
.minor = c.GTK_MINOR_VERSION,
|
||||
.patch = c.GTK_MICRO_VERSION,
|
||||
};
|
||||
|
||||
pub fn getRuntimeVersion() std.SemanticVersion {
|
||||
return .{
|
||||
.major = gtk.getMajorVersion(),
|
||||
.minor = gtk.getMinorVersion(),
|
||||
.patch = gtk.getMicroVersion(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn logVersion() void {
|
||||
log.info("GTK version build={d}.{d}.{d} runtime={d}.{d}.{d}", .{
|
||||
version.major,
|
||||
version.minor,
|
||||
version.patch,
|
||||
gtk.getMajorVersion(),
|
||||
gtk.getMinorVersion(),
|
||||
gtk.getMicroVersion(),
|
||||
log.info("GTK version build={} runtime={}", .{
|
||||
comptime_version,
|
||||
getRuntimeVersion(),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +55,7 @@ pub inline fn atLeast(
|
|||
// we can return false immediately. This prevents us from
|
||||
// compiling against unknown symbols and makes runtime checks
|
||||
// very slightly faster.
|
||||
if (comptime version.order(.{
|
||||
if (comptime comptime_version.order(.{
|
||||
.major = major,
|
||||
.minor = minor,
|
||||
.patch = micro,
|
||||
|
|
@ -75,15 +79,12 @@ pub inline fn runtimeAtLeast(
|
|||
) bool {
|
||||
// We use the functions instead of the constants such as c.GTK_MINOR_VERSION
|
||||
// because the function gets the actual runtime version.
|
||||
if (gtk.getMajorVersion() >= major) {
|
||||
if (gtk.getMajorVersion() > major) return true;
|
||||
if (gtk.getMinorVersion() >= minor) {
|
||||
if (gtk.getMinorVersion() > minor) return true;
|
||||
return gtk.getMicroVersion() >= micro;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
const runtime_version = getRuntimeVersion();
|
||||
return runtime_version.order(.{
|
||||
.major = major,
|
||||
.minor = minor,
|
||||
.patch = micro,
|
||||
}) != .lt;
|
||||
}
|
||||
|
||||
test "atLeast" {
|
||||
|
|
@ -20,7 +20,6 @@ pub const c = @cImport({
|
|||
|
||||
const input = @import("../../../input.zig");
|
||||
const Config = @import("../../../config.zig").Config;
|
||||
const adwaita = @import("../adwaita.zig");
|
||||
const ApprtWindow = @import("../Window.zig");
|
||||
|
||||
const log = std.log.scoped(.gtk_x11);
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ const internal_os = @import("../os/main.zig");
|
|||
const xev = @import("../global.zig").xev;
|
||||
const renderer = @import("../renderer.zig");
|
||||
|
||||
const gtk_version = @import("../apprt/gtk/version.zig").version;
|
||||
const gtk = @import("gtk");
|
||||
const adw = @import("adw");
|
||||
const gtk_version = @import("../apprt/gtk/gtk_version.zig");
|
||||
const adw_version = @import("../apprt/gtk/adw_version.zig");
|
||||
|
||||
pub const Options = struct {};
|
||||
|
||||
|
|
@ -44,25 +43,11 @@ pub fn run(alloc: Allocator) !u8 {
|
|||
if (comptime build_config.app_runtime == .gtk) {
|
||||
try stdout.print(" - desktop env: {s}\n", .{@tagName(internal_os.desktopEnvironment())});
|
||||
try stdout.print(" - GTK version:\n", .{});
|
||||
try stdout.print(" build : {d}.{d}.{d}\n", .{
|
||||
gtk_version.major,
|
||||
gtk_version.minor,
|
||||
gtk_version.patch,
|
||||
});
|
||||
try stdout.print(" runtime : {d}.{d}.{d}\n", .{
|
||||
gtk.getMajorVersion(),
|
||||
gtk.getMinorVersion(),
|
||||
gtk.getMicroVersion(),
|
||||
});
|
||||
try stdout.print(" build : {}\n", .{gtk_version.comptime_version});
|
||||
try stdout.print(" runtime : {}\n", .{gtk_version.getRuntimeVersion()});
|
||||
try stdout.print(" - libadwaita : enabled\n", .{});
|
||||
try stdout.print(" build : {s}\n", .{
|
||||
adw.VERSION_S,
|
||||
});
|
||||
try stdout.print(" runtime : {}.{}.{}\n", .{
|
||||
adw.getMajorVersion(),
|
||||
adw.getMinorVersion(),
|
||||
adw.getMicroVersion(),
|
||||
});
|
||||
try stdout.print(" build : {}\n", .{adw_version.comptime_version});
|
||||
try stdout.print(" runtime : {}\n", .{adw_version.getRuntimeVersion()});
|
||||
if (comptime build_options.x11) {
|
||||
try stdout.print(" - libX11 : enabled\n", .{});
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue