diff --git a/patches/blur/README.md b/patches/blur/README.md new file mode 100644 index 0000000..ff6a5e0 --- /dev/null +++ b/patches/blur/README.md @@ -0,0 +1,70 @@ +### Description + +Blur implemented using scenefx + +Implemented keybinds: +- dynamically toggle blur globally: +```c + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_B, toggleblur, {0} }, +``` +- toggle blur for focused window: +```c + { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_b, toggleblurfocused,{0} }, +``` + +Options in config.def.h: +```c +#define blur_params 2, 2, 0, 0.703125, 0.4375, 0.875 // passes, radius, noise, brightness, contrast, saturation +static int blur_enabled = 1; +``` + +Requires [scenefx](https://github.com/wlrfx/scenefx) version 0.5 (which is currently the latest version). Some information about installation instructions is provided at the bottom. + +I have only implemented the xray version of blur, where blur skips past contents of other windows underneath a window and directly shows the background, because this way the background blur is cached, which helps to significantly reduce the gpu usage. + +Tested blur.patch on main branch commit dwl/dwl@f1675a4800 + +As of commit fd5e06a50d the bar patch does not apply cleanly to dwl/dwl@f1675a4800, therefore the blur_bar.patch would also need to be manually applied. I will update it after the bar patch gets updated. + +### Download + +- [blur.patch](/dwl/dwl-patches/raw/branch/main/patches/blur/blur.patch) : for application to base dwl, does not apply blur to the bar + +- [blur_bar.patch](/dwl/dwl-patches/raw/branch/main/patches/blur/blur_bar.patch) : for use with the bar patch, this version applies blur to the bar too, but to actually see the blur effect the bar background color would need to be changed to a transparent or translucent value, for example: +```c +static uint32_t colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { 0x777777ff, 0x00000000, 0x00000000 }, + [SchemeSel] = { 0x00ffffff, 0x00000000, 0x00ffffff }, + [SchemeUrg] = { 0xff00ffff, 0x00000000, 0xff00ffff }, +}; +``` + +### Authors + +- [atourist](https://codeberg.org/atourist) + +--- + +Installing [scenefx](https://github.com/wlrfx/scenefx) version 0.5 + +The recommended way to install scenefx is through your linux distro's package manager, if the scenefx version in your distro's official repositories is 0.5. The scenefx github page has a [list](https://github.com/wlrfx/scenefx#Installation) with the version info on some common distros. For vanilla Arch Linux users, scenefx is not available in the official repositories, but it can be installed via the AUR instead, either using yay or paru or some other AUR helper, or manually by following the steps listed on the [Arch wiki for AUR](https://wiki.archlinux.org/title/Arch_User_Repository). Some derivative Arch distros like CachyOS provide scenefx through their official repositories. + +If you install scenefx via your package manager or through AUR, **no further steps are needed**. +But if you compile from source using the instructions provided in the [scenefx github repository](https://github.com/wlrfx/scenefx), depending on where you install scenefx, you might need to ensure that the `PKG_CONFIG` specified in dwl's `config.mk` is able to locate the header files for scenefx. By default, it uses pkg-config, so to check, use the following terminal command: +```sh +pkg-config --cflags scenefx-0.5 +``` +If this returns a path to the scenefx header files, **no further steps are needed**. +**Otherwise** the path to the header files needs to be manually provided following these steps: +1. Apply the blur patch +2. In `Makefile` in the dwl source code, remove `scenefx-0.5` from `PKGS = ` +3. In `Makefile` add `-I/path/to/scenefx_headers` with the correct path to `DWLCFLAGS =` such that it is placed before all other options, so it should look something like this: +```Makefile +DWLCFLAGS = -I/path/to/scenefx_headers `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) +``` +4. In `Makefile` add `-lscenefx-0.5` to `LDLIBS =` such that it is placed before all other options, so it should look something like this: +```Makefile +LDLIBS = -lscenefx-0.5 `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) +``` + diff --git a/patches/blur/blur.patch b/patches/blur/blur.patch new file mode 100644 index 0000000..02efe1f --- /dev/null +++ b/patches/blur/blur.patch @@ -0,0 +1,196 @@ +diff --git a/Makefile b/Makefile +index 8304245..f55e2f9 100644 +--- a/Makefile ++++ b/Makefile +@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wayland-server xkbcommon libinput $(XLIBS) ++PKGS = scenefx-0.5 wayland-server xkbcommon libinput $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) + +diff --git a/config.def.h b/config.def.h +index a4019d3..88029d9 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -18,6 +18,9 @@ static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You ca + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) + ++#define blur_params 2, 2, 0, 0.703125, 0.4375, 0.875 // passes, radius, noise, brightness, contrast, saturation ++static int blur_enabled = 1; ++ + /* logging */ + static int log_level = WLR_ERROR; + +@@ -123,6 +126,8 @@ static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_B, toggleblur, {0} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_b, toggleblurfocused,{0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +diff --git a/dwl.c b/dwl.c +index ca97c30..af50458 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -11,6 +11,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -51,7 +53,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -88,8 +89,7 @@ + /* enums */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ +-enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrUnmanaged, LyrOverlay, +- LyrIMPopup, LyrBlock, NUM_LAYERS }; /* scene layers */ ++enum { LyrBg, LyrBlur, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrUnmanaged, LyrOverlay, LyrIMPopup, LyrBlock, NUM_LAYERS }; /* scene layers */ + enum { AxisUp, AxisRight, AxisDown, AxisLeft }; + + typedef union { +@@ -159,6 +159,7 @@ typedef struct { + unsigned int bw; + uint32_t tags; + int isfloating, isurgent, isfullscreen; ++ struct wlr_scene_blur *blur; + } Client; + + typedef struct { +@@ -226,6 +227,7 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ struct wlr_scene_optimized_blur *blur; + }; + + typedef struct { +@@ -357,6 +359,8 @@ static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); ++static void toggleblur(const Arg *arg); ++static void toggleblurfocused(const Arg *arg); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -841,6 +845,8 @@ cleanupmon(struct wl_listener *listener, void *data) + + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); ++ wlr_scene_node_destroy(&m->blur->node); ++ m->blur = NULL; + free(m); + } + +@@ -944,6 +950,7 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) + } + + arrangelayers(l->mon); ++ if ((layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) && (l->mon)) wlr_scene_optimized_blur_mark_dirty(l->mon->blur); + } + + void +@@ -990,6 +997,7 @@ commitnotify(struct wl_listener *listener, void *data) + } + + resize(c, c->geom, (c->isfloating && !c->isfullscreen)); ++ wlr_scene_blur_set_size(c->blur, c->geom.width, c->geom.height); + } + + void +@@ -1211,6 +1219,11 @@ 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); + ++ m->blur = wlr_scene_optimized_blur_create(&scene->tree, m->m.width, m->m.height); ++ wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); ++ wlr_scene_node_reparent(&m->blur->node, layers[LyrBlur]); ++ wlr_scene_node_set_enabled(&m->blur->node, blur_enabled); ++ + /* Adds this to the output layout in the order it was configured. + * + * The output layout utility automatically adds a wl_output global to the +@@ -1955,6 +1968,11 @@ mapnotify(struct wl_listener *listener, void *data) + } + printstatus(); + ++ c->blur = wlr_scene_blur_create(c->scene, c->geom.width, c->geom.height); ++ wlr_scene_node_lower_to_bottom(&c->blur->node); ++ wlr_scene_blur_set_should_only_blur_bottom_layer(c->blur, true); ++ wlr_scene_node_set_enabled(&c->blur->node, blur_enabled); ++ + unset_fullscreen: + m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); + wl_list_for_each(w, &clients, link) { +@@ -2651,11 +2669,13 @@ setup(void) + drag_icon = wlr_scene_tree_create(&scene->tree); + wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); + ++ wlr_scene_set_blur_data(scene, blur_params); ++ + /* 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. */ +- if (!(drw = wlr_renderer_autocreate(backend))) ++ if (!(drw = fx_renderer_create(backend))) + die("couldn't create renderer"); + wl_signal_add(&drw->events.lost, &gpu_reset); + +@@ -2933,6 +2953,21 @@ tile(Monitor *m) + } + } + ++void toggleblur(const Arg *arg) { ++ Client *c; ++ Monitor *m = NULL; ++ blur_enabled = !blur_enabled; ++ wl_list_for_each(m, &mons, link) { ++ wlr_scene_node_set_enabled(&m->blur->node, blur_enabled); ++ } ++ wl_list_for_each(c, &clients, link) wlr_scene_node_set_enabled(&c->blur->node, blur_enabled); ++} ++ ++void toggleblurfocused(const Arg *arg) { ++ Client *sel = focustop(selmon); ++ if (sel && sel->blur) wlr_scene_node_set_enabled(&sel->blur->node, !sel->blur->node.enabled); ++} ++ + void + togglefloating(const Arg *arg) + { +@@ -2995,6 +3030,7 @@ unmaplayersurfacenotify(struct wl_listener *listener, void *data) + arrangelayers(l->mon); + if (l->layer_surface->surface == seat->keyboard_state.focused_surface) + focusclient(focustop(selmon), NULL, 1); ++ if ((l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) && (l->mon)) wlr_scene_optimized_blur_mark_dirty(l->mon->blur); + motionnotify(0, NULL, 0, 0, 0, 0); + } + +@@ -3098,6 +3134,9 @@ 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); + ++ wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); ++ wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.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); diff --git a/patches/blur/blur_bar.patch b/patches/blur/blur_bar.patch new file mode 100644 index 0000000..82042c6 --- /dev/null +++ b/patches/blur/blur_bar.patch @@ -0,0 +1,209 @@ +diff --git a/Makefile b/Makefile +index 09ae285..02e7e13 100644 +--- a/Makefile ++++ b/Makefile +@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) ++PKGS = scenefx-0.5 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) + +diff --git a/config.def.h b/config.def.h +index 1c50fc5..90e17d6 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -20,6 +20,9 @@ static uint32_t colors[][3] = { + [SchemeUrg] = { 0, 0, 0x770000ff }, + }; + ++#define blur_params 2, 2, 0, 0.703125, 0.4375, 0.875 // passes, radius, noise, brightness, contrast, saturation ++static int blur_enabled = 1; ++ + /* tagging */ + static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +@@ -130,6 +133,8 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_b, togglebar, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_B, toggleblur, {0} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_b, toggleblurfocused,{0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +diff --git a/dwl.c b/dwl.c +index 2afec86..9bec152 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -12,6 +12,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -50,7 +52,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -91,7 +92,7 @@ + enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ +-enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrIMPopup, LyrBlock, NUM_LAYERS }; /* scene layers */ ++enum { LyrBg, LyrBlur, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrIMPopup, LyrBlock, NUM_LAYERS }; /* scene layers */ + enum { AxisUp, AxisRight, AxisDown, AxisLeft }; + enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ + +@@ -163,6 +164,7 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ struct wlr_scene_blur *blur; + } Client; + + typedef struct { +@@ -221,6 +223,7 @@ struct Monitor { + struct wlr_output *wlr_output; + struct wlr_scene_output *scene_output; + struct wlr_scene_buffer *scene_buffer; /* bar buffer */ ++ struct wlr_scene_blur *bar_blur; + struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ + struct wl_listener frame; + struct wl_listener destroy; +@@ -247,6 +250,7 @@ struct Monitor { + Drwl *drw; + Buffer *pool[2]; + int lrpad; ++ struct wlr_scene_optimized_blur *blur; + }; + + typedef struct { +@@ -387,6 +391,8 @@ static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglebar(const Arg *arg); ++static void toggleblur(const Arg *arg); ++static void toggleblurfocused(const Arg *arg); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -979,6 +985,8 @@ cleanupmon(struct wl_listener *listener, void *data) + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); + wlr_scene_node_destroy(&m->scene_buffer->node); ++ wlr_scene_node_destroy(&m->blur->node); ++ m->blur = NULL; + free(m); + } + +@@ -1087,6 +1095,7 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) + } + + arrangelayers(l->mon); ++ if ((layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) && (l->mon)) wlr_scene_optimized_blur_mark_dirty(l->mon->blur); + } + + void +@@ -1120,6 +1129,7 @@ commitnotify(struct wl_listener *listener, void *data) + /* mark a pending resize as completed */ + if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) + c->resize = 0; ++ wlr_scene_blur_set_size(c->blur, c->geom.width, c->geom.height); + } + + void +@@ -1347,6 +1357,16 @@ 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); + ++ m->blur = wlr_scene_optimized_blur_create(&scene->tree, m->m.width, m->m.height); ++ wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); ++ wlr_scene_node_reparent(&m->blur->node, layers[LyrBlur]); ++ wlr_scene_node_set_enabled(&m->blur->node, blur_enabled); ++ m->bar_blur = wlr_scene_blur_create(layers[LyrBottom], m->b.real_width, m->b.real_height); ++ wlr_scene_node_set_position(&m->bar_blur->node, m->m.x, m->m.y); ++ wlr_scene_node_lower_to_bottom(&m->bar_blur->node); ++ wlr_scene_blur_set_should_only_blur_bottom_layer(m->bar_blur, true); ++ wlr_scene_node_set_enabled(&m->bar_blur->node, blur_enabled); ++ + /* Adds this to the output layout in the order it was configured. + * + * The output layout utility automatically adds a wl_output global to the +@@ -2154,6 +2174,11 @@ mapnotify(struct wl_listener *listener, void *data) + } + drawbars(); + ++ c->blur = wlr_scene_blur_create(c->scene, c->geom.width, c->geom.height); ++ wlr_scene_node_lower_to_bottom(&c->blur->node); ++ wlr_scene_blur_set_should_only_blur_bottom_layer(c->blur, true); ++ wlr_scene_node_set_enabled(&c->blur->node, blur_enabled); ++ + unset_fullscreen: + m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); + wl_list_for_each(w, &clients, link) { +@@ -2785,11 +2810,13 @@ setup(void) + drag_icon = wlr_scene_tree_create(&scene->tree); + wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); + ++ wlr_scene_set_blur_data(scene, blur_params); ++ + /* 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. */ +- if (!(drw = wlr_renderer_autocreate(backend))) ++ if (!(drw = fx_renderer_create(backend))) + die("couldn't create renderer"); + wl_signal_add(&drw->events.lost, &gpu_reset); + +@@ -3108,6 +3135,22 @@ togglebar(const Arg *arg) + drawbars(); + } + ++void toggleblur(const Arg *arg) { ++ Client *c; ++ Monitor *m = NULL; ++ blur_enabled = !blur_enabled; ++ wl_list_for_each(m, &mons, link) { ++ wlr_scene_node_set_enabled(&m->blur->node, blur_enabled); ++ wlr_scene_node_set_enabled(&m->bar_blur->node, blur_enabled); ++ } ++ wl_list_for_each(c, &clients, link) wlr_scene_node_set_enabled(&c->blur->node, blur_enabled); ++} ++ ++void toggleblurfocused(const Arg *arg) { ++ Client *sel = focustop(selmon); ++ if (sel && sel->blur) wlr_scene_node_set_enabled(&sel->blur->node, !sel->blur->node.enabled); ++} ++ + void + togglefloating(const Arg *arg) + { +@@ -3172,6 +3215,7 @@ unmaplayersurfacenotify(struct wl_listener *listener, void *data) + arrangelayers(l->mon); + if (l->layer_surface->surface == seat->keyboard_state.focused_surface) + focusclient(focustop(selmon), 1); ++ if ((l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) && (l->mon)) wlr_scene_optimized_blur_mark_dirty(l->mon->blur); + motionnotify(0, NULL, 0, 0, 0, 0); + } + +@@ -3274,6 +3318,9 @@ 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); + ++ wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); ++ wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.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);