diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 9195355db..4b1ea9d30 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -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(); diff --git a/src/apprt/gtk/ClipboardConfirmationWindow.zig b/src/apprt/gtk/ClipboardConfirmationWindow.zig index 803660794..ce67c7a7b 100644 --- a/src/apprt/gtk/ClipboardConfirmationWindow.zig +++ b/src/apprt/gtk/ClipboardConfirmationWindow.zig @@ -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( diff --git a/src/apprt/gtk/CloseDialog.zig b/src/apprt/gtk/CloseDialog.zig index da6a45a36..47ea5f27b 100644 --- a/src/apprt/gtk/CloseDialog.zig +++ b/src/apprt/gtk/CloseDialog.zig @@ -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); diff --git a/src/apprt/gtk/ConfigErrorsDialog.zig b/src/apprt/gtk/ConfigErrorsDialog.zig index 9bfedc8bc..c10c5771d 100644 --- a/src/apprt/gtk/ConfigErrorsDialog.zig +++ b/src/apprt/gtk/ConfigErrorsDialog.zig @@ -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, diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index 27c9db7ac..b48655610 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -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); diff --git a/src/apprt/gtk/Tab.zig b/src/apprt/gtk/Tab.zig index 9d78abb93..57a9644d9 100644 --- a/src/apprt/gtk/Tab.zig +++ b/src/apprt/gtk/Tab.zig @@ -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); diff --git a/src/apprt/gtk/TabView.zig b/src/apprt/gtk/TabView.zig index 41690b193..0078e4d3d 100644 --- a/src/apprt/gtk/TabView.zig +++ b/src/apprt/gtk/TabView.zig @@ -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(); } diff --git a/src/apprt/gtk/Window.zig b/src/apprt/gtk/Window.zig index 2ec77d723..2866c5ede 100644 --- a/src/apprt/gtk/Window.zig +++ b/src/apprt/gtk/Window.zig @@ -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(); diff --git a/src/apprt/gtk/adw_version.zig b/src/apprt/gtk/adw_version.zig new file mode 100644 index 000000000..ff7439a21 --- /dev/null +++ b/src/apprt/gtk/adw_version.zig @@ -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); +} diff --git a/src/apprt/gtk/adwaita.zig b/src/apprt/gtk/adwaita.zig deleted file mode 100644 index 1191b6fca..000000000 --- a/src/apprt/gtk/adwaita.zig +++ /dev/null @@ -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); -} diff --git a/src/apprt/gtk/version.zig b/src/apprt/gtk/gtk_version.zig similarity index 84% rename from src/apprt/gtk/version.zig rename to src/apprt/gtk/gtk_version.zig index 9129d1f30..59d7a5782 100644 --- a/src/apprt/gtk/version.zig +++ b/src/apprt/gtk/gtk_version.zig @@ -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" { diff --git a/src/apprt/gtk/winproto/x11.zig b/src/apprt/gtk/winproto/x11.zig index 1df71ea6f..6d6950f74 100644 --- a/src/apprt/gtk/winproto/x11.zig +++ b/src/apprt/gtk/winproto/x11.zig @@ -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); diff --git a/src/cli/version.zig b/src/cli/version.zig index ffab102b7..a27d1050d 100644 --- a/src/cli/version.zig +++ b/src/cli/version.zig @@ -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 {