diff --git a/scenefx/scenefx.patch b/scenefx/scenefx.patch index ae1c581..f009d20 100644 --- a/scenefx/scenefx.patch +++ b/scenefx/scenefx.patch @@ -1,15 +1,15 @@ -From cd8040c4e4f22514837a2c768a8a41f0e9820900 Mon Sep 17 00:00:00 2001 +From 1f7161a10ea24eb7aa4fbeb80034fdd459190c01 Mon Sep 17 00:00:00 2001 From: wochap -Date: Fri, 5 Apr 2024 09:46:32 -0500 -Subject: [PATCH] implement wlrfx/scenefx shadows +Date: Wed, 10 Apr 2024 11:00:23 -0500 +Subject: [PATCH] implement wlrfx/scenefx -add options for shadow and corner_radius +add options for shadow, blur, opacity and corner_radius --- Makefile | 2 +- - client.h | 11 ++++- - config.def.h | 8 ++++ - dwl.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++--- - 4 files changed, 134 insertions(+), 9 deletions(-) + client.h | 11 +++- + config.def.h | 28 ++++++++- + dwl.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 4 files changed, 198 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 6cde460..f235edf 100644 @@ -59,39 +59,60 @@ index 71c7d76..6532e05 100644 static inline void diff --git a/config.def.h b/config.def.h -index db0babc..521bd04 100644 +index db0babc..185765a 100644 --- a/config.def.h +++ b/config.def.h -@@ -12,6 +12,14 @@ static const float focuscolor[] = COLOR(0x005577ff); +@@ -11,7 +11,33 @@ static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); static const float urgentcolor[] = COLOR(0xff0000ff); /* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */ - static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; /* You can also use glsl colors */ -+static const int shadow = 1; +-static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; /* You can also use glsl colors */ ++static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 0.0}; /* You can also use glsl colors */ ++ ++static const int opacity = 0; /* flag to enable opacity */ ++static const float opacity_inactive = 0.5; ++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 int shadow_blur_sigma = 20; +static const int shadow_blur_sigma_focus = 40; -+static const char *const shadow_ignore_list[] = { "xdg-desktop-portal-gtk", "cpupower-gui", NULL }; /* list of app-id to ignore */ -+static const int corner_radius = 0; ++static const char *const shadow_ignore_list[] = { "xdg-desktop-portal-gtk", NULL }; /* list of app-id to ignore */ ++ ++static const int corner_radius = 0; /* 0 disables corner_radius */ ++ ++static const int blur = 0; /* flag to enable blur */ ++static const int blur_optimized = 1; ++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, ++}; /* tagging - TAGCOUNT must be no greater than 31 */ #define TAGCOUNT (9) diff --git a/dwl.c b/dwl.c -index ef27a1d..e0e8222 100644 +index ef27a1d..4e9614e 100644 --- a/dwl.c +++ b/dwl.c -@@ -9,6 +9,9 @@ +@@ -9,6 +9,10 @@ #include #include #include +#include ++#include +#include +#include #include #include #include -@@ -37,7 +40,6 @@ +@@ -37,7 +41,6 @@ #include #include #include @@ -99,7 +120,7 @@ index ef27a1d..e0e8222 100644 #include #include #include -@@ -130,6 +132,10 @@ typedef struct { +@@ -130,6 +133,10 @@ typedef struct { uint32_t tags; int isfloating, isurgent, isfullscreen; uint32_t resize; /* configure serial of a pending resize */ @@ -110,34 +131,36 @@ index ef27a1d..e0e8222 100644 } Client; typedef struct { -@@ -327,6 +333,8 @@ static Monitor *xytomon(double x, double y); +@@ -327,6 +334,9 @@ 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 int in_shadow_ignore_list(const char *str); -+static void output_configure_scene(struct wlr_scene_node *node, Client *c); ++static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); ++static void iter_xdg_scene_buffers_shadow(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); /* variables */ static const char broken[] = "broken"; -@@ -440,6 +448,13 @@ applyrules(Client *c) +@@ -440,6 +450,14 @@ applyrules(Client *c) mon = m; } } -+ if (shadow_only_floating) { ++ if (shadow && shadow_only_floating) { + if (c->isfloating && !in_shadow_ignore_list(appid)) { + c->shadow_data.enabled = 1; + } else { + c->shadow_data.enabled = 0; + } ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_shadow, c); + } wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrFloat : LyrTile]); setmon(c, mon, newtags); } -@@ -975,6 +990,13 @@ createnotify(struct wl_listener *listener, void *data) +@@ -975,6 +993,13 @@ createnotify(struct wl_listener *listener, void *data) wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); -+ c->opacity = 1; ++ c->opacity = opacity; + c->corner_radius = corner_radius; + c->shadow_data = shadow_data_get_default(); + c->shadow_data.enabled = shadow_only_floating != 1 && !in_shadow_ignore_list(client_get_appid(c)); @@ -147,54 +170,73 @@ index ef27a1d..e0e8222 100644 LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify); LISTEN(&xdg_surface->surface->events.map, &c->map, mapnotify); LISTEN(&xdg_surface->surface->events.unmap, &c->unmap, unmapnotify); -@@ -1204,8 +1226,11 @@ focusclient(Client *c, int lift) +@@ -1204,8 +1229,21 @@ focusclient(Client *c, int lift) /* Don't change border color if there is an exclusive focus or we are * handling a drag operation */ - if (!exclusive_focus && !seat->drag) + if (!exclusive_focus && !seat->drag) { client_set_border_color(c, focuscolor); -+ c->shadow_data.blur_sigma = shadow_blur_sigma_focus; -+ c->shadow_data.color = shadow_color_focus; ++ if (shadow) { ++ c->shadow_data.blur_sigma = shadow_blur_sigma_focus; ++ c->shadow_data.color = shadow_color_focus; ++ } ++ if (opacity) { ++ c->opacity = opacity_active; ++ } ++ if (opacity) { ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers, c); ++ } else if (shadow) { ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_shadow, c); ++ } + } } /* Deactivate old client if focus is changing */ -@@ -1223,6 +1248,8 @@ focusclient(Client *c, int lift) +@@ -1223,6 +1261,18 @@ focusclient(Client *c, int lift) * and probably other clients */ } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { client_set_border_color(old_c, bordercolor); -+ old_c->shadow_data.blur_sigma = shadow_blur_sigma; -+ old_c->shadow_data.color = shadow_color; ++ if (shadow) { ++ old_c->shadow_data.blur_sigma = shadow_blur_sigma; ++ old_c->shadow_data.color = shadow_color; ++ } ++ if (opacity) { ++ old_c->opacity = opacity_inactive; ++ } ++ if (opacity) { ++ wlr_scene_node_for_each_buffer(&old_c->scene_surface->node, iter_xdg_scene_buffers, old_c); ++ } else if (shadow) { ++ wlr_scene_node_for_each_buffer(&old_c->scene_surface->node, iter_xdg_scene_buffers_shadow, old_c); ++ } client_activate_surface(old, 0); } -@@ -1554,6 +1581,13 @@ mapnotify(struct wl_listener *listener, void *data) +@@ -1518,6 +1568,8 @@ mapnotify(struct wl_listener *listener, void *data) + : wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); + c->scene->node.data = c->scene_surface->node.data = c; + ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers, c); ++ + /* Handle unmanaged clients first so we can return prior create borders */ + if (client_is_unmanaged(c)) { + client_get_geometry(c, &c->geom); +@@ -1554,6 +1606,14 @@ mapnotify(struct wl_listener *listener, void *data) /* TODO: https://github.com/djpohly/dwl/pull/334#issuecomment-1330166324 */ if (c->type == XDGShell && (p = client_get_parent(c))) { c->isfloating = 1; -+ if (shadow_only_floating) { ++ if (shadow && shadow_only_floating) { + if (!in_shadow_ignore_list(client_get_appid(c))) { + c->shadow_data.enabled = 1; + } else { + c->shadow_data.enabled = 0; + } ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_shadow, c); + } wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]); setmon(c, p->mon, p->tags); } else { -@@ -1878,6 +1912,10 @@ rendermon(struct wl_listener *listener, void *data) - if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c)) - goto skip; - -+ if (shadow) { -+ output_configure_scene(&m->scene_output->scene->tree.node, NULL); -+ } -+ - /* - * 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 -@@ -1936,6 +1974,7 @@ resize(Client *c, struct wlr_box geo, int interact) +@@ -1936,6 +1996,7 @@ resize(Client *c, struct wlr_box geo, int interact) { struct wlr_box *bbox = interact ? &sgeom : &c->mon->w; struct wlr_box clip; @@ -202,7 +244,7 @@ index ef27a1d..e0e8222 100644 client_set_bounds(c, geo.width, geo.height); c->geom = geo; applybounds(c, bbox); -@@ -1954,8 +1993,12 @@ resize(Client *c, struct wlr_box geo, int interact) +@@ -1954,8 +2015,12 @@ resize(Client *c, struct wlr_box geo, int interact) /* this is a no-op if size hasn't changed */ c->resize = client_set_size(c, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); @@ -217,21 +259,30 @@ index ef27a1d..e0e8222 100644 } void -@@ -2048,6 +2091,13 @@ void +@@ -2048,6 +2113,14 @@ void setfloating(Client *c, int floating) { c->isfloating = floating; -+ if (shadow_only_floating) { ++ if (shadow && shadow_only_floating) { + if (c->isfloating && !in_shadow_ignore_list(client_get_appid(c))) { + c->shadow_data.enabled = 1; + } else { + c->shadow_data.enabled = 0; + } ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_shadow, c); + } if (!c->mon) return; wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen -@@ -2196,7 +2246,7 @@ setup(void) +@@ -2192,11 +2265,15 @@ setup(void) + drag_icon = wlr_scene_tree_create(&scene->tree); + wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); + ++ if (blur) { ++ wlr_scene_set_blur_data(scene, blur_data); ++ } ++ + /* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The user * can also specify a renderer using the WLR_RENDERER env var. * The renderer is responsible for defining the various pixel formats it * supports for shared memory, this configures that for clients. */ @@ -240,20 +291,23 @@ index ef27a1d..e0e8222 100644 die("couldn't create renderer"); /* Create shm, drm and linux_dmabuf interfaces by ourselves. -@@ -2650,8 +2700,11 @@ urgent(struct wl_listener *listener, void *data) +@@ -2650,8 +2727,14 @@ urgent(struct wl_listener *listener, void *data) if (!c || c == focustop(selmon)) return; - if (client_surface(c)->mapped) + if (client_surface(c)->mapped) { client_set_border_color(c, urgentcolor); -+ c->shadow_data.blur_sigma = shadow_blur_sigma_focus; -+ c->shadow_data.color = shadow_color_focus; ++ if (shadow) { ++ c->shadow_data.blur_sigma = shadow_blur_sigma_focus; ++ c->shadow_data.color = shadow_color_focus; ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_shadow, c); ++ } + } c->isurgent = 1; printstatus(); } -@@ -2746,6 +2799,63 @@ zoom(const Arg *arg) +@@ -2746,6 +2829,78 @@ zoom(const Arg *arg) arrange(selmon); } @@ -268,48 +322,63 @@ index ef27a1d..e0e8222 100644 +} + +void -+output_configure_scene(struct wlr_scene_node *node, Client *c) ++iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) +{ -+ Client *_c; ++ Client *c = user_data; ++ struct wlr_scene_surface * scene_surface = wlr_scene_surface_try_from_buffer(buffer); ++ struct wlr_xdg_surface *xdg_surface; + -+ if (!node->enabled) { ++ if (!scene_surface) { + return; + } + -+ _c = node->data; -+ if (_c) { -+ c = _c; -+ } ++ xdg_surface = wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface); + -+ if (node->type == WLR_SCENE_NODE_BUFFER) { -+ struct wlr_xdg_surface *xdg_surface; -+ struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); -+ -+ struct wlr_scene_surface * scene_surface = -+ wlr_scene_surface_try_from_buffer(buffer); -+ if (!scene_surface) { -+ return; ++ 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 (opacity) { ++ wlr_scene_buffer_set_opacity(buffer, c->opacity); + } + -+ xdg_surface = wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface); -+ -+ 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? -+ wlr_scene_buffer_set_opacity(buffer, c->opacity); -+ -+ if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { ++ if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { ++ if (corner_radius > 0) { + wlr_scene_buffer_set_corner_radius(buffer, c->corner_radius); ++ } ++ ++ if (shadow) { + wlr_scene_buffer_set_shadow_data(buffer, c->shadow_data); + } ++ ++ if (blur) { ++ 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); ++ } + } -+ } else if (node->type == WLR_SCENE_NODE_TREE) { -+ struct wlr_scene_tree *tree = wl_container_of(node, tree, node); -+ struct wlr_scene_node *_node; -+ wl_list_for_each(_node, &tree->children, link) { -+ output_configure_scene(_node, c); ++ } ++} ++ ++void ++iter_xdg_scene_buffers_shadow(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)) { ++ wlr_scene_buffer_set_shadow_data(buffer, c->shadow_data); + } + } +}