mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
gtk(wayland): add support for background blur on KDE Plasma
This commit is contained in:

committed by
Mitchell Hashimoto

parent
31439f311d
commit
9184395cba
@ -1479,7 +1479,14 @@ fn addDeps(
|
||||
|
||||
const wayland = b.createModule(.{ .root_source_file = scanner.result });
|
||||
|
||||
const plasma_wayland_protocols = b.dependency("plasma_wayland_protocols", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
scanner.addCustomProtocol(plasma_wayland_protocols.path("src/protocols/blur.xml"));
|
||||
|
||||
scanner.generate("wl_compositor", 1);
|
||||
scanner.generate("org_kde_kwin_blur_manager", 1);
|
||||
|
||||
step.root_module.addImport("wayland", wayland);
|
||||
step.linkSystemLibrary2("wayland-client", dynamic_link_opts);
|
||||
|
@ -847,9 +847,11 @@ fn configChange(
|
||||
new_config: *const Config,
|
||||
) void {
|
||||
switch (target) {
|
||||
// We don't do anything for surface config change events. There
|
||||
// is nothing to sync with regards to a surface today.
|
||||
.surface => {},
|
||||
.surface => |surface| {
|
||||
if (surface.rt_surface.container.window()) |window| window.syncAppearance(new_config) catch |err| {
|
||||
log.warn("error syncing appearance changes to window err={}", .{err});
|
||||
};
|
||||
},
|
||||
|
||||
.app => {
|
||||
// We clone (to take ownership) and update our configuration.
|
||||
|
@ -392,6 +392,17 @@ pub fn init(self: *Window, app: *App) !void {
|
||||
c.gtk_widget_show(window);
|
||||
}
|
||||
|
||||
/// Updates appearance based on config settings. Will be called once upon window
|
||||
/// realization, and every time the config is reloaded.
|
||||
///
|
||||
/// TODO: Many of the initial style settings in `create` could possibly be made
|
||||
/// reactive by moving them here.
|
||||
pub fn syncAppearance(self: *Window, config: *const configpkg.Config) !void {
|
||||
if (self.wayland) |*wl| {
|
||||
try wl.setBlur(config.@"background-blur-radius" > 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets up the GTK actions for the window scope. Actions are how GTK handles
|
||||
/// menus and such. The menu is defined in App.zig but the action is defined
|
||||
/// here. The string name binds them.
|
||||
@ -565,6 +576,10 @@ fn gtkRealize(v: *c.GtkWindow, ud: ?*anyopaque) callconv(.C) bool {
|
||||
self.wayland = wayland.SurfaceState.init(v, wl);
|
||||
}
|
||||
|
||||
self.syncAppearance(&self.app.config) catch |err| {
|
||||
log.err("failed to initialize appearance={}", .{err});
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ const std = @import("std");
|
||||
const c = @import("c.zig").c;
|
||||
const wayland = @import("wayland");
|
||||
const wl = wayland.client.wl;
|
||||
const org = wayland.client.org;
|
||||
const build_options = @import("build_options");
|
||||
|
||||
const log = std.log.scoped(.gtk_wayland);
|
||||
@ -9,6 +10,7 @@ const log = std.log.scoped(.gtk_wayland);
|
||||
/// Wayland state that contains application-wide Wayland objects (e.g. wl_display).
|
||||
pub const AppState = struct {
|
||||
display: *wl.Display,
|
||||
blur_manager: ?*org.KdeKwinBlurManager = null,
|
||||
|
||||
pub fn init(display: ?*c.GdkDisplay) ?AppState {
|
||||
if (comptime !build_options.wayland) return null;
|
||||
@ -45,6 +47,9 @@ pub const SurfaceState = struct {
|
||||
app_state: *AppState,
|
||||
surface: *wl.Surface,
|
||||
|
||||
/// A token that, when present, indicates that the window is blurred.
|
||||
blur_token: ?*org.KdeKwinBlur = null,
|
||||
|
||||
pub fn init(window: *c.GtkWindow, app_state: *AppState) ?SurfaceState {
|
||||
if (comptime !build_options.wayland) return null;
|
||||
|
||||
@ -66,6 +71,32 @@ pub const SurfaceState = struct {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *SurfaceState) void {
|
||||
if (self.blur_token) |blur| blur.release();
|
||||
}
|
||||
|
||||
pub fn setBlur(self: *SurfaceState, blurred: bool) !void {
|
||||
log.debug("setting blur={}", .{blurred});
|
||||
|
||||
const mgr = self.app_state.blur_manager orelse {
|
||||
log.warn("can't set blur: org_kde_kwin_blur_manager protocol unavailable", .{});
|
||||
return;
|
||||
};
|
||||
|
||||
if (self.blur_token) |blur| {
|
||||
// Only release token when transitioning from blurred -> not blurred
|
||||
if (!blurred) {
|
||||
mgr.unset(self.surface);
|
||||
blur.release();
|
||||
self.blur_token = null;
|
||||
}
|
||||
} else {
|
||||
// Only acquire token when transitioning from not blurred -> blurred
|
||||
if (blurred) {
|
||||
const blur_token = try mgr.create(self.surface);
|
||||
blur_token.commit();
|
||||
self.blur_token = blur_token;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -73,6 +104,10 @@ fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, state: *Ap
|
||||
switch (event) {
|
||||
.global => |global| {
|
||||
log.debug("got global interface={s}", .{global.interface});
|
||||
if (bindInterface(org.KdeKwinBlurManager, registry, global, 1)) |iface| {
|
||||
state.blur_manager = iface;
|
||||
return;
|
||||
}
|
||||
},
|
||||
.global_remove => {},
|
||||
}
|
||||
|
@ -583,11 +583,27 @@ palette: Palette = .{},
|
||||
@"background-opacity": f64 = 1.0,
|
||||
|
||||
/// A positive value enables blurring of the background when background-opacity
|
||||
/// is less than 1. The value is the blur radius to apply. A value of 20
|
||||
/// is less than 1.
|
||||
///
|
||||
/// On macOS, the value is the blur radius to apply. A value of 20
|
||||
/// is reasonable for a good looking blur. Higher values will cause strange
|
||||
/// rendering issues as well as performance issues.
|
||||
///
|
||||
/// This is only supported on macOS.
|
||||
/// On KDE Plasma under Wayland, the exact value is _ignored_ — the reason is
|
||||
/// that KWin, the window compositor powering Plasma, only has one global blur
|
||||
/// setting and does not allow applications to have individual blur settings.
|
||||
///
|
||||
/// To configure KWin's global blur setting, open System Settings and go to
|
||||
/// "Apps & Windows" > "Window Management" > "Desktop Effects" and select the
|
||||
/// "Blur" plugin. If disabled, enable it by ticking the checkbox to the left.
|
||||
/// Then click on the "Configure" button and there will be two sliders that
|
||||
/// allow you to set background blur and noise strengths for all apps,
|
||||
/// including Ghostty.
|
||||
///
|
||||
/// All other Linux desktop environments are as of now unsupported. Users may
|
||||
/// need to set environment-specific settings and/or install third-party plugins
|
||||
/// in order to support background blur, as there isn't a unified interface for
|
||||
/// doing so.
|
||||
@"background-blur-radius": u8 = 0,
|
||||
|
||||
/// The opacity level (opposite of transparency) of an unfocused split.
|
||||
|
Reference in New Issue
Block a user