gtk: various blur-related fixes (#10727)

This commit is contained in:
Leah Amelia Chen
2026-03-20 14:54:21 +00:00
committed by GitHub
13 changed files with 355 additions and 130 deletions

View File

@@ -91,8 +91,8 @@
.lazy = true,
},
.wayland_protocols = .{
.url = "https://deps.files.ghostty.org/wayland-protocols-258d8f88f2c8c25a830c6316f87d23ce1a0f12d9.tar.gz",
.hash = "N-V-__8AAKw-DAAaV8bOAAGqA0-oD7o-HNIlPFYKRXSPT03S",
.url = "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz",
.hash = "N-V-__8AAFdWDwA0ktbNUi9pFBHCRN4weXIgIfCrVjfGxqgA",
.lazy = true,
},
.plasma_wayland_protocols = .{

5
build.zig.zon.json generated
View File

@@ -139,6 +139,11 @@
"url": "https://deps.files.ghostty.org/wayland-protocols-258d8f88f2c8c25a830c6316f87d23ce1a0f12d9.tar.gz",
"hash": "sha256-XO3K3egbdeYPI+XoO13SuOtO+5+Peb16NH0UiusFMPg="
},
"N-V-__8AAFdWDwA0ktbNUi9pFBHCRN4weXIgIfCrVjfGxqgA": {
"name": "wayland_protocols",
"url": "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz",
"hash": "sha256-3S3xSrX0EDgleq7cxLX7msDuAY8/D5SvkJcCjmDTMiM="
},
"N-V-__8AAAzZywE3s51XfsLbP9eyEw57ae9swYB9aGB6fCMs": {
"name": "wuffs",
"url": "https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz",

8
build.zig.zon.nix generated
View File

@@ -306,6 +306,14 @@ in
hash = "sha256-XO3K3egbdeYPI+XoO13SuOtO+5+Peb16NH0UiusFMPg=";
};
}
{
name = "N-V-__8AAFdWDwA0ktbNUi9pFBHCRN4weXIgIfCrVjfGxqgA";
path = fetchZigArtifact {
name = "wayland_protocols";
url = "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz";
hash = "sha256-3S3xSrX0EDgleq7cxLX7msDuAY8/D5SvkJcCjmDTMiM=";
};
}
{
name = "N-V-__8AAAzZywE3s51XfsLbP9eyEw57ae9swYB9aGB6fCMs";
path = fetchZigArtifact {

1
build.zig.zon.txt generated
View File

@@ -34,3 +34,4 @@ https://deps.files.ghostty.org/zig_wayland-1b5c038ec10da20ed3a15b0b2a6db1c21383e
https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz
https://github.com/ivanstepanovftw/zigimg/archive/d7b7ab0ba0899643831ef042bd73289510b39906.tar.gz
https://github.com/ocornut/imgui/archive/refs/tags/v1.92.5-docking.tar.gz
https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz

View File

@@ -167,6 +167,12 @@
"dest": "vendor/p/N-V-__8AAKw-DAAaV8bOAAGqA0-oD7o-HNIlPFYKRXSPT03S",
"sha256": "5cedcadde81b75e60f23e5e83b5dd2b8eb4efb9f8f79bd7a347d148aeb0530f8"
},
{
"type": "archive",
"url": "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/1.47/wayland-protocols-1.47.tar.gz",
"dest": "vendor/p/N-V-__8AAFdWDwA0ktbNUi9pFBHCRN4weXIgIfCrVjfGxqgA",
"sha256": "dd2df14ab5f41038257aaedcc4b5fb9ac0ee018f3f0f94af9097028e60d33223"
},
{
"type": "archive",
"url": "https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz",

View File

@@ -1071,21 +1071,6 @@ pub const Window = extern struct {
self.syncAppearance();
}
fn propGdkSurfaceHeight(
_: *gdk.Surface,
_: *gobject.ParamSpec,
self: *Self,
) callconv(.c) void {
// X11 needs to fix blurring on resize, but winproto implementations
// could do anything.
self.private().winproto.resizeEvent() catch |err| {
log.warn(
"winproto resize event failed error={}",
.{err},
);
};
}
fn propIsActive(
_: *gtk.Window,
_: *gobject.ParamSpec,
@@ -1111,7 +1096,7 @@ pub const Window = extern struct {
};
}
fn propGdkSurfaceWidth(
fn propGdkSurfaceDims(
_: *gdk.Surface,
_: *gobject.ParamSpec,
self: *Self,
@@ -1250,7 +1235,7 @@ pub const Window = extern struct {
fn finalize(self: *Self) callconv(.c) void {
const priv = self.private();
priv.tab_bindings.unref();
priv.winproto.deinit(Application.default().allocator());
priv.winproto.deinit();
gobject.Object.virtual_methods.finalize.call(
Class.parent,
@@ -1282,14 +1267,14 @@ pub const Window = extern struct {
_ = gobject.Object.signals.notify.connect(
gdk_surface,
*Self,
propGdkSurfaceWidth,
propGdkSurfaceDims,
self,
.{ .detail = "width" },
);
_ = gobject.Object.signals.notify.connect(
gdk_surface,
*Self,
propGdkSurfaceHeight,
propGdkSurfaceDims,
self,
.{ .detail = "height" },
);

View File

@@ -117,9 +117,9 @@ pub const Window = union(Protocol) {
};
}
pub fn deinit(self: *Window, alloc: Allocator) void {
pub fn deinit(self: *Window) void {
switch (self.*) {
inline else => |*v| v.deinit(alloc),
inline else => |*v| v.deinit(),
}
}

View File

@@ -0,0 +1,187 @@
const BlurRegion = @This();
const std = @import("std");
const Allocator = std.mem.Allocator;
const gobject = @import("gobject");
const gdk = @import("gdk");
const gtk = @import("gtk");
const Window = @import("../winproto.zig").Window;
const ApprtWindow = @import("../class/window.zig").Window;
slices: std.ArrayList(Slice),
/// A rectangular slice of the blur region.
// Marked `extern` since we want to be able to use this in X11 directly.
pub const Slice = extern struct {
x: Pos,
y: Pos,
width: Pos,
height: Pos,
};
// X11 compatibility. Ideally this should just be an `i32` like Wayland,
// but XLib sucks
const Pos = c_long;
pub const empty: BlurRegion = .{
.slices = .empty,
};
pub fn deinit(self: *BlurRegion, alloc: Allocator) void {
self.slices.deinit(alloc);
self.slices = .empty;
}
// Calculate the blur regions for a window.
//
// Since we have rounded corners by default, we need to carve out the
// pixels on each corner to avoid the "korners bug".
// (cf. https://github.com/cutefishos/fishui/blob/41d4ba194063a3c7fff4675619b57e6ac0504f06/src/platforms/linux/blurhelper/windowblur.cpp#L134)
pub fn calcForWindow(
alloc: Allocator,
window: *ApprtWindow,
csd: bool,
to_device_coordinates: bool,
) Allocator.Error!BlurRegion {
const native = window.as(gtk.Native);
const surface = native.getSurface() orelse return .empty;
var slices: std.ArrayList(Slice) = .empty;
errdefer slices.deinit(alloc);
// Calculate the primary blur region
// (the one that covers most of the screen).
// It's easier to do this inside a vector since we have to scale
// everything by the scale factor anyways.
// 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.
const x: Pos, const y: Pos = off: {
var x: f64 = 0;
var y: f64 = 0;
native.getSurfaceTransform(&x, &y);
// Slightly inset the corners if we're using CSDs
if (csd) {
x += 1;
y += 1;
}
break :off .{ @intFromFloat(x), @intFromFloat(y) };
};
var width = @as(Pos, surface.getWidth());
var height = @as(Pos, surface.getHeight());
// Trim off the offsets. Be careful not to get negative.
width -= x * 2;
height -= y * 2;
if (width <= 0 or height <= 0) return .empty;
// Empirically determined.
const are_corners_rounded = rounded: {
// This cast should always succeed as all of our windows
// should be toplevel. If this fails, something very strange
// is going on.
const toplevel = gobject.ext.cast(
gdk.Toplevel,
surface,
) orelse break :rounded false;
const state = toplevel.getState();
if (state.fullscreen or state.maximized or state.tiled)
break :rounded false;
break :rounded csd;
};
const new_slices = try approxRoundedRect(
alloc,
x,
y,
width,
height,
// See https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/css-variables.html#window-radius
if (are_corners_rounded) 15 else 0,
);
if (to_device_coordinates) {
// Transform surface coordinates to device coordinates.
const sf = surface.getScaleFactor();
for (new_slices.items) |*s| {
s.x *= sf;
s.y *= sf;
s.width *= sf;
s.height *= sf;
}
}
return .{ .slices = new_slices };
}
/// Whether two sets of blur regions are equal.
pub fn eql(self: BlurRegion, other: BlurRegion) bool {
if (self.slices.items.len != other.slices.items.len) return false;
for (self.slices.items, other.slices.items) |this, that| {
if (!std.meta.eql(this, that)) return false;
}
return true;
}
/// Approximate a rounded rectangle with many smaller rectangles.
fn approxRoundedRect(
alloc: Allocator,
x: Pos,
y: Pos,
width: Pos,
height: Pos,
radius: Pos,
) Allocator.Error!std.ArrayList(Slice) {
const r_f: f32 = @floatFromInt(radius);
var slices: std.ArrayList(Slice) = .empty;
errdefer slices.deinit(alloc);
// Add the central rectangle
try slices.append(alloc, .{
.x = x,
.y = y + radius,
.width = width,
.height = height - 2 * radius,
});
// Add the corner rows. This is honestly quite cursed.
var row: Pos = 0;
while (row < radius) : (row += 1) {
// y distance from this row to the center corner circle
const dy = @as(f32, @floatFromInt(radius - row)) - 0.5;
// x distance - as given by the definition of a circle
const dx = @sqrt(r_f * r_f - dy * dy);
// How much each row should be offset, rounded to an integer
const row_x: Pos = @intFromFloat(r_f - @round(dx + 0.5));
// Remove the offset from both ends
const row_w = width - 2 * row_x;
// Top slice
try slices.append(alloc, .{
.x = x + row_x,
.y = y + row,
.width = row_w,
.height = 1,
});
// Bottom slice
try slices.append(alloc, .{
.x = x + row_x,
.y = y + height - 1 - row,
.width = row_w,
.height = 1,
});
}
return slices;
}

View File

@@ -46,9 +46,8 @@ pub const Window = struct {
return .{};
}
pub fn deinit(self: Window, alloc: Allocator) void {
pub fn deinit(self: *Window) void {
_ = self;
_ = alloc;
}
pub fn updateConfigEvent(

View File

@@ -10,6 +10,7 @@ const layer_shell = @import("gtk4-layer-shell");
const wayland = @import("wayland");
const wl = wayland.client.wl;
const ext = wayland.client.ext;
const kde = wayland.client.kde;
const org = wayland.client.org;
const xdg = wayland.client.xdg;
@@ -18,6 +19,7 @@ const Config = @import("../../../config.zig").Config;
const Globals = @import("wayland/Globals.zig");
const input = @import("../../../input.zig");
const ApprtWindow = @import("../class/window.zig").Window;
const BlurRegion = @import("BlurRegion.zig");
const log = std.log.scoped(.winproto_wayland);
@@ -96,8 +98,8 @@ pub const Window = struct {
/// The context from the app where we can load our Wayland interfaces.
globals: *Globals,
/// A token that, when present, indicates that the window is blurred.
blur_token: ?*org.KdeKwinBlur = null,
/// Object that controls background effects like background blur.
bg_effect: ?*ext.BackgroundEffectSurfaceV1 = null,
/// Object that controls the decoration mode (client/server/auto)
/// of the window.
@@ -111,6 +113,8 @@ pub const Window = struct {
/// requesting attention from the user.
activation_token: ?*xdg.ActivationTokenV1 = null,
blur_region: BlurRegion = .empty,
pub fn init(
alloc: Allocator,
app: *App,
@@ -148,6 +152,20 @@ pub const Window = struct {
break :deco deco;
};
const bg_effect: ?*ext.BackgroundEffectSurfaceV1 = bg: {
const mgr = app.globals.get(.ext_background_effect) orelse
break :bg null;
const bg_effect: *ext.BackgroundEffectSurfaceV1 = mgr.getBackgroundEffect(
wl_surface,
) catch |err| {
log.warn("could not create background effect object={}", .{err});
break :bg null;
};
break :bg bg_effect;
};
if (apprt_window.isQuickTerminal()) {
_ = gdk.Surface.signals.enter_monitor.connect(
gdk_surface,
@@ -163,24 +181,29 @@ pub const Window = struct {
.surface = wl_surface,
.globals = app.globals,
.decoration = deco,
.bg_effect = bg_effect,
};
}
pub fn deinit(self: Window, alloc: Allocator) void {
_ = alloc;
if (self.blur_token) |blur| blur.release();
pub fn deinit(self: *Window) void {
self.blur_region.deinit(self.globals.alloc);
if (self.bg_effect) |bg| bg.destroy();
if (self.decoration) |deco| deco.release();
if (self.slide) |slide| slide.release();
}
pub fn resizeEvent(_: *Window) !void {}
pub fn resizeEvent(self: *Window) !void {
self.syncBlur() catch |err| {
log.err("failed to sync blur={}", .{err});
};
}
pub fn syncAppearance(self: *Window) !void {
self.syncBlur() catch |err| {
log.err("failed to sync blur={}", .{err});
};
self.syncDecoration() catch |err| {
log.err("failed to sync blur={}", .{err});
log.err("failed to sync decoration={}", .{err});
};
if (self.apprt_window.isQuickTerminal()) {
@@ -224,28 +247,47 @@ pub const Window = struct {
/// Update the blur state of the window.
fn syncBlur(self: *Window) !void {
const manager = self.globals.get(.kde_blur_manager) orelse return;
const compositor = self.globals.get(.compositor) orelse return;
const bg = self.bg_effect orelse return;
if (!self.globals.state.bg_effect_capabilities.blur) return;
const config = if (self.apprt_window.getConfig()) |v|
v.get()
else
return;
const blur = config.@"background-blur";
if (self.blur_token) |tok| {
// Only release token when transitioning from blurred -> not blurred
if (!blur.enabled()) {
manager.unset(self.surface);
tok.release();
self.blur_token = null;
}
} else {
// Only acquire token when transitioning from not blurred -> blurred
if (blur.enabled()) {
const tok = try manager.create(self.surface);
tok.commit();
self.blur_token = tok;
}
if (!blur.enabled()) {
self.blur_region.deinit(self.globals.alloc);
bg.setBlurRegion(null);
return;
}
var region: BlurRegion = try .calcForWindow(
self.globals.alloc,
self.apprt_window,
self.clientSideDecorationEnabled(),
false,
);
errdefer region.deinit(self.globals.alloc);
if (region.eql(self.blur_region)) {
// Region didn't change. Don't do anything.
region.deinit(self.globals.alloc);
return;
}
const wl_region = try compositor.createRegion();
errdefer if (wl_region) |r| r.destroy();
for (region.slices.items) |s| wl_region.add(
@intCast(s.x),
@intCast(s.y),
@intCast(s.width),
@intCast(s.height),
);
bg.setBlurRegion(wl_region);
self.blur_region = region;
}
fn syncDecoration(self: *Window) !void {

View File

@@ -5,6 +5,7 @@ const Allocator = std.mem.Allocator;
const wayland = @import("wayland");
const wl = wayland.client.wl;
const ext = wayland.client.ext;
const kde = wayland.client.kde;
const org = wayland.client.org;
const xdg = wayland.client.xdg;
@@ -26,7 +27,8 @@ const Binding = struct {
};
pub const Tag = enum {
kde_blur_manager,
compositor,
ext_background_effect,
kde_decoration_manager,
kde_slide_manager,
kde_output_order,
@@ -34,7 +36,8 @@ pub const Tag = enum {
fn Type(comptime self: Tag) type {
return switch (self) {
.kde_blur_manager => org.KdeKwinBlurManager,
.compositor => wl.Compositor,
.ext_background_effect => ext.BackgroundEffectManagerV1,
.kde_decoration_manager => org.KdeKwinServerDecorationManager,
.kde_slide_manager => org.KdeKwinSlideManager,
.kde_output_order => kde.OutputOrderV1,
@@ -56,6 +59,8 @@ pub const State = struct {
default_deco_mode: ?org.KdeKwinServerDecorationManager.Mode = null,
bg_effect_capabilities: ext.BackgroundEffectManagerV1.Capability = .{},
/// Reset cached state derived from kde_output_order_v1.
fn resetOutputOrder(self: *State, alloc: Allocator) void {
if (self.primary_output_name) |name| alloc.free(name);
@@ -102,6 +107,11 @@ fn onGlobalAttached(self: *Globals, comptime tag: Tag) void {
// keeps listener setup and object lifetime in one
// place and also supports globals that appear later.
switch (tag) {
.ext_background_effect => {
const v = self.get(tag) orelse return;
v.setListener(*Globals, bgEffectListener, self);
self.needs_roundtrip = true;
},
.kde_decoration_manager => {
const v = self.get(tag) orelse return;
v.setListener(*Globals, decoManagerListener, self);
@@ -179,6 +189,18 @@ fn registryListener(
}
}
fn bgEffectListener(
_: *ext.BackgroundEffectManagerV1,
event: ext.BackgroundEffectManagerV1.Event,
self: *Globals,
) void {
switch (event) {
.capabilities => |cap| {
self.state.bg_effect_capabilities = cap.flags;
},
}
}
fn decoManagerListener(
_: *org.KdeKwinServerDecorationManager,
event: org.KdeKwinServerDecorationManager.Event,

View File

@@ -19,6 +19,7 @@ pub const c = @cImport({
const input = @import("../../../input.zig");
const Config = @import("../../../config.zig").Config;
const ApprtWindow = @import("../class/window.zig").Window;
const BlurRegion = @import("BlurRegion.zig");
const log = std.log.scoped(.gtk_x11);
@@ -169,13 +170,13 @@ pub const Window = struct {
app: *App,
apprt_window: *ApprtWindow,
x11_surface: *gdk_x11.X11Surface,
alloc: Allocator,
blur_region: Region = .{},
blur_region: BlurRegion = .empty,
// Cache last applied values to avoid redundant X11 property updates.
// Redundant property updates seem to cause some visual glitches
// with some window managers: https://github.com/ghostty-org/ghostty/pull/8075
last_applied_blur_region: ?Region = null,
last_applied_decoration_hints: ?MotifWMHints = null,
pub fn init(
@@ -183,8 +184,6 @@ pub const Window = struct {
app: *App,
apprt_window: *ApprtWindow,
) !Window {
_ = alloc;
const surface = apprt_window.as(gtk.Native).getSurface() orelse
return error.NotX11Surface;
@@ -195,49 +194,31 @@ pub const Window = struct {
return .{
.app = app,
.alloc = alloc,
.apprt_window = apprt_window,
.x11_surface = x11_surface,
};
}
pub fn deinit(self: Window, alloc: Allocator) void {
_ = self;
_ = alloc;
pub fn deinit(self: *Window) void {
self.blur_region.deinit(self.alloc);
}
pub fn resizeEvent(self: *Window) !void {
// The blur region must update with window resizes
try self.syncBlur();
self.syncBlur() catch |err| {
log.err("failed to sync blur={}", .{err});
};
}
pub fn syncAppearance(self: *Window) !void {
// The user could have toggled between CSDs and SSDs,
// therefore we need to recalculate the blur region offset.
self.blur_region = blur: {
// 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 = 0;
var y: f64 = 0;
self.apprt_window.as(gtk.Native).getSurfaceTransform(&x, &y);
// Transform surface coordinates to device coordinates.
const scale: f64 = @floatFromInt(self.apprt_window.as(gtk.Widget).getScaleFactor());
x *= scale;
y *= scale;
break :blur .{
.x = @intFromFloat(x),
.y = @intFromFloat(y),
};
};
self.syncBlur() catch |err| {
log.err("failed to synchronize blur={}", .{err});
log.err("failed to sync blur={}", .{err});
};
self.syncDecorations() catch |err| {
log.err("failed to synchronize decorations={}", .{err});
log.err("failed to sync decorations={}", .{err});
};
}
@@ -249,53 +230,49 @@ pub const Window = struct {
}
fn syncBlur(self: *Window) !void {
// 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 noticeable enough to justify the effort.
// (Wayland also has this visual artifact anyway...)
const gtk_widget = self.apprt_window.as(gtk.Widget);
const config = if (self.apprt_window.getConfig()) |v| v.get() else return;
// When blur is disabled, remove the property if it was previously set
const blur = config.@"background-blur";
if (!blur.enabled()) {
if (self.last_applied_blur_region != null) {
try self.deleteProperty(self.app.atoms.kde_blur);
self.last_applied_blur_region = null;
}
var region: BlurRegion = if (blur.enabled())
try .calcForWindow(
self.alloc,
self.apprt_window,
self.clientSideDecorationEnabled(),
true,
)
else
.empty;
errdefer region.deinit(self.alloc);
// Only update X11 properties when the blur region actually changes
if (region.eql(self.blur_region)) {
region.deinit(self.alloc);
return;
}
// Transform surface coordinates to device coordinates.
const scale = gtk_widget.getScaleFactor();
self.blur_region.width = gtk_widget.getWidth() * scale;
self.blur_region.height = gtk_widget.getHeight() * scale;
if (region.slices.items.len > 0) {
log.debug("set blur={}, window xid={}, region={}", .{
blur,
self.x11_surface.getXid(),
region,
});
// Only update X11 properties when the blur region actually changes
if (self.last_applied_blur_region) |last| {
if (std.meta.eql(self.blur_region, last)) return;
try self.changeProperty(
BlurRegion.Slice,
self.app.atoms.kde_blur,
c.XA_CARDINAL,
._32,
.{ .mode = .replace },
region.slices.items,
);
} else {
try self.deleteProperty(self.app.atoms.kde_blur);
}
log.debug("set blur={}, window xid={}, region={}", .{
blur,
self.x11_surface.getXid(),
self.blur_region,
});
try self.changeProperty(
Region,
self.app.atoms.kde_blur,
c.XA_CARDINAL,
._32,
.{ .mode = .replace },
&self.blur_region,
);
self.last_applied_blur_region = self.blur_region;
self.blur_region.deinit(self.alloc);
self.blur_region = region;
}
fn syncDecorations(self: *Window) !void {
@@ -335,7 +312,7 @@ pub const Window = struct {
self.app.atoms.motif_wm_hints,
._32,
.{ .mode = .replace },
&hints,
&.{hints},
);
self.last_applied_decoration_hints = hints;
}
@@ -410,9 +387,11 @@ pub const Window = struct {
options: struct {
mode: PropertyChangeMode,
},
value: *T,
values: []const T,
) X11Error!void {
const data: format.bufferType() = @ptrCast(value);
const data: format.bufferType() = @ptrCast(@constCast(values));
// The number of "words" that each element `T` occupies.
const words_per_elem = @divExact(@sizeOf(T), @sizeOf(format.elemType()));
const status = c.XChangeProperty(
@ptrCast(@alignCast(self.app.display)),
@@ -422,7 +401,7 @@ pub const Window = struct {
@intFromEnum(format),
@intFromEnum(options.mode),
data,
@divExact(@sizeOf(T), @sizeOf(format.elemType())),
@intCast(words_per_elem * values.len),
);
// For some godforsaken reason Xlib alternates between
@@ -498,13 +477,6 @@ const PropertyFormat = enum(c_int) {
}
};
const Region = extern struct {
x: c_long = 0,
y: c_long = 0,
width: c_long = 0,
height: c_long = 0,
};
// See Xm/MwmUtil.h, packaged with the Motif Window Manager
const MotifWMHints = extern struct {
flags: packed struct(c_ulong) {

View File

@@ -626,9 +626,6 @@ fn addGtkNg(
.wayland_protocols = wayland_protocols_dep.path(""),
});
scanner.addCustomProtocol(
plasma_wayland_protocols_dep.path("src/protocols/blur.xml"),
);
// FIXME: replace with `zxdg_decoration_v1` once GTK merges https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6398
scanner.addCustomProtocol(
plasma_wayland_protocols_dep.path("src/protocols/server-decoration.xml"),
@@ -640,13 +637,14 @@ fn addGtkNg(
plasma_wayland_protocols_dep.path("src/protocols/kde-output-order-v1.xml"),
);
scanner.addSystemProtocol("staging/xdg-activation/xdg-activation-v1.xml");
scanner.addSystemProtocol("staging/ext-background-effect/ext-background-effect-v1.xml");
scanner.generate("wl_compositor", 1);
scanner.generate("org_kde_kwin_blur_manager", 1);
scanner.generate("org_kde_kwin_server_decoration_manager", 1);
scanner.generate("org_kde_kwin_slide_manager", 1);
scanner.generate("kde_output_order_v1", 1);
scanner.generate("xdg_activation_v1", 1);
scanner.generate("ext_background_effect_manager_v1", 1);
step.root_module.addImport("wayland", b.createModule(.{
.root_source_file = scanner.result,