mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 07:46:12 +03:00
gtk(x11): implement background blur for KDE/KWin on X11
This commit is contained in:

committed by
Mitchell Hashimoto

parent
03fee2ac33
commit
405a897230
@ -11,6 +11,8 @@ pub const c = @cImport({
|
|||||||
// Add in X11-specific GDK backend which we use for specific things
|
// Add in X11-specific GDK backend which we use for specific things
|
||||||
// (e.g. X11 window class).
|
// (e.g. X11 window class).
|
||||||
@cInclude("gdk/x11/gdkx.h");
|
@cInclude("gdk/x11/gdkx.h");
|
||||||
|
@cInclude("X11/Xlib.h");
|
||||||
|
@cInclude("X11/Xatom.h");
|
||||||
// Xkb for X11 state handling
|
// Xkb for X11 state handling
|
||||||
@cInclude("X11/XKBlib.h");
|
@cInclude("X11/XKBlib.h");
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ const log = std.log.scoped(.gtk_x11);
|
|||||||
pub const App = struct {
|
pub const App = struct {
|
||||||
common: *protocol.App,
|
common: *protocol.App,
|
||||||
display: *c.Display,
|
display: *c.Display,
|
||||||
|
kde_blur_atom: c.Atom,
|
||||||
|
|
||||||
base_event_code: c_int = 0,
|
base_event_code: c_int = 0,
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ pub const App = struct {
|
|||||||
var self: App = .{
|
var self: App = .{
|
||||||
.common = common,
|
.common = common,
|
||||||
.display = c.gdk_x11_display_get_xdisplay(common.gdk_display) orelse return,
|
.display = c.gdk_x11_display_get_xdisplay(common.gdk_display) orelse return,
|
||||||
|
.kde_blur_atom = c.gdk_x11_get_xatom_by_name_for_display(common.gdk_display, "_KDE_NET_WM_BLUR_BEHIND_REGION"),
|
||||||
};
|
};
|
||||||
|
|
||||||
log.debug("X11 platform init={}", .{self});
|
log.debug("X11 platform init={}", .{self});
|
||||||
@ -130,6 +132,8 @@ pub const Surface = struct {
|
|||||||
app: *App,
|
app: *App,
|
||||||
window: c.Window,
|
window: c.Window,
|
||||||
|
|
||||||
|
blur_region: Region,
|
||||||
|
|
||||||
pub fn init(common: *protocol.Surface) void {
|
pub fn init(common: *protocol.Surface) void {
|
||||||
const surface = c.gtk_native_get_surface(@ptrCast(common.gtk_window)) orelse return;
|
const surface = c.gtk_native_get_surface(@ptrCast(common.gtk_window)) orelse return;
|
||||||
|
|
||||||
@ -140,22 +144,80 @@ pub const Surface = struct {
|
|||||||
) == 0)
|
) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var blur_region: Region = .{};
|
||||||
|
|
||||||
|
if ((comptime adwaita.versionAtLeast(0, 0, 0)) and common.derived_config.adw_enabled) {
|
||||||
|
// NOTE(pluiedev): CSDs are a f--king mistake.
|
||||||
|
// Please, GNOME, stop this nonsense of making a window ~30% bigger
|
||||||
|
// internally than how they really are just for your shadows and
|
||||||
|
// rounded corners and all that fluff. Please. I beg of you.
|
||||||
|
|
||||||
|
var x: f64, var y: f64 = .{ 0, 0 };
|
||||||
|
c.gtk_native_get_surface_transform(@ptrCast(common.gtk_window), &x, &y);
|
||||||
|
blur_region.x, blur_region.y = .{ @intFromFloat(x), @intFromFloat(y) };
|
||||||
|
}
|
||||||
|
|
||||||
common.inner = .{ .x11 = .{
|
common.inner = .{ .x11 = .{
|
||||||
.common = common,
|
.common = common,
|
||||||
.app = &common.app.inner.x11,
|
.app = &common.app.inner.x11,
|
||||||
.window = c.gdk_x11_surface_get_xid(surface),
|
.window = c.gdk_x11_surface_get_xid(surface),
|
||||||
|
.blur_region = blur_region,
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onConfigUpdate(self: *Surface) !void {
|
pub fn onConfigUpdate(self: *Surface) !void {
|
||||||
_ = self;
|
// Whether background blur is enabled could've changed. Update.
|
||||||
|
try self.updateBlur();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onResize(self: *Surface) !void {
|
pub fn onResize(self: *Surface) !void {
|
||||||
_ = self;
|
// The blur region must update with window resizes
|
||||||
|
self.blur_region.width = c.gtk_widget_get_width(@ptrCast(self.common.gtk_window));
|
||||||
|
self.blur_region.height = c.gtk_widget_get_height(@ptrCast(self.common.gtk_window));
|
||||||
|
try self.updateBlur();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn updateBlur(self: *Surface) !void {
|
fn updateBlur(self: *Surface) !void {
|
||||||
_ = self;
|
// FIXME: This doesn't currently factor in rounded corners on Adwaita,
|
||||||
|
// which means that the blur region will grow slightly outside of the
|
||||||
|
// window borders. Unfortunately, actually calculating the rounded
|
||||||
|
// region can be quite complex without having access to existing APIs
|
||||||
|
// (cf. https://github.com/cutefishos/fishui/blob/41d4ba194063a3c7fff4675619b57e6ac0504f06/src/platforms/linux/blurhelper/windowblur.cpp#L134)
|
||||||
|
// and I think it's not really noticable enough to justify the effort.
|
||||||
|
// (Wayland also has this visual artifact anyway...)
|
||||||
|
|
||||||
|
const blur = self.common.derived_config.blur;
|
||||||
|
log.debug("set blur={}, window xid={}, region={}", .{ blur, self.window, self.blur_region });
|
||||||
|
|
||||||
|
if (blur.enabled()) {
|
||||||
|
_ = c.XChangeProperty(
|
||||||
|
self.app.display,
|
||||||
|
self.window,
|
||||||
|
self.app.kde_blur_atom,
|
||||||
|
c.XA_CARDINAL,
|
||||||
|
// Despite what you might think, the "32" here does NOT mean
|
||||||
|
// that the data should be in u32s. Instead, they should be
|
||||||
|
// c_longs, which on any 64-bit architecture would be obviously
|
||||||
|
// 64 bits. WTF?!
|
||||||
|
32,
|
||||||
|
c.PropModeReplace,
|
||||||
|
// SAFETY: Region is an extern struct that has the same
|
||||||
|
// representation of 4 c_longs put next to each other.
|
||||||
|
// Therefore, reinterpretation should be safe.
|
||||||
|
// We don't have to care about endianness either since
|
||||||
|
// Xlib converts it to network byte order for us.
|
||||||
|
@ptrCast(std.mem.asBytes(&self.blur_region)),
|
||||||
|
4,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
_ = c.XDeleteProperty(self.app.display, self.window, self.app.kde_blur_atom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Region = extern struct {
|
||||||
|
x: c_long = 0,
|
||||||
|
y: c_long = 0,
|
||||||
|
width: c_long = 0,
|
||||||
|
height: c_long = 0,
|
||||||
|
};
|
||||||
|
@ -604,7 +604,7 @@ palette: Palette = .{},
|
|||||||
///
|
///
|
||||||
/// Supported on macOS and on some Linux desktop environments, including:
|
/// Supported on macOS and on some Linux desktop environments, including:
|
||||||
///
|
///
|
||||||
/// * KDE Plasma (Wayland only)
|
/// * KDE Plasma (Wayland and X11)
|
||||||
///
|
///
|
||||||
/// Warning: the exact blur intensity is _ignored_ under KDE Plasma, and setting
|
/// Warning: the exact blur intensity is _ignored_ under KDE Plasma, and setting
|
||||||
/// this setting to either `true` or any positive blur intensity value would
|
/// this setting to either `true` or any positive blur intensity value would
|
||||||
|
Reference in New Issue
Block a user