Compare commits

...

2 Commits

Author SHA1 Message Date
wochap
2aa64763fb docs scenefx 2025-03-12 20:45:37 +00:00
wochap
7e3e98dd7a refactor scenefx patch and apply optimized_blur 2025-03-12 20:39:42 +00:00
2 changed files with 299 additions and 197 deletions

View File

@ -11,26 +11,26 @@ static const float opacity_active = 1.0;
static const int shadow = 1; /* flag to enable shadow */
static const int shadow_only_floating = 0; /* only apply shadow to floating windows */
static const struct wlr_render_color shadow_color = COLOR(0x0000FFff);
static const struct wlr_render_color shadow_color_focus = COLOR(0xFF0000ff);
static const float shadow_color[4] = COLOR(0x0000FFff);
static const float shadow_color_focus[4] = COLOR(0xFF0000ff);
static const int shadow_blur_sigma = 20;
static const int shadow_blur_sigma_focus = 40;
static const char *const shadow_ignore_list[] = { NULL }; /* list of app-id to ignore */
static const int corner_radius = 0; /* 0 disables corner_radius */
static const int corner_radius_inner = 3; /* 0 disables corner_radius */
static const int corner_radius = 8; /* 0 disables corner_radius */
static const int corner_radius_inner = 8; /* 0 disables corner_radius */
static const int corner_radius_only_floating = 0; /* only apply corner_radius and corner_radius_inner to floating windows */
static const int blur = 1; /* flag to enable blur */
static const int blur_optimized = 1;
static const int blur_xray = 0; /* flag to make transparent fs and floating windows display your background */
static const int blur_ignore_transparent = 1;
static const struct blur_data blur_data = {
.radius = 5,
.num_passes = 3,
.noise = 0.02,
.brightness = 0.9,
.contrast = 0.9,
.saturation = 1.1,
.noise = (float)0.02,
.brightness = (float)0.9,
.contrast = (float)0.9,
.saturation = (float)1.1,
};
```
@ -53,7 +53,7 @@ static const struct blur_data blur_data = {
- [0.8](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/scenefx/scenefx.patch)
**NOTE:** This patch was tested with the `87c0e8b6d5c86557a800445e8e4c322f387fe19c` commit on the `main` branch of `SceneFX`. It supports rounded borders, blur, and shadows.
**NOTE:** This patch was tested with the `87c0e8b6d5c86557a800445e8e4c322f387fe19c` commit on the `main` branch of `SceneFX`. It supports rounded borders, blur, and shadows. However, it does not add rounded borders or shadows to Xwayland apps. That said, Xwayland apps can have shadows, and they might also support rounded borders, but I was never able to make it work. PRs are welcome!
**IMPORTANT:** This patch requires you to build DWL with the following dependencies

View File

@ -1,14 +1,14 @@
From 11b587299587b1544b091f5804272d177d1a3dee Mon Sep 17 00:00:00 2001
From d209aeaee541a045de9dba2154bbbd5475bba2ec Mon Sep 17 00:00:00 2001
From: wochap <gean.marroquin@gmail.com>
Date: Sat, 15 Feb 2025 11:14:42 -0500
Subject: [PATCH] implement scenefx-0.2
Date: Sun, 9 Mar 2025 17:26:07 -0500
Subject: [PATCH] implement scenefx
---
Makefile | 2 +-
client.h | 14 ++-
config.def.h | 30 ++++-
dwl.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 380 insertions(+), 10 deletions(-)
client.h | 18 +++
config.def.h | 30 +++-
dwl.c | 414 ++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 457 insertions(+), 7 deletions(-)
diff --git a/Makefile b/Makefile
index 3358bae..8dc79bd 100644
@ -24,39 +24,43 @@ index 3358bae..8dc79bd 100644
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS)
diff --git a/client.h b/client.h
index 42f225f..e3cef30 100644
index 42f225f..4e8f016 100644
--- a/client.h
+++ b/client.h
@@ -136,10 +136,10 @@ client_get_clip(Client *c, struct wlr_box *clip)
{
struct wlr_box xdg_geom = {0};
*clip = (struct wlr_box){
- .x = 0,
- .y = 0,
- .width = c->geom.width - c->bw,
- .height = c->geom.height - c->bw,
@@ -147,6 +147,13 @@ client_get_clip(Client *c, struct wlr_box *clip)
return;
#endif
+ *clip = (struct wlr_box){
+ .x = c->bw,
+ .y = c->bw,
+ .width = c->geom.width - c->bw * 2,
+ .height = c->geom.height - c->bw * 2,
};
#ifdef XWAYLAND
@@ -328,6 +328,12 @@ static inline void
+ };
+
wlr_xdg_surface_get_geometry(c->surface.xdg, &xdg_geom);
clip->x = xdg_geom.x;
clip->y = xdg_geom.y;
@@ -328,6 +335,17 @@ static inline void
client_set_border_color(Client *c, const float color[static 4])
{
int i;
+
+#ifdef XWAYLAND
+ if (!client_is_x11(c)) {
+#endif
+ if (corner_radius > 0) {
+ wlr_scene_rect_set_color(c->round_border, color);
+ return;
+ }
+#ifdef XWAYLAND
+ }
+#endif
+
for (i = 0; i < 4; i++)
wlr_scene_rect_set_color(c->border[i], color);
}
diff --git a/config.def.h b/config.def.h
index 22d2171..4ec6adb 100644
index 22d2171..8c50932 100644
--- a/config.def.h
+++ b/config.def.h
@@ -12,7 +12,35 @@ static const float bordercolor[] = COLOR(0x444444ff);
@ -83,7 +87,7 @@ index 22d2171..4ec6adb 100644
+static const int corner_radius_only_floating = 0; /* only apply corner_radius and corner_radius_inner to floating windows */
+
+static const int blur = 1; /* flag to enable blur */
+static const int blur_optimized = 1;
+static const int blur_xray = 0; /* flag to make transparent fs and floating windows display your background */
+static const int blur_ignore_transparent = 1;
+static const struct blur_data blur_data = {
+ .radius = 5,
@ -97,7 +101,7 @@ index 22d2171..4ec6adb 100644
/* tagging - TAGCOUNT must be no greater than 31 */
#define TAGCOUNT (9)
diff --git a/dwl.c b/dwl.c
index 5bf995e..eb12234 100644
index 5bf995e..655e175 100644
--- a/dwl.c
+++ b/dwl.c
@@ -10,8 +10,14 @@
@ -123,6 +127,15 @@ index 5bf995e..eb12234 100644
#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_server_decoration.h>
@@ -83,7 +88,7 @@
/* enums */
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
enum { XDGShell, LayerShell, X11 }; /* client types */
-enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
+enum { LyrBg, LyrBlur, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
#ifdef XWAYLAND
enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
@@ -141,6 +146,12 @@ typedef struct {
uint32_t tags;
int isfloating, isurgent, isfullscreen;
@ -136,29 +149,34 @@ index 5bf995e..eb12234 100644
} Client;
typedef struct {
@@ -355,6 +366,12 @@ static Monitor *xytomon(double x, double y);
@@ -208,6 +219,7 @@ struct Monitor {
int nmaster;
char ltsymbol[16];
int asleep;
+ struct wlr_scene_optimized_blur *blur_layer;
};
typedef struct {
@@ -355,6 +367,18 @@ static Monitor *xytomon(double x, double y);
static void xytonode(double x, double y, struct wlr_surface **psurface,
Client **pc, LayerSurface **pl, double *nx, double *ny);
static void zoom(const Arg *arg);
+static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data);
+static void iter_xdg_scene_buffers_blur(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data);
+static void iter_xdg_scene_buffers_opacity(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data);
+static void iter_xdg_scene_buffers_corner_radius(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data);
+static void output_configure_scene(struct wlr_scene_node *node, Client *c);
+static int in_shadow_ignore_list(const char *str);
+static void client_set_shadow_blur_sigma(Client *c, int blur_sigma);
+static void update_client_corner_radius(Client *c);
+static void update_client_shadow_color(Client *c);
+static void update_client_focus_decorations(Client *c, int focused, int urgent);
+static void update_client_blur(Client *c);
+static void update_buffer_corner_radius(Client *c, struct wlr_scene_buffer *buffer);
/* variables */
static const char broken[] = "broken";
@@ -366,6 +383,8 @@ static struct wl_event_loop *event_loop;
static struct wlr_backend *backend;
static struct wlr_scene *scene;
static struct wlr_scene_tree *layers[NUM_LAYERS];
+/* TODO: implement wlr_scene_optimized_blur */
+/* static struct wlr_scene_optimized_blur *blur_layer; */
static struct wlr_scene_tree *drag_icon;
/* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */
static const int layermap[] = { LyrBg, LyrBottom, LyrTop, LyrOverlay };
@@ -413,6 +432,8 @@ static struct wlr_box sgeom;
@@ -413,6 +437,8 @@ static struct wlr_box sgeom;
static struct wl_list mons;
static Monitor *selmon;
@ -167,7 +185,62 @@ index 5bf995e..eb12234 100644
#ifdef XWAYLAND
static void activatex11(struct wl_listener *listener, void *data);
static void associatex11(struct wl_listener *listener, void *data);
@@ -1061,6 +1082,9 @@ createnotify(struct wl_listener *listener, void *data)
@@ -499,6 +525,10 @@ arrange(Monitor *m)
wlr_scene_node_set_enabled(&m->fullscreen_bg->node,
(c = focustop(m)) && c->isfullscreen);
+ if (blur) {
+ wlr_scene_node_set_enabled(&m->blur_layer->node, 1);
+ }
+
strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
/* We move all clients (except fullscreen and unmanaged) to LyrTile while
@@ -722,6 +752,11 @@ cleanupmon(struct wl_listener *listener, void *data)
closemon(m);
wlr_scene_node_destroy(&m->fullscreen_bg->node);
+
+ if (blur) {
+ wlr_scene_node_destroy(&m->blur_layer->node);
+ }
+
free(m);
}
@@ -785,6 +820,18 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
}
arrangelayers(l->mon);
+
+ if (blur) {
+ // Rerender the optimized blur on change
+ struct wlr_layer_surface_v1 *wlr_layer_surface = l->layer_surface;
+ if (wlr_layer_surface->current.layer ==
+ ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ||
+ wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
+ if (l->mon) {
+ wlr_scene_optimized_blur_mark_dirty(l->mon->blur_layer);
+ }
+ }
+ }
}
void
@@ -1036,6 +1083,12 @@ createmon(struct wl_listener *listener, void *data)
m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg);
wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0);
+ if (blur) {
+ m->blur_layer = wlr_scene_optimized_blur_create(&scene->tree, 0, 0);
+ wlr_scene_node_reparent(&m->blur_layer->node, layers[LyrBlur]);
+ wlr_scene_node_set_enabled(&m->blur_layer->node, 0);
+ }
+
/* Adds this to the output layout in the order it was configured.
*
* The output layout utility automatically adds a wl_output global to the
@@ -1061,6 +1114,9 @@ createnotify(struct wl_listener *listener, void *data)
c->surface.xdg = toplevel->base;
c->bw = borderpx;
@ -177,7 +250,7 @@ index 5bf995e..eb12234 100644
LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify);
LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify);
LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify);
@@ -1369,8 +1393,20 @@ focusclient(Client *c, int lift)
@@ -1369,8 +1425,11 @@ focusclient(Client *c, int lift)
/* Don't change border color if there is an exclusive focus or we are
* handling a drag operation */
@ -185,87 +258,74 @@ index 5bf995e..eb12234 100644
+ if (!exclusive_focus && !seat->drag) {
client_set_border_color(c, focuscolor);
+
+ if (shadow) {
+ client_set_shadow_blur_sigma(c, (int)round(shadow_blur_sigma_focus));
+ if (c->has_shadow_enabled) {
+ wlr_scene_shadow_set_color(c->shadow, shadow_color_focus);
+ }
+ }
+ if (opacity) {
+ c->opacity = opacity_active;
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_opacity, c);
+ }
+ update_client_focus_decorations(c, 1, 0);
+ }
}
/* Deactivate old client if focus is changing */
@@ -1389,6 +1425,17 @@ focusclient(Client *c, int lift)
@@ -1389,6 +1448,8 @@ focusclient(Client *c, int lift)
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
client_set_border_color(old_c, bordercolor);
+ if (shadow) {
+ client_set_shadow_blur_sigma(old_c, (int)round(shadow_blur_sigma));
+ if (old_c->has_shadow_enabled) {
+ wlr_scene_shadow_set_color(old_c->shadow, shadow_color);
+ }
+ }
+ if (opacity) {
+ old_c->opacity = opacity_inactive;
+ wlr_scene_node_for_each_buffer(&old_c->scene_surface->node, iter_xdg_scene_buffers_opacity, old_c);
+ }
+ update_client_focus_decorations(old_c, 0, 0);
+
client_activate_surface(old, 0);
}
}
@@ -1718,6 +1765,21 @@ mapnotify(struct wl_listener *listener, void *data)
@@ -1718,6 +1779,38 @@ mapnotify(struct wl_listener *listener, void *data)
c->border[i]->node.data = c;
}
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers, c);
+
+#ifdef XWAYLAND
+ if (!client_is_x11(c)) {
+#endif
+ if (corner_radius > 0) {
+ c->round_border = wlr_scene_rect_create(c->scene, 0, 0, c->isurgent ? urgentcolor : bordercolor);
+ c->round_border->node.data = c;
+ /* Lower the border below the XDG scene tree */
+ wlr_scene_node_lower_to_bottom(&c->round_border->node);
+ }
+
+ /* hide original border */
+ for (i = 0; i < 4; i++) {
+ wlr_scene_rect_set_color(c->border[i], transparent);
+ }
+ }
+#ifdef XWAYLAND
+ }
+#endif
+
+#ifdef XWAYLAND
+ if (!client_is_x11(c)) {
+#endif
+ if (shadow) {
+ c->shadow = wlr_scene_shadow_create(c->scene, 0, 0, c->corner_radius, shadow_blur_sigma, shadow_color);
+ /* Lower the shadow below the border */
+ wlr_scene_node_lower_to_bottom(&c->shadow->node);
+ }
+#ifdef XWAYLAND
+ }
+#endif
+
/* Initialize client geometry with room for border */
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
c->geom.width += 2 * c->bw;
@@ -1739,6 +1801,25 @@ mapnotify(struct wl_listener *listener, void *data)
@@ -1739,6 +1832,13 @@ mapnotify(struct wl_listener *listener, void *data)
}
printstatus();
+ if (corner_radius > 0) {
+ int radius = c->corner_radius + c->bw;
+ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) {
+ radius = 0;
+ }
+ wlr_scene_rect_set_corner_radius(c->round_border, radius, CORNER_LOCATION_ALL);
+ }
+ /* TODO: shouldn't we call iter_xdg_scene_buffers_corner_radius? */
+ update_client_corner_radius(c);
+
+ if (shadow) {
+ const float *color = focustop(c->mon) == c ? shadow_color_focus : shadow_color;
+ int has_shadow_enabled = 1;
+ if ((shadow_only_floating && !c->isfloating) || in_shadow_ignore_list(client_get_appid(c)) || c->isfullscreen) {
+ color = transparent;
+ has_shadow_enabled = 0;
+ }
+ wlr_scene_shadow_set_color(c->shadow, color);
+ c->has_shadow_enabled = has_shadow_enabled;
+ }
+ update_client_shadow_color(c);
+
+ update_client_blur(c);
+
unset_fullscreen:
m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
wl_list_for_each(w, &clients, link) {
@@ -2113,6 +2194,8 @@ rendermon(struct wl_listener *listener, void *data)
@@ -2113,6 +2213,8 @@ rendermon(struct wl_listener *listener, void *data)
goto skip;
}
@ -274,21 +334,12 @@ index 5bf995e..eb12234 100644
/*
* HACK: The "correct" way to set the gamma is to commit it together with
* the rest of the state in one go, but to do that we would need to rewrite
@@ -2181,6 +2264,8 @@ resize(Client *c, struct wlr_box geo, int interact)
{
struct wlr_box *bbox;
struct wlr_box clip;
+ int blur_sigma;
+ int i;
if (!c->mon || !c->scene)
return;
@@ -2207,6 +2292,30 @@ resize(Client *c, struct wlr_box geo, int interact)
@@ -2207,6 +2309,21 @@ resize(Client *c, struct wlr_box geo, int interact)
c->geom.height - 2 * c->bw);
client_get_clip(c, &clip);
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
+
+ if (corner_radius > 0) {
+ if (corner_radius > 0 && c->round_border) {
+ wlr_scene_node_set_position(&c->round_border->node, 0, 0);
+ wlr_scene_rect_set_size(c->round_border, c->geom.width, c->geom.height);
+ wlr_scene_rect_set_clipped_region(c->round_border, (struct clipped_region) {
@ -296,91 +347,48 @@ index 5bf995e..eb12234 100644
+ .corners = CORNER_LOCATION_ALL,
+ .area = { c->bw, c->bw, c->geom.width - c->bw * 2, c->geom.height - c->bw * 2 }
+ });
+ /* hide original border */
+ for (i = 0; i < 4; i++)
+ wlr_scene_rect_set_color(c->border[i], transparent);
+ }
+
+ if (shadow) {
+ blur_sigma = (int)round(c->shadow->blur_sigma);
+ wlr_scene_node_set_position(&c->shadow->node, -blur_sigma, -blur_sigma);
+ wlr_scene_shadow_set_size(c->shadow, c->geom.width + blur_sigma * 2, c->geom.height + blur_sigma * 2);
+ wlr_scene_shadow_set_clipped_region(c->shadow, (struct clipped_region) {
+ .corner_radius = c->corner_radius + c->bw,
+ .corners = CORNER_LOCATION_ALL,
+ .area = { blur_sigma, blur_sigma, c->geom.width, c->geom.height }
+ });
+ if (shadow && c->shadow) {
+ /* TODO: shouldn't we call wlr_scene_shadow_set_blur_sigma? */
+ client_set_shadow_blur_sigma(c, (int)round(c->shadow->blur_sigma));
+ }
}
void
@@ -2307,6 +2416,29 @@ setfloating(Client *c, int floating)
@@ -2307,6 +2424,13 @@ setfloating(Client *c, int floating)
{
Client *p = client_get_parent(c);
c->isfloating = floating;
+
+ if (corner_radius > 0 && c->round_border != NULL) {
+ int radius = c->corner_radius + c->bw;
+ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) {
+ radius = 0;
+ }
+ wlr_scene_rect_set_corner_radius(c->round_border, radius, CORNER_LOCATION_ALL);
+ }
+ if (corner_radius_inner > 0 && c->round_border != NULL) {
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_corner_radius, c);
+ }
+ update_client_corner_radius(c);
+
+ if (shadow && c->shadow != NULL) {
+ const float *color = focustop(c->mon) == c ? shadow_color_focus : shadow_color;
+ int has_shadow_enabled = 1;
+ if ((shadow_only_floating && !c->isfloating) || in_shadow_ignore_list(client_get_appid(c)) || c->isfullscreen) {
+ color = transparent;
+ has_shadow_enabled = 0;
+ }
+ wlr_scene_shadow_set_color(c->shadow, color);
+ c->has_shadow_enabled = has_shadow_enabled;
+ }
+ update_client_shadow_color(c);
+
+ update_client_blur(c);
+
/* If in floating layout do not change the client's layer */
if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange)
return;
@@ -2336,6 +2468,29 @@ setfullscreen(Client *c, int fullscreen)
@@ -2336,6 +2460,13 @@ setfullscreen(Client *c, int fullscreen)
* client positions are set by the user and cannot be recalculated */
resize(c, c->prev, 0);
}
+
+ if (corner_radius > 0 && c->round_border != NULL) {
+ int radius = c->corner_radius + c->bw;
+ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) {
+ radius = 0;
+ }
+ wlr_scene_rect_set_corner_radius(c->round_border, radius, CORNER_LOCATION_ALL);
+ }
+ if (corner_radius_inner > 0 && c->round_border != NULL) {
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_corner_radius, c);
+ }
+ update_client_corner_radius(c);
+
+ if (shadow && c->shadow != NULL) {
+ const float *color = focustop(c->mon) == c ? shadow_color_focus : shadow_color;
+ int has_shadow_enabled = 1;
+ if ((shadow_only_floating && !c->isfloating) || in_shadow_ignore_list(client_get_appid(c)) || c->isfullscreen) {
+ color = transparent;
+ has_shadow_enabled = 0;
+ }
+ wlr_scene_shadow_set_color(c->shadow, color);
+ c->has_shadow_enabled = has_shadow_enabled;
+ }
+ update_client_shadow_color(c);
+
+ update_client_blur(c);
+
arrange(c->mon);
printstatus();
}
@@ -2457,11 +2612,17 @@ setup(void)
@@ -2457,11 +2588,15 @@ setup(void)
drag_icon = wlr_scene_tree_create(&scene->tree);
wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node);
+ if (blur) {
+ /* TODO: implement wlr_scene_optimized_blur_create */
+ /* blur_layer = wlr_scene_optimized_blur_create(&scene->tree, 0, 0); */
+ wlr_scene_set_blur_data(scene, blur_data);
+ }
+
@ -393,22 +401,18 @@ index 5bf995e..eb12234 100644
die("couldn't create renderer");
LISTEN_STATIC(&drw->events.lost, gpureset);
@@ -2871,6 +3032,14 @@ updatemons(struct wl_listener *listener, void *data)
@@ -2870,6 +3005,10 @@ updatemons(struct wl_listener *listener, void *data)
wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y);
wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height);
+
+ if (blur) {
+ wlr_scene_optimized_blur_set_size(m->blur_layer, m->m.width, m->m.height);
+ }
+ /*
+ * Sets the blur node size to the outputs size. Assumes there's only one
+ * output. More advanced compositors should either implement per output blur
+ * nodes or set it to the size of all outputs.
+ */
+ /* TODO: implement wlr_scene_optimized_blur_set_size */
+ /* wlr_scene_optimized_blur_set_size(blur_layer, m->wlr_output->width, m->wlr_output->height); */
+
if (m->lock_surface) {
struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data;
wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y);
@@ -2940,8 +3109,16 @@ urgent(struct wl_listener *listener, void *data)
@@ -2940,8 +3079,11 @@ urgent(struct wl_listener *listener, void *data)
c->isurgent = 1;
printstatus();
@ -416,17 +420,12 @@ index 5bf995e..eb12234 100644
+ if (client_surface(c)->mapped) {
client_set_border_color(c, urgentcolor);
+
+ if (shadow && c->shadow != NULL) {
+ client_set_shadow_blur_sigma(c, (int)round(shadow_blur_sigma_focus));
+ if (c->has_shadow_enabled) {
+ wlr_scene_shadow_set_color(c->shadow, shadow_color_focus);
+ }
+ }
+ update_client_focus_decorations(c, 1, 1);
+ }
}
void
@@ -3053,6 +3230,165 @@ zoom(const Arg *arg)
@@ -3053,6 +3195,268 @@ zoom(const Arg *arg)
arrange(selmon);
}
@ -451,15 +450,10 @@ index 5bf995e..eb12234 100644
+ }
+
+ if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) {
+ if (corner_radius_inner > 0) {
+ int radius = corner_radius_inner;
+ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) {
+ radius = 0;
+ }
+ wlr_scene_buffer_set_corner_radius(buffer, radius, CORNER_LOCATION_ALL);
+ }
+ update_buffer_corner_radius(c, buffer);
+
+ if (blur) {
+ int blur_optimized = !c->isfloating || blur_xray;
+ wlr_scene_buffer_set_backdrop_blur(buffer, 1);
+ wlr_scene_buffer_set_backdrop_blur_optimized(buffer, blur_optimized);
+ wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, blur_ignore_transparent);
@ -469,6 +463,29 @@ index 5bf995e..eb12234 100644
+}
+
+void
+iter_xdg_scene_buffers_blur(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data)
+{
+ Client *c = user_data;
+ struct wlr_scene_surface * scene_surface = wlr_scene_surface_try_from_buffer(buffer);
+ struct wlr_xdg_surface *xdg_surface;
+
+ if (!scene_surface) {
+ return;
+ }
+
+ xdg_surface = wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface);
+
+ if (c && xdg_surface && xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
+ if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) {
+ if (blur) {
+ int blur_optimized = !c->isfloating || blur_xray;
+ wlr_scene_buffer_set_backdrop_blur_optimized(buffer, blur_optimized);
+ }
+ }
+ }
+}
+
+void
+iter_xdg_scene_buffers_opacity(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data)
+{
+ Client *c = user_data;
@ -506,13 +523,7 @@ index 5bf995e..eb12234 100644
+ if (c && xdg_surface && xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
+ /* TODO: Be able to set whole decoration_data instead of calling */
+ /* each individually? */
+ if (corner_radius_inner > 0) {
+ int radius = corner_radius_inner;
+ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) {
+ radius = 0;
+ }
+ wlr_scene_buffer_set_corner_radius(buffer, radius, CORNER_LOCATION_ALL);
+ }
+ update_buffer_corner_radius(c, buffer);
+ }
+}
+
@ -548,13 +559,7 @@ index 5bf995e..eb12234 100644
+ }
+
+ if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) {
+ if (corner_radius_inner > 0) {
+ int radius = corner_radius_inner;
+ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) {
+ radius = 0;
+ }
+ wlr_scene_buffer_set_corner_radius(buffer, radius, CORNER_LOCATION_ALL);
+ }
+ update_buffer_corner_radius(c, buffer);
+ }
+ }
+ } else if (node->type == WLR_SCENE_NODE_TREE) {
@ -588,7 +593,104 @@ index 5bf995e..eb12234 100644
+ .area = { blur_sigma, blur_sigma, c->geom.width, c->geom.height }
+ });
+}
+
+void
+update_client_corner_radius(Client *c)
+{
+ if (corner_radius && c->round_border) {
+ int radius = c->corner_radius + c->bw;
+ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) {
+ radius = 0;
+ }
+ wlr_scene_rect_set_corner_radius(c->round_border, radius, CORNER_LOCATION_ALL);
+ }
+
+#ifdef XWAYLAND
+ if (!client_is_x11(c)) {
+#endif
+ if (corner_radius_inner > 0 && c->scene) {
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_corner_radius, c);
+ }
+#ifdef XWAYLAND
+ }
+#endif
+}
+
+void
+update_client_blur(Client *c)
+{
+ if (!blur) {
+ return;
+ }
+
+ if (c->scene) {
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_blur, c);
+ }
+}
+
+void
+update_buffer_corner_radius(Client *c, struct wlr_scene_buffer *buffer)
+{
+ int radius;
+
+#ifdef XWAYLAND
+ if (client_is_x11(c)) {
+ return;
+ }
+#endif
+
+ if (!corner_radius_inner) {
+ return;
+ }
+
+ radius = corner_radius_inner;
+ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) {
+ radius = 0;
+ }
+ wlr_scene_buffer_set_corner_radius(buffer, radius, CORNER_LOCATION_ALL);
+}
+
+void
+update_client_shadow_color(Client *c)
+{
+ int has_shadow_enabled = 1;
+ const float *color;
+
+ if (!shadow || !c->shadow) {
+ return;
+ }
+
+ color = focustop(c->mon) == c ? shadow_color_focus : shadow_color;
+
+ if ((shadow_only_floating && !c->isfloating) ||
+ in_shadow_ignore_list(client_get_appid(c)) ||
+ c->isfullscreen) {
+ color = transparent;
+ has_shadow_enabled = 0;
+ }
+
+ wlr_scene_shadow_set_color(c->shadow, color);
+ c->has_shadow_enabled = has_shadow_enabled;
+}
+
+void
+update_client_focus_decorations(Client *c, int focused, int urgent)
+{
+ if (corner_radius > 0 && c->round_border) {
+ wlr_scene_rect_set_color(c->round_border, urgent ? urgentcolor : (focused ? focuscolor : bordercolor));
+ }
+ if (shadow && c->shadow) {
+ client_set_shadow_blur_sigma(c, (int)round(focused ? shadow_blur_sigma_focus : shadow_blur_sigma));
+ if (c->has_shadow_enabled) {
+ wlr_scene_shadow_set_color(c->shadow, focused ? shadow_color_focus : shadow_color);
+ }
+ }
+ if (opacity) {
+ c->opacity = focused ? opacity_active : opacity_inactive;
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_opacity, c);
+ }
+}
+
#ifdef XWAYLAND
void
activatex11(struct wl_listener *listener, void *data)
activatex11(struct wl_listener *listener, void *data)