@@ -17,6 +17,7 @@ const blur = @import("blur.zig");
1717const wl = wayland .client .wl ;
1818const org = wayland .client .org ;
1919const xdg = wayland .client .xdg ;
20+ const ext = wayland .client .ext ;
2021
2122const log = std .log .scoped (.winproto_wayland );
2223
@@ -30,6 +31,9 @@ pub const App = struct {
3031
3132 kde_blur_manager : ? * org.KdeKwinBlurManager = null ,
3233
34+ ext_bg_effect_manager : ? * ext.BackgroundEffectManagerV1 = null ,
35+ ext_bg_capabilities : ext.BackgroundEffectManagerV1.Capability = .{},
36+
3337 // FIXME: replace with `zxdg_decoration_v1` once GTK merges
3438 // https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6398
3539 kde_decoration_manager : ? * org.KdeKwinServerDecorationManager = null ,
@@ -86,9 +90,19 @@ pub const App = struct {
8690 registry .setListener (* Context , registryListener , context );
8791 if (display .roundtrip () != .SUCCESS ) return error .RoundtripFailed ;
8892
89- // Do another round-trip to get the default decoration mode
93+ // Sometimes we need to do another roundtrip
94+ // to get all information we need.
95+ var needs_roundtrip = false ;
9096 if (context .kde_decoration_manager ) | deco_manager | {
9197 deco_manager .setListener (* Context , decoManagerListener , context );
98+ needs_roundtrip = true ;
99+ }
100+ if (context .ext_bg_effect_manager ) | mgr | {
101+ mgr .setListener (* Context , effectManagerListener , context );
102+ needs_roundtrip = true ;
103+ }
104+
105+ if (needs_roundtrip ) {
92106 if (display .roundtrip () != .SUCCESS ) return error .RoundtripFailed ;
93107 }
94108
@@ -224,6 +238,18 @@ pub const App = struct {
224238 },
225239 }
226240 }
241+
242+ fn effectManagerListener (
243+ _ : * ext.BackgroundEffectManagerV1 ,
244+ event : ext.BackgroundEffectManagerV1.Event ,
245+ context : * Context ,
246+ ) void {
247+ switch (event ) {
248+ .capabilities = > | cap | {
249+ context .ext_bg_capabilities = cap .flags ;
250+ },
251+ }
252+ }
227253};
228254
229255/// Per-window (wl_surface) state for the Wayland protocol.
@@ -239,6 +265,9 @@ pub const Window = struct {
239265 /// A token that, when present, indicates that the window is blurred.
240266 blur_token : ? * org.KdeKwinBlur = null ,
241267
268+ /// Object that controls background effects like blur.
269+ bg_effect : ? * ext.BackgroundEffectSurfaceV1 = null ,
270+
242271 /// Object that controls the decoration mode (client/server/auto)
243272 /// of the window.
244273 decoration : ? * org.KdeKwinServerDecoration = null ,
@@ -362,38 +391,55 @@ pub const Window = struct {
362391 /// Update the blur state of the window.
363392 pub fn setBlur (self : * Window , region : blur.Region ) ! void {
364393 const compositor = self .app_context .compositor orelse return ;
365- const manager = self .app_context .kde_blur_manager orelse return ;
366394
367395 const config = if (self .apprt_window .getConfig ()) | v |
368396 v .get ()
369397 else
370398 return ;
371399 const blur_setting = config .@"background-blur" ;
372400
373- if (blur_setting .enabled ()) {
374- // Do we already have a blur token? If not, create one.
375- const token = self .blur_token orelse try manager .create (self .surface );
376- defer self .blur_token = token ;
377-
378- const wl_region = try compositor .createRegion ();
379- errdefer wl_region .destroy ();
380-
381- for (region .slices .items ) | slice | {
382- // X11 coming over to bite Wayland.
383- wl_region .add (
384- @intCast (slice .x ),
385- @intCast (slice .y ),
386- @intCast (slice .width ),
387- @intCast (slice .height ),
388- );
401+ const wl_region = try compositor .createRegion ();
402+ errdefer wl_region .destroy ();
403+
404+ for (region .slices .items ) | slice | {
405+ // X11 coming over to bite Wayland.
406+ wl_region .add (
407+ @intCast (slice .x ),
408+ @intCast (slice .y ),
409+ @intCast (slice .width ),
410+ @intCast (slice .height ),
411+ );
412+ }
413+
414+ // Does the compositor support the `ext-background-effect-v1`
415+ // protocol? If so, try that first, though it might not actually
416+ // support the blur setting.
417+ if (self .app_context .ext_bg_effect_manager ) | mgr | fx : {
418+ if (! self .app_context .ext_bg_capabilities .blur ) break :fx ;
419+
420+ if (blur_setting .enabled ()) {
421+ // Do we already have a blur token? If not, create one.
422+ const effect = self .bg_effect orelse try mgr .getBackgroundEffect (self .surface );
423+ defer self .bg_effect = effect ;
424+ effect .setBlurRegion (wl_region );
425+ } else if (self .bg_effect ) | effect | {
426+ // Destroy the blur token if present.
427+ effect .destroy ();
428+ self .bg_effect = null ;
389429 }
430+ return ;
431+ }
390432
391- token .setRegion (wl_region );
392- token .commit ();
393- } else {
394- // Destroy the blur token if present.
395- if (self .blur_token ) | token | {
396- manager .unset (self .surface );
433+ if (self .app_context .kde_blur_manager ) | mgr | {
434+ if (blur_setting .enabled ()) {
435+ // Do we already have a blur token? If not, create one.
436+ const token = self .blur_token orelse try mgr .create (self .surface );
437+ defer self .blur_token = token ;
438+ token .setRegion (wl_region );
439+ token .commit ();
440+ } else if (self .blur_token ) | token | {
441+ // Destroy the blur token if present.
442+ mgr .unset (self .surface );
397443 token .release ();
398444 self .blur_token = null ;
399445 }
0 commit comments