summaryrefslogtreecommitdiff
path: root/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx
diff options
context:
space:
mode:
authorAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
committerAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
commit70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch)
treeab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx
parent5d94c0a7d44a2255b81815a52a7056a94a39842d (diff)
downloadRaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.tar.gz
RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.zip
Replaced file structures for themes in the correct format
Diffstat (limited to 'raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx')
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/LICENSE674
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/appfolders.js265
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/applications.js614
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/coverflow_alt_tab.js91
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/dash_to_dock.js421
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/lockscreen.js89
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/overview.js226
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/panel.js577
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/screenshot.js110
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/window_list.js148
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/connections.js106
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/dummy_pipeline.js112
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/effects_manager.js90
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/keys.js190
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/paint_signals.js91
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js223
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipelines_manager.js168
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/settings.js363
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/settings_updater.js40
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/utils.js38
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/client.js58
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/iface.xml12
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/services.js93
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.glsl111
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.js168
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.glsl93
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.js211
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.glsl71
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.js120
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.glsl76
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.js140
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effects.js362
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.glsl70
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.js213
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.glsl14
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.js31
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl52
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.js207
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js43
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js43
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.glsl20
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.js76
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/pixelize.js88
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.glsl18
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.js31
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.glsl57
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.js120
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/extension.js614
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-row-symbolic.svg4
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg56
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg44
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg44
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/down-symbolic.svg2
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/duplicate-row-symbolic.svg1
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dynamic-mode-symbolic.svg71
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/edit-row-symbolic.svg14
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-symbolic.svg2
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg1
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg56
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/pipelines-symbolic.svg64
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-row-symbolic.svg3
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg7
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-row-symbolic.svg2
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg2
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/static-mode-symbolic.svg71
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 7989 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 16821 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 1203 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 3499 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 16153 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 17615 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 16877 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/da/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 927 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 17826 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 15541 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 17367 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/et/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 2815 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fi/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 10156 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 17531 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 592 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 25812 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hr/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 8690 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 17520 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 16481 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 17361 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 18455 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ka/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 6964 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 14985 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ml/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 523 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/mrh/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 521 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/my/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 362 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 7966 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 17331 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 1185 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 15190 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 16967 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 17153 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 10249 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 22437 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sk/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 1083 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 11678 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 16934 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 28773 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/th/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 362 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 17288 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 21663 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 18415 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_CN/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 15517 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mobin0 -> 15248 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/metadata.json28
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/applications.js217
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/applications_management/application_row.js112
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/dash.js81
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/menu.js68
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/other.js86
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/overview.js59
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/panel.js102
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines.js98
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/effect_row.js222
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/effects_dialog.js174
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_choose_row.js106
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_group.js99
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/prefs.js51
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/gschemas.compiledbin0 -> 9976 bytes
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml595
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/stylesheet.css573
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/application-row.ui47
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/applications.ui276
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/dash.ui172
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/effects-dialog.ui77
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/menu.ui37
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/other.ui208
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/overview.ui143
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/panel.ui240
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipeline-choose-row.ui39
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipeline-group.ui29
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipelines.ui44
137 files changed, 12275 insertions, 0 deletions
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/LICENSE b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/appfolders.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/appfolders.js
new file mode 100644
index 0000000..8824777
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/appfolders.js
@@ -0,0 +1,265 @@
+import Shell from 'gi://Shell';
+import Clutter from 'gi://Clutter';
+import Cogl from 'gi://Cogl';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import { adjustAnimationTime } from 'resource:///org/gnome/shell/misc/animationUtils.js';
+
+import { PaintSignals } from '../conveniences/paint_signals.js';
+// TODO drop Tweener in favour of Clutter's `ease` (will need to extend the blur effect for it)
+const Tweener = imports.tweener.tweener;
+
+// TODO: Drop GNOME 46 backwards compatibility
+const transparent = Clutter.Color ?
+ Clutter.Color.from_pixel(0x00000000) :
+ new Cogl.Color({
+ red: 0,
+ green: 0,
+ blue: 0,
+ alpha: 0
+ });
+const FOLDER_DIALOG_ANIMATION_TIME = 200;
+
+const DIALOGS_STYLES = [
+ "appfolder-dialogs-transparent",
+ "appfolder-dialogs-light",
+ "appfolder-dialogs-dark"
+];
+
+let original_zoomAndFadeIn = null;
+let original_zoomAndFadeOut = null;
+let sigma;
+let brightness;
+
+let _zoomAndFadeIn = function () {
+ let [sourceX, sourceY] =
+ this._source.get_transformed_position();
+ let [dialogX, dialogY] =
+ this.child.get_transformed_position();
+
+ this.child.set({
+ translation_x: sourceX - dialogX,
+ translation_y: sourceY - dialogY,
+ scale_x: this._source.width / this.child.width,
+ scale_y: this._source.height / this.child.height,
+ opacity: 0,
+ });
+
+ this.set_background_color(transparent);
+
+ let blur_effect = this.get_effect("appfolder-blur");
+
+ blur_effect.radius = 0;
+ blur_effect.brightness = 1.0;
+ Tweener.addTween(blur_effect,
+ {
+ radius: sigma * 2,
+ brightness: brightness,
+ time: adjustAnimationTime(FOLDER_DIALOG_ANIMATION_TIME / 1000),
+ transition: 'easeOutQuad'
+ }
+ );
+
+ this.child.ease({
+ translation_x: 0,
+ translation_y: 0,
+ scale_x: 1,
+ scale_y: 1,
+ opacity: 255,
+ duration: FOLDER_DIALOG_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+
+ this._needsZoomAndFade = false;
+
+ if (this._sourceMappedId === 0) {
+ this._sourceMappedId = this._source.connect(
+ 'notify::mapped', this._zoomAndFadeOut.bind(this));
+ }
+};
+
+let _zoomAndFadeOut = function () {
+ if (!this._isOpen)
+ return;
+
+ if (!this._source.mapped) {
+ this.hide();
+ return;
+ }
+
+ let [sourceX, sourceY] =
+ this._source.get_transformed_position();
+ let [dialogX, dialogY] =
+ this.child.get_transformed_position();
+
+ this.set_background_color(transparent);
+
+ let blur_effect = this.get_effect("appfolder-blur");
+ Tweener.addTween(blur_effect,
+ {
+ radius: 0,
+ brightness: 1.0,
+ time: adjustAnimationTime(FOLDER_DIALOG_ANIMATION_TIME / 1000),
+ transition: 'easeInQuad'
+ }
+ );
+
+ this.child.ease({
+ translation_x: sourceX - dialogX,
+ translation_y: sourceY - dialogY,
+ scale_x: this._source.width / this.child.width,
+ scale_y: this._source.height / this.child.height,
+ opacity: 0,
+ duration: FOLDER_DIALOG_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ onComplete: () => {
+ this.child.set({
+ translation_x: 0,
+ translation_y: 0,
+ scale_x: 1,
+ scale_y: 1,
+ opacity: 255,
+ });
+ this.hide();
+
+ this._popdownCallbacks.forEach(func => func());
+ this._popdownCallbacks = [];
+ },
+ });
+
+ this._needsZoomAndFade = false;
+};
+
+
+export const AppFoldersBlur = class AppFoldersBlur {
+ // we do not use the effects manager and dummy pipelines here because we
+ // really want to manage our sigma value ourself during the transition
+ constructor(connections, settings, _) {
+ this.connections = connections;
+ this.paint_signals = new PaintSignals(connections);
+ this.settings = settings;
+ }
+
+ enable() {
+ this._log("blurring appfolders");
+
+ brightness = this.settings.appfolder.BRIGHTNESS;
+ sigma = this.settings.appfolder.SIGMA;
+
+ let appDisplay = Main.overview._overview.controls._appDisplay;
+
+ if (appDisplay._folderIcons.length > 0) {
+ this.blur_appfolders();
+ }
+
+ this.connections.connect(
+ appDisplay, 'view-loaded', _ => this.blur_appfolders()
+ );
+ }
+
+ blur_appfolders() {
+ let appDisplay = Main.overview._overview.controls._appDisplay;
+
+ if (this.settings.HACKS_LEVEL === 1)
+ this._log("appfolders hack level 1");
+
+ appDisplay._folderIcons.forEach(icon => {
+ icon._ensureFolderDialog();
+
+ if (original_zoomAndFadeIn == null) {
+ original_zoomAndFadeIn = icon._dialog._zoomAndFadeIn;
+ }
+ if (original_zoomAndFadeOut == null) {
+ original_zoomAndFadeOut = icon._dialog._zoomAndFadeOut;
+ }
+
+ let blur_effect = new Shell.BlurEffect({
+ name: "appfolder-blur",
+ radius: sigma * 2,
+ brightness: brightness,
+ mode: Shell.BlurMode.BACKGROUND
+ });
+
+ icon._dialog.remove_effect_by_name("appfolder-blur");
+ icon._dialog.add_effect(blur_effect);
+
+ DIALOGS_STYLES.forEach(
+ style => icon._dialog._viewBox.remove_style_class_name(style)
+ );
+
+ if (this.settings.appfolder.STYLE_DIALOGS > 0)
+ icon._dialog._viewBox.add_style_class_name(
+ DIALOGS_STYLES[this.settings.appfolder.STYLE_DIALOGS - 1]
+ );
+
+ // finally override the builtin functions
+ icon._dialog._zoomAndFadeIn = _zoomAndFadeIn;
+ icon._dialog._zoomAndFadeOut = _zoomAndFadeOut;
+
+
+ // HACK
+ //
+ //`Shell.BlurEffect` does not repaint when shadows are under it. [1]
+ //
+ // This does not entirely fix this bug (shadows caused by windows
+ // still cause artifacts), but it prevents the shadows of the panel
+ // buttons to cause artifacts on the panel itself
+ //
+ // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857
+
+ if (this.settings.HACKS_LEVEL === 1) {
+ this.paint_signals.disconnect_all_for_actor(icon._dialog);
+ this.paint_signals.connect(icon._dialog, blur_effect);
+ } else {
+ this.paint_signals.disconnect_all();
+ }
+ });
+ };
+
+ set_sigma(s) {
+ sigma = s;
+ if (this.settings.appfolder.BLUR)
+ this.blur_appfolders();
+ }
+
+ set_brightness(b) {
+ brightness = b;
+ if (this.settings.appfolder.BLUR)
+ this.blur_appfolders();
+ }
+
+ disable() {
+ this._log("removing blur from appfolders");
+
+ let appDisplay = Main.overview._overview.controls._appDisplay;
+
+ if (original_zoomAndFadeIn != null) {
+ appDisplay._folderIcons.forEach(icon => {
+ if (icon._dialog)
+ icon._dialog._zoomAndFadeIn = original_zoomAndFadeIn;
+ });
+ }
+
+ if (original_zoomAndFadeOut != null) {
+ appDisplay._folderIcons.forEach(icon => {
+ if (icon._dialog)
+ icon._dialog._zoomAndFadeOut = original_zoomAndFadeOut;
+ });
+ }
+
+ appDisplay._folderIcons.forEach(icon => {
+ if (icon._dialog) {
+ icon._dialog.remove_effect_by_name("appfolder-blur");
+ DIALOGS_STYLES.forEach(
+ s => icon._dialog._viewBox.remove_style_class_name(s)
+ );
+ }
+ });
+
+ this.connections.disconnect_all();
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > appfolders] ${str}`);
+ }
+}; \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/applications.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/applications.js
new file mode 100644
index 0000000..e783046
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/applications.js
@@ -0,0 +1,614 @@
+import Meta from 'gi://Meta';
+import Gio from 'gi://Gio';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import * as Config from 'resource:///org/gnome/shell/misc/config.js';
+
+import { ApplicationsService } from '../dbus/services.js';
+import { PaintSignals } from '../conveniences/paint_signals.js';
+import { DummyPipeline } from '../conveniences/dummy_pipeline.js';
+import { Pipeline } from '../conveniences/pipeline.js';
+
+
+/// Converts a wildcard pattern to a RegExp object.
+/// Supports * (matches any sequence) and ? (matches any single character).
+/// Matching is case-insensitive.
+///
+/// @param {string} pattern - The wildcard pattern (e.g., "Firefox*", "*Code*")
+/// @returns {RegExp} The compiled regex pattern
+function wildcardToRegex(pattern) {
+ // Escape special regex characters except * and ?
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&');
+ // Convert wildcards: * -> .*, ? -> .
+ const regex = '^' + escaped.replace(/\*/g, '.*').replace(/\?/g, '.') + '$';
+ return new RegExp(regex, 'i');
+}
+
+
+/// Compiles an array of wildcard patterns into RegExp objects.
+/// Caches the results to avoid recompilation on every check.
+///
+/// @param {string[]} patterns - Array of wildcard patterns
+/// @param {Map} cache - Cache map storing pattern -> regex mappings
+/// @returns {RegExp[]} Array of compiled regex patterns
+function compilePatterns(patterns, cache) {
+ return patterns.map(pattern => {
+ if (cache.has(pattern)) {
+ return cache.get(pattern);
+ }
+ const regex = wildcardToRegex(pattern);
+ cache.set(pattern, regex);
+ return regex;
+ });
+}
+
+
+/// Tests if a value matches any of the compiled patterns.
+///
+/// @param {string} value - The value to test (e.g., wm_class)
+/// @param {RegExp[]} patterns - Array of compiled regex patterns
+/// @returns {boolean} True if value matches any pattern
+function matchesAnyPattern(value, patterns) {
+ if (!value || patterns.length === 0) {
+ return false;
+ }
+ return patterns.some(pattern => pattern.test(value));
+}
+
+export const ApplicationsBlur = class ApplicationsBlur {
+ constructor(connections, settings, effects_manager) {
+ this.connections = connections;
+ this.settings = settings;
+ this.effects_manager = effects_manager;
+ this.paint_signals = new PaintSignals(connections);
+
+ // stores every blurred meta window
+ this.meta_window_map = new Map();
+
+ // cache for compiled patterns to avoid recompilation
+ this._whitelist_pattern_cache = new Map();
+ this._blacklist_pattern_cache = new Map();
+ this._compiled_whitelist = [];
+ this._compiled_blacklist = [];
+
+ // compile initial patterns
+ this._update_patterns();
+ }
+
+ /// Updates the compiled whitelist and blacklist patterns from settings.
+ /// Called during initialization and when whitelist/blacklist settings change.
+ _update_patterns() {
+ const whitelist = this.settings.applications.WHITELIST || [];
+ const blacklist = this.settings.applications.BLACKLIST || [];
+
+ this._compiled_whitelist = compilePatterns(whitelist, this._whitelist_pattern_cache);
+ this._compiled_blacklist = compilePatterns(blacklist, this._blacklist_pattern_cache);
+
+ this._log(`Patterns updated - whitelist: ${whitelist.length}, blacklist: ${blacklist.length}`);
+ }
+
+ enable() {
+ this._log("blurring applications...");
+
+ // export dbus service for preferences
+ this.service = new ApplicationsService;
+ this.service.export();
+
+ this.mutter_gsettings = new Gio.Settings({ schema: 'org.gnome.mutter' });
+
+ // blur already existing windows
+ this.update_all_windows();
+
+ // blur every new window
+ this.connections.connect(
+ global.display,
+ 'window-created',
+ (_meta_display, meta_window) => {
+ this._log("window created");
+
+ if (meta_window)
+ this.track_new(meta_window);
+ }
+ );
+
+ // update window blur when focus is changed
+ this.focused_window_pid = null;
+ this.init_dynamic_opacity();
+ this.connections.connect(
+ global.display,
+ 'focus-window',
+ (_meta_display, meta_window, _p0) => {
+ if (meta_window && meta_window.bms_pid != this.focused_window_pid)
+ this.set_focus_for_window(meta_window);
+ else if (!meta_window)
+ this.set_focus_for_window(null);
+ }
+ );
+
+ this.connect_to_overview();
+ }
+
+ /// Initializes the dynamic opacity for windows, without touching to the connections.
+ /// This is used both when enabling the component, and when changing the dynamic-opacity pref.
+ init_dynamic_opacity() {
+ if (this.settings.applications.DYNAMIC_OPACITY) {
+ // make the currently focused window solid
+ if (global.display.focus_window)
+ this.set_focus_for_window(global.display.focus_window);
+ } else {
+ // remove old focused window if the pref was changed
+ if (this.focused_window_pid)
+ this.set_focus_for_window(null);
+ }
+ }
+
+ /// Connect to the overview being opened/closed to force the blur being
+ /// shown on every window of the workspaces viewer.
+ connect_to_overview() {
+ this.connections.disconnect_all_for(Main.overview);
+
+ if (this.settings.applications.BLUR_ON_OVERVIEW) {
+ // when the overview is opened, show every window actors (which
+ // allows the blur to be shown too)
+ this.connections.connect(
+ Main.overview, 'showing',
+ _ => this.meta_window_map.forEach((meta_window, _pid) => {
+ let window_actor = meta_window.get_compositor_private();
+ window_actor?.show();
+ })
+ );
+
+ // when the overview is closed, hide every actor that is not on the
+ // current workspace (to mimic the original behaviour)
+ this.connections.connect(
+ Main.overview, 'hidden',
+ _ => {
+ this.meta_window_map.forEach((meta_window, _pid) => {
+ let window_actor = meta_window.get_compositor_private();
+
+ if (
+ (!meta_window.get_workspace().active) || meta_window.minimized
+ )
+ window_actor.hide();
+ });
+ }
+ );
+ }
+ }
+
+ /// Iterate through all existing windows and add blur as needed.
+ update_all_windows() {
+ // Recompile patterns in case whitelist/blacklist changed
+ this._update_patterns();
+
+ // remove all previously blurred windows, in the case where the
+ // whitelist was changed
+ this.meta_window_map.forEach(((_meta_window, pid) => {
+ this.remove_blur(pid);
+ }));
+
+ for (
+ let i = 0;
+ i < global.workspace_manager.get_n_workspaces();
+ ++i
+ ) {
+ let workspace = global.workspace_manager.get_workspace_by_index(i);
+ let windows = workspace.list_windows();
+
+ windows.forEach(meta_window => this.track_new(meta_window));
+ }
+ }
+
+ /// Adds the needed signals to every new tracked window, and adds blur if
+ /// needed.
+ /// Accepts only untracked meta windows (i.e no `bms_pid` set)
+ track_new(meta_window) {
+ // create a pid that will follow the window during its whole life
+ const pid = ("" + Math.random()).slice(2, 16);
+ meta_window.bms_pid = pid;
+
+ this._log(`new window tracked, pid: ${pid}`);
+
+ // register the blurred window
+ this.meta_window_map.set(pid, meta_window);
+
+ // update the blur when wm-class is changed
+ this.connections.connect(
+ meta_window, 'notify::wm-class',
+ _ => this.check_blur(meta_window)
+ );
+
+ // update the clip, position, and/or size when the window changes
+ this.connections.connect(
+ meta_window, 'size-changed',
+ _ => this.update_size(pid)
+ );
+ if (this.settings.applications.STATIC_BLUR) {
+ this.connections.connect(
+ meta_window, 'position-changed',
+ _ => this.update_size(pid)
+ );
+ }
+
+ // remove the blur when the window is unmanaged
+ this.connections.connect(
+ meta_window, 'unmanaging',
+ _ => this.untrack_meta_window(pid)
+ );
+
+ this.check_blur(meta_window);
+
+ if (this.settings.applications.STATIC_BLUR && meta_window.get_client_type() === Meta.WindowClientType.X11) {
+ const window_actor = meta_window.get_compositor_private();
+ window_actor.connect('child-added', _ => {
+ if (!meta_window.blur_actor) {
+ this._warn("can't move blur actor to back, it doesn't exist");
+ return;
+ }
+
+ window_actor.set_child_below_sibling(meta_window.blur_actor, null);
+ });
+ }
+ }
+
+ /// Updates the size of the blur actor associated to a meta window from its pid.
+ /// Accepts only tracked meta window (i.e `bms_pid` set), be it blurred or not.
+ update_size(pid) {
+ if (this.meta_window_map.has(pid)) {
+ const meta_window = this.meta_window_map.get(pid);
+ const blur_actor = meta_window.blur_actor;
+ if (blur_actor) {
+ if (this.settings.applications.STATIC_BLUR) {
+ const bg_manager = meta_window.bg_manager;
+ const bg_actor_monitor_index = bg_manager.backgroundActor.monitor;
+ const window_monitor_index = meta_window.get_monitor();
+ const monitor = Main.layoutManager.monitors[window_monitor_index];
+
+ if (bg_actor_monitor_index !== window_monitor_index) {
+ this._log(`application (pid ${pid}) switching to monitor: ${window_monitor_index}`);
+
+ // Recreate the BackgroundActor on the right monitor. This is necessary to make sure differently
+ // sized monitors have the correct scaled image of the wallpaper.
+ bg_manager._monitorIndex = window_monitor_index;
+ bg_manager._updateBackgroundActor();
+
+ // Also to fix differently sized monitor issues.
+ blur_actor.width = monitor.width;
+ blur_actor.height = monitor.height;
+ }
+
+ const frame = meta_window.get_frame_rect();
+ const buffer = meta_window.get_buffer_rect();
+ blur_actor.x = monitor.x - buffer.x;
+ blur_actor.y = monitor.y - buffer.y;
+
+ // set_clip(x-offset, y-offset, width, height)
+ blur_actor.set_clip(frame.x - monitor.x, frame.y - monitor.y, frame.width, frame.height);
+ } else {
+ const allocation = this.compute_allocation(meta_window);
+ blur_actor.x = allocation.x;
+ blur_actor.y = allocation.y;
+ blur_actor.width = allocation.width;
+ blur_actor.height = allocation.height;
+ }
+ }
+ } else
+ // the pid was visibly not removed
+ this.untrack_meta_window(pid);
+ }
+
+ /// Checks if the given actor needs to be blurred.
+ /// Accepts only tracked meta window, be it blurred or not.
+ ///
+ /// In order to be blurred, a window either:
+ /// - is whitelisted in the user preferences if not enable-all
+ /// - is not blacklisted if enable-all
+ ///
+ /// Whitelist and blacklist support wildcard patterns:
+ /// - * matches any sequence of characters
+ /// - ? matches any single character
+ /// - Matching is case-insensitive
+ check_blur(meta_window) {
+ const window_wm_class = meta_window.get_wm_class();
+ const enable_all = this.settings.applications.ENABLE_ALL;
+ if (window_wm_class)
+ this._log(`pid ${meta_window.bms_pid} associated to wm class name ${window_wm_class}`);
+
+
+ // if we are in blacklist mode and the window is not blacklisted
+ // or if we are in whitelist mode and the window is whitelisted
+ if (
+ window_wm_class !== ""
+ && ((enable_all && !matchesAnyPattern(window_wm_class, this._compiled_blacklist))
+ || (!enable_all && matchesAnyPattern(window_wm_class, this._compiled_whitelist))
+ )
+ && [
+ Meta.FrameType.NORMAL,
+ Meta.FrameType.DIALOG,
+ Meta.FrameType.MODAL_DIALOG
+ ].includes(meta_window.get_frame_type())
+ ) {
+ // only blur the window if it is not already done
+ if (!meta_window.blur_actor)
+ this.create_blur_effect(meta_window);
+ }
+
+ // remove blur it is not explicitly whitelisted or un-blacklisted
+ else if (meta_window.blur_actor)
+ this.remove_blur(meta_window.bms_pid);
+ }
+
+ /// Add the blur effect to the window.
+ /// Accepts only tracked meta window that is NOT already blurred.
+ create_blur_effect(meta_window) {
+ const pid = meta_window.bms_pid;
+ const window_actor = meta_window.get_compositor_private();
+
+ let blur_actor;
+
+ if (this.settings.applications.STATIC_BLUR) {
+ const pipeline = new Pipeline(this.effects_manager, global.blur_my_shell._pipelines_manager, this.settings.applications.PIPELINE);
+ const bg_managers = [];
+ blur_actor = pipeline.create_background_with_effects(
+ meta_window.get_monitor(), bg_managers, window_actor,
+ 'bms-application-blurred-widget'
+ );
+
+ if (bg_managers.length > 0) meta_window.bg_manager = bg_managers[0];
+ else // I've never seen this happen, but just in case
+ this._warn(`no bg_manager on blur creation for pid ${pid}`);
+ } else {
+ const pipeline = new DummyPipeline(this.effects_manager, this.settings.applications);
+ [blur_actor, meta_window.bg_manager] = pipeline.create_background_with_effect(
+ window_actor, 'bms-application-blurred-widget'
+ );
+
+ // if hacks are selected, force to repaint the window
+ if (this.settings.HACKS_LEVEL === 1) {
+ this._log("hack level 1");
+
+ this.paint_signals.disconnect_all_for_actor(blur_actor);
+ this.paint_signals.connect(blur_actor, pipeline.effect);
+ } else {
+ this.paint_signals.disconnect_all_for_actor(blur_actor);
+ }
+ }
+
+ meta_window.blur_actor = blur_actor;
+
+ // make sure window is blurred in overview
+ if (this.settings.applications.BLUR_ON_OVERVIEW)
+ this.enforce_window_visibility_on_overview_for(window_actor);
+
+ // update the size
+ this.update_size(pid);
+
+ // set the window actor's opacity
+ this.set_window_opacity(window_actor, this.settings.applications.OPACITY);
+
+ // now set up the signals, for the window actor only: they are disconnected
+ // in `remove_blur`, whereas the signals for the meta window are disconnected
+ // only when the whole component is disabled
+
+ // update the window opacity when it changes, else we don't control it fully
+ this.connections.connect(
+ window_actor, 'notify::opacity',
+ _ => {
+ if (this.focused_window_pid != pid)
+ this.set_window_opacity(window_actor, this.settings.applications.OPACITY);
+ }
+ );
+
+ // hide the blur if window becomes invisible
+ if (!window_actor.visible)
+ blur_actor.hide();
+
+ this.connections.connect(
+ window_actor,
+ 'notify::visible',
+ window_actor => {
+ if (window_actor.visible)
+ meta_window.blur_actor.show();
+ else
+ meta_window.blur_actor.hide();
+ }
+ );
+ }
+
+ /// With `focus=true`, tells us we are focused on said window (which can be null if
+ /// we are not focused anymore). It automatically removes the ancient focus.
+ /// With `focus=false`, just remove the focus from said window (which can still be null).
+ set_focus_for_window(meta_window, focus = true) {
+ let blur_actor = null;
+ let window_actor = null;
+ let new_pid = null;
+ if (meta_window) {
+ blur_actor = meta_window.blur_actor;
+ window_actor = meta_window.get_compositor_private();
+ new_pid = meta_window.bms_pid;
+ }
+
+ if (focus) {
+ // remove old focused window if any
+ if (this.focused_window_pid) {
+ const old_focused_window = this.meta_window_map.get(this.focused_window_pid);
+ if (old_focused_window)
+ this.set_focus_for_window(old_focused_window, false);
+ }
+ // set new focused window pid
+ this.focused_window_pid = new_pid;
+ // if we have blur, hide it and make the window opaque
+ if (this.settings.applications.DYNAMIC_OPACITY && blur_actor) {
+ blur_actor.hide();
+ this.set_window_opacity(window_actor, 255);
+ }
+ }
+ // if we remove the focus and have blur, show it and make the window transparent
+ else if (blur_actor) {
+ blur_actor.show();
+ this.set_window_opacity(window_actor, this.settings.applications.OPACITY);
+ }
+ }
+
+ /// Makes sure that, when the overview is visible, the window actor will
+ /// stay visible no matter what.
+ /// We can instead hide the last child of the window actor, which will
+ /// improve performances without hiding the blur effect.
+ enforce_window_visibility_on_overview_for(window_actor) {
+ this.connections.connect(window_actor, 'notify::visible',
+ _ => {
+ if (this.settings.applications.BLUR_ON_OVERVIEW) {
+ if (
+ !window_actor.visible
+ && Main.overview.visible
+ ) {
+ window_actor.show();
+ window_actor.get_last_child().hide();
+ } else if (
+ window_actor.visible
+ )
+ window_actor.get_last_child().show();
+ }
+ }
+ );
+ }
+
+ /// Set the opacity of the window actor that sits on top of the blur effect.
+ set_window_opacity(window_actor, opacity) {
+ window_actor?.get_children().forEach(child => {
+ if (child.name !== "blur-actor" && child.opacity != opacity)
+ child.opacity = opacity;
+ });
+ }
+
+ /// Update the opacity of all window actors.
+ set_opacity() {
+ let opacity = this.settings.applications.OPACITY;
+
+ this.meta_window_map.forEach(((meta_window, pid) => {
+ if (pid != this.focused_window_pid && meta_window.blur_actor) {
+ let window_actor = meta_window.get_compositor_private();
+ this.set_window_opacity(window_actor, opacity);
+ }
+ }));
+ }
+
+ /// Find the system's window scaling.
+ /// If `scale-monitor-framebuffer` experimental feature if on, we don't need to manage scaling.
+ /// Else, on wayland, we need to divide by the scale to get the correct result.
+ compute_scale(meta_window) {
+ // TODO: Drop GNOME <50 compatibility
+ const gnome_shell_major_version = parseInt(Config.PACKAGE_VERSION.split('.')[0]);
+ const scale_monitor_framebuffer =
+ gnome_shell_major_version >= 50 ||
+ this.mutter_gsettings
+ .get_strv('experimental-features')
+ .includes('scale-monitor-framebuffer');
+ const is_wayland = gnome_shell_major_version >= 50 ||
+ (typeof Meta.is_wayland_compositor === 'function'
+ ? Meta.is_wayland_compositor()
+ : global.display?.is_wayland_compositor?.() ?? true);
+ const monitor_index = meta_window.get_monitor();
+ // check if the window is using wayland, or xwayland/xorg for rendering
+ return !scale_monitor_framebuffer && is_wayland && meta_window.get_client_type() == 0
+ ? Main.layoutManager.monitors[monitor_index].geometry_scale
+ : 1;
+ }
+
+ /// Compute the size and position for a blur actor.
+ /// Coordinates are relative to window buffer's corner.
+ compute_allocation(meta_window) {
+ const scale = this.compute_scale(meta_window);
+
+ let frame = meta_window.get_frame_rect();
+ let buffer = meta_window.get_buffer_rect();
+
+ return {
+ x: (frame.x - buffer.x) / scale,
+ y: (frame.y - buffer.y) / scale,
+ width: frame.width / scale,
+ height: frame.height / scale
+ };
+ }
+
+ change_blur_type() {
+ this._log("resetting...");
+
+ this.disable();
+ setTimeout(_ => this.enable(), 1);
+ }
+
+ change_pipeline() {
+ this.update_all_windows();
+ }
+
+ /// Removes the blur actor to make a blurred window become normal again.
+ /// It however does not untrack the meta window itself.
+ /// Accepts a pid corresponding (or not) to a blurred (or not) meta window.
+ remove_blur(pid) {
+ this._log(`removing blur for pid ${pid}`);
+
+ let meta_window = this.meta_window_map.get(pid);
+ if (meta_window) {
+ let window_actor = meta_window.get_compositor_private();
+ let blur_actor = meta_window.blur_actor;
+ let bg_manager = meta_window.bg_manager;
+
+ if (blur_actor && window_actor) {
+ // reset the opacity
+ this.set_window_opacity(window_actor, 255);
+
+ // remove the blurred actor
+ window_actor.remove_child(blur_actor);
+ bg_manager._bms_pipeline.destroy();
+ bg_manager.destroy();
+ blur_actor.destroy();
+
+ // kinda untrack the blurred actor, as its presence is how we know
+ // whether we are blurred or not
+ delete meta_window.blur_actor;
+ delete meta_window.bg_manager;
+
+ // disconnect the signals of the window actor
+ this.paint_signals.disconnect_all_for_actor(blur_actor);
+ this.connections.disconnect_all_for(window_actor);
+ }
+ }
+ }
+
+ /// Kinda the same as `remove_blur`, but better: it also untracks the window.
+ /// This needs to be called when the component is being disabled, else it
+ /// would cause havoc by having untracked windows during normal operations,
+ /// which is not the point at all!
+ /// Accepts a pid corresponding (or not) to a blurred (or not) meta window.
+ untrack_meta_window(pid) {
+ this.remove_blur(pid);
+ let meta_window = this.meta_window_map.get(pid);
+ if (meta_window) {
+ this.connections.disconnect_all_for(meta_window);
+ this.meta_window_map.delete(pid);
+ }
+ }
+
+ disable() {
+ this._log("removing blur from applications...");
+
+ this.service?.unexport();
+ delete this.mutter_gsettings;
+
+ this.meta_window_map.forEach((_meta_window, pid) => {
+ this.untrack_meta_window(pid);
+ });
+
+ this.connections.disconnect_all();
+ this.paint_signals.disconnect_all();
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > applications] ${str}`);
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > applications] ${str}`);
+ }
+};
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/coverflow_alt_tab.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/coverflow_alt_tab.js
new file mode 100644
index 0000000..4e6062a
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/coverflow_alt_tab.js
@@ -0,0 +1,91 @@
+import * as Main from "resource:///org/gnome/shell/ui/main.js";
+
+import { PaintSignals } from "../conveniences/paint_signals.js";
+import { Pipeline } from "../conveniences/pipeline.js";
+
+export const CoverflowAltTabBlur = class CoverflowAltTabBlur {
+ constructor(connections, settings, effects_manager) {
+ this.connections = connections;
+ this.settings = settings;
+ this.paint_signals = new PaintSignals(connections);
+ this.effects_manager = effects_manager;
+ this.background_actors = [];
+ this.background_managers = [];
+ }
+
+ enable() {
+ this._log("blurring coverflow alt-tab");
+
+ this.update_backgrounds();
+
+ this.connections.connect(
+ Main.layoutManager.uiGroup,
+ "child-added",
+ (_, child) => this.try_blur(child)
+ );
+
+ this.connections.connect(Main.layoutManager, "monitors-changed", (_) => {
+ this.update_backgrounds();
+ });
+ }
+
+ update_backgrounds() {
+ this.remove_background_actors();
+
+ Main.layoutManager.uiGroup
+ .get_children()
+ .forEach((child) => this.try_blur(child));
+ }
+
+ try_blur(actor) {
+ if (
+ actor.constructor.name !== "Meta_BackgroundGroup" ||
+ actor.get_name() !== "coverflow-alt-tab-background-group"
+ ) {
+ return;
+ }
+
+ this._log("found coverflow alt-tab to blur");
+
+ for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
+ const pipeline = new Pipeline(
+ this.effects_manager,
+ global.blur_my_shell._pipelines_manager,
+ this.settings.coverflow_alt_tab.PIPELINE
+ );
+
+ const background_actor = pipeline.create_background_with_effects(
+ i,
+ this.background_managers,
+ actor,
+ "bms-coverflow-alt-tab-blurred-widget"
+ );
+
+ this.background_actors.push(background_actor);
+ }
+ }
+
+ remove_background_actors() {
+ this.background_actors.forEach((actor) => actor.destroy());
+ this.background_actors = [];
+
+ this.background_managers.forEach((background_manager) => {
+ background_manager._bms_pipeline.destroy();
+ background_manager.destroy();
+ });
+ this.background_managers = [];
+ }
+
+ disable() {
+ this._log("removing blur from coverflow alt-tab");
+
+ this.remove_background_actors();
+ this.connections.disconnect_all();
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG) {
+ console.log(`[Blur my Shell > coverflow alt-tab] ${str}`);
+ }
+ }
+};
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/dash_to_dock.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/dash_to_dock.js
new file mode 100644
index 0000000..4ff212c
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/dash_to_dock.js
@@ -0,0 +1,421 @@
+import Meta from 'gi://Meta';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import * as Signals from 'resource:///org/gnome/shell/misc/signals.js';
+
+import { PaintSignals } from '../conveniences/paint_signals.js';
+
+import { Pipeline } from '../conveniences/pipeline.js';
+import { DummyPipeline } from '../conveniences/dummy_pipeline.js';
+
+const DASH_STYLES = [
+ "transparent-dash",
+ "light-dash",
+ "dark-dash"
+];
+
+
+/// This type of object is created for every dash found, and talks to the main
+/// DashBlur thanks to signals.
+///
+/// This allows to dynamically track the created dashes for each screen.
+class DashInfos {
+ constructor(
+ dash_blur, dash, dash_container, dash_background,
+ background, background_group, bg_manager
+ ) {
+ // the parent DashBlur object, to communicate
+ this.dash_blur = dash_blur;
+ this.dash = dash;
+ this.dash_container = dash_container;
+ this.dash_background = dash_background;
+ this.background = background;
+ this.background_group = background_group;
+ this.bg_manager = bg_manager;
+ this.settings = dash_blur.settings;
+ this.old_style = this.dash._background.style;
+
+ this.dash_destroy_id = dash.connect('destroy', () => this.remove_dash_blur(false));
+ this.dash_blur_connections_ids = [];
+ this.dash_blur_connections_ids.push(
+ this.dash_blur.connect('remove-dashes', () => this.remove_dash_blur()),
+ this.dash_blur.connect('override-style', () => this.override_style()),
+ this.dash_blur.connect('remove-style', () => this.remove_style()),
+ this.dash_blur.connect('show', () => this.background_group.show()),
+ this.dash_blur.connect('hide', () => this.background_group.hide()),
+ this.dash_blur.connect('update-size', () => this.update_size()),
+ this.dash_blur.connect('change-blur-type', () => this.change_blur_type()),
+ this.dash_blur.connect('update-pipeline', () => this.update_pipeline())
+ );
+ }
+
+ // IMPORTANT: do never call this in a mutable `this.dash_blur.forEach`
+ remove_dash_blur(dash_not_already_destroyed = true) {
+ // remove the style and destroy the effects
+ this.remove_style();
+ this.destroy_dash(dash_not_already_destroyed);
+
+ // remove the dash infos from their list
+ const dash_infos_index = this.dash_blur.dashes.indexOf(this);
+ if (dash_infos_index >= 0)
+ this.dash_blur.dashes.splice(dash_infos_index, 1);
+
+ // disconnect everything
+ this.dash_blur_connections_ids.forEach(id => { if (id) this.dash_blur.disconnect(id); });
+ this.dash_blur_connections_ids = [];
+ if (this.dash_destroy_id)
+ this.dash.disconnect(this.dash_destroy_id);
+ this.dash_destroy_id = null;
+ }
+
+ override_style() {
+ this.remove_style();
+
+ this.dash.set_style_class_name(
+ DASH_STYLES[this.settings.dash_to_dock.STYLE_DASH_TO_DOCK]
+ );
+ }
+
+ remove_style() {
+ this.dash._background.style = this.old_style;
+
+ DASH_STYLES.forEach(
+ style => this.dash.remove_style_class_name(style)
+ );
+ }
+
+ destroy_dash(dash_not_already_destroyed = true) {
+ if (!dash_not_already_destroyed)
+ this.bg_manager.backgroundActor = null;
+
+ this.paint_signals?.disconnect_all();
+ this.dash.get_parent().remove_child(this.background_group);
+ this.bg_manager._bms_pipeline.destroy();
+ this.bg_manager.destroy();
+ this.background_group.destroy();
+ }
+
+ change_blur_type() {
+ this.destroy_dash();
+
+ let [
+ background, background_group, bg_manager, paint_signals
+ ] = this.dash_blur.add_blur(this.dash);
+
+ this.background = background;
+ this.background_group = background_group;
+ this.bg_manager = bg_manager;
+ this.paint_signals = paint_signals;
+
+ this.dash.get_parent().insert_child_at_index(this.background_group, 0);
+
+ this.update_size();
+ }
+
+ update_pipeline() {
+ this.bg_manager._bms_pipeline.change_pipeline_to(
+ this.settings.dash_to_dock.PIPELINE
+ );
+ }
+
+ update_size() {
+ if (this.dash_blur.is_static) {
+ let [x, y] = this.get_dash_position(this.dash_container, this.dash_background);
+
+ this.background.x = -x;
+ this.background.y = -y;
+
+ if (this.dash_container.get_style_class_name().includes("top"))
+ this.background.set_clip(
+ x,
+ y + this.dash.y + this.dash_background.y,
+ this.dash_background.width,
+ this.dash_background.height
+ );
+ else if (this.dash_container.get_style_class_name().includes("bottom"))
+ this.background.set_clip(
+ x,
+ y + this.dash.y + this.dash_background.y,
+ this.dash_background.width,
+ this.dash_background.height
+ );
+ else if (this.dash_container.get_style_class_name().includes("left"))
+ this.background.set_clip(
+ x + this.dash.x + this.dash_background.x,
+ y + this.dash.y + this.dash_background.y,
+ this.dash_background.width,
+ this.dash_background.height
+ );
+ else if (this.dash_container.get_style_class_name().includes("right"))
+ this.background.set_clip(
+ x + this.dash.x + this.dash_background.x,
+ y + this.dash.y + this.dash_background.y,
+ this.dash_background.width,
+ this.dash_background.height
+ );
+ } else {
+ this.background.width = this.dash_background.width;
+ this.background.height = this.dash_background.height;
+
+ this.background.x = this.dash_background.x;
+ this.background.y = this.dash_background.y + this.dash.y;
+ }
+ }
+
+ get_dash_position(dash_container, dash_background) {
+ var x, y;
+
+ let monitor = Main.layoutManager.findMonitorForActor(dash_container);
+ let dash_box = dash_container._slider.get_child();
+
+ if (dash_container.get_style_class_name().includes("top")) {
+ x = (monitor.width - dash_background.width) / 2;
+ y = dash_box.y;
+ } else if (dash_container.get_style_class_name().includes("bottom")) {
+ x = (monitor.width - dash_background.width) / 2;
+ y = monitor.height - dash_container.height;
+ } else if (dash_container.get_style_class_name().includes("left")) {
+ x = dash_box.x;
+ y = dash_container.y + (dash_container.height - dash_background.height) / 2 - dash_background.y;
+ } else if (dash_container.get_style_class_name().includes("right")) {
+ x = monitor.width - dash_container.width;
+ y = dash_container.y + (dash_container.height - dash_background.height) / 2 - dash_background.y;
+ }
+
+ return [x, y];
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > dash] ${str}`);
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > dash] ${str}`);
+ }
+}
+
+export const DashBlur = class DashBlur extends Signals.EventEmitter {
+ constructor(connections, settings, _) {
+ super();
+ this.dashes = [];
+ this.connections = connections;
+ this.settings = settings;
+ this.paint_signals = new PaintSignals(connections);
+ this.is_static = this.settings.dash_to_dock.STATIC_BLUR;
+ this.enabled = false;
+ }
+
+ enable() {
+ this.connections.connect(Main.uiGroup, 'child-added', (_, actor) => {
+ if (
+ (actor.get_name() === "dashtodockContainer") &&
+ (actor.constructor.name === 'DashToDock')
+ )
+ this.try_blur(actor);
+ });
+
+ this.blur_existing_dashes();
+ this.connect_to_overview();
+
+ this.update_size();
+
+ this.enabled = true;
+ }
+
+ // Finds all existing dashes on every monitor, and call `try_blur` on them
+ // We cannot only blur `Main.overview.dash`, as there could be several
+ blur_existing_dashes() {
+ this._log("searching for dash");
+
+ // blur every dash found, filtered by name
+ Main.uiGroup.get_children().filter((child) => {
+ return (child.get_name() === "dashtodockContainer") &&
+ (child.constructor.name === 'DashToDock');
+ }).forEach(dash_container => this.try_blur(dash_container));
+ }
+
+ // Tries to blur the dash contained in the given actor
+ try_blur(dash_container) {
+ let dash_box = dash_container._slider.get_child();
+
+ // verify that we did not already blur that dash
+ if (!dash_box.get_children().some(child =>
+ child.get_name() === "bms-dash-backgroundgroup"
+ )) {
+ this._log("dash to dock found, blurring it");
+
+ // finally blur the dash
+ let dash = dash_box.get_children().find(child => {
+ return child.get_name() === 'dash';
+ });
+
+ this.dashes.push(this.blur_dash_from(dash, dash_container));
+ }
+ }
+
+ // Blurs the dash and returns a `DashInfos` containing its information
+ blur_dash_from(dash, dash_container) {
+ let [background, background_group, bg_manager, paint_signals] = this.add_blur(dash);
+
+ // insert the background group to the right element
+ dash.get_parent().insert_child_at_index(background_group, 0);
+
+ // updates size and position on change
+ this.connections.connect(
+ dash,
+ ['notify::width', 'notify::height'],
+ _ => this.update_size()
+ );
+ this.connections.connect(
+ dash_container,
+ ['notify::width', 'notify::height', 'notify::y', 'notify::x'],
+ _ => this.update_size()
+ );
+
+ const dash_background = dash.get_children().find(child => {
+ return child.get_style_class_name() === 'dash-background';
+ });
+
+ // create infos
+ let infos = new DashInfos(
+ this,
+ dash,
+ dash_container,
+ dash_background,
+ background,
+ background_group,
+ bg_manager,
+ paint_signals
+ );
+
+ this.update_size();
+ this.update_background();
+
+ // returns infos
+ return infos;
+ }
+
+ add_blur(dash) {
+ const monitor = Main.layoutManager.findMonitorForActor(dash);
+ if (!monitor)
+ return;
+
+ const background_group = new Meta.BackgroundGroup({
+ name: 'bms-dash-backgroundgroup', width: 0, height: 0
+ });
+
+ let background, bg_manager, paint_signals;
+ let static_blur = this.settings.dash_to_dock.STATIC_BLUR;
+ if (static_blur) {
+ let bg_manager_list = [];
+ const pipeline = new Pipeline(
+ global.blur_my_shell._effects_manager,
+ global.blur_my_shell._pipelines_manager,
+ this.settings.dash_to_dock.PIPELINE
+ );
+ background = pipeline.create_background_with_effects(
+ monitor.index, bg_manager_list,
+ background_group, 'bms-dash-blurred-widget'
+ );
+ bg_manager = bg_manager_list[0];
+ }
+ else {
+ const pipeline = new DummyPipeline(
+ global.blur_my_shell._effects_manager,
+ this.settings.dash_to_dock
+ );
+ [background, bg_manager] = pipeline.create_background_with_effect(
+ background_group, 'bms-dash-blurred-widget'
+ );
+
+ paint_signals = new PaintSignals(this.connections);
+
+ // HACK
+ //
+ //`Shell.BlurEffect` does not repaint when shadows are under it. [1]
+ //
+ // This does not entirely fix this bug (shadows caused by windows
+ // still cause artifacts), but it prevents the shadows of the dash
+ // buttons to cause artifacts on the dash itself
+ //
+ // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857
+
+ if (this.settings.HACKS_LEVEL === 1) {
+ this._log("hack level 1");
+
+ paint_signals.disconnect_all();
+ paint_signals.connect(background, pipeline.effect);
+ } else {
+ paint_signals.disconnect_all();
+ }
+ }
+
+ return [background, background_group, bg_manager, paint_signals];
+ }
+
+ change_blur_type() {
+ this.is_static = this.settings.dash_to_dock.STATIC_BLUR;
+ this.emit('change-blur-type');
+
+ this.update_background();
+ }
+
+ /// Connect when overview if opened/closed to hide/show the blur accordingly
+ connect_to_overview() {
+ this.connections.disconnect_all_for(Main.overview);
+
+ if (this.settings.dash_to_dock.UNBLUR_IN_OVERVIEW) {
+ this.connections.connect(
+ Main.overview, 'showing', _ => this.hide()
+ );
+ this.connections.connect(
+ Main.overview, 'hidden', _ => this.show()
+ );
+ }
+ };
+
+ /// Updates the background to either remove it or not, according to the
+ /// user preferences.
+ update_background() {
+ this._log("updating background");
+ if (this.settings.dash_to_dock.OVERRIDE_BACKGROUND)
+ this.emit('override-style');
+ else
+ this.emit('remove-style');
+ }
+
+ update_pipeline() {
+ this.emit('update-pipeline');
+ }
+
+ update_size() {
+ this.emit('update-size');
+ }
+
+ show() {
+ this.emit('show');
+ }
+ hide() {
+ this.emit('hide');
+ }
+
+ disable() {
+ this._log("removing blur from dashes");
+
+ this.emit('remove-dashes');
+
+ this.dashes = [];
+ this.connections.disconnect_all();
+
+ this.enabled = false;
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > dash manager] ${str}`);
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > dash manager] ${str}`);
+ }
+}; \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/lockscreen.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/lockscreen.js
new file mode 100644
index 0000000..7755ba9
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/lockscreen.js
@@ -0,0 +1,89 @@
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import { UnlockDialog } from 'resource:///org/gnome/shell/ui/unlockDialog.js';
+
+import { Pipeline } from '../conveniences/pipeline.js';
+
+const original_createBackground =
+ UnlockDialog.prototype._createBackground;
+const original_updateBackgroundEffects =
+ UnlockDialog.prototype._updateBackgroundEffects;
+const original_updateBackgrounds =
+ UnlockDialog.prototype._updateBackgrounds;
+
+
+export const LockscreenBlur = class LockscreenBlur {
+ constructor(connections, settings, effects_manager) {
+ this.connections = connections;
+ this.settings = settings;
+ this.effects_manager = effects_manager;
+ this.enabled = false;
+ }
+
+ enable() {
+ this._log("blurring lockscreen");
+
+ this.update_lockscreen();
+
+ this.enabled = true;
+ }
+
+ update_lockscreen() {
+ UnlockDialog.prototype._createBackground =
+ this._createBackground;
+ UnlockDialog.prototype._updateBackgroundEffects =
+ this._updateBackgroundEffects;
+ UnlockDialog.prototype._updateBackgrounds =
+ this._updateBackgrounds;
+ }
+
+ _createBackground(monitor_index) {
+ let pipeline = new Pipeline(
+ global.blur_my_shell._effects_manager, global.blur_my_shell._pipelines_manager,
+ global.blur_my_shell._settings.lockscreen.PIPELINE
+ );
+
+ pipeline.create_background_with_effects(
+ monitor_index,
+ this._bgManagers,
+ this._backgroundGroup,
+ "screen-shield-background"
+ );
+ }
+
+ _updateBackgroundEffects() {
+ this._updateBackgrounds();
+ }
+
+ _updateBackgrounds() {
+ for (let i = 0; i < this._bgManagers.length; i++) {
+ this._bgManagers[i]._bms_pipeline.destroy();
+ this._bgManagers[i].destroy();
+ }
+
+ this._bgManagers = [];
+ this._backgroundGroup.destroy_all_children();
+
+ for (let i = 0; i < Main.layoutManager.monitors.length; i++)
+ this._createBackground(i);
+ }
+
+ disable() {
+ this._log("removing blur from lockscreen");
+
+ UnlockDialog.prototype._createBackground =
+ original_createBackground;
+ UnlockDialog.prototype._updateBackgroundEffects =
+ original_updateBackgroundEffects;
+ UnlockDialog.prototype._updateBackgrounds =
+ original_updateBackgrounds;
+
+ this.connections.disconnect_all();
+
+ this.enabled = false;
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > lockscreen] ${str}`);
+ }
+};
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/overview.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/overview.js
new file mode 100644
index 0000000..50a625e
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/overview.js
@@ -0,0 +1,226 @@
+import Meta from 'gi://Meta';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+
+import { WorkspaceAnimationController } from 'resource:///org/gnome/shell/ui/workspaceAnimation.js';
+const wac_proto = WorkspaceAnimationController.prototype;
+
+import { Pipeline } from '../conveniences/pipeline.js';
+
+const OVERVIEW_COMPONENTS_STYLE = [
+ "overview-components-light",
+ "overview-components-dark",
+ "overview-components-transparent"
+];
+
+
+export const OverviewBlur = class OverviewBlur {
+ constructor(connections, settings, effects_manager) {
+ this.connections = connections;
+ this.settings = settings;
+ this.effects_manager = effects_manager;
+ this.overview_background_managers = [];
+ this.overview_background_group = new Meta.BackgroundGroup(
+ { name: 'bms-overview-backgroundgroup' }
+ );
+ this.animation_background_managers = [];
+ this.animation_background_group = new Meta.BackgroundGroup(
+ { name: 'bms-animation-backgroundgroup' }
+ );
+ this.enabled = false;
+ this.proto_patched = false;
+ }
+
+ enable() {
+ this._log("blurring overview");
+
+ // add css class name for workspace-switch background
+ Main.uiGroup.add_style_class_name("blurred-overview");
+
+ // add css class name to make components semi-transparent if wanted
+ this.update_components_classname();
+
+ // update backgrounds when the component is enabled
+ this.update_backgrounds();
+
+ // connect to monitors change
+ this.connections.connect(Main.layoutManager, 'monitors-changed',
+ _ => this.update_backgrounds()
+ );
+
+ // part for the workspace animation switch
+
+ // make sure not to do this part if the functions were patched prior, as
+ // the functions would call themselves and cause infinite recursion
+ if (!this.proto_patched) {
+ // store original workspace switching methods for restoring them on
+ // disable()
+ this._original_PrepareSwitch = wac_proto._prepareWorkspaceSwitch;
+ this._original_FinishSwitch = wac_proto._finishWorkspaceSwitch;
+
+ const w_m = global.workspace_manager;
+ const outer_this = this;
+
+ // create a blurred background actor for each monitor during a
+ // workspace switch
+ wac_proto._prepareWorkspaceSwitch = function (...params) {
+ outer_this._log("prepare workspace switch");
+ outer_this._original_PrepareSwitch.apply(this, params);
+
+ // this permits to show the blur behind windows that are on
+ // workspaces on the left and right
+ if (
+ outer_this.settings.applications.BLUR
+ ) {
+ let ws_index = w_m.get_active_workspace_index();
+ [ws_index - 1, ws_index + 1].forEach(
+ i => w_m.get_workspace_by_index(i)?.list_windows().forEach(
+ window => window.get_compositor_private().show()
+ )
+ );
+ }
+
+ Main.uiGroup.insert_child_above(
+ outer_this.animation_background_group,
+ global.window_group
+ );
+
+ outer_this.animation_background_managers.forEach(bg_manager => {
+ if (bg_manager._bms_pipeline.actor)
+ if (
+ Meta.prefs_get_workspaces_only_on_primary() &&
+ bg_manager._monitorIndex !== Main.layoutManager.primaryMonitor.index
+ )
+ bg_manager._bms_pipeline.actor.visible = false;
+ else
+ bg_manager._bms_pipeline.actor.visible = true;
+ });
+ };
+
+ // remove the workspace-switch actors when the switch is done
+ wac_proto._finishWorkspaceSwitch = function (...params) {
+ outer_this._log("finish workspace switch");
+ outer_this._original_FinishSwitch.apply(this, params);
+
+ // this hides windows that are not on the current workspace
+ if (
+ outer_this.settings.applications.BLUR
+ )
+ for (let i = 0; i < w_m.get_n_workspaces(); i++) {
+ if (i != w_m.get_active_workspace_index())
+ w_m.get_workspace_by_index(i)?.list_windows().forEach(
+ window => window.get_compositor_private().hide()
+ );
+ }
+
+ Main.uiGroup.remove_child(outer_this.animation_background_group);
+ };
+
+ this.proto_patched = true;
+ }
+
+ this.enabled = true;
+ }
+
+ update_backgrounds() {
+ // remove every old background
+ this.remove_background_actors();
+ // create new backgrounds for the overview and the animation
+ for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
+ const pipeline_overview = new Pipeline(
+ this.effects_manager,
+ global.blur_my_shell._pipelines_manager,
+ this.settings.overview.PIPELINE
+ );
+ pipeline_overview.create_background_with_effects(
+ i, this.overview_background_managers,
+ this.overview_background_group, 'bms-overview-blurred-widget'
+ );
+
+ const pipeline_animation = new Pipeline(
+ this.effects_manager,
+ global.blur_my_shell._pipelines_manager,
+ this.settings.overview.PIPELINE
+ );
+ pipeline_animation.create_background_with_effects(
+ i, this.animation_background_managers,
+ this.animation_background_group, 'bms-animation-blurred-widget'
+ );
+ }
+ // add the container widget for the overview only to the overview group
+ Main.layoutManager.overviewGroup.insert_child_at_index(this.overview_background_group, 0);
+ // make sure it stays below
+ this.connections.connect(Main.layoutManager.overviewGroup, "child-added", (_, child) => {
+ if (child !== this.overview_background_group) {
+ if (this.overview_background_group.get_parent())
+ Main.layoutManager.overviewGroup.remove_child(this.overview_background_group);
+ Main.layoutManager.overviewGroup.insert_child_at_index(this.overview_background_group, 0);
+ }
+ });
+ }
+
+ /// Updates the classname to style overview components with semi-transparent
+ /// backgrounds.
+ update_components_classname() {
+ OVERVIEW_COMPONENTS_STYLE.forEach(
+ style => Main.uiGroup.remove_style_class_name(style)
+ );
+
+ if (this.settings.overview.STYLE_COMPONENTS > 0)
+ Main.uiGroup.add_style_class_name(
+ OVERVIEW_COMPONENTS_STYLE[this.settings.overview.STYLE_COMPONENTS - 1]
+ );
+ }
+
+ remove_background_actors() {
+ this.overview_background_group.remove_all_children();
+ this.animation_background_group.remove_all_children();
+
+ this.connections.disconnect_all_for(Main.layoutManager.overviewGroup);
+ if (this.overview_background_group.get_parent())
+ Main.layoutManager.overviewGroup.remove_child(this.overview_background_group);
+
+ this.overview_background_managers.forEach(background_manager => {
+ background_manager._bms_pipeline.destroy();
+ background_manager.destroy();
+ });
+ this.animation_background_managers.forEach(background_manager => {
+ background_manager._bms_pipeline.destroy();
+ background_manager.destroy();
+ });
+ this.overview_background_managers = [];
+ this.animation_background_managers = [];
+ }
+
+ disable() {
+ this._log("removing blur from overview");
+
+ this.remove_background_actors();
+ Main.uiGroup.remove_style_class_name("blurred-overview");
+ OVERVIEW_COMPONENTS_STYLE.forEach(
+ style => Main.uiGroup.remove_style_class_name(style)
+ );
+
+ this.connections.disconnect_all();
+ this.enabled = false;
+ }
+
+ restore_patched_proto() {
+ if (this.proto_patched) {
+ if (this._original_PrepareSwitch)
+ wac_proto._prepareWorkspaceSwitch = this._original_PrepareSwitch;
+ if (this._original_FinishSwitch)
+ wac_proto._finishWorkspaceSwitch = this._original_FinishSwitch;
+
+ this.proto_patched = false;
+ }
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > overview] ${str}`);
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > overview] ${str}`);
+ }
+};
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/panel.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/panel.js
new file mode 100644
index 0000000..6c084cf
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/panel.js
@@ -0,0 +1,577 @@
+import St from 'gi://St';
+import GLib from 'gi://GLib';
+import Meta from 'gi://Meta';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+
+import { PaintSignals } from '../conveniences/paint_signals.js';
+
+import { Pipeline } from '../conveniences/pipeline.js';
+import { DummyPipeline } from '../conveniences/dummy_pipeline.js';
+
+const DASH_TO_PANEL_UUID = 'dash-to-panel@jderose9.github.com';
+const PANEL_STYLES = [
+ "transparent-panel",
+ "light-panel",
+ "dark-panel",
+ "contrasted-panel"
+];
+
+// global listener, so we don't miss the panel destruction event
+let isMainPanelAlive = true;
+Main.panel.connect('destroy', () => isMainPanelAlive = false);
+
+export const PanelBlur = class PanelBlur {
+ constructor(connections, settings, effects_manager) {
+ this.connections = connections;
+ this.window_signal_ids = new Map();
+ this.settings = settings;
+ this.effects_manager = effects_manager;
+ this.actors_list = [];
+ this.enabled = false;
+ }
+
+ enable() {
+ if (this.enabled) {
+ this._log("blur already enabled");
+ return;
+ }
+
+ this._log("blurring top panel");
+
+ // check for panels when Dash to Panel is activated
+ this.connections.connect(
+ Main.extensionManager,
+ 'extension-state-changed',
+ (_, extension) => {
+ if (extension.uuid === DASH_TO_PANEL_UUID
+ && extension.state === 1
+ ) {
+ this.connections.connect(
+ global.dashToPanel,
+ 'panels-created',
+ _ => this.blur_dtp_panels()
+ );
+
+ this.blur_existing_panels();
+ }
+ }
+ );
+
+ this.blur_existing_panels();
+
+ // connect to overview being opened/closed, and dynamically show or not
+ // the blur when a window is near a panel
+ this.connect_to_windows_and_overview();
+
+ // connect to workareas change
+ this.connections.connect(global.display, 'workareas-changed',
+ _ => this.reset()
+ );
+
+ this.enabled = true;
+ }
+
+ reset() {
+ if (!this.enabled) {
+ this._log("reset called but blur is not enabled");
+ return;
+ }
+
+ this._log("resetting...");
+
+ this.disable();
+ setTimeout(_ => this.enable(), 1);
+ }
+
+ /// Check for already existing panels and blur them if they are not already
+ blur_existing_panels() {
+ // check if dash-to-panel is present
+ if (global.dashToPanel) {
+ // blur already existing ones
+ if (global.dashToPanel.panels)
+ this.blur_dtp_panels();
+
+ // blur main panel if requested in settings
+ if (this.settings.dash_to_panel.BLUR_ORIGINAL_PANEL && isMainPanelAlive)
+ this.maybe_blur_panel(Main.panel);
+ } else {
+ // if no dash-to-panel, blur the main and only panel
+ this.maybe_blur_panel(Main.panel);
+ }
+ }
+
+ blur_dtp_panels() {
+ // Defer the blurring to the next idle cycle.
+ // This is crucial to ensure the panel actors have been allocated their
+ // final size and position by the compositor, avoiding race conditions
+ // during extension startup.
+ GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
+ if (!global.dashToPanel?.panels) {
+ return GLib.SOURCE_REMOVE;
+ }
+
+ this._log("Blurring Dash to Panel panels after idle.");
+
+ // blur every panel, except Main.panel (this is handled in blur_existing_panels() method above)
+ global.dashToPanel.panels.forEach(p => {
+ if (p.panel != Main.panel)
+ this.maybe_blur_panel(p.panel);
+ });
+
+ return GLib.SOURCE_REMOVE;
+ });
+ };
+
+ /// Blur a panel only if it is not already blurred (contained in the list)
+ maybe_blur_panel(panel) {
+ // check if the panel is contained in the list
+ let actors = this.actors_list.find(
+ actors => actors.widgets.panel == panel
+ );
+
+ if (!actors)
+ // if the actors is not blurred, blur it
+ this.blur_panel(panel);
+ }
+
+ /// Blur a panel
+ blur_panel(panel) {
+ let panel_box = panel.get_parent();
+ let is_dtp_panel = false;
+ if (!panel_box.name) {
+ is_dtp_panel = true;
+ panel_box = panel_box.get_parent();
+ }
+
+ let monitor = Main.layoutManager.findMonitorForActor(panel);
+ if (!monitor)
+ return;
+
+ let background_group = new Meta.BackgroundGroup(
+ { name: 'bms-panel-backgroundgroup', width: 0, height: 0 }
+ );
+
+ let background, bg_manager;
+ let static_blur = this.settings.panel.STATIC_BLUR;
+ if (static_blur) {
+ let bg_manager_list = [];
+ const pipeline = new Pipeline(
+ this.effects_manager,
+ global.blur_my_shell._pipelines_manager,
+ this.settings.panel.PIPELINE
+ );
+ background = pipeline.create_background_with_effects(
+ monitor.index, bg_manager_list,
+ background_group, 'bms-panel-blurred-widget'
+ );
+ bg_manager = bg_manager_list[0];
+ }
+ else {
+ const pipeline = new DummyPipeline(this.effects_manager, this.settings.panel);
+ [background, bg_manager] = pipeline.create_background_with_effect(
+ background_group, 'bms-panel-blurred-widget'
+ );
+
+ let paint_signals = new PaintSignals(this.connections);
+
+ // HACK
+ //
+ //`Shell.BlurEffect` does not repaint when shadows are under it. [1]
+ //
+ // This does not entirely fix this bug (shadows caused by windows
+ // still cause artifacts), but it prevents the shadows of the panel
+ // buttons to cause artifacts on the panel itself
+ //
+ // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857
+
+ {
+ if (this.settings.HACKS_LEVEL === 1) {
+ this._log("panel hack level 1");
+
+ paint_signals.disconnect_all();
+ paint_signals.connect(background, pipeline.effect);
+ } else {
+ paint_signals.disconnect_all();
+ }
+ }
+ }
+
+ // insert the background group to the panel box
+ panel_box.insert_child_at_index(background_group, 0);
+
+ // the object that is used to remembering each elements that is linked to the blur effect
+ let actors = {
+ widgets: { panel, panel_box, background, background_group },
+ static_blur,
+ monitor,
+ bg_manager,
+ is_dtp_panel
+ };
+ this.actors_list.push(actors);
+
+ // update the size of the actor
+ this.update_size(actors);
+
+ // connect to panel, panel_box and its parent position or size change
+ // this should fire update_size every time one of its params change
+ this.connections.connect(
+ panel,
+ 'notify::position',
+ _ => this.update_size(actors)
+ );
+ this.connections.connect(
+ panel_box,
+ ['notify::size', 'notify::position'],
+ _ => this.update_size(actors)
+ );
+ this.connections.connect(
+ panel_box.get_parent(),
+ 'notify::position',
+ _ => this.update_size(actors)
+ );
+
+ // connect to the panel getting destroyed
+ this.connections.connect(
+ panel,
+ 'destroy',
+ _ => this.destroy_blur(actors, true)
+ );
+ }
+
+ update_size(actors) {
+ let panel = actors.widgets.panel;
+ let panel_box = actors.widgets.panel_box;
+ let background = actors.widgets.background;
+ let [width, height] = panel_box.get_size();
+
+ // if static blur, need to clip the background
+ if (actors.static_blur) {
+ let monitor = Main.layoutManager.findMonitorForActor(panel);
+ if (!monitor)
+ return;
+
+ // an alternative to panel.get_transformed_position, because it
+ // sometimes yields NaN (probably when the actor is not fully
+ // positionned yet)
+ let [p_x, p_y] = panel_box.get_position();
+ let [p_p_x, p_p_y] = panel_box.get_parent().get_position();
+ let x = p_x + p_p_x - monitor.x + (width - panel.width) / 2;
+ let y = p_y + p_p_y - monitor.y + (height - panel.height) / 2;
+
+ background.set_clip(x, y, panel.width, panel.height);
+ background.x = (width - panel.width) / 2 - x;
+ background.y = .5 + (height - panel.height) / 2 - y;
+ } else {
+ background.x = panel.x;
+ background.y = panel.y;
+ background.width = panel.width;
+ background.height = panel.height;
+ }
+
+ // update the monitor panel is on
+ actors.monitor = Main.layoutManager.findMonitorForActor(panel);
+ }
+
+ /// Connect when overview if opened/closed to hide/show the blur accordingly
+ ///
+ /// If HIDETOPBAR is set, we need just to hide the blur when showing appgrid
+ /// (so no shadow is cropped)
+ connect_to_overview() {
+ // may be called when panel blur is disabled, if hidetopbar
+ // compatibility is toggled on/off
+ // if this is the case, do nothing as only the panel blur interfers with
+ // hidetopbar
+ if (
+ this.settings.panel.BLUR &&
+ this.settings.panel.UNBLUR_IN_OVERVIEW
+ ) {
+ if (!this.settings.hidetopbar.COMPATIBILITY) {
+ this.connections.connect(
+ Main.overview, 'showing', _ => this.hide()
+ );
+ this.connections.connect(
+ Main.overview, 'hidden', _ => this.show()
+ );
+ } else {
+ let appDisplay = Main.overview._overview._controls._appDisplay;
+
+ this.connections.connect(
+ appDisplay, 'show', _ => this.hide()
+ );
+ this.connections.connect(
+ appDisplay, 'hide', _ => this.show()
+ );
+ this.connections.connect(
+ Main.overview, 'hidden', _ => this.show()
+ );
+ }
+
+ }
+ }
+
+ /// Connect to windows disable transparency when a window is too close
+ connect_to_windows() {
+ if (
+ this.settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY
+ ) {
+ // connect to overview opening/closing
+ this.connections.connect(Main.overview, ['showing', 'hiding'],
+ _ => this.update_visibility()
+ );
+
+ // connect to session mode update
+ this.connections.connect(Main.sessionMode, 'updated',
+ _ => this.update_visibility()
+ );
+
+ // manage already-existing windows
+ for (const meta_window_actor of global.get_window_actors()) {
+ this.on_window_actor_added(
+ meta_window_actor.get_parent(), meta_window_actor
+ );
+ }
+
+ // manage windows at their creation/removal
+ this.connections.connect(global.window_group, 'child-added',
+ this.on_window_actor_added.bind(this)
+ );
+ this.connections.connect(global.window_group, 'child-removed',
+ this.on_window_actor_removed.bind(this)
+ );
+
+ // connect to a workspace change
+ this.connections.connect(global.window_manager, 'switch-workspace',
+ _ => this.update_visibility()
+ );
+
+ // perform early update
+ this.update_visibility();
+ } else {
+ // reset transparency for every panels
+ this.actors_list.forEach(
+ actors => this.set_should_override_panel(actors, true)
+ );
+ }
+ }
+
+ /// An helper to connect to both the windows and overview signals.
+ /// This is the only function that should be directly called, to prevent
+ /// inconsistencies with signals not being disconnected.
+ connect_to_windows_and_overview() {
+ this.disconnect_from_windows_and_overview();
+ this.connect_to_overview();
+ this.connect_to_windows();
+ }
+
+ /// Disconnect all the connections created by connect_to_windows
+ disconnect_from_windows_and_overview() {
+ // disconnect the connections to actors
+ for (const actor of [
+ Main.overview, Main.sessionMode,
+ global.window_group, global.window_manager,
+ Main.overview._overview._controls._appDisplay
+ ]) {
+ this.connections.disconnect_all_for(actor);
+ }
+
+ // disconnect the connections from windows
+ for (const [actor, ids] of this.window_signal_ids) {
+ for (const id of ids) {
+ actor.disconnect(id);
+ }
+ }
+ this.window_signal_ids = new Map();
+ }
+
+ /// Update the css classname of the panel for light theme
+ update_light_text_classname(disable = false) {
+ if (!isMainPanelAlive) {
+ this._log("cannot update light text classname, Main.panel is not alive");
+ return;
+ }
+
+ if (this.settings.panel.FORCE_LIGHT_TEXT && !disable)
+ Main.panel.add_style_class_name("panel-light-text");
+ else
+ Main.panel.remove_style_class_name("panel-light-text");
+ }
+
+ /// Callback when a new window is added
+ on_window_actor_added(container, meta_window_actor) {
+ this.window_signal_ids.set(meta_window_actor, [
+ meta_window_actor.connect('notify::allocation',
+ _ => this.update_visibility()
+ ),
+ meta_window_actor.connect('notify::visible',
+ _ => this.update_visibility()
+ )
+ ]);
+ this.update_visibility();
+ }
+
+ /// Callback when a window is removed
+ on_window_actor_removed(container, meta_window_actor) {
+ for (const signalId of this.window_signal_ids.get(meta_window_actor)) {
+ meta_window_actor.disconnect(signalId);
+ }
+ this.window_signal_ids.delete(meta_window_actor);
+ this.update_visibility();
+ }
+
+ /// Update the visibility of the blur effect
+ update_visibility() {
+ if (
+ isMainPanelAlive && Main.panel.has_style_pseudo_class('overview')
+ || !Main.sessionMode.hasWindows
+ ) {
+ this.actors_list.forEach(
+ actors => this.set_should_override_panel(actors, true)
+ );
+ return;
+ }
+
+ if (!Main.layoutManager.primaryMonitor)
+ return;
+
+ // get all the windows in the active workspace that are visible
+ const workspace = global.workspace_manager.get_active_workspace();
+ const windows = workspace.list_windows().filter(meta_window =>
+ meta_window.showing_on_its_workspace()
+ && !meta_window.is_hidden()
+ && meta_window.get_window_type() !== Meta.WindowType.DESKTOP
+ // exclude Desktop Icons NG
+ && meta_window.get_gtk_application_id() !== "com.rastersoft.ding"
+ && meta_window.get_gtk_application_id() !== "com.desktop.ding"
+ );
+
+ // check if at least one window is near enough to each panel and act
+ // accordingly
+ const scale = St.ThemeContext.get_for_stage(global.stage).scale_factor;
+ this.actors_list
+ // do not apply for dtp panels, as it would only cause bugs and it
+ // can be done from its preferences anyway
+ .filter(actors => !actors.is_dtp_panel)
+ .forEach(actors => {
+ let panel = actors.widgets.panel;
+ let panel_top = panel.get_transformed_position()[1];
+ let panel_bottom = panel_top + panel.get_height();
+
+ // check if at least a window is near enough the panel
+ let window_overlap_panel = false;
+ windows.forEach(meta_window => {
+ let window_monitor_i = meta_window.get_monitor();
+ let same_monitor = actors.monitor.index == window_monitor_i;
+
+ let window_vertical_pos = meta_window.get_frame_rect().y;
+ let window_vertical_bottom = window_vertical_pos + meta_window.get_frame_rect().height;
+
+ // if so, and if in the same monitor, then it overlaps
+ if (same_monitor
+ &&
+ // check if panel is on top
+ ((panel_top === 0 && window_vertical_pos < panel_bottom + 5 * scale) ||
+ // check if panel is at the bottom
+ (panel_top > 0 && window_vertical_bottom > panel_top - 5 * scale))
+ )
+ window_overlap_panel = true;
+ });
+
+ // if no window overlaps, then the panel is transparent
+ this.set_should_override_panel(
+ actors, !window_overlap_panel
+ );
+ });
+ }
+
+ /// Choose wether or not the panel background should be overriden, in
+ /// respect to its argument and the `override-background` setting.
+ set_should_override_panel(actors, should_override) {
+ let panel = actors.widgets.panel;
+
+ PANEL_STYLES.forEach(style => panel.remove_style_class_name(style));
+
+ if (
+ this.settings.panel.OVERRIDE_BACKGROUND
+ &&
+ should_override
+ ) {
+ panel.add_style_class_name(
+ PANEL_STYLES[this.settings.panel.STYLE_PANEL]
+ );
+ }
+
+ // update the classname if the panel to have or have not light text
+ this.update_light_text_classname(!should_override);
+ }
+
+ update_pipeline() {
+ this.actors_list.forEach(actors =>
+ actors.bg_manager._bms_pipeline.change_pipeline_to(
+ this.settings.panel.PIPELINE
+ )
+ );
+ }
+
+ show() {
+ this.actors_list.forEach(actors => {
+ actors.widgets.background.show();
+ });
+ }
+
+ hide() {
+ this.actors_list.forEach(actors => {
+ actors.widgets.background.hide();
+ });
+ }
+
+ // IMPORTANT: do never call this in a mutable `this.actors_list.forEach`
+ destroy_blur(actors, panel_already_destroyed) {
+ this.set_should_override_panel(actors, false);
+
+ actors.bg_manager._bms_pipeline.destroy();
+
+ if (panel_already_destroyed)
+ actors.bg_manager.backgroundActor = null;
+ actors.bg_manager.destroy();
+
+ if (!panel_already_destroyed) {
+ actors.widgets.panel_box.remove_child(actors.widgets.background_group);
+ actors.widgets.background_group.destroy_all_children();
+ actors.widgets.background_group.destroy();
+ }
+
+ let index = this.actors_list.indexOf(actors);
+ if (index >= 0)
+ this.actors_list.splice(index, 1);
+ }
+
+ disable() {
+ if (!this.enabled) {
+ this._log("blur already removed");
+ return;
+ }
+
+ this._log("removing blur from top panel");
+
+ this.disconnect_from_windows_and_overview();
+
+ this.update_light_text_classname(true);
+
+ const immutable_actors_list = [...this.actors_list];
+ immutable_actors_list.forEach(actors => this.destroy_blur(actors, false));
+ this.actors_list = [];
+
+ this.connections.disconnect_all();
+
+ this.enabled = false;
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > panel] ${str}`);
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > panel] ${str}`);
+ }
+};
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/screenshot.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/screenshot.js
new file mode 100644
index 0000000..dcf05eb
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/screenshot.js
@@ -0,0 +1,110 @@
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+
+import { Pipeline } from '../conveniences/pipeline.js';
+
+export const ScreenshotBlur = class ScreenshotBlur {
+ constructor(connections, settings, effects_manager) {
+ this.connections = connections;
+ this.settings = settings;
+ this.screenshot_background_managers = [];
+ this.effects_manager = effects_manager;
+ }
+
+ enable() {
+ this._log("blurring screenshot's window selector");
+
+ // connect to monitors change
+ this.connections.connect(Main.layoutManager, 'monitors-changed',
+ _ => this.update_backgrounds()
+ );
+
+ // update backgrounds when the component is enabled
+ this.update_backgrounds();
+ }
+
+ update_backgrounds() {
+ // remove every old background
+ this.remove_background_actors();
+ // create new backgrounds for the screenshot window selector
+ for (let i = 0; i < Main.screenshotUI._windowSelectors.length; i++) {
+ const window_selector = Main.screenshotUI._windowSelectors[i];
+ const pipeline = new Pipeline(
+ this.effects_manager,
+ global.blur_my_shell._pipelines_manager,
+ this.settings.screenshot.PIPELINE
+ );
+ pipeline.create_background_with_effects(
+ window_selector._monitorIndex, this.screenshot_background_managers,
+ window_selector, 'bms-screenshot-blurred-widget', false
+ );
+
+ // prevent old `BackgroundActor` from being accessed, which creates a whole bug of logs
+ this.connections.connect(window_selector.get_parent(), 'destroy', _ => {
+ this.screenshot_background_managers.forEach(background_manager => {
+ if (background_manager.backgroundActor) {
+ let widget = background_manager.backgroundActor.get_parent();
+ let parent = widget?.get_parent();
+
+ if (parent == window_selector) {
+ background_manager._bms_pipeline.destroy();
+ parent.remove_child(widget);
+ }
+ }
+ background_manager.destroy();
+ });
+
+ window_selector.get_children().forEach(child => {
+ if (child.get_name() == 'bms-screenshot-blurred-widget')
+ window_selector.remove_child(child);
+ });
+
+ let index = this.screenshot_background_managers.indexOf(window_selector);
+ this.screenshot_background_managers.splice(index, 1);
+ });
+ }
+ }
+
+ update_pipeline() {
+ this.screenshot_background_managers.forEach(background_manager =>
+ background_manager._bms_pipeline.change_pipeline_to(
+ this.settings.screenshot.PIPELINE
+ )
+ );
+ }
+
+ remove_background_actors() {
+ this.screenshot_background_managers.forEach(background_manager => {
+ background_manager._bms_pipeline.destroy();
+ if (background_manager.backgroundActor) {
+ let widget = background_manager.backgroundActor.get_parent();
+ widget?.get_parent()?.remove_child(widget);
+ }
+ background_manager.destroy();
+ });
+
+ Main.screenshotUI._windowSelectors.forEach(window_selector =>
+ window_selector.get_children().forEach(child => {
+ if (child.get_name() == 'bms-screenshot-blurred-widget')
+ window_selector.remove_child(child);
+ })
+ );
+
+ this.screenshot_background_managers = [];
+ }
+
+ disable() {
+ this._log("removing blur from screenshot's window selector");
+
+ this.remove_background_actors();
+ this.connections.disconnect_all();
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > screenshot] ${str}`);
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > screenshot] ${str}`);
+ }
+};
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/window_list.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/window_list.js
new file mode 100644
index 0000000..6ab0644
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/window_list.js
@@ -0,0 +1,148 @@
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+
+import { PaintSignals } from '../conveniences/paint_signals.js';
+import { DummyPipeline } from '../conveniences/dummy_pipeline.js';
+
+
+export const WindowListBlur = class WindowListBlur {
+ constructor(connections, settings, effects_manager) {
+ this.connections = connections;
+ this.settings = settings;
+ this.paint_signals = new PaintSignals(connections);
+ this.effects_manager = effects_manager;
+ this.pipelines = [];
+ }
+
+ enable() {
+ this._log("blurring window list");
+
+ // blur if window-list is found
+ Main.layoutManager.uiGroup.get_children().forEach(
+ child => this.try_blur(child)
+ );
+
+ // listen to new actors in `Main.layoutManager.uiGroup` and blur it if
+ // if is window-list
+ this.connections.connect(
+ Main.layoutManager.uiGroup,
+ 'child-added',
+ (_, child) => this.try_blur(child)
+ );
+
+ // connect to overview
+ this.connections.connect(Main.overview, 'showing', _ => {
+ this.hide();
+ });
+ this.connections.connect(Main.overview, 'hidden', _ => {
+ this.show();
+ });
+ }
+
+ try_blur(actor) {
+ if (
+ actor.constructor.name === "WindowList" &&
+ actor.style !== "background:transparent;"
+ ) {
+ this._log("found window list to blur");
+
+ const pipeline = new DummyPipeline(
+ this.effects_manager, this.settings.window_list
+ );
+ pipeline.attach_effect_to_actor(actor);
+ this.pipelines.push(pipeline);
+
+ actor.set_style("background:transparent;");
+
+ actor._windowList.get_children().forEach(
+ window => this.style_window_button(window)
+ );
+
+ this.connections.connect(
+ actor._windowList,
+ 'child-added',
+ (_, window) => this.style_window_button(window)
+ );
+
+ this.connections.connect(
+ actor,
+ 'destroy',
+ _ => this.destroy_blur(pipeline, true)
+ );
+
+
+ // HACK
+ //
+ //`Shell.BlurEffect` does not repaint when shadows are under it. [1]
+ //
+ // This does not entirely fix this bug (shadows caused by windows
+ // still cause artifacts), but it prevents the shadows of the panel
+ // buttons to cause artifacts on the panel itself
+ //
+ // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857
+
+ if (this.settings.HACKS_LEVEL === 1) {
+ this._log("window list hack level 1");
+
+ this.paint_signals.disconnect_all_for_actor(actor);
+ this.paint_signals.connect(actor, pipeline.effect);
+ } else {
+ this.paint_signals.disconnect_all_for_actor(actor);
+ }
+ }
+ }
+
+ style_window_button(window) {
+ window.get_child_at_index(0).set_style(
+ "box-shadow:none; background-color:rgba(0,0,0,0.2); border-radius:5px;"
+ );
+ }
+
+ // IMPORTANT: do never call this in a mutable `this.pipelines.forEach`
+ destroy_blur(pipeline, actor_destroyed = false) {
+ if (!actor_destroyed) {
+ this.remove_style(pipeline.actor);
+ this.paint_signals.disconnect_all_for_actor(pipeline.actor);
+ }
+
+ pipeline.destroy();
+
+ let index = this.pipelines.indexOf(pipeline);
+ if (index >= 0)
+ this.pipelines.splice(pipeline, 1);
+ }
+
+ remove_style(actor) {
+ if (
+ actor.constructor.name === "WindowList" &&
+ actor.style === "background:transparent;"
+ ) {
+ actor.style = null;
+ actor._windowList.get_children().forEach(
+ child => child.get_child_at_index(0).set_style(null)
+ );
+ }
+ }
+
+ hide() {
+ this.pipelines.forEach(pipeline => pipeline.effect?.set_enabled(false));
+ }
+
+ show() {
+ this.pipelines.forEach(pipeline => pipeline.effect?.set_enabled(true));
+ }
+
+ disable() {
+ this._log("removing blur from window list");
+
+ const immutable_pipelines_list = [...this.pipelines];
+ immutable_pipelines_list.forEach(pipeline => this.destroy_blur(pipeline));
+
+ this.pipelines = [];
+ this.connections.disconnect_all();
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > window list] ${str}`);
+ }
+}; \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/connections.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/connections.js
new file mode 100644
index 0000000..0583db3
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/connections.js
@@ -0,0 +1,106 @@
+import GObject from 'gi://GObject';
+
+/// An object to easily manage signals.
+export const Connections = class Connections {
+ constructor() {
+ this.buffer = [];
+ }
+
+ /// Adds a connection.
+ ///
+ /// Takes as arguments:
+ /// - an actor, which fires the signal
+ /// - signal(s) (string or array of strings), which are watched for
+ /// - a callback, which is called when the signal is fired
+ connect(actor, signals, handler) {
+ if (signals instanceof Array) {
+ signals.forEach(signal => {
+ let id = actor.connect(signal, handler);
+ this.process_connection(actor, id);
+ });
+ } else {
+ let id = actor.connect(signals, handler);
+ this.process_connection(actor, id);
+ }
+
+ }
+
+ /// Process the given actor and id.
+ ///
+ /// This makes sure that the signal is disconnected when the actor is
+ /// destroyed, and that the signal can be managed through other Connections
+ /// methods.
+ process_connection(actor, id) {
+ let infos = {
+ actor: actor,
+ id: id
+ };
+
+ // remove the signal when the actor is destroyed
+ if (
+ actor.connect &&
+ (
+ !(actor instanceof GObject.Object) ||
+ GObject.signal_lookup('destroy', actor)
+ )
+ ) {
+ let destroy_id = actor.connect('destroy', () => {
+ actor.disconnect(id);
+ actor.disconnect(destroy_id);
+
+ let index = this.buffer.indexOf(infos);
+ if (index >= 0) {
+ this.buffer.splice(index, 1);
+ }
+ });
+ infos.destroy_id = destroy_id;
+ }
+
+ this.buffer.push(infos);
+ }
+
+ /// Disconnects every connection found for an actor.
+ disconnect_all_for(actor) {
+ // get every connection stored for the actor
+ let actor_connections = this.buffer.filter(
+ infos => infos.actor === actor
+ );
+
+ // remove each of them
+ actor_connections.forEach(connection => {
+ // disconnect
+ try {
+ connection.actor.disconnect(connection.id);
+ if ('destroy_id' in connection)
+ connection.actor.disconnect(connection.destroy_id);
+ } catch (e) {
+ this._warn(`error removing connection: ${e}; continuing`);
+ }
+
+ // remove from buffer
+ let index = this.buffer.indexOf(connection);
+ this.buffer.splice(index, 1);
+ });
+ }
+
+ /// Disconnect every connection for each actor.
+ disconnect_all() {
+ this.buffer.forEach(connection => {
+ // disconnect
+ try {
+ connection.actor.disconnect(connection.id);
+ if ('destroy_id' in connection)
+ connection.actor.disconnect(connection.destroy_id);
+ } catch (e) {
+ this._warn(`error removing connection: ${e}; continuing`);
+ }
+ });
+
+ // reset buffer
+ this.buffer = [];
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > connections] ${str}`);
+ }
+}; \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/dummy_pipeline.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/dummy_pipeline.js
new file mode 100644
index 0000000..544d68c
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/dummy_pipeline.js
@@ -0,0 +1,112 @@
+import St from 'gi://St';
+import Clutter from 'gi://Clutter';
+
+/// A dummy `Pipeline`, for dynamic blur only.
+/// Instead of a pipeline id, we take the settings of the component we want to blur.
+export const DummyPipeline = class DummyPipeline {
+ constructor(effects_manager, settings, actor = null) {
+ this.effects_manager = effects_manager;
+ this.settings = settings;
+ this.effect = null;
+ this.attach_effect_to_actor(actor);
+ }
+
+ create_background_with_effect(
+ background_group,
+ widget_name
+ ) {
+ // create the new actor
+ this.actor = new St.Widget({ name: widget_name });
+
+ this.attach_effect_to_actor(this.actor);
+
+ // a dummy `BackgroundManager`, just to access the pipeline easily
+ let bg_manager = new Clutter.Actor;
+ bg_manager.backgroundActor = this.actor;
+ bg_manager._bms_pipeline = this;
+
+ background_group.insert_child_at_index(this.actor, 0);
+
+ return [this.actor, bg_manager];
+ };
+
+ attach_effect_to_actor(actor) {
+ // set the actor
+ if (actor)
+ this.actor = actor;
+ else {
+ this.remove_pipeline_from_actor();
+ return;
+ }
+
+ // build the new effect to be added
+ this.build_effect({
+ unscaled_radius: 2 * this.settings.SIGMA,
+ brightness: this.settings.BRIGHTNESS,
+ });
+
+ this.actor_destroy_id = this.actor.connect(
+ "destroy", () => this.remove_pipeline_from_actor()
+ );
+
+ // add the effect to the actor
+ if (this.actor)
+ this.actor.add_effect(this.effect);
+ else
+ this._warn(`could not add effect to actor, actor does not exist anymore`);
+ }
+
+ remove_pipeline_from_actor() {
+ this.remove_effect();
+ if (this.actor && this.actor_destroy_id)
+ this.actor.disconnect(this.actor_destroy_id);
+ this.actor_destroy_id = null;
+ this.actor = null;
+ }
+
+ build_effect(params) {
+ // create the effect
+ this.effect = this.effects_manager.new_native_dynamic_gaussian_blur_effect(params);
+
+ // connect to settings changes, using the true gsettings object
+ this._sigma_changed_id = this.settings.settings.connect(
+ 'changed::sigma', () => this.effect.unscaled_radius = 2 * this.settings.SIGMA
+ );
+ this._brightness_changed_id = this.settings.settings.connect(
+ 'changed::brightness', () => this.effect.brightness = this.settings.BRIGHTNESS
+ );
+ }
+
+ repaint_effect() {
+ this.effect?.queue_repaint();
+ }
+
+ /// Remove every effect from the actor it is attached to. Please note that they are not
+ /// destroyed, but rather stored (thanks to the `EffectManager` class) to be reused later.
+ remove_effect() {
+ if (this.effect)
+ this.effects_manager.remove(this.effect);
+ this.effect = null;
+
+ if (this._sigma_changed_id)
+ this.settings.settings.disconnect(this._sigma_changed_id);
+ if (this._brightness_changed_id)
+ this.settings.settings.disconnect(this._brightness_changed_id);
+ delete this._sigma_changed_id;
+ delete this._brightness_changed_id;
+ }
+
+ /// Do nothing for this dummy pipeline.
+ /// Note: exposed to public API.
+ change_pipeline_to() { return; }
+
+ /// Note: exposed to public API.
+ destroy() {
+ this.remove_effect();
+ this.remove_pipeline_from_actor();
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > dummy pip] ${str}`);
+ }
+}; \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/effects_manager.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/effects_manager.js
new file mode 100644
index 0000000..947d535
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/effects_manager.js
@@ -0,0 +1,90 @@
+import { get_supported_effects } from '../effects/effects.js';
+
+/// An object to manage effects (by not destroying them all the time)
+export const EffectsManager = class EffectsManager {
+ constructor(connections) {
+ this.connections = connections;
+ this.used = [];
+ this.SUPPORTED_EFFECTS = get_supported_effects();
+
+ Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => {
+ // init the arrays containing each unused effect
+ this[effect_name + '_effects'] = [];
+
+ // init the functions for each effect
+ this['new_' + effect_name + '_effect'] = function (params) {
+ let effect;
+ if (this[effect_name + '_effects'].length > 0) {
+ effect = this[effect_name + '_effects'].splice(0, 1)[0];
+ effect.set({
+ ...this.SUPPORTED_EFFECTS[effect_name].class.default_params, ...params
+ });
+ } else
+ effect = new this.SUPPORTED_EFFECTS[effect_name].class({
+ ...this.SUPPORTED_EFFECTS[effect_name].class.default_params, ...params
+ });
+
+ this.used.push(effect);
+ this.connect_to_destroy(effect);
+ return effect;
+ };
+ });
+ }
+
+ connect_to_destroy(effect) {
+ effect.old_actor = effect.get_actor();
+ if (effect.old_actor)
+ effect.old_actor_id = effect.old_actor.connect('destroy', _ => {
+ this.remove(effect, true);
+ });
+
+ this.connections.connect(effect, 'notify::actor', _ => {
+ let actor = effect.get_actor();
+
+ if (effect.old_actor && actor != effect.old_actor)
+ effect.old_actor.disconnect(effect.old_actor_id);
+
+ if (actor && actor != effect.old_actor) {
+ effect.old_actor_id = actor.connect('destroy', _ => {
+ this.remove(effect, true);
+ });
+ }
+ });
+ }
+
+ // IMPORTANT: do never call this in a mutable `this.used.forEach`
+ remove(effect, actor_already_destroyed = false) {
+ if (!actor_already_destroyed)
+ try {
+ effect.get_actor()?.remove_effect(effect);
+ } catch (e) {
+ this._warn(`could not remove the effect, continuing: ${e}`);
+ }
+ if (effect.old_actor)
+ effect.old_actor.disconnect(effect.old_actor_id);
+ delete effect.old_actor;
+ delete effect.old_actor_id;
+
+ let index = this.used.indexOf(effect);
+ if (index >= 0) {
+ this.used.splice(index, 1);
+
+ Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => {
+ if (effect instanceof this.SUPPORTED_EFFECTS[effect_name].class)
+ this[effect_name + '_effects'].push(effect);
+ });
+ }
+ }
+
+ destroy_all() {
+ const immutable_used_list = [...this.used];
+ immutable_used_list.forEach(effect => this.remove(effect));
+ Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => {
+ this[effect_name + '_effects'].splice(0, this[effect_name + '_effects'].length);
+ });
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > effects mng] ${str}`);
+ }
+};
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/keys.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/keys.js
new file mode 100644
index 0000000..fcde72b
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/keys.js
@@ -0,0 +1,190 @@
+import { Type } from './settings.js';
+
+// This lists the preferences keys
+export const KEYS = [
+ {
+ component: "general", schemas: [
+ { type: Type.PIPELINES, name: "pipelines" },
+ { type: Type.I, name: "hacks-level" },
+ { type: Type.B, name: "debug" },
+ ]
+ },
+ {
+ component: "overview", schemas: [
+ { type: Type.B, name: "blur" },
+ { type: Type.S, name: "pipeline" },
+ { type: Type.I, name: "style-components" },
+ ]
+ },
+ {
+ component: "appfolder", schemas: [
+ { type: Type.B, name: "blur" },
+ { type: Type.I, name: "sigma" },
+ { type: Type.D, name: "brightness" },
+ { type: Type.I, name: "style-dialogs" },
+ ]
+ },
+ {
+ component: "panel", schemas: [
+ { type: Type.B, name: "blur" },
+ { type: Type.B, name: "static-blur" },
+ { type: Type.S, name: "pipeline" },
+ { type: Type.I, name: "sigma" },
+ { type: Type.D, name: "brightness" },
+ { type: Type.B, name: "unblur-in-overview" },
+ { type: Type.B, name: "force-light-text" },
+ { type: Type.B, name: "override-background" },
+ { type: Type.I, name: "style-panel" },
+ { type: Type.B, name: "override-background-dynamically" },
+ ]
+ },
+ {
+ component: "dash-to-dock", schemas: [
+ { type: Type.B, name: "blur" },
+ { type: Type.B, name: "static-blur" },
+ { type: Type.S, name: "pipeline" },
+ { type: Type.I, name: "sigma" },
+ { type: Type.D, name: "brightness" },
+ { type: Type.B, name: "unblur-in-overview" },
+ { type: Type.B, name: "override-background" },
+ { type: Type.I, name: "style-dash-to-dock" },
+ ]
+ },
+ {
+ component: "applications", schemas: [
+ { type: Type.B, name: "blur" },
+ { type: Type.B, name: "static-blur" },
+ { type: Type.S, name: "pipeline" },
+ { type: Type.I, name: "sigma" },
+ { type: Type.D, name: "brightness" },
+ { type: Type.I, name: "opacity" },
+ { type: Type.B, name: "dynamic-opacity" },
+ { type: Type.B, name: "blur-on-overview" },
+ { type: Type.B, name: "enable-all" },
+ { type: Type.AS, name: "whitelist" },
+ { type: Type.AS, name: "blacklist" },
+ ]
+ },
+ {
+ component: "lockscreen", schemas: [
+ { type: Type.B, name: "blur" },
+ { type: Type.S, name: "pipeline" },
+ ]
+ },
+ {
+ component: "window-list", schemas: [
+ { type: Type.B, name: "blur" },
+ { type: Type.S, name: "pipeline" },
+ { type: Type.I, name: "sigma" },
+ { type: Type.D, name: "brightness" },
+ ]
+ },
+ {
+ component: "coverflow-alt-tab", schemas: [
+ { type: Type.B, name: "blur" },
+ { type: Type.S, name: "pipeline" },
+ ]
+ },
+ {
+ component: "screenshot", schemas: [
+ { type: Type.B, name: "blur" },
+ { type: Type.S, name: "pipeline" },
+ ]
+ },
+ {
+ component: "hidetopbar", schemas: [
+ { type: Type.B, name: "compatibility" },
+ ]
+ },
+ {
+ component: "dash-to-panel", schemas: [
+ { type: Type.B, name: "blur-original-panel" },
+ ]
+ },
+];
+
+
+// This lists the deprecated preferences keys
+export const DEPRECATED_KEYS = [
+ {
+ component: "general", schemas: [
+ { type: Type.I, name: "sigma" },
+ { type: Type.D, name: "brightness" },
+ { type: Type.C, name: "color" },
+ { type: Type.D, name: "noise-amount" },
+ { type: Type.D, name: "noise-lightness" },
+ { type: Type.B, name: "color-and-noise" },
+ ]
+ },
+ {
+ component: "overview", schemas: [
+ { type: Type.B, name: "customize" },
+ { type: Type.I, name: "sigma" },
+ { type: Type.D, name: "brightness" },
+ { type: Type.C, name: "color" },
+ { type: Type.D, name: "noise-amount" },
+ { type: Type.D, name: "noise-lightness" },
+ ]
+ },
+ {
+ component: "appfolder", schemas: [
+ { type: Type.B, name: "customize" },
+ { type: Type.C, name: "color" },
+ { type: Type.D, name: "noise-amount" },
+ { type: Type.D, name: "noise-lightness" },
+ ]
+ },
+ {
+ component: "panel", schemas: [
+ { type: Type.B, name: "customize" },
+ { type: Type.C, name: "color" },
+ { type: Type.D, name: "noise-amount" },
+ { type: Type.D, name: "noise-lightness" },
+ ]
+ },
+ {
+ component: "dash-to-dock", schemas: [
+ { type: Type.B, name: "customize" },
+ { type: Type.C, name: "color" },
+ { type: Type.D, name: "noise-amount" },
+ { type: Type.D, name: "noise-lightness" },
+ { type: Type.I, name: "corner-radius" },
+ ]
+ },
+ {
+ component: "applications", schemas: [
+ { type: Type.B, name: "customize" },
+ { type: Type.C, name: "color" },
+ { type: Type.D, name: "noise-amount" },
+ { type: Type.D, name: "noise-lightness" },
+ ]
+ },
+ {
+ component: "lockscreen", schemas: [
+ { type: Type.B, name: "customize" },
+ { type: Type.I, name: "sigma" },
+ { type: Type.D, name: "brightness" },
+ { type: Type.C, name: "color" },
+ { type: Type.D, name: "noise-amount" },
+ { type: Type.D, name: "noise-lightness" },
+ ]
+ },
+ {
+ component: "window-list", schemas: [
+ { type: Type.B, name: "customize" },
+ { type: Type.C, name: "color" },
+ { type: Type.D, name: "noise-amount" },
+ { type: Type.D, name: "noise-lightness" },
+ ]
+ },
+ {
+ component: "screenshot", schemas: [
+ { type: Type.B, name: "customize" },
+ { type: Type.I, name: "sigma" },
+ { type: Type.D, name: "brightness" },
+ { type: Type.C, name: "color" },
+ { type: Type.D, name: "noise-amount" },
+ { type: Type.D, name: "noise-lightness" },
+ ]
+ },
+]; \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/paint_signals.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/paint_signals.js
new file mode 100644
index 0000000..5fbfee4
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/paint_signals.js
@@ -0,0 +1,91 @@
+import GObject from 'gi://GObject';
+import Clutter from 'gi://Clutter';
+
+
+export const PaintSignals = class PaintSignals {
+ constructor(connections) {
+ this.buffer = [];
+ this.connections = connections;
+ }
+
+ connect(actor, blur_effect) {
+ let paint_effect = new EmitPaintSignal();
+ let infos = {
+ actor: actor,
+ paint_effect: paint_effect
+ };
+ let counter = 0;
+
+ actor.add_effect(paint_effect);
+ this.connections.connect(paint_effect, 'update-blur', () => {
+ try {
+ // checking if blur_effect.queue_repaint() has been recently called
+ if (counter === 0) {
+ counter = 2;
+ blur_effect.queue_repaint();
+ }
+ else counter--;
+ } catch (e) { }
+ });
+
+ // remove the actor from buffer when it is destroyed
+ if (
+ actor.connect &&
+ (
+ !(actor instanceof GObject.Object) ||
+ GObject.signal_lookup('destroy', actor)
+ )
+ )
+ this.connections.connect(actor, 'destroy', () => {
+ const immutable_buffer = [...this.buffer];
+ immutable_buffer.forEach(infos => {
+ if (infos.actor === actor) {
+ // remove from buffer
+ let index = this.buffer.indexOf(infos);
+ this.buffer.splice(index, 1);
+ }
+ });
+ });
+
+ this.buffer.push(infos);
+ }
+
+ disconnect_all_for_actor(actor) {
+ const immutable_buffer = [...this.buffer];
+ immutable_buffer.forEach(infos => {
+ if (infos.actor === actor) {
+ this.connections.disconnect_all_for(infos.paint_effect);
+ infos.actor.remove_effect(infos.paint_effect);
+
+ // remove from buffer
+ let index = this.buffer.indexOf(infos);
+ this.buffer.splice(index, 1);
+ }
+ });
+ }
+
+ disconnect_all() {
+ this.buffer.forEach(infos => {
+ this.connections.disconnect_all_for(infos.paint_effect);
+ infos.actor.remove_effect(infos.paint_effect);
+ });
+
+ this.buffer = [];
+ }
+};
+
+export const EmitPaintSignal = GObject.registerClass({
+ GTypeName: 'EmitPaintSignal',
+ Signals: {
+ 'update-blur': {
+ param_types: []
+ },
+ }
+},
+ class EmitPaintSignal extends Clutter.Effect {
+ vfunc_paint(node, paint_context, paint_flags) {
+ this.emit("update-blur");
+ super.vfunc_paint(node, paint_context, paint_flags);
+ }
+ }
+); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js
new file mode 100644
index 0000000..84b1d7a
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js
@@ -0,0 +1,223 @@
+import St from 'gi://St';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import * as Background from 'resource:///org/gnome/shell/ui/background.js';
+
+/// A `Pipeline` object is a handy way to manage the effects attached to an actor. It only manages
+/// one actor at a time (so blurring multiple widgets will need multiple `Pipeline`), and is
+/// linked to a `pipeline_id` that has been (hopefully) defined in the settings.
+///
+/// It communicates with the settings through the `PipelinesManager` object, and receives different
+/// signals (with `pipeline_id` being an unique string):
+/// - `'pipeline_id'::pipeline-updated`, handing a new pipeline descriptor object, when the pipeline
+/// has been changed enough that it needs to rebuild the effects configuration
+/// - `'pipeline_id'::pipeline-destroyed`, when the pipeline has been destroyed; thus making the
+/// `Pipeline` change its id to `pipeline_default`
+///
+/// And each effect, with an unique `id`, is connected to the `PipelinesManager` for the signals:
+/// - `'pipeline_id'::effect-'id'-key-removed`, handing the key that was removed
+/// - `'pipeline_id'::effect-'id'-key-updated`, handing the key that was changed and its new value
+/// - `'pipeline_id'::effect-'id'-key-added`, handing the key that was added and its value
+export const Pipeline = class Pipeline {
+ constructor(effects_manager, pipelines_manager, pipeline_id, actor = null) {
+ this.effects_manager = effects_manager;
+ this.pipelines_manager = pipelines_manager;
+ this.effects = [];
+ this.set_pipeline_id(pipeline_id);
+ this.attach_pipeline_to_actor(actor);
+ }
+
+ /// Create a background linked to the monitor with index `monitor_index`, with a
+ /// `BackgroundManager` that is appended to the list `background_managers`. The background actor
+ /// will be given the name `widget_name` and inserted into the given `background_group`.
+ /// If `use_absolute_position` is false, then the position used is at (0,0); useful when the
+ /// positioning is relative.
+ /// Note: exposed to public API.
+ create_background_with_effects(
+ monitor_index,
+ background_managers,
+ background_group,
+ widget_name,
+ use_absolute_position = true
+ ) {
+ let monitor = Main.layoutManager.monitors[monitor_index];
+
+ // create the new actor
+ this.actor = new St.Widget({
+ name: widget_name,
+ x: use_absolute_position ? monitor.x : 0,
+ y: .5 + (use_absolute_position ? monitor.y : 0), // add 1 to correct z-position
+ z_position: 1, // seems to fix the multi-monitor glitch
+ width: monitor.width,
+ height: monitor.height
+ });
+
+ // remove the effects, wether or not we attach the pipeline to the actor: if they are fired
+ // while the actor has changed, this could go bad
+ this.remove_all_effects();
+ if (this.pipeline_id)
+ this.attach_pipeline_to_actor(this.actor);
+
+ let bg_manager = new Background.BackgroundManager({
+ container: this.actor,
+ monitorIndex: monitor_index,
+ controlPosition: false,
+ });
+ bg_manager._bms_pipeline = this;
+
+ background_managers.push(bg_manager);
+ background_group.insert_child_at_index(this.actor, 0);
+
+ return this.actor;
+ };
+
+ /// Set the pipeline id, correctly connecting the `Pipeline` object to listen the pipelines
+ /// manager for pipeline-wide changes. This does not update the effects in consequence, call
+ /// `change_pipeline_to` instead if you want to reconstruct the effects too.
+ set_pipeline_id(pipeline_id) {
+ // disconnect ancient signals
+ this.remove_connections();
+
+ // change the id
+ this.pipeline_id = pipeline_id;
+
+ // connect to settings changes
+ this._pipeline_changed_id = this.pipelines_manager.connect(
+ this.pipeline_id + '::pipeline-updated',
+ (_, new_pipeline) => this.update_effects_from_pipeline(new_pipeline)
+ );
+ this._pipeline_destroyed_id = this.pipelines_manager.connect(
+ this.pipeline_id + '::pipeline-destroyed',
+ _ => this.change_pipeline_to("pipeline_default")
+ );
+ }
+
+ /// Disconnect the signals for the pipeline changes. Please note that the signals related to the
+ /// effects are stored with them and removed with `remove_all_effects`.
+ remove_connections() {
+ if (this._pipeline_changed_id)
+ this.pipelines_manager.disconnect(this._pipeline_changed_id);
+ if (this._pipeline_destroyed_id)
+ this.pipelines_manager.disconnect(this._pipeline_destroyed_id);
+ this._pipeline_changed_id = null;
+ this._pipeline_destroyed_id = null;
+ }
+
+ /// Attach a Pipeline object with `pipeline_id` already set to an actor.
+ attach_pipeline_to_actor(actor) {
+ // set the actor
+ if (actor)
+ this.actor = actor;
+ else {
+ this.remove_pipeline_from_actor();
+ return;
+ }
+
+ // attach the pipeline
+ let pipeline = this.pipelines_manager.pipelines[this.pipeline_id];
+ if (!pipeline) {
+ this._warn(`could not attach pipeline to actor, pipeline "${this.pipeline_id}" not found`);
+ // do not recurse...
+ if ("pipeline_default" in this.pipelines_manager.pipelines) {
+ this.set_pipeline_id("pipeline_default");
+ pipeline = this.pipelines_manager.pipelines["pipeline_default"];
+ } else
+ return;
+ }
+
+ this.actor_destroy_id = this.actor.connect(
+ "destroy", () => this.remove_pipeline_from_actor()
+ );
+
+ // update the effects
+ this.update_effects_from_pipeline(pipeline);
+ }
+
+ remove_pipeline_from_actor() {
+ this.remove_all_effects();
+ if (this.actor && this.actor_destroy_id)
+ this.actor.disconnect(this.actor_destroy_id);
+ this.actor_destroy_id = null;
+ this.actor = null;
+ }
+
+ /// Update the effects from the given pipeline object, the hard way.
+ update_effects_from_pipeline(pipeline) {
+ // remove all effects
+ this.remove_all_effects();
+
+ // build the new effects to be added
+ pipeline.effects.forEach(effect => {
+ if ('new_' + effect.type + '_effect' in this.effects_manager)
+ this.build_effect(effect);
+ else
+ this._warn(`could not add effect to actor, effect "${effect.type}" not found`);
+ });
+ this.effects.reverse();
+
+ // add the effects to the actor
+ if (this.actor)
+ this.effects.forEach(effect => this.actor.add_effect(effect));
+ else
+ this._warn(`could not add effect to actor, actor does not exist anymore`);
+ }
+
+ /// Given an `effect_infos` object containing the effect type, id and params, build an effect
+ /// and append it to the effects list
+ build_effect(effect_infos) {
+ let effect = this.effects_manager['new_' + effect_infos.type + '_effect'](effect_infos.params);
+ this.effects.push(effect);
+
+ // connect to settings changes
+ effect._effect_key_removed_id = this.pipelines_manager.connect(
+ this.pipeline_id + '::effect-' + effect_infos.id + '-key-removed',
+ (_, key) => effect[key] = effect.constructor.default_params[key]
+ );
+ effect._effect_key_updated_id = this.pipelines_manager.connect(
+ this.pipeline_id + '::effect-' + effect_infos.id + '-key-updated',
+ (_, key, value) => effect[key] = value
+ );
+ effect._effect_key_added_id = this.pipelines_manager.connect(
+ this.pipeline_id + '::effect-' + effect_infos.id + '-key-added',
+ (_, key, value) => effect[key] = value
+ );
+ }
+
+ /// Remove every effect from the actor it is attached to. Please note that they are not
+ /// destroyed, but rather stored (thanks to the `EffectManager` class) to be reused later.
+ remove_all_effects() {
+ this.effects.forEach(effect => {
+ this.effects_manager.remove(effect);
+ [
+ effect._effect_key_removed_id,
+ effect._effect_key_updated_id,
+ effect._effect_key_added_id
+ ].forEach(
+ id => { if (id) this.pipelines_manager.disconnect(id); }
+ );
+ delete effect._effect_key_removed_id;
+ delete effect._effect_key_updated_id;
+ delete effect._effect_key_added_id;
+ });
+ this.effects = [];
+ }
+
+ /// Change the pipeline id, and update the effects according to this change.
+ /// Note: exposed to public API.
+ change_pipeline_to(pipeline_id) {
+ this.set_pipeline_id(pipeline_id);
+ this.attach_pipeline_to_actor(this.actor);
+ }
+
+ /// Resets the `Pipeline` object to a sane state, removing every effect and signal.
+ /// Note: exposed to public API.
+ destroy() {
+ this.remove_all_effects();
+ this.remove_connections();
+ this.remove_pipeline_from_actor();
+ this.pipeline_id = null;
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > pipeline] ${str}`);
+ }
+}; \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipelines_manager.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipelines_manager.js
new file mode 100644
index 0000000..0fdfe9e
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipelines_manager.js
@@ -0,0 +1,168 @@
+const Signals = imports.signals;
+
+/// The `PipelinesManager` object permits to store the list of pipelines and their effects in
+/// memory. It is meant to *always* be in sync with the `org.gnome.shell.extensions.blur-my-shell`'s
+/// `pipelines` gschema. However, we do not want to re-create every effect each time this schema is
+/// changed, so the pipelines manager handles it, and dispatches the updates with targeted signals.
+///
+/// It is only connected to ONE signal (the pipelines schema being changed), and emits numerous
+/// which are connected to by both the different `Pipeline` objects in the extension, and by the
+/// different pages of the extension preferences.
+/// It emits three different types of signals:
+///
+/// - general changes to the pipelines list, connected to by the extension preferences:
+/// - `pipeline-list-changed`, when the list of pipelines has changed (by creation or deletion)
+/// - `pipeline-names-changed`, when the name of a pipeline is changed
+///
+/// - signals that are targeted towards a given pipeline, with `pipeline_id` being its unique id:
+/// - `'pipeline_id'::pipeline-updated`, handing a new pipeline descriptor object, when the
+/// pipeline has been changed quite a bit (added/destroyed/reordered the effects)
+/// - `'pipeline_id'::pipeline-destroyed`, when the pipeline has been destroyed
+/// - `'pipeline_id'::pipeline-renamed`, handing the new name, when the pipeline has been
+/// renamed, which is only important for the preferences
+///
+/// - signals that are targeted towards a given effect, with `effect_id` being its unique id, and
+/// `pipeline_id` the unique id of the pipeline it is attached to:
+/// - `'pipeline_id'::effect-'effect_id'-key-removed`, handing the key that was removed
+/// - `'pipeline_id'::effect-'effect_id'-key-updated`, handing the key that was changed and its
+/// new value
+/// - `'pipeline_id'::effect-'effect_id'-key-added`, handing the key that was added and its
+/// value
+export class PipelinesManager {
+ constructor(settings) {
+ this.settings = settings;
+ this.pipelines = this.settings.PIPELINES;
+ this.settings.PIPELINES_changed(_ => this.on_pipeline_update());
+ }
+
+ create_pipeline(name, effects = []) {
+ // select a random id for the pipeline
+ let id = "pipeline_" + ("" + Math.random()).slice(2, 16);
+ // add a random ID for each effect, to help tracking them
+ effects.forEach(effect => effect.id = "effect_" + ("" + Math.random()).slice(2, 16));
+
+ this.pipelines[id] = { name, effects };
+ this.settings.PIPELINES = this.pipelines;
+ this._emit('pipeline-created', id, this.pipelines[id]);
+ this._emit('pipeline-list-changed');
+ return id;
+ }
+
+ duplicate_pipeline(id) {
+ if (!(id in this.pipelines)) {
+ this._warn(`could not duplicate pipeline, id ${id} does not exist`);
+ return;
+ }
+ const pipeline = this.pipelines[id];
+ this.create_pipeline(pipeline.name + " - duplicate", [...pipeline.effects]);
+ this.settings.PIPELINES = this.pipelines;
+ }
+
+ delete_pipeline(id) {
+ if (!(id in this.pipelines)) {
+ this._warn(`could not delete pipeline, id ${id} does not exist`);
+ return;
+ }
+ if (id == "pipeline_default") {
+ this._warn(`could not delete pipeline "pipeline_default" as it is immutable`);
+ return;
+ }
+ delete this.pipelines[id];
+ this.settings.PIPELINES = this.pipelines;
+ this._emit(id + '::pipeline-destroyed');
+ this._emit('pipeline-list-changed');
+ }
+
+ update_pipeline_effects(id, effects, emit_update_signal = true) {
+ if (!(id in this.pipelines)) {
+ this._warn(`could not update pipeline effects, id ${id} does not exist`);
+ return;
+ }
+ this.pipelines[id].effects = [...effects];
+ this.settings.PIPELINES = this.pipelines;
+ if (emit_update_signal)
+ this._emit(id + '::pipeline-updated');
+ }
+
+ rename_pipeline(id, name) {
+ if (!(id in this.pipelines)) {
+ this._warn(`could not rename pipeline, id ${id} does not exist`);
+ return;
+ }
+ this.pipelines[id].name = name.slice();
+ this.settings.PIPELINES = this.pipelines;
+ this._emit(id + '::pipeline-renamed', name);
+ this._emit('pipeline-names-changed');
+ }
+
+ on_pipeline_update() {
+ const old_pipelines = this.pipelines;
+ this.pipelines = this.settings.PIPELINES;
+
+ for (var pipeline_id in old_pipelines) {
+ // if we find a pipeline that does not exist anymore, signal it
+ if (!(pipeline_id in this.pipelines)) {
+ this._emit(pipeline_id + '::pipeline-destroyed');
+ continue;
+ }
+
+ const old_pipeline = old_pipelines[pipeline_id];
+ const new_pipeline = this.pipelines[pipeline_id];
+
+ // verify if both pipelines have effects in the same order
+ // if they have, then check for their parameters
+ if (
+ old_pipeline.effects.length == new_pipeline.effects.length &&
+ old_pipeline.effects.every((effect, i) => effect.id === new_pipeline.effects[i].id)
+ ) {
+ for (let i = 0; i < old_pipeline.effects.length; i++) {
+ const old_effect = old_pipeline.effects[i];
+ const new_effect = new_pipeline.effects[i];
+ const id = old_effect.id;
+ for (let key in old_effect.params) {
+ // if a key was removed, we emit to tell the effect to use the default value
+ if (!(key in new_effect.params))
+ this._emit(
+ pipeline_id + '::effect-' + id + '-key-removed', key
+ );
+ // if a key was updated, we emit to tell the effect to change its value
+ else if (old_effect.params[key] != new_effect.params[key])
+ this._emit(
+ pipeline_id + '::effect-' + id + '-key-updated', key, new_effect.params[key]
+ );
+ }
+ for (let key in new_effect.params) {
+ // if a key was added, we emit to tell the effect the key and its value
+ if (!(key in old_effect.params))
+ this._emit(
+ pipeline_id + '::effect-' + id + '-key-added', key, new_effect.params[key]
+ );
+ }
+ }
+ }
+ // if either the order has changed, or there are new effects, then rebuild it
+ else
+ this._emit(pipeline_id + '::pipeline-updated', new_pipeline);
+ }
+ }
+
+ destroy() {
+ this.settings.PIPELINES_disconnect();
+ }
+
+ _emit(signal, ...args) {
+ this.emit(signal, ...args);
+ this._log(`signal: '${signal}', arguments: ${args}`);
+ }
+
+ _log(str) {
+ if (this.settings.DEBUG)
+ console.log(`[Blur my Shell > pipelines] ${str}`);
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > pipelines] ${str}`);
+ }
+}
+
+Signals.addSignalMethods(PipelinesManager.prototype); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/settings.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/settings.js
new file mode 100644
index 0000000..53f8497
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/settings.js
@@ -0,0 +1,363 @@
+import GLib from 'gi://GLib';
+const Signals = imports.signals;
+
+/// An enum non-extensively describing the type of gsettings key.
+export const Type = {
+ B: 'Boolean',
+ I: 'Integer',
+ D: 'Double',
+ S: 'String',
+ C: 'Color',
+ AS: 'StringArray',
+ PIPELINES: 'Pipelines'
+};
+
+/// An object to get and manage the gsettings preferences.
+///
+/// Should be initialized with an array of keys, for example:
+///
+/// let settings = new Settings([
+/// { type: Type.I, name: "panel-corner-radius" },
+/// { type: Type.B, name: "debug" }
+/// ]);
+///
+/// Each {type, name} object represents a gsettings key, which must be created
+/// in the gschemas.xml file of the extension.
+export const Settings = class Settings {
+ constructor(keys, settings) {
+ this.settings = settings;
+ this.keys = keys;
+
+ this.keys.forEach(bundle => {
+ let component = this;
+ let component_settings = settings;
+ if (bundle.component !== "general") {
+ let bundle_component = bundle.component.replaceAll('-', '_');
+ this[bundle_component] = {
+ settings: this.settings.get_child(bundle.component)
+ };
+ component = this[bundle_component];
+ component_settings = settings.get_child(bundle.component);
+ }
+
+
+ bundle.schemas.forEach(key => {
+ let property_name = this.get_property_name(key.name);
+
+ switch (key.type) {
+ case Type.B:
+ Object.defineProperty(component, property_name, {
+ get() {
+ return component_settings.get_boolean(key.name);
+ },
+ set(v) {
+ component_settings.set_boolean(key.name, v);
+ }
+ });
+ break;
+
+ case Type.I:
+ Object.defineProperty(component, property_name, {
+ get() {
+ return component_settings.get_int(key.name);
+ },
+ set(v) {
+ component_settings.set_int(key.name, v);
+ }
+ });
+ break;
+
+ case Type.D:
+ Object.defineProperty(component, property_name, {
+ get() {
+ return component_settings.get_double(key.name);
+ },
+ set(v) {
+ component_settings.set_double(key.name, v);
+ }
+ });
+ break;
+
+ case Type.S:
+ Object.defineProperty(component, property_name, {
+ get() {
+ return component_settings.get_string(key.name);
+ },
+ set(v) {
+ component_settings.set_string(key.name, v);
+ }
+ });
+ break;
+
+ case Type.C:
+ Object.defineProperty(component, property_name, {
+ // returns the array [red, blue, green, alpha] with
+ // values between 0 and 1
+ get() {
+ let val = component_settings.get_value(key.name);
+ return val.deep_unpack();
+ },
+ // takes an array [red, blue, green, alpha] with
+ // values between 0 and 1
+ set(v) {
+ let val = new GLib.Variant("(dddd)", v);
+ component_settings.set_value(key.name, val);
+ }
+ });
+ break;
+
+ case Type.AS:
+ Object.defineProperty(component, property_name, {
+ get() {
+ let val = component_settings.get_value(key.name);
+ return val.deep_unpack();
+ },
+ set(v) {
+ let val = new GLib.Variant("as", v);
+ component_settings.set_value(key.name, val);
+ }
+ });
+ break;
+
+ case Type.PIPELINES:
+ Object.defineProperty(component, property_name, {
+ get() {
+ let pips = component_settings.get_value(key.name).deep_unpack();
+ Object.keys(pips).forEach(pipeline_id => {
+ let pipeline = pips[pipeline_id];
+
+ if (!('name' in pipeline)) {
+ this._warn('impossible to get pipelines, pipeline has not name, resetting');
+ component[property_name + '_reset']();
+ return component[property_name];
+ }
+ let name = pipeline.name.deep_unpack();
+ if (typeof name !== 'string') {
+ this._warn('impossible to get pipelines, pipeline name is not a string, resetting');
+ component[property_name + '_reset']();
+ return component[property_name];
+ }
+
+ if (!('effects' in pipeline)) {
+ this._warn('impossible to get pipelines, pipeline has not effects, resetting');
+ component[property_name + '_reset']();
+ return component[property_name];
+ }
+ let effects = pipeline.effects.deep_unpack();
+ if (!Array.isArray(effects)) {
+ this._warn('impossible to get pipelines, pipeline effects is not an array, resetting');
+ component[property_name + '_reset']();
+ return component[property_name];
+ }
+
+ effects = effects.map(effect => effect.deep_unpack());
+ effects.forEach(effect => {
+ if (!('type' in effect)) {
+ this._warn('impossible to get pipelines, effect has not type, resetting');
+ component[property_name + '_reset']();
+ return component[property_name];
+ }
+ let type = effect.type.deep_unpack();
+ if (typeof type !== 'string') {
+ this._warn('impossible to get pipelines, effect type is not a string, resetting');
+ component[property_name + '_reset']();
+ return component[property_name];
+ }
+
+ if (!('id' in effect)) {
+ this._warn('impossible to get pipelines, effect has not id, resetting');
+ component[property_name + '_reset']();
+ return component[property_name];
+ }
+ let id = effect.id.deep_unpack();
+ if (typeof id !== 'string') {
+ this._warn('impossible to get pipelines, effect id is not a string, resetting');
+ component[property_name + '_reset']();
+ return component[property_name];
+ }
+
+ let params = {};
+ if ('params' in effect)
+ params = effect.params.deep_unpack();
+ if (!(params && typeof params === 'object' && params.constructor === Object)) {
+ this._warn('impossible to get pipelines, effect params is not an object, resetting');
+ component[property_name + '_reset']();
+ return component[property_name];
+ }
+ Object.keys(params).forEach(param_key => {
+ params[param_key] = params[param_key].deep_unpack();
+ });
+
+ effect.type = type;
+ effect.id = id;
+ effect.params = params;
+ });
+ pipeline.name = name;
+ pipeline.effects = effects;
+ });
+ return pips;
+ },
+ set(pips) {
+ let pipelines = {};
+ Object.keys(pips).forEach(pipeline_id => {
+ let pipeline = pips[pipeline_id];
+ if (!(pipeline && typeof pipeline === 'object' && pipeline.constructor === Object)) {
+ this._warn('impossible to set pipelines, pipeline is not an object');
+ return;
+ }
+
+ if (!('name' in pipeline)) {
+ this._warn('impossible to set pipelines, pipeline has no name');
+ return;
+ }
+ if (typeof pipeline.name !== 'string') {
+ this._warn('impossible to set pipelines, pipeline name is not a string');
+ return;
+ }
+
+ if (!('effects' in pipeline)) {
+ this._warn('impossible to set pipelines, pipeline has no effect');
+ return;
+ }
+ if (!Array.isArray(pipeline.effects)) {
+ this._warn('impossible to set pipelines, effects is not an array');
+ return;
+ }
+
+ let gvariant_effects = [];
+ pipeline.effects.forEach(effect => {
+ if (!(effect instanceof Object)) {
+ this._warn('impossible to set pipelines, effect is not an object');
+ return;
+ }
+
+ if (!('type' in effect)) {
+ this._warn('impossible to set pipelines, effect has not type');
+ return;
+ }
+ if (typeof effect.type !== 'string') {
+ this._warn('impossible to set pipelines, effect type is not a string');
+ return;
+ }
+
+ if (!('id' in effect)) {
+ this._warn('impossible to set pipelines, effect has not id');
+ return;
+ }
+ if (typeof effect.id !== 'string') {
+ this._warn('impossible to set pipelines, effect id is not a string');
+ return;
+ }
+
+ let params = {};
+ if ('params' in effect) {
+ params = effect.params;
+ }
+ let gvariant_params = {};
+ Object.keys(params).forEach(param_key => {
+ let param = params[param_key];
+ if (typeof param === 'boolean')
+ gvariant_params[param_key] = GLib.Variant.new_boolean(param);
+ else if (typeof param === 'number') {
+ if (Number.isInteger(param))
+ gvariant_params[param_key] = GLib.Variant.new_int32(param);
+ else
+ gvariant_params[param_key] = GLib.Variant.new_double(param);
+ } else if (typeof param === 'string')
+ gvariant_params[param_key] = GLib.Variant.new_string(param);
+ else if (Array.isArray(param) && param.length == 4)
+ gvariant_params[param_key] = new GLib.Variant("(dddd)", param);
+ else
+ this._warn('impossible to set pipeline, effect parameter type is unknown');
+ });
+
+ gvariant_effects.push(
+ new GLib.Variant("a{sv}", {
+ type: GLib.Variant.new_string(effect.type),
+ id: GLib.Variant.new_string(effect.id),
+ params: new GLib.Variant("a{sv}", gvariant_params)
+ })
+ );
+ });
+
+ pipelines[pipeline_id] = {
+ name: GLib.Variant.new_string(pipeline.name),
+ effects: new GLib.Variant("av", gvariant_effects)
+ };
+ });
+ let val = new GLib.Variant("a{sa{sv}}", pipelines);
+ component_settings.set_value(key.name, val);
+ }
+ });
+ break;
+ }
+
+
+ component[property_name + '_reset'] = function () {
+ return component_settings.reset(key.name);
+ };
+
+ component[property_name + '_signal_ids'] = [];
+ component[property_name + '_changed'] = function (cb) {
+ component[property_name + '_signal_ids'].push(
+ component_settings.connect('changed::' + key.name, cb)
+ );
+ };
+
+ component[property_name + '_disconnect'] = function () {
+ component[property_name + '_signal_ids'].forEach(
+ id => component_settings.disconnect(id)
+ );
+ component[property_name + '_signal_ids'] = [];
+ };
+ });
+ });
+ };
+
+ /// Reset the preferences.
+ reset() {
+ this.keys.forEach(bundle => {
+ let component = this;
+ if (bundle.component !== "general") {
+ let bundle_component = bundle.component.replaceAll('-', '_');
+ component = this[bundle_component];
+ }
+
+ bundle.schemas.forEach(key => {
+ let property_name = this.get_property_name(key.name);
+ component[property_name + '_reset']();
+ });
+ });
+
+ this.emit('reset', true);
+ }
+
+ /// From the gschema name, returns the name of the associated property on
+ /// the Settings object.
+ get_property_name(name) {
+ return name.replaceAll('-', '_').toUpperCase();
+ }
+
+ /// Remove all connections managed by the Settings object, i.e. created with
+ /// `settings.PROPERTY_changed(callback)`.
+ disconnect_all_settings() {
+ this.keys.forEach(bundle => {
+ let component = this;
+ if (bundle.component !== "general") {
+ let bundle_component = bundle.component.replaceAll('-', '_');
+ component = this[bundle_component];
+ }
+
+ bundle.schemas.forEach(key => {
+ let property_name = this.get_property_name(key.name);
+ component[property_name + '_disconnect']();
+ });
+ });
+ }
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > settings] ${str}`);
+ }
+};
+
+Signals.addSignalMethods(Settings.prototype); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/settings_updater.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/settings_updater.js
new file mode 100644
index 0000000..2affbc1
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/settings_updater.js
@@ -0,0 +1,40 @@
+import { Settings } from './settings.js';
+import { KEYS, DEPRECATED_KEYS } from './keys.js';
+
+const CURRENT_SETTINGS_VERSION = 2;
+
+export function update_from_old_settings(gsettings) {
+ const preferences = new Settings(KEYS, gsettings);
+ const deprecated_preferences = new Settings(DEPRECATED_KEYS, gsettings);
+ const old_version = preferences.settings.get_int('settings-version');
+
+ if (old_version < CURRENT_SETTINGS_VERSION) {
+ // set artifacts hacks to be 1 at most, as it should be suitable now that most big bugs have
+ // been resolved (and especially because hack levels to 2 now means disabling clipped
+ // redraws entirely, which is very much not what we want for users that update)
+ if (preferences.HACKS_LEVEL > 1)
+ preferences.HACKS_LEVEL = 1;
+
+ // enable dash-to-dock blurring, as most disabled it due to the lack of rounded corners; set
+ // it to static blur by default too and with transparent background
+ preferences.dash_to_dock.BLUR = true;
+ preferences.dash_to_dock.STATIC_BLUR = true;
+ preferences.dash_to_dock.STYLE_DASH_TO_DOCK = 0;
+
+ // 'customize' has been removed: we merge the current used settings
+ ['appfolder', 'panel', 'dash_to_dock', 'applications', 'window_list'].forEach(
+ component_name => {
+ const deprecated_component = deprecated_preferences[component_name];
+ const new_component = preferences[component_name];
+ if (!deprecated_component.CUSTOMIZE) {
+ new_component.SIGMA = deprecated_preferences.SIGMA;
+ new_component.BRIGHTNESS = deprecated_preferences.BRIGHTNESS;
+ }
+ });
+
+ // remove old preferences in order not to clutter the gsettings
+ deprecated_preferences.reset();
+ }
+
+ preferences.settings.set_int('settings-version', CURRENT_SETTINGS_VERSION);
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/utils.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/utils.js
new file mode 100644
index 0000000..0277e0e
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/utils.js
@@ -0,0 +1,38 @@
+import GLib from 'gi://GLib';
+
+export const IS_IN_PREFERENCES = typeof global === 'undefined';
+
+// Taken from https://github.com/Schneegans/Burn-My-Windows/blob/main/src/utils.js
+// This method can be used to import a module in the GNOME Shell process only. This
+// is useful if you want to use a module in extension.js, but not in the preferences
+// process. This method returns null if it is called in the preferences process.
+export async function import_in_shell_only(module) {
+ if (IS_IN_PREFERENCES)
+ return null;
+ return (await import(module)).default;
+}
+
+// In use for the effects, to prevent boilerplate code
+export function setup_params(outer_this, params) {
+ // setup each parameter, either with the given or the default value
+ for (const params_name in outer_this.constructor.default_params) {
+ outer_this["_" + params_name] = null;
+ outer_this[params_name] = params_name in params ?
+ params[params_name] :
+ outer_this.constructor.default_params[params_name];
+ }
+};
+
+export const get_shader_source = (Shell, shader_filename, self_uri) => {
+ if (!Shell)
+ return;
+ const shader_path = GLib.filename_from_uri(
+ GLib.uri_resolve_relative(self_uri, shader_filename, GLib.UriFlags.NONE)
+ )[0];
+ try {
+ return Shell.get_file_contents_utf8_sync(shader_path);
+ } catch (e) {
+ console.warn(`[Blur my Shell > effect] error loading shader from ${shader_path}: ${e}`);
+ return null;
+ }
+}; \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/client.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/client.js
new file mode 100644
index 0000000..3867b3a
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/client.js
@@ -0,0 +1,58 @@
+import Gio from 'gi://Gio';
+
+const bus_name = 'org.gnome.Shell';
+const iface_name = 'dev.aunetx.BlurMyShell';
+const obj_path = '/dev/aunetx/BlurMyShell';
+
+
+/// Call pick() from the DBus service, it will open the Inspector from
+/// gnome-shell to pick an actor on stage.
+export function pick() {
+ Gio.DBus.session.call(
+ bus_name,
+ obj_path,
+ iface_name,
+ 'pick',
+ null,
+ null,
+ Gio.DBusCallFlags.NO_AUTO_START,
+ -1,
+ null,
+ null
+ );
+}
+
+/// Connect to DBus 'picking' signal, which will be emitted when the inspector
+/// is picking a window.
+export function on_picking(cb) {
+ const id = Gio.DBus.session.signal_subscribe(
+ bus_name,
+ iface_name,
+ 'picking',
+ obj_path,
+ null,
+ Gio.DBusSignalFlags.NONE,
+ _ => {
+ cb();
+ Gio.DBus.session.signal_unsubscribe(id);
+ }
+ );
+}
+
+/// Connect to DBus 'picked' signal, which will be emitted when a window is
+/// picked.
+export function on_picked(cb) {
+ const id = Gio.DBus.session.signal_subscribe(
+ bus_name,
+ iface_name,
+ 'picked',
+ obj_path,
+ null,
+ Gio.DBusSignalFlags.NONE,
+ (conn, sender, obj_path, iface, signal, params) => {
+ const val = params.get_child_value(0);
+ cb(val.get_string()[0]);
+ Gio.DBus.session.signal_unsubscribe(id);
+ }
+ );
+}
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/iface.xml b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/iface.xml
new file mode 100644
index 0000000..4f298ad
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/iface.xml
@@ -0,0 +1,12 @@
+<node>
+ <interface name="dev.aunetx.BlurMyShell">
+ <!-- This method is called in preferences to pick a window -->
+ <method name="pick" />
+ <!-- When window is picking, send a signal to preferences -->
+ <signal name="picking"></signal>
+ <!-- If window is picked, send a signal to preferences -->
+ <signal name="picked">
+ <arg name="window" type="s" />
+ </signal>
+ </interface>
+</node> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/services.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/services.js
new file mode 100644
index 0000000..4b1f4f0
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/services.js
@@ -0,0 +1,93 @@
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js';
+
+
+export const ApplicationsService = class ApplicationsService {
+ constructor() {
+ let decoder = new TextDecoder();
+ let path = GLib.filename_from_uri(GLib.uri_resolve_relative(
+ import.meta.url, 'iface.xml', GLib.UriFlags.NONE)
+ )[0];
+ let [, buffer] = GLib.file_get_contents(path);
+ let iface = decoder.decode(buffer);
+ GLib.free(buffer);
+
+ this.DBusImpl = Gio.DBusExportedObject.wrapJSObject(iface, this);
+ }
+
+ /// Pick Window for Preferences Page, exported to DBus client.
+ pick() {
+ // emit `picking` signal to know we are listening
+ const send_picking_signal = _ =>
+ this.DBusImpl.emit_signal(
+ 'picking',
+ null
+ );
+
+ // emit `picked` signal to send wm_class
+ const send_picked_signal = wm_class =>
+ this.DBusImpl.emit_signal(
+ 'picked',
+ new GLib.Variant('(s)', [wm_class])
+ );
+
+ // notify the preferences that we are listening
+ send_picking_signal();
+
+ // A very interesting way to pick a window:
+ // 1. Open LookingGlass to mask all event handles of window
+ // 2. Use inspector to pick window, thats is also lookingGlass do
+ // 3. Close LookingGlass when done
+ // It will restore event handles of window
+
+ // open then hide LookingGlass
+ const looking_class = Main.createLookingGlass();
+ looking_class.open();
+ looking_class.hide();
+
+ // inspect window now
+ const inspector = new LookingGlass.Inspector(Main.createLookingGlass());
+ inspector.connect('target', (me, target, x, y) => {
+ // remove border effect when window is picked.
+ const effect_name = 'lookingGlass_RedBorderEffect';
+ target
+ .get_effects()
+ .filter(e => e.toString().includes(effect_name))
+ .forEach(e => target.remove_effect(e));
+
+ // get wm_class_instance property of window, then pass it to DBus
+ // client
+ const type_str = target.toString();
+
+ let actor = target;
+ if (type_str.includes('MetaSurfaceActor'))
+ actor = target.get_parent();
+
+ if (!actor.toString().includes('WindowActor'))
+ actor = actor.get_parent();
+
+ if (!actor.toString().includes('WindowActor'))
+ return send_picked_signal('window-not-found');
+
+ send_picked_signal(
+ actor.meta_window.get_wm_class() ?? 'window-not-found'
+ );
+ });
+
+ // close LookingGlass when we're done
+ inspector.connect('closed', _ => looking_class.close());
+ }
+
+ export() {
+ this.DBusImpl.export(
+ Gio.DBus.session,
+ '/dev/aunetx/BlurMyShell'
+ );
+ };
+
+ unexport() {
+ this.DBusImpl.unexport();
+ }
+};
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.glsl
new file mode 100644
index 0000000..5df6512
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.glsl
@@ -0,0 +1,111 @@
+uniform sampler2D tex;
+uniform float red;
+uniform float green;
+uniform float blue;
+uniform float blend;
+uniform int mode;
+
+const int NORMAL = 0;
+const int MULTIPLY = 1;
+const int SCREEN = 2;
+const int OVERLAY = 3;
+const int DARKEN = 4;
+const int LIGHTEN = 5;
+const int PLUS_DARKER = 6;
+const int PLUS_LIGHTER = 7;
+const int COLOR_DODGE = 8;
+const int COLOR_BURN = 9;
+const int HARD_LIGHT = 10;
+const int SOFT_LIGHT = 11;
+const int DIFFERENCE = 12;
+const int EXCLUSION = 13;
+const int HUE = 14;
+const int SATURATION = 15;
+const int COLOR = 16;
+const int LUMINOSITY = 17;
+
+vec3 rgb_to_hsl(vec3 c) {
+ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+ vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+ vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+
+ float d = q.x - min(q.w, q.y);
+ float e = 1.0e-10;
+ return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
+}
+
+vec3 hsl_to_rgb(vec3 c) {
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+
+float soft_light_channel(float base, float _blend) {
+ if (_blend < 0.5) {
+ return base - (1.0 - 2.0 * _blend) * base * (1.0 - base);
+ } else {
+ float d = (base < 0.25)
+ ? ((16.0 * base - 12.0) * base + 4.0) * base
+ : sqrt(base);
+ return base + (2.0 * _blend - 1.0) * (d - base);
+ }
+}
+
+vec3 get_blend(vec3 base, vec3 _blend) {
+ if (mode == MULTIPLY) return base * _blend;
+ if (mode == SCREEN) return 1 - (1 - base) * (1 - _blend);
+ if (mode == OVERLAY) {
+ vec3 result;
+ result.r = base.r < 0.5 ? (2.0 * base.r * _blend.r) : (1.0 - 2.0 * (1.0 - base.r) * (1.0 - _blend.r));
+ result.g = base.g < 0.5 ? (2.0 * base.g * _blend.g) : (1.0 - 2.0 * (1.0 - base.g) * (1.0 - _blend.g));
+ result.b = base.b < 0.5 ? (2.0 * base.b * _blend.b) : (1.0 - 2.0 * (1.0 - base.b) * (1.0 - _blend.b));
+ return result;
+ }
+ if (mode == DARKEN) return min(base, _blend);
+ if (mode == LIGHTEN) return max(base, _blend);
+ if (mode == PLUS_DARKER) return base + _blend - 1;
+ if (mode == PLUS_LIGHTER) return base + _blend;
+ if (mode == COLOR_DODGE) return base / (1 - _blend);
+ if (mode == COLOR_BURN) return 1 - (1 - base) / _blend;
+ if (mode == HARD_LIGHT) {
+ vec3 result;
+ result.r = _blend.r < 0.5 ? (2.0 * base.r * _blend.r) : (1.0 - 2.0 * (1.0 - base.r) * (1.0 - _blend.r));
+ result.g = _blend.g < 0.5 ? (2.0 * base.g * _blend.g) : (1.0 - 2.0 * (1.0 - base.g) * (1.0 - _blend.g));
+ result.b = _blend.b < 0.5 ? (2.0 * base.b * _blend.b) : (1.0 - 2.0 * (1.0 - base.b) * (1.0 - _blend.b));
+ return result;
+ }
+ if (mode == SOFT_LIGHT) {
+ return vec3(soft_light_channel(base.r, _blend.r), soft_light_channel(base.g, _blend.g), soft_light_channel(base.b, _blend.b));
+ }
+ if (mode == DIFFERENCE) return abs(base - _blend);
+ if (mode == EXCLUSION) return 0.5 - 2 * (base - 0.5) * (_blend - 0.5);
+ if (mode == HUE) {
+ vec3 base_hsl = rgb_to_hsl(base);
+ vec3 blend_hsl = rgb_to_hsl(_blend);
+ return hsl_to_rgb(vec3(blend_hsl.x, base_hsl.y, base_hsl.z));
+ }
+ if (mode == SATURATION) {
+ vec3 base_hsl = rgb_to_hsl(base);
+ vec3 blend_hsl = rgb_to_hsl(_blend);
+ return hsl_to_rgb(vec3(base_hsl.x, blend_hsl.y, base_hsl.z));
+ }
+ if (mode == COLOR) {
+ vec3 base_hsl = rgb_to_hsl(base);
+ vec3 blend_hsl = rgb_to_hsl(_blend);
+ return hsl_to_rgb(vec3(blend_hsl.x, blend_hsl.y, base_hsl.z));
+ }
+ if (mode == LUMINOSITY) {
+ vec3 base_hsl = rgb_to_hsl(base);
+ vec3 blend_hsl = rgb_to_hsl(_blend);
+ return hsl_to_rgb(vec3(base_hsl.x, base_hsl.y, blend_hsl.z));
+ }
+ return _blend; // For NORMAL
+}
+
+void main() {
+ vec4 c = texture2D(tex, cogl_tex_coord_in[0].st);
+ vec3 pix_color = c.xyz;
+ vec3 color = get_blend(pix_color, vec3(red, green, blue));
+
+ cogl_color_out = vec4(mix(pix_color, color, blend), 1.);
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.js
new file mode 100644
index 0000000..1f4bdf4
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.js
@@ -0,0 +1,168 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'color.glsl';
+const DEFAULT_PARAMS = {
+ color: [0.0, 0.0, 0.0, 0.0],
+ blend_mode: 0
+};
+
+
+export const ColorEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "ColorEffect",
+ Properties: {
+ 'red': GObject.ParamSpec.double(
+ `red`,
+ `Red`,
+ `Red value in shader`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 1.0,
+ 0.0,
+ ),
+ 'green': GObject.ParamSpec.double(
+ `green`,
+ `Green`,
+ `Green value in shader`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 1.0,
+ 0.0,
+ ),
+ 'blue': GObject.ParamSpec.double(
+ `blue`,
+ `Blue`,
+ `Blue value in shader`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 1.0,
+ 0.0,
+ ),
+ 'blend': GObject.ParamSpec.double(
+ `blend`,
+ `Blend`,
+ `Amount of blending between the colors`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 1.0,
+ 0.0,
+ ),
+ 'blend_mode': GObject.ParamSpec.int(
+ `blend_mode`,
+ `Blend mode`,
+ `Blend mode`,
+ GObject.ParamFlags.READWRITE,
+ 0, 17,
+ 0,
+ )
+ }
+ // Normal (0), Multiply (1), Screen (2), Overlay (3), Darken (4), Lighten (5), Plus darker (6), Plus lighter (7), Color dodge (8),
+ // Color burn (9), Hard light (10), Soft light (11), Difference (12), Exclusion (13), Hue (14), Saturation (15), Color (16),
+ // Luminosity (17)
+ }, class ColorEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ // initialize without color as a parameter
+ const { color, ...parent_params } = params;
+ super(parent_params);
+
+ this._red = null;
+ this._green = null;
+ this._blue = null;
+ this._blend = null;
+ this._blend_mode = null;
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+
+ // set params; utils.setup_params doesn't work here with color
+ this.color = 'color' in params ? color : this.constructor.default_params.color;
+ this.blend_mode = 'blend_mode' in params ? params.blend_mode : this.constructor.default_params.blend_mode;
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get red() {
+ return this._red;
+ }
+
+ set red(value) {
+ if (this._red !== value) {
+ this._red = value;
+
+ this.set_uniform_value('red', parseFloat(this._red - 1e-6));
+ }
+ }
+
+ get green() {
+ return this._green;
+ }
+
+ set green(value) {
+ if (this._green !== value) {
+ this._green = value;
+
+ this.set_uniform_value('green', parseFloat(this._green - 1e-6));
+ }
+ }
+
+ get blue() {
+ return this._blue;
+ }
+
+ set blue(value) {
+ if (this._blue !== value) {
+ this._blue = value;
+
+ this.set_uniform_value('blue', parseFloat(this._blue - 1e-6));
+ }
+ }
+
+ get blend() {
+ return this._blend;
+ }
+
+ set blend(value) {
+ if (this._blend !== value) {
+ this._blend = value;
+
+ this.set_uniform_value('blend', parseFloat(this._blend - 1e-6));
+ this.set_enabled(this.blend > 0);
+ }
+ }
+
+ get blend_mode() {
+ return this._blend_mode;
+ }
+
+ set blend_mode(value) {
+ if (this._blend_mode !== value) {
+ this._blend_mode = value;
+
+ this.set_uniform_value('mode', this._blend_mode);
+ }
+ }
+
+ set color(rgba) {
+ let [r, g, b, a] = rgba;
+ this.red = r;
+ this.green = g;
+ this.blue = b;
+ this.blend = a;
+ }
+
+ get color() {
+ return [this.red, this.green, this.blue, this.blend];
+ }
+
+ /// False set function, only cares about the color. Too hard to change.
+ set(params) {
+ this.color = params.color;
+ this.blend_mode = params.blend_mode;
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.glsl
new file mode 100644
index 0000000..760798a
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.glsl
@@ -0,0 +1,93 @@
+// Heavily based on https://github.com/yilozt/rounded-window-corners
+// which is itself based on upstream Mutter code
+
+uniform sampler2D tex;
+uniform float radius;
+uniform float width;
+uniform float height;
+uniform bool corners_top;
+uniform bool corners_bottom;
+
+uniform float clip_x0;
+uniform float clip_y0;
+uniform float clip_width;
+uniform float clip_height;
+
+float circle_bounds(vec2 p, vec2 center, float clip_radius) {
+ vec2 delta = p - center;
+ float dist_squared = dot(delta, delta);
+
+ float outer_radius = clip_radius + 0.5;
+ if (dist_squared >= (outer_radius * outer_radius))
+ return 0.0;
+
+ float inner_radius = clip_radius - 0.5;
+ if (dist_squared <= (inner_radius * inner_radius))
+ return 1.0;
+
+ return outer_radius - sqrt(dist_squared);
+}
+
+vec4 getTexture(vec2 uv) {
+ if (uv.x < 2. / width)
+ uv.x = 2. / width;
+
+ if (uv.y < 2. / height)
+ uv.y = 2. / height;
+
+ if (uv.x > 1. - 3. / width)
+ uv.x = 1. - 3. / width;
+
+ if (uv.y > 1. - 3. / height)
+ uv.y = 1. - 3. / height;
+
+ return texture2D(tex, uv);
+}
+
+float rounded_rect_coverage(vec2 p, vec4 bounds, float clip_radius) {
+ // Outside the bounds
+ if (p.x < bounds.x || p.x > bounds.z || p.y < bounds.y || p.y > bounds.w) {
+ return 0.;
+ }
+
+ vec2 center;
+
+ float center_left = bounds.x + clip_radius;
+ float center_right = bounds.z - clip_radius;
+
+ if (p.x < center_left)
+ center.x = center_left + 2.;
+ else if (p.x > center_right)
+ center.x = center_right - 1.;
+ else
+ return 1.0;
+
+ float center_top = bounds.y + clip_radius;
+ float center_bottom = bounds.w - clip_radius;
+
+ if (corners_top && p.y < center_top)
+ center.y = center_top + 2.;
+ else if (corners_bottom && p.y > center_bottom)
+ center.y = center_bottom - 1.;
+ else
+ return 1.0;
+
+ return circle_bounds(p, center, clip_radius);
+}
+
+void main(void) {
+ vec2 uv = cogl_tex_coord_in[0].xy;
+ vec2 pos = uv * vec2(width, height);
+ vec4 c = getTexture(uv);
+
+ vec4 bounds;
+ if (clip_width < 0. || clip_height < 0.) {
+ bounds = vec4(clip_x0, clip_y0, clip_x0 + width, clip_y0 + height);
+ } else {
+ bounds = vec4(clip_x0, clip_y0, clip_x0 + clip_width, clip_y0 + clip_height);
+ }
+
+ float alpha = rounded_rect_coverage(pos, bounds, radius);
+
+ cogl_color_out = vec4(c.rgb * alpha, min(alpha, c.a));
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.js
new file mode 100644
index 0000000..109be12
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.js
@@ -0,0 +1,211 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const St = await utils.import_in_shell_only('gi://St');
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'corner.glsl';
+const DEFAULT_PARAMS = {
+ radius: 12, width: 0, height: 0,
+ corners_top: true, corners_bottom: true,
+ clip: [0, 0, -1, -1]
+};
+
+
+export const CornerEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "CornerEffect",
+ Properties: {
+ 'radius': GObject.ParamSpec.double(
+ `radius`,
+ `Corner Radius`,
+ `Corner Radius`,
+ GObject.ParamFlags.READWRITE,
+ 0, Number.MAX_SAFE_INTEGER,
+ 12,
+ ),
+ 'width': GObject.ParamSpec.double(
+ `width`,
+ `Width`,
+ `Width`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'height': GObject.ParamSpec.double(
+ `height`,
+ `Height`,
+ `Height`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'corners_top': GObject.ParamSpec.boolean(
+ `corners_top`,
+ `Round top corners`,
+ `Round top corners`,
+ GObject.ParamFlags.READWRITE,
+ true,
+ ),
+ 'corners_bottom': GObject.ParamSpec.boolean(
+ `corners_bottom`,
+ `Round bottom corners`,
+ `Round bottom corners`,
+ GObject.ParamFlags.READWRITE,
+ true,
+ ),
+ // FIXME this works but it logs an error, because I'm not a double...
+ // I don't want to fiddle with GVariants again
+ 'clip': GObject.ParamSpec.double(
+ `clip`,
+ `Clip`,
+ `Clip`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ }
+ }, class CornerEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ super(params);
+
+ this._clip_x0 = null;
+ this._clip_y0 = null;
+ this._clip_width = null;
+ this._clip_height = null;
+
+ utils.setup_params(this, params);
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+
+ const theme_context = St.ThemeContext.get_for_stage(global.stage);
+ theme_context.connectObject('notify::scale-factor', _ => this.update_radius(), this);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get radius() {
+ return this._radius;
+ }
+
+ set radius(value) {
+ if (this._radius !== value) {
+ this._radius = value;
+
+ this.update_radius();
+ }
+ }
+
+ update_radius() {
+ const theme_context = St.ThemeContext.get_for_stage(global.stage);
+ let radius = Math.min(
+ this.radius * theme_context.scale_factor,
+ this.width / 2, this.height / 2
+ );
+ if (this._clip_width >= 0 || this._clip_height >= 0)
+ radius = Math.min(radius, this._clip_width / 2, this._clip_height / 2);
+
+ this.set_uniform_value('radius', parseFloat(radius - 1e-6));
+ }
+
+ get width() {
+ return this._width;
+ }
+
+ set width(value) {
+ if (this._width !== value) {
+ this._width = value;
+
+ this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6));
+ this.update_radius();
+ }
+ }
+
+ get height() {
+ return this._height;
+ }
+
+ set height(value) {
+ if (this._height !== value) {
+ this._height = value;
+
+ this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6));
+ this.update_radius();
+ }
+ }
+
+ get corners_top() {
+ return this._corners_top;
+ }
+
+ set corners_top(value) {
+ if (this._corners_top !== value) {
+ this._corners_top = value;
+
+ this.set_uniform_value('corners_top', this._corners_top ? 1 : 0);
+ }
+ }
+
+ get corners_bottom() {
+ return this._corners_bottom;
+ }
+
+ set corners_bottom(value) {
+ if (this._corners_bottom !== value) {
+ this._corners_bottom = value;
+
+ this.set_uniform_value('corners_bottom', this._corners_bottom ? 1 : 0);
+ }
+ }
+
+ get clip() {
+ return [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height];
+ }
+
+ set clip(value) {
+ [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height] = value;
+ this.set_uniform_value('clip_x0', parseFloat(this._clip_x0 - 1e-6));
+ this.set_uniform_value('clip_y0', parseFloat(this._clip_y0 - 1e-6));
+ this.set_uniform_value('clip_width', parseFloat(this._clip_width + 3 - 1e-6));
+ this.set_uniform_value('clip_height', parseFloat(this._clip_height + 3 - 1e-6));
+ this.update_radius();
+ }
+
+ vfunc_set_actor(actor) {
+ if (this._actor_connection_size_id) {
+ let old_actor = this.get_actor();
+ old_actor?.disconnect(this._actor_connection_size_id);
+ }
+ if (this._actor_connection_clip_rect_id) {
+ let old_actor = this.get_actor();
+ old_actor?.disconnect(this._actor_connection_clip_rect_id);
+ }
+
+ if (actor) {
+ this.width = actor.width;
+ this.height = actor.height;
+ this._actor_connection_size_id = actor.connect('notify::size', _ => {
+ this.width = actor.width;
+ this.height = actor.height;
+ });
+
+ this.clip = actor.has_clip ? actor.get_clip() : [0, 0, -10, -10];
+ this._actor_connection_clip_rect_id = actor.connect('notify::clip-rect', _ => {
+ this.clip = actor.has_clip ? actor.get_clip() : [0, 0, -10, -10];
+ });
+ }
+ else {
+ this._actor_connection_size_id = null;
+ this._actor_connection_clip_rect_id = null;
+ }
+
+ super.vfunc_set_actor(actor);
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.glsl
new file mode 100644
index 0000000..64c1682
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.glsl
@@ -0,0 +1,71 @@
+uniform sampler2D tex;
+uniform int operation;
+uniform float width;
+uniform float height;
+
+#define CORRECTION 2.25
+#define SIZE_ADDITION 3
+
+vec4 get_texture_at_position(vec2 position) {
+ vec2 raw_position = position + vec2(CORRECTION, CORRECTION);
+ vec2 raw_uv = raw_position / vec2(width + SIZE_ADDITION, height + SIZE_ADDITION);
+
+ return texture2D(tex, raw_uv);
+}
+
+vec4 try_get_texture_at_position(vec2 position, inout int count) {
+ if (any(greaterThanEqual(position, vec2(width, height))) ||
+ any(lessThan(position, vec2(0, 0)))) {
+ return vec4(0);
+ } else {
+ count++;
+ return get_texture_at_position(position);
+ }
+}
+
+ivec2 get_corrected_position() {
+ vec2 raw_uv = cogl_tex_coord0_in.st;
+ vec2 raw_position = raw_uv * vec2(width + SIZE_ADDITION, height + SIZE_ADDITION);
+ return ivec2(raw_position - vec2(CORRECTION, CORRECTION));
+}
+
+void main() {
+ ivec2 corrected_position = get_corrected_position();
+
+ // 1-step derivative
+ if (operation == 0) {
+ vec4 color = vec4(0);
+ int c = 0;
+ color += try_get_texture_at_position(corrected_position + vec2(0, 1), c);
+ color -= try_get_texture_at_position(corrected_position + vec2(0, 0), c);
+ color += try_get_texture_at_position(corrected_position + vec2(1, 0), c);
+ color -= try_get_texture_at_position(corrected_position + vec2(0, 0), c);
+ if (c < 4) {
+ color = vec4(0);
+ }
+ cogl_color_out = vec4(color.xyz, 1);
+ } else
+ // 2-step derivative
+ if (operation == 1) {
+ vec4 color = vec4(0);
+ int c = 0;
+ color += try_get_texture_at_position(corrected_position + vec2(0, 1), c);
+ color -= try_get_texture_at_position(corrected_position + vec2(0, -1), c);
+ color += try_get_texture_at_position(corrected_position + vec2(1, 0), c);
+ color -= try_get_texture_at_position(corrected_position + vec2(-1, 0), c);
+ if (c < 4) {
+ color = vec4(0);
+ }
+ cogl_color_out = vec4(color.xyz / 2, 1);
+ } else
+ // laplacian
+ if (operation == 2) {
+ vec4 color = vec4(0);
+ color = -4 * get_texture_at_position(corrected_position);
+ color += get_texture_at_position(corrected_position + vec2(0, 1));
+ color += get_texture_at_position(corrected_position + vec2(0, -1));
+ color += get_texture_at_position(corrected_position + vec2(1, 0));
+ color += get_texture_at_position(corrected_position + vec2(-1, 0));
+ cogl_color_out = vec4(color.xyz, 1);
+ }
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.js
new file mode 100644
index 0000000..04d6100
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.js
@@ -0,0 +1,120 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'derivative.glsl';
+const DEFAULT_PARAMS = {
+ operation: 0, width: 0, height: 0
+};
+
+
+export const DerivativeEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "DerivativeEffect",
+ Properties: {
+ 'operation': GObject.ParamSpec.int(
+ `operation`,
+ `Operation`,
+ `Operation`,
+ GObject.ParamFlags.READWRITE,
+ 0, 2,
+ 0,
+ ),
+ 'width': GObject.ParamSpec.double(
+ `width`,
+ `Width`,
+ `Width`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'height': GObject.ParamSpec.double(
+ `height`,
+ `Height`,
+ `Height`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ )
+ }
+ }, class DerivativeEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ super(params);
+
+ utils.setup_params(this, params);
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get operation() {
+ return this._operation;
+ }
+
+ set operation(value) {
+ if (this._operation !== value) {
+ this._operation = value;
+
+ this.set_uniform_value('operation', this._operation);
+ }
+ }
+
+ get width() {
+ return this._width;
+ }
+
+ set width(value) {
+ if (this._width !== value) {
+ this._width = value;
+
+ this.set_uniform_value('width', parseFloat(this._width - 1e-6));
+ }
+ }
+
+ get height() {
+ return this._height;
+ }
+
+ set height(value) {
+ if (this._height !== value) {
+ this._height = value;
+
+ this.set_uniform_value('height', parseFloat(this._height - 1e-6));
+ }
+ }
+
+ vfunc_set_actor(actor) {
+ if (this._actor_connection_size_id) {
+ let old_actor = this.get_actor();
+ old_actor?.disconnect(this._actor_connection_size_id);
+ }
+ if (actor) {
+ this.width = actor.width;
+ this.height = actor.height;
+ this._actor_connection_size_id = actor.connect('notify::size', _ => {
+ this.width = actor.width;
+ this.height = actor.height;
+ });
+ }
+ else
+ this._actor_connection_size_id = null;
+
+ super.vfunc_set_actor(actor);
+ }
+
+ vfunc_paint_target(paint_node, paint_context) {
+ // force setting nearest-neighbour texture filtering
+ this.get_pipeline().set_layer_filters(0, 9728, 9728);
+
+ super.vfunc_paint_target(paint_node, paint_context);
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.glsl
new file mode 100644
index 0000000..9871268
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.glsl
@@ -0,0 +1,76 @@
+uniform sampler2D tex;
+uniform int divider;
+uniform float width;
+uniform float height;
+uniform int downsampling_mode;
+
+#define CORRECTION 2.25
+#define SIZE_ADDITION 3
+
+vec4 get_texture_at_position(vec2 position) {
+ vec2 raw_position = position + vec2(CORRECTION, CORRECTION);
+ vec2 raw_uv = raw_position / vec2(width + SIZE_ADDITION, height + SIZE_ADDITION);
+
+ return texture2D(tex, raw_uv);
+}
+
+vec2 get_corrected_position() {
+ vec2 raw_uv = cogl_tex_coord0_in.st;
+ vec2 raw_position = raw_uv * vec2(width + SIZE_ADDITION, height + SIZE_ADDITION);
+ return raw_position - vec2(CORRECTION, CORRECTION);
+}
+
+void main() {
+ ivec2 corrected_position = ivec2(get_corrected_position());
+ vec2 multiplied_position = corrected_position * divider;
+
+ if (any(greaterThan(multiplied_position, vec2(width, height)))) {
+ discard;
+ }
+
+ // mode 0: boxcar downsampling
+ if (downsampling_mode == 0) {
+
+ vec4 color = vec4(0.);
+ int count = 0;
+ for (int i = 0; i < divider; i++) {
+ for (int j = 0; j < divider; j++) {
+ vec2 lookup_position = multiplied_position + vec2(i, j);
+ if (all(greaterThanEqual(lookup_position, vec2(0, 0))) &&
+ all(lessThan(lookup_position, vec2(width, height)))) {
+ color += get_texture_at_position(lookup_position);
+ count += 1;
+ }
+ }
+ }
+ cogl_color_out = color / count;
+
+ } else
+ // mode 1: triangular downsampling
+ if (downsampling_mode == 1) {
+
+ vec4 color = vec4(0.);
+ int count = 0;
+ int force = 1;
+ for (int i = 0; i < divider; i++) {
+ for (int j = 0; j < divider; j++) {
+ vec2 lookup_position = multiplied_position + vec2(i, j);
+ if (all(greaterThanEqual(lookup_position, vec2(0, 0))) &&
+ all(lessThan(lookup_position, vec2(width, height)))) {
+ force = 1 + divider - int(abs(divider - i - j));
+ color += get_texture_at_position(lookup_position) * force;
+ count += force;
+ }
+ }
+ }
+ cogl_color_out = color / count;
+
+ } else
+ // mode 2: Dirac downsampling
+ if (downsampling_mode == 2) {
+
+ vec2 lookup_position = min(multiplied_position + vec2(divider, divider) / 2, vec2(width - 1, height - 1));
+ cogl_color_out = get_texture_at_position(lookup_position);
+
+ }
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.js
new file mode 100644
index 0000000..8103486
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.js
@@ -0,0 +1,140 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'downscale.glsl';
+const DEFAULT_PARAMS = {
+ divider: 8, downsampling_mode: 0, width: 0, height: 0
+};
+
+
+export const DownscaleEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "DownscaleEffect",
+ Properties: {
+ 'divider': GObject.ParamSpec.int(
+ `divider`,
+ `Divider`,
+ `Divider`,
+ GObject.ParamFlags.READWRITE,
+ 0, 64,
+ 8,
+ ),
+ 'downsampling_mode': GObject.ParamSpec.int(
+ `downsampling_mode`,
+ `Downsampling mode`,
+ `Downsampling mode`,
+ GObject.ParamFlags.READWRITE,
+ 0, 2,
+ 0,
+ ),
+ 'width': GObject.ParamSpec.double(
+ `width`,
+ `Width`,
+ `Width`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'height': GObject.ParamSpec.double(
+ `height`,
+ `Height`,
+ `Height`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ )
+ }
+ }, class DownscaleEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ super(params);
+
+ utils.setup_params(this, params);
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get divider() {
+ return this._divider;
+ }
+
+ set divider(value) {
+ if (this._divider !== value) {
+ this._divider = value;
+
+ this.set_uniform_value('divider', this._divider);
+ }
+ }
+
+ get downsampling_mode() {
+ return this._downsampling_mode;
+ }
+
+ set downsampling_mode(value) {
+ if (this._downsampling_mode !== value) {
+ this._downsampling_mode = value;
+
+ this.set_uniform_value('downsampling_mode', this._downsampling_mode);
+ }
+ }
+
+ get width() {
+ return this._width;
+ }
+
+ set width(value) {
+ if (this._width !== value) {
+ this._width = value;
+
+ this.set_uniform_value('width', parseFloat(this._width - 1e-6));
+ }
+ }
+
+ get height() {
+ return this._height;
+ }
+
+ set height(value) {
+ if (this._height !== value) {
+ this._height = value;
+
+ this.set_uniform_value('height', parseFloat(this._height - 1e-6));
+ }
+ }
+
+ vfunc_set_actor(actor) {
+ if (this._actor_connection_size_id) {
+ let old_actor = this.get_actor();
+ old_actor?.disconnect(this._actor_connection_size_id);
+ }
+ if (actor) {
+ this.width = actor.width;
+ this.height = actor.height;
+ this._actor_connection_size_id = actor.connect('notify::size', _ => {
+ this.width = actor.width;
+ this.height = actor.height;
+ });
+ }
+ else
+ this._actor_connection_size_id = null;
+
+ super.vfunc_set_actor(actor);
+ }
+
+ vfunc_paint_target(paint_node, paint_context) {
+ // force setting nearest-neighbour texture filtering
+ this.get_pipeline().set_layer_filters(0, 9728, 9728);
+
+ super.vfunc_paint_target(paint_node, paint_context);
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effects.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effects.js
new file mode 100644
index 0000000..e35588d
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effects.js
@@ -0,0 +1,362 @@
+import { NativeDynamicBlurEffect } from '../effects/native_dynamic_gaussian_blur.js';
+import { NativeStaticBlurEffect } from '../effects/native_static_gaussian_blur.js';
+import { GaussianBlurEffect } from '../effects/gaussian_blur.js';
+import { MonteCarloBlurEffect } from '../effects/monte_carlo_blur.js';
+import { ColorEffect } from '../effects/color.js';
+import { NoiseEffect } from '../effects/noise.js';
+import { CornerEffect } from '../effects/corner.js';
+import { DownscaleEffect } from './downscale.js';
+import { UpscaleEffect } from './upscale.js';
+import { PixelizeEffect } from './pixelize.js';
+import { DerivativeEffect } from './derivative.js';
+import { RgbToHslEffect } from './rgb_to_hsl.js';
+import { HslToRgbEffect } from './hsl_to_rgb.js';
+
+// We do in this way because I've not found another way to store our preferences in a dictionnary
+// while calling `gettext` on it while in preferences. Not so pretty, but works.
+export function get_effects_groups(_ = _ => "") {
+ return {
+ blur_effects: {
+ name: _("Blur effects"),
+ contains: [
+ "native_static_gaussian_blur",
+ "gaussian_blur",
+ "monte_carlo_blur"
+ ]
+ },
+ texture_effects: {
+ name: _("Texture effects"),
+ contains: [
+ "downscale",
+ "upscale",
+ "pixelize",
+ "derivative",
+ "noise",
+ "color",
+ "rgb_to_hsl",
+ "hsl_to_rgb"
+ ]
+ },
+ shape_effects: {
+ name: _("Shape effects"),
+ contains: [
+ "corner"
+ ]
+ }
+ };
+};
+
+export function get_supported_effects(_ = () => "") {
+ return {
+ native_dynamic_gaussian_blur: {
+ class: NativeDynamicBlurEffect
+ },
+
+ native_static_gaussian_blur: {
+ class: NativeStaticBlurEffect,
+ name: _("Native gaussian blur"),
+ description: _("An optimized blur effect that smoothly blends pixels within a given radius."),
+ is_advanced: false,
+ editable_params: {
+ unscaled_radius: {
+ name: _("Radius"),
+ description: _("The intensity of the blur effect."),
+ type: "float",
+ min: 0.,
+ max: 100.,
+ increment: 1.0,
+ big_increment: 10.,
+ digits: 0
+ },
+ brightness: {
+ name: _("Brightness"),
+ description: _("The brightness of the blur effect, a high value might make the text harder to read."),
+ type: "float",
+ min: 0.,
+ max: 1.,
+ increment: 0.01,
+ big_increment: 0.1,
+ digits: 2
+ },
+ }
+ },
+
+ gaussian_blur: {
+ class: GaussianBlurEffect,
+ name: _("Gaussian blur (advanced effect)"),
+ description: _("A blur effect that smoothly blends pixels within a given radius. This effect is more precise, but way less optimized."),
+ is_advanced: true,
+ editable_params: {
+ radius: {
+ name: _("Radius"),
+ description: _("The intensity of the blur effect. The bigger it is, the slower it will be."),
+ type: "float",
+ min: 0.,
+ max: 100.,
+ increment: .1,
+ big_increment: 10.,
+ digits: 1
+ },
+ brightness: {
+ name: _("Brightness"),
+ description: _("The brightness of the blur effect, a high value might make the text harder to read."),
+ type: "float",
+ min: 0.,
+ max: 1.,
+ increment: 0.01,
+ big_increment: 0.1,
+ digits: 2
+ },
+ }
+ },
+
+ monte_carlo_blur: {
+ class: MonteCarloBlurEffect,
+ name: _("Monte Carlo blur"),
+ description: _("A blur effect that mimics a random walk, by picking pixels further and further away from its origin and mixing them all together."),
+ is_advanced: false,
+ editable_params: {
+ radius: {
+ name: _("Radius"),
+ description: _("The maximum travel distance for each step in the random walk. A higher value will make the blur more randomized."),
+ type: "float",
+ min: 0.,
+ max: 10.,
+ increment: 0.01,
+ big_increment: 0.1,
+ digits: 2
+ },
+ iterations: {
+ name: _("Iterations"),
+ description: _("The number of iterations. The more there are, the smoother the blur is."),
+ type: "integer",
+ min: 0,
+ max: 50,
+ increment: 1
+ },
+ brightness: {
+ name: _("Brightness"),
+ description: _("The brightness of the blur effect, a high value might make the text harder to read."),
+ type: "float",
+ min: 0.,
+ max: 1.,
+ increment: 0.01,
+ big_increment: 0.1,
+ digits: 2
+ },
+ use_base_pixel: {
+ name: _("Use base pixel"),
+ description: _("Whether or not the original pixel is counted for the blur. If it is, the image will be more legible."),
+ type: "boolean"
+ },
+ prefer_closer_pixels: {
+ name: _("Prefer closer pixels"),
+ description: _("Whether or not the pixels that are closer to the original pixel will have more weight."),
+ type: "boolean"
+ }
+ }
+ },
+
+ color: {
+ class: ColorEffect,
+ name: _("Color"),
+ description: _("An effect that blends a color into the pipeline."),
+ is_advanced: false,
+ // TODO make this RGB + blend
+ editable_params: {
+ color: {
+ name: _("Color"),
+ description: _("The color to blend in. The blending amount is controled by the opacity of the color."),
+ type: "rgba"
+ },
+ blend_mode: {
+ name: _("Blend mode"),
+ description: _("How the color is blended in."),
+ type: "dropdown",
+ options: [
+ _("Normal"),
+ _("Multiply"),
+ _("Screen"),
+ _("Overlay"),
+ _("Darken"),
+ _("Lighten"),
+ _("Plus darker"),
+ _("Plus lighter"),
+ _("Color dodge"),
+ _("Color burn"),
+ _("Hard light"),
+ _("Soft light"),
+ _("Difference"),
+ _("Exclusion"),
+ _("Hue"),
+ _("Saturation"),
+ _("Color"),
+ _("Luminosity")
+ ]
+ }
+ }
+ },
+
+ pixelize: {
+ class: PixelizeEffect,
+ name: _("Pixelize"),
+ description: _("An effect that pixelizes the image."),
+ is_advanced: false,
+ editable_params: {
+ factor: {
+ name: _("Factor"),
+ description: _("How much to scale down the image."),
+ type: "integer",
+ min: 1,
+ max: 50,
+ increment: 1
+ },
+ downsampling_mode: {
+ name: _("Downsampling mode"),
+ description: _("The downsampling method that is used."),
+ type: "dropdown",
+ options: [
+ _("Boxcar"),
+ _("Triangular"),
+ _("Dirac")
+ ]
+ }
+ }
+ },
+
+ downscale: {
+ class: DownscaleEffect,
+ name: _("Downscale (advanced effect)"),
+ description: _("An effect that downscales the image and put it on the top-left corner."),
+ is_advanced: true,
+ editable_params: {
+ divider: {
+ name: _("Factor"),
+ description: _("How much to scale down the image."),
+ type: "integer",
+ min: 1,
+ max: 50,
+ increment: 1
+ },
+ downsampling_mode: {
+ name: _("Downsampling mode"),
+ description: _("The downsampling method that is used."),
+ type: "dropdown",
+ options: [
+ _("Boxcar"),
+ _("Triangular"),
+ _("Dirac")
+ ]
+ }
+ }
+ },
+
+ upscale: {
+ class: UpscaleEffect,
+ name: _("Upscale (advanced effect)"),
+ description: _("An effect that upscales the image from the top-left corner."),
+ is_advanced: true,
+ editable_params: {
+ factor: {
+ name: _("Factor"),
+ description: _("How much to scale up the image."),
+ type: "integer",
+ min: 1,
+ max: 50,
+ increment: 1
+ }
+ }
+ },
+
+ derivative: {
+ class: DerivativeEffect,
+ name: _("Derivative"),
+ description: _("Apply a spatial derivative, or a laplacian."),
+ is_advanced: false,
+ editable_params: {
+ operation: {
+ name: _("Operation"),
+ description: _("The mathematical operation to apply."),
+ type: "dropdown",
+ options: [
+ _("1-step derivative"),
+ _("2-step derivative"),
+ _("Laplacian")
+ ]
+ }
+ }
+ },
+
+ noise: {
+ class: NoiseEffect,
+ name: _("Noise"),
+ description: _("An effect that adds a random noise. Prefer the Monte Carlo blur for a more organic effect if needed."),
+ is_advanced: false,
+ editable_params: {
+ noise: {
+ name: _("Noise"),
+ description: _("The amount of noise to add."),
+ type: "float",
+ min: 0.,
+ max: 1.,
+ increment: 0.01,
+ big_increment: 0.1,
+ digits: 2
+ },
+ lightness: {
+ name: _("Lightness"),
+ description: _("The luminosity of the noise. A setting of '1.0' will make the effect transparent."),
+ type: "float",
+ min: 0.,
+ max: 2.,
+ increment: 0.01,
+ big_increment: 0.1,
+ digits: 2
+ }
+ }
+ },
+
+ rgb_to_hsl: {
+ class: RgbToHslEffect,
+ name: _("RGB to HSL (advanced effect)"),
+ description: _("Converts the image from RGBA colorspace to HSLA."),
+ is_advanced: true,
+ editable_params: {}
+ },
+
+ hsl_to_rgb: {
+ class: HslToRgbEffect,
+ name: _("HSL to RGB (advanced effect)"),
+ description: _("Converts the image from HSLA colorspace to RGBA."),
+ is_advanced: true,
+ editable_params: {}
+ },
+
+ corner: {
+ class: CornerEffect,
+ name: _("Corner"),
+ description: _("An effect that draws corners. Add it last not to have the other effects perturb the corners."),
+ is_advanced: false,
+ editable_params: {
+ radius: {
+ name: _("Radius"),
+ description: _("The radius of the corner. GNOME apps use a radius of 12 px by default."),
+ type: "integer",
+ min: 0,
+ max: 50,
+ increment: 1,
+ },
+ corners_top: {
+ name: _("Top corners"),
+ description: _("Whether or not to round the top corners."),
+ type: "boolean"
+ },
+ corners_bottom: {
+ name: _("Bottom corners"),
+ description: _("Whether or not to round the bottom corners."),
+ type: "boolean"
+ }
+ }
+ }
+ };
+}; \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.glsl
new file mode 100644
index 0000000..809cc93
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.glsl
@@ -0,0 +1,70 @@
+uniform sampler2D tex;
+uniform float sigma;
+uniform int dir;
+uniform float brightness;
+uniform float width;
+uniform float height;
+
+vec4 getTexture(vec2 uv) {
+ if (uv.x < 3. / width)
+ uv.x = 3. / width;
+
+ if (uv.y < 3. / height)
+ uv.y = 3. / height;
+
+ if (uv.x > 1. - 3. / width)
+ uv.x = 1. - 3. / width;
+
+ if (uv.y > 1. - 3. / height)
+ uv.y = 1. - 3. / height;
+
+ return texture2D(tex, uv);
+}
+
+void main(void) {
+ vec2 uv = cogl_tex_coord_in[0].xy;
+ vec2 direction = vec2(dir, (1.0 - dir));
+
+ float pixel_step;
+ if (dir == 0)
+ pixel_step = 1.0 / height;
+ else
+ pixel_step = 1.0 / width;
+
+ vec3 gauss_coefficient;
+ gauss_coefficient.x = 1.0 / (sqrt(2.0 * 3.14159265) * sigma);
+ gauss_coefficient.y = exp(-0.5 / (sigma * sigma));
+ gauss_coefficient.z = gauss_coefficient.y * gauss_coefficient.y;
+
+ float gauss_coefficient_total = gauss_coefficient.x;
+
+ vec4 ret = getTexture(uv) * gauss_coefficient.x;
+ gauss_coefficient.xy *= gauss_coefficient.yz;
+
+ int n_steps = int(ceil(1.5 * sigma)) * 2;
+
+ for (int i = 1; i <= n_steps; i += 2) {
+ float coefficient_subtotal = gauss_coefficient.x;
+ gauss_coefficient.xy *= gauss_coefficient.yz;
+ coefficient_subtotal += gauss_coefficient.x;
+
+ float gauss_ratio = gauss_coefficient.x / coefficient_subtotal;
+
+ float foffset = float(i) + gauss_ratio;
+ vec2 offset = direction * foffset * pixel_step;
+
+ ret += getTexture(uv + offset) * coefficient_subtotal;
+ ret += getTexture(uv - offset) * coefficient_subtotal;
+
+ gauss_coefficient_total += 2.0 * coefficient_subtotal;
+ gauss_coefficient.xy *= gauss_coefficient.yz;
+ }
+ vec4 outColor = ret / gauss_coefficient_total;
+
+ // apply brightness on the second pass (dir==0 comes last)
+ if (dir == 0) {
+ outColor.rgb *= brightness;
+ }
+
+ cogl_color_out = outColor;
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.js
new file mode 100644
index 0000000..113a6fd
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.js
@@ -0,0 +1,213 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const St = await utils.import_in_shell_only('gi://St');
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'gaussian_blur.glsl';
+const DEFAULT_PARAMS = {
+ radius: 30, brightness: .6,
+ width: 0, height: 0, direction: 0, chained_effect: null
+};
+
+
+export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "GaussianBlurEffect",
+ Properties: {
+ 'radius': GObject.ParamSpec.double(
+ `radius`,
+ `Radius`,
+ `Blur radius`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 2000.0,
+ 30.0,
+ ),
+ 'brightness': GObject.ParamSpec.double(
+ `brightness`,
+ `Brightness`,
+ `Blur brightness`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 1.0,
+ 0.6,
+ ),
+ 'width': GObject.ParamSpec.double(
+ `width`,
+ `Width`,
+ `Width`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'height': GObject.ParamSpec.double(
+ `height`,
+ `Height`,
+ `Height`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'direction': GObject.ParamSpec.int(
+ `direction`,
+ `Direction`,
+ `Direction`,
+ GObject.ParamFlags.READWRITE,
+ 0, 1,
+ 0,
+ ),
+ 'chained_effect': GObject.ParamSpec.object(
+ `chained_effect`,
+ `Chained Effect`,
+ `Chained Effect`,
+ GObject.ParamFlags.READWRITE,
+ GObject.Object,
+ ),
+ }
+ }, class GaussianBlurEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ super(params);
+
+ utils.setup_params(this, params);
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+
+ const theme_context = St.ThemeContext.get_for_stage(global.stage);
+ theme_context.connectObject(
+ 'notify::scale-factor', _ =>
+ this.set_uniform_value('sigma',
+ parseFloat(this.radius * theme_context.scale_factor / 2 - 1e-6)
+ ),
+ this
+ );
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get radius() {
+ return this._radius;
+ }
+
+ set radius(value) {
+ if (this._radius !== value) {
+ this._radius = value;
+
+ const scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
+
+ // like Clutter, we use the assumption radius = 2*sigma
+ this.set_uniform_value('sigma', parseFloat(this._radius * scale_factor / 2 - 1e-6));
+ this.set_enabled(this.radius > 0.);
+
+ if (this.chained_effect)
+ this.chained_effect.radius = value;
+ }
+ }
+
+ get brightness() {
+ return this._brightness;
+ }
+
+ set brightness(value) {
+ if (this._brightness !== value) {
+ this._brightness = value;
+
+ this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6));
+
+ if (this.chained_effect)
+ this.chained_effect.brightness = value;
+ }
+ }
+
+ get width() {
+ return this._width;
+ }
+
+ set width(value) {
+ if (this._width !== value) {
+ this._width = value;
+
+ this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6));
+
+ if (this.chained_effect)
+ this.chained_effect.width = value;
+ }
+ }
+
+ get height() {
+ return this._height;
+ }
+
+ set height(value) {
+ if (this._height !== value) {
+ this._height = value;
+
+ this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6));
+
+ if (this.chained_effect)
+ this.chained_effect.height = value;
+ }
+ }
+
+ get direction() {
+ return this._direction;
+ }
+
+ set direction(value) {
+ if (this._direction !== value)
+ this._direction = value;
+ }
+
+ get chained_effect() {
+ return this._chained_effect;
+ }
+
+ set chained_effect(value) {
+ this._chained_effect = value;
+ }
+
+ vfunc_set_actor(actor) {
+ if (this._actor_connection_size_id) {
+ let old_actor = this.get_actor();
+ old_actor?.disconnect(this._actor_connection_size_id);
+ }
+ if (actor) {
+ this.width = actor.width;
+ this.height = actor.height;
+ this._actor_connection_size_id = actor.connect('notify::size', _ => {
+ this.width = actor.width;
+ this.height = actor.height;
+ });
+ }
+ else
+ this._actor_connection_size_id = null;
+
+ super.vfunc_set_actor(actor);
+
+ if (this.direction == 0) {
+ if (this.chained_effect)
+ this.chained_effect.get_actor()?.remove_effect(this.chained_effect);
+ else
+ this.chained_effect = new GaussianBlurEffect({
+ radius: this.radius,
+ brightness: this.brightness,
+ width: this.width,
+ height: this.height,
+ direction: 1
+ });
+ if (actor !== null)
+ actor.add_effect(this.chained_effect);
+ }
+ }
+
+ vfunc_paint_target(paint_node, paint_context) {
+ this.set_uniform_value("dir", this.direction);
+
+ super.vfunc_paint_target(paint_node, paint_context);
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.glsl
new file mode 100644
index 0000000..58d2694
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.glsl
@@ -0,0 +1,14 @@
+uniform sampler2D tex;
+
+vec3 hsl_to_rgb(vec3 c) {
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+
+void main(void) {
+ vec2 uv = cogl_tex_coord_in[0].xy;
+ vec4 hsla = texture2D(tex, uv);
+ vec4 rgba = vec4(hsl_to_rgb(hsla.xyz), hsla.w);
+ cogl_color_out = rgba;
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.js
new file mode 100644
index 0000000..fe53114
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.js
@@ -0,0 +1,31 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'hsl_to_rgb.glsl';
+const DEFAULT_PARAMS = {};
+
+
+export const HslToRgbEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "HslToRgbEffect",
+ Properties: {}
+ }, class HslToRgbEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ super(params);
+
+ utils.setup_params(this, params);
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl
new file mode 100644
index 0000000..27b3806
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl
@@ -0,0 +1,52 @@
+uniform sampler2D tex;
+uniform float radius;
+uniform int iterations;
+uniform float brightness;
+uniform float width;
+uniform float height;
+uniform bool use_base_pixel;
+uniform bool prefer_closer_pixels;
+
+float srand(vec2 a) {
+ return sin(dot(a, vec2(1233.224, 1743.335)));
+}
+
+float rand(inout float r) {
+ r = fract(3712.65 * r + 0.61432);
+ return (r - 0.5) * 2.0;
+}
+
+void main() {
+ vec2 uv = cogl_tex_coord0_in.st;
+ vec2 p = 16 * radius / vec2(width, height);
+ float r = srand(uv);
+
+ vec2 rv;
+ vec2 dir;
+ vec2 new_uv;
+ int strength;
+
+ int count = 0;
+ vec4 c = vec4(0.);
+
+ for (int i = 0; i < iterations; i++) {
+ rv.x = rand(r);
+ rv.y = rand(r) * 3.141592;
+ dir = vec2(cos(rv.y), sin(rv.y));
+ new_uv = uv + rv.x * dir * p;
+ if (new_uv.x > 2. / width && new_uv.y > 2. / height && new_uv.x < 1. - 3. / width && new_uv.y < 1. - 3. / height) {
+ strength = prefer_closer_pixels ? (iterations - i)^2 : 1;
+ c += strength * texture2D(tex, new_uv);
+ count += strength;
+ }
+ }
+
+ if (count == 0 || use_base_pixel) {
+ strength = prefer_closer_pixels ? (iterations + 1)^2 : 1;
+ c += strength * texture2D(tex, uv);
+ count += strength;
+ }
+
+ c.xyz *= brightness;
+ cogl_color_out = c / count;
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.js
new file mode 100644
index 0000000..0da56ed
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.js
@@ -0,0 +1,207 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const St = await utils.import_in_shell_only('gi://St');
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'monte_carlo_blur.glsl';
+const DEFAULT_PARAMS = {
+ radius: 2., iterations: 5, brightness: .6,
+ width: 0, height: 0, use_base_pixel: true,
+ prefer_closer_pixels: true,
+};
+
+
+export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "MonteCarloBlurEffect",
+ Properties: {
+ 'radius': GObject.ParamSpec.double(
+ `radius`,
+ `Radius`,
+ `Blur radius`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 2000.0,
+ 2.0,
+ ),
+ 'iterations': GObject.ParamSpec.int(
+ `iterations`,
+ `Iterations`,
+ `Blur iterations`,
+ GObject.ParamFlags.READWRITE,
+ 0, 64,
+ 5,
+ ),
+ 'brightness': GObject.ParamSpec.double(
+ `brightness`,
+ `Brightness`,
+ `Blur brightness`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 1.0,
+ 0.6,
+ ),
+ 'width': GObject.ParamSpec.double(
+ `width`,
+ `Width`,
+ `Width`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'height': GObject.ParamSpec.double(
+ `height`,
+ `Height`,
+ `Height`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'use_base_pixel': GObject.ParamSpec.boolean(
+ `use_base_pixel`,
+ `Use base pixel`,
+ `Use base pixel`,
+ GObject.ParamFlags.READWRITE,
+ true,
+ ),
+ 'prefer_closer_pixels': GObject.ParamSpec.boolean(
+ `prefer_closer_pixels`,
+ `Prefer closer pixels`,
+ `Prefer closer pixels`,
+ GObject.ParamFlags.READWRITE,
+ true,
+ ),
+ }
+ }, class MonteCarloBlurEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ super(params);
+
+ utils.setup_params(this, params);
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+
+ const theme_context = St.ThemeContext.get_for_stage(global.stage);
+ theme_context.connectObject(
+ 'notify::scale-factor',
+ _ => this.set_uniform_value('radius',
+ parseFloat(this._radius * theme_context.scale_factor - 1e-6)
+ ),
+ this
+ );
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get radius() {
+ return this._radius;
+ }
+
+ set radius(value) {
+ if (this._radius !== value) {
+ this._radius = value;
+
+ const scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
+
+ this.set_uniform_value('radius', parseFloat(this._radius * scale_factor - 1e-6));
+ this.set_enabled(this.radius > 0. && this.iterations > 0);
+ }
+ }
+
+ get iterations() {
+ return this._iterations;
+ }
+
+ set iterations(value) {
+ if (this._iterations !== value) {
+ this._iterations = value;
+
+ this.set_uniform_value('iterations', this._iterations);
+ this.set_enabled(this.radius > 0. && this.iterations > 0);
+ }
+ }
+
+ get brightness() {
+ return this._brightness;
+ }
+
+ set brightness(value) {
+ if (this._brightness !== value) {
+ this._brightness = value;
+
+ this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6));
+ }
+ }
+
+ get width() {
+ return this._width;
+ }
+
+ set width(value) {
+ if (this._width !== value) {
+ this._width = value;
+
+ this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6));
+ }
+ }
+
+ get height() {
+ return this._height;
+ }
+
+ set height(value) {
+ if (this._height !== value) {
+ this._height = value;
+
+ this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6));
+ }
+ }
+
+ get use_base_pixel() {
+ return this._use_base_pixel;
+ }
+
+ set use_base_pixel(value) {
+ if (this._use_base_pixel !== value) {
+ this._use_base_pixel = value;
+
+ this.set_uniform_value('use_base_pixel', this._use_base_pixel ? 1 : 0);
+ }
+ }
+
+ get prefer_closer_pixels() {
+ return this._prefer_closer_pixels;
+ }
+
+ set prefer_closer_pixels(value) {
+ if (this._prefer_closer_pixels !== value) {
+ this._prefer_closer_pixels = value;
+
+ this.set_uniform_value('prefer_closer_pixels', this._prefer_closer_pixels ? 1 : 0);
+ }
+ }
+
+ vfunc_set_actor(actor) {
+ if (this._actor_connection_size_id) {
+ let old_actor = this.get_actor();
+ old_actor?.disconnect(this._actor_connection_size_id);
+ }
+ if (actor) {
+ this.width = actor.width;
+ this.height = actor.height;
+ this._actor_connection_size_id = actor.connect('notify::size', _ => {
+ this.width = actor.width;
+ this.height = actor.height;
+ });
+ }
+ else
+ this._actor_connection_size_id = null;
+
+ super.vfunc_set_actor(actor);
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js
new file mode 100644
index 0000000..556ffa4
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js
@@ -0,0 +1,43 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const St = await utils.import_in_shell_only('gi://St');
+const Shell = await utils.import_in_shell_only('gi://Shell');
+
+const DEFAULT_PARAMS = {
+ unscaled_radius: 30, brightness: 0.6
+};
+
+
+export const NativeDynamicBlurEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "NativeDynamicBlurEffect"
+ }, class NativeDynamicBlurEffect extends Shell.BlurEffect {
+ constructor(params) {
+ const { unscaled_radius, brightness, ...parent_params } = params;
+ super({ ...parent_params, mode: Shell.BlurMode.BACKGROUND });
+
+ this._theme_context = St.ThemeContext.get_for_stage(global.stage);
+ this._theme_context.connectObject(
+ 'notify::scale-factor',
+ _ => this.radius = this.unscaled_radius * this._theme_context.scale_factor,
+ this
+ );
+
+ utils.setup_params(this, params);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get unscaled_radius() {
+ return this._unscaled_radius;
+ }
+
+ set unscaled_radius(value) {
+ this._unscaled_radius = value;
+ this.radius = value * this._theme_context.scale_factor;
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js
new file mode 100644
index 0000000..fe003f5
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js
@@ -0,0 +1,43 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const St = await utils.import_in_shell_only('gi://St');
+const Shell = await utils.import_in_shell_only('gi://Shell');
+
+const DEFAULT_PARAMS = {
+ unscaled_radius: 30, brightness: 0.6
+};
+
+
+export const NativeStaticBlurEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "NativeStaticBlurEffect"
+ }, class NativeStaticBlurEffect extends Shell.BlurEffect {
+ constructor(params) {
+ const { unscaled_radius, brightness, ...parent_params } = params;
+ super({ ...parent_params, mode: Shell.BlurMode.ACTOR });
+
+ this._theme_context = St.ThemeContext.get_for_stage(global.stage);
+ this._theme_context.connectObject(
+ 'notify::scale-factor',
+ _ => this.radius = this.unscaled_radius * this._theme_context.scale_factor,
+ this
+ );
+
+ utils.setup_params(this, params);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get unscaled_radius() {
+ return this._unscaled_radius;
+ }
+
+ set unscaled_radius(value) {
+ this._unscaled_radius = value;
+ this.radius = value * this._theme_context.scale_factor;
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.glsl
new file mode 100644
index 0000000..6d701b6
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.glsl
@@ -0,0 +1,20 @@
+uniform sampler2D tex;
+uniform float noise;
+uniform float lightness;
+
+float PHI = 1.61803398874989484820459;
+float SEED = 24;
+
+float noise_gen(in vec2 xy) {
+ float r = fract(tan(distance(xy * PHI, xy) * SEED) * xy.x);
+ r = r != r ? 0.0 : r;
+ return r;
+}
+
+void main() {
+ vec4 c = texture2D(tex, cogl_tex_coord_in[0].st);
+ vec3 pix_color = c.xyz;
+ float blend = noise * (1. - noise_gen(gl_FragCoord.xy));
+
+ cogl_color_out = vec4(mix(pix_color, lightness * pix_color, blend), 1.);
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.js
new file mode 100644
index 0000000..3049fa1
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.js
@@ -0,0 +1,76 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'noise.glsl';
+const DEFAULT_PARAMS = {
+ noise: 0.4, lightness: 0.4
+};
+
+
+export const NoiseEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "NoiseEffect",
+ Properties: {
+ 'noise': GObject.ParamSpec.double(
+ `noise`,
+ `Noise`,
+ `Amount of noise integrated with the image`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 1.0,
+ 0.4,
+ ),
+ 'lightness': GObject.ParamSpec.double(
+ `lightness`,
+ `Lightness`,
+ `Lightness of the grey used for the noise`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 2.0,
+ 0.4,
+ ),
+ }
+ }, class NoiseEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ super(params);
+
+ utils.setup_params(this, params);
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get noise() {
+ return this._noise;
+ }
+
+ set noise(value) {
+ if (this._noise !== value) {
+ this._noise = value;
+
+ this.set_uniform_value('noise', parseFloat(this._noise - 1e-6));
+ this.set_enabled(this.noise > 0. && this.lightness != 1);
+ }
+ }
+
+ get lightness() {
+ return this._lightness;
+ }
+
+ set lightness(value) {
+ if (this._lightness !== value) {
+ this._lightness = value;
+
+ this.set_uniform_value('lightness', parseFloat(this._lightness - 1e-6));
+ this.set_enabled(this.noise > 0. && this.lightness != 1);
+ }
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/pixelize.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/pixelize.js
new file mode 100644
index 0000000..e9cad9b
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/pixelize.js
@@ -0,0 +1,88 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+import { UpscaleEffect } from './upscale.js';
+import { DownscaleEffect } from './downscale.js';
+
+const DEFAULT_PARAMS = {
+ factor: 8, downsampling_mode: 0
+};
+
+
+export const PixelizeEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "PixelizeEffect",
+ Properties: {
+ 'factor': GObject.ParamSpec.int(
+ `factor`,
+ `Factor`,
+ `Factor`,
+ GObject.ParamFlags.READWRITE,
+ 0, 64,
+ 8,
+ ),
+ 'downsampling_mode': GObject.ParamSpec.int(
+ `downsampling_mode`,
+ `Downsampling mode`,
+ `Downsampling mode`,
+ GObject.ParamFlags.READWRITE,
+ 0, 2,
+ 0,
+ )
+ }
+ }, class PixelizeEffect extends Clutter.Effect {
+ constructor(params) {
+ super();
+
+ this.upscale_effect = new UpscaleEffect({});
+ this.downscale_effect = new DownscaleEffect({});
+
+ utils.setup_params(this, params);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get factor() {
+ // should be the same as `this.downscale_effect.divider`
+ return this.upscale_effect.factor;
+ }
+
+ set factor(value) {
+ this.upscale_effect.factor = value;
+ this.downscale_effect.divider = value;
+ }
+
+ get downsampling_mode() {
+ return this.downscale_effect.downsampling_mode;
+ }
+
+ set downsampling_mode(value) {
+ this.downscale_effect.downsampling_mode = value;
+ }
+
+ vfunc_set_actor(actor) {
+ // deattach effects from old actor
+ this.upscale_effect?.actor?.remove_effect(this.upscale_effect);
+ this.downscale_effect?.actor?.remove_effect(this.downscale_effect);
+ // attach effects to new actor
+ if (actor) {
+ if (this.upscale_effect)
+ actor.add_effect(this.upscale_effect);
+ if (this.downscale_effect)
+ actor.add_effect(this.downscale_effect);
+ }
+
+ super.vfunc_set_actor(actor);
+ }
+
+ vfunc_set_enabled(is_enabled) {
+ this.upscale_effect?.set_enabled(is_enabled);
+ this.downscale_effect?.set_enabled(is_enabled);
+ super.vfunc_set_enabled(is_enabled);
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.glsl
new file mode 100644
index 0000000..b7a35ac
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.glsl
@@ -0,0 +1,18 @@
+uniform sampler2D tex;
+
+vec3 rgb_to_hsl(vec3 c) {
+ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+ vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+ vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+
+ float d = q.x - min(q.w, q.y);
+ float e = 1.0e-10;
+ return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
+}
+
+void main(void) {
+ vec2 uv = cogl_tex_coord_in[0].xy;
+ vec4 rgba = texture2D(tex, uv);
+ vec4 hsla = vec4(rgb_to_hsl(rgba.xyz), rgba.w);
+ cogl_color_out = hsla;
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.js
new file mode 100644
index 0000000..5c4eb05
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.js
@@ -0,0 +1,31 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'rgb_to_hsl.glsl';
+const DEFAULT_PARAMS = {};
+
+
+export const RgbToHslEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "RgbToHslEffect",
+ Properties: {}
+ }, class RgbToHslEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ super(params);
+
+ utils.setup_params(this, params);
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.glsl
new file mode 100644
index 0000000..5cc06ec
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.glsl
@@ -0,0 +1,57 @@
+uniform sampler2D tex;
+uniform int factor;
+uniform float width;
+uniform float height;
+
+#define CORRECTION 2.25
+#define SIZE_ADDITION 3
+
+vec4 get_texture_at_position(vec2 position) {
+ vec2 raw_position = position + vec2(CORRECTION, CORRECTION);
+ vec2 raw_uv = raw_position / vec2(width + SIZE_ADDITION, height + SIZE_ADDITION);
+
+ return texture2D(tex, raw_uv);
+}
+
+ivec2 get_corrected_position() {
+ vec2 raw_uv = cogl_tex_coord0_in.st;
+ vec2 raw_position = raw_uv * vec2(width + SIZE_ADDITION, height + SIZE_ADDITION);
+ return ivec2(raw_position - vec2(CORRECTION, CORRECTION));
+}
+
+void main() {
+ ivec2 corrected_position = get_corrected_position();
+
+ vec2 adjusted_position = corrected_position / factor;
+
+ cogl_color_out = get_texture_at_position(adjusted_position);
+
+ // round
+ if (distance(corrected_position, (floor(adjusted_position) + 0.5) * factor) < factor / 2.5) {
+ //cogl_color_out = get_texture_at_position(adjusted_position);
+ } else {
+ //cogl_color_out = vec4(0, 0, 0, 1);
+ }
+
+ // square
+ if (mod(corrected_position.x, factor) >= 2 && mod(corrected_position.y, factor) >= 2) {
+ //cogl_color_out = get_texture_at_position(adjusted_position);
+ } else {
+ //cogl_color_out = vec4(0, 0, 0, 1);
+ }
+
+ // local mix
+ vec4 color = vec4(0);
+ int count = 0;
+ for (int i = -1; i <= 1; i++) {
+ for (int j = -1; j <= 1; j++) {
+ vec2 lookup_position = adjusted_position + vec2(i, j);
+ if (all(greaterThanEqual(lookup_position, vec2(0, 0))) &&
+ all(lessThan(lookup_position, vec2(width, height) / factor))) {
+ color += get_texture_at_position(lookup_position);
+ count += 1;
+ }
+ }
+ }
+ //cogl_color_out = color / count;
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.js
new file mode 100644
index 0000000..fb719c3
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.js
@@ -0,0 +1,120 @@
+import GObject from 'gi://GObject';
+
+import * as utils from '../conveniences/utils.js';
+const Shell = await utils.import_in_shell_only('gi://Shell');
+const Clutter = await utils.import_in_shell_only('gi://Clutter');
+
+const SHADER_FILENAME = 'upscale.glsl';
+const DEFAULT_PARAMS = {
+ factor: 8, width: 0, height: 0
+};
+
+
+export const UpscaleEffect = utils.IS_IN_PREFERENCES ?
+ { default_params: DEFAULT_PARAMS } :
+ new GObject.registerClass({
+ GTypeName: "UpscaleEffect",
+ Properties: {
+ 'factor': GObject.ParamSpec.int(
+ `factor`,
+ `Factor`,
+ `Factor`,
+ GObject.ParamFlags.READWRITE,
+ 0, 64,
+ 8,
+ ),
+ 'width': GObject.ParamSpec.double(
+ `width`,
+ `Width`,
+ `Width`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'height': GObject.ParamSpec.double(
+ `height`,
+ `Height`,
+ `Height`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ )
+ }
+ }, class UpscaleEffect extends Clutter.ShaderEffect {
+ constructor(params) {
+ super(params);
+
+ utils.setup_params(this, params);
+
+ // set shader source
+ this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
+ if (this._source)
+ this.set_shader_source(this._source);
+ }
+
+ static get default_params() {
+ return DEFAULT_PARAMS;
+ }
+
+ get factor() {
+ return this._factor;
+ }
+
+ set factor(value) {
+ if (this._factor !== value) {
+ this._factor = value;
+
+ this.set_uniform_value('factor', this._factor);
+ }
+ }
+
+ get width() {
+ return this._width;
+ }
+
+ set width(value) {
+ if (this._width !== value) {
+ this._width = value;
+
+ this.set_uniform_value('width', parseFloat(this._width - 1e-6));
+ }
+ }
+
+ get height() {
+ return this._height;
+ }
+
+ set height(value) {
+ if (this._height !== value) {
+ this._height = value;
+
+ this.set_uniform_value('height', parseFloat(this._height - 1e-6));
+ }
+ }
+
+ vfunc_set_actor(actor) {
+ if (this._actor_connection_size_id) {
+ let old_actor = this.get_actor();
+ old_actor?.disconnect(this._actor_connection_size_id);
+ }
+ if (actor) {
+ this.width = actor.width;
+ this.height = actor.height;
+ this._actor_connection_size_id = actor.connect('notify::size', _ => {
+ this.width = actor.width;
+ this.height = actor.height;
+ });
+ }
+ else
+ this._actor_connection_size_id = null;
+
+ super.vfunc_set_actor(actor);
+ }
+
+ vfunc_paint_target(paint_node, paint_context) {
+ // force setting nearest-neighbour texture filtering
+ this.get_pipeline().set_layer_filters(0, 9728, 9728);
+
+ super.vfunc_paint_target(paint_node, paint_context);
+ }
+ }); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/extension.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/extension.js
new file mode 100644
index 0000000..fbfb54c
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/extension.js
@@ -0,0 +1,614 @@
+import Meta from 'gi://Meta';
+import Clutter from 'gi://Clutter';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import * as Config from 'resource:///org/gnome/shell/misc/config.js';
+
+import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js';
+
+import { update_from_old_settings } from './conveniences/settings_updater.js';
+import { PipelinesManager } from './conveniences/pipelines_manager.js';
+import { EffectsManager } from './conveniences/effects_manager.js';
+import { Connections } from './conveniences/connections.js';
+import { Settings } from './conveniences/settings.js';
+import { KEYS } from './conveniences/keys.js';
+
+import { PanelBlur } from './components/panel.js';
+import { OverviewBlur } from './components/overview.js';
+import { DashBlur } from './components/dash_to_dock.js';
+import { LockscreenBlur } from './components/lockscreen.js';
+import { AppFoldersBlur } from './components/appfolders.js';
+import { WindowListBlur } from './components/window_list.js';
+import { CoverflowAltTabBlur } from './components/coverflow_alt_tab.js';
+import { ApplicationsBlur } from './components/applications.js';
+import { ScreenshotBlur } from './components/screenshot.js';
+
+
+/// The main extension class, created when the GNOME Shell is loaded.
+export default class BlurMyShell extends Extension {
+ /// Enables the extension.
+ enable() {
+ // add the extension to global to make it accessible to other extensions
+ // create it first as it is very useful when debugging crashes
+ global.blur_my_shell = this;
+
+ // update from old settings, very important for hacks level specifically
+ update_from_old_settings(this.getSettings());
+
+ // create a Settings instance, to manage extension's preferences
+ // it needs to be loaded before logging, as it checks for DEBUG
+ this._settings = new Settings(KEYS, this.getSettings());
+
+ this._log("enabling extension...");
+
+ // create main extension Connections instance
+ this._connection = new Connections;
+
+ // store it in a global array
+ this._connections = [this._connection];
+
+ // create a global effects manager (to prevent RAM bleeding)
+ this._effects_manager = new EffectsManager(this._connection);
+
+ // create a global pipelines manager, that helps talking with preferences
+ this._pipelines_manager = new PipelinesManager(this._settings);
+
+ // create an instance of each component, with its associated Connections
+ let init = () => {
+ // create a Connections instance, to manage signals
+ let connection = new Connections;
+
+ // store it to keeps track of them globally
+ this._connections.push(connection);
+
+ return [connection, this._settings, this._effects_manager];
+ };
+
+ this._panel_blur = new PanelBlur(...init());
+ this._dash_to_dock_blur = new DashBlur(...init());
+ this._overview_blur = new OverviewBlur(...init());
+ this._lockscreen_blur = new LockscreenBlur(...init());
+ this._appfolder_blur = new AppFoldersBlur(...init());
+ this._window_list_blur = new WindowListBlur(...init());
+ this._coverflow_alt_tab_blur = new CoverflowAltTabBlur(...init());
+ this._applications_blur = new ApplicationsBlur(...init());
+ this._screenshot_blur = new ScreenshotBlur(...init());
+
+ // connect each component to preferences change
+ this._connect_to_settings();
+
+ // enable the lockscreen blur, only one important in both `user` session and `unlock-dialog`
+ if (this._settings.lockscreen.BLUR && !this._lockscreen_blur.enabled)
+ this._lockscreen_blur.enable();
+
+ // ensure we take the correct action for the current session mode
+ this._user_session_mode_enabled = false;
+ this._on_session_mode_changed(Main.sessionMode);
+
+ // watch for changes to the session mode
+ this._connection.connect(Main.sessionMode, 'updated',
+ () => this._on_session_mode_changed(Main.sessionMode)
+ );
+ }
+
+ /// Enables the components related to the user session (everything except lockscreen blur).
+ _enable_user_session() {
+ this._log("changing mode to user session...");
+
+ // maybe disable clipped redraw
+ this._update_clipped_redraws();
+
+ // enable every component
+ // if the shell is still starting up, wait for it to be entirely loaded;
+ // this should prevent bugs like #136 and #137
+ if (Main.layoutManager._startingUp) {
+ this._connection.connect(
+ Main.layoutManager,
+ 'startup-complete',
+ () => this._enable_components()
+ );
+ } else
+ this._enable_components();
+
+ // try to enable the components as soon as possible anyway, this way the
+ // overview may load before the user sees it
+ try {
+ if (this._settings.overview.BLUR && !this._overview_blur.enabled)
+ this._overview_blur.enable();
+ } catch (e) {
+ this._log("Could not enable overview blur directly");
+ this._log(e);
+ }
+ try {
+ if (this._settings.dash_to_dock.BLUR
+ && !this._dash_to_dock_blur.enabled)
+ this._dash_to_dock_blur.enable();
+ } catch (e) {
+ this._log("Could not enable dash-to-dock blur directly");
+ this._log(e);
+ }
+ try {
+ if (this._settings.panel.BLUR && !this._panel_blur.enabled)
+ this._panel_blur.enable();
+ } catch (e) {
+ this._log("Could not enable panel blur directly");
+ this._log(e);
+ }
+
+ // tells the extension we have enabled the user session components, so that we do not
+ // disable them later if they were not even enabled to begin with
+ this._user_session_mode_enabled = true;
+ }
+
+ /// Disables the extension.
+ ///
+ /// This extension needs to use the 'unlock-dialog' session mode in order to change the blur on
+ /// the lockscreen. We have kind of two states of enablement for this extension:
+ /// - the 'enabled' state, which means that we have created the necessary components (which only
+ /// are js objects) and enabled the lockscreen blur (which means swapping two functions from
+ /// the `UnlockDialog` constructor with our ones;
+ /// - the 'user session enabled` mode, which means that we are in the 'enabled' mode AND we are
+ /// in the user mode, and so we enable all the other components that we created before.
+ /// We switch from one state to the other thanks to `this._on_session_mode_changed`, and we
+ /// track wether or not we are in the user mode with `this._user_session_mode_enabled` (because
+ /// `this._on_session_mode_changed` might be called multiple times while in the user session
+ /// mode, typically when going back from simple lockscreen and not sleep mode).
+ disable() {
+ this._log("disabling extension...");
+
+ // disable every component from user session mode
+ if (this._user_session_mode_enabled)
+ this._disable_user_session();
+ this._overview_blur.restore_patched_proto();
+
+ // disable lockscreen blur too
+ this._lockscreen_blur.disable();
+
+ // untrack them
+ this._panel_blur = null;
+ this._dash_to_dock_blur = null;
+ this._overview_blur = null;
+ this._appfolder_blur = null;
+ this._lockscreen_blur = null;
+ this._window_list_blur = null;
+ this._coverflow_alt_tab_blur = null;
+ this._applications_blur = null;
+ this._screenshot_blur = null;
+
+ // make sure no settings change can re-enable them
+ this._settings.disconnect_all_settings();
+
+ // force disconnecting every signal, even if component crashed
+ this._connections.forEach((connections) => {
+ connections.disconnect_all();
+ });
+ this._connections = [];
+
+ // remove the clipped redraws flag
+ this._reenable_clipped_redraws();
+
+ // remove the extension from GJS's global
+ delete global.blur_my_shell;
+
+ this._log("extension disabled.");
+
+ this._settings = null;
+ }
+
+ /// Disables the components related to the user session (everything except lockscreen blur).
+ _disable_user_session() {
+ this._log("disabling user session mode...");
+
+ // disable every component except lockscreen blur
+ this._panel_blur.disable();
+ this._dash_to_dock_blur.disable();
+ this._overview_blur.disable();
+ this._appfolder_blur.disable();
+ this._window_list_blur.disable();
+ this._coverflow_alt_tab_blur.disable();
+ this._applications_blur.disable();
+ this._screenshot_blur.disable();
+
+ // remove the clipped redraws flag
+ this._reenable_clipped_redraws();
+
+ // tells the extension we have disabled the user session components, so that we do not
+ // disable them later again if they were already disabled
+ this._user_session_mode_enabled = false;
+ }
+
+ /// Restarts the components related to the user session.
+ _restart() {
+ this._log("restarting...");
+
+ this._disable_user_session();
+ this._enable_user_session();
+
+ this._log("restarted.");
+ }
+
+ /// Changes the extension to operate either on 'user' mode or 'unlock-dialog' mode, switching
+ /// from one to the other means enabling/disabling every component except lockscreen blur.
+ _on_session_mode_changed(session) {
+ if (session.currentMode === 'user' || session.parentMode === 'user') {
+ if (!this._user_session_mode_enabled)
+ // we need to activate everything
+ this._enable_user_session();
+ }
+ else if (session.currentMode === 'unlock-dialog') {
+ if (this._user_session_mode_enabled)
+ // we need to disable the components related to the user session mode
+ this._disable_user_session();
+ }
+ }
+
+ /// Add or remove the clutter debug flag to disable clipped redraws.
+ /// This will entirely fix the blur effect, but should not be used except if
+ /// the user really needs it, as clipped redraws are a huge performance
+ /// boost for the compositor.
+ _update_clipped_redraws() {
+ if (this._settings.HACKS_LEVEL === 2)
+ this._disable_clipped_redraws();
+ else
+ this._reenable_clipped_redraws();
+ }
+
+ /// Add the Clutter debug flag.
+ _disable_clipped_redraws() {
+ let gnome_shell_major_version = parseInt(Config.PACKAGE_VERSION.split('.')[0]);
+ if (gnome_shell_major_version >= 48)
+ Clutter.add_debug_flags(
+ null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null
+ );
+ else
+ Meta.add_clutter_debug_flags(
+ null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null
+ );
+ }
+
+ /// Remove the Clutter debug flag.
+ _reenable_clipped_redraws() {
+ let gnome_shell_major_version = parseInt(Config.PACKAGE_VERSION.split('.')[0]);
+ if (gnome_shell_major_version >= 48)
+ Clutter.remove_debug_flags(
+ null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null
+ );
+ else
+ Meta.remove_clutter_debug_flags(
+ null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null
+ );
+ }
+
+ /// Enables every component from the user session needed, should be called when the shell is
+ /// entirely loaded as the `enable` methods interact with it.
+ _enable_components() {
+ // enable each component if needed, and if it is not already enabled
+
+ if (this._settings.panel.BLUR && !this._panel_blur.enabled)
+ this._panel_blur.enable();
+
+ if (this._settings.dash_to_dock.BLUR && !this._dash_to_dock_blur.enabled)
+ this._dash_to_dock_blur.enable();
+
+ if (this._settings.overview.BLUR && !this._overview_blur.enabled)
+ this._overview_blur.enable();
+
+ if (this._settings.appfolder.BLUR)
+ this._appfolder_blur.enable();
+
+ if (this._settings.applications.BLUR)
+ this._applications_blur.enable();
+
+ if (this._settings.window_list.BLUR)
+ this._window_list_blur.enable();
+
+ if (this._settings.coverflow_alt_tab.BLUR)
+ this._coverflow_alt_tab_blur.enable();
+
+ if (this._settings.screenshot.BLUR)
+ this._screenshot_blur.enable();
+
+ this._log("all components enabled.");
+ }
+
+ /// Updates needed things in each component when a preference changed
+ _connect_to_settings() {
+ // restart the extension when hacks level is changed, easier than
+ // restarting individual components and should not happen often either
+ this._settings.HACKS_LEVEL_changed(() => this._restart());
+
+
+ // ---------- OVERVIEW ----------
+
+ // toggled on/off
+ this._settings.overview.BLUR_changed(() => {
+ if (this._settings.overview.BLUR)
+ this._overview_blur.enable();
+ else
+ this._overview_blur.disable();
+ });
+
+ // overview pipeline changed
+ this._settings.overview.PIPELINE_changed(() => {
+ if (this._settings.overview.BLUR)
+ this._overview_blur.update_backgrounds();
+ });
+
+ // overview components style changed
+ this._settings.overview.STYLE_COMPONENTS_changed(() => {
+ if (this._settings.overview.BLUR)
+ this._overview_blur.update_components_classname();
+ });
+
+
+ // ---------- APPFOLDER ----------
+
+ // toggled on/off
+ this._settings.appfolder.BLUR_changed(() => {
+ if (this._settings.appfolder.BLUR)
+ this._appfolder_blur.enable();
+ else
+ this._appfolder_blur.disable();
+ });
+
+ // appfolder sigma changed
+ this._settings.appfolder.SIGMA_changed(() => {
+ if (this._settings.appfolder.BLUR)
+ this._appfolder_blur.set_sigma(
+ this._settings.appfolder.SIGMA
+ );
+ });
+
+ // appfolder brightness changed
+ this._settings.appfolder.BRIGHTNESS_changed(() => {
+ if (this._settings.appfolder.BLUR)
+ this._appfolder_blur.set_brightness(
+ this._settings.appfolder.BRIGHTNESS
+ );
+ });
+
+ // appfolder dialogs style changed
+ this._settings.appfolder.STYLE_DIALOGS_changed(() => {
+ if (this._settings.appfolder.BLUR)
+ this._appfolder_blur.blur_appfolders();
+ });
+
+
+ // ---------- PANEL ----------
+
+ // toggled on/off
+ this._settings.panel.BLUR_changed(() => {
+ if (this._settings.panel.BLUR)
+ this._panel_blur.enable();
+ else
+ this._panel_blur.disable();
+ });
+
+ // static blur toggled on/off, really we can just reload the blur at this point
+ this._settings.panel.STATIC_BLUR_changed(() => {
+ if (this._settings.panel.BLUR)
+ this._panel_blur.reset();
+ });
+
+ // panel pipeline changed
+ this._settings.panel.PIPELINE_changed(() => {
+ if (this._settings.panel.BLUR)
+ this._panel_blur.update_pipeline();
+ });
+
+ // panel blur's overview connection toggled on/off
+ this._settings.panel.UNBLUR_IN_OVERVIEW_changed(() => {
+ this._panel_blur.connect_to_windows_and_overview();
+ });
+
+ // force light text toggled on/off
+ this._settings.panel.FORCE_LIGHT_TEXT_changed(() => {
+ if (this._settings.panel.BLUR)
+ this._panel_blur.update_light_text_classname();
+ });
+
+ // panel override background toggled on/off
+ this._settings.panel.OVERRIDE_BACKGROUND_changed(() => {
+ if (this._settings.panel.BLUR)
+ this._panel_blur.connect_to_windows_and_overview();
+ });
+
+ // panel style changed
+ this._settings.panel.STYLE_PANEL_changed(() => {
+ if (this._settings.panel.BLUR)
+ this._panel_blur.connect_to_windows_and_overview();
+ });
+
+ // panel background's dynamic overriding toggled on/off
+ this._settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_changed(() => {
+ if (this._settings.panel.BLUR)
+ this._panel_blur.connect_to_windows_and_overview();
+ });
+
+
+ // ---------- DASH TO DOCK ----------
+
+ // toggled on/off
+ this._settings.dash_to_dock.BLUR_changed(() => {
+ if (this._settings.dash_to_dock.BLUR)
+ this._dash_to_dock_blur.enable();
+ else
+ this._dash_to_dock_blur.disable();
+ });
+
+ // static blur toggled on/off
+ this._settings.dash_to_dock.STATIC_BLUR_changed(() => {
+ if (this._settings.dash_to_dock.BLUR)
+ this._dash_to_dock_blur.change_blur_type();
+ });
+
+ // overview pipeline changed
+ this._settings.dash_to_dock.PIPELINE_changed(() => {
+ if (this._settings.dash_to_dock.BLUR)
+ this._dash_to_dock_blur.update_pipeline();
+ });
+
+ // dash-to-dock override background toggled on/off
+ this._settings.dash_to_dock.OVERRIDE_BACKGROUND_changed(() => {
+ if (this._settings.dash_to_dock.BLUR)
+ this._dash_to_dock_blur.update_background();
+ });
+
+ // dash-to-dock style changed
+ this._settings.dash_to_dock.STYLE_DASH_TO_DOCK_changed(() => {
+ if (this._settings.dash_to_dock.BLUR)
+ this._dash_to_dock_blur.update_background();
+ });
+
+ // dash-to-dock blur's overview connection toggled on/off
+ this._settings.dash_to_dock.UNBLUR_IN_OVERVIEW_changed(() => {
+ if (this._settings.dash_to_dock.BLUR)
+ this._dash_to_dock_blur.connect_to_overview();
+ });
+
+
+ // ---------- APPLICATIONS ----------
+
+ // toggled on/off
+ this._settings.applications.BLUR_changed(() => {
+ if (this._settings.applications.BLUR)
+ this._applications_blur.enable();
+ else
+ this._applications_blur.disable();
+ });
+
+ // static blur toggled on/off
+ this._settings.applications.STATIC_BLUR_changed(() => {
+ if (this._settings.applications.BLUR)
+ this._applications_blur.change_blur_type();
+ });
+
+ // pipeline changed
+ this._settings.applications.PIPELINE_changed(() => {
+ if (this._settings.applications.BLUR)
+ this._applications_blur.change_pipeline();
+ });
+
+ // application opacity changed
+ this._settings.applications.OPACITY_changed(() => {
+ if (this._settings.applications.BLUR)
+ this._applications_blur.set_opacity(
+ this._settings.applications.OPACITY
+ );
+ });
+
+ // application dynamic-opacity changed
+ this._settings.applications.DYNAMIC_OPACITY_changed(() => {
+ if (this._settings.applications.BLUR)
+ this._applications_blur.init_dynamic_opacity();
+ });
+
+ // application blur-on-overview changed
+ this._settings.applications.BLUR_ON_OVERVIEW_changed(() => {
+ if (this._settings.applications.BLUR)
+ this._applications_blur.connect_to_overview();
+ });
+
+ // application enable-all changed
+ this._settings.applications.ENABLE_ALL_changed(() => {
+ if (this._settings.applications.BLUR)
+ this._applications_blur.update_all_windows();
+ });
+
+ // application whitelist changed
+ this._settings.applications.WHITELIST_changed(() => {
+ if (
+ this._settings.applications.BLUR
+ && !this._settings.applications.ENABLE_ALL
+ )
+ this._applications_blur.update_all_windows();
+ });
+
+ // application blacklist changed
+ this._settings.applications.BLACKLIST_changed(() => {
+ if (
+ this._settings.applications.BLUR
+ && this._settings.applications.ENABLE_ALL
+ )
+ this._applications_blur.update_all_windows();
+ });
+
+
+ // ---------- LOCKSCREEN ----------
+
+ // toggled on/off
+ this._settings.lockscreen.BLUR_changed(() => {
+ if (this._settings.lockscreen.BLUR)
+ this._lockscreen_blur.enable();
+ else
+ this._lockscreen_blur.disable();
+ });
+
+ // lockscreen pipeline changed
+ this._settings.lockscreen.PIPELINE_changed(() => {
+ if (this._settings.lockscreen.BLUR)
+ this._lockscreen_blur.update_lockscreen();
+ });
+
+
+ // ---------- WINDOW LIST ----------
+
+ // toggled on/off
+ this._settings.window_list.BLUR_changed(() => {
+ if (this._settings.window_list.BLUR)
+ this._window_list_blur.enable();
+ else
+ this._window_list_blur.disable();
+ });
+
+
+ // ---------- COVERFLOW ALT-TAB ----------
+
+ // toggled on/off
+ this._settings.coverflow_alt_tab.BLUR_changed(() => {
+ if (this._settings.coverflow_alt_tab.BLUR)
+ this._coverflow_alt_tab_blur.enable();
+ else
+ this._coverflow_alt_tab_blur.disable();
+ });
+
+
+ // ---------- HIDETOPBAR ----------
+
+ // toggled on/off
+ this._settings.hidetopbar.COMPATIBILITY_changed(() => {
+ // no need to verify if it is enabled or not, it is done anyway
+ this._panel_blur.connect_to_windows_and_overview();
+ });
+
+
+ // ---------- DASH TO PANEL ----------
+
+ // toggled on/off
+ this._settings.dash_to_panel.BLUR_ORIGINAL_PANEL_changed(() => {
+ if (this._settings.panel.BLUR)
+ this._panel_blur.reset();
+ });
+
+
+ // ---------- SCREENSHOT ----------
+
+ // toggled on/off
+ this._settings.screenshot.BLUR_changed(() => {
+ if (this._settings.screenshot.BLUR)
+ this._screenshot_blur.enable();
+ else
+ this._screenshot_blur.disable();
+ });
+
+ // screenshot pipeline changed
+ this._settings.screenshot.PIPELINE_changed(() => {
+ if (this._settings.screenshot.BLUR)
+ this._screenshot_blur.update_pipeline();
+ });
+ }
+
+ _log(str) {
+ if (this._settings.DEBUG)
+ console.log(`[Blur my Shell > extension] ${str}`);
+ }
+}
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-row-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-row-symbolic.svg
new file mode 100644
index 0000000..bdab309
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-row-symbolic.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="2" y="7" width="11" height="1" fill="#363636"/>
+ <rect transform="rotate(90)" x="2" y="-8" width="11" height="1" fill="#363636"/>
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg
new file mode 100644
index 0000000..87f307f
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg7"
+ sodipodi:docname="applications.svg"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview9"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="44.6875"
+ inkscape:cx="5.5944056"
+ inkscape:cy="8"
+ inkscape:window-width="1500"
+ inkscape:window-height="963"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg7" />
+ <defs
+ id="defs3">
+ <style
+ id="current-color-scheme"
+ type="text/css">.ColorScheme-Text { color:#363636; }</style>
+ </defs>
+ <path
+ d="M 2,1 C 0.892,1 0,1.892 0,3 v 9 c 0,1.108 0.892,2 2,2 h 12 c 1.108,0 2,-0.892 2,-2 V 3 C 16,1.892 15.108,1 14,1 Z m 0,1 h 12 c 0.554,0 1,0.446 1,1 H 1 C 1,2.446 1.446,2 2,2 Z M 1,3 h 14 v 9 c 0,0.554 -0.446,1 -1,1 H 2 C 1.446,13 1,12.554 1,12 Z"
+ style="fill:currentColor"
+ class="ColorScheme-Text"
+ id="path5"
+ sodipodi:nodetypes="sssssssssssccsccssssc" />
+ <g
+ id="g68"
+ transform="translate(0.3993007,0.15314685)">
+ <path
+ d="M 9.5,4 C 9.223,4 9,4.223 9,4.5 v 2 A 0.499,0.499 0 0 0 9.5,7 h 2 C 11.777,7 12,6.777 12,6.5 v -2 C 12,4.223 11.777,4 11.5,4 Z M 10,5 h 1 v 1 h -1 z"
+ fill="#363636"
+ id="path2" />
+ <path
+ d="M 4,6 C 3.446,6 3,6.446 3,7 v 3 c 0,0.554 0.446,1 1,1 h 3 c 0.554,0 1,-0.446 1,-1 V 7 C 8,6.446 7.554,6 7,6 Z m 0,1 h 3 v 3 H 4 Z"
+ fill="#363636"
+ id="path8" />
+ </g>
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg
new file mode 100644
index 0000000..2eda98b
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg7"
+ sodipodi:docname="panel.svg"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview9"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="44.6875"
+ inkscape:cx="5.5944056"
+ inkscape:cy="8"
+ inkscape:window-width="1500"
+ inkscape:window-height="963"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg7" />
+ <defs
+ id="defs3">
+ <style
+ id="current-color-scheme"
+ type="text/css">.ColorScheme-Text { color:#363636; }</style>
+ </defs>
+ <path
+ d="M 2,1 C 0.892,1 0,1.892 0,3 v 9 c 0,1.108 0.892,2 2,2 h 12 c 1.108,0 2,-0.892 2,-2 V 3 C 16,1.892 15.108,1 14,1 Z m 0,1 h 12 c 0.554,0 1,0.446 1,1 H 1 C 1,2.446 1.446,2 2,2 Z M 1,4 h 14 v 8 c 0,0.554 -0.446,1 -1,1 H 2 C 1.446,13 1,12.554 1,12 Z"
+ style="fill:currentColor"
+ class="ColorScheme-Text"
+ id="path5"
+ sodipodi:nodetypes="sssssssssssccsccssssc" />
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg
new file mode 100644
index 0000000..5a78b46
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg7"
+ sodipodi:docname="top-panel.svg"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview9"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="44.6875"
+ inkscape:cx="5.5944056"
+ inkscape:cy="8"
+ inkscape:window-width="1500"
+ inkscape:window-height="963"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg7" />
+ <defs
+ id="defs3">
+ <style
+ id="current-color-scheme"
+ type="text/css">.ColorScheme-Text { color:#363636; }</style>
+ </defs>
+ <path
+ d="M 2,1 C 0.892,1 0,1.892 0,3 v 9 c 0,1.108 0.892,2 2,2 h 12 c 1.108,0 2,-0.892 2,-2 V 3 C 16,1.892 15.108,1 14,1 Z m 0,1 h 12 c 0.554,0 1,0.446 1,1 H 1 C 1,2.446 1.446,2 2,2 Z M 1,3 h 14 v 9 c 0,0.554 -0.446,1 -1,1 H 2 C 1.446,13 1,12.554 1,12 Z m 3,7 c -0.554,0 -1,0.446 -1,1 0,0.554 0.446,1 1,1 h 8 c 0.554,0 1,-0.446 1,-1 0,-0.554 -0.446,-1 -1,-1 z"
+ style="fill:currentColor"
+ class="ColorScheme-Text"
+ id="path5"
+ sodipodi:nodetypes="sssssssssssccsccsssscsssssss" />
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/down-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/down-symbolic.svg
new file mode 100644
index 0000000..652f8c0
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/down-symbolic.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 2.292969 6.707031 l 5 5 c 0.390625 0.390625 1.023437 0.390625 1.414062 0 l 5 -5 c 0.390625 -0.390625 0.390625 -1.023437 0 -1.414062 s -1.023437 -0.390625 -1.414062 0 l -4.292969 4.292969 l -4.292969 -4.292969 c -0.390625 -0.390625 -1.023437 -0.390625 -1.414062 0 s -0.390625 1.023437 0 1.414062 z m 0 0" fill="#222222" fill-rule="evenodd"/></svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/duplicate-row-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/duplicate-row-symbolic.svg
new file mode 100644
index 0000000..925e900
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/duplicate-row-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M7 5c-1.108 0-2 .892-2 2v7c0 1.108.892 2 2 2h7c1.108 0 2-.892 2-2V7c0-1.108-.892-2-2-2Zm0 1h7c.554 0 1 .446 1 1v7c0 .554-.446 1-1 1H7c-.554 0-1-.446-1-1V7c0-.554.446-1 1-1Z" style="fill:#dedede;stroke:none;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke fill markers;stop-color:#000"/><path d="M2 0C.892 0 0 .892 0 2v7c0 1.108.892 2 2 2h2v-1H2c-.554 0-1-.446-1-1V2c0-.554.446-1 1-1h7c.554 0 1 .446 1 1v2h1V2c0-1.108-.892-2-2-2Z" style="fill:#dedede;stroke:none;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke fill markers;stop-color:#000"/></svg> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dynamic-mode-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dynamic-mode-symbolic.svg
new file mode 100644
index 0000000..c37b9aa
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dynamic-mode-symbolic.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="16px"
+ height="16px"
+ viewBox="0 0 16 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="dynamic-mode-symbolic.svg"
+ inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs5" />
+ <sodipodi:namedview
+ id="namedview5"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:zoom="44.75"
+ inkscape:cx="7.9888268"
+ inkscape:cy="8"
+ inkscape:window-width="1500"
+ inkscape:window-height="963"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg5"
+ showguides="true" />
+ <path
+ d="m 11.5,11.34375 a 5.75,5.75 0 0 1 -1,0.134766 v 2.234375 C 10.5,14.425813 9.9258135,15 9.2128906,15 H 2.2871094 C 1.5741865,15 1,14.425813 1,13.712891 V 6.7871094 C 1,6.0741865 1.5741865,5.5 2.2871094,5.5 h 2.234375 A 5.75,5.75 0 0 1 4.65625,4.5 H 1.5585937 C 0.69558189,4.5 0,5.1955819 0,6.0585937 V 14.441406 C 0,15.304418 0.69558189,16 1.5585937,16 H 9.9414063 C 10.804418,16 11.5,15.304418 11.5,14.441406 Z"
+ style="opacity:1;fill:#dedede;stroke-linejoin:round"
+ id="path14" />
+ <path
+ d="M 10.5,11.478516 A 5.75,5.75 0 0 1 10.25,11.5 5.75,5.75 0 0 1 4.5,5.75 5.75,5.75 0 0 1 4.5214844,5.5 H 2.2871094 C 1.5741865,5.5 1,6.0741865 1,6.7871094 V 13.712891 C 1,14.425813 1.5741865,15 2.2871094,15 H 9.2128906 C 9.9258135,15 10.5,14.425813 10.5,13.712891 Z"
+ style="opacity:0.25;fill:#dedede;stroke-width:0.826087;stroke-linejoin:round"
+ id="path15" />
+ <path
+ d="m 11.5,11.34375 v -1.029297 a 4.75,4.75 0 0 1 -1,0.164063 v 1 a 5.75,5.75 0 0 0 1,-0.134766 z"
+ style="opacity:1;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.25351;stroke-linejoin:round;-inkscape-stroke:hairline"
+ id="path22" />
+ <path
+ d="M 10.25,0 A 5.75,5.75 0 0 0 4.65625,4.5 H 5.6855469 A 4.75,4.75 0 0 1 10.25,1 4.75,4.75 0 0 1 15,5.75 4.75,4.75 0 0 1 11.5,10.314453 V 11.34375 A 5.75,5.75 0 0 0 16,5.75 5.75,5.75 0 0 0 10.25,0 Z"
+ style="opacity:1;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.25351;stroke-linejoin:round;-inkscape-stroke:hairline"
+ id="path18" />
+ <path
+ d="m 4.5214844,5.5 h 1 a 4.75,4.75 0 0 1 0.1640625,-1 H 4.65625 a 5.75,5.75 0 0 0 -0.1347656,1 z"
+ style="opacity:1;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.25351;stroke-linejoin:round;-inkscape-stroke:hairline"
+ id="path17" />
+ <path
+ d="m 10.5,11.478516 v -1 A 4.75,4.75 0 0 1 10.25,10.5 4.75,4.75 0 0 1 5.5,5.75 4.75,4.75 0 0 1 5.5214844,5.5 h -1 A 5.75,5.75 0 0 0 4.5,5.75 a 5.75,5.75 0 0 0 5.75,5.75 5.75,5.75 0 0 0 0.25,-0.02148 z"
+ style="opacity:1;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.25351;stroke-linejoin:round;-inkscape-stroke:hairline"
+ id="path16" />
+ <path
+ d="M 10.5,10.478516 V 6.7871094 C 10.5,6.0741865 9.9258135,5.5 9.2128906,5.5 H 5.5214844 A 4.75,4.75 0 0 0 5.5,5.75 a 4.75,4.75 0 0 0 4.75,4.75 4.75,4.75 0 0 0 0.25,-0.02148 z"
+ style="opacity:0.125;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.03551;stroke-linejoin:round;-inkscape-stroke:hairline;fill-opacity:1"
+ id="path21" />
+ <path
+ d="m 5.6855469,4.5 a 4.75,4.75 0 0 0 -0.1640625,1 H 9.2128906 C 9.9258135,5.5 10.5,6.0741865 10.5,6.7871094 v 3.6914066 a 4.75,4.75 0 0 0 1,-0.164063 V 6.0585937 C 11.5,5.1955819 10.804418,4.5 9.9414063,4.5 Z"
+ style="opacity:0.5;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.03551;stroke-linejoin:round;-inkscape-stroke:hairline;fill-opacity:1"
+ id="path20" />
+ <path
+ d="M 5.6855469,4.5 H 9.9414063 C 10.804418,4.5 11.5,5.1955819 11.5,6.0585937 V 10.314453 A 4.75,4.75 0 0 0 15,5.75 4.75,4.75 0 0 0 10.25,1 4.75,4.75 0 0 0 5.6855469,4.5 Z"
+ style="opacity:0;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.03551;stroke-linejoin:round;-inkscape-stroke:hairline;fill-opacity:1"
+ id="path19" />
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/edit-row-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/edit-row-symbolic.svg
new file mode 100644
index 0000000..f4115ad
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/edit-row-symbolic.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <metadata>
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <dc:title/>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <path d="m4 1c-1.108 0-2 0.892-2 2v10c0 1.108 0.892 2 2 2h8c1.108 0 2-0.892 2-2v-5.0488l-1 1v4.0488c0 0.554-0.446 1-1 1h-8c-0.554 0-1-0.446-1-1v-10c0-0.554 0.446-1 1-1h6.0488l1-1z" fill="#dedede"/>
+ <path class="ColorScheme-Text" d="m14.607 1.6863c-0.78347-0.78347-2.045-0.78347-2.8284 0l3.5355 3.5355c0.78347-0.78347 0.78348-2.045 0-2.8284zm-3.5355 0.70711-7.0711 7.0711-6e-7 3.5355h3.5355l7.0711-7.0711zm0 1.4142 2.1213 2.1213-5.6569 5.6569-2.1213-2.1213z" fill="#dedede"/>
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-symbolic.svg
new file mode 100644
index 0000000..fa045a8
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-symbolic.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 5.074219 1.9375 c -3.136719 -0.3125 -5.875 3.914062 -2.816407 6.613281 l 5.742188 5.117188 l 5.746094 -5.117188 c 2.585937 -2.238281 1.070312 -6.492187 -2.351563 -6.585937 c -0.972656 -0.027344 -1.921875 0.324218 -2.636719 0.984375 l -0.757812 0.675781 l -0.753906 -0.675781 c -0.703125 -0.628907 -1.449219 -0.941407 -2.171875 -1.011719 z m -0.097657 0.988281 c 0.507813 0.046875 1.039063 0.265625 1.597657 0.769531 h 0.003906 l 1.421875 1.269532 l 1.425781 -1.273438 l 0.007813 -0.007812 c 0.523437 -0.480469 1.21875 -0.738282 1.933594 -0.71875 c 1.300781 0.035156 2.15625 0.816406 2.515624 1.824218 c 0.355469 1.007813 0.191407 2.15625 -0.792968 3.003907 l -0.003906 0.007812 l -5.085938 4.527344 l -5.078125 -4.527344 h -0.003906 c -0.753907 -0.664062 -0.992188 -1.332031 -0.996094 -2 c 0 -0.667969 0.285156 -1.351562 0.761719 -1.890625 c 0.480468 -0.535156 1.128906 -0.898437 1.789062 -0.976562 c 0.167969 -0.015625 0.335938 -0.019532 0.503906 -0.007813 z m 0 0" fill="#222222"/></svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg
new file mode 100644
index 0000000..45e703e
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g transform="matrix(0 -1 -1 0 -413 -83.997)" color="#000" fill="#dedede"><rect y="-418" x="-92.997" width="2" style="marker:none" ry="1" rx="1" height="2" overflow="visible" enable-background="new"/><rect y="-422" x="-92.997" width="2" style="marker:none" ry="1" rx="1" height="2" overflow="visible" enable-background="new"/><rect y="-426" x="-92.997" width="2" style="marker:none" ry="1" rx="1" height="2" overflow="visible" enable-background="new"/></g></svg> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg
new file mode 100644
index 0000000..445f662
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg7"
+ sodipodi:docname="overview.svg"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview9"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="44.6875"
+ inkscape:cx="5.5944056"
+ inkscape:cy="8"
+ inkscape:window-width="1500"
+ inkscape:window-height="963"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g68"
+ inkscape:snap-bbox="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true" />
+ <defs
+ id="defs3">
+ <style
+ id="current-color-scheme"
+ type="text/css">.ColorScheme-Text { color:#363636; }</style>
+ </defs>
+ <path
+ d="M 2,1 C 0.892,1 0,1.892 0,3 v 9 c 0,1.108 0.892,2 2,2 h 12 c 1.108,0 2,-0.892 2,-2 V 3 C 16,1.892 15.108,1 14,1 Z m 0,1 h 12 c 0.554,0 1,0.446 1,1 H 1 C 1,2.446 1.446,2 2,2 Z M 1,3 h 14 v 9 c 0,0.554 -0.446,1 -1,1 H 2 C 1.446,13 1,12.554 1,12 Z"
+ style="fill:currentColor"
+ class="ColorScheme-Text"
+ id="path5"
+ sodipodi:nodetypes="sssssssssssccsccssssc" />
+ <g
+ id="g68"
+ transform="translate(0.3993007,0.15314685)">
+ <path
+ d="m 3.1756095,3.5602457 c -0.8440582,0 -1,0.446 -1,1 v 5.5732153 c 0,0.677136 0.446,1 1,1 H 12.02579 c 0.554,0 0.999999,-0.446 0.999999,-1 V 4.5602457 c 0,-0.554 -0.445999,-1 -0.999999,-1 z m 0,1 H 12.02579 V 10.133461 H 3.1756095 Z"
+ fill="#363636"
+ id="path8"
+ sodipodi:nodetypes="sssssssssccccc" />
+ </g>
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/pipelines-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/pipelines-symbolic.svg
new file mode 100644
index 0000000..d451b23
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/pipelines-symbolic.svg
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="16"
+ height="16"
+ enable-background="new"
+ version="1.1"
+ id="svg16"
+ sodipodi:docname="pipelines-symbolic.svg"
+ inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs20" />
+ <sodipodi:namedview
+ id="namedview18"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ showgrid="false"
+ inkscape:zoom="24.174578"
+ inkscape:cx="13.98163"
+ inkscape:cy="8.3765683"
+ inkscape:window-width="1500"
+ inkscape:window-height="963"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g14" />
+ <g
+ fill="#363636"
+ id="g14"
+ transform="rotate(90,7.75,8.25)">
+ <path
+ d="m 2.9500144,1 c -0.277,0 -0.5,0.223 -0.5,0.5 v 6.5547 a 2.5,2.5 0 0 1 0.5,-0.054688 2.5,2.5 0 0 1 0.5,0.050781 v -6.5508 c 0,-0.277 -0.223,-0.5 -0.5,-0.5 z m 0.5,11.945 a 2.5,2.5 0 0 1 -0.5,0.05469 2.5,2.5 0 0 1 -0.5,-0.05078 v 1.5508 c 0,0.277 0.223,0.5 0.5,0.5 0.277,0 0.5,-0.223 0.5,-0.5 v -1.5547 z"
+ id="path2" />
+ <path
+ d="M 7.5,1 C 7.223,1 7,1.223 7,1.5 V 3.0547 A 2.5,2.5 0 0 1 7.5,3.000012 2.5,2.5 0 0 1 8,3.050793 v -1.5508 c 0,-0.277 -0.223,-0.5 -0.5,-0.5 z M 8,7.9453 A 2.5,2.5 0 0 1 7.5,7.999988 2.5,2.5 0 0 1 7,7.949207 v 6.5508 c 0,0.277 0.223,0.5 0.5,0.5 0.277,0 0.5,-0.223 0.5,-0.5 v -6.5547 z"
+ id="path4" />
+ <path
+ d="m 12.049986,1.0001482 c -0.277,0 -0.5,0.223 -0.5,0.5 v 6.5547 a 2.5,2.5 0 0 1 0.5,-0.054688 2.5,2.5 0 0 1 0.5,0.050781 v -6.5508 c 0,-0.277 -0.223,-0.5 -0.5,-0.5 z m 0.5,11.9450008 a 2.5,2.5 0 0 1 -0.5,0.05469 2.5,2.5 0 0 1 -0.5,-0.05078 v 1.5508 c 0,0.276999 0.223,0.5 0.5,0.5 0.277,0 0.5,-0.223001 0.5,-0.5 v -1.5547 z"
+ id="path6" />
+ <circle
+ cx="2.9500144"
+ cy="10.5"
+ id="circle8"
+ r="1.5" />
+ <circle
+ cx="7.5"
+ cy="5.5"
+ r="1.5"
+ id="circle10" />
+ <circle
+ cx="12.049986"
+ cy="10.500149"
+ id="circle12"
+ r="1.5" />
+ </g>
+</svg> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-row-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-row-symbolic.svg
new file mode 100644
index 0000000..a8da14f
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-row-symbolic.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="m4.4647 3.9648c-0.12775 0-0.2555 0.048567-0.35339 0.14649-0.19578 0.19586-0.19578 0.51116 0 0.70703l3.1816 3.1816-3.1816 3.1816c-0.19578 0.19586-0.19578 0.51116 0 0.70703 0.19578 0.19586 0.51118 0.19586 0.70704 0l3.1816-3.1816 3.1816 3.1816c0.19578 0.19586 0.51114 0.19586 0.70704 0 0.19578-0.19586 0.19578-0.51116 0-0.70703l-3.1816-3.1816 3.1816-3.1816c0.19578-0.19586 0.19578-0.51116 0-0.70703-0.19578-0.19586-0.51118-0.19586-0.70704 0l-3.1816 3.1816-3.1816-3.1816c-0.09789-0.097928-0.22564-0.14649-0.35339-0.14649z" fill="#363636" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.9149" style="paint-order:stroke fill markers"/>
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg
new file mode 100644
index 0000000..e443de4
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg
@@ -0,0 +1,7 @@
+<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#363636">
+ <path d="m8 3a6 6 0 0 0-6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6h-1a5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5z"/>
+ <path d="m8.1719 0.67188-0.70703 0.70703 2.1211 2.1211-2.1211 2.1211 0.70703 0.70703 2.8281-2.8281-0.70703-0.70703z"/>
+ <rect x="8" y="3" width="2" height="1"/>
+ </g>
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-row-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-row-symbolic.svg
new file mode 100644
index 0000000..e6d2d9e
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-row-symbolic.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="16px" viewBox="0 0 16 16" width="16px"><filter id="a" height="100%" width="100%" x="0%" y="0%"><feColorMatrix color-interpolation-filters="sRGB" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><mask id="b"><g filter="url(#a)"><path d="m -1.6 -1.6 h 19.2 v 19.2 h -19.2 z" fill-opacity="0.5"/></g></mask><clipPath id="c"><path d="m 0 0 h 1600 v 1200 h -1600 z"/></clipPath><mask id="d"><g filter="url(#a)"><path d="m -1.6 -1.6 h 19.2 v 19.2 h -19.2 z" fill-opacity="0.7"/></g></mask><clipPath id="e"><path d="m 0 0 h 1600 v 1200 h -1600 z"/></clipPath><mask id="f"><g filter="url(#a)"><path d="m -1.6 -1.6 h 19.2 v 19.2 h -19.2 z" fill-opacity="0.35"/></g></mask><clipPath id="g"><path d="m 0 0 h 1600 v 1200 h -1600 z"/></clipPath><g mask="url(#b)"><g clip-path="url(#c)" transform="matrix(1 0 0 1 -860 -60)"><path d="m 550 182 c -0.351562 0.003906 -0.695312 0.101562 -1 0.28125 v 3.4375 c 0.304688 0.179688 0.648438 0.277344 1 0.28125 c 1.105469 0 2 -0.894531 2 -2 s -0.894531 -2 -2 -2 z m 0 5 c -0.339844 0 -0.679688 0.058594 -1 0.175781 v 6.824219 h 4 v -4 c 0 -1.65625 -1.34375 -3 -3 -3 z m 0 0"/></g></g><g mask="url(#d)"><g clip-path="url(#e)" transform="matrix(1 0 0 1 -860 -60)"><path d="m 569 182 v 4 c 1.105469 0 2 -0.894531 2 -2 s -0.894531 -2 -2 -2 z m 0 5 v 7 h 3 v -4 c 0 -1.65625 -1.34375 -3 -3 -3 z m 0 0"/></g></g><g mask="url(#f)"><g clip-path="url(#g)" transform="matrix(1 0 0 1 -860 -60)"><path d="m 573 182.269531 v 3.449219 c 0.613281 -0.355469 0.996094 -1.007812 1 -1.71875 c 0 -0.714844 -0.382812 -1.375 -1 -1.730469 z m 0 4.90625 v 6.824219 h 2 v -4 c 0 -1.269531 -0.800781 -2.402344 -2 -2.824219 z m 0 0"/></g></g><path d="m 7.292969 1.707031 l 7 7 v -1.414062 l -7 7 c -0.390625 0.390625 -0.390625 1.023437 0 1.414062 s 1.023437 0.390625 1.414062 0 l 7 -7 c 0.390625 -0.390625 0.390625 -1.023437 0 -1.414062 l -7 -7 c -0.390625 -0.3906252 -1.023437 -0.3906252 -1.414062 0 c -0.390625 0.390625 -0.390625 1.023437 0 1.414062 z m 0 0"/><path d="m 15 7 h -14 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 h 14 c 0.550781 0 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 0 0"/></svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg
new file mode 100644
index 0000000..cad2da8
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 2.953125 1.074219 l 2.417969 13.210937 l 3.238281 -2.398437 l 2.054687 2.648437 c 1.03125 1.433594 3.148438 -0.210937 2.011719 -1.5625 l -2.015625 -2.59375 l 2.984375 -2.175781 z m 0 0" fill="#222222"/></svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/static-mode-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/static-mode-symbolic.svg
new file mode 100644
index 0000000..5b0eb20
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/static-mode-symbolic.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="16px"
+ height="16px"
+ viewBox="0 0 16 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="static-mode-symbolic.svg"
+ inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs5" />
+ <sodipodi:namedview
+ id="namedview5"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:zoom="44.75"
+ inkscape:cx="8"
+ inkscape:cy="8"
+ inkscape:window-width="1500"
+ inkscape:window-height="963"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg5"
+ showguides="true" />
+ <path
+ d="m 11.5,11.34375 a 5.75,5.75 0 0 1 -1,0.134766 v 2.234375 C 10.5,14.425813 9.9258135,15 9.2128906,15 H 2.2871094 C 1.5741865,15 1,14.425813 1,13.712891 V 6.7871094 C 1,6.0741865 1.5741865,5.5 2.2871094,5.5 h 2.234375 A 5.75,5.75 0 0 1 4.65625,4.5 H 1.5585937 C 0.69558189,4.5 0,5.1955819 0,6.0585937 V 14.441406 C 0,15.304418 0.69558189,16 1.5585937,16 H 9.9414063 C 10.804418,16 11.5,15.304418 11.5,14.441406 Z"
+ style="opacity:1;fill:#dedede;stroke-linejoin:round"
+ id="path14" />
+ <path
+ d="M 10.5,11.478516 A 5.75,5.75 0 0 1 10.25,11.5 5.75,5.75 0 0 1 4.5,5.75 5.75,5.75 0 0 1 4.5214844,5.5 H 2.2871094 C 1.5741865,5.5 1,6.0741865 1,6.7871094 V 13.712891 C 1,14.425813 1.5741865,15 2.2871094,15 H 9.2128906 C 9.9258135,15 10.5,14.425813 10.5,13.712891 Z"
+ style="opacity:0.25;fill:#dedede;stroke-width:0.826087;stroke-linejoin:round"
+ id="path15" />
+ <path
+ d="m 11.5,11.34375 v -1.029297 a 4.75,4.75 0 0 1 -1,0.164063 v 1 a 5.75,5.75 0 0 0 1,-0.134766 z"
+ style="opacity:1;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.25351;stroke-linejoin:round;-inkscape-stroke:hairline"
+ id="path22" />
+ <path
+ d="M 10.25,0 A 5.75,5.75 0 0 0 4.65625,4.5 H 5.6855469 A 4.75,4.75 0 0 1 10.25,1 4.75,4.75 0 0 1 15,5.75 4.75,4.75 0 0 1 11.5,10.314453 V 11.34375 A 5.75,5.75 0 0 0 16,5.75 5.75,5.75 0 0 0 10.25,0 Z"
+ style="opacity:1;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.25351;stroke-linejoin:round;-inkscape-stroke:hairline"
+ id="path18" />
+ <path
+ d="m 4.5214844,5.5 h 1 a 4.75,4.75 0 0 1 0.1640625,-1 H 4.65625 a 5.75,5.75 0 0 0 -0.1347656,1 z"
+ style="opacity:1;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.25351;stroke-linejoin:round;-inkscape-stroke:hairline"
+ id="path17" />
+ <path
+ d="m 10.5,11.478516 v -1 A 4.75,4.75 0 0 1 10.25,10.5 4.75,4.75 0 0 1 5.5,5.75 4.75,4.75 0 0 1 5.5214844,5.5 h -1 A 5.75,5.75 0 0 0 4.5,5.75 a 5.75,5.75 0 0 0 5.75,5.75 5.75,5.75 0 0 0 0.25,-0.02148 z"
+ style="opacity:1;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.25351;stroke-linejoin:round;-inkscape-stroke:hairline"
+ id="path16" />
+ <path
+ d="M 10.5,10.478516 V 6.7871094 C 10.5,6.0741865 9.9258135,5.5 9.2128906,5.5 H 5.5214844 A 4.75,4.75 0 0 0 5.5,5.75 a 4.75,4.75 0 0 0 4.75,4.75 4.75,4.75 0 0 0 0.25,-0.02148 z"
+ style="opacity:0;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.03551;stroke-linejoin:round;-inkscape-stroke:hairline;fill-opacity:1"
+ id="path21" />
+ <path
+ d="m 5.6855469,4.5 a 4.75,4.75 0 0 0 -0.1640625,1 H 9.2128906 C 9.9258135,5.5 10.5,6.0741865 10.5,6.7871094 v 3.6914066 a 4.75,4.75 0 0 0 1,-0.164063 V 6.0585937 C 11.5,5.1955819 10.804418,4.5 9.9414063,4.5 Z"
+ style="opacity:0;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.03551;stroke-linejoin:round;-inkscape-stroke:hairline;fill-opacity:1"
+ id="path20" />
+ <path
+ d="M 5.6855469,4.5 H 9.9414063 C 10.804418,4.5 11.5,5.1955819 11.5,6.0585937 V 10.314453 A 4.75,4.75 0 0 0 15,5.75 4.75,4.75 0 0 0 10.25,1 4.75,4.75 0 0 0 5.6855469,4.5 Z"
+ style="opacity:0;vector-effect:non-scaling-stroke;fill:#dedede;stroke-width:1.03551;stroke-linejoin:round;-inkscape-stroke:hairline;fill-opacity:1"
+ id="path19" />
+</svg>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..7fd4c31
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..aac168e
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..2d37384
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..6229b38
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..9d8da30
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..f804035
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..8f46756
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/da/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/da/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..b44f3c8
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/da/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..923e3e6
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..c671ffa
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..352d3bc
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/et/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/et/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..a92f357
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/et/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fi/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fi/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..4e50603
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fi/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..a3a72a3
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..c00a0b0
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..d3801bb
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hr/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hr/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..45ed92c
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hr/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..40e34c4
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..034f55a
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..a6fc86a
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..12d1d52
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ka/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ka/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..f38aa09
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ka/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..9088bf3
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ml/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ml/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..a03d776
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ml/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/mrh/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/mrh/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..52a61c4
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/mrh/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/my/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/my/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..0d81fb0
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/my/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..50cdf68
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..a1a3517
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..28f7c42
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..47fc350
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..10d3aa1
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..3dcad8d
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..dd7822e
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..f7ba1de
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sk/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sk/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..be8e9a4
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sk/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..34b6505
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..c7bc46f
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..8fc6e3d
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/th/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/th/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..e04e4a5
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/th/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..04fce82
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..9957d99
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..385f8fa
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_CN/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_CN/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..7b84952
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_CN/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mo
new file mode 100644
index 0000000..20e60f5
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mo
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/metadata.json b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/metadata.json
new file mode 100644
index 0000000..cce8059
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/metadata.json
@@ -0,0 +1,28 @@
+{
+ "_generated": "Generated by SweetTooth, do not edit",
+ "description": "Adds a blur look to different parts of the GNOME Shell, including the top panel, dash and overview.\n\nYou can support my work by sponsoring me on:\n- github: https://github.com/sponsors/aunetx\n- ko-fi: https://ko-fi.com/aunetx\n\nIf you use Ubuntu, you may want to change the radius of the corner effect for Dash-to-Dock in preferences, else you may see unpleasantly mixed radii in your dock.\n\nNote: if the extension shows an error after updating, please make sure to restart your session to see if it persists. This is due to a bug in gnome shell, which I can't fix by myself.",
+ "donations": {
+ "github": "aunetx",
+ "kofi": "aunetx"
+ },
+ "gettext-domain": "blur-my-shell@aunetx",
+ "name": "Blur my Shell",
+ "original-authors": [
+ "me@aunetx.dev"
+ ],
+ "session-modes": [
+ "unlock-dialog",
+ "user"
+ ],
+ "settings-schema": "org.gnome.shell.extensions.blur-my-shell",
+ "shell-version": [
+ "46",
+ "47",
+ "48",
+ "49",
+ "50"
+ ],
+ "url": "https://github.com/aunetx/blur-my-shell",
+ "uuid": "blur-my-shell@aunetx",
+ "version": 71
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/applications.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/applications.js
new file mode 100644
index 0000000..a4dd5be
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/applications.js
@@ -0,0 +1,217 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gio from 'gi://Gio';
+
+import { ApplicationRow } from './applications_management/application_row.js';
+
+
+const make_array = prefs_group => {
+ let list_box = prefs_group
+ .get_first_child()
+ .get_last_child()
+ .get_first_child();
+
+ let elements = [];
+ let i = 0;
+ let element = list_box.get_row_at_index(i);
+ while (element) {
+ elements.push(element);
+ i++;
+ element = list_box.get_row_at_index(i);
+ }
+
+ return elements;
+};
+
+
+export const Applications = GObject.registerClass({
+ GTypeName: 'Applications',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../ui/applications.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ 'blur',
+ 'pipeline_choose_row',
+ 'mode_static',
+ 'mode_dynamic',
+ 'sigma_row',
+ 'sigma',
+ 'brightness_row',
+ 'brightness',
+ 'opacity',
+ 'dynamic_opacity',
+ 'blur_on_overview',
+ 'enable_all',
+ 'whitelist',
+ 'add_window_whitelist',
+ 'blacklist',
+ 'add_window_blacklist'
+ ],
+}, class Applications extends Adw.PreferencesPage {
+ constructor(preferences, preferences_window, pipelines_manager, pipelines_page) {
+ super({});
+ this._preferences_window = preferences_window;
+
+ this.preferences = preferences;
+ this.pipelines_manager = pipelines_manager;
+ this.pipelines_page = pipelines_page;
+
+ this.preferences.applications.settings.bind(
+ 'blur', this._blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ this._pipeline_choose_row.initialize(
+ this.preferences.applications, this.pipelines_manager, this.pipelines_page
+ );
+
+ this.change_blur_mode(this.preferences.applications.STATIC_BLUR, true);
+
+ this._mode_static.connect('toggled',
+ () => this.preferences.applications.STATIC_BLUR = this._mode_static.active
+ );
+ this.preferences.applications.STATIC_BLUR_changed(
+ () => this.change_blur_mode(this.preferences.applications.STATIC_BLUR, false)
+ );
+
+ this.preferences.applications.settings.bind(
+ 'opacity', this._opacity, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.applications.settings.bind(
+ 'dynamic-opacity', this._dynamic_opacity, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.applications.settings.bind(
+ 'blur-on-overview', this._blur_on_overview, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.applications.settings.bind(
+ 'enable-all', this._enable_all, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.applications.settings.bind(
+ 'sigma', this._sigma, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.applications.settings.bind(
+ 'brightness', this._brightness, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ // connect 'enable all' button to whitelist/blacklist visibility
+ this._enable_all.bind_property(
+ 'active', this._whitelist, 'visible',
+ GObject.BindingFlags.INVERT_BOOLEAN
+ );
+ this._enable_all.bind_property(
+ 'active', this._blacklist, 'visible',
+ GObject.BindingFlags.DEFAULT
+ );
+
+ // make sure that blacklist / whitelist is correctly hidden
+ if (this._enable_all.active)
+ this._whitelist.visible = false;
+ this._blacklist.visible = !this._whitelist.visible;
+
+ // listen to app row addition
+ this._add_window_whitelist.connect('clicked',
+ () => this.add_to_whitelist()
+ );
+ this._add_window_blacklist.connect('clicked',
+ () => this.add_to_blacklist()
+ );
+
+ // add initial applications
+ this.add_widgets_from_lists();
+
+ this.preferences.connect('reset', () => {
+ this.remove_all_widgets();
+ this.add_widgets_from_lists();
+ });
+ }
+
+ // A way to retriew the whitelist widgets.
+ get _whitelist_elements() {
+ return make_array(this._whitelist);
+ }
+
+ // A way to retriew the blacklist widgets.
+ get _blacklist_elements() {
+ return make_array(this._blacklist);
+ }
+
+ add_widgets_from_lists() {
+ this.preferences.applications.WHITELIST.forEach(
+ app_name => this.add_to_whitelist(app_name)
+ );
+
+ this.preferences.applications.BLACKLIST.forEach(
+ app_name => this.add_to_blacklist(app_name)
+ );
+
+ }
+
+ close_all_expanded_rows() {
+ this._whitelist_elements.forEach(
+ element => element.set_expanded(false)
+ );
+ this._blacklist_elements.forEach(
+ element => element.set_expanded(false)
+ );
+ }
+
+ remove_all_widgets() {
+ this._whitelist_elements.forEach(
+ element => this._whitelist.remove(element)
+ );
+ this._blacklist_elements.forEach(
+ element => this._blacklist.remove(element)
+ );
+ }
+
+ add_to_whitelist(app_name = null) {
+ let window_row = new ApplicationRow('whitelist', this, app_name);
+ this._whitelist.add(window_row);
+ }
+
+ add_to_blacklist(app_name = null) {
+ let window_row = new ApplicationRow('blacklist', this, app_name);
+ this._blacklist.add(window_row);
+ }
+
+ update_whitelist_titles() {
+ let titles = this._whitelist_elements
+ .map(element => element._window_class.buffer.text)
+ .filter(title => title != "");
+
+ this.preferences.applications.WHITELIST = titles;
+ }
+
+ update_blacklist_titles() {
+ let titles = this._blacklist_elements
+ .map(element => element._window_class.buffer.text)
+ .filter(title => title != "");
+
+ this.preferences.applications.BLACKLIST = titles;
+ }
+
+ remove_from_whitelist(widget) {
+ this._whitelist.remove(widget);
+ this.update_whitelist_titles();
+ }
+
+ remove_from_blacklist(widget) {
+ this._blacklist.remove(widget);
+ this.update_blacklist_titles();
+ }
+
+ change_blur_mode(is_static_blur, first_run) {
+ this._mode_static.set_active(is_static_blur);
+ if (first_run)
+ this._mode_dynamic.set_active(!is_static_blur);
+
+ this._pipeline_choose_row.set_visible(is_static_blur);
+ this._sigma_row.set_visible(!is_static_blur);
+ this._brightness_row.set_visible(!is_static_blur);
+ }
+}); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/applications_management/application_row.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/applications_management/application_row.js
new file mode 100644
index 0000000..4af3bf8
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/applications_management/application_row.js
@@ -0,0 +1,112 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gio from 'gi://Gio';
+import Gtk from 'gi://Gtk';
+
+import { pick, on_picking, on_picked } from '../../dbus/client.js';
+
+
+export const ApplicationRow = GObject.registerClass({
+ GTypeName: 'ApplicationRow',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/application-row.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ 'window_picker',
+ 'window_class',
+ 'picking_failure_toast',
+ 'window_not_found_toast'
+ ],
+}, class ApplicationRow extends Adw.ExpanderRow {
+ constructor(list, app_page, app_name) {
+ super({});
+ this._list = list;
+ this._app_page = app_page;
+
+ // add a 'remove' button before the text
+ let action_row = this.child.get_first_child().get_first_child();
+ let remove_button = new Gtk.Button({
+ 'icon-name': 'remove-row-symbolic',
+ 'width-request': 38,
+ 'height-request': 38,
+ 'margin-top': 6,
+ 'margin-bottom': 6,
+ });
+ remove_button.add_css_class('circular');
+ remove_button.add_css_class('flat');
+ action_row.add_prefix(remove_button);
+
+ // connect the button to the whitelist / blacklist removal
+ remove_button.connect('clicked', () => this._remove_row());
+
+ // bind row title to text buffer
+ this._window_class.buffer.bind_property(
+ 'text', this, 'title',
+ Gio.SettingsBindFlags.BIDIRECTIONNAL
+ );
+
+ // set application name if it exists, or open the revealer and pick one
+ if (app_name)
+ this._window_class.buffer.text = app_name;
+ else {
+ app_page.close_all_expanded_rows();
+ this.set_expanded(true);
+ this._do_pick_window(true);
+ }
+
+ // pick a window when the picker button is clicked
+ this._window_picker.connect('clicked', () => this._do_pick_window());
+
+ // update list on text buffer change
+ this._window_class.connect('changed',
+ () => this._update_rows_titles()
+ );
+ }
+
+ _remove_row() {
+ this._app_page["remove_from_" + this._list](this);
+ }
+
+ _update_rows_titles() {
+ this._app_page["update_" + this._list + "_titles"](this);
+ }
+
+ _do_pick_window(remove_if_failed = false) {
+ // a mechanism to know if the extension is listening correcly
+ let has_responded = false;
+ let should_take_answer = true;
+ setTimeout(() => {
+ if (!has_responded) {
+ // show toast about failure
+ this._app_page._preferences_window.add_toast(
+ this._picking_failure_toast
+ );
+
+ // prevent title from changing with later picks
+ should_take_answer = false;
+
+ // remove row if asked
+ if (remove_if_failed)
+ this._remove_row();
+ }
+ }, 250);
+
+ on_picking(() =>
+ has_responded = true
+ );
+
+ on_picked(wm_class => {
+ if (should_take_answer) {
+ if (wm_class == 'window-not-found') {
+ console.warn("Can't pick window from here");
+ this._app_page._preferences_window.add_toast(
+ this._window_not_found_toast
+ );
+ return;
+ }
+ this._window_class.buffer.text = wm_class;
+ }
+ });
+
+ pick();
+ }
+});
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/dash.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/dash.js
new file mode 100644
index 0000000..aae3768
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/dash.js
@@ -0,0 +1,81 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gio from 'gi://Gio';
+
+
+export const Dash = GObject.registerClass({
+ GTypeName: 'Dash',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../ui/dash.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ 'blur',
+ 'pipeline_choose_row',
+ 'mode_static',
+ 'mode_dynamic',
+ 'sigma_row',
+ 'sigma',
+ 'brightness_row',
+ 'brightness',
+ 'override_background',
+ 'style_dash_to_dock',
+ 'unblur_in_overview'
+ ],
+}, class Dash extends Adw.PreferencesPage {
+ constructor(preferences, pipelines_manager, pipelines_page) {
+ super({});
+
+ this.preferences = preferences;
+ this.pipelines_manager = pipelines_manager;
+ this.pipelines_page = pipelines_page;
+
+ this.preferences.dash_to_dock.settings.bind(
+ 'blur', this._blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ this._pipeline_choose_row.initialize(
+ this.preferences.dash_to_dock, this.pipelines_manager, this.pipelines_page
+ );
+
+ this.change_blur_mode(this.preferences.dash_to_dock.STATIC_BLUR, true);
+
+ this._mode_static.connect('toggled',
+ () => this.preferences.dash_to_dock.STATIC_BLUR = this._mode_static.active
+ );
+ this.preferences.dash_to_dock.STATIC_BLUR_changed(
+ () => this.change_blur_mode(this.preferences.dash_to_dock.STATIC_BLUR, false)
+ );
+
+ this.preferences.dash_to_dock.settings.bind(
+ 'sigma', this._sigma, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.dash_to_dock.settings.bind(
+ 'brightness', this._brightness, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.dash_to_dock.settings.bind(
+ 'override-background',
+ this._override_background, 'enable-expansion',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.dash_to_dock.settings.bind(
+ 'style-dash-to-dock', this._style_dash_to_dock, 'selected',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.dash_to_dock.settings.bind(
+ 'unblur-in-overview', this._unblur_in_overview, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ }
+
+ change_blur_mode(is_static_blur, first_run) {
+ this._mode_static.set_active(is_static_blur);
+ if (first_run)
+ this._mode_dynamic.set_active(!is_static_blur);
+
+ this._pipeline_choose_row.set_visible(is_static_blur);
+ this._sigma_row.set_visible(!is_static_blur);
+ this._brightness_row.set_visible(!is_static_blur);
+ }
+}); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/menu.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/menu.js
new file mode 100644
index 0000000..899fdcf
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/menu.js
@@ -0,0 +1,68 @@
+import Gdk from 'gi://Gdk';
+import Gtk from 'gi://Gtk';
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+
+
+export function addMenu(window) {
+ const builder = new Gtk.Builder();
+
+ // add a dummy page and remove it immediately, to access headerbar
+ builder.add_from_file(GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, '../ui/menu.ui', GLib.UriFlags.NONE))[0]);
+ let menu_util = builder.get_object('menu_util');
+ window.add(menu_util);
+ try {
+ addMenuToHeader(window, builder);
+ } catch (error) {
+ // could not add menu... not so bad
+ }
+ window.remove(menu_util);
+}
+
+function addMenuToHeader(window, builder) {
+ // a little hack to get to the headerbar
+ const page = builder.get_object('menu_util');
+ const pages_stack = page.get_parent(); // AdwViewStack
+ const content_stack = pages_stack.get_parent().get_parent(); // GtkStack
+ const preferences = content_stack.get_parent(); // GtkBox
+ const headerbar = preferences.get_first_child().get_next_sibling()
+ .get_first_child().get_first_child().get_first_child(); // AdwHeaderBar
+ headerbar.pack_start(builder.get_object('info_menu'));
+
+ // setup menu actions
+ const actionGroup = new Gio.SimpleActionGroup();
+ window.insert_action_group('prefs', actionGroup);
+
+ // a list of actions with their associated link
+ const actions = [
+ {
+ name: 'open-bug-report',
+ link: 'https://github.com/aunetx/blur-my-shell/issues'
+ },
+ {
+ name: 'open-readme',
+ link: 'https://github.com/aunetx/blur-my-shell'
+ },
+ {
+ name: 'open-license',
+ link: 'https://github.com/aunetx/blur-my-shell/blob/master/LICENSE'
+ },
+ {
+ name: 'donate-github',
+ link: 'https://github.com/sponsors/aunetx'
+ },
+ {
+ name: 'donate-kofi',
+ link: 'https://ko-fi.com/aunetx'
+ },
+ ];
+
+ actions.forEach(action => {
+ let act = new Gio.SimpleAction({ name: action.name });
+ act.connect(
+ 'activate',
+ () => Gtk.show_uri(window, action.link, Gdk.CURRENT_TIME)
+ );
+ actionGroup.add_action(act);
+ });
+}
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/other.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/other.js
new file mode 100644
index 0000000..0fac364
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/other.js
@@ -0,0 +1,86 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gio from 'gi://Gio';
+
+
+export const Other = GObject.registerClass({
+ GTypeName: 'Other',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../ui/other.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ 'lockscreen_blur',
+ 'lockscreen_pipeline_choose_row',
+
+ 'screenshot_blur',
+ 'screenshot_pipeline_choose_row',
+
+ 'window_list_blur',
+ 'window_list_sigma',
+ 'window_list_brightness',
+
+ 'coverflow_alt_tab_blur',
+ 'coverflow_alt_tab_pipeline_choose_row',
+
+ 'hack_level',
+ 'debug',
+ 'reset'
+ ],
+}, class Overview extends Adw.PreferencesPage {
+ constructor(preferences, pipelines_manager, pipelines_page) {
+ super({});
+
+ this.preferences = preferences;
+ this.pipelines_manager = pipelines_manager;
+ this.pipelines_page = pipelines_page;
+
+ this.preferences.lockscreen.settings.bind(
+ 'blur', this._lockscreen_blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ this._lockscreen_pipeline_choose_row.initialize(
+ this.preferences.lockscreen, this.pipelines_manager, this.pipelines_page
+ );
+
+ this.preferences.screenshot.settings.bind(
+ 'blur', this._screenshot_blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ this._screenshot_pipeline_choose_row.initialize(
+ this.preferences.screenshot, this.pipelines_manager, this.pipelines_page
+ );
+
+ this.preferences.window_list.settings.bind(
+ 'blur', this._window_list_blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.window_list.settings.bind(
+ 'sigma', this._window_list_sigma, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.window_list.settings.bind(
+ 'brightness', this._window_list_brightness, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ this.preferences.coverflow_alt_tab.settings.bind(
+ 'blur', this._coverflow_alt_tab_blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this._coverflow_alt_tab_pipeline_choose_row.initialize(
+ this.preferences.coverflow_alt_tab, this.pipelines_manager, this.pipelines_page
+ );
+
+ this.preferences.settings.bind(
+ 'hacks-level', this._hack_level, 'selected',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.settings.bind(
+ 'debug', this._debug, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ this._reset.connect('clicked', () => this.preferences.reset());
+ }
+}); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/overview.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/overview.js
new file mode 100644
index 0000000..f6fe592
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/overview.js
@@ -0,0 +1,59 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gio from 'gi://Gio';
+
+
+export const Overview = GObject.registerClass({
+ GTypeName: 'Overview',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../ui/overview.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ 'overview_blur',
+ 'pipeline_choose_row',
+ 'overview_style_components',
+
+ 'appfolder_blur',
+ 'appfolder_sigma',
+ 'appfolder_brightness',
+ 'appfolder_style_dialogs'
+ ],
+}, class Overview extends Adw.PreferencesPage {
+ constructor(preferences, pipelines_manager, pipelines_page) {
+ super({});
+
+ this.preferences = preferences;
+ this.pipelines_manager = pipelines_manager;
+ this.pipelines_page = pipelines_page;
+
+ this.preferences.overview.settings.bind(
+ 'blur', this._overview_blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ this._pipeline_choose_row.initialize(
+ this.preferences.overview, this.pipelines_manager, this.pipelines_page
+ );
+
+ this.preferences.overview.settings.bind(
+ 'style-components', this._overview_style_components, 'selected',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ this.preferences.appfolder.settings.bind(
+ 'blur', this._appfolder_blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.appfolder.settings.bind(
+ 'sigma', this._appfolder_sigma, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.appfolder.settings.bind(
+ 'brightness', this._appfolder_brightness, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.appfolder.settings.bind(
+ 'style-dialogs', this._appfolder_style_dialogs, 'selected',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ }
+}); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/panel.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/panel.js
new file mode 100644
index 0000000..c49f323
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/panel.js
@@ -0,0 +1,102 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gio from 'gi://Gio';
+
+
+export const Panel = GObject.registerClass({
+ GTypeName: 'Panel',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../ui/panel.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ 'blur',
+ 'pipeline_choose_row',
+ 'mode_static',
+ 'mode_dynamic',
+ 'sigma_row',
+ 'sigma',
+ 'brightness_row',
+ 'brightness',
+ 'unblur_in_overview',
+ 'force_light_text',
+ 'override_background',
+ 'style_panel',
+ 'override_background_dynamically',
+ 'hidetopbar_compatibility',
+ 'dtp_blur_original_panel'
+ ],
+}, class Panel extends Adw.PreferencesPage {
+ constructor(preferences, pipelines_manager, pipelines_page) {
+ super({});
+
+ this.preferences = preferences;
+ this.pipelines_manager = pipelines_manager;
+ this.pipelines_page = pipelines_page;
+
+ this.preferences.panel.settings.bind(
+ 'blur', this._blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+
+ this._pipeline_choose_row.initialize(
+ this.preferences.panel, this.pipelines_manager, this.pipelines_page
+ );
+
+ this.change_blur_mode(this.preferences.panel.STATIC_BLUR, true);
+
+ this._mode_static.connect('toggled',
+ () => this.preferences.panel.STATIC_BLUR = this._mode_static.active
+ );
+ this.preferences.panel.STATIC_BLUR_changed(
+ () => this.change_blur_mode(this.preferences.panel.STATIC_BLUR, false)
+ );
+
+ this.preferences.panel.settings.bind(
+ 'sigma', this._sigma, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.panel.settings.bind(
+ 'brightness', this._brightness, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.panel.settings.bind(
+ 'unblur-in-overview', this._unblur_in_overview, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.panel.settings.bind(
+ 'force-light-text', this._force_light_text, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.panel.settings.bind(
+ 'override-background',
+ this._override_background, 'enable-expansion',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.panel.settings.bind(
+ 'style-panel', this._style_panel, 'selected',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.panel.settings.bind(
+ 'override-background-dynamically',
+ this._override_background_dynamically, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.hidetopbar.settings.bind(
+ 'compatibility', this._hidetopbar_compatibility, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.dash_to_panel.settings.bind(
+ 'blur-original-panel', this._dtp_blur_original_panel, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ }
+
+ change_blur_mode(is_static_blur, first_run) {
+ this._mode_static.set_active(is_static_blur);
+ if (first_run)
+ this._mode_dynamic.set_active(!is_static_blur);
+
+ this._pipeline_choose_row.set_visible(is_static_blur);
+ this._sigma_row.set_visible(!is_static_blur);
+ this._brightness_row.set_visible(!is_static_blur);
+ }
+}); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines.js
new file mode 100644
index 0000000..158ea9a
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines.js
@@ -0,0 +1,98 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
+
+import { PipelineGroup } from './pipelines_management/pipeline_group.js';
+import { EffectsDialog } from './pipelines_management/effects_dialog.js';
+
+
+export const Pipelines = GObject.registerClass({
+ GTypeName: 'Pipelines',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../ui/pipelines.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ 'add_pipeline'
+ ],
+}, class Pipelines extends Adw.PreferencesPage {
+ constructor(preferences, pipelines_manager, window) {
+ super({});
+
+ this.preferences = preferences;
+ this.pipelines_manager = pipelines_manager;
+ this.window = window;
+
+ this.pipelines_map = new Map;
+
+ for (let pipeline_id in this.pipelines_manager.pipelines)
+ this.add_pipeline(pipeline_id, false);
+
+ this.preferences.connect('reset', _ => {
+ this.pipelines_map.forEach((_infos, pid) => this.remove_pipeline(pid));
+ for (let pipeline_id in this.pipelines_manager.pipelines)
+ this.add_pipeline(pipeline_id, false);
+ });
+
+ this._add_pipeline.connect(
+ "clicked",
+ () => this.pipelines_manager.create_pipeline(_("New pipeline"))
+ );
+
+ this.pipelines_manager.connect(
+ "pipeline-created",
+ (_obj, id, _pipeline) => this.add_pipeline(id, true)
+ );
+ }
+
+ add_pipeline(pipeline_id, scroll_to_bottom) {
+ let pipeline = this.pipelines_manager.pipelines[pipeline_id];
+ let pipeline_group = new PipelineGroup(
+ this.pipelines_manager, pipeline_id, pipeline, this
+ );
+
+ let pipeline_destroyed_id = this.pipelines_manager.connect(
+ pipeline_id + "::pipeline-destroyed",
+ () => this.remove_pipeline(pipeline_id)
+ );
+
+ let pipeline_renamed_id = this.pipelines_manager.connect(
+ pipeline_id + "::pipeline-renamed",
+ (_obj, name) => this.rename_pipeline(pipeline_id, name)
+ );
+
+ this.pipelines_map.set(pipeline_id, {
+ pipeline_group, pipeline_destroyed_id, pipeline_renamed_id
+ });
+
+ this.add(pipeline_group);
+
+ // scroll to the bottom of the page
+ if (scroll_to_bottom) {
+ this.window.set_visible_page(this);
+ setTimeout(() => {
+ const scroll_adjustment = this.get_first_child().get_vadjustment();
+ scroll_adjustment.value = scroll_adjustment.get_upper();
+ }, 10);
+ pipeline_group._title.grab_focus();
+ }
+ }
+
+ remove_pipeline(pipeline_id) {
+ let pipeline_infos = this.pipelines_map.get(pipeline_id);
+ if (pipeline_infos) {
+ this.pipelines_manager.disconnect(pipeline_infos.pipeline_destroyed_id);
+ this.remove(pipeline_infos.pipeline_group);
+ this.pipelines_map.delete(pipeline_id);
+ }
+ }
+
+ rename_pipeline(pipeline_id, name) {
+ let pipeline_infos = this.pipelines_map.get(pipeline_id);
+ if (pipeline_infos)
+ pipeline_infos.pipeline_group.set_title(name.length > 0 ? name : " ");
+ }
+
+ open_effects_dialog(pipeline_id) {
+ let dialog = new EffectsDialog(this.pipelines_manager, pipeline_id);
+ dialog.present(this.window);
+ }
+}); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/effect_row.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/effect_row.js
new file mode 100644
index 0000000..130edfd
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/effect_row.js
@@ -0,0 +1,222 @@
+import Adw from 'gi://Adw';
+import GObject from 'gi://GObject';
+import Gtk from 'gi://Gtk';
+import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
+
+import { get_supported_effects } from '../../effects/effects.js';
+
+
+export const EffectRow = GObject.registerClass({
+ GTypeName: 'EffectRow',
+ InternalChildren: [],
+}, class EffectRow extends Adw.ExpanderRow {
+ constructor(effect, effects_dialog) {
+ super({});
+
+ this.SUPPORTED_EFFECTS = get_supported_effects(_);
+
+ this.effect = effect;
+ this.effects_dialog = effects_dialog;
+ this.pipeline_id = effects_dialog.pipeline_id;
+ this.pipelines_manager = effects_dialog.pipelines_manager;
+
+ if (effect.type in this.SUPPORTED_EFFECTS) {
+ this.set_title(this.SUPPORTED_EFFECTS[effect.type].name);
+ this.set_subtitle(this.SUPPORTED_EFFECTS[effect.type].description);
+ this.populate_options();
+ }
+ else {
+ this._warn(`could not assign effect ${effect.type} to its correct name`);
+ this.set_title(effect.type);
+ }
+
+ let prefix_bin = new Gtk.Box({
+ spacing: 6
+ });
+ this.add_prefix(prefix_bin);
+
+ let move_bin = new Gtk.Box({
+ orientation: Gtk.Orientation.VERTICAL,
+ 'width-request': 38,
+ 'height-request': 38,
+ 'margin-top': 6,
+ 'margin-bottom': 6
+ });
+ prefix_bin.append(move_bin);
+ move_bin.add_css_class('linked');
+
+ this._move_up_button = new Gtk.Button({
+ 'icon-name': 'go-up-symbolic',
+ 'width-request': 38,
+ 'height-request': 19
+ });
+ this._move_down_button = new Gtk.Button({
+ 'icon-name': 'go-down-symbolic',
+ 'width-request': 38,
+ 'height-request': 19
+ });
+ this._move_up_button.add_css_class('flat');
+ this._move_down_button.add_css_class('flat');
+ move_bin.append(this._move_up_button);
+ move_bin.append(this._move_down_button);
+
+ this._move_up_button.connect('clicked', () => effects_dialog.move_row_by(this, -1));
+ this._move_down_button.connect('clicked', () => effects_dialog.move_row_by(this, +1));
+
+ let remove_button = new Gtk.Button({
+ 'icon-name': 'remove-row-symbolic',
+ 'width-request': 38,
+ 'height-request': 38,
+ 'margin-top': 6,
+ 'margin-bottom': 6,
+ 'valign': Gtk.Align.CENTER
+ });
+ prefix_bin.append(remove_button);
+ remove_button.add_css_class('destructive-action');
+
+ remove_button.connect('clicked', () => effects_dialog.remove_row(this));
+ }
+
+ populate_options() {
+ const editable_params = this.SUPPORTED_EFFECTS[this.effect.type].editable_params;
+
+ if (Object.keys(editable_params).length == 0)
+ this.enable_expansion = false;
+
+ for (const param_key in editable_params) {
+ let param = editable_params[param_key];
+ let row;
+ switch (param.type) {
+ case "integer":
+ row = new Adw.SpinRow({
+ adjustment: new Gtk.Adjustment({
+ lower: param.min,
+ upper: param.max,
+ step_increment: param.increment
+ })
+ });
+ row.adjustment.set_value(this.get_effect_param(param_key));
+ row.adjustment.connect(
+ 'value-changed', () => this.set_effect_param(param_key, row.adjustment.value)
+ );
+ break;
+
+ case "float":
+ row = new Adw.ActionRow;
+ let scale = new Gtk.Scale({
+ valign: Gtk.Align.CENTER,
+ hexpand: true,
+ width_request: 200,
+ draw_value: true,
+ value_pos: Gtk.PositionType.RIGHT,
+ digits: param.digits,
+ adjustment: new Gtk.Adjustment({
+ lower: param.min,
+ upper: param.max,
+ step_increment: param.increment,
+ page_increment: param.big_increment
+ })
+ });
+ // TODO check if it's a good idea to set the default parameter, as the "good"
+ // value really change depending on the user wallpaper... if so, do for dynamic
+ // blur too
+ scale.add_mark(
+ this.get_default_effect_param(param_key), Gtk.PositionType.BOTTOM, null
+ );
+ row.add_suffix(scale);
+ scale.adjustment.set_value(this.get_effect_param(param_key));
+ scale.adjustment.connect(
+ 'value-changed', () => this.set_effect_param(param_key, scale.adjustment.value)
+ );
+ break;
+
+ case "boolean":
+ row = new Adw.SwitchRow;
+ row.set_active(this.get_effect_param(param_key));
+ row.connect(
+ 'notify::active', () => this.set_effect_param(param_key, row.active)
+ );
+ break;
+
+ case "dropdown":
+ row = new Adw.ComboRow({ model: new Gtk.StringList });
+ param.options.forEach(option => row.model.append(option));
+ row.selected = this.get_effect_param(param_key);
+ row.connect(
+ 'notify::selected', () => this.set_effect_param(param_key, row.selected)
+ );
+ break;
+
+ case "rgba":
+ row = new Adw.ActionRow;
+ let color_button = new Gtk.ColorButton({
+ valign: Gtk.Align.CENTER,
+ width_request: 75,
+ height_request: 45,
+ show_editor: true,
+ use_alpha: true
+ });
+ row.add_suffix(color_button);
+ // set original color
+ let c = color_button.get_rgba().copy();
+ [c.red, c.green, c.blue, c.alpha] = this.get_effect_param(param_key);
+ color_button.set_rgba(c);
+ // update on on 'color-set'
+ color_button.connect(
+ 'color-set', () => {
+ let c = color_button.get_rgba();
+ this.set_effect_param(param_key, [c.red, c.green, c.blue, c.alpha]);
+ }
+ );
+ break;
+
+ default:
+ row = new Adw.ActionRow;
+ break;
+ }
+ row.set_title(param.name);
+ row.set_subtitle(param.description);
+ this.add_row(row);
+ }
+ }
+
+ get_effect_param(key) {
+ let effects = this.pipelines_manager.pipelines[this.pipeline_id].effects;
+ const gsettings_effect = effects.find(e => e.id == this.effect.id);
+
+ if ('params' in gsettings_effect && key in gsettings_effect.params)
+ return gsettings_effect.params[key];
+ else
+ return this.get_default_effect_param(key);
+ }
+
+ get_default_effect_param(key) {
+ return this.SUPPORTED_EFFECTS[this.effect.type].class.default_params[key];
+ }
+
+ set_effect_param(key, value) {
+ // we must pay attention not to change the effects in the pipelines manager before updating
+ // it in gsettings, else it won't be updated (or every effect will be)
+ let effects = this.pipelines_manager.pipelines[this.pipeline_id].effects;
+ const effect_index = effects.findIndex(e => e.id == this.effect.id);
+
+ if (effect_index >= 0) {
+ effects[effect_index] = {
+ ...this.effect, params: { ...this.effect.params }
+ };
+ effects[effect_index].params[key] = value;
+ this.effect = effects[effect_index];
+ }
+ else
+ this._warn(`effect not found when setting key ${key}`);
+
+ this.pipelines_manager.update_pipeline_effects(this.pipeline_id, effects, false);
+ }
+
+ _warn(str) {
+ console.warn(
+ `[Blur my Shell > effect row] pipeline '${this.pipeline_id}',`
+ + ` effect '${this.effect.id}': ${str}`
+ );
+ }
+});
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/effects_dialog.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/effects_dialog.js
new file mode 100644
index 0000000..222a92e
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/effects_dialog.js
@@ -0,0 +1,174 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gtk from 'gi://Gtk';
+import Gio from 'gi://Gio';
+import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
+
+import { EffectRow } from './effect_row.js';
+import { get_effects_groups, get_supported_effects } from '../../effects/effects.js';
+
+export const EffectsDialog = GObject.registerClass({
+ GTypeName: 'EffectsDialog',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/effects-dialog.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ "add_effect",
+ "add_effect_alt_menu",
+ "effects_list"
+ ],
+}, class EffectsDialog extends Adw.PreferencesDialog {
+ constructor(pipelines_manager, pipeline_id) {
+ super({});
+
+ this.EFFECTS_GROUPS = get_effects_groups(_);
+ this.SUPPORTED_EFFECTS = get_supported_effects(_);
+
+ this.pipelines_manager = pipelines_manager;
+ this.pipeline_id = pipeline_id;
+
+ let pipeline = pipelines_manager.pipelines[pipeline_id];
+
+ this.set_title(pipeline.name.length > 0 ? _(`Effects for "${pipeline.name}"`) : _("Effects"));
+
+ pipeline.effects.forEach(effect => {
+ const effect_row = new EffectRow(effect, this);
+ this._effects_list.add(effect_row);
+ this.update_rows_insensitive_mover(effect_row);
+ });
+
+ // setup advanced effects chooser action
+ this.show_advanced_effects = false;
+ let action_group = new Gio.SimpleActionGroup();
+ this.insert_action_group('effects-dialog', action_group);
+ let advanced_effects_action = Gio.SimpleAction.new_stateful(
+ 'advanced-effects-bool',
+ null,
+ GLib.Variant.new_boolean(this.show_advanced_effects)
+ );
+ advanced_effects_action.connect(
+ 'change-state',
+ (_, state) => {
+ this.show_advanced_effects = state.get_boolean();
+ this.build_effects_chooser();
+ advanced_effects_action.set_state(state);
+ }
+ );
+ action_group.add_action(advanced_effects_action);
+
+ this.build_effects_chooser();
+ this._add_effect.connect('clicked', () => this.effects_chooser_dialog.present(this));
+ }
+
+ build_effects_chooser() {
+ this.effects_chooser_dialog = new Adw.Dialog({
+ presentation_mode: Adw.DialogPresentationMode.BOTTOM_SHEET,
+ content_width: 450
+ });
+
+ let page = new Adw.PreferencesPage;
+ this.effects_chooser_dialog.set_child(page);
+
+ for (const effects_group in this.EFFECTS_GROUPS) {
+ const group_infos = this.EFFECTS_GROUPS[effects_group];
+
+ let group = new Adw.PreferencesGroup({
+ title: group_infos.name
+ });
+ page.add(group);
+
+ for (const effect_type of group_infos.contains) {
+ if (!(effect_type in this.SUPPORTED_EFFECTS))
+ continue;
+
+ if (!this.show_advanced_effects && this.SUPPORTED_EFFECTS[effect_type].is_advanced)
+ continue;
+
+ let action_row = new Adw.ActionRow({
+ title: this.SUPPORTED_EFFECTS[effect_type].name,
+ subtitle: this.SUPPORTED_EFFECTS[effect_type].description
+ });
+ let select_button = new Gtk.Button({
+ 'icon-name': 'select-row-symbolic',
+ 'width-request': 38,
+ 'height-request': 38,
+ 'margin-top': 6,
+ 'margin-bottom': 6
+ });
+ group.add(action_row);
+
+ select_button.add_css_class('flat');
+ action_row.add_suffix(select_button);
+ action_row.set_activatable_widget(select_button);
+ select_button.connect('clicked', () => {
+ this.append_effect(effect_type);
+ this.effects_chooser_dialog.close();
+ });
+ }
+ }
+ }
+
+ append_effect(effect_type) {
+ const effect = {
+ type: effect_type, id: "effect_" + ("" + Math.random()).slice(2, 16)
+ };
+ this.pipelines_manager.update_pipeline_effects(
+ this.pipeline_id,
+ [...this.pipelines_manager.pipelines[this.pipeline_id].effects, effect]
+ );
+
+ const effect_row = new EffectRow(effect, this);
+ this._effects_list.add(effect_row);
+ this.move_row_by(effect_row, 0);
+ this.update_rows_insensitive_mover(effect_row);
+ }
+
+ move_row_by(row, number) {
+ const effects = this.pipelines_manager.pipelines[this.pipeline_id].effects;
+ const effect_index = effects.findIndex(e => e.id == row.effect.id);
+
+ if (effect_index >= 0) {
+ effects.splice(effect_index, 1);
+ effects.splice(effect_index + number, 0, row.effect);
+
+ const listbox = row.get_parent();
+ listbox.set_sort_func((row_a, row_b) => {
+ const id_a = effects.findIndex(e => e.id == row_a.effect.id);
+ const id_b = effects.findIndex(e => e.id == row_b.effect.id);
+ return id_a > id_b;
+ });
+
+ this.update_rows_insensitive_mover(row);
+
+ this.pipelines_manager.update_pipeline_effects(
+ this.pipeline_id, effects
+ );
+ }
+ }
+
+ update_rows_insensitive_mover(any_row) {
+ if (this._insensitive_top)
+ this._insensitive_top.set_sensitive(true);
+ if (this._insensitive_bottom)
+ this._insensitive_bottom.set_sensitive(true);
+
+ const listbox = any_row.get_parent();
+ this._insensitive_top = listbox.get_first_child()._move_up_button;
+ this._insensitive_top?.set_sensitive(false);
+ this._insensitive_bottom = listbox.get_last_child()._move_down_button;
+ this._insensitive_bottom?.set_sensitive(false);
+ }
+
+ remove_row(row) {
+ const effects = this.pipelines_manager.pipelines[this.pipeline_id].effects;
+ const effect_index = effects.findIndex(e => e.id == row.effect.id);
+
+ if (effect_index >= 0) {
+ effects.splice(effect_index, 1);
+ this.pipelines_manager.update_pipeline_effects(
+ this.pipeline_id, effects
+ );
+ }
+
+ this._effects_list.remove(row);
+ }
+});
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_choose_row.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_choose_row.js
new file mode 100644
index 0000000..e0c5165
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_choose_row.js
@@ -0,0 +1,106 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gtk from 'gi://Gtk';
+import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
+
+
+export const PipelineChooseRow = GObject.registerClass({
+ GTypeName: 'PipelineChooseRow',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/pipeline-choose-row.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ 'pipeline_choose',
+ 'pipeline_model',
+ 'pipeline_edit'
+ ],
+}, class PipelineChooseRow extends Adw.ActionRow {
+ initialize(preferences, pipelines_manager, pipelines_page) {
+ this.preferences = preferences;
+ this.pipelines_manager = pipelines_manager;
+ this.pipelines_page = pipelines_page;
+
+ this.create_pipelines_list();
+
+ // display the correct pipeline name in the drop-down instead of their ids
+ const closure_func = string_object => {
+ const pipeline_id = string_object.get_string();
+ if (pipeline_id == 'create_new')
+ return _("Create new pipeline");
+ if (pipeline_id in this.pipelines_manager.pipelines)
+ return this.pipelines_manager.pipelines[pipeline_id].name;
+ else
+ return "";
+ };
+
+ const expression = new Gtk.ClosureExpression(GObject.TYPE_STRING, closure_func, []);
+ this._pipeline_choose.expression = expression;
+
+ // TODO fix the expression not being re-evaluated other than by setting it again
+ this.pipelines_manager.connect(
+ 'pipeline-names-changed',
+ () => this._pipeline_choose.expression = new Gtk.ClosureExpression(
+ GObject.TYPE_STRING, closure_func, []
+ )
+ );
+
+ this.preferences.PIPELINE_changed(() => this.on_settings_pipeline_changed());
+
+ this.pipelines_manager.connect('pipeline-list-changed', () => this.create_pipelines_list());
+
+ this._pipeline_choose.connect('notify::selected', () => this.on_selected_pipeline_changed());
+
+ this._pipeline_edit.connect(
+ 'clicked',
+ () => this.pipelines_page.open_effects_dialog(this.preferences.PIPELINE)
+ );
+ }
+
+ on_selected_pipeline_changed() {
+ if (!this._pipeline_choose.selected_item || this._is_creating_pipelines_list)
+ return;
+
+ const pipeline_id = this._pipeline_choose.selected_item.get_string();
+ if (pipeline_id == 'create_new') {
+ const id = this.pipelines_manager.create_pipeline(_("New pipeline"));
+ this.preferences.PIPELINE = id;
+ }
+ else
+ this.preferences.PIPELINE = pipeline_id;
+ }
+
+ on_settings_pipeline_changed() {
+ for (let i = 0; i < this._pipeline_model.n_items; i++) {
+ const pipeline_id = this._pipeline_model.get_string(i);
+ // if we have more pipelines than we should have: rebuild...
+ // that is the case when resetting the preferences for example
+ if (!(pipeline_id in this.pipelines_manager)) {
+ this.create_pipelines_list();
+ return;
+ }
+ if (pipeline_id == this.preferences.PIPELINE)
+ this._pipeline_choose.set_selected(i);
+ }
+ }
+
+ create_pipelines_list() {
+ // prevent the pipeline selector from being updated while re-creating the list
+ this._is_creating_pipelines_list = true;
+
+ // remove ancient items
+ this._pipeline_model.splice(0, this._pipeline_model.n_items, null);
+
+ // add new ones
+ let i = 0;
+ for (let pipeline_id in this.pipelines_manager.pipelines) {
+ this._pipeline_model.append(pipeline_id);
+ if (pipeline_id == this.preferences.PIPELINE)
+ this._pipeline_choose.set_selected(i);
+ i++;
+ }
+ this._pipeline_model.append('create_new');
+
+ // now update the drop-down selector
+ this._is_creating_pipelines_list = false;
+ this.on_selected_pipeline_changed();
+ }
+}); \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_group.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_group.js
new file mode 100644
index 0000000..627b576
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_group.js
@@ -0,0 +1,99 @@
+import Adw from 'gi://Adw';
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Gtk from 'gi://Gtk';
+import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
+
+import { get_supported_effects } from '../../effects/effects.js';
+
+
+export const PipelineGroup = GObject.registerClass({
+ GTypeName: 'PipelineGroup',
+ Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/pipeline-group.ui', GLib.UriFlags.NONE),
+ InternalChildren: [
+ "title",
+ "effects_description_row",
+ "manage_effects"
+ ],
+}, class PipelineGroup extends Adw.PreferencesGroup {
+ constructor(pipelines_manager, pipeline_id, pipeline, pipelines_page) {
+ super({});
+
+ this.SUPPORTED_EFFECTS = get_supported_effects(_);
+
+ this._pipelines_manager = pipelines_manager;
+ this._pipelines_page = pipelines_page;
+ this._pipeline_id = pipeline_id;
+
+ // set the description
+ this.set_description(_(`Pipeline id: "${pipeline_id}"`));
+
+ // set the title and connect it to the text entry
+ this.set_title(pipeline.name.length > 0 ? pipeline.name : " ");
+ this._title.set_text(pipeline.name);
+ this._title.connect(
+ 'changed',
+ () => pipelines_manager.rename_pipeline(pipeline_id, this._title.get_text())
+ );
+
+ // the bin containing the actions
+ let prefix_bin = new Gtk.Box;
+ prefix_bin.add_css_class('linked');
+ this._title.add_prefix(prefix_bin);
+
+ // add a 'remove' button if we are not the default pipeline
+ if (pipeline_id != "pipeline_default") {
+ let remove_button = new Gtk.Button({
+ 'icon-name': 'remove-row-symbolic',
+ 'width-request': 38,
+ 'height-request': 38,
+ 'margin-top': 6,
+ 'margin-bottom': 6
+ });
+ remove_button.add_css_class('destructive-action');
+ prefix_bin.append(remove_button);
+ remove_button.connect('clicked', () => pipelines_manager.delete_pipeline(pipeline_id));
+ }
+ // add a 'duplicate' button
+ let duplicate_button = new Gtk.Button({
+ 'icon-name': 'duplicate-row-symbolic',
+ 'width-request': 38,
+ 'height-request': 38,
+ 'margin-top': 6,
+ 'margin-bottom': 6
+ });
+ prefix_bin.append(duplicate_button);
+ duplicate_button.connect('clicked', () => pipelines_manager.duplicate_pipeline(pipeline_id));
+
+ this.update_effects_description_row();
+ this._pipelines_manager.connect(
+ pipeline_id + '::pipeline-updated',
+ () => this.update_effects_description_row()
+ );
+
+ this._manage_effects.connect(
+ 'clicked',
+ () => pipelines_page.open_effects_dialog(pipeline_id)
+ );
+ }
+
+ update_effects_description_row() {
+ const effects = this._pipelines_manager.pipelines[this._pipeline_id].effects;
+
+ if (effects.length == 0)
+ this._effects_description_row.set_title(_("No effect"));
+ else if (effects.length == 1)
+ this._effects_description_row.set_title(_("1 effect"));
+ else
+ this._effects_description_row.set_title(_(`${effects.length} effects`));
+
+ let subtitle = "";
+ effects.forEach(effect => {
+ if (effect.type in this.SUPPORTED_EFFECTS)
+ subtitle += _(`${this.SUPPORTED_EFFECTS[effect.type].name}, `);
+ else
+ subtitle += _("Unknown effect, ");
+ });
+ this._effects_description_row.set_subtitle(subtitle.slice(0, -2));
+ }
+});
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/prefs.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/prefs.js
new file mode 100644
index 0000000..43c4889
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/prefs.js
@@ -0,0 +1,51 @@
+import Gdk from 'gi://Gdk';
+import Gtk from 'gi://Gtk';
+import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
+
+import { update_from_old_settings } from './conveniences/settings_updater.js';
+import { PipelinesManager } from './conveniences/pipelines_manager.js';
+import { Settings } from './conveniences/settings.js';
+import { KEYS } from './conveniences/keys.js';
+
+import { addMenu } from './preferences/menu.js';
+import { Pipelines } from './preferences/pipelines.js';
+import { Panel } from './preferences/panel.js';
+import { Overview } from './preferences/overview.js';
+import { Dash } from './preferences/dash.js';
+import { Applications } from './preferences/applications.js';
+import { Other } from './preferences/other.js';
+
+import './preferences/pipelines_management/pipeline_choose_row.js';
+
+
+export default class BlurMyShellPreferences extends ExtensionPreferences {
+ constructor(metadata) {
+ super(metadata);
+
+ // load the icon theme
+ let iconPath = this.dir.get_child("icons").get_path();
+ let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default());
+ iconTheme.add_search_path(iconPath);
+ }
+
+ fillPreferencesWindow(window) {
+ addMenu(window);
+
+ // update from old settings, very important for hacks level specifically
+ update_from_old_settings(this.getSettings());
+
+ const preferences = new Settings(KEYS, this.getSettings());
+ const pipelines_manager = new PipelinesManager(preferences);
+
+ const pipelines_page = new Pipelines(preferences, pipelines_manager, window);
+
+ window.add(pipelines_page);
+ window.add(new Panel(preferences, pipelines_manager, pipelines_page));
+ window.add(new Overview(preferences, pipelines_manager, pipelines_page));
+ window.add(new Dash(preferences, pipelines_manager, pipelines_page));
+ window.add(new Applications(preferences, window, pipelines_manager, pipelines_page));
+ window.add(new Other(preferences, pipelines_manager, pipelines_page));
+
+ window.search_enabled = true;
+ }
+}
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/gschemas.compiled b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/gschemas.compiled
new file mode 100644
index 0000000..c2b6708
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/gschemas.compiled
Binary files differ
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml
new file mode 100644
index 0000000..7526e30
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml
@@ -0,0 +1,595 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist>
+ <!-- GENERAL -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell"
+ path="/org/gnome/shell/extensions/blur-my-shell/">
+ <!-- SETTINGS VERSION -->
+ <key type="i" name="settings-version">
+ <default>1</default>
+ <summary>The version of the settings to update from.</summary>
+ </key>
+ <!-- PIPELINES -->
+ <key type="a{sa{sv}}" name="pipelines">
+ <default> <![CDATA[
+ {
+ 'pipeline_default': {
+ 'name': <'Default'>,
+ 'effects': <[
+ <{
+ 'type': <'native_static_gaussian_blur'>,
+ 'id': <'effect_000000000000'>,
+ 'params': <{
+ 'radius': <30>,
+ 'brightness': <0.6>
+ }>
+ }>
+ ]>
+ },
+ 'pipeline_default_rounded': {
+ 'name': <'Default rounded'>,
+ 'effects': <[
+ <{
+ 'type': <'native_static_gaussian_blur'>,
+ 'id': <'effect_000000000001'>,
+ 'params': <{
+ 'radius': <30>,
+ 'brightness': <0.6>
+ }>
+ }>,
+ <{
+ 'type': <'corner'>,
+ 'id': <'effect_000000000002'>,
+ 'params': <{
+ 'radius': <24>
+ }>
+ }>
+ ]>
+ }
+ }
+ ]]></default>
+ <summary>A dictionnary describing the different pipelines and their effects.</summary>
+ </key>
+ <!-- SIGMA -->
+ <key type="i" name="sigma">
+ <default>30</default>
+ <summary>Global gaussian sigma to use</summary>
+ </key>
+ <!-- BRIGHTNESS -->
+ <key type="d" name="brightness">
+ <default>0.6</default>
+ <summary>Global brightness to use</summary>
+ </key>
+ <!-- COLOR -->
+ <key type="(dddd)" name="color">
+ <default>(0.,0.,0.,0.)</default>
+ <summary>Color to mix with the blur effect</summary>
+ </key>
+ <!-- NOISE AMOUNT -->
+ <key type="d" name="noise-amount">
+ <default>0.</default>
+ <summary>Amount of noise to add to the blur effect</summary>
+ </key>
+ <!-- NOISE LIGHTNESS -->
+ <key type="d" name="noise-lightness">
+ <default>0.</default>
+ <summary>Lightness of the noise added to the blur effect</summary>
+ </key>
+ <!-- COLOR AND NOISE -->
+ <key type="b" name="color-and-noise">
+ <default>true</default>
+ <summary>Boolean, controls wether or not the color and noise effects are in use globally</summary>
+ </key>
+ <!-- HACKS LEVEL -->
+ <key type="i" name="hacks-level">
+ <default>1</default>
+ <summary>Level of hacks to use (from 0 to 2, 2 disabling clipped redraws entirely)</summary>
+ </key>
+ <!-- DEBUG -->
+ <key type="b" name="debug">
+ <default>false</default>
+ <summary>Boolean, set to true to activate debug mode (more verbose journalctl logs)</summary>
+ </key>
+
+ <child name='overview' schema='org.gnome.shell.extensions.blur-my-shell.overview'></child>
+ <child name='appfolder' schema='org.gnome.shell.extensions.blur-my-shell.appfolder'></child>
+ <child name='panel' schema='org.gnome.shell.extensions.blur-my-shell.panel'></child>
+ <child name='dash-to-dock' schema='org.gnome.shell.extensions.blur-my-shell.dash-to-dock'></child>
+ <child name='applications' schema='org.gnome.shell.extensions.blur-my-shell.applications'></child>
+ <child name='screenshot' schema='org.gnome.shell.extensions.blur-my-shell.screenshot'></child>
+ <child name='lockscreen' schema='org.gnome.shell.extensions.blur-my-shell.lockscreen'></child>
+ <child name='window-list' schema='org.gnome.shell.extensions.blur-my-shell.window-list'></child>
+ <child name='coverflow-alt-tab' schema='org.gnome.shell.extensions.blur-my-shell.coverflow-alt-tab'></child>
+ <child name='hidetopbar' schema='org.gnome.shell.extensions.blur-my-shell.hidetopbar'></child>
+ <child name='dash-to-panel' schema='org.gnome.shell.extensions.blur-my-shell.dash-to-panel'></child>
+ </schema>
+
+ <!-- OVERVIEW -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.overview"
+ path="/org/gnome/shell/extensions/blur-my-shell/overview/">
+ <!-- BLUR -->
+ <key type="b" name="blur">
+ <default>true</default>
+ <summary>Boolean, whether to blur activate the blur for this component or not</summary>
+ </key>
+ <!-- PIPELINE -->
+ <key type="s" name="pipeline">
+ <default>"pipeline_default"</default>
+ <summary>String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used</summary>
+ </key>
+ <!-- CUSTOMIZE -->
+ <key type="b" name="customize">
+ <default>false</default>
+ <summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
+ </key>
+ <!-- SIGMA -->
+ <key type="i" name="sigma">
+ <default>30</default>
+ <summary>Gaussian sigma to use for the blur effect</summary>
+ </key>
+ <!-- BRIGHTNESS -->
+ <key type="d" name="brightness">
+ <default>0.6</default>
+ <summary>Brightness to use for the blur effect</summary>
+ </key>
+ <!-- COLOR -->
+ <key type="(dddd)" name="color">
+ <default>(0.,0.,0.,0.)</default>
+ <summary>Color to mix with the blur effect</summary>
+ </key>
+ <!-- NOISE AMOUNT -->
+ <key type="d" name="noise-amount">
+ <default>0.</default>
+ <summary>Amount of noise to add to the blur effect</summary>
+ </key>
+ <!-- NOISE LIGHTNESS -->
+ <key type="d" name="noise-lightness">
+ <default>0.</default>
+ <summary>Lightness of the noise added to the blur effect</summary>
+ </key>
+ <!-- STYLE COMPONENTS -->
+ <key type="i" name="style-components">
+ <default>1</default>
+ <summary>Enum to select the style of the components in overview (0 not styled, 1 light, 2 dark, 3 transparent)</summary>
+ </key>
+ </schema>
+
+ <!-- APPFOLDER -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.appfolder"
+ path="/org/gnome/shell/extensions/blur-my-shell/appfolder/">
+ <!-- BLUR -->
+ <key type="b" name="blur">
+ <default>true</default>
+ <summary>Boolean, whether to blur activate the blur for this component or not</summary>
+ </key>
+ <!-- CUSTOMIZE -->
+ <key type="b" name="customize">
+ <default>false</default>
+ <summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
+ </key>
+ <!-- SIGMA -->
+ <key type="i" name="sigma">
+ <default>30</default>
+ <summary>Gaussian sigma to use for the blur effect</summary>
+ </key>
+ <!-- BRIGHTNESS -->
+ <key type="d" name="brightness">
+ <default>0.6</default>
+ <summary>Brightness to use for the blur effect</summary>
+ </key>
+ <!-- COLOR -->
+ <key type="(dddd)" name="color">
+ <default>(0.,0.,0.,0.)</default>
+ <summary>Color to mix with the blur effect</summary>
+ </key>
+ <!-- NOISE AMOUNT -->
+ <key type="d" name="noise-amount">
+ <default>0.</default>
+ <summary>Amount of noise to add to the blur effect</summary>
+ </key>
+ <!-- NOISE LIGHTNESS -->
+ <key type="d" name="noise-lightness">
+ <default>0.</default>
+ <summary>Lightness of the noise added to the blur effect</summary>
+ </key>
+ <!-- STYLE DIALOGS -->
+ <key type="i" name="style-dialogs">
+ <default>1</default>
+ <summary>Enum to select the style of the appfolder dialogs (0 not styled, 1 transparent, 2 light, 3 dark)</summary>
+ </key>
+ </schema>
+
+ <!-- PANEL -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.panel"
+ path="/org/gnome/shell/extensions/blur-my-shell/panel/">
+ <!-- BLUR -->
+ <key type="b" name="blur">
+ <default>true</default>
+ <summary>Boolean, whether to blur activate the blur for this component or not</summary>
+ </key>
+ <!-- PIPELINE -->
+ <key type="s" name="pipeline">
+ <default>"pipeline_default"</default>
+ <summary>String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used</summary>
+ </key>
+ <!-- CUSTOMIZE -->
+ <key type="b" name="customize">
+ <default>false</default>
+ <summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
+ </key>
+ <!-- SIGMA -->
+ <key type="i" name="sigma">
+ <default>30</default>
+ <summary>Gaussian sigma to use for the blur effect</summary>
+ </key>
+ <!-- BRIGHTNESS -->
+ <key type="d" name="brightness">
+ <default>0.6</default>
+ <summary>Brightness to use for the blur effect</summary>
+ </key>
+ <!-- COLOR -->
+ <key type="(dddd)" name="color">
+ <default>(0.,0.,0.,0.)</default>
+ <summary>Color to mix with the blur effect</summary>
+ </key>
+ <!-- NOISE AMOUNT -->
+ <key type="d" name="noise-amount">
+ <default>0.</default>
+ <summary>Amount of noise to add to the blur effect</summary>
+ </key>
+ <!-- NOISE LIGHTNESS -->
+ <key type="d" name="noise-lightness">
+ <default>0.</default>
+ <summary>Lightness of the noise added to the blur effect</summary>
+ </key>
+ <!-- STATIC BLUR -->
+ <key type="b" name="static-blur">
+ <default>true</default>
+ <summary>Boolean, whether to use a static or dynamic blur for this component</summary>
+ </key>
+ <!-- UNBLUR IN OVERVIEW -->
+ <key type="b" name="unblur-in-overview">
+ <default>true</default>
+ <summary>Boolean, whether to disable blur from this component when opening the overview or not</summary>
+ </key>
+ <!-- FORCE LIGHT TEXT -->
+ <key type="b" name="force-light-text">
+ <default>false</default>
+ <summary>Boolean, whether or not to force the panel to have light text, useful when using light theme</summary>
+ </key>
+ <!-- OVERRIDE BACKGROUND -->
+ <key type="b" name="override-background">
+ <default>true</default>
+ <summary>Boolean, whether to override the background or not</summary>
+ </key>
+ <!-- STYLE PANEL -->
+ <key type="i" name="style-panel">
+ <default>0</default>
+ <summary>Enum to select the style of the panel (0 transparent, 1 light, 2 dark, 3 contrasted)</summary>
+ </key>
+ <!-- UNBLUR DYNAMICALLY -->
+ <key type="b" name="override-background-dynamically">
+ <default>false</default>
+ <summary>Boolean, whether to disable blur from this component when a window is close to the panel</summary>
+ </key>
+ </schema>
+
+ <!-- DASH TO DOCK -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.dash-to-dock"
+ path="/org/gnome/shell/extensions/blur-my-shell/dash-to-dock/">
+ <!-- BLUR -->
+ <key type="b" name="blur">
+ <default>true</default>
+ <summary>Boolean, whether to blur activate the blur for this component or not</summary>
+ </key>
+ <!-- PIPELINE -->
+ <key type="s" name="pipeline">
+ <default>"pipeline_default_rounded"</default>
+ <summary>String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used</summary>
+ </key>
+ <!-- CUSTOMIZE -->
+ <key type="b" name="customize">
+ <default>false</default>
+ <summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
+ </key>
+ <!-- SIGMA -->
+ <key type="i" name="sigma">
+ <default>30</default>
+ <summary>Gaussian sigma to use for the blur effect</summary>
+ </key>
+ <!-- BRIGHTNESS -->
+ <key type="d" name="brightness">
+ <default>0.6</default>
+ <summary>Brightness to use for the blur effect</summary>
+ </key>
+ <!-- COLOR -->
+ <key type="(dddd)" name="color">
+ <default>(0.,0.,0.,0.)</default>
+ <summary>Color to mix with the blur effect</summary>
+ </key>
+ <!-- NOISE AMOUNT -->
+ <key type="d" name="noise-amount">
+ <default>0.</default>
+ <summary>Amount of noise to add to the blur effect</summary>
+ </key>
+ <!-- NOISE LIGHTNESS -->
+ <key type="d" name="noise-lightness">
+ <default>0.</default>
+ <summary>Lightness of the noise added to the blur effect</summary>
+ </key>
+ <!-- STATIC BLUR -->
+ <key type="b" name="static-blur">
+ <default>true</default>
+ <summary>Boolean, whether to use static or dynamic blur for this component</summary>
+ </key>
+ <!-- OVERRIDE BACKGROUND -->
+ <key type="b" name="override-background">
+ <default>true</default>
+ <summary>Boolean, whether to override the background or not</summary>
+ </key>
+ <!-- STYLE DASH TO DOCK -->
+ <key type="i" name="style-dash-to-dock">
+ <default>0</default>
+ <summary>Enum to select the style of dash to dock (0 transparent, 1 light, 2 dark)</summary>
+ </key>
+ <!-- UNBLUR IN OVERVIEW -->
+ <key type="b" name="unblur-in-overview">
+ <default>false</default>
+ <summary>Boolean, whether to disable blur from this component when opening the overview or not</summary>
+ </key>
+ <!-- CORNER RADIUS -->
+ <key type="i" name="corner-radius">
+ <default>12</default>
+ <summary>Radius for the corner rounding effect</summary>
+ </key>
+ </schema>
+
+ <!-- APPLICATIONS -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.applications"
+ path="/org/gnome/shell/extensions/blur-my-shell/applications/">
+ <!-- BLUR -->
+ <key type="b" name="blur">
+ <default>false</default>
+ <summary>Boolean, whether to blur activate the blur for this component or not</summary>
+ </key>
+ <!-- PIPELINE -->
+ <key type="s" name="pipeline">
+ <default>"pipeline_default"</default>
+ <summary>String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used</summary>
+ </key>
+ <!-- STATIC BLUR -->
+ <key type="b" name="static-blur">
+ <default>false</default>
+ <summary>Boolean, whether to use static or dynamic blur for this component</summary>
+ </key>
+ <!-- CUSTOMIZE -->
+ <key type="b" name="customize">
+ <default>true</default>
+ <summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
+ </key>
+ <!-- SIGMA -->
+ <key type="i" name="sigma">
+ <default>30</default>
+ <summary>Gaussian sigma to use for the blur effect</summary>
+ </key>
+ <!-- BRIGHTNESS -->
+ <key type="d" name="brightness">
+ <default>1.</default>
+ <summary>Brightness to use for the blur effect</summary>
+ </key>
+ <!-- COLOR -->
+ <key type="(dddd)" name="color">
+ <default>(0.,0.,0.,0.)</default>
+ <summary>Color to mix with the blur effect</summary>
+ </key>
+ <!-- NOISE AMOUNT -->
+ <key type="d" name="noise-amount">
+ <default>0.</default>
+ <summary>Amount of noise to add to the blur effect</summary>
+ </key>
+ <!-- NOISE LIGHTNESS -->
+ <key type="d" name="noise-lightness">
+ <default>0.</default>
+ <summary>Lightness of the noise added to the blur effect</summary>
+ </key>
+ <!-- OPACITY -->
+ <key type="i" name="opacity">
+ <default>215</default>
+ <summary>Opacity of the window actor on top of the blur effect</summary>
+ </key>
+ <!-- DYNAMIC OPACITY -->
+ <key type="b" name="dynamic-opacity">
+ <default>true</default>
+ <summary>Wether or not to make the focused window opaque</summary>
+ </key>
+ <!-- BLUR ON OVERVIEW -->
+ <key type="b" name="blur-on-overview">
+ <default>false</default>
+ <summary>Wether or not to blur applications on the overview</summary>
+ </key>
+ <!-- ENABLE ALL -->
+ <key type="b" name="enable-all">
+ <default>false</default>
+ <summary>Wether or not to blur all applications by default</summary>
+ </key>
+ <!-- WHITELIST -->
+ <key type="as" name="whitelist">
+ <default>[]</default>
+ <summary>List of applications to blur</summary>
+ </key>
+ <!-- BLACKLIST -->
+ <key type="as" name="blacklist">
+ <default>["Plank","com.desktop.ding", "Conky"]</default>
+ <summary>List of applications not to blur</summary>
+ </key>
+ </schema>
+
+ <!-- SCREENSHOT -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.screenshot"
+ path="/org/gnome/shell/extensions/blur-my-shell/screenshot/">
+ <!-- BLUR -->
+ <key type="b" name="blur">
+ <default>true</default>
+ <summary>Boolean, whether to blur activate the blur for this component or not</summary>
+ </key>
+ <!-- PIPELINE -->
+ <key type="s" name="pipeline">
+ <default>"pipeline_default"</default>
+ <summary>String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used</summary>
+ </key>
+ <!-- CUSTOMIZE -->
+ <key type="b" name="customize">
+ <default>false</default>
+ <summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
+ </key>
+ <!-- SIGMA -->
+ <key type="i" name="sigma">
+ <default>30</default>
+ <summary>Gaussian sigma to use for the blur effect</summary>
+ </key>
+ <!-- BRIGHTNESS -->
+ <key type="d" name="brightness">
+ <default>0.6</default>
+ <summary>Brightness to use for the blur effect</summary>
+ </key>
+ <!-- COLOR -->
+ <key type="(dddd)" name="color">
+ <default>(0.,0.,0.,0.)</default>
+ <summary>Color to mix with the blur effect</summary>
+ </key>
+ <!-- NOISE AMOUNT -->
+ <key type="d" name="noise-amount">
+ <default>0.</default>
+ <summary>Amount of noise to add to the blur effect</summary>
+ </key>
+ <!-- NOISE LIGHTNESS -->
+ <key type="d" name="noise-lightness">
+ <default>0.</default>
+ <summary>Lightness of the noise added to the blur effect</summary>
+ </key>
+ </schema>
+
+ <!-- LOCKSCREEN -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.lockscreen"
+ path="/org/gnome/shell/extensions/blur-my-shell/lockscreen/">
+ <!-- BLUR -->
+ <key type="b" name="blur">
+ <default>true</default>
+ <summary>Boolean, whether to blur activate the blur for this component or not</summary>
+ </key>
+ <!-- PIPELINE -->
+ <key type="s" name="pipeline">
+ <default>"pipeline_default"</default>
+ <summary>String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used</summary>
+ </key>
+ <!-- CUSTOMIZE -->
+ <key type="b" name="customize">
+ <default>false</default>
+ <summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
+ </key>
+ <!-- SIGMA -->
+ <key type="i" name="sigma">
+ <default>30</default>
+ <summary>Gaussian sigma to use for the blur effect</summary>
+ </key>
+ <!-- BRIGHTNESS -->
+ <key type="d" name="brightness">
+ <default>0.6</default>
+ <summary>Brightness to use for the blur effect</summary>
+ </key>
+ <!-- COLOR -->
+ <key type="(dddd)" name="color">
+ <default>(0.,0.,0.,0.)</default>
+ <summary>Color to mix with the blur effect</summary>
+ </key>
+ <!-- NOISE AMOUNT -->
+ <key type="d" name="noise-amount">
+ <default>0.</default>
+ <summary>Amount of noise to add to the blur effect</summary>
+ </key>
+ <!-- NOISE LIGHTNESS -->
+ <key type="d" name="noise-lightness">
+ <default>0.</default>
+ <summary>Lightness of the noise added to the blur effect</summary>
+ </key>
+ </schema>
+
+ <!-- WINDOW LIST -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.window-list"
+ path="/org/gnome/shell/extensions/blur-my-shell/window-list/">
+ <!-- BLUR -->
+ <key type="b" name="blur">
+ <default>true</default>
+ <summary>Boolean, whether to blur activate the blur for this component or not</summary>
+ </key>
+ <!-- PIPELINE -->
+ <key type="s" name="pipeline">
+ <default>"pipeline_default"</default>
+ <summary>String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used</summary>
+ </key>
+ <!-- CUSTOMIZE -->
+ <key type="b" name="customize">
+ <default>false</default>
+ <summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
+ </key>
+ <!-- SIGMA -->
+ <key type="i" name="sigma">
+ <default>30</default>
+ <summary>Gaussian sigma to use for the blur effect</summary>
+ </key>
+ <!-- BRIGHTNESS -->
+ <key type="d" name="brightness">
+ <default>0.6</default>
+ <summary>Brightness to use for the blur effect</summary>
+ </key>
+ <!-- COLOR -->
+ <key type="(dddd)" name="color">
+ <default>(0.,0.,0.,0.)</default>
+ <summary>Color to mix with the blur effect</summary>
+ </key>
+ <!-- NOISE AMOUNT -->
+ <key type="d" name="noise-amount">
+ <default>0.</default>
+ <summary>Amount of noise to add to the blur effect</summary>
+ </key>
+ <!-- NOISE LIGHTNESS -->
+ <key type="d" name="noise-lightness">
+ <default>0.</default>
+ <summary>Lightness of the noise added to the blur effect</summary>
+ </key>
+ </schema>
+
+ <!-- COVERFLOW ALT-TAB -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.coverflow-alt-tab"
+ path="/org/gnome/shell/extensions/blur-my-shell/coverflow-alt-tab/">
+ <!-- BLUR -->
+ <key type="b" name="blur">
+ <default>true</default>
+ <summary>Boolean, whether to blur activate the blur for this component or not</summary>
+ </key>
+ <!-- PIPELINE -->
+ <key type="s" name="pipeline">
+ <default>"pipeline_default"</default>
+ <summary>String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used</summary>
+ </key>
+ </schema>
+
+ <!-- HIDETOPBAR -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.hidetopbar"
+ path="/org/gnome/shell/extensions/blur-my-shell/hidetopbar/">
+ <!-- COMPATIBILITY -->
+ <key type="b" name="compatibility">
+ <default>false</default>
+ <summary>Boolean, whether to try compatibility with hidetopbar@mathieu.bidon.ca or not</summary>
+ </key>
+ </schema>
+
+ <!-- DASH TO PANEL -->
+ <schema id="org.gnome.shell.extensions.blur-my-shell.dash-to-panel"
+ path="/org/gnome/shell/extensions/blur-my-shell/dash-to-panel/">
+ <!-- COMPATIBILITY -->
+ <key type="b" name="blur-original-panel">
+ <default>true</default>
+ <summary>Boolean, whether to blur the original panel (if option selected) with Dash to Panel</summary>
+ </key>
+ </schema>
+</schemalist> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/stylesheet.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/stylesheet.css
new file mode 100644
index 0000000..b61e530
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/stylesheet.css
@@ -0,0 +1,573 @@
+/*** PANEL ***/
+
+/*
+* `.transparent-panel`
+*/
+#panel.transparent-panel {
+ background: transparent;
+ transition-duration: 500ms;
+}
+
+/*
+* `.dark-panel`
+*/
+#panel.dark-panel {
+ background-color: rgba(100, 100, 100, 0.35);
+ box-shadow: none;
+ transition-duration: 500ms;
+}
+
+/*
+* `.light-panel`
+*/
+#panel.light-panel {
+ background-color: rgba(200, 200, 200, 0.2);
+ box-shadow: none;
+ transition-duration: 500ms;
+}
+
+/*
+* `.contrasted-panel`
+*/
+#panel.contrasted-panel {
+ background-color: transparent;
+ box-shadow: none;
+ transition-duration: 500ms;
+}
+
+.contrasted-panel .panel-button,
+.contrasted-panel .clock,
+.contrasted-panel .clock-display StIcon {
+ color: #ffffff;
+ border-radius: 14px;
+ border: 3px solid transparent;
+ background-color: rgba(0, 0, 0, 0.8);
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.03);
+}
+
+
+.contrasted-panel .clock-display StIcon {
+ padding: 8px;
+ margin: 0;
+}
+
+.contrasted-panel .panel-button:hover,
+.contrasted-panel .panel-button:hover .clock {
+ color: #ffffff;
+ background-color: rgba(0, 0, 0, 0.8);
+}
+
+.contrasted-panel .clock-display {
+ background-color: transparent !important;
+ box-shadow: none !important;
+ border: none !important;
+}
+
+.contrasted-panel .clock {
+ margin: 0 !important;
+}
+
+
+/*** DASH-TO-DOCK ***/
+
+/*
+* `.transparent-dash`
+*/
+.transparent-dash .dash-background {
+ background-color: transparent !important;
+}
+
+/*
+* `.light-dash`
+*/
+.light-dash .dash-background {
+ background-color: rgba(200, 200, 200, 0.2) !important;
+}
+
+/*
+* `.dark-dash`
+*/
+.dark-dash .dash-background {
+ background-color: rgba(100, 100, 100, 0.35) !important;
+}
+
+
+/*** OVERVIEW ***/
+
+/*
+* Add transparency to the workspace animation (between workspaces)
+*/
+.blurred-overview .workspace-animation {
+ background-color: transparent !important;
+}
+
+
+/*
+* `.overview-components-transparent`
+*/
+
+.overview-components-transparent .workspace-thumbnail {
+ border: 1px solid rgba(100, 100, 100, 0.35);
+}
+
+.overview-components-transparent .search-entry {
+ color: white;
+ background-color: rgba(0, 0, 0, 0);
+ border-color: transparent;
+ box-shadow: none;
+}
+
+.overview-components-transparent .search-entry .search-entry-icon {
+ color: rgba(255, 255, 255, 0.65);
+}
+
+.overview-components-transparent .overview-tile,
+.overview-components-transparent .overview-icon,
+.overview-components-transparent .grid-search-result,
+.overview-components-transparent .list-search-result,
+.overview-components-transparent .search-provider-icon,
+/* prevents the extension from interfering with Just Perfection */
+.overview-components-transparent.just-perfection .search-section-content,
+/* remove the rectangular background from the dash */
+.overview-components-transparent #dash .overview-tile,
+.overview-components-transparent #dashtopanelScrollview .overview-tile {
+ background-color: transparent;
+}
+
+.overview-components-transparent .workspace-thumbnail,
+.overview-components-transparent .search-section-content,
+.overview-components-transparent .overview-tile.app-folder,
+.overview-components-transparent .page-navigation-arrow,
+.overview-components-transparent .app-folder-dialog .icon-button,
+/* this shouldn't apply to Dash to Dock */
+.overview-components-transparent StBoxLayout>StWidget>#dash>.dash-background {
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.overview-components-transparent .overview-tile:hover,
+.overview-components-transparent .overview-tile:focus,
+.overview-components-transparent .overview-tile:selected,
+.overview-components-transparent .overview-tile:highlighted,
+.overview-components-transparent .grid-search-result:hover,
+.overview-components-transparent .grid-search-result:focus,
+.overview-components-transparent .grid-search-result:selected,
+.overview-components-transparent .grid-search-result:highlighted,
+.overview-components-transparent .list-search-result:hover,
+.overview-components-transparent .list-search-result:focus,
+.overview-components-transparent .list-search-result:selected,
+.overview-components-transparent .list-search-result:highlighted,
+.overview-components-transparent .search-provider-icon:hover,
+.overview-components-transparent .search-provider-icon:focus,
+.overview-components-transparent .page-navigation-arrow:hover,
+.overview-components-transparent .page-navigation-arrow:focus,
+.overview-components-transparent .app-folder-dialog .icon-button:hover,
+.overview-components-transparent .app-folder-dialog .icon-button:focus,
+.overview-components-transparent #dash .overview-tile:hover .overview-icon,
+.overview-components-transparent #dash .overview-tile:focus .overview-icon,
+.overview-components-transparent #dash .show-apps:hover .overview-icon,
+.overview-components-transparent #dash .show-apps:focus .overview-icon {
+ background-color: rgba(230, 230, 230, 0.08);
+}
+
+.overview-components-transparent .overview-tile:active,
+.overview-components-transparent .overview-tile:focus:hover,
+.overview-components-transparent .overview-tile:drop,
+.overview-components-transparent .overview-tile:selected:hover,
+.overview-components-transparent .overview-tile:highlighted:hover,
+.overview-components-transparent .grid-search-result:active,
+.overview-components-transparent .grid-search-result:focus:hover,
+.overview-components-transparent .grid-search-result:selected:hover,
+.overview-components-transparent .grid-search-result:highlighted:hover,
+.overview-components-transparent .list-search-result:active,
+.overview-components-transparent .list-search-result:focus:hover,
+.overview-components-transparent .list-search-result:selected:hover,
+.overview-components-transparent .list-search-result:highlighted:hover,
+.overview-components-transparent .search-provider-icon:active,
+.overview-components-transparent .search-provider-icon:focus:hover,
+.overview-components-transparent .page-navigation-arrow:active,
+.overview-components-transparent .page-navigation-arrow:focus:hover,
+.overview-components-transparent .app-folder-dialog .icon-button:active,
+.overview-components-transparent .app-folder-dialog .icon-button:focus:hover,
+.overview-components-transparent #dash .overview-tile:active .overview-icon,
+.overview-components-transparent #dash .overview-tile:focus:hover .overview-icon,
+.overview-components-transparent #dash .overview-tile:drop .overview-icon,
+.overview-components-transparent #dash .show-apps:checked .overview-icon {
+ background-color: rgba(230, 230, 230, 0.12);
+}
+
+.overview-components-transparent .overview-tile:focus:active,
+.overview-components-transparent .overview-tile:selected:active,
+.overview-components-transparent .overview-tile:highlighted:active,
+.overview-components-transparent .grid-search-result:focus:active,
+.overview-components-transparent .grid-search-result:selected:active,
+.overview-components-transparent .grid-search-result:highlighted:active,
+.overview-components-transparent .list-search-result:focus:active,
+.overview-components-transparent .list-search-result:selected:active,
+.overview-components-transparent .list-search-result:highlighted:active,
+.overview-components-transparent .search-provider-icon:focus:active,
+.overview-components-transparent .page-navigation-arrow:focus:active,
+.overview-components-transparent .app-folder-dialog .icon-button:focus:active,
+.overview-components-transparent #dash .show-apps:checked .overview-icon:hover {
+ background-color: rgba(230, 230, 230, 0.15);
+}
+
+
+/*
+* `.overview-components-light`
+*/
+
+.overview-components-light .search-entry {
+ color: white;
+ background-color: rgba(200, 200, 200, 0.2);
+ border-color: transparent;
+ box-shadow: none;
+}
+
+.overview-components-light .search-entry .search-entry-icon {
+ color: rgba(255, 255, 255, 0.65);
+}
+
+.overview-components-light .overview-tile,
+.overview-components-light .overview-icon,
+.overview-components-light .grid-search-result,
+.overview-components-light .list-search-result,
+.overview-components-light .search-provider-icon,
+/* prevents the extension from interfering with Just Perfection */
+.overview-components-light.just-perfection .search-section-content,
+/* remove the rectangular background from the dash */
+.overview-components-light #dash .overview-tile,
+.overview-components-light #dashtopanelScrollview .overview-tile {
+ background-color: transparent;
+}
+
+.overview-components-light .workspace-thumbnail,
+.overview-components-light .search-section-content,
+.overview-components-light .overview-tile.app-folder,
+.overview-components-light .page-navigation-arrow,
+.overview-components-light .app-folder-dialog .icon-button,
+/* this shouldn't apply to Dash to Dock */
+.overview-components-light StBoxLayout>StWidget>#dash>.dash-background {
+ background-color: rgba(200, 200, 200, 0.2);
+}
+
+.overview-components-light .overview-tile:hover,
+.overview-components-light .overview-tile:focus,
+.overview-components-light .overview-tile:selected,
+.overview-components-light .overview-tile:highlighted,
+.overview-components-light .grid-search-result:hover,
+.overview-components-light .grid-search-result:focus,
+.overview-components-light .grid-search-result:selected,
+.overview-components-light .grid-search-result:highlighted,
+.overview-components-light .list-search-result:hover,
+.overview-components-light .list-search-result:focus,
+.overview-components-light .list-search-result:selected,
+.overview-components-light .list-search-result:highlighted,
+.overview-components-light .search-provider-icon:hover,
+.overview-components-light .search-provider-icon:focus,
+.overview-components-light .page-navigation-arrow:hover,
+.overview-components-light .page-navigation-arrow:focus,
+.overview-components-light .app-folder-dialog .icon-button:hover,
+.overview-components-light .app-folder-dialog .icon-button:focus,
+.overview-components-light #dash .overview-tile:hover .overview-icon,
+.overview-components-light #dash .overview-tile:focus .overview-icon,
+.overview-components-light #dash .show-apps:hover .overview-icon,
+.overview-components-light #dash .show-apps:focus .overview-icon {
+ background-color: rgba(230, 230, 230, 0.2);
+}
+
+.overview-components-light .overview-tile:active,
+.overview-components-light .overview-tile:focus:hover,
+.overview-components-light .overview-tile:drop,
+.overview-components-light .overview-tile:selected:hover,
+.overview-components-light .overview-tile:highlighted:hover,
+.overview-components-light .grid-search-result:active,
+.overview-components-light .grid-search-result:focus:hover,
+.overview-components-light .grid-search-result:selected:hover,
+.overview-components-light .grid-search-result:highlighted:hover,
+.overview-components-light .list-search-result:active,
+.overview-components-light .list-search-result:focus:hover,
+.overview-components-light .list-search-result:selected:hover,
+.overview-components-light .list-search-result:highlighted:hover,
+.overview-components-light .search-provider-icon:active,
+.overview-components-light .search-provider-icon:focus:hover,
+.overview-components-light .page-navigation-arrow:active,
+.overview-components-light .page-navigation-arrow:focus:hover,
+.overview-components-light .app-folder-dialog .icon-button:active,
+.overview-components-light .app-folder-dialog .icon-button:focus:hover,
+.overview-components-light #dash .overview-tile:active .overview-icon,
+.overview-components-light #dash .overview-tile:focus:hover .overview-icon,
+.overview-components-light #dash .overview-tile:drop .overview-icon,
+.overview-components-light #dash .show-apps:checked .overview-icon {
+ background-color: rgba(230, 230, 230, 0.25);
+}
+
+.overview-components-light .overview-tile:focus:active,
+.overview-components-light .overview-tile:selected:active,
+.overview-components-light .overview-tile:highlighted:active,
+.overview-components-light .grid-search-result:focus:active,
+.overview-components-light .grid-search-result:selected:active,
+.overview-components-light .grid-search-result:highlighted:active,
+.overview-components-light .list-search-result:focus:active,
+.overview-components-light .list-search-result:selected:active,
+.overview-components-light .list-search-result:highlighted:active,
+.overview-components-light .search-provider-icon:focus:active,
+.overview-components-light .page-navigation-arrow:focus:active,
+.overview-components-light .app-folder-dialog .icon-button:focus:active,
+.overview-components-light #dash .show-apps:checked .overview-icon:hover {
+ background-color: rgba(230, 230, 230, 0.3);
+}
+
+
+/*
+* `.overview-components-dark`
+*/
+
+.overview-components-dark .search-entry {
+ color: white;
+ background-color: rgba(100, 100, 100, 0.35);
+ border-color: transparent;
+ box-shadow: none;
+}
+
+.overview-components-dark .search-entry .search-entry-icon {
+ color: rgba(255, 255, 255, 0.65);
+}
+
+.overview-components-dark .overview-tile,
+.overview-components-dark .overview-icon,
+.overview-components-dark .grid-search-result,
+.overview-components-dark .list-search-result,
+.overview-components-dark .search-provider-icon,
+/* prevents the extension from interfering with Just Perfection */
+.overview-components-dark.just-perfection .search-section-content,
+/* remove the rectangular background from the dash */
+.overview-components-dark #dash .overview-tile,
+.overview-components-dark #dashtopanelScrollview .overview-tile {
+ background-color: transparent;
+}
+
+.overview-components-dark .workspace-thumbnail,
+.overview-components-dark .search-section-content,
+.overview-components-dark .overview-tile.app-folder,
+.overview-components-dark .page-navigation-arrow,
+.overview-components-dark .app-folder-dialog .icon-button,
+/* this shouldn't apply to Dash to Dock */
+.overview-components-dark StBoxLayout>StWidget>#dash>.dash-background {
+ background-color: rgba(100, 100, 100, 0.35);
+}
+
+.overview-components-dark .overview-tile:hover,
+.overview-components-dark .overview-tile:focus,
+.overview-components-dark .overview-tile:selected,
+.overview-components-dark .overview-tile:highlighted,
+.overview-components-dark .grid-search-result:hover,
+.overview-components-dark .grid-search-result:focus,
+.overview-components-dark .grid-search-result:selected,
+.overview-components-dark .grid-search-result:highlighted,
+.overview-components-dark .list-search-result:hover,
+.overview-components-dark .list-search-result:focus,
+.overview-components-dark .list-search-result:selected,
+.overview-components-dark .list-search-result:highlighted,
+.overview-components-dark .search-provider-icon:hover,
+.overview-components-dark .search-provider-icon:focus,
+.overview-components-dark .page-navigation-arrow:hover,
+.overview-components-dark .page-navigation-arrow:focus,
+.overview-components-dark .app-folder-dialog .icon-button:hover,
+.overview-components-dark .app-folder-dialog .icon-button:focus,
+.overview-components-dark #dash .overview-tile:hover .overview-icon,
+.overview-components-dark #dash .overview-tile:focus .overview-icon,
+.overview-components-dark #dash .show-apps:hover .overview-icon,
+.overview-components-dark #dash .show-apps:focus .overview-icon {
+ background-color: rgba(120, 120, 120, 0.35);
+}
+
+.overview-components-dark .overview-tile:active,
+.overview-components-dark .overview-tile:focus:hover,
+.overview-components-dark .overview-tile:drop,
+.overview-components-dark .overview-tile:selected:hover,
+.overview-components-dark .overview-tile:highlighted:hover,
+.overview-components-dark .grid-search-result:active,
+.overview-components-dark .grid-search-result:focus:hover,
+.overview-components-dark .grid-search-result:selected:hover,
+.overview-components-dark .grid-search-result:highlighted:hover,
+.overview-components-dark .list-search-result:active,
+.overview-components-dark .list-search-result:focus:hover,
+.overview-components-dark .list-search-result:selected:hover,
+.overview-components-dark .list-search-result:highlighted:hover,
+.overview-components-dark .search-provider-icon:active,
+.overview-components-dark .search-provider-icon:focus:hover,
+.overview-components-dark .page-navigation-arrow:active,
+.overview-components-dark .page-navigation-arrow:focus:hover,
+.overview-components-dark .app-folder-dialog .icon-button:active,
+.overview-components-dark .app-folder-dialog .icon-button:focus:hover,
+.overview-components-dark #dash .overview-tile:active .overview-icon,
+.overview-components-dark #dash .overview-tile:focus:hover .overview-icon,
+.overview-components-dark #dash .overview-tile:drop .overview-icon,
+.overview-components-dark #dash .show-apps:checked .overview-icon {
+ background-color: rgba(120, 120, 120, 0.4);
+}
+
+.overview-components-dark .overview-tile:focus:active,
+.overview-components-dark .overview-tile:selected:active,
+.overview-components-dark .overview-tile:highlighted:active,
+.overview-components-dark .grid-search-result:focus:active,
+.overview-components-dark .grid-search-result:selected:active,
+.overview-components-dark .grid-search-result:highlighted:active,
+.overview-components-dark .list-search-result:focus:active,
+.overview-components-dark .list-search-result:selected:active,
+.overview-components-dark .list-search-result:highlighted:active,
+.overview-components-dark .search-provider-icon:focus:active,
+.overview-components-dark .page-navigation-arrow:focus:active,
+.overview-components-dark .app-folder-dialog .icon-button:focus:active,
+.overview-components-dark #dash .show-apps:checked .overview-icon:hover {
+ background-color: rgba(120, 120, 120, 0.45);
+}
+
+
+/*** APPFOLDER DIALOG ***/
+
+/*
+* `.appfolder-dialogs-transparent`
+*/
+
+.appfolder-dialogs-transparent {
+ background-color: rgba(0, 0, 0, 0);
+ border: none;
+ box-shadow: none;
+}
+
+.appfolder-dialogs-transparent .folder-name-entry {
+ color: white;
+ background-color: rgba(0, 0, 0, 0);
+ border: 0;
+ box-shadow: none;
+}
+
+/*
+* `.appfolder-dialogs-light`
+*/
+
+.appfolder-dialogs-light {
+ background-color: rgba(200, 200, 200, 0.2);
+ border: none;
+ box-shadow: none;
+}
+
+.appfolder-dialogs-light .folder-name-entry {
+ color: white;
+ background-color: rgba(200, 200, 200, 0.2);
+ border: 0;
+ box-shadow: none;
+}
+
+
+/*
+* `.appfolder-dialogs-dark`
+*/
+
+.appfolder-dialogs-dark {
+ background-color: rgba(100, 100, 100, 0.35);
+ border: none;
+ box-shadow: none;
+}
+
+.appfolder-dialogs-dark .folder-name-entry {
+ color: white;
+ background-color: rgba(100, 100, 100, 0.35);
+ border: 0;
+ box-shadow: none;
+}
+
+
+/*** PANEL LIGHT TEXT ***/
+
+/*
+* `.panel-light-text`, adapted from gnome-shell-light.css
+*/
+
+#panel.panel-light-text .panel-button,
+#panel.panel-light-text .panel-button.clock-display,
+#panel.panel-light-text .netSpeedLabel {
+ color: #f6f5f4;
+ box-shadow: none;
+}
+
+#panel.panel-light-text .panel-button:active,
+#panel.panel-light-text .panel-button:focus,
+#panel.panel-light-text .panel-button:checked,
+#panel.panel-light-text .panel-button.clock-display:active .clock,
+#panel.panel-light-text .panel-button.clock-display:focus .clock,
+#panel.panel-light-text .panel-button.clock-display:checked .clock {
+ box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.25);
+}
+
+#panel.panel-light-text .panel-button:active:hover,
+#panel.panel-light-text .panel-button:focus:hover,
+#panel.panel-light-text .panel-button:checked:hover,
+#panel.panel-light-text .panel-button.clock-display:active:hover,
+#panel.panel-light-text .panel-button.clock-display:focus:hover,
+#panel.panel-light-text .panel-button.clock-display:checked:hover,
+#panel.panel-light-text .panel-button.clock-display:active .clock:hover,
+#panel.panel-light-text .panel-button.clock-display:focus .clock:hover,
+#panel.panel-light-text .panel-button.clock-display:checked .clock:hover {
+ box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.35);
+}
+
+#panel.panel-light-text .panel-button:hover,
+#panel.panel-light-text .panel-button.clock-display:hover,
+#panel.panel-light-text .panel-button.clock-display:hover .clock {
+ box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.2);
+}
+
+#panel.panel-light-text .panel-button#panelActivities .workspace-dot {
+ background-color: #f6f5f4;
+}
+
+#panel.panel-light-text .panel-button.clock-display:active,
+#panel.panel-light-text .panel-button.clock-display:focus,
+#panel.panel-light-text .panel-button.clock-display:checked,
+#panel.panel-light-text .panel-button.clock-display:hover {
+ box-shadow: none !important;
+}
+
+#panel.panel-light-text .panel-button.screen-recording-indicator {
+ color: #f6f5f4;
+ box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.8);
+}
+
+#panel.panel-light-text .panel-button.screen-recording-indicator:active,
+#panel.panel-light-text .panel-button.screen-recording-indicator:focus,
+#panel.panel-light-text .panel-button.screen-recording-indicator:checked {
+ box-shadow: inset 0 0 0 100px #c01c28;
+}
+
+#panel.panel-light-text .panel-button.screen-recording-indicator:active:hover,
+#panel.panel-light-text .panel-button.screen-recording-indicator:focus:hover,
+#panel.panel-light-text .panel-button.screen-recording-indicator:checked:hover {
+ box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.95);
+}
+
+#panel.panel-light-text .panel-button.screen-recording-indicator:hover {
+ box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.9);
+}
+
+#panel.panel-light-text .panel-button.screen-sharing-indicator {
+ color: #282828;
+ box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.8);
+}
+
+#panel.panel-light-text .panel-button.screen-sharing-indicator:active,
+#panel.panel-light-text .panel-button.screen-sharing-indicator:focus,
+#panel.panel-light-text .panel-button.screen-sharing-indicator:checked {
+ box-shadow: inset 0 0 0 100px #ff7800;
+}
+
+#panel.panel-light-text .panel-button.screen-sharing-indicator:active:hover,
+#panel.panel-light-text .panel-button.screen-sharing-indicator:focus:hover,
+#panel.panel-light-text .panel-button.screen-sharing-indicator:checked:hover {
+ box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.95);
+}
+
+#panel.panel-light-text .panel-button.screen-sharing-indicator:hover {
+ box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.9);
+} \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/application-row.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/application-row.ui
new file mode 100644
index 0000000..2a26d14
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/application-row.ui
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="ApplicationRow" parent="AdwExpanderRow">
+ <property name="title" translatable="yes">Window Name</property>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Select window</property>
+ <property name="subtitle" translatable="yes">Pick a window or select it by its classname.</property>
+
+ <child>
+ <object class="GtkBox" id="window_selector">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">175px</property>
+ <style>
+ <class name="linked" />
+ </style>
+
+ <child>
+ <object class="GtkButton" id="window_picker">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="icon-name">select-window-symbolic</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkEntry" id="window_class">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="AdwToast" id="picking_failure_toast">
+ <property name="title">Could not pick window, make sure that the extension is enabled.</property>
+ </object>
+
+ <object class="AdwToast" id="window_not_found_toast">
+ <property name="title">Could not pick window from here, does not seem like a valid window.</property>
+ </object>
+</interface> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/applications.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/applications.ui
new file mode 100644
index 0000000..14c9364
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/applications.ui
@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="Applications" parent="AdwPreferencesPage">
+ <property name="name">applications</property>
+ <property name="title" translatable="yes">Applications</property>
+ <property name="icon-name">applications-symbolic</property>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Applications blur</property>
+ <property name="description" translatable="yes">Adds blur to the applications.
+To get the best results possible, although with reduced performances, you can choose the option “No artifact” in the “Other → Hack level” tab.</property>
+ <property name="header-suffix">
+ <object class="GtkSwitch" id="blur">
+ <property name="valign">center</property>
+ </object>
+ </property>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Blur type</property>
+ <property name="subtitle" translatable="yes">The dynamic blur is slower and only compatible with a gaussian blur effect, but shows content behind windows.</property>
+ <property name="activatable-widget">blur_mode_choose</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkBox" id="blur_mode_choose">
+ <property name="valign">center</property>
+ <property name="hexpand">false</property>
+ <style>
+ <class name="linked" />
+ </style>
+
+ <child>
+ <object class="GtkToggleButton" id="mode_static">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="group">mode_dynamic</property>
+ <property name="child">
+ <object class="AdwButtonContent">
+ <property name="icon-name">static-mode-symbolic</property>
+ <property name="label" translatable="yes">Static</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="mode_dynamic">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="child">
+ <object class="AdwButtonContent">
+ <property name="icon-name">dynamic-mode-symbolic</property>
+ <property name="label" translatable="yes">Dynamic</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="PipelineChooseRow" id="pipeline_choose_row">
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="sigma_row">
+ <property name="title" translatable="yes">Sigma</property>
+ <property name="subtitle" translatable="yes">The intensity of the blur.</property>
+ <property name="activatable-widget">sigma_scale</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="sigma_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">0</property>
+ <property name="adjustment">sigma</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="brightness_row">
+ <property name="title" translatable="yes">Brightness</property>
+ <property name="subtitle" translatable="yes">The brightness of the blur effect, a high value might make the text harder to read.</property>
+ <property name="activatable-widget">brightness_scale</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="brightness_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">2</property>
+ <property name="adjustment">brightness</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Opacity</property>
+ <property name="subtitle" translatable="yes">The opacity of the window on top of the blur effect, a higher value will be more legible.</property>
+ <property name="activatable-widget">opacity_scale</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="opacity_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="orientation">horizontal</property>
+ <property name="digits">0</property>
+ <property name="adjustment">opacity</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Opaque focused window</property>
+ <property name="subtitle" translatable="yes">Makes the focused window opaque and the other ones blurred, helping with legibility.</property>
+ <property name="activatable-widget">dynamic_opacity</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkSwitch" id="dynamic_opacity">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Blur on overview</property>
+ <property name="subtitle" translatable="yes">Forces the blur to be properly shown on all workspaces on overview.
+This may cause some latency or performance issues.</property>
+ <property name="activatable-widget">blur_on_overview</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkSwitch" id="blur_on_overview">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Enable all by default</property>
+ <property name="subtitle" translatable="yes">Adds blur behind all windows by default.</property>
+ <property name="activatable-widget">enable_all</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkSwitch" id="enable_all">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="whitelist">
+ <property name="title" translatable="yes">Whitelist</property>
+ <property name="description" translatable="yes">A list of windows to blur.
+Use * to match any sequence of characters (e.g., Firefox* or *Code*), and ? for a single one.</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+ <property name="header-suffix">
+ <object class="GtkButton" id="add_window_whitelist">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <child>
+ <object class="GtkImage">
+ <property name="margin-end">6</property>
+ <property name="icon-name">add-row-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Add Window</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="circular" />
+ <class name="suggested-action" />
+ </style>
+ </object>
+ </property>
+
+ <!-- WINDOW ROW WIDGETS GO HERE -->
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup" id="blacklist">
+ <property name="title" translatable="yes">Blacklist</property>
+ <property name="description" translatable="yes">A list of windows not to blur.
+Use * to match any sequence of characters (e.g., Firefox* or *Code*), and ? for a single one.</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+ <property name="header-suffix">
+ <object class="GtkButton" id="add_window_blacklist">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <child>
+ <object class="GtkImage">
+ <property name="margin-end">6</property>
+ <property name="icon-name">add-row-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Add Window</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="circular" />
+ <class name="suggested-action" />
+ </style>
+ </object>
+ </property>
+
+ <!-- WINDOW ROW WIDGETS GO HERE -->
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkAdjustment" id="sigma">
+ <property name="lower">0</property>
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ </object>
+
+ <object class="GtkAdjustment" id="brightness">
+ <property name="lower">0.0</property>
+ <property name="upper">1.0</property>
+ <property name="step-increment">0.01</property>
+ </object>
+
+ <object class="GtkAdjustment" id="opacity">
+ <property name="lower">25</property>
+ <property name="upper">255</property>
+ <property name="step-increment">1</property>
+ </object>
+</interface>
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/dash.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/dash.ui
new file mode 100644
index 0000000..b08a4d1
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/dash.ui
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="Dash" parent="AdwPreferencesPage">
+ <property name="name">dash</property>
+ <property name="title" translatable="yes">Dash</property>
+ <property name="icon-name">dash-symbolic</property>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Dash to Dock blur</property>
+ <property name="description" translatable="yes">Blur the background of the Dash to Dock extension, if it is used.</property>
+ <property name="header-suffix">
+ <object class="GtkSwitch" id="blur">
+ <property name="valign">center</property>
+ </object>
+ </property>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Blur type</property>
+ <property name="subtitle" translatable="yes">The dynamic blur is slower and only compatible with a gaussian blur effect.</property>
+ <property name="activatable-widget">blur_mode_choose</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkBox" id="blur_mode_choose">
+ <property name="valign">center</property>
+ <property name="hexpand">false</property>
+ <style>
+ <class name="linked" />
+ </style>
+
+ <child>
+ <object class="GtkToggleButton" id="mode_static">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="group">mode_dynamic</property>
+ <property name="child">
+ <object class="AdwButtonContent">
+ <property name="icon-name">static-mode-symbolic</property>
+ <property name="label" translatable="yes">Static</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="mode_dynamic">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="child">
+ <object class="AdwButtonContent">
+ <property name="icon-name">dynamic-mode-symbolic</property>
+ <property name="label" translatable="yes">Dynamic</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="PipelineChooseRow" id="pipeline_choose_row">
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="sigma_row">
+ <property name="title" translatable="yes">Sigma</property>
+ <property name="subtitle" translatable="yes">The intensity of the blur.</property>
+ <property name="activatable-widget">sigma_scale</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="sigma_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">0</property>
+ <property name="adjustment">sigma</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="brightness_row">
+ <property name="title" translatable="yes">Brightness</property>
+ <property name="subtitle" translatable="yes">The brightness of the blur effect, a high value might make the text harder to read.</property>
+ <property name="activatable-widget">brightness_scale</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="brightness_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">2</property>
+ <property name="adjustment">brightness</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwExpanderRow" id="override_background">
+ <property name="title" translatable="yes">Override background</property>
+ <property name="subtitle" translatable="yes">Makes the background either transparent or semi-transparent, disable this to use Dash to Dock preferences instead.</property>
+ <property name="show-enable-switch">true</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Background style</property>
+ <property name="subtitle" translatable="yes">The transparent/semi-transparent style for the dock background.</property>
+ <property name="activatable-widget">style_dash_to_dock</property>
+
+ <child>
+ <object class="GtkDropDown" id="style_dash_to_dock">
+ <property name="valign">center</property>
+ <property name="model">style_dash_to_dock_model</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Disable in overview</property>
+ <property name="subtitle" translatable="yes">Disables the blur from Dash to Dock when entering the overview.</property>
+ <property name="activatable-widget">unblur_in_overview</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkSwitch" id="unblur_in_overview">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkAdjustment" id="sigma">
+ <property name="lower">0</property>
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ </object>
+
+ <object class="GtkAdjustment" id="brightness">
+ <property name="lower">0.0</property>
+ <property name="upper">1.0</property>
+ <property name="step-increment">0.01</property>
+ </object>
+
+ <object class="GtkStringList" id="style_dash_to_dock_model">
+ <items>
+ <item translatable="yes">Transparent</item>
+ <item translatable="yes">Light</item>
+ <item translatable="yes">Dark</item>
+ </items>
+ </object>
+</interface> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/effects-dialog.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/effects-dialog.ui
new file mode 100644
index 0000000..c6baf62
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/effects-dialog.ui
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="EffectsDialog" parent="AdwPreferencesDialog">
+ <property name="title" translatable="yes">Effects</property>
+ <property name="presentation-mode">ADW_DIALOG_BOTTOM_SHEET</property>
+ <property name="content-width">600</property>
+ <property name="content-height">480</property>
+
+ <child>
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup" id="effects_list">
+ <property name="title">Effects list</property>
+ <property name="description">Effect on the top will be applied first.</property>
+
+ <property name="header-suffix">
+ <object class="GtkBox">
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <style>
+ <class name="linked" />
+ </style>
+ <child>
+ <object class="GtkButton" id="add_effect">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <child>
+ <object class="GtkImage">
+ <property name="margin-end">6</property>
+ <property name="icon-name">list-add-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Add Effect</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="circular" />
+ <class name="suggested-action" />
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkMenuButton" id="add_effect_alt_menu">
+ <property name="valign">center</property>
+ <property name="icon-name">down-symbolic</property>
+ <property name="menu-model">add_effect_alt_menu_model</property>
+ <style>
+ <class name="circular" />
+ </style>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <menu id="add_effect_alt_menu_model">
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Include advanced effects</attribute>
+ <attribute name="action">effects-dialog.advanced-effects-bool</attribute>
+ </item>
+ </section>
+ </menu>
+</interface> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/menu.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/menu.ui
new file mode 100644
index 0000000..6d2a474
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/menu.ui
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <menu id="info_menu_model">
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Project page</attribute>
+ <attribute name="action">prefs.open-readme</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Report a Bug</attribute>
+ <attribute name="action">prefs.open-bug-report</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">License</attribute>
+ <attribute name="action">prefs.open-license</attribute>
+ </item>
+ <submenu>
+ <attribute name="label" translatable="yes">Donate</attribute>
+ <item>
+ <attribute name="label">GitHub</attribute>
+ <attribute name="action">prefs.donate-github</attribute>
+ </item>
+ <item>
+ <attribute name="label">Ko-fi</attribute>
+ <attribute name="action">prefs.donate-kofi</attribute>
+ </item>
+ </submenu>
+ </section>
+ </menu>
+
+ <object class="GtkMenuButton" id="info_menu">
+ <property name="menu-model">info_menu_model</property>
+ <property name="icon-name">heart-symbolic</property>
+ </object>
+
+ <object class="AdwPreferencesPage" id="menu_util"></object>
+</interface> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/other.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/other.ui
new file mode 100644
index 0000000..e136e38
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/other.ui
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="Other" parent="AdwPreferencesPage">
+ <property name="name">other</property>
+ <property name="title" translatable="yes">Other</property>
+ <property name="icon-name">other-symbolic</property>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Lockscreen blur</property>
+ <property name="description" translatable="yes">Change the blur of the lockscreen to use this extension's preferences.</property>
+ <property name="header-suffix">
+ <object class="GtkSwitch" id="lockscreen_blur">
+ <property name="valign">center</property>
+ </object>
+ </property>
+
+ <child>
+ <object class="PipelineChooseRow" id="lockscreen_pipeline_choose_row">
+ <property name="sensitive" bind-source="lockscreen_blur" bind-property="state" bind-flags="sync-create" />
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Screenshot blur</property>
+ <property name="description" translatable="yes">Add blur to the background of the window selector in the screenshot UI.</property>
+ <property name="header-suffix">
+ <object class="GtkSwitch" id="screenshot_blur">
+ <property name="valign">center</property>
+ </object>
+ </property>
+
+ <child>
+ <object class="PipelineChooseRow" id="screenshot_pipeline_choose_row">
+ <property name="sensitive" bind-source="screenshot_blur" bind-property="state" bind-flags="sync-create" />
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Window list extension blur</property>
+ <property name="description" translatable="yes">Make the window-list extension blurred, if it is used.</property>
+ <property name="header-suffix">
+ <object class="GtkSwitch" id="window_list_blur">
+ <property name="valign">center</property>
+ </object>
+ </property>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Sigma</property>
+ <property name="subtitle" translatable="yes">The intensity of the blur.</property>
+ <property name="activatable-widget">window_list_sigma_scale</property>
+ <property name="sensitive" bind-source="window_list_blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="window_list_sigma_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">0</property>
+ <property name="adjustment">window_list_sigma</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Brightness</property>
+ <property name="subtitle" translatable="yes">The brightness of the blur effect, a high value might make the text harder to read.</property>
+ <property name="activatable-widget">window_list_brightness_scale</property>
+ <property name="sensitive" bind-source="window_list_blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="window_list_brightness_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">2</property>
+ <property name="adjustment">window_list_brightness</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Coverflow Alt-Tab extension blur</property>
+ <property name="description" translatable="yes">Make the coverflow alt-tab extension blurred, if it is used.</property>
+ <property name="header-suffix">
+ <object class="GtkSwitch" id="coverflow_alt_tab_blur">
+ <property name="valign">center</property>
+ </object>
+ </property>
+
+ <child>
+ <object class="PipelineChooseRow" id="coverflow_alt_tab_pipeline_choose_row">
+ <property name="sensitive" bind-source="coverflow_alt_tab_blur" bind-property="state" bind-flags="sync-create" />
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Performance</property>
+ <property name="description" translatable="yes">Various options to tweak the performance.</property>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Hack level</property>
+ <property name="subtitle" translatable="yes">Changes the behaviour of the dynamic blur effect. The default value is highly recommended.
+The “No artifact” option will entirely disable clipped redraws in GNOME shell, and will impact your computer performances significantly.</property>
+ <property name="activatable-widget">hack_level</property>
+ <child>
+ <object class="GtkDropDown" id="hack_level">
+ <property name="valign">center</property>
+ <property name="model">hack_level_model</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Debug</property>
+ <property name="subtitle" translatable="yes">Makes the extension verbose in logs, activate when you need to report an issue.</property>
+ <property name="activatable-widget">debug</property>
+ <child>
+ <object class="GtkSwitch" id="debug">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Reset preferences</property>
+ <property name="description" translatable="yes">Resets preferences of Blur my Shell irreversibly.</property>
+ <property name="header-suffix">
+ <object class="GtkButton" id="reset">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-start">20</property>
+ <property name="margin-end">20</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <child>
+ <object class="GtkImage">
+ <property name="margin-end">6</property>
+ <property name="icon-name">reset-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Reset</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="circular" />
+ <class name="destructive-action" />
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkAdjustment" id="window_list_sigma">
+ <property name="lower">0</property>
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ </object>
+
+ <object class="GtkAdjustment" id="window_list_brightness">
+ <property name="lower">0.0</property>
+ <property name="upper">1.0</property>
+ <property name="step-increment">0.01</property>
+ </object>
+
+ <object class="GtkStringList" id="hack_level_model">
+ <items>
+ <item translatable="yes">High performances</item>
+ <item translatable="yes">Default</item>
+ <item translatable="yes">No artifact</item>
+ </items>
+ </object>
+</interface> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/overview.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/overview.ui
new file mode 100644
index 0000000..36b91fc
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/overview.ui
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="Overview" parent="AdwPreferencesPage">
+ <property name="name">overview</property>
+ <property name="title" translatable="yes">Overview</property>
+ <property name="icon-name">overview-symbolic</property>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Background blur</property>
+ <property name="description" translatable="yes">Add blur to the overview background, using the wallpaper picture.</property>
+ <property name="header-suffix">
+ <object class="GtkSwitch" id="overview_blur">
+ <property name="valign">center</property>
+ </object>
+ </property>
+
+ <child>
+ <object class="PipelineChooseRow" id="pipeline_choose_row">
+ <property name="sensitive" bind-source="overview_blur" bind-property="state" bind-flags="sync-create" />
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Overview components style</property>
+ <property name="subtitle" translatable="yes">The semi-transparent style for the dash, search entry/results, and application folders.</property>
+ <property name="sensitive" bind-source="overview_blur" bind-property="state" bind-flags="sync-create" />
+ <property name="activatable-widget">overview_style_components</property>
+
+ <child>
+ <object class="GtkDropDown" id="overview_style_components">
+ <property name="valign">center</property>
+ <property name="model">overview_style_components_model</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Application folder blur</property>
+ <property name="description" translatable="yes">Makes the background of application folder dialogs blurred.</property>
+ <property name="header-suffix">
+ <object class="GtkSwitch" id="appfolder_blur">
+ <property name="valign">center</property>
+ </object>
+ </property>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Sigma</property>
+ <property name="subtitle" translatable="yes">The intensity of the blur.</property>
+ <property name="activatable-widget">appfolder_sigma_scale</property>
+ <property name="sensitive" bind-source="appfolder_blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="appfolder_sigma_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">0</property>
+ <property name="adjustment">appfolder_sigma</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Brightness</property>
+ <property name="subtitle" translatable="yes">The brightness of the blur effect, a high value might make the text harder to read.</property>
+ <property name="activatable-widget">appfolder_brightness_scale</property>
+ <property name="sensitive" bind-source="appfolder_blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="appfolder_brightness_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">2</property>
+ <property name="adjustment">appfolder_brightness</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Application folder dialogs style</property>
+ <property name="subtitle" translatable="yes">The semi-transparent style for the application folder dialogs.</property>
+ <property name="sensitive" bind-source="appfolder_blur" bind-property="state" bind-flags="sync-create" />
+ <property name="activatable-widget">appfolder_style_dialogs</property>
+
+ <child>
+ <object class="GtkDropDown" id="appfolder_style_dialogs">
+ <property name="valign">center</property>
+ <property name="model">appfolder_style_dialogs_model</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkStringList" id="overview_style_components_model">
+ <items>
+ <item translatable="yes">Do not style</item>
+ <item translatable="yes">Light</item>
+ <item translatable="yes">Dark</item>
+ <item translatable="yes">Transparent</item>
+ </items>
+ </object>
+
+ <object class="GtkAdjustment" id="appfolder_sigma">
+ <property name="lower">0</property>
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ </object>
+
+ <object class="GtkAdjustment" id="appfolder_brightness">
+ <property name="lower">0.0</property>
+ <property name="upper">1.0</property>
+ <property name="step-increment">0.01</property>
+ </object>
+
+
+ <object class="GtkStringList" id="appfolder_style_dialogs_model">
+ <items>
+ <item translatable="yes">Do not style</item>
+ <item translatable="yes">Transparent</item>
+ <item translatable="yes">Light</item>
+ <item translatable="yes">Dark</item>
+ </items>
+ </object>
+</interface> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/panel.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/panel.ui
new file mode 100644
index 0000000..306f4ef
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/panel.ui
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="Panel" parent="AdwPreferencesPage">
+ <property name="name">panel</property>
+ <property name="title" translatable="yes">Panel</property>
+ <property name="icon-name">bottom-panel-symbolic</property>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Panel blur</property>
+ <property name="description" translatable="yes">Blur the top panel using the background image.</property>
+ <property name="header-suffix">
+ <object class="GtkSwitch" id="blur">
+ <property name="valign">center</property>
+ </object>
+ </property>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Blur type</property>
+ <property name="subtitle" translatable="yes">The dynamic blur is slower and only compatible with a gaussian blur effect.</property>
+ <property name="activatable-widget">blur_mode_choose</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkBox" id="blur_mode_choose">
+ <property name="valign">center</property>
+ <property name="hexpand">false</property>
+ <style>
+ <class name="linked" />
+ </style>
+
+ <child>
+ <object class="GtkToggleButton" id="mode_static">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="group">mode_dynamic</property>
+ <property name="child">
+ <object class="AdwButtonContent">
+ <property name="icon-name">static-mode-symbolic</property>
+ <property name="label" translatable="yes">Static</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="mode_dynamic">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="child">
+ <object class="AdwButtonContent">
+ <property name="icon-name">dynamic-mode-symbolic</property>
+ <property name="label" translatable="yes">Dynamic</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="PipelineChooseRow" id="pipeline_choose_row">
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="sigma_row">
+ <property name="title" translatable="yes">Sigma</property>
+ <property name="subtitle" translatable="yes">The intensity of the blur.</property>
+ <property name="activatable-widget">sigma_scale</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="sigma_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">0</property>
+ <property name="adjustment">sigma</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="brightness_row">
+ <property name="title" translatable="yes">Brightness</property>
+ <property name="subtitle" translatable="yes">The brightness of the blur effect, a high value might make the text harder to read.</property>
+ <property name="activatable-widget">brightness_scale</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkScale" id="brightness_scale">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="width-request">200px</property>
+ <property name="draw-value">true</property>
+ <property name="value-pos">right</property>
+ <property name="digits">2</property>
+ <property name="adjustment">brightness</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Force light text</property>
+ <property name="subtitle" translatable="yes">Use a light text for the panel, useful when using gnome-shell's light theme.</property>
+ <property name="activatable-widget">force_light_text</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkSwitch" id="force_light_text">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwExpanderRow" id="override_background">
+ <property name="title" translatable="yes">Override background</property>
+ <property name="subtitle" translatable="yes">Override the background of the panel to use a transparent or semi-transparent one.
+Recommended unless you want to customize your GNOME theme.</property>
+ <property name="show-enable-switch">true</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Background style</property>
+ <property name="subtitle" translatable="yes">The transparent/semi-transparent style for the panel background.</property>
+ <property name="activatable-widget">style_panel</property>
+
+ <child>
+ <object class="GtkDropDown" id="style_panel">
+ <property name="valign">center</property>
+ <property name="model">style_panel_model</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Disable when a window is near</property>
+ <property name="subtitle" translatable="yes">Disables the transparency of the panel when a window is near it.</property>
+ <property name="activatable-widget">override_background_dynamically</property>
+
+ <child>
+ <object class="GtkSwitch" id="override_background_dynamically">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Disable in overview</property>
+ <property name="subtitle" translatable="yes">Disables the blur from the panel when entering the overview.</property>
+ <property name="activatable-widget">unblur_in_overview</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkSwitch" id="unblur_in_overview">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Compatibility</property>
+ <property name="description" translatable="yes">Various options to provide compatibility with other extensions.</property>
+ <property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Hidetopbar extension</property>
+ <property name="subtitle" translatable="yes">Does not disable the blur in overview, best used with static blur.</property>
+ <property name="activatable-widget">hidetopbar_compatibility</property>
+ <property name="sensitive" bind-source="unblur_in_overview" bind-property="state" bind-flags="sync-create" />
+
+ <child>
+ <object class="GtkSwitch" id="hidetopbar_compatibility">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Blur original panel with Dash to Panel</property>
+ <property name="subtitle" translatable="yes">Enables the blurring of the original panel with Dash to Panel, if selected in the extension's options.</property>
+ <property name="activatable-widget">dtp_blur_original_panel</property>
+
+ <child>
+ <object class="GtkSwitch" id="dtp_blur_original_panel">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkStringList" id="style_panel_model">
+ <items>
+ <item translatable="yes">Transparent</item>
+ <item translatable="yes">Light</item>
+ <item translatable="yes">Dark</item>
+ <item translatable="yes">Contrasted</item>
+ </items>
+ </object>
+
+ <object class="GtkAdjustment" id="sigma">
+ <property name="lower">0</property>
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ </object>
+
+ <object class="GtkAdjustment" id="brightness">
+ <property name="lower">0.0</property>
+ <property name="upper">1.0</property>
+ <property name="step-increment">0.01</property>
+ </object>
+</interface> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipeline-choose-row.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipeline-choose-row.ui
new file mode 100644
index 0000000..72b854b
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipeline-choose-row.ui
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="PipelineChooseRow" parent="AdwActionRow">
+ <property name="title" translatable="yes">Pipeline</property>
+ <property name="subtitle" translatable="yes">The pipeline to be used with this component.</property>
+ <property name="activatable-widget">pipeline_choose</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="valign">center</property>
+ <property name="hexpand">false</property>
+ <style>
+ <class name="linked" />
+ </style>
+
+ <child>
+ <object class="GtkDropDown" id="pipeline_choose">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="model">
+ <object class="GtkStringList" id="pipeline_model">
+ <items>
+ </items>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkButton" id="pipeline_edit">
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="icon-name">edit-row-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipeline-group.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipeline-group.ui
new file mode 100644
index 0000000..19a12bf
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipeline-group.ui
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="PipelineGroup" parent="AdwPreferencesGroup">
+ <child>
+ <object class="AdwEntryRow" id="title">
+ <property name="title" translatable="yes">Pipeline name</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="AdwActionRow" id="effects_description_row">
+ <property name="activatable-widget">manage_effects</property>
+
+ <child>
+ <object class="GtkButton" id="manage_effects">
+ <property name="valign">center</property>
+ <property name="child">
+ <object class="AdwButtonContent">
+ <property name="icon-name">edit-row-symbolic</property>
+ <property name="label" translatable="yes">Manage effects</property>
+ <property name="use-underline">True</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface> \ No newline at end of file
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipelines.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipelines.ui
new file mode 100644
index 0000000..555ec0a
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/pipelines.ui
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="blur-my-shell@aunetx">
+ <template class="Pipelines" parent="AdwPreferencesPage">
+ <property name="name">pipelines</property>
+ <property name="title" translatable="yes">Pipelines</property>
+ <property name="icon-name">pipelines-symbolic</property>
+
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="description" translatable="yes">Each component uses a pipeline, which can be chosen in the corresponding tab. Here you can create, modify and delete the pipelines and their effects.</property>
+
+ <property name="header-suffix">
+ <object class="GtkButton" id="add_pipeline">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="margin-start">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <child>
+ <object class="GtkImage">
+ <property name="margin-end">6</property>
+ <property name="icon-name">list-add-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Add Pipeline</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="circular" />
+ <class name="suggested-action" />
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+
+ </template>
+</interface> \ No newline at end of file