diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index c902f0fe3..c539326ba 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -37,6 +37,7 @@ const InspectorWindow = @import("inspector_window.zig").InspectorWindow; const i18n = @import("../../../os/i18n.zig"); const media = @import("../media.zig"); const global = @import("../../../global.zig"); +const gtk_version = @import("../gtk_version.zig"); const log = std.log.scoped(.gtk_ghostty_surface); @@ -1991,6 +1992,58 @@ pub const Surface = extern struct { ); } + fn snapshot(self: *Self, snap: *gtk.Snapshot) callconv(.c) void { + const priv = self.private(); + + const blur = blur: { + // Native GTK blur is only available since GTK 4.23.3 + if (gtk_version.runtimeUntil(4, 23, 3)) break :blur null; + const config = priv.config orelse break :blur null; + + break :blur switch (config.get().@"background-blur") { + .radius => |v| @as(f32, v), + .true, .@"macos-glass-regular", .@"macos-glass-clear" => 20.0, + .false => null, + }; + }; + + if (blur) |b| blur: { + // pushCopy and appendPaste are only supported since 4.22. + // These two functions are crucial for the blur function + // and it cannot be implemented otherwise, so if you compile + // Ghostty on an older GTK version, you won't get blur. + // Sorry. + if (comptime !gtk_version.atLeast(4, 22, 0)) break :blur; + + const width = self.as(gtk.Widget).getWidth(); + const height = self.as(gtk.Widget).getHeight(); + + // Push the current render state (background) + // to be appended below + snap.pushCopy(); + defer snap.pop(); + + // Apply blur to the copied background + snap.pushBlur(b); + defer snap.pop(); + + snap.appendPaste(&.{ + .f_origin = .{ .f_x = 0, .f_y = 0 }, + .f_size = .{ + .f_width = @floatFromInt(width), + .f_height = @floatFromInt(height), + }, + }, 0); + } + + // Draw the children normally + gtk.Widget.virtual_methods.snapshot.call( + Class.parent, + self.as(Parent), + snap, + ); + } + //--------------------------------------------------------------- // Properties @@ -3737,6 +3790,7 @@ pub const Surface = extern struct { // Virtual methods gobject.Object.virtual_methods.dispose.implement(class, &dispose); gobject.Object.virtual_methods.finalize.implement(class, &finalize); + gtk.Widget.virtual_methods.snapshot.implement(class, &snapshot); } pub const as = C.Class.as; diff --git a/src/apprt/gtk/winproto/wayland.zig b/src/apprt/gtk/winproto/wayland.zig index dc3647679..c65429699 100644 --- a/src/apprt/gtk/winproto/wayland.zig +++ b/src/apprt/gtk/winproto/wayland.zig @@ -22,6 +22,7 @@ const input = @import("../../../input.zig"); const ApprtWindow = @import("../class/window.zig").Window; const GlobalShortcuts = @import("../class/global_shortcuts.zig").GlobalShortcuts; const BlurRegion = @import("BlurRegion.zig"); +const gtk_version = @import("../gtk_version.zig"); const log = std.log.scoped(.winproto_wayland); @@ -174,6 +175,12 @@ pub const Window = struct { }; const bg_effect: ?*ext.BackgroundEffectSurfaceV1 = bg: { + if (gtk_version.runtimeAtLeast(4, 23, 3)) { + // GTK 4.23.3 added an official way to do background blur, + // so we don't need to do anything on our own. + break :bg null; + } + const mgr = app.globals.get(.ext_background_effect) orelse break :bg null;