From 9d5be1660d8f74038ebed3d74fdbc809e43787ae Mon Sep 17 00:00:00 2001 From: Nippy Date: Fri, 9 Oct 2026 17:23:53 +0200 Subject: gnome fix --- .../blur-my-shell@aunetx/components/appfolders.js | 87 ++- .../components/applications.js | 182 ++--- .../components/dash_to_dock.js | 382 ++++++--- .../blur-my-shell@aunetx/components/overview.js | 35 +- .../blur-my-shell@aunetx/components/panel.js | 406 +++++++--- .../blur-my-shell@aunetx/components/popup.js | 1 + .../components/popup/blur_surface.js | 484 ++++++++++++ .../blur-my-shell@aunetx/components/popup/index.js | 556 ++++++++++++++ .../components/popup/message_stacks.js | 571 ++++++++++++++ .../components/popup/static_actor.js | 301 ++++++++ .../components/popup/static_corner.js | 70 ++ .../components/popup/surface_fade.js | 132 ++++ .../components/popup/surface_geometry.js | 291 +++++++ .../components/popup/surface_placement.js | 328 ++++++++ .../components/popup/surface_signals.js | 117 +++ .../components/popup/surface_style.js | 59 ++ .../components/popup/surface_transitions.js | 139 ++++ .../components/popup/targets.js | 255 +++++++ .../blur-my-shell@aunetx/components/window_list.js | 8 +- .../conveniences/connections.js | 158 ++-- .../conveniences/dummy_pipeline.js | 49 +- .../conveniences/effects_manager.js | 68 +- .../blur-my-shell@aunetx/conveniences/keys.js | 23 + .../conveniences/paint_signals.js | 101 +-- .../blur-my-shell@aunetx/conveniences/pipeline.js | 187 ++++- .../conveniences/pipeline_settings.js | 136 ++++ .../conveniences/pipelines_manager.js | 56 +- .../blur-my-shell@aunetx/conveniences/settings.js | 180 +---- .../conveniences/shader_uniforms.js | 61 ++ .../blur-my-shell@aunetx/conveniences/utils.js | 108 ++- .../installed/blur-my-shell@aunetx/dbus/iface.xml | 12 - .../blur-my-shell@aunetx/dbus/services.js | 26 +- .../blur-my-shell@aunetx/effects/color.glsl | 16 +- .../blur-my-shell@aunetx/effects/color.js | 76 +- .../blur-my-shell@aunetx/effects/corner.glsl | 33 +- .../blur-my-shell@aunetx/effects/corner.js | 105 +-- .../blur-my-shell@aunetx/effects/derivative.glsl | 57 +- .../blur-my-shell@aunetx/effects/derivative.js | 73 +- .../blur-my-shell@aunetx/effects/downscale.glsl | 36 +- .../blur-my-shell@aunetx/effects/downscale.js | 80 +- .../blur-my-shell@aunetx/effects/effect_groups.js | 31 + .../blur-my-shell@aunetx/effects/effects.js | 175 ++++- .../effects/gaussian_blur.glsl | 29 +- .../blur-my-shell@aunetx/effects/gaussian_blur.js | 59 +- .../blur-my-shell@aunetx/effects/hsl_to_rgb.glsl | 5 +- .../blur-my-shell@aunetx/effects/hsl_to_rgb.js | 59 +- .../blur-my-shell@aunetx/effects/luminosity.glsl | 11 +- .../blur-my-shell@aunetx/effects/luminosity.js | 64 +- .../effects/monte_carlo_blur.glsl | 20 +- .../effects/monte_carlo_blur.js | 58 +- .../effects/native_dynamic_gaussian_blur.js | 54 +- .../effects/native_static_gaussian_blur.js | 19 +- .../blur-my-shell@aunetx/effects/noise.glsl | 12 +- .../blur-my-shell@aunetx/effects/noise.js | 58 +- .../blur-my-shell@aunetx/effects/pixelize.js | 49 +- .../blur-my-shell@aunetx/effects/refraction.glsl | 412 ++++++++++ .../blur-my-shell@aunetx/effects/refraction.js | 849 +++++++++++++++++++++ .../blur-my-shell@aunetx/effects/rgb_to_hsl.glsl | 5 +- .../blur-my-shell@aunetx/effects/rgb_to_hsl.js | 59 +- .../blur-my-shell@aunetx/effects/upscale.glsl | 26 +- .../blur-my-shell@aunetx/effects/upscale.js | 78 +- .../installed/blur-my-shell@aunetx/extension.js | 132 +++- .../hicolor/scalable/actions/popup-symbolic.svg | 3 + .../locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 17338 -> 23620 bytes .../locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 17426 -> 18261 bytes .../locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 17602 -> 17762 bytes .../locale/eo/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 367 -> 630 bytes .../locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 17198 -> 20791 bytes .../locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 17362 -> 20983 bytes .../locale/ga/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 1045 bytes .../locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 592 -> 584 bytes .../locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 16293 -> 19714 bytes .../locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 18237 -> 18553 bytes .../locale/ml/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 523 -> 515 bytes .../locale/mrh/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 521 -> 513 bytes .../locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 17158 -> 17176 bytes .../pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 16986 -> 20437 bytes .../locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 10058 -> 10222 bytes .../locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 22226 -> 22404 bytes .../locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 28451 -> 34125 bytes .../locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 21475 -> 25916 bytes .../zh_CN/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 15371 -> 15976 bytes .../installed/blur-my-shell@aunetx/metadata.json | 33 +- .../preferences/applications.js | 5 + .../blur-my-shell@aunetx/preferences/other.js | 4 +- .../blur-my-shell@aunetx/preferences/panel.js | 36 + .../pipelines_management/pipeline_choose_row.js | 7 +- .../blur-my-shell@aunetx/preferences/popup.js | 121 +++ .../installed/blur-my-shell@aunetx/prefs.js | 2 + .../blur-my-shell@aunetx/schemas/gschemas.compiled | Bin 10240 -> 0 bytes ...nome.shell.extensions.blur-my-shell.gschema.xml | 105 ++- .../blur-my-shell@aunetx/styles/appfolders.css | 55 ++ .../installed/blur-my-shell@aunetx/styles/dash.css | 26 + .../blur-my-shell@aunetx/styles/overview.css | 364 +++++++++ .../styles/panel-light-text.css | 92 +++ .../blur-my-shell@aunetx/styles/panel.css | 97 +++ .../blur-my-shell@aunetx/styles/popup/base.css | 729 ++++++++++++++++++ .../blur-my-shell@aunetx/styles/popup/dark.css | 258 +++++++ .../blur-my-shell@aunetx/styles/popup/light.css | 335 ++++++++ .../styles/popup/menu-items.css | 120 +++ .../styles/popup/transparent.css | 262 +++++++ .../installed/blur-my-shell@aunetx/stylesheet.css | 583 +------------- .../blur-my-shell@aunetx/ui/applications.ui | 19 +- .../installed/blur-my-shell@aunetx/ui/dash.ui | 2 +- .../installed/blur-my-shell@aunetx/ui/other.ui | 9 +- .../installed/blur-my-shell@aunetx/ui/panel.ui | 66 +- .../installed/blur-my-shell@aunetx/ui/popup.ui | 288 +++++++ 107 files changed, 10105 insertions(+), 1825 deletions(-) create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/blur_surface.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/index.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/message_stacks.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/static_actor.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/static_corner.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_fade.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_geometry.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_placement.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_signals.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_style.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_transitions.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/targets.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline_settings.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/shader_uniforms.js delete mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/iface.xml create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effect_groups.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/popup-symbolic.svg create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ga/LC_MESSAGES/blur-my-shell@aunetx.mo create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/popup.js delete mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/gschemas.compiled create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/appfolders.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/dash.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/overview.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/panel-light-text.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/panel.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/base.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/dark.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/light.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/menu-items.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/transparent.css create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/popup.ui (limited to 'raveos-gnome-theme/theme-data/extensions') 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 index 8824777..b04e39d 100644 --- 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 @@ -2,11 +2,8 @@ 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 ? @@ -30,6 +27,26 @@ let original_zoomAndFadeOut = null; let sigma; let brightness; +const BLUR_RADIUS_PROPERTY = '@effects.appfolder-blur.radius'; +const BLUR_BRIGHTNESS_PROPERTY = '@effects.appfolder-blur.brightness'; + +function stop_blur_animation(dialog) { + dialog.remove_transition(BLUR_RADIUS_PROPERTY); + dialog.remove_transition(BLUR_BRIGHTNESS_PROPERTY); +} + +function animate_blur(dialog, target, mode) { + stop_blur_animation(dialog); + dialog.ease_property(BLUR_RADIUS_PROPERTY, target.radius, { + duration: FOLDER_DIALOG_ANIMATION_TIME, + mode, + }); + dialog.ease_property(BLUR_BRIGHTNESS_PROPERTY, target.brightness, { + duration: FOLDER_DIALOG_ANIMATION_TIME, + mode, + }); +} + let _zoomAndFadeIn = function () { let [sourceX, sourceY] = this._source.get_transformed_position(); @@ -50,13 +67,10 @@ let _zoomAndFadeIn = function () { 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' - } + animate_blur( + this, + { radius: sigma * 2, brightness }, + Clutter.AnimationMode.EASE_OUT_QUAD ); this.child.ease({ @@ -93,14 +107,10 @@ let _zoomAndFadeOut = function () { 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' - } + animate_blur( + this, + { radius: 0, brightness: 1.0 }, + Clutter.AnimationMode.EASE_IN_QUAD ); this.child.ease({ @@ -172,15 +182,19 @@ export const AppFoldersBlur = class AppFoldersBlur { 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); + let blur_effect = icon._dialog.get_effect('appfolder-blur'); + if (!blur_effect) { + blur_effect = new Shell.BlurEffect({ + name: 'appfolder-blur', + radius: sigma * 2, + brightness, + mode: Shell.BlurMode.BACKGROUND, + }); + icon._dialog.add_effect(blur_effect); + } else { + stop_blur_animation(icon._dialog); + blur_effect.set({ radius: sigma * 2, brightness }); + } DIALOGS_STYLES.forEach( style => icon._dialog._viewBox.remove_style_class_name(style) @@ -218,19 +232,31 @@ export const AppFoldersBlur = class AppFoldersBlur { set_sigma(s) { sigma = s; if (this.settings.appfolder.BLUR) - this.blur_appfolders(); + this.update_blur_effects({ radius: sigma * 2 }); } set_brightness(b) { brightness = b; if (this.settings.appfolder.BLUR) - this.blur_appfolders(); + this.update_blur_effects({ brightness }); + } + + update_blur_effects(params) { + const appDisplay = Main.overview._overview.controls._appDisplay; + appDisplay._folderIcons.forEach(icon => { + if (!icon._dialog) + return; + + stop_blur_animation(icon._dialog); + icon._dialog.get_effect('appfolder-blur')?.set(params); + }); } disable() { this._log("removing blur from appfolders"); let appDisplay = Main.overview._overview.controls._appDisplay; + this.paint_signals.disconnect_all(); if (original_zoomAndFadeIn != null) { appDisplay._folderIcons.forEach(icon => { @@ -248,6 +274,7 @@ export const AppFoldersBlur = class AppFoldersBlur { appDisplay._folderIcons.forEach(icon => { if (icon._dialog) { + stop_blur_animation(icon._dialog); icon._dialog.remove_effect_by_name("appfolder-blur"); DIALOGS_STYLES.forEach( s => icon._dialog._viewBox.remove_style_class_name(s) @@ -262,4 +289,4 @@ export const AppFoldersBlur = class AppFoldersBlur { 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 index 5280b55..4711a0e 100644 --- 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 @@ -145,34 +145,23 @@ export const ApplicationsBlur = class ApplicationsBlur { /// shown on every window of the workspaces viewer. connect_to_overview() { this.connections.disconnect_all_for(Main.overview); + this.overview_visible = Main.overview.visible; - 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(); - }) - ); + const reconcile_windows = () => this.meta_window_map.forEach( + (meta_window, _pid) => this.reconcile_window_visibility(meta_window) + ); + this.connections.connect(Main.overview, 'showing', _ => { + this.overview_visible = true; + reconcile_windows(); + }); + this.connections.connect(Main.overview, 'hidden', _ => { + this.overview_visible = false; + reconcile_windows(); + }); - // 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(); - }); - } - ); - } + this.meta_window_map.forEach((meta_window, _pid) => + this.reconcile_window_visibility(meta_window) + ); } /// Iterate through all existing windows and add blur as needed. @@ -239,14 +228,14 @@ export const ApplicationsBlur = class ApplicationsBlur { 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; - } + if (window_actor) { + this.connections.connect(window_actor, 'child-added', _ => { + if (!meta_window.blur_actor) + return; - window_actor.set_child_below_sibling(meta_window.blur_actor, null); - }); + window_actor.set_child_below_sibling(meta_window.blur_actor, null); + }); + } } } @@ -375,19 +364,17 @@ export const ApplicationsBlur = class ApplicationsBlur { 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); + if (!this.settings.applications.BLUR_ON_OVERVIEW && Main.overview.visible) + blur_actor.hide(); // update the size this.update_size(pid); - // set the window actor's opacity - this.set_window_opacity(window_actor, this.settings.applications.OPACITY); - // update corner radius based on window state this.update_corner_radius(meta_window); + this.reconcile_window_visibility(meta_window); + // 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 @@ -403,15 +390,17 @@ export const ApplicationsBlur = class ApplicationsBlur { ); this.connections.connect( meta_window, 'notify::fullscreen', - _ => this.update_corner_radius(meta_window) + _ => { + this.update_corner_radius(meta_window); + this.reconcile_window_visibility(meta_window); + } ); // 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); + this.reconcile_window_visibility(meta_window); } ); @@ -422,12 +411,7 @@ export const ApplicationsBlur = class ApplicationsBlur { this.connections.connect( window_actor, 'notify::visible', - window_actor => { - if (window_actor.visible) - meta_window.blur_actor.show(); - else - meta_window.blur_actor.hide(); - } + _ => this.reconcile_window_visibility(meta_window) ); } @@ -435,57 +419,18 @@ export const ApplicationsBlur = class ApplicationsBlur { /// 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 + if (focus) 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); - } - } + else + this.focused_window_pid = null; - /// 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(); - } - } + this.meta_window_map.forEach((tracked_window, _pid) => + this.reconcile_window_visibility(tracked_window) ); } @@ -504,11 +449,38 @@ export const ApplicationsBlur = class ApplicationsBlur { }) } else { if (meta_window.bg_manager?._bms_pipeline?.effect) - meta_window.bg_manager._bms_pipeline.effect.corner_radius = use_0_radius ? + meta_window.bg_manager._bms_pipeline.effect.unscaled_corner_radius = use_0_radius ? 0 : this.settings.applications.CORNER_RADIUS; } } + reconcile_window_visibility(meta_window, overview_visible = this.overview_visible) { + const window_actor = meta_window.get_compositor_private(); + const blur_actor = meta_window.blur_actor; + if (!window_actor || !blur_actor) + return; + + const is_focused = this.settings.applications.DYNAMIC_OPACITY + && meta_window.bms_pid === this.focused_window_pid; + const is_fullscreen = this.settings.applications.UNBLUR_WHEN_FULLSCREEN + && meta_window.fullscreen; + const visible_for_blur = window_actor.visible + || (this.settings.applications.BLUR_ON_OVERVIEW && overview_visible); + const show_blur = visible_for_blur + && !is_focused + && !is_fullscreen + && (this.settings.applications.BLUR_ON_OVERVIEW || !overview_visible); + + if (show_blur) + blur_actor.show(); + else + blur_actor.hide(); + + this.set_window_opacity(window_actor, show_blur + ? this.settings.applications.OPACITY + : 255); + } + /// Update all corners, to use when the setting has been changed. update_all_corner_radii() { this.meta_window_map.forEach( @@ -516,24 +488,30 @@ export const ApplicationsBlur = class ApplicationsBlur { ) } + update_fullscreen_status() { + this.meta_window_map.forEach( + (meta_window, _pid) => this.reconcile_window_visibility(meta_window) + ); + } + /// Set the opacity of the window actor that sits on top of the blur effect. set_window_opacity(window_actor, opacity) { + // Define known blur actor names. This makes it easy to update if names change again. + const BLUR_ACTOR_NAMES = new Set(["blur-actor", "bms-application-blurred-widget"]); + window_actor?.get_children().forEach(child => { - if (child.name !== "blur-actor" && child.opacity != opacity) + // Check against the Set and the opacity + if (!BLUR_ACTOR_NAMES.has(child.name) && 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); - } - })); + this.meta_window_map.forEach((meta_window, _pid) => + this.reconcile_window_visibility(meta_window) + ); } /// Find the system's window scaling. 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 index 4ff212c..d386722 100644 --- 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 @@ -3,6 +3,7 @@ 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 * as utils from '../conveniences/utils.js'; import { Pipeline } from '../conveniences/pipeline.js'; import { DummyPipeline } from '../conveniences/dummy_pipeline.js'; @@ -21,7 +22,7 @@ const DASH_STYLES = [ class DashInfos { constructor( dash_blur, dash, dash_container, dash_background, - background, background_group, bg_manager + background, background_group, bg_manager, paint_signals ) { // the parent DashBlur object, to communicate this.dash_blur = dash_blur; @@ -31,28 +32,55 @@ class DashInfos { this.background = background; this.background_group = background_group; this.bg_manager = bg_manager; + this.paint_signals = paint_signals; this.settings = dash_blur.settings; - this.old_style = this.dash._background.style; + this.old_style = this.dash._background?.style; + + this.updateId = 0; + this._first_boot = true; + + this.bg_allocation_id = this.background_group?.connect('notify::allocation', () => { + this.schedule_update(); + }); + + let monitor = Main.layoutManager.findMonitorForActor(this.dash_container); + this.current_monitor_index = monitor ? monitor.index : null; - this.dash_destroy_id = dash.connect('destroy', () => this.remove_dash_blur(false)); + this.dash_destroy_id = dash.connect('destroy', () => this.remove_dash_blur()); 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('show', () => this.background_group?.show()), + this.dash_blur.connect('hide', () => this.background_group?.hide()), + this.dash_blur.connect('update-size', () => this.schedule_update()), this.dash_blur.connect('change-blur-type', () => this.change_blur_type()), this.dash_blur.connect('update-pipeline', () => this.update_pipeline()) ); } + schedule_update() { + this.clear_pending_idles(); + this.updateId = global.compositor.get_laters().add(Meta.LaterType.IDLE, () => { + this.updateId = 0; + this.update_size(); + return false; + }); + } + + clear_pending_idles() { + if (this.updateId) { + global.compositor.get_laters().remove(this.updateId); + this.updateId = 0; + } + } + // IMPORTANT: do never call this in a mutable `this.dash_blur.forEach` - remove_dash_blur(dash_not_already_destroyed = true) { + remove_dash_blur() { // remove the style and destroy the effects this.remove_style(); - this.destroy_dash(dash_not_already_destroyed); + this.destroy_dash(); // remove the dash infos from their list const dash_infos_index = this.dash_blur.dashes.indexOf(this); @@ -60,6 +88,10 @@ class DashInfos { this.dash_blur.dashes.splice(dash_infos_index, 1); // disconnect everything + if (this.bg_allocation_id && this.background_group) { + this.background_group.disconnect(this.bg_allocation_id); + this.bg_allocation_id = null; + } this.dash_blur_connections_ids.forEach(id => { if (id) this.dash_blur.disconnect(id); }); this.dash_blur_connections_ids = []; if (this.dash_destroy_id) @@ -70,36 +102,74 @@ class DashInfos { override_style() { this.remove_style(); - this.dash.set_style_class_name( - DASH_STYLES[this.settings.dash_to_dock.STYLE_DASH_TO_DOCK] - ); + const style = DASH_STYLES[ + this.settings.dash_to_dock.STYLE_DASH_TO_DOCK + ]; + + // Dash to Dock owns its style class list. Replacing it removes the + // extension's layout and border-radius rules. Add Blur My Shell's + // visual modifier alongside the native classes instead. + if (style && !this.dash.has_style_class_name(style)) + this.dash.add_style_class_name(style); } remove_style() { - this.dash._background.style = this.old_style; + if (this.dash?._background) + this.dash._background.style = this.old_style; DASH_STYLES.forEach( - style => this.dash.remove_style_class_name(style) + style => { + this.dash?.remove_style_class_name(style); + this.dash_background?.remove_style_class_name(style); + } ); } - destroy_dash(dash_not_already_destroyed = true) { - if (!dash_not_already_destroyed) + destroy_dash() { + this.clear_pending_idles(); + + if (this.paint_signals) + this.paint_signals.disconnect_all(); + + if (this.background_group && this.dash) { + const parent = this.dash.get_parent(); + if (parent) + parent.remove_child(this.background_group); + } + + if (this.bg_manager) { + if (this.bg_manager._bms_pipeline) { + this.bg_manager._bms_pipeline.destroy(); + this.bg_manager._bms_pipeline = null; + } this.bg_manager.backgroundActor = null; + this.bg_manager.destroy(); + this.bg_manager = null; + } + + if (this.bg_allocation_id && this.background_group) { + this.background_group.disconnect(this.bg_allocation_id); + this.bg_allocation_id = null; + } + + this._first_boot = 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(); + if (this.background_group) { + this.background_group.destroy(); + this.background_group = null; + } } change_blur_type() { this.destroy_dash(); + let blur_result = this.dash_blur.add_blur(this.dash, this.dash_container); + if (!blur_result) + return; + let [ background, background_group, bg_manager, paint_signals - ] = this.dash_blur.add_blur(this.dash); + ] = blur_result; this.background = background; this.background_group = background_group; @@ -108,50 +178,52 @@ class DashInfos { this.dash.get_parent().insert_child_at_index(this.background_group, 0); - this.update_size(); + // Apply the layout instantly before drawing the first frame + this.bg_allocation_id = this.background_group.connect('notify::allocation', () => { + this.schedule_update(); + }); + + this.schedule_update(); } update_pipeline() { - this.bg_manager._bms_pipeline.change_pipeline_to( - this.settings.dash_to_dock.PIPELINE - ); + if (this.bg_manager?._bms_pipeline) { + this.bg_manager._bms_pipeline.change_pipeline_to( + this.settings.dash_to_dock.PIPELINE + ); + } } update_size() { + if (!this.dash_blur._has_valid_allocation(this.dash_container) || + !this.dash_blur._has_valid_allocation(this.dash) || + !this.dash_blur._has_valid_allocation(this.dash_background)) + return; + 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 - ); + let monitor = Main.layoutManager.findMonitorForActor(this.dash_container); + if (!monitor) return; + + if (this.current_monitor_index !== monitor.index) { + this.current_monitor_index = monitor.index; + this.change_blur_type(); + return; + } + + let dash_box = this.get_dash_position(this.dash_container); + if (!dash_box) + return; + + const inset = utils.static_blur_clip_inset(); + const clip_x = Math.floor(dash_box.clip_x) - inset; + const clip_y = Math.floor(dash_box.clip_y) - inset; + const clip_w = Math.ceil(this.dash_background.width) + inset * 2; + const clip_h = Math.ceil(this.dash_background.height) + inset * 2; + + this.background.x = dash_box.background_x + inset; + this.background.y = dash_box.background_y + inset; + + this.background.set_clip(clip_x, clip_y, clip_w, clip_h); } else { this.background.width = this.dash_background.width; this.background.height = this.dash_background.height; @@ -159,29 +231,38 @@ class DashInfos { this.background.x = this.dash_background.x; this.background.y = this.dash_background.y + this.dash.y; } + + if (this._first_boot) { + if (this.settings.dash_to_dock.UNBLUR_IN_OVERVIEW && Main.overview.visible) { + this.background_group?.hide(); + } + this._first_boot = false; + } } - get_dash_position(dash_container, dash_background) { - var x, y; + get_dash_position(dash_container) { + let monitor = Main.layoutManager.findMonitorForActor(this.dash_container); + if (!monitor) + return; - let monitor = Main.layoutManager.findMonitorForActor(dash_container); let dash_box = dash_container._slider.get_child(); + if (!dash_box) + return null; - 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; - } + let parent = this.background_group?.get_parent(); + if (!parent) + return; + + let [parent_stage_x, parent_stage_y] = parent.get_transformed_position(); + let [bg_stage_x, bg_stage_y] = this.dash_background.get_transformed_position(); + + let background_x = monitor.x - parent_stage_x; + let background_y = monitor.y - parent_stage_y; - return [x, y]; + let clip_x = bg_stage_x - monitor.x; + let clip_y = bg_stage_y - monitor.y; + + return {background_x, background_y, clip_x, clip_y}; } _log(str) { @@ -234,28 +315,110 @@ export const DashBlur = class DashBlur extends Signals.EventEmitter { }).forEach(dash_container => this.try_blur(dash_container)); } + _has_valid_allocation(actor) { + return actor && + (!actor.has_allocation || actor.has_allocation()) && + actor.width > 0 && actor.height > 0; + } + + _defer_blur_until_allocated(dash_container, dash) { + if (dash_container._bms_pending_blur_setup) + return; + + dash_container._bms_pending_blur_setup = true; + + const connections = []; + const cleanup = () => { + delete dash_container._bms_pending_blur_setup; + delete dash_container._bms_defer_cleanup; + connections.forEach(({ actor, id }) => { + if (actor && id) + actor.disconnect(id); + }); + }; + + const retry = () => { + if (!dash_container._bms_pending_blur_setup) + return; + + let current_dash_box = dash_container._slider?.get_child(); + let current_dash = dash || current_dash_box?.get_children().find(child => child.get_name() === 'dash'); + + if (!this._has_valid_allocation(dash_container) || + !this._has_valid_allocation(current_dash_box) || + !this._has_valid_allocation(current_dash)) + return; + + cleanup(); + this.try_blur(dash_container); + }; + + const dash_cont_id = dash_container.connect('notify::allocation', retry); + connections.push({ actor: dash_container, id: dash_cont_id }); + + if (dash) { + const dash_id = dash.connect('notify::allocation', retry); + connections.push({ actor: dash, id: dash_id }); + } + + const destroy_id = dash_container.connect('destroy', cleanup); + connections.push({ actor: dash_container, id: destroy_id }); + + dash_container._bms_defer_cleanup = cleanup; + } + // Tries to blur the dash contained in the given actor try_blur(dash_container) { - let dash_box = dash_container._slider.get_child(); + let dash_box = dash_container._slider?.get_child(); + if (!dash_box){ + this._defer_blur_until_allocated(dash_container); + return; + } - // verify that we did not already blur that dash - if (!dash_box.get_children().some(child => + let dash = dash_box.get_children().find(child => { + return child.get_name() === 'dash'; + }); + + if (!dash || + !this._has_valid_allocation(dash_container) || + !this._has_valid_allocation(dash_box) || + !this._has_valid_allocation(dash)) { + this._defer_blur_until_allocated(dash_container, dash); + return; + } + + let dash_exist = this.dashes.find(info => info.dash === dash); + if (dash_exist) { + dash_exist.remove_dash_blur(); + } + + let existing_bg = dash_box.get_children().find(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'; - }); + if (existing_bg) { + if (dash_box.contains(existing_bg)) + dash_box.remove_child(existing_bg); + + existing_bg.destroy(); + } + + // verify that we did not already blur that dash + this._log("dash to dock found, blurring it"); - this.dashes.push(this.blur_dash_from(dash, dash_container)); + let infos = this.blur_dash_from(dash, dash_container); + if (infos) { + this.dashes.push(infos); } } // 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); + let blur_result = this.add_blur(dash, dash_container); + if (!blur_result) + return null; + + let [background, background_group, bg_manager, paint_signals] = blur_result; // insert the background group to the right element dash.get_parent().insert_child_at_index(background_group, 0); @@ -268,14 +431,32 @@ export const DashBlur = class DashBlur extends Signals.EventEmitter { ); this.connections.connect( dash_container, - ['notify::width', 'notify::height', 'notify::y', 'notify::x'], + [ + 'notify::width', + 'notify::height', + 'notify::y', + 'notify::x', + 'notify::style-class-name', + 'notify::allocation' + ], _ => this.update_size() ); - const dash_background = dash.get_children().find(child => { - return child.get_style_class_name() === 'dash-background'; - }); + const slider = dash_container._slider; + if (slider) { + this.connections.connect( + slider, + ['notify::slide-x', 'notify::allocation'], + _ => this.update_size() + ); + } + + const dash_background = dash._background || + dash.get_children().find(child => child.has_style_class_name('dash-background')) || + dash; + if (!dash_background) + return null; // create infos let infos = new DashInfos( this, @@ -289,16 +470,23 @@ export const DashBlur = class DashBlur extends Signals.EventEmitter { ); this.update_size(); + + global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, () => { + this.update_size(); + return false; + }); + this.update_background(); // returns infos return infos; } - add_blur(dash) { - const monitor = Main.layoutManager.findMonitorForActor(dash); + add_blur(dash, dash_container = null) { + const target_actor = dash_container || dash; + const monitor = Main.layoutManager.findMonitorForActor(target_actor) || Main.layoutManager.primaryMonitor; if (!monitor) - return; + return null; const background_group = new Meta.BackgroundGroup({ name: 'bms-dash-backgroundgroup', width: 0, height: 0 @@ -404,6 +592,12 @@ export const DashBlur = class DashBlur extends Signals.EventEmitter { this.emit('remove-dashes'); + for (let child of Main.uiGroup.get_children()) { + if (child._bms_defer_cleanup) + child._bms_defer_cleanup(); + delete child._bms_pending_blur_setup; + } + this.dashes = []; this.connections.disconnect_all(); @@ -418,4 +612,4 @@ export const DashBlur = class DashBlur extends Signals.EventEmitter { _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/overview.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/overview.js index 3bbde61..c97a459 100644 --- 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 @@ -104,13 +104,39 @@ export const OverviewBlur = class OverviewBlur { // this hides windows that are not on the current workspace if ( outer_this.settings.applications.BLUR - ) + ) { + // compile blacklist patterns once for this switch + const blacklist = outer_this.settings.applications.BLACKLIST || []; + const blacklist_regexes = blacklist.map(pattern => { + const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&'); + return new RegExp('^' + escaped.replace(/\*/g, '.*').replace(/\?/g, '.') + '$', 'i'); + }); + 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() + window => { + // skip windows on all workspaces (e.g. secondary + // monitor windows under `workspaces-only-on-primary`); + // hiding them on any inactive workspace hides them globally + if (window.is_on_all_workspaces()) return; + + // skip desktop-type windows (e.g. DING, Nautilus desktop): + // they should always remain visible + if (window.get_window_type() === Meta.WindowType.DESKTOP) + return; + + // skip blacklisted windows: + // they are not blurred and should always remain visible + const wm_class = window.get_wm_class(); + if (wm_class && blacklist_regexes.some(re => re.test(wm_class))) + return; + + window.get_compositor_private().hide(); + } ); } + } Main.uiGroup.remove_child(outer_this.animation_background_group); }; @@ -149,14 +175,11 @@ export const OverviewBlur = class OverviewBlur { // 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 - let _reordering = false; this.connections.connect(Main.layoutManager.overviewGroup, "child-added", (_, child) => { - if (!_reordering && child !== this.overview_background_group) { - _reordering = true; + 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); - _reordering = false; } }); } 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 index bd39166..7d00224 100644 --- 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 @@ -4,6 +4,7 @@ import Meta from 'gi://Meta'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import { PaintSignals } from '../conveniences/paint_signals.js'; +import * as utils from '../conveniences/utils.js'; import { Pipeline } from '../conveniences/pipeline.js'; import { DummyPipeline } from '../conveniences/dummy_pipeline.js'; @@ -16,9 +17,10 @@ const PANEL_STYLES = [ "contrasted-panel" ]; -// global listener, so we don't miss the panel destruction event -let isMainPanelAlive = true; -Main.panel.connect('destroy', () => isMainPanelAlive = false); +const GRADIENT_PANEL_STYLES = [ + "gradient-panel", + "gradient-panel-reverse" +]; export const PanelBlur = class PanelBlur { constructor(connections, settings, effects_manager) { @@ -27,7 +29,9 @@ export const PanelBlur = class PanelBlur { this.settings = settings; this.effects_manager = effects_manager; this.actors_list = []; + this.queued_updates = new Set(); this.enabled = false; + this._first_boot = true; } enable() { @@ -36,6 +40,12 @@ export const PanelBlur = class PanelBlur { return; } + // global listener, so we don't miss the panel destruction event + this._isMainPanelAlive = true; + this.connections.connect(Main.panel, 'destroy', () => { + this._isMainPanelAlive = false; + }); + this._log("blurring top panel"); // check for panels when Dash to Panel is activated @@ -59,6 +69,9 @@ export const PanelBlur = class PanelBlur { this.blur_existing_panels(); + // Hide the panel blur first to avoid the panel background from display on login + this.panel_hide_blur_startup(); + // 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(); @@ -113,20 +126,16 @@ export const PanelBlur = class PanelBlur { // 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 panel - if (isMainPanelAlive) + if (this._isMainPanelAlive) this.maybe_blur_panel(Main.panel); // blur panels already created by extension multi-monitors-bar@frederykabryan Main.uiGroup.get_children().forEach(actor => { if (actor.get_name() === "panelBox" && actor.get_n_children() === 1) { let multi_monitor_panel = actor.get_child_at_index(0); - if (isMainPanelAlive && multi_monitor_panel != Main.panel) + if (this._isMainPanelAlive && multi_monitor_panel != Main.panel) this.maybe_blur_panel(multi_monitor_panel); } }) @@ -145,12 +154,27 @@ export const PanelBlur = class PanelBlur { this._log("Blurring Dash to Panel panels after idle."); - // blur every panel, except Main.panel (this is handled in blur_existing_panels() method above) + // blur every panel found global.dashToPanel.panels.forEach(p => { - if (p.panel != Main.panel) + if ( + p.panel != Main.panel || + this.settings.dash_to_panel.BLUR_ORIGINAL_PANEL + ) this.maybe_blur_panel(p.panel); }); + // if main panel is not included in the previous panels, blur it + if ( + !global.dashToPanel.panels + .map(p => p.panel) + .includes(Main.panel) + && + this.settings.dash_to_panel.BLUR_ORIGINAL_PANEL + && + this._isMainPanelAlive + ) + this.maybe_blur_panel(Main.panel); + return GLib.SOURCE_REMOVE; }); }; @@ -169,10 +193,14 @@ export const PanelBlur = class PanelBlur { /// Blur a panel blur_panel(panel) { + let geometry_actor = panel; + let wrapper = null; let panel_box = panel.get_parent(); let is_dtp_panel = false; if (!panel_box.name) { is_dtp_panel = true; + wrapper = panel_box; + geometry_actor = panel; // Track the inner panel dynamically panel_box = panel_box.get_parent(); } @@ -186,9 +214,11 @@ export const PanelBlur = class PanelBlur { let background, bg_manager; let static_blur = this.settings.panel.STATIC_BLUR; + let pipeline; // Hoist the pipeline variable so our proxy can access it + if (static_blur) { let bg_manager_list = []; - const pipeline = new Pipeline( + pipeline = new Pipeline( this.effects_manager, global.blur_my_shell._pipelines_manager, this.settings.panel.PIPELINE @@ -200,32 +230,55 @@ export const PanelBlur = class PanelBlur { bg_manager = bg_manager_list[0]; } else { - const pipeline = new DummyPipeline(this.effects_manager, this.settings.panel); + 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(); - } + 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"); + + // Proxy object to dynamically resolve the active blur effect. + // This ensures repaints continue safely even if pipeline effects are rebuilt. + let dynamic_target = { + queue_repaint: () => { + let active_pipeline = (bg_manager && bg_manager._bms_pipeline) ? bg_manager._bms_pipeline : pipeline; + + if (static_blur && active_pipeline && active_pipeline.effects) { + // Repaint all effects in the static pipeline to be agnostic of the active effects + for (let i = 0; i < active_pipeline.effects.length; i++) { + let eff = active_pipeline.effects[i]; + if (eff && typeof eff.queue_repaint === 'function') { + eff.queue_repaint(); + } + } + } else if (!static_blur && active_pipeline) { + let eff = active_pipeline.effect; // Dynamic pipeline uses a single effect + if (eff && typeof eff.queue_repaint === 'function') { + eff.queue_repaint(); + } + } + } + }; + + paint_signals.disconnect_all(); + paint_signals.connect(background, dynamic_target); + } else { + paint_signals.disconnect_all(); } } @@ -234,75 +287,151 @@ export const PanelBlur = class PanelBlur { // 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 }, + widgets: { + panel, + wrapper, + panel_box, + background, + background_group, + geometry_actor + }, static_blur, monitor, bg_manager, is_dtp_panel }; this.actors_list.push(actors); + background_group.connect('destroy', () => { + actors.widgets.background_group = null; + }); - // update the size of the actor - this.update_size(actors); + // defer size update to idle to avoid allocation race + this.queue_update_size(actors); - // connect to panel, panel_box and its parent position or size change + // connect to the relevant actors geometry changes // this should fire update_size every time one of its params change this.connections.connect( - panel, - 'notify::position', - _ => this.update_size(actors) + geometry_actor, + ['notify::allocation', 'notify::size', 'notify::position'], + _ => this.queue_update_size(actors) ); + + if (wrapper) { + this.connections.connect( + wrapper, + ['notify::allocation', 'notify::size', 'notify::position'], + _ => this.queue_update_size(actors) + ); + } this.connections.connect( panel_box, ['notify::size', 'notify::position'], - _ => this.update_size(actors) + _ => this.queue_update_size(actors) ); this.connections.connect( panel_box.get_parent(), 'notify::position', - _ => this.update_size(actors) + _ => this.queue_update_size(actors) ); // connect to the panel getting destroyed this.connections.connect( panel, 'destroy', - _ => this.destroy_blur(actors, true) + _ => this.destroy_blur(actors) ); } + queue_update_size(actors) { + if (this.queued_updates.has(actors)) + return; + + this.queued_updates.add(actors); + GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { + this.queued_updates.delete(actors); + + if (!this.enabled || !this.actors_list.includes(actors)) + return GLib.SOURCE_REMOVE; + + this.update_size(actors); + return GLib.SOURCE_REMOVE; + }); + } + update_size(actors) { - let panel = actors.widgets.panel; + let geometry_actor = actors.widgets.geometry_actor; let panel_box = actors.widgets.panel_box; + let wrapper = actors.widgets.wrapper; let background = actors.widgets.background; let [width, height] = panel_box.get_size(); + let [geometry_width, geometry_height] = geometry_actor.get_size(); + + if (!width || !height || !geometry_width || !geometry_height) { + this.queue_update_size(actors); + return; + } // if static blur, need to clip the background if (actors.static_blur) { - let monitor = Main.layoutManager.findMonitorForActor(panel); - if (!monitor) + let monitor = Main.layoutManager.findMonitorForActor(geometry_actor); + if (!monitor) { + this.queue_update_size(actors); 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; + // updated coordinates for static blur + let g_x, g_y; + if (actors.is_dtp_panel) { + let [w_x, w_y] = wrapper.get_position(); + let [pan_x, pan_y] = geometry_actor.get_position(); + g_x = w_x + pan_x; + g_y = w_y + pan_y; + } else { + [g_x, g_y] = geometry_actor.get_position(); + } + + let x = p_x + p_p_x - monitor.x + g_x; + let y = p_y + p_p_y - monitor.y + g_y; + let is_horizontal = geometry_width >= geometry_height; + let distance_to_top = Math.abs(y); + let distance_to_bottom = Math.abs( + monitor.height - (y + geometry_height) + ); + let is_bottom_panel = is_horizontal && + distance_to_bottom < distance_to_top; + + const inset = utils.static_blur_clip_inset(); + const offset = utils.subpixel_stage_offset(); + const workspace_edge_inset = is_bottom_panel + ? Math.max(inset, 1) + : inset; + const clip_x = Math.floor(x) - inset; + const clip_y = Math.floor(y) - workspace_edge_inset; + const clip_w = Math.ceil(geometry_width) + inset * 2; + const clip_h = Math.ceil(geometry_height) + + inset + workspace_edge_inset; + + background.set_clip(clip_x, clip_y, clip_w, clip_h); + background.x = g_x - x + inset; + background.y = offset + g_y - y + inset; } else { - background.x = panel.x; - background.y = panel.y; - background.width = panel.width; - background.height = panel.height; + // updated coordinates for dynamic blur + if (actors.is_dtp_panel) { + background.x = wrapper.x + geometry_actor.x; + background.y = wrapper.y + geometry_actor.y; + } else { + background.x = geometry_actor.x; + background.y = geometry_actor.y; + } + background.width = geometry_width; + background.height = geometry_height; } // update the monitor panel is on - actors.monitor = Main.layoutManager.findMonitorForActor(panel); + actors.monitor = Main.layoutManager.findMonitorForActor(geometry_actor); } /// Connect when overview if opened/closed to hide/show the blur accordingly @@ -322,23 +451,27 @@ export const PanelBlur = class PanelBlur { this.connections.connect( Main.overview, 'showing', _ => this.hide() ); + this.connections.connect( - Main.overview, 'hidden', _ => this.show() + Main.overview, 'hidden', _ => { + this.panel_hide_blur_dynamically(); + this.update_visibility(); + } ); } else { let appDisplay = Main.overview._overview._controls._appDisplay; - + this.connections.connect( appDisplay, 'show', _ => this.hide() ); + this.connections.connect( - appDisplay, 'hide', _ => this.show() + appDisplay, 'hide', _ => this.update_visibility() ); this.connections.connect( - Main.overview, 'hidden', _ => this.show() + Main.overview, 'hidden', _ => this.update_visibility() ); } - } } @@ -418,13 +551,13 @@ export const PanelBlur = class PanelBlur { /// Update the css classname of the panel for light theme update_light_text_classname(disable = false) { - if (!isMainPanelAlive) + if (!this._isMainPanelAlive) return; if (this.settings.panel.FORCE_LIGHT_TEXT && !disable) - Main.panel.add_style_class_name("panel-light-text"); + Main.uiGroup.add_style_class_name("panel-light-text"); else - Main.panel.remove_style_class_name("panel-light-text"); + Main.uiGroup.remove_style_class_name("panel-light-text"); } /// Callback when a new window is added @@ -452,7 +585,7 @@ export const PanelBlur = class PanelBlur { /// Update the visibility of the blur effect update_visibility() { if ( - isMainPanelAlive && Main.panel.has_style_pseudo_class('overview') + this._isMainPanelAlive && Main.panel.has_style_pseudo_class('overview') || !Main.sessionMode.hasWindows ) { this.actors_list.forEach( @@ -469,7 +602,13 @@ export const PanelBlur = class PanelBlur { 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 + // Whitelist only standard application windows. + // This prevents system overlays from disabling panel blur. + && [ + Meta.WindowType.NORMAL, + Meta.WindowType.DIALOG, + Meta.WindowType.MODAL_DIALOG + ].includes(meta_window.get_window_type()) // exclude Desktop Icons NG && meta_window.get_gtk_application_id() !== "com.rastersoft.ding" && meta_window.get_gtk_application_id() !== "com.desktop.ding" @@ -499,10 +638,10 @@ export const PanelBlur = class PanelBlur { // 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 on top (relative to the monitor's Y origin) + ((panel_top === actors.monitor.y && window_vertical_pos < panel_bottom + 5 * scale) || // check if panel is at the bottom - (panel_top > 0 && window_vertical_bottom > panel_top - 5 * scale)) + (panel_top > actors.monitor.y && window_vertical_bottom > panel_top - 5 * scale)) ) window_overlap_panel = true; }); @@ -519,22 +658,100 @@ export const PanelBlur = class PanelBlur { 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] - ); + if (this.settings.panel.OVERRIDE_BACKGROUND) { + if (this.settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY) { + if (this.settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_MODE == 0) { + // This is an invert of the above behavior, + // Blur and all styling is hidden when "should_override" is true. + if (!should_override) { + this.proximity_show(actors, panel); + } + else { + this.proximity_hide(actors, panel); + }; + } + if (this.settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_MODE == 1) { + if (should_override) { + this.update_panel_style_class(panel, PANEL_STYLES[this.settings.panel.STYLE_PANEL]); + } else { + this.update_panel_style_class(panel, null); // Clear custom styles + } + } + } + else { + this.update_panel_style_class(panel, PANEL_STYLES[this.settings.panel.STYLE_PANEL]); + } + } + else { + this.update_panel_style_class(panel, null); } // update the classname if the panel to have or have not light text this.update_light_text_classname(!should_override); } + update_panel_style_class(panel, target_class) { + const ALL_STYLES = [...PANEL_STYLES, ...GRADIENT_PANEL_STYLES]; + + // Remove all managed classes EXCEPT the target class we are moving to + ALL_STYLES.forEach(style => { + if (style !== target_class) { + panel.remove_style_class_name(style); + } + }); + + // Add the target class if specified and not already present + if (target_class && !panel.has_style_class_name(target_class)) { + panel.add_style_class_name(target_class); + } + } + + panel_hide_blur_dynamically() { + if (this.settings.panel.OVERRIDE_BACKGROUND && this.settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY) { + if (this.settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_MODE == 0) { + this.hide() + } + else {this.show()} + } + else { + this.show() + } + } + + proximity_hide(actors, panel) { + let target_style = null; + if (this.settings.panel.GRADIENT_PANEL) { + if (!Main.overview.visible) { + target_style = GRADIENT_PANEL_STYLES[this.settings.panel.GRADIENT_PANEL_MODE]; + } + else { + target_style = this.settings.panel.UNBLUR_IN_OVERVIEW + ? PANEL_STYLES[0] + : GRADIENT_PANEL_STYLES[this.settings.panel.GRADIENT_PANEL_MODE]; + } + } + else { + target_style = PANEL_STYLES[this.settings.panel.STYLE_PANEL]; + } + + this.update_panel_style_class(panel, target_style); + actors.widgets.background.hide(); + } + + proximity_show(actors, panel) { + this.update_panel_style_class(panel, PANEL_STYLES[this.settings.panel.STYLE_PANEL]); + actors.widgets.background.show(); + } + + panel_hide_blur_startup(){ + if (this._first_boot) { + if (this.settings.panel.UNBLUR_IN_OVERVIEW && Main.overview.visible) { + this.hide(); + } + this._first_boot = false; + } + } + update_pipeline() { this.actors_list.forEach(actors => actors.bg_manager._bms_pipeline.change_pipeline_to( @@ -556,19 +773,22 @@ export const PanelBlur = class PanelBlur { } // IMPORTANT: do never call this in a mutable `this.actors_list.forEach` - destroy_blur(actors, panel_already_destroyed) { + destroy_blur(actors) { this.set_should_override_panel(actors, false); - actors.bg_manager._bms_pipeline.destroy(); - - if (panel_already_destroyed) + if (actors.bg_manager) { + if (actors.bg_manager._bms_pipeline) { + actors.bg_manager._bms_pipeline.destroy(); + actors.bg_manager._bms_pipeline = null; + } actors.bg_manager.backgroundActor = null; - actors.bg_manager.destroy(); + actors.bg_manager.destroy(); + actors.bg_manager = null; + } - if (!panel_already_destroyed) { - actors.widgets.panel_box.remove_child(actors.widgets.background_group); - actors.widgets.background_group.destroy_all_children(); + if (actors.widgets && actors.widgets.background_group) { actors.widgets.background_group.destroy(); + actors.widgets.background_group = null; } let index = this.actors_list.indexOf(actors); @@ -589,10 +809,12 @@ export const PanelBlur = class PanelBlur { this.update_light_text_classname(true); const immutable_actors_list = [...this.actors_list]; - immutable_actors_list.forEach(actors => this.destroy_blur(actors, false)); + immutable_actors_list.forEach(actors => this.destroy_blur(actors)); this.actors_list = []; + this.queued_updates.clear(); this._dirty = true; + this._first_boot = null; this.connections.disconnect_all(); diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup.js new file mode 100644 index 0000000..959b2f4 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup.js @@ -0,0 +1 @@ +export { PopupBlur } from './popup/index.js'; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/blur_surface.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/blur_surface.js new file mode 100644 index 0000000..8fcf82b --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/blur_surface.js @@ -0,0 +1,484 @@ +import GLib from 'gi://GLib'; +import Meta from 'gi://Meta'; +import St from 'gi://St'; + +import { DummyPipeline } from '../../conveniences/dummy_pipeline.js'; +import { PaintSignals } from '../../conveniences/paint_signals.js'; +import { PopupBlurSurfaceFade } from './surface_fade.js'; +import { PopupBlurSurfacePlacement } from './surface_placement.js'; +import { PopupBlurSurfaceSignals } from './surface_signals.js'; +import { PopupBlurSurfaceStyle } from './surface_style.js'; +import { PopupBlurSurfaceTransitions } from './surface_transitions.js'; +import { PopupBlurStaticActor } from './static_actor.js'; + +const NOTIFICATION_STYLE_CLASSES = ['notification-banner']; +const FULL_GEOMETRY_STYLE_CLASSES = [ + 'popup-menu-content', 'candidate-popup-content', + 'quick-settings', 'quick-toggle-menu', 'screenshot-ui-panel', + 'notification-banner', 'snap-assistant', + 'osd-window', 'resize-popup', 'workspace-switcher', + 'modal-dialog', 'run-dialog', + 'bms-keyboard-surface', +]; +const IS_HEAVY_SURFACE_STYLE_CLASSES = [ + 'datemenu-popover', 'quick-settings', 'modal-dialog', + 'candidate-popup-content', 'candidate-popup-boxpointer', +]; +const IS_QUICK_SETTINGS_STYLE_CLASSES = [ + 'quick-toggle-menu', 'quick-settings', 'datemenu-popover', +]; + +export const PopupBlurSurface = class PopupBlurSurface { + constructor(connections, settings, effects_manager, target, root_actor, parent, sibling, corner_radius) { + this.connections = connections; + this.settings = settings; + this.effects_manager = effects_manager; + this.target = target; + this.root_actor = root_actor; + this.parent = parent; + this.sibling = sibling; + this.corner_radius = corner_radius; + this.paint_signals = new PaintSignals(connections); + this.placement = new PopupBlurSurfacePlacement(this); + this.signals = new PopupBlurSurfaceSignals(this); + this.style = new PopupBlurSurfaceStyle(this); + this.transitions = new PopupBlurSurfaceTransitions(this); + this.repaint_id = 0; + this.update_id = 0; + this.transition_update_id = 0; + this.opacity = null; + this.static_blur = settings.popup.STATIC_BLUR; + this.static_actor = null; + this.actor = null; + this.blur_actor = null; + } + + enable() { + if (!this.create_actor()) { + if (this.static_blur) + this.destroy_static_actor(); + return false; + } + + this.fade = new PopupBlurSurfaceFade( + this.actor, + this.target, + this.root_actor, + this.parent + ); + this.actor.hide(); + this.parent.add_child(this.actor); + this.set_actor_position(); + this.style.capture_target_style(); + this.style.update_target_style(); + + this.connect_repaints(); + this.signals.connect_actor(this.target); + this.signals.connect_actor(this.root_actor); + this.signals.connect_ancestors(this.target); + this.signals.connect_ancestors(this.root_actor); + if (this.style.has_any_style_class(this.target, ['screenshot-ui-panel'])) + this.signals.connect_actor(this.parent); + this.signals.connect_layout(); + this.signals.connect_settings(); + this.queue_update(); + + return true; + } + + create_actor() { + if (this.static_blur) + return this.create_static_actor(); + + this.blur_actor = new St.Widget({ + name: 'bms-popup-blurred-widget', + reactive: false, + }); + this.blur_actor.add_style_class_name('bms-popup-blurred-widget'); + this.track_owned_actor(this.blur_actor); + this.pipeline = new DummyPipeline( + this.effects_manager, + this.settings.popup, + this.blur_actor, + { + corner_radius_key: this.corner_radius.key, + corner_radius_getter: () => this.get_corner_radius(), + } + ); + this.actor = this.blur_actor; + return true; + } + + create_static_actor() { + this.static_actor = new PopupBlurStaticActor( + this.settings, + this.effects_manager, + this.target, + this.root_actor, + this.parent, + () => this.get_corner_radius() + ); + if (!this.static_actor.create()) + return false; + this.sync_static_actor(); + return true; + } + + sync_static_actor() { + this.actor = this.static_actor.actor; + this.blur_actor = this.static_actor.blur_actor; + this.pipeline = this.static_actor.pipeline; + } + + track_owned_actor(actor) { + this.connections.connect(actor, 'destroy', () => { + this.actor = null; + this.blur_actor = null; + }); + } + + set_actor_position() { + if (!this.is_actor_valid()) + return; + const sibling = this.sibling?.get_parent() === this.parent ? this.sibling : null; + if (this.is_below_sibling(sibling)) + return; + this.parent.set_child_below_sibling(this.actor, sibling); + } + + is_below_sibling(sibling) { + const children = this.parent.get_children(); + const actor_index = children.indexOf(this.actor); + if (actor_index < 0) + return false; + if (!sibling) + return actor_index === 0; + const sibling_index = children.indexOf(sibling); + return sibling_index >= 0 && actor_index < sibling_index; + } + + is_quick_settings() { + return this.style.has_any_style_class(this.target, IS_QUICK_SETTINGS_STYLE_CLASSES) + || this.style.has_any_style_class(this.root_actor, IS_QUICK_SETTINGS_STYLE_CLASSES); + } + + is_heavy_surface() { + return this.style.has_any_style_class(this.target, IS_HEAVY_SURFACE_STYLE_CLASSES) + || this.style.has_any_style_class(this.root_actor, IS_HEAVY_SURFACE_STYLE_CLASSES); + } + + update() { + if (this.is_notification_surface()) { + this.update_live_surface(); + return; + } + let transition_state = this.transitions.get_state(); + let geometry = this.placement.get_surface_geometry(); + const visible = this.is_visible(); + const geometry_changed = this.placement.has_surface_geometry_changed(geometry); + if ( + !visible + || !this.placement.has_valid_geometry(geometry) + || (!transition_state.geometry && geometry_changed) + ) + transition_state = this.transitions.complete_state(transition_state); + if (!visible && !transition_state.running) { + this.hide_surface(); + return; + } + if (!this.placement.has_valid_geometry(geometry)) { + if (this.placement.offscreen) + return this.hide_surface(); + if (this.placement.keep_transition_visible(transition_state)) { + this.queue_repaint(true); + this.queue_transition_update(transition_state); + return; + } + + if (transition_state.running) { + this.queue_transition_update(transition_state); + return; + } + this.hide_surface(); + return; + } + this.set_actor_position(); + if (!this.placement.update_surface_geometry(geometry)) + return; + if (!this.placement.prepare_visible_geometry()) + return; + const opacity = this.update_opacity(transition_state); + if (opacity > 0) + this.show_actors(); + else + this.hide_actors(); + this.queue_repaint(!visible); + this.queue_transition_update(transition_state); + } + + update_live_surface() { + if (!this.is_visible()) { + this.hide_surface(); + return; + } + this.set_actor_position(); + const geometry = this.placement.get_unclipped_monitor_surface_geometry(); + if (!this.placement.has_valid_geometry(geometry)) + return this.hide_surface(); + if (!this.placement.update_surface_geometry(geometry)) + return; + if (!this.placement.prepare_visible_geometry()) + return; + if (this.update_opacity() > 0) + this.show_actors(); + else + this.hide_actors(); + this.queue_repaint(); + this.queue_transition_update(); + } + + hide_surface() { + this.opacity = 0; + this.update_surface_opacity(0); + this.hide_actors(); + this.placement.hide(); + } + + update_opacity(transition_state = null) { + const opacity = this.fade.get_opacity(); + const transition_opacity = this.get_transition_opacity(opacity, transition_state); + if ( + this.opacity === transition_opacity + && this.has_surface_opacity(transition_opacity) + ) + return transition_opacity; + this.update_surface_opacity(transition_opacity); + this.opacity = transition_opacity; + return transition_opacity; + } + + get_transition_opacity(opacity, transition_state) { + if ( + this.static_blur + || !transition_state?.geometry + || transition_state.opacity + || this.opacity <= 0 + ) + return opacity; + return Math.max(opacity, this.opacity); + } + + has_surface_opacity(opacity) { + if (this.static_blur) + return this.static_actor.has_opacity(opacity); + if (!this.is_actor_valid()) + return false; + return this.actor.opacity === opacity; + } + + update_surface_opacity(opacity) { + const pipeline_opacity = this.get_pipeline_opacity(opacity); + if (this.static_blur) { + this.static_actor.set_opacity(opacity, pipeline_opacity); + return; + } + this.fade.set_opacity(opacity); + this.pipeline?.set_opacity_factor(pipeline_opacity / 255); + } + + get_pipeline_opacity(opacity) { + if (!this.style.has_any_style_class(this.target, ['screenshot-ui-panel'])) + return opacity; + return Math.round(opacity * (this.parent?.opacity ?? 255) / 255); + } + + get_geometry_actor() { + return this.target; + } + + should_use_content_geometry() { + return !this.uses_full_actor_geometry(); + } + + should_use_margin_geometry() { + return !this.uses_full_actor_geometry(); + } + + uses_full_actor_geometry() { + return ( + this.style.has_any_style_class(this.target, FULL_GEOMETRY_STYLE_CLASSES) + || this.style.has_any_style_class(this.root_actor, FULL_GEOMETRY_STYLE_CLASSES) + ); + } + + is_notification_surface() { + return ( + this.style.has_any_style_class(this.target, NOTIFICATION_STYLE_CLASSES) + || this.style.has_any_style_class(this.root_actor, NOTIFICATION_STYLE_CLASSES) + ); + } + + show_actors() { + if (this.is_actor_valid()) + this.actor?.show(); + } + + hide_actors() { + if (this.is_actor_valid()) + this.actor?.hide(); + } + + is_actor_valid() { + return ( + !!this.actor + && (!this.static_blur || !!this.static_actor?.background_group) + ); + } + + queue_update() { + if (!this.actor || this.update_id || this.transition_update_id) + return; + this.update_id = global.compositor.get_laters().add( + Meta.LaterType.BEFORE_REDRAW, + () => { + this.update_id = 0; + if (this.actor) + this.update(); + return GLib.SOURCE_REMOVE; + } + ); + } + + queue_transition_update(transition_state = null) { + const has_running_transition = transition_state?.running ?? this.transitions.has_running(); + if (!this.actor || this.transition_update_id || this.update_id || !has_running_transition) + return; + this.transition_update_id = global.compositor.get_laters().add( + Meta.LaterType.BEFORE_REDRAW, + () => { + this.transition_update_id = 0; + if (this.actor) + this.update(); + return GLib.SOURCE_REMOVE; + } + ); + } + + connect_repaints() { + if (this.static_blur || this.settings.HACKS_LEVEL !== 1) + return; + const repaint_source = { + queue_repaint: () => this.queue_repaint(), + }; + [ + this.blur_actor, + this.target, + ].forEach(actor => { + this.paint_signals.disconnect_all_for_actor(actor); + this.paint_signals.connect(actor, repaint_source); + }); + } + + update_settings() { + this.style.update_target_style(); + this.static_actor?.update_settings(); + } + + get_corner_radius() { + return this.settings.popup[this.corner_radius.property] ?? this.settings.popup.CORNER_RADIUS; + } + + queue_repaint(force = false) { + if (this.static_blur || this.repaint_id || (!force && !this.should_repaint())) + return; + this.repaint_id = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { + this.repaint_id = 0; + if (force || this.should_repaint()) + this.pipeline?.repaint_effect(); + return GLib.SOURCE_REMOVE; + }); + } + + should_repaint() { + return this.is_visible(); + } + + is_visible() { + return this.is_actor_visible(this.target) && this.is_actor_visible(this.root_actor); + } + + is_keyboard_surface() { + return ( + this.style.has_style_class(this.target, 'bms-keyboard-surface') + || this.style.has_style_class(this.root_actor, 'bms-keyboard-surface') + ); + } + + is_actor_visible(actor) { + if (!actor) + return false; + if (actor.visible && actor.mapped) + return true; + if (!this.is_keyboard_surface()) + return false; + + const parent = actor.get_parent(); + return parent?.visible && parent?.mapped; + } + + update_pipeline() { + if (this.static_blur) { + this.static_actor.update_pipeline(); + this.sync_static_actor(); + } + } + + destroy() { + if (this.update_id) { + global.compositor.get_laters().remove(this.update_id); + this.update_id = 0; + } + if (this.transition_update_id) { + global.compositor.get_laters().remove(this.transition_update_id); + this.transition_update_id = 0; + } + if (this.repaint_id) { + GLib.Source.remove(this.repaint_id); + this.repaint_id = 0; + } + + this.signals.disconnect_all(); + this.paint_signals.disconnect_all_for_actor(this.blur_actor); + this.paint_signals.disconnect_all_for_actor(this.target); + this.style.restore_target_style(); + + if (this.static_blur) + this.destroy_static_actor(); + else + this.destroy_dynamic_actor(); + + this.fade = null; + } + + destroy_dynamic_actor() { + const pipeline = this.pipeline; + const blur_actor = this.blur_actor; + this.pipeline = null; + this.blur_actor = null; + this.actor = null; + if (pipeline) + pipeline.destroy(); + if (blur_actor) + blur_actor.destroy(); + } + + destroy_static_actor() { + if (this.static_actor) + this.static_actor.destroy(); + this.static_actor = null; + this.actor = null; + this.blur_actor = null; + this.pipeline = null; + this.placement.clear(); + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/index.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/index.js new file mode 100644 index 0000000..edc9369 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/index.js @@ -0,0 +1,556 @@ +import GLib from 'gi://GLib'; +import Gio from 'gi://Gio'; +import Meta from 'gi://Meta'; +import St from 'gi://St'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; + +import { + POPUP_BACKGROUND_STYLES, + POPUP_SURFACE_STYLES, + PopupBlurTargets, +} from './targets.js'; +import { PopupBlurSurface } from './blur_surface.js'; +import { PopupBlurMessageStacks } from './message_stacks.js'; + +const POPUP_INTERNAL_STYLE_CLASSES = ['bms-popup-blurred-widget', 'bms-popup-backgroundgroup']; +const POPUP_INTERNAL_NAMES = ['bms-popup-blurred-widget', 'bms-popup-backgroundgroup']; +const KEYBOARD_STYLE_CLASS = 'bms-keyboard-surface'; + +export const PopupBlur = class PopupBlur { + constructor(connections, settings, effects_manager) { + this.connections = connections; + this.settings = settings; + this.effects_manager = effects_manager; + this.surfaces = new Map(); + this.containers = new Set(); + this.queued_actors = new Set(); + this.watched_actors = new WeakSet(); + this.destroyed_actors = new WeakSet(); + this.interface_settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); + this.message_stacks = new PopupBlurMessageStacks(connections); + this.targets = new PopupBlurTargets(this); + this.queue_id = 0; + this.follow_up_queue_id = 0; + this.follow_up_actors = new Set(); + this.reset_id = 0; + this.enabled = false; + } + + enable() { + if (this.enabled) { + this._log("blur already enabled"); + return; + } + + this._log("blurring popup surfaces"); + this.enabled = true; + + this.update_background(); + this.message_stacks.enable(); + this.connections.connect( + this.interface_settings, + 'changed::color-scheme', + () => this.update_background() + ); + this.connections.connect( + this.interface_settings, + 'changed::gtk-theme', + () => this.update_background() + ); + this.connections.connect( + Main.sessionMode, + 'updated', + () => this.update_background() + ); + this.connections.connect( + St.Settings.get(), + 'notify::color-scheme', + () => this.update_background() + ); + + this.track_container(Main.uiGroup); + (Main.osdWindowManager?._osdWindows ?? []).forEach(window => this.track_container(window)); + this.track_container(Main.layoutManager?.modalDialogGroup); + this.track_container(Main.layoutManager?.screenShieldGroup); + this.track_container(Main.layoutManager?.unlockDialogGroup); + this.track_container(Main.messageTray?._bannerBin); + this.track_quick_settings(); + this.track_container(global.window_group); + this.track_keyboard(); + this.track_container(Main.keyboard?.keyboardActor); + } + + track_container(container) { + if (!container || this.containers.has(container)) + return; + if (!this.watch_actor(container)) + return; + + this.containers.add(container); + this.message_stacks.track_container(container); + + this.get_children(container).forEach(child => this.try_blur(child)); + + this.connections.connect( + container, + 'child-added', + (_, child) => this.queue_try_blur(child) + ); + } + + track_quick_settings() { + const menu = Main.panel?.statusArea?.quickSettings?.menu; + this.track_container(menu?._overlay); + } + + track_keyboard() { + const keyboard_box = Main.layoutManager?.keyboardBox; + this.track_container(keyboard_box); + if (!keyboard_box) + return; + + this.connections.connect( + keyboard_box, + 'child-added', + (_, child) => this.update_keyboard_style(child) + ); + } + + try_blur(actor) { + if (this.is_internal_actor(actor) || !this.watch_actor(actor)) + return; + + this.message_stacks.scan(actor); + this.track_container(this.get_actor_overlay(actor)); + + const targets = this.get_blur_targets(actor); + + if (this.targets.is_blur_target_actor(actor)) + this.track_container(actor); + + if (this.has_style_class(actor, 'switcher-popup')) + this.track_container(actor); + + if (this.is_window_actor(actor)) + this.track_container(actor); + + targets.forEach(target => this.blur_actor(target, actor)); + } + + queue_try_blur(actor) { + if (this.is_internal_actor(actor) || !this.watch_actor(actor)) + return; + + this.queued_actors.add(actor); + if (this.queue_id) + return; + + this.queue_id = global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, () => { + this.queue_id = 0; + const actors = [...this.queued_actors]; + this.queued_actors.clear(); + + this.try_blur_actors(actors); + this.queue_follow_up_blurs(actors); + + return GLib.SOURCE_REMOVE; + }); + } + + queue_follow_up_blurs(actors) { + actors.forEach(actor => this.follow_up_actors.add(actor)); + + if (this.follow_up_queue_id || this.follow_up_actors.size === 0) + return; + + this.follow_up_queue_id = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { + this.follow_up_queue_id = 0; + const actors = [...this.follow_up_actors]; + this.follow_up_actors.clear(); + + this.try_blur_actors(actors); + + return GLib.SOURCE_REMOVE; + }); + } + + try_blur_actors(actors) { + if (!this.enabled) + return; + + actors.forEach(actor => { + if (!this.destroyed_actors.has(actor) && !this.is_internal_actor(actor)) + this.try_blur(actor); + }); + } + + cancel_queued_blurs() { + if (this.queue_id) { + global.compositor.get_laters().remove(this.queue_id); + this.queue_id = 0; + } + if (this.follow_up_queue_id) { + GLib.source_remove(this.follow_up_queue_id); + this.follow_up_queue_id = 0; + } + this.queued_actors.clear(); + this.follow_up_actors.clear(); + } + + blur_actor(target, root_actor) { + if ( + this.is_internal_actor(target) + || this.is_internal_actor(root_actor) + || !this.watch_actor(target) + || !this.watch_actor(root_actor) + ) + return; + + if (this.surfaces.has(target)) + return; + + this.destroy_blurred_ancestors(target); + + const { parent, sibling } = this.get_overlay_parent(root_actor, target); + const surface = new PopupBlurSurface( + this.connections, + this.settings, + this.effects_manager, + target, + root_actor, + parent, + sibling, + this.get_corner_radius(target, root_actor), + () => this.enabled && this.surfaces.has(target) + ); + + this.surfaces.set(target, surface); + + if (surface.enable()) + return this.connect_surface(target, root_actor); + + this.surfaces.delete(target); + surface.destroy(); + } + + connect_surface(target, root_actor) { + this.connections.connect( + target, + 'destroy', + () => this.destroy_blur(target) + ); + + if (root_actor !== target) { + this.connections.connect( + root_actor, + 'destroy', + () => this.destroy_blur(target) + ); + } + } + + destroy_blurred_ancestors(actor) { + actor = actor ? actor.get_parent() : null; + + while (actor && !this.destroyed_actors.has(actor)) { + if (this.surfaces.has(actor) && this.targets.prefers_descendant_targets(actor)) { + this.destroy_blur(actor); + } + + actor = actor.get_parent(); + } + } + + get_overlay_parent(root_actor, target) { + if (this.has_any_style_class(target, ['screenshot-ui-panel'])) { + const parent = Main.screenshotUI ?? Main.uiGroup; + let sibling = target; + while (sibling && sibling.get_parent() && sibling.get_parent() !== parent) { + sibling = sibling.get_parent(); + } + return { + parent, + sibling: sibling ?? target, + }; + } + + let actor = root_actor; + let child = null; + while (actor && !this.destroyed_actors.has(actor)) { + let parent = null; + parent = actor.get_parent(); + + if (!parent) + break; + + if (parent === Main.layoutManager.unlockDialogGroup || + parent === Main.layoutManager.screenShieldGroup || + parent === Main.uiGroup || + parent === Main.layoutManager.uiGroup) + return { parent, sibling: actor }; + + if (parent === global.window_group) + return { parent: actor, sibling: child ?? actor.get_last_child() }; + + child = actor; + actor = parent; + } + + return { parent: Main.uiGroup, sibling: null }; + } + + get_corner_radius(target, root_actor) { + return this.targets.get_corner_radius(target, root_actor); + } + + get_blur_targets(actor) { + return this.targets.find(actor); + } + + has_any_style_class(actor, style_classes) { + if (!actor || this.destroyed_actors.has(actor)) + return false; + + if (actor.get_style_class_name) { + const class_names = actor.get_style_class_name(); + if (typeof class_names === 'string') { + const normalized = ` ${class_names.trim().replace(/\s+/g, ' ')} `; + return style_classes.some(style_class => normalized.includes(` ${style_class} `)); + } + } + + return style_classes.some(style => this.has_style_class(actor, style)); + } + + has_style_class(actor, style_class) { + if (!actor || this.destroyed_actors.has(actor)) + return false; + + if (actor.has_style_class_name) + return actor.has_style_class_name(style_class); + + if (actor.get_style_class_name) + return (actor.get_style_class_name() ?? '').split(/\s+/).includes(style_class); + + return false; + } + + is_window_actor(actor) { + if (!actor || this.destroyed_actors.has(actor)) + return false; + return actor.get_parent() === global.window_group; + } + + is_internal_actor(actor) { + if (!actor) + return false; + + if (this.has_any_style_class(actor, POPUP_INTERNAL_STYLE_CLASSES)) + return true; + + if (this.destroyed_actors.has(actor)) + return false; + + return POPUP_INTERNAL_NAMES.includes(actor.name ?? actor.get_name()); + } + + watch_actor(actor) { + if (!actor || this.destroyed_actors.has(actor)) + return false; + if (this.watched_actors.has(actor)) + return true; + + this.connections.connect(actor, 'destroy', () => { + this.destroyed_actors.add(actor); + this.containers.delete(actor); + }); + + this.watched_actors.add(actor); + return true; + } + + get_children(actor) { + if (!this.watch_actor(actor)) + return []; + + return actor.get_children(); + } + + get_actor_delegate(actor) { + if (!this.watch_actor(actor)) + return null; + + return actor._delegate || null; + } + + get_actor_overlay(actor) { + const delegate = this.get_actor_delegate(actor); + return (delegate && delegate._overlay) || null; + } + + get_actor_dialog_layout(actor) { + if (!this.watch_actor(actor)) + return null; + + return actor.dialogLayout || null; + } + + destroy_blur(actor) { + const surface = this.surfaces.get(actor); + if (!surface) + return; + + this.surfaces.delete(actor); + surface.destroy(); + } + + reset() { + if (!this.enabled) + return; + + this.cancel_queued_blurs(); + + this.disable(); + this.reset_id = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { + this.reset_id = 0; + + if (this.settings.popup.BLUR) + this.enable(); + + return GLib.SOURCE_REMOVE; + }); + } + + update_pipeline() { + this.surfaces.forEach(surface => surface.update_pipeline()); + } + + _get_keyboard_actors() { + const actors = new Set(); + if (Main.keyboard && Main.keyboard.keyboardActor) + actors.add(Main.keyboard.keyboardActor); + if (Main.keyboard && Main.keyboard._keyboard) + actors.add(Main.keyboard._keyboard); + if (Main.layoutManager.keyboardBox) + Main.layoutManager.keyboardBox.get_children().forEach(child => actors.add(child)); + return [...actors]; + } + + update_background() { + [...POPUP_BACKGROUND_STYLES, ...POPUP_SURFACE_STYLES] + .forEach(style => Main.uiGroup.remove_style_class_name(style)); + + const keyboard_actors = this._get_keyboard_actors(); + keyboard_actors.forEach(actor => this.clear_keyboard_style(actor)); + [...POPUP_BACKGROUND_STYLES, ...POPUP_SURFACE_STYLES] + .forEach(style => keyboard_actors.forEach(actor => actor.remove_style_class_name(style))); + + let background_style = null; + if (this.settings.popup.OVERRIDE_BACKGROUND) { + const style = this.get_background_style(); + background_style = this.settings.popup.PRESERVE_SHELL_THEME ? + POPUP_SURFACE_STYLES[style] : + POPUP_BACKGROUND_STYLES[style]; + Main.uiGroup.add_style_class_name( + background_style + ); + } + keyboard_actors.forEach(actor => this.update_keyboard_style(actor, background_style)); + this.surfaces.forEach(surface => surface.update_settings()); + } + + clear_keyboard_style(actor, remove_marker = false) { + if (!actor) + return; + + if (remove_marker) + actor.remove_style_class_name(KEYBOARD_STYLE_CLASS); + + if (!this.settings.popup.OVERRIDE_BACKGROUND) + return; + + [...POPUP_BACKGROUND_STYLES, ...POPUP_SURFACE_STYLES] + .forEach(style => actor.remove_style_class_name(style)); + } + + update_keyboard_style(actor, background_style = null) { + if (!actor) + return; + + this.clear_keyboard_style(actor); + actor.add_style_class_name(KEYBOARD_STYLE_CLASS); + if (!this.settings.popup.OVERRIDE_BACKGROUND) + return; + + const style = background_style ?? ( + this.settings.popup.PRESERVE_SHELL_THEME ? + POPUP_SURFACE_STYLES[this.get_background_style()] : + POPUP_BACKGROUND_STYLES[this.get_background_style()] + ); + actor.add_style_class_name(style); + } + + get_background_style() { + const style = this.settings.popup.STYLE_POPUP; + + if (style >= 0 && style < POPUP_BACKGROUND_STYLES.length) + return style; + + const theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); + let uri = theme?.default_stylesheet?.get_uri(); + if (theme?.application_stylesheet) + uri = theme?.application_stylesheet?.get_uri(); + const lower_uri = typeof uri === 'string' ? uri.toLowerCase() : ''; + if (lower_uri.includes('yaru')) + return lower_uri.includes('dark') ? 2 : 1; + + const shell_style = Main.getStyleVariant(); + if (shell_style === 'light') + return 1; + + if (shell_style === 'dark') + return 2; + + return this.interface_settings.get_string('color-scheme') === 'prefer-dark' ? 2 : 1; + } + + disable() { + if (this.reset_id) { + GLib.source_remove(this.reset_id); + this.reset_id = 0; + } + + this.cancel_queued_blurs(); + + if (!this.enabled) { + this._log("blur already removed"); + return; + } + + this._log("removing blur from popup surfaces"); + this.enabled = false; + + const keyboard_actors = this._get_keyboard_actors(); + keyboard_actors.forEach(actor => this.clear_keyboard_style(actor, true)); + [...POPUP_BACKGROUND_STYLES, ...POPUP_SURFACE_STYLES] + .forEach(style => keyboard_actors.forEach(actor => actor.remove_style_class_name(style))); + + [...POPUP_BACKGROUND_STYLES, ...POPUP_SURFACE_STYLES] + .forEach(style => Main.uiGroup.remove_style_class_name(style)); + + const actors = [...this.surfaces.keys()]; + actors.forEach(actor => this.destroy_blur(actor)); + this.surfaces.clear(); + this.containers.clear(); + this.watched_actors = new WeakSet(); + this.destroyed_actors = new WeakSet(); + this.message_stacks.disable(); + + this.connections.disconnect_all(); + } + + _log(str) { + if (this.settings.DEBUG) + console.log(`[Blur my Shell > popup blur] ${str}`); + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/message_stacks.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/message_stacks.js new file mode 100644 index 0000000..cc4af30 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/message_stacks.js @@ -0,0 +1,571 @@ +import GLib from 'gi://GLib'; + +const STACKED_PSEUDO_CLASSES = ['second-in-stack', 'lower-in-stack']; +const MESSAGE_CONTAINER_STYLE_CLASSES = ['message-list', 'message-view', 'message-notification-group']; +const INTERNAL_STYLE_CLASSES = ['bms-popup-blurred-widget', 'bms-popup-backgroundgroup']; +const INTERNAL_NAMES = ['bms-popup-blurred-widget', 'bms-popup-backgroundgroup']; + +export const PopupBlurMessageStacks = class PopupBlurMessageStacks { + constructor(connections) { + this.connections = connections; + this.containers = new Set(); + this.groups = new Set(); + this.messages = new Set(); + this.queued_actors = new WeakSet(); + this.watched_actors = new WeakSet(); + this.destroyed_actors = new WeakSet(); + this.bms_clipped = new WeakSet(); + this.group_connections = new Map(); + this.update_ids = new Map(); + this.original_opacity = new WeakMap(); + this.original_message_opacity = new WeakMap(); + this.enabled = false; + } + + enable() { + this.enabled = true; + } + + track_container(container) { + if (!container || this.containers.has(container)) + return; + if (!this.watch_actor(container)) + return; + + this.containers.add(container); + this.scan(container); + + this.connect( + container, + 'child-added', + (_, child) => { + this.queue_scan(child); + this.queue_update_all(); + } + ); + + this.connect( + container, + 'child-removed', + () => this.queue_update_all() + ); + } + + queue_scan(actor) { + if (this.is_internal_actor(actor) || !this.watch_actor(actor) || this.queued_actors.has(actor)) + return; + + this.queued_actors.add(actor); + this.scan(actor); + this.queued_actors.delete(actor); + } + + scan(actor, seen = new WeakSet()) { + if (this.is_internal_actor(actor) || !this.watch_actor(actor) || seen.has(actor)) + return; + + seen.add(actor); + + if (this.has_any_style_class(actor, MESSAGE_CONTAINER_STYLE_CLASSES)) + this.track_container(actor); + + if (this.has_style_class(actor, 'message-notification-group')) + this.track_group(actor); + + if (this.has_style_class(actor, 'message')) + this.track_message(actor); + + this.get_children(actor).forEach(child => this.scan(child, seen)); + + const child = this.get_child(actor); + if (child) + this.scan(child, seen); + } + + track_message(message) { + if (this.is_internal_actor(message) || !this.watch_actor(message) || this.messages.has(message)) + return; + + this.messages.add(message); + this.update_message(message); + + this.connect( + message, + 'style-changed', + () => this.queue_update_message(message) + ); + + this.connect( + message, + 'notify::pseudo-class', + () => this.queue_update_message(message) + ); + + this.connect( + message, + 'notify::allocation', + () => this.queue_update_message(message) + ); + + this.connect( + message, + 'destroy', + () => { + this.cancel_update(message); + this.remove_stack_mask(message); + this.messages.delete(message); + } + ); + } + + track_group(group) { + if (!this.watch_actor(group) || this.groups.has(group)) + return; + + this.groups.add(group); + this.update_group_header(group); + + this.connect( + group, + 'notify::expanded', + () => this.update_all() + ); + + this.connect( + group, + 'notify::allocation', + () => this.update_group_header(group) + ); + + if (group.layout_manager) { + const lm = group.layout_manager; + const id = lm.connect('notify::expansion', () => { + this.update_group_header(group); + this.update_group_messages(group); + }); + this.group_connections.set(group, { lm, id }); + } + } + + untrack_group(group) { + if (this.group_connections.has(group)) { + const { lm, id } = this.group_connections.get(group); + lm.disconnect(id); + this.group_connections.delete(group); + } + this.groups.delete(group); + } + + update_all() { + this.groups.forEach(group => { + this.update_group_header(group); + this.update_group_messages(group); + }); + this.messages.forEach(message => { + if (!this.get_message_group(message)) + this.update_message(message); + }); + } + + update_group_header(group) { + if (!this.watch_actor(group)) + return; + + const header = group._headerBox; + if (!header) + return; + + const expansion = group.layout_manager?.expansion ?? (group.expanded ? 1 : 0); + const target_opacity = this.enabled ? Math.round(expansion * 255) : 255; + + header.opacity = target_opacity; + } + + get_group_messages(group) { + const list = []; + const find_messages = actor => { + if (this.has_style_class(actor, 'message')) { + list.push(actor); + return; + } + this.get_children(actor).forEach(find_messages); + }; + find_messages(group); + return list; + } + + update_group_messages(group) { + if (!this.enabled || !this.watch_actor(group)) + return; + + const expansion = group.layout_manager?.expansion ?? (group.expanded ? 1.0 : 0.0); + const messages = this.get_group_messages(group); + + messages.forEach((message, index) => { + this.update_message_with_expansion(message, index, expansion, group); + }); + } + + queue_update_all() { + this.messages.forEach(message => this.queue_update_message(message)); + } + + queue_update_message(message) { + if (this.update_ids.has(message)) + return; + + const id = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { + this.update_ids.delete(message); + + if (this.enabled && this.messages.has(message)) + this.update_message(message); + + return GLib.SOURCE_REMOVE; + }); + + this.update_ids.set(message, id); + } + + update_message(message) { + if (!this.enabled) { + this.remove_stack_mask(message); + return; + } + + const group = this.get_message_group(message); + if (group) { + const expansion = group.layout_manager?.expansion ?? (group.expanded ? 1.0 : 0.0); + const index = this.get_message_index_in_group(message); + this.update_message_with_expansion(message, index >= 0 ? index : 0, expansion, group); + } else { + const is_expanded = this.is_in_expanded_group(message); + if (this.is_stacked(message) && !is_expanded) { + this.apply_stack_mask(message); + this.hide_message_content(message); + this.restore_message_opacity(message); + } else { + this.remove_stack_mask(message); + } + } + } + + update_message_with_expansion(message, index, expansion, group) { + if (!this.enabled || !this.watch_actor(message)) + return; + + const is_stacked = this.is_stacked(message) || index > 0; + + if (!is_stacked) { + this.remove_stack_mask(message); + return; + } + + if (expansion >= 0.99) { + this.remove_stack_mask(message); + return; + } + + if (expansion <= 0.01) { + this.apply_stack_mask(message); + this.hide_message_content(message); + this.restore_message_opacity(message); + return; + } + + // 0.01 < expansion < 0.99: Animating unravel / collapse + const height = message.height || message.get_height() || 0; + const width = message.width || message.get_width() || 0; + + if (height <= 0 || width <= 0) + return; + + const base_edge = (index === 1) ? 10 : (index === 2 ? 7 : 0); + const visible_edge = Math.round(base_edge + (height - base_edge) * expansion); + const clip_y = Math.max(0, height - visible_edge); + + message.set_clip(0, clip_y, width, visible_edge); + this.bms_clipped.add(message); + + // Staggered opacity progress for cards so they smoothly fade in as they unravel + const stagger_start = Math.min(0.8, index * 0.04); + const progress = Math.min(1.0, Math.max(0.0, (expansion - stagger_start) / (1.0 - stagger_start))); + const target_alpha = Math.round(255 * progress); + + this.set_child_opacity(message, target_alpha); + + if (index >= 3) { + this.set_message_opacity(message, target_alpha); + } else { + this.restore_message_opacity(message); + } + } + + apply_stack_mask(message) { + if (!this.watch_actor(message)) + return; + + const height = message.height || message.get_height() || 0; + const width = message.width || message.get_width() || 0; + + if (height <= 0 || width <= 0) + return; + + const index = this.get_message_index_in_group(message); + + if (index === 1) { + // 2nd card: tight visible strip of 10px (matches exact 10px bottom offset below card 1) + const visible_edge = 10; + const clip_y = Math.max(0, height - visible_edge); + message.set_clip(0, clip_y, width, visible_edge); + this.bms_clipped.add(message); + } else if (index === 2) { + // 3rd card: tight visible strip of 7px (matches exact 7px bottom offset below card 2) + const visible_edge = 7; + const clip_y = Math.max(0, height - visible_edge); + message.set_clip(0, clip_y, width, visible_edge); + this.bms_clipped.add(message); + } else if (index >= 3) { + // 4th+ cards: hidden when collapsed so they don't stack behind card 3 + message.set_clip(0, height, width, 0); + this.bms_clipped.add(message); + } else { + // Fallback by pseudo class + const is_second = this.has_pseudo_class(message, 'second-in-stack'); + const visible_edge = is_second ? 10 : 6; + const clip_y = Math.max(0, height - visible_edge); + message.set_clip(0, clip_y, width, visible_edge); + this.bms_clipped.add(message); + } + } + + remove_stack_mask(message) { + if (!message || this.destroyed_actors.has(message)) + return; + + if (this.bms_clipped.has(message)) { + message.remove_clip(); + this.bms_clipped.delete(message); + } + + this.restore_message_content(message); + this.restore_message_opacity(message); + } + + set_child_opacity(message, opacity) { + const child = this.get_child(message); + if (!child) + return; + + if (!this.original_opacity.has(child)) + this.original_opacity.set(child, child.opacity ?? 255); + + child.opacity = opacity; + } + + hide_message_content(message) { + this.set_child_opacity(message, 0); + } + + restore_message_content(message) { + const child = this.get_child(message); + if (!child) + return; + + if (this.original_opacity.has(child)) { + child.opacity = this.original_opacity.get(child); + this.original_opacity.delete(child); + } + } + + set_message_opacity(message, opacity) { + if (!this.watch_actor(message)) + return; + + if (!this.original_message_opacity.has(message)) + this.original_message_opacity.set(message, message.opacity ?? 255); + + message.opacity = opacity; + } + + restore_message_opacity(message) { + if (!message || this.destroyed_actors.has(message)) + return; + + if (this.original_message_opacity.has(message)) { + message.opacity = this.original_message_opacity.get(message); + this.original_message_opacity.delete(message); + } + } + + get_message_index_in_group(message) { + const group = this.get_message_group(message); + if (!group) + return -1; + + const list = []; + const find_messages = actor => { + if (this.has_style_class(actor, 'message')) { + list.push(actor); + return; + } + actor.get_children().forEach(find_messages); + }; + find_messages(group); + return list.indexOf(message); + } + + has_pseudo_class(actor, pseudo_class) { + if (!actor || this.destroyed_actors.has(actor)) + return false; + + if (actor.has_style_pseudo_class) + return actor.has_style_pseudo_class(pseudo_class); + + if (actor.get_style_pseudo_class) + return (actor.get_style_pseudo_class() ?? '').split(/\s+/).includes(pseudo_class); + + return false; + } + + get_message_group(message) { + let actor = message ? message.get_parent() : null; + + while (actor && !this.destroyed_actors.has(actor)) { + if (this.has_style_class(actor, 'message-notification-group')) + return actor; + actor = actor.get_parent(); + } + return null; + } + + is_in_expanded_group(message) { + let actor = message ? message.get_parent() : null; + + while (actor && !this.destroyed_actors.has(actor)) { + if ( + this.has_style_class(actor, 'message-notification-group') + && actor.expanded + ) + return true; + actor = actor.get_parent(); + } + + return false; + } + + is_stacked(message) { + if (!message || this.destroyed_actors.has(message)) + return false; + return STACKED_PSEUDO_CLASSES.some(pseudo_class => { + if (message.has_style_pseudo_class) + return message.has_style_pseudo_class(pseudo_class); + + if (message.get_style_pseudo_class) + return (message.get_style_pseudo_class() ?? '').split(/\s+/).includes(pseudo_class); + + return false; + }); + } + + has_any_style_class(actor, style_classes) { + return style_classes.some(style_class => this.has_style_class(actor, style_class)); + } + + is_internal_actor(actor) { + if (!actor) + return false; + + if (this.has_any_style_class(actor, INTERNAL_STYLE_CLASSES)) + return true; + + if (this.destroyed_actors.has(actor)) + return false; + + return INTERNAL_NAMES.includes(actor.name ?? actor.get_name()); + } + + has_style_class(actor, style_class) { + if (!actor || this.destroyed_actors.has(actor)) + return false; + + if (actor.has_style_class_name) + return actor.has_style_class_name(style_class); + + if (actor.get_style_class_name) + return (actor.get_style_class_name() ?? '').split(/\s+/).includes(style_class); + + return false; + } + + watch_actor(actor) { + if (!actor || this.destroyed_actors.has(actor)) + return false; + if (this.watched_actors.has(actor)) + return true; + + this.connections.connect(actor, 'destroy', () => { + this.destroyed_actors.add(actor); + this.containers.delete(actor); + if (this.groups.has(actor)) { + this.untrack_group(actor); + } + this.messages.delete(actor); + this.cancel_update(actor); + }); + + this.watched_actors.add(actor); + return true; + } + + get_children(actor) { + if (this.is_internal_actor(actor) || !this.watch_actor(actor)) + return []; + + return actor.get_children(); + } + + get_child(actor) { + if (!this.watch_actor(actor)) + return null; + + return (actor.get_child ? actor.get_child() : actor.child) || null; + } + + cancel_update(message) { + const id = this.update_ids.get(message); + if (!id) + return; + + GLib.source_remove(id); + this.update_ids.delete(message); + } + + connect(actor, signal, handler) { + this.connections.connect(actor, signal, handler); + } + + disable() { + this.update_ids.forEach(id => GLib.source_remove(id)); + this.update_ids.clear(); + this.messages.forEach(message => this.remove_stack_mask(message)); + this.groups.forEach(group => { + if (group._headerBox) { + group._headerBox.opacity = 255; + } + this.untrack_group(group); + }); + this.group_connections.forEach(({ lm, id }) => { + lm.disconnect(id); + }); + this.group_connections.clear(); + this.messages.clear(); + this.groups.clear(); + this.containers.clear(); + this.watched_actors = new WeakSet(); + this.destroyed_actors = new WeakSet(); + this.bms_clipped = new WeakSet(); + this.original_opacity = new WeakMap(); + this.original_message_opacity = new WeakMap(); + this.enabled = false; + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/static_actor.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/static_actor.js new file mode 100644 index 0000000..c933b36 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/static_actor.js @@ -0,0 +1,301 @@ +import Meta from 'gi://Meta'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; + +import { Pipeline } from '../../conveniences/pipeline.js'; +import { transform_to_actor_space } from './surface_geometry.js'; +import { PopupBlurStaticCorner } from './static_corner.js'; +import { has_style_class } from './targets.js'; + +export const PopupBlurStaticActor = class PopupBlurStaticActor { + constructor(settings, effects_manager, target, root_actor, parent, get_corner_radius) { + this.settings = settings; + this.effects_manager = effects_manager; + this.target = target; + this.root_actor = root_actor; + this.parent = parent; + this.get_corner_radius = get_corner_radius; + this.static_corner = new PopupBlurStaticCorner(effects_manager, get_corner_radius); + this.background_group = null; + this.blur_actor = null; + this.bg_manager = null; + this.pipeline = null; + this.monitor_index = null; + this.opacity_factor = 1; + this.background_opacity = null; + this.x = null; + this.y = null; + this.width = null; + this.height = null; + } + + create() { + this.background_group = new Meta.BackgroundGroup({ + name: 'bms-popup-backgroundgroup', + width: 0, + height: 0, + }); + this.background_group.hide(); + this.background_group.connect('destroy', () => { + this.background_group = null; + }); + + return this.update_background(); + } + + get actor() { + return this.background_group; + } + + update_background(monitor_index = null) { + const monitor = this.find_monitor(monitor_index); + if (!monitor) + return false; + + if (monitor.index === this.monitor_index && this.blur_actor) + return true; + + this.destroy_background(); + + const bg_manager_list = []; + const pipeline = new Pipeline( + this.effects_manager, + global.blur_my_shell._pipelines_manager, + this.settings.popup.PIPELINE, + null, + { + effect_overrides: { + native_static_gaussian_blur: params => this.get_blur_effect_overrides(params, 'unscaled_radius'), + gaussian_blur: params => this.get_blur_effect_overrides(params, 'radius'), + monte_carlo_blur: params => this.get_blur_effect_overrides(params, 'radius'), + downscale: () => this.get_texture_effect_overrides(), + upscale: () => this.get_texture_effect_overrides(), + pixelize: () => this.get_texture_effect_overrides(), + derivative: () => this.get_texture_effect_overrides(), + refraction: () => this.get_texture_effect_overrides(), + color: params => this.get_color_effect_overrides(params), + luminosity: () => this.get_luminosity_effect_overrides(), + noise: params => this.get_noise_effect_overrides(params), + rgb_to_hsl: () => this.get_texture_effect_overrides(), + hsl_to_rgb: () => this.get_texture_effect_overrides(), + corner: () => ({ radius: this.get_corner_radius() }), + }, + } + ); + + this.blur_actor = pipeline.create_background_with_effects( + monitor.index, + bg_manager_list, + this.background_group, + 'bms-popup-blurred-widget' + ); + this.blur_actor.connect('destroy', () => { + this.blur_actor = null; + }); + this.blur_actor.hide(); + this.bg_manager = bg_manager_list[0]; + this.pipeline = pipeline; + this.monitor_index = monitor.index; + this.static_corner.bind(this.pipeline, this.blur_actor); + + return true; + } + + find_monitor(monitor_index = null) { + if (monitor_index !== null) + return Main.layoutManager.monitors[monitor_index] || null; + + return ( + Main.layoutManager.findMonitorForActor(this.target) + ?? Main.layoutManager.findMonitorForActor(this.root_actor) + ?? Main.layoutManager.primaryMonitor + ); + } + + is_screenshot_ui() { + return has_style_class(this.target, 'screenshot-ui-panel') + || has_style_class(this.root_actor, 'screenshot-ui-panel'); + } + + update_geometry(target_x, target_y, width, height, monitor_index = null) { + if (!this.update_background(monitor_index)) + return false; + if (!this.blur_actor) + return false; + + const monitor = Main.layoutManager.monitors[this.monitor_index]; + if (!monitor) + return false; + + const monitor_geometry = transform_to_actor_space(this.parent, monitor); + const target_geometry = transform_to_actor_space(this.parent, { + x: target_x, + y: target_y, + width, + height, + }); + if (!monitor_geometry || !target_geometry) + return false; + + const clip_x = Math.round(target_geometry.x - monitor_geometry.x); + const clip_y = Math.round(target_geometry.y - monitor_geometry.y); + const clip_width = Math.ceil(target_geometry.width); + const clip_height = Math.ceil(target_geometry.height); + + if (!this.blur_actor) + return false; + + if (this.is_screenshot_ui() && this.background_group) { + this.background_group.set_position(0, 0); + this.background_group.set_size(monitor_geometry.width, monitor_geometry.height); + } + + if (this.blur_actor.x !== monitor_geometry.x || this.blur_actor.y !== monitor_geometry.y) + this.blur_actor.set_position(monitor_geometry.x, monitor_geometry.y); + if ( + this.blur_actor.width !== monitor_geometry.width + || this.blur_actor.height !== monitor_geometry.height + ) + this.blur_actor.set_size(monitor_geometry.width, monitor_geometry.height); + + if ( + this.x !== clip_x + || this.y !== clip_y + || this.width !== clip_width + || this.height !== clip_height + ) { + this.blur_actor.set_clip(clip_x, clip_y, clip_width, clip_height); + this.x = clip_x; + this.y = clip_y; + this.width = clip_width; + this.height = clip_height; + } + + this.blur_actor.show(); + + return { x: clip_x, y: clip_y, width: clip_width, height: clip_height }; + } + + has_opacity(opacity) { + if (this.background_opacity !== opacity) + return false; + + const background_actor = this.get_background_actor(); + return !background_actor || background_actor.opacity === opacity; + } + + set_opacity(opacity, pipeline_opacity = opacity) { + this.set_opacity_factor(pipeline_opacity / 255); + if (this.background_group) + this.background_group.opacity = 255; + if (this.blur_actor) + this.blur_actor.opacity = 255; + + this.background_opacity = opacity; + + const background_actor = this.get_background_actor(); + if (background_actor) + background_actor.opacity = opacity; + + this.blur_actor?.get_children().forEach(child => child.opacity = opacity); + } + + set_opacity_factor(opacity_factor) { + opacity_factor = Math.max(0, Math.min(1, opacity_factor)); + if (this.opacity_factor === opacity_factor) + return; + + this.opacity_factor = opacity_factor; + this.pipeline?.apply_effect_overrides(); + } + + get_blur_effect_overrides(params, radius_key) { + const overrides = {}; + + if (radius_key in params) + overrides[radius_key] = params[radius_key] * this.opacity_factor; + if ('brightness' in params) + overrides.brightness = 1 - (1 - params.brightness) * this.opacity_factor; + + return overrides; + } + + get_color_effect_overrides(params) { + const overrides = this.get_texture_effect_overrides(); + + if (Array.isArray(params.color) && params.color.length >= 4) + overrides.color = params.color; + + return overrides; + } + + get_luminosity_effect_overrides() { + return this.get_texture_effect_overrides(); + } + + get_noise_effect_overrides(params) { + const overrides = this.get_texture_effect_overrides(); + + if ('noise' in params) + overrides.noise = params.noise; + + return overrides; + } + + get_texture_effect_overrides() { + return { + opacity_factor: this.opacity_factor, + }; + } + + get_background_actor() { + return this.bg_manager ? (this.bg_manager.backgroundActor || null) : null; + } + + update_settings() { + this.static_corner.update(); + } + + update_pipeline() { + this.bg_manager?._bms_pipeline.change_pipeline_to(this.settings.popup.PIPELINE); + this.static_corner.update(); + } + + destroy() { + const background_group = this.background_group; + this.destroy_background(); + this.background_group = null; + + if (background_group) + background_group.destroy(); + } + + destroy_background() { + const bg_manager = this.bg_manager; + const blur_actor = this.blur_actor; + this.bg_manager = null; + this.blur_actor = null; + this.pipeline = null; + + this.static_corner.destroy(); + + if (bg_manager) { + if (bg_manager._bms_pipeline) { + bg_manager._bms_pipeline.destroy(); + bg_manager._bms_pipeline = null; + } + if (!blur_actor) + bg_manager.backgroundActor = null; + bg_manager.destroy(); + } else if (this.background_group) { + this.background_group.destroy_all_children(); + } + blur_actor?.destroy(); + + this.monitor_index = null; + this.background_opacity = null; + this.x = null; + this.y = null; + this.width = null; + this.height = null; + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/static_corner.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/static_corner.js new file mode 100644 index 0000000..e575e09 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/static_corner.js @@ -0,0 +1,70 @@ +export const PopupBlurStaticCorner = class PopupBlurStaticCorner { + constructor(effects_manager, get_radius) { + this.effects_manager = effects_manager; + this.get_radius = get_radius; + this.pipeline = null; + this.actor = null; + this.effect = null; + } + + bind(pipeline, actor) { + this.pipeline = pipeline; + this.actor = actor; + this.update(); + } + + update() { + if (!this.pipeline || !this.actor) + return; + + this.pipeline.apply_effect_overrides('corner'); + + if (this.pipeline_has_corner_effect()) { + this.destroy_external_effect(); + return; + } + + if (!this.effect) { + this.effect = this.effects_manager.new_corner_effect({ + radius: this.get_radius(), + }); + this.attach_external_effect_as_outermost(); + return; + } + + this.effect.radius = this.get_radius(); + } + + attach_external_effect_as_outermost() { + const existing_effects = this.pipeline?.effects ?? []; + + existing_effects.forEach(effect => { + this.actor.remove_effect(effect); + }); + + this.actor.add_effect(this.effect); + + existing_effects.forEach(effect => { + this.actor.add_effect(effect); + }); + } + + pipeline_has_corner_effect() { + const corner_class = this.effects_manager.SUPPORTED_EFFECTS.corner.class; + return this.pipeline.effects.some(effect => effect instanceof corner_class); + } + + destroy_external_effect() { + if (!this.effect) + return; + + this.effects_manager.remove(this.effect); + this.effect = null; + } + + destroy() { + this.destroy_external_effect(); + this.pipeline = null; + this.actor = null; + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_fade.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_fade.js new file mode 100644 index 0000000..2a0b9a5 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_fade.js @@ -0,0 +1,132 @@ +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import { has_style_class } from './targets.js'; + +export const PopupBlurSurfaceFade = class PopupBlurSurfaceFade { + constructor(actor, target, root_actor, parent) { + this.actor = actor; + this.target = target; + this.root_actor = root_actor; + this.parent = parent; + } + + get_opacity() { + let opacity = 255; + const visited = new WeakSet(); + let actor = this.target; + + while (actor && actor !== this.parent) { + opacity = this.apply_actor_opacity(opacity, actor, visited); + actor = actor.get_parent(); + } + + opacity = this.apply_actor_opacity(opacity, this.root_actor, visited); + + [ + this.target, + this.root_actor, + ].forEach(actor => { + const paint_opacity = this.get_paint_opacity(actor); + if (paint_opacity !== null) + opacity = Math.min(opacity, paint_opacity); + }); + + if (this.is_notification_banner()) { + opacity = Math.round(opacity * this.get_banner_position_alpha()); + } + + return opacity; + } + + is_notification_banner() { + if (has_style_class(this.target, 'notification-banner')) + return true; + if (this.root_actor?.name === 'notification-container') + return true; + let a = this.target; + while (a && a !== this.parent) { + if (has_style_class(a, 'notification-banner')) + return true; + a = a.get_parent(); + } + return false; + } + + get_banner_position_alpha() { + try { + const [, stage_y] = this.target.get_transformed_position(); + + if (!Main.panel) + return 1; + + const monitor = Main.layoutManager.findMonitorForActor(Main.panel) + ?? Main.layoutManager.primaryMonitor; + + if (!monitor) + return 1; + + const [, panel_y] = Main.panel.get_transformed_position(); + const panel_width = Main.panel.width || Main.panel.get_width() || 0; + const panel_height = Main.panel.height || Main.panel.get_height() || 36; + + // Must be a horizontal panel anchored at the monitor's top edge + const is_horizontal = panel_width > panel_height; + const is_at_monitor_top = Math.abs(panel_y - monitor.y) <= 5; + + if (!is_horizontal || !is_at_monitor_top) + return 1; + + const panel_bottom = panel_y + panel_height; + const threshold = panel_bottom + 5; + + if (stage_y <= panel_y) + return 0; + if (stage_y >= threshold) + return 1; + + return Math.clamp((stage_y - panel_y) / (threshold - panel_y), 0, 1); + } catch (e) { + return 1; + } + } + + set_opacity(opacity) { + this.actor.opacity = opacity; + } + + apply_actor_opacity(opacity, actor, visited) { + if (!actor || visited.has(actor)) + return opacity; + + visited.add(actor); + + let visible = actor.visible; + let mapped = actor.mapped; + if (!visible && this.is_keyboard_actor(actor)) { + const parent = actor.get_parent(); + visible = parent?.visible && parent?.mapped; + mapped = parent?.mapped; + } + if (!visible || !mapped) + return 0; + + return Math.round(opacity * (actor.opacity ?? 255) / 255); + } + + is_keyboard_actor(actor) { + return ( + has_style_class(actor, 'bms-keyboard-surface') + ); + } + + get_paint_opacity(actor) { + if (this.is_keyboard_actor(actor) && (!actor.visible || !actor.mapped)) { + const parent = actor.get_parent(); + if (parent?.visible && parent?.mapped) + return null; + } + if (actor?.get_paint_opacity) + return actor.get_paint_opacity(); + + return null; + } +}; \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_geometry.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_geometry.js new file mode 100644 index 0000000..84832d9 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_geometry.js @@ -0,0 +1,291 @@ +import St from 'gi://St'; + +export function transform_to_actor_space(actor, { x, y, width, height }) { + if (!actor) + return null; + const [actor_x, actor_y] = actor.get_transformed_position(); + const [actor_width, actor_height] = actor.get_size(); + const [transformed_width, transformed_height] = actor.get_transformed_size(); + const scale_x = actor_width > 0 ? transformed_width / actor_width : 1; + const scale_y = actor_height > 0 ? transformed_height / actor_height : 1; + + return { + x: (x - actor_x) / scale_x, + y: (y - actor_y) / scale_y, + width: width / scale_x, + height: height / scale_y, + }; +} + +export const PopupBlurSurfaceGeometry = class PopupBlurSurfaceGeometry { + get(actor, { use_content = true, use_margins = true } = {}) { + const actor_geometry = this.get_transformed_actor(actor); + if (!this.has_valid_geometry(actor_geometry)) + return actor_geometry; + + const margin_geometry = use_margins + ? this.get_margin_adjusted(actor, actor_geometry) + : actor_geometry; + if (!use_content) + return margin_geometry; + + const content_geometry = this.get_transformed_content(actor, margin_geometry); + + if (!this.should_use_content(margin_geometry, content_geometry)) + return margin_geometry; + + return content_geometry; + } + + get_transformed_actor(actor) { + const extents = actor.get_transformed_extents(); + const top_left = extents?.get_top_left(); + const bottom_right = extents?.get_bottom_right(); + + if (top_left && bottom_right) { + return { + x: top_left.x, + y: top_left.y, + width: bottom_right.x - top_left.x, + height: bottom_right.y - top_left.y, + }; + } + + if (!actor) + return null; + const [x, y] = actor.get_transformed_position(); + const [width, height] = actor.get_transformed_size(); + return { x, y, width, height }; + } + + get_transformed_clip(actor) { + if (!actor?.has_clip) + return null; + + const [clip_x, clip_y, clip_width, clip_height] = actor.get_clip(); + if (clip_width <= 0 || clip_height <= 0) + return null; + + const [actor_x, actor_y] = actor.get_transformed_position(); + const [actor_width, actor_height] = actor.get_transformed_size(); + const scale_x = this.get_actor_scale(actor, actor_width, 'width'); + const scale_y = this.get_actor_scale(actor, actor_height, 'height'); + + return { + x: actor_x + clip_x * scale_x, + y: actor_y + clip_y * scale_y, + width: clip_width * scale_x, + height: clip_height * scale_y, + }; + } + + get_margin_adjusted(actor, geometry) { + const margins = this.get_margins(actor); + if (!margins) + return geometry; + + const scale_x = this.get_actor_scale(actor, geometry.width, 'width'); + const scale_y = this.get_actor_scale(actor, geometry.height, 'height'); + + return this.shrink(geometry, + margins.top * scale_y, + margins.right * scale_x, + margins.bottom * scale_y, + margins.left * scale_x + ) ?? geometry; + } + + get_transformed_content(actor, boundary) { + const children = this.get_transformed_children(actor); + if (!this.has_valid_geometry(children)) + return null; + + const insets = this.get_paint_insets(actor, boundary); + const geometry = this.inflate( + children, + insets.top, + insets.right, + insets.bottom, + insets.left + ); + + return this.intersect(geometry, boundary); + } + + get_transformed_children(actor) { + let geometry = null; + + this.get_children(actor).forEach(child => { + if (!this.is_visible(child)) + return; + + const child_geometry = this.get_transformed_actor(child); + if (!this.has_valid_geometry(child_geometry)) + return; + + geometry = this.union(geometry, child_geometry); + }); + + return geometry; + } + + get_margins(actor) { + const margins = { + top: this.get_margin(actor, 'top', St.Side.TOP), + right: this.get_margin(actor, 'right', St.Side.RIGHT), + bottom: this.get_margin(actor, 'bottom', St.Side.BOTTOM), + left: this.get_margin(actor, 'left', St.Side.LEFT), + }; + + return Object.values(margins).some(margin => margin > 0) ? margins : null; + } + + get_margin(actor, side_name, side) { + const property_names = [ + `margin_${side_name}`, + `margin${side_name[0].toUpperCase()}${side_name.slice(1)}`, + ]; + + for (const property of property_names) { + const value = actor[property]; + if (typeof value === 'number') + return value; + } + + const getter = actor[`get_margin_${side_name}`]; + if (getter) { + const value = getter.call(actor); + if (typeof value === 'number') + return value; + } + + try { + const theme_node = actor.get_theme_node(); + if (!theme_node?.get_margin) + return 0; + + return theme_node.get_margin(side); + } catch (e) { + // get_theme_node() may throw when actor is not yet mapped to a stage + return 0; + } + } + + get_paint_insets(actor, geometry) { + const scale_x = this.get_actor_scale(actor, geometry.width, 'width'); + const scale_y = this.get_actor_scale(actor, geometry.height, 'height'); + + return { + top: this.get_inset(actor, St.Side.TOP) * scale_y, + right: this.get_inset(actor, St.Side.RIGHT) * scale_x, + bottom: this.get_inset(actor, St.Side.BOTTOM) * scale_y, + left: this.get_inset(actor, St.Side.LEFT) * scale_x, + }; + } + + get_inset(actor, side) { + try { + const theme_node = actor.get_theme_node(); + if (!theme_node) + return 0; + + let inset = 0; + if (theme_node.get_padding) + inset += theme_node.get_padding(side); + if (theme_node.get_border_width) + inset += theme_node.get_border_width(side); + return inset; + } catch (e) { + // get_theme_node() may throw when actor is not yet mapped to a stage + return 0; + } + } + + get_actor_scale(actor, transformed_size, property) { + const size = actor ? (actor[property] ?? (actor[`get_${property}`] ? actor[`get_${property}`]() : 0)) : 0; + return size > 0 ? transformed_size / size : 1; + } + + should_use_content(outer, content) { + if (!this.has_valid_geometry(content)) + return false; + + if ( + content.width > outer.width + 1 + || content.height > outer.height + 1 + ) + return false; + + return outer.width - content.width > 2 || outer.height - content.height > 2; + } + + is_visible(actor) { + return actor?.visible && actor.mapped; + } + + get_children(actor) { + return actor ? actor.get_children() : []; + } + + has_valid_geometry(geometry) { + return geometry?.width > 0 && geometry?.height > 0; + } + + shrink(geometry, top, right, bottom, left) { + const width = geometry.width - left - right; + const height = geometry.height - top - bottom; + + if (width <= 0 || height <= 0) + return null; + + return { + x: geometry.x + left, + y: geometry.y + top, + width, + height, + }; + } + + inflate(geometry, top, right, bottom, left) { + return { + x: geometry.x - left, + y: geometry.y - top, + width: geometry.width + left + right, + height: geometry.height + top + bottom, + }; + } + + intersect(a, b) { + const x1 = Math.max(a.x, b.x); + const y1 = Math.max(a.y, b.y); + const x2 = Math.min(a.x + a.width, b.x + b.width); + const y2 = Math.min(a.y + a.height, b.y + b.height); + + if (x2 <= x1 || y2 <= y1) + return null; + + return { + x: x1, + y: y1, + width: x2 - x1, + height: y2 - y1, + }; + } + + union(a, b) { + if (!a) + return b; + + const x1 = Math.min(a.x, b.x); + const y1 = Math.min(a.y, b.y); + const x2 = Math.max(a.x + a.width, b.x + b.width); + const y2 = Math.max(a.y + a.height, b.y + b.height); + + return { + x: x1, + y: y1, + width: x2 - x1, + height: y2 - y1, + }; + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_placement.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_placement.js new file mode 100644 index 0000000..cad36f9 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_placement.js @@ -0,0 +1,328 @@ +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; + +import { PopupBlurSurfaceGeometry, transform_to_actor_space } from './surface_geometry.js'; + +export const PopupBlurSurfacePlacement = class PopupBlurSurfacePlacement { + constructor(surface) { + this.surface = surface; + this.geometry = new PopupBlurSurfaceGeometry(); + this.clear(); + this.ready = false; + } + + get_surface_geometry() { + this.offscreen = false; + + const geometry = this.get_unclipped_surface_geometry(); + if (!this.has_valid_geometry(geometry)) + return null; + + const clipped_geometry = this.get_clipped_surface_geometry(geometry); + if (!this.has_valid_geometry(clipped_geometry)) + return null; + + const monitor_geometry = this.get_monitor_clipped_surface_geometry(clipped_geometry); + if (!this.has_valid_geometry(monitor_geometry)) { + this.offscreen = true; + return null; + } + + return monitor_geometry; + } + + get_unclipped_monitor_surface_geometry() { + this.offscreen = false; + + const geometry = this.get_unclipped_surface_geometry(); + if (!this.has_valid_geometry(geometry)) + return null; + + const monitor_geometry = this.get_monitor_clipped_surface_geometry(geometry); + if (!this.has_valid_geometry(monitor_geometry)) { + this.offscreen = true; + return null; + } + + return monitor_geometry; + } + + get_unclipped_surface_geometry() { + const geometry_actor = this.surface.get_geometry_actor(); + const geometry = this.geometry.get(geometry_actor, { + use_content: this.surface.should_use_content_geometry(), + use_margins: this.surface.should_use_margin_geometry(), + }); + if (!this.has_valid_geometry(geometry)) + return null; + + return this.create_surface_geometry( + geometry.x, + geometry.y, + geometry.width, + geometry.height + ); + } + + create_surface_geometry(target_x, target_y, width, height) { + const local_geometry = transform_to_actor_space(this.surface.parent, { + x: target_x, + y: target_y, + width, + height, + }); + if (!local_geometry) + return null; + + return { + target_x, + target_y, + target_width: width, + target_height: height, + x: Math.round(local_geometry.x), + y: Math.round(local_geometry.y), + width: Math.ceil(local_geometry.width), + height: Math.ceil(local_geometry.height), + }; + } + + get_clipped_surface_geometry(geometry) { + let clipped = { + x: geometry.target_x, + y: geometry.target_y, + width: geometry.target_width, + height: geometry.target_height, + }; + + let actor = this.surface.get_geometry_actor(); + while (actor && actor !== this.surface.parent) { + const clip = this.geometry.get_transformed_clip(actor); + if (clip) { + clipped = this.geometry.intersect(clipped, clip); + if (!this.has_valid_geometry(clipped)) + return null; + } + + actor = actor.get_parent(); + } + + return this.create_surface_geometry( + clipped.x, + clipped.y, + clipped.width, + clipped.height + ); + } + + get_monitor_clipped_surface_geometry(geometry) { + const rect = { + x: geometry.target_x, + y: geometry.target_y, + width: geometry.target_width, + height: geometry.target_height, + }; + const cached_monitor = this.get_cached_monitor(); + const match = cached_monitor + ? this.get_monitor_intersection(rect, cached_monitor.monitor, cached_monitor.index) + : this.find_best_monitor_intersection(rect); + + if (!match) + return null; + + this.monitor_index = match.monitor_index; + + const surface_geometry = this.create_surface_geometry( + rect.x, + rect.y, + rect.width, + rect.height + ); + surface_geometry.monitor_index = match.monitor_index; + return surface_geometry; + } + + get_cached_monitor() { + if (this.monitor_index === null) + return null; + + const monitor = Main.layoutManager.monitors?.[this.monitor_index]; + if (!monitor) { + this.monitor_index = null; + return null; + } + + return { monitor, index: this.monitor_index }; + } + + find_best_monitor_intersection(rect) { + let best_match = null; + let best_area = 0; + + (Main.layoutManager.monitors ?? []).forEach((monitor, index) => { + const match = this.get_monitor_intersection(rect, monitor, index); + if (!match) + return; + + const area = match.intersection.width * match.intersection.height; + if (area > best_area) { + best_match = match; + best_area = area; + } + }); + + return best_match; + } + + get_monitor_intersection(rect, monitor, monitor_index) { + const intersection = this.geometry.intersect(rect, monitor); + if (!this.has_valid_geometry(intersection)) + return null; + + return { + monitor_index, + intersection, + }; + } + + has_valid_geometry(geometry) { + return geometry?.width > 0 && geometry?.height > 0; + } + + keep_transition_visible(transition_state) { + if (this.offscreen || !this.ready || !this.has_cached_geometry() || !transition_state.running) + return false; + + const opacity = this.surface.update_opacity(transition_state); + if (opacity <= 0) + return false; + + if (this.surface.static_blur) { + this.surface.blur_actor?.show(); + } + this.surface.show_actors(); + return true; + } + + has_cached_geometry() { + return ( + this.x !== null + && this.y !== null + && this.width > 0 + && this.height > 0 + ); + } + + has_cached_surface_geometry() { + return ( + this.surface_x !== null + && this.surface_y !== null + && this.surface_width > 0 + && this.surface_height > 0 + ); + } + + has_surface_geometry_changed(geometry) { + return ( + this.has_valid_geometry(geometry) + && ( + !this.has_cached_surface_geometry() + || this.surface_x !== geometry.x + || this.surface_y !== geometry.y + || this.surface_width !== geometry.width + || this.surface_height !== geometry.height + ) + ); + } + + store_surface_geometry(geometry) { + this.surface_x = geometry.x; + this.surface_y = geometry.y; + this.surface_width = geometry.width; + this.surface_height = geometry.height; + } + + prepare_visible_geometry() { + if (this.ready) + return true; + + this.ready = true; + this.surface.opacity = 0; + this.surface.update_surface_opacity(0); + this.surface.hide_actors(); + this.surface.queue_update(); + return false; + } + + update_surface_geometry(geometry) { + if (this.surface.static_blur) { + if (!this.update_static_geometry( + geometry.target_x, + geometry.target_y, + geometry.target_width, + geometry.target_height + )) + return false; + } else { + if (!this.update_dynamic_geometry(geometry.x, geometry.y, geometry.width, geometry.height)) + return false; + } + + this.store_surface_geometry(geometry); + return true; + } + + update_dynamic_geometry(x, y, width, height) { + if (this.x !== x || this.y !== y) { + this.surface.blur_actor.set_position(x, y); + this.x = x; + this.y = y; + } + + if (this.width !== width || this.height !== height) { + this.surface.blur_actor.set_size(width, height); + this.width = width; + this.height = height; + } + + return true; + } + + update_static_geometry(target_x, target_y, width, height) { + const geometry = this.surface.static_actor.update_geometry( + target_x, + target_y, + width, + height, + this.monitor_index + ); + this.surface.sync_static_actor(); + + if (!geometry) { + this.surface.hide_actors(); + return false; + } + + this.x = geometry.x; + this.y = geometry.y; + this.width = geometry.width; + this.height = geometry.height; + return true; + } + + hide() { + this.ready = false; + this.clear(); + } + + clear() { + this.x = null; + this.y = null; + this.width = null; + this.height = null; + this.surface_x = null; + this.surface_y = null; + this.surface_width = null; + this.surface_height = null; + this.monitor_index = null; + this.offscreen = false; + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_signals.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_signals.js new file mode 100644 index 0000000..47adb91 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_signals.js @@ -0,0 +1,117 @@ +import Meta from 'gi://Meta'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; + +const SURFACE_SIGNALS = [ + 'notify::allocation', + 'notify::position', + 'notify::size', + 'notify::x', + 'notify::y', + 'notify::width', + 'notify::height', + 'notify::clip-rect', + 'notify::visible', + 'notify::mapped', + 'notify::opacity', + 'notify::translation-x', + 'notify::translation-y', + 'notify::scale-x', + 'notify::scale-y', + 'notify::pseudo-class', +]; + +export const PopupBlurSurfaceSignals = class PopupBlurSurfaceSignals { + constructor(surface) { + this.surface = surface; + this.signal_ids = []; + this.signal_actors = new WeakSet(); + this.destroyed_actors = new WeakSet(); + } + + connect_actor(actor) { + if (!actor || this.signal_actors.has(actor)) + return; + + this.signal_actors.add(actor); + this.track_destroy(actor); + + const is_heavy_surface = this.surface.is_heavy_surface(); + + SURFACE_SIGNALS.forEach(signal => { + let id = actor.connect(signal, () => { + this.clear_pending_idles(); + const is_visibility_change = signal === 'notify::visible' || signal === 'notify::mapped'; + if (is_heavy_surface || is_visibility_change) { + this.surface.queue_update(); + return; + } + else { + this.updateId = global.compositor.get_laters().add(Meta.LaterType.IDLE, () => { + this.updateId = 0; + this.surface.queue_update(); + return false; + }); + } + }); + this.signal_ids.push([actor, id, signal]); + }); + } + + track_destroy(actor) { + const id = actor.connect('destroy', () => this.destroyed_actors.add(actor)); + this.signal_ids.push([actor, id]); + } + + connect_ancestors(actor) { + actor = actor ? actor.get_parent() : null; + + while (actor && actor !== this.surface.parent) { + this.connect_actor(actor); + actor = actor.get_parent(); + } + } + + connect_layout() { + if (!this.surface.static_blur) + return; + + this.signal_ids.push([ + Main.layoutManager, + Main.layoutManager.connect('monitors-changed', () => this.surface.queue_update()), + ]); + } + + connect_settings() { + [ + this.surface.corner_radius.key, + 'override-background', + 'style-popup', + ].forEach(key => { + const id = this.surface.settings.popup.settings.connect( + `changed::${key}`, + () => this.surface.update_settings() + ); + this.signal_ids.push([this.surface.settings.popup.settings, id]); + }); + } + + clear_pending_idles() { + if (this.updateId) { + global.compositor.get_laters().remove(this.updateId); + this.updateId = 0; + } + } + + disconnect_all() { + this.clear_pending_idles(); + this.signal_ids.forEach(([signal_actor, signal_id]) => { + if (this.destroyed_actors.has(signal_actor)) + return; + + signal_actor.disconnect(signal_id); + }); + this.signal_ids = []; + this.signal_actors = new WeakSet(); + this.destroyed_actors = new WeakSet(); + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_style.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_style.js new file mode 100644 index 0000000..1dfb947 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_style.js @@ -0,0 +1,59 @@ +export const PopupBlurSurfaceStyle = class PopupBlurSurfaceStyle { + constructor(surface) { + this.surface = surface; + this.original_target_style = null; + this.target_style_set = false; + } + + capture_target_style() { + this.original_target_style = this.surface.target ? this.surface.target.get_style() : null; + } + + update_target_style() { + if ( + !this.surface.target.set_style + || !this.surface.settings.popup.OVERRIDE_BACKGROUND + ) { + this.restore_target_style(); + return; + } + + if ( + this.has_style_class(this.surface.target, 'bms-keyboard-surface') + ) + return; + + const base_style = this.original_target_style ?? ''; + const separator = base_style.trim() && !base_style.trim().endsWith(';') ? '; ' : ''; + + this.surface.target.set_style( + `${base_style}${separator}border-radius: ${this.surface.get_corner_radius()}px;` + ); + this.target_style_set = true; + } + + restore_target_style() { + if (!this.target_style_set || !this.surface.target.set_style) + return; + + this.surface.target.set_style(this.original_target_style); + this.target_style_set = false; + } + + has_any_style_class(actor, style_classes) { + return style_classes.some(style_class => this.has_style_class(actor, style_class)); + } + + has_style_class(actor, style_class) { + if (!actor) + return false; + + if (actor.has_style_class_name) + return actor.has_style_class_name(style_class); + + if (actor.get_style_class_name) + return (actor.get_style_class_name() ?? '').split(/\s+/).includes(style_class); + + return false; + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_transitions.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_transitions.js new file mode 100644 index 0000000..70fd520 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_transitions.js @@ -0,0 +1,139 @@ +const GEOMETRY_TRANSITION_PROPERTIES = [ + 'x', + 'y', + 'width', + 'height', + 'clip-rect', + 'clip_rect', + 'translation-x', + 'translation-y', + 'translation_x', + 'translation_y', + 'scale-x', + 'scale-y', + 'scale_x', + 'scale_y', +]; + +export const PopupBlurSurfaceTransitions = class PopupBlurSurfaceTransitions { + constructor(surface) { + this.surface = surface; + } + + has_running() { + return this.get_state().running; + } + + get_state(include_descendants = false) { + const surface_actors = this.get_surface_actors(); + const actors = include_descendants + ? this.get_actors(surface_actors) + : surface_actors; + const geometry_properties = this.get_running_properties( + GEOMETRY_TRANSITION_PROPERTIES, + actors + ); + const opacity = this.has_running_for(['opacity'], surface_actors); + + return { + complete: include_descendants, + running: opacity || geometry_properties.size > 0, + geometry: geometry_properties.size > 0, + geometry_properties, + opacity, + }; + } + + complete_state(transition_state) { + if (transition_state.complete) + return transition_state; + + return this.get_state(true); + } + + has_running_for(properties, actors) { + return actors.some(actor => + properties.some(property => this.has_transition(actor, property)) + ); + } + + get_running_properties(properties, actors) { + const running_properties = new Set(); + + actors.forEach(actor => { + properties.forEach(property => { + if (this.has_transition(actor, property)) + running_properties.add(this.normalize_property(property)); + }); + }); + + return running_properties; + } + + normalize_property(property) { + return property.replace(/_/g, '-'); + } + + get_actors(surface_actors = this.get_surface_actors()) { + const actors = [...surface_actors]; + const seen = new WeakSet(); + actors.forEach(actor => seen.add(actor)); + + if (!this.surface.is_quick_settings()) { + this.add_descendants(actors, seen, this.surface.target); + this.add_descendants(actors, seen, this.surface.root_actor); + } + + return actors; + } + + get_surface_actors() { + const actors = []; + const seen = new WeakSet(); + + this.add_actor(actors, seen, this.surface.target); + this.add_actor(actors, seen, this.surface.root_actor); + this.add_actor(actors, seen, this.surface.get_geometry_actor()); + this.add_ancestors(actors, seen, this.surface.target); + this.add_ancestors(actors, seen, this.surface.root_actor); + + return actors; + } + + add_actor(actors, seen, actor) { + if (!actor || seen.has(actor)) + return; + + seen.add(actor); + actors.push(actor); + } + + add_ancestors(actors, seen, actor) { + actor = actor?.get_parent(); + while (actor && actor !== this.surface.parent) { + this.add_actor(actors, seen, actor); + actor = actor.get_parent(); + } + } + + add_descendants(actors, seen, actor) { + const stack = this.get_children(actor).slice().reverse(); + + while (stack.length > 0) { + const child = stack.pop(); + if (seen.has(child)) + continue; + + this.add_actor(actors, seen, child); + stack.push(...this.get_children(child).slice().reverse()); + } + } + + has_transition(actor, property) { + return !!actor?.get_transition(property); + } + + get_children(actor) { + return actor ? actor.get_children() : []; + } +}; diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/targets.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/targets.js new file mode 100644 index 0000000..dd537b0 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/targets.js @@ -0,0 +1,255 @@ +const POPUP_STYLE_CLASSES = ['popup-menu', 'quick-toggle-menu-container', 'candidate-popup-boxpointer']; +const POPUP_TARGET_STYLE_CLASSES = ['popup-menu-content', 'quick-settings', 'quick-toggle-menu', 'notification-banner', 'candidate-popup-content','screenshot-ui-panel']; +const POPUP_CHILD_STYLE_CLASSES = ['osd-window', 'resize-popup', 'switcher-list', 'workspace-switcher', 'modal-dialog', 'run-dialog']; +const POPUP_TARGET_STYLE_CLASSES_OSK = ['bms-keyboard-surface'] +const POPUP_DESCENDANT_TARGET_STYLE_CLASSES = ['switcher-list']; + +export const POPUP_BACKGROUND_STYLES = ['bms-popup-background-transparent', 'bms-popup-background-light', 'bms-popup-background-dark']; +export const POPUP_SURFACE_STYLES = POPUP_BACKGROUND_STYLES.map( + style => style.replace('bms-popup-background-', 'bms-popup-surface-') +); +export const DEFAULT_CORNER_RADIUS = { key: 'corner-radius', property: 'CORNER_RADIUS' }; +export const POPUP_CORNER_RADII = [ + { + key: 'quick-settings-corner-radius', + property: 'QUICK_SETTINGS_CORNER_RADIUS', + style_classes: ['quick-settings', 'quick-toggle-menu', 'datemenu-popover','screenshot-ui-panel'], + }, + { + key: 'notification-corner-radius', + property: 'NOTIFICATION_CORNER_RADIUS', + style_classes: ['notification-banner', 'message', 'message-view', 'message-list'], + }, + { + key: 'menu-corner-radius', + property: 'MENU_CORNER_RADIUS', + style_classes: ['popup-menu-content', 'popup-menu', 'candidate-popup-content', 'candidate-popup-boxpointer'], + }, + { + key: 'osd-corner-radius', + property: 'OSD_CORNER_RADIUS', + style_classes: ['osd-window', 'resize-popup', 'switcher-list', 'workspace-switcher'], + }, + { + key: 'dialog-corner-radius', + property: 'DIALOG_CORNER_RADIUS', + style_classes: ['modal-dialog', 'run-dialog'], + }, + { + key: 'osk-corner-radius', + property: 'OSK_CORNER_RADIUS', + style_classes: ['bms-keyboard-surface'], + }, +]; + +export const PopupBlurTargets = class PopupBlurTargets { + constructor(actor) { + this.actor = actor; + this.style_cache = null; + } + + find(actor) { + return this.with_style_cache(() => this.find_actor(actor)); + } + + find_actor(actor) { + if (this.actor.is_internal_actor(actor) || !this.actor.watch_actor(actor)) + return []; + + const targets = this.create_targets(); + const delegate = this.actor.get_actor_delegate(actor); + + if (this.prefers_descendant_targets(actor)) { + this.find_target_children(actor, targets); + if (targets.actors.length > 0) + return targets.actors; + } + + if (this.actor.watch_actor(delegate?.box) && (this.has_any_style_class(delegate.box, POPUP_TARGET_STYLE_CLASSES) || this.has_any_style_class(delegate.box, POPUP_TARGET_STYLE_CLASSES_OSK))) + this.add(targets, delegate.box); + + if (this.has_any_style_class(actor, POPUP_TARGET_STYLE_CLASSES)) + this.add(targets, actor); + + if (this.has_any_style_class(actor, POPUP_TARGET_STYLE_CLASSES_OSK)) + this.add(targets, actor); + + if (this.has_any_style_class(actor, POPUP_CHILD_STYLE_CLASSES)) + this.add(targets, actor); + + const dialog_layout = this.actor.get_actor_dialog_layout(actor); + if (this.actor.watch_actor(dialog_layout) && this.has_any_style_class(dialog_layout, POPUP_CHILD_STYLE_CLASSES)) + this.add(targets, dialog_layout); + + if (targets.actors.length === 0) + this.find_target_children(actor, targets); + + if ( + targets.actors.length === 0 + && this.has_any_style_class(actor, POPUP_STYLE_CLASSES) + ) + this.add(targets, actor); + + return targets.actors; + } + + find_target_children(actor, targets, seen = new WeakSet()) { + const stack = this.get_children(actor) + .slice() + .reverse() + .map(child => ({ actor: child, fallback_count: null })); + + while (stack.length > 0) { + const { actor: child, fallback_count } = stack.pop(); + if ( + !child + || this.actor.is_internal_actor(child) + ) + continue; + + if (fallback_count !== null) { + if ( + targets.actors.length === fallback_count + && this.is_blur_target_actor(child) + ) + this.add(targets, child); + continue; + } + + if (seen.has(child)) + continue; + + seen.add(child); + + if (this.prefers_descendant_targets(child)) { + const children = this.get_children(child); + if (children.length > 0) { + stack.push({ + actor: child, + fallback_count: targets.actors.length, + }); + this.push_children(stack, children); + continue; + } + } + + if (this.is_blur_target_actor(child)) { + this.add(targets, child); + continue; + } + + this.push_children(stack, this.get_children(child)); + } + } + + prefers_descendant_targets(actor) { + return this.has_any_style_class(actor, POPUP_DESCENDANT_TARGET_STYLE_CLASSES); + } + + is_blur_target_actor(actor) { + return ( + this.has_any_style_class(actor, POPUP_TARGET_STYLE_CLASSES) + || this.has_any_style_class(actor, POPUP_TARGET_STYLE_CLASSES_OSK) + || this.has_any_style_class(actor, POPUP_CHILD_STYLE_CLASSES) + ); + } + + get_corner_radius(target, root_actor) { + return POPUP_CORNER_RADII.find(radius => + this.has_any_style_class(target, radius.style_classes) + || this.has_any_style_class(root_actor, radius.style_classes) + ) ?? DEFAULT_CORNER_RADIUS; + } + + with_style_cache(callback) { + const previous_cache = this.style_cache; + this.style_cache = new WeakMap(); + + try { + return callback(); + } finally { + this.style_cache = previous_cache; + } + } + + has_any_style_class(actor, style_classes) { + if (!actor) + return false; + + const classes = this.get_style_classes(actor); + if (classes) + return style_classes.some(style_class => classes.has(style_class)); + + return style_classes.some(style_class => this.has_style_class(actor, style_class)); + } + + has_style_class(actor, style_class) { + return has_style_class(actor, style_class); + } + + get_style_classes(actor) { + if (!actor || !this.style_cache) + return null; + + if (this.style_cache.has(actor)) + return this.style_cache.get(actor); + + if (!actor.get_style_class_name) { + this.style_cache.set(actor, null); + return null; + } + + const class_names = actor.get_style_class_name(); + if (typeof class_names !== 'string') { + this.style_cache.set(actor, null); + return null; + } + + const classes = new Set(class_names.split(/\s+/).filter(Boolean)); + this.style_cache.set(actor, classes); + return classes; + } + + create_targets() { + return { + actors: [], + seen: new WeakSet(), + }; + } + + get_children(actor) { + return actor ? actor.get_children() : []; + } + + push_children(stack, children) { + children + .slice() + .reverse() + .forEach(child => stack.push({ actor: child, fallback_count: null })); + } + + add(targets, target) { + if ( + this.actor.is_internal_actor(target) + || !this.actor.watch_actor(target) + || targets.seen.has(target) + ) + return; + + targets.seen.add(target); + targets.actors.push(target); + } +}; + +export function has_style_class(actor, style_class) { + if (!actor || !style_class) + return false; + + if (actor.has_style_class_name) + return actor.has_style_class_name(style_class); + + if (actor.get_style_class_name) + return (actor.get_style_class_name() ?? '').split(/\s+/).includes(style_class); + + return false; +} 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 index 6ab0644..33a9be3 100644 --- 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 @@ -66,7 +66,7 @@ export const WindowListBlur = class WindowListBlur { this.connections.connect( actor, 'destroy', - _ => this.destroy_blur(pipeline, true) + _ => this.destroy_blur(pipeline) ); @@ -98,8 +98,8 @@ export const WindowListBlur = class WindowListBlur { } // IMPORTANT: do never call this in a mutable `this.pipelines.forEach` - destroy_blur(pipeline, actor_destroyed = false) { - if (!actor_destroyed) { + destroy_blur(pipeline) { + if (pipeline.actor) { this.remove_style(pipeline.actor); this.paint_signals.disconnect_all_for_actor(pipeline.actor); } @@ -108,7 +108,7 @@ export const WindowListBlur = class WindowListBlur { let index = this.pipelines.indexOf(pipeline); if (index >= 0) - this.pipelines.splice(pipeline, 1); + this.pipelines.splice(index, 1); } remove_style(actor) { 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 index 0583db3..8d17b62 100644 --- 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 @@ -1,106 +1,98 @@ import GObject from 'gi://GObject'; -/// An object to easily manage signals. +function supports_destroy_signal(object) { + const gtype = object?.constructor?.$gtype; + return gtype && GObject.signal_lookup('destroy', gtype) !== 0; +} + export const Connections = class Connections { constructor() { - this.buffer = []; + this.records = new Map(); } - /// 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); - } + connect(object, signals, handler) { + const names = Array.isArray(signals) ? signals : [signals]; + const record = this.get_record(object); + const ids = []; + for (const signal of names) { + const id = object.connect(signal, handler); + record.ids.add(id); + ids.push(id); + } + return Array.isArray(signals) ? ids : ids[0]; } - /// 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 + get_record(object) { + let record = this.records.get(object); + if (record) + return record; + + record = { + ids: new Set(), + destroy_id: null, }; + this.records.set(object, record); - // 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); - } + if (supports_destroy_signal(object)) + record.destroy_id = object.connect('destroy', () => { + this.records.delete(object); + record.ids.clear(); + record.destroy_id = null; }); - infos.destroy_id = destroy_id; - } - this.buffer.push(infos); + return record; } - /// 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_all_for(object) { + const record = this.records.get(object); + if (!record) + return; + + this.records.delete(object); + for (const id of record.ids) + this.raw_disconnect(object, id); + if (record.destroy_id) + this.raw_disconnect(object, record.destroy_id); } - /// 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 = []; + for (const object of [...this.records.keys()]) + this.disconnect_all_for(object); + } + + disconnect(object, id) { + const record = this.records.get(object); + if (record) + record.ids.delete(id); + + this.raw_disconnect(object, id); + + if (record && record.ids.size === 0) { + this.records.delete(object); + if (record.destroy_id) + this.raw_disconnect(object, record.destroy_id); + } + } + + raw_disconnect(object, id) { + if (!id) + return; + + try { + if ( + object instanceof GObject.Object + && !GObject.signal_handler_is_connected(object, id) + ) + return; + + object.disconnect(id); + } catch (error) { + this._warn(`error removing connection: ${error}; continuing`); + } } _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 index 02b2d13..4d71d46 100644 --- 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 @@ -4,9 +4,12 @@ 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) { + constructor(effects_manager, settings, actor = null, options = {}) { this.effects_manager = effects_manager; this.settings = settings; + this.corner_radius_key = options.corner_radius_key ?? 'corner-radius'; + this.corner_radius_getter = options.corner_radius_getter ?? (() => this.settings.CORNER_RADIUS); + this.opacity_factor = 1; this.effect = null; this.attach_effect_to_actor(actor); } @@ -41,9 +44,9 @@ export const DummyPipeline = class DummyPipeline { // build the new effect to be added this.build_effect({ - unscaled_radius: 2 * this.settings.SIGMA, - brightness: this.settings.BRIGHTNESS, - corner_radius: this.settings.CORNER_RADIUS, + unscaled_radius: this.get_unscaled_radius(), + brightness: this.get_brightness(), + unscaled_corner_radius: this.corner_radius_getter(), }); this.actor_destroy_id = this.actor.connect( @@ -70,17 +73,40 @@ export const DummyPipeline = class DummyPipeline { 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 - ); + this._sigma_changed_id = this.settings.settings.connect('changed::sigma', () => this.update_effect()); + this._brightness_changed_id = this.settings.settings.connect('changed::brightness', () => this.update_effect()); this._corner_radius_changed_id = this.settings.settings.connect( - 'changed::corner-radius', () => this.effect.corner_radius = this.settings.CORNER_RADIUS + `changed::${this.corner_radius_key}`, + () => this.update_effect() ); } + set_opacity_factor(opacity_factor) { + opacity_factor = Math.max(0, Math.min(1, opacity_factor)); + if (this.opacity_factor === opacity_factor) + return; + + this.opacity_factor = opacity_factor; + this.update_effect(); + } + + update_effect() { + if (!this.effect) + return; + + this.effect.unscaled_radius = this.get_unscaled_radius(); + this.effect.brightness = this.get_brightness(); + this.effect.unscaled_corner_radius = this.corner_radius_getter(); + } + + get_unscaled_radius() { + return 2 * this.settings.SIGMA * this.opacity_factor; + } + + get_brightness() { + return 1 - (1 - this.settings.BRIGHTNESS) * this.opacity_factor; + } + repaint_effect() { this.effect?.queue_repaint(); } @@ -109,7 +135,6 @@ export const DummyPipeline = class DummyPipeline { /// Note: exposed to public API. destroy() { - this.remove_effect(); this.remove_pipeline_from_actor(); } 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 index 947d535..8b99396 100644 --- 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 @@ -4,7 +4,7 @@ import { get_supported_effects } from '../effects/effects.js'; export const EffectsManager = class EffectsManager { constructor(connections) { this.connections = connections; - this.used = []; + this.used = new Set(); this.SUPPORTED_EFFECTS = get_supported_effects(); Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => { @@ -15,60 +15,56 @@ export const EffectsManager = class EffectsManager { 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 = this[effect_name + '_effects'].pop(); effect.set({ ...this.SUPPORTED_EFFECTS[effect_name].class.default_params, ...params }); - } else + } else { effect = new this.SUPPORTED_EFFECTS[effect_name].class({ ...this.SUPPORTED_EFFECTS[effect_name].class.default_params, ...params }); + this.connect_to_destroy(effect); + } - this.used.push(effect); - this.connect_to_destroy(effect); + this.used.add(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(); + const update_actor = () => { + const actor = effect.get_actor(); + if (actor === effect._bms_actor) + return; - if (effect.old_actor && actor != effect.old_actor) - effect.old_actor.disconnect(effect.old_actor_id); + this.disconnect_actor_destroy(effect); + effect._bms_actor = actor; + if (actor) + effect._bms_actor_destroy_id = actor.connect( + 'destroy', () => this.remove(effect, true) + ); + }; - if (actor && actor != effect.old_actor) { - effect.old_actor_id = actor.connect('destroy', _ => { - this.remove(effect, true); - }); - } - }); + this.connections.connect(effect, 'notify::actor', update_actor); + update_actor(); } - // 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; + disconnect_actor_destroy(effect) { + if (effect._bms_actor && effect._bms_actor_destroy_id) { + effect._bms_actor.disconnect(effect._bms_actor_destroy_id); + } + effect._bms_actor = null; + effect._bms_actor_destroy_id = null; + } - let index = this.used.indexOf(effect); - if (index >= 0) { - this.used.splice(index, 1); + remove(effect) { + const actor = effect.get_actor(); + if (actor) + actor.remove_effect(effect); + this.disconnect_actor_destroy(effect); + if (this.used.delete(effect)) { Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => { if (effect instanceof this.SUPPORTED_EFFECTS[effect_name].class) this[effect_name + '_effects'].push(effect); 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 index d821b88..0876d16 100644 --- 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 @@ -38,6 +38,9 @@ export const KEYS = [ { type: Type.B, name: "override-background" }, { type: Type.I, name: "style-panel" }, { type: Type.B, name: "override-background-dynamically" }, + { type: Type.I, name: "override-background-dynamically-mode" }, + { type: Type.B, name: "gradient-panel" }, + { type: Type.I, name: "gradient-panel-mode" }, ] }, { @@ -65,6 +68,7 @@ export const KEYS = [ { type: Type.I, name: "opacity" }, { type: Type.B, name: "dynamic-opacity" }, { type: Type.B, name: "blur-on-overview" }, + { type: Type.B, name: "unblur-when-fullscreen" }, { type: Type.B, name: "enable-all" }, { type: Type.AS, name: "whitelist" }, { type: Type.AS, name: "blacklist" }, @@ -96,6 +100,25 @@ export const KEYS = [ { type: Type.S, name: "pipeline" }, ] }, + { + component: "popup", 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: "corner-radius" }, + { type: Type.I, name: "menu-corner-radius" }, + { type: Type.I, name: "quick-settings-corner-radius" }, + { type: Type.I, name: "notification-corner-radius" }, + { type: Type.I, name: "osd-corner-radius" }, + { type: Type.I, name: "dialog-corner-radius" }, + { type: Type.I, name: "osk-corner-radius" }, + { type: Type.B, name: "override-background" }, + { type: Type.B, name: "preserve-shell-theme" }, + { type: Type.I, name: "style-popup" }, + ] + }, { component: "hidetopbar", schemas: [ { type: Type.B, name: "compatibility" }, 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 index 5fbfee4..10a6d26 100644 --- 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 @@ -1,91 +1,64 @@ import GObject from 'gi://GObject'; import Clutter from 'gi://Clutter'; +const PAINTS_BETWEEN_REPAINTS = 2; export const PaintSignals = class PaintSignals { constructor(connections) { - this.buffer = []; + this.entries = new Map(); this.connections = connections; } connect(actor, blur_effect) { - let paint_effect = new EmitPaintSignal(); - let infos = { - actor: actor, - paint_effect: paint_effect - }; - let counter = 0; + this.disconnect_all_for_actor(actor); - 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) { } - }); + let paints_to_skip = 0; + const paint_effect = new PaintCallbackEffect(); + paint_effect.set_callback(() => { + if (paints_to_skip > 0) { + paints_to_skip--; + return; + } - // 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); - } - }); - }); + paints_to_skip = PAINTS_BETWEEN_REPAINTS; + blur_effect.queue_repaint(); + }); - this.buffer.push(infos); + actor.add_effect(paint_effect); + const destroy_id = this.connections.connect(actor, 'destroy', () => { + paint_effect.set_callback(null); + this.entries.delete(actor); + }); + this.entries.set(actor, { paint_effect, destroy_id }); } 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); + const entry = this.entries.get(actor); + if (!entry) + return; - // remove from buffer - let index = this.buffer.indexOf(infos); - this.buffer.splice(index, 1); - } - }); + this.entries.delete(actor); + entry.paint_effect.set_callback(null); + this.connections.disconnect(actor, entry.destroy_id); + actor.remove_effect(entry.paint_effect); } disconnect_all() { - this.buffer.forEach(infos => { - this.connections.disconnect_all_for(infos.paint_effect); - infos.actor.remove_effect(infos.paint_effect); - }); - - this.buffer = []; + for (const actor of [...this.entries.keys()]) + this.disconnect_all_for_actor(actor); } }; -export const EmitPaintSignal = GObject.registerClass({ - GTypeName: 'EmitPaintSignal', - Signals: { - 'update-blur': { - param_types: [] - }, - } -}, - class EmitPaintSignal extends Clutter.Effect { +const PaintCallbackEffect = GObject.registerClass( + { GTypeName: 'BmsPaintCallbackEffect' }, + class PaintCallbackEffect extends Clutter.Effect { + set_callback(callback) { + this._callback = callback; + } + vfunc_paint(node, paint_context, paint_flags) { - this.emit("update-blur"); + this._callback(); 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 index 84b1d7a..f52e26f 100644 --- 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 @@ -1,6 +1,9 @@ import St from 'gi://St'; +import Meta from 'gi://Meta'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as Background from 'resource:///org/gnome/shell/ui/background.js'; +import * as uniforms from './shader_uniforms.js'; +import * as utils from './utils.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 @@ -18,10 +21,11 @@ import * as Background from 'resource:///org/gnome/shell/ui/background.js'; /// - `'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) { + constructor(effects_manager, pipelines_manager, pipeline_id, actor = null, options = {}) { this.effects_manager = effects_manager; this.pipelines_manager = pipelines_manager; this.effects = []; + this.effect_overrides = options.effect_overrides ?? {}; this.set_pipeline_id(pipeline_id); this.attach_pipeline_to_actor(actor); } @@ -41,19 +45,18 @@ export const Pipeline = class Pipeline { ) { let monitor = Main.layoutManager.monitors[monitor_index]; + this.remove_pipeline_from_actor(); + // 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 + y: utils.subpixel_stage_offset() + (use_absolute_position ? monitor.y : 0), 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); @@ -64,6 +67,17 @@ export const Pipeline = class Pipeline { }); bg_manager._bms_pipeline = this; + // 'controlPosition: false' skips BackgroundManager's default layout pass, which also diables + // sibling re-ordering. + // Without it, new actors render on top while loading, causing a solid color flash through + // on the surface. + this.child_added_id = this.actor.connect( + 'child-added', (container, child) => { + if (child instanceof Meta.BackgroundActor) + container.set_child_below_sibling(child, null); + } + ); + background_managers.push(bg_manager); background_group.insert_child_at_index(this.actor, 0); @@ -104,14 +118,14 @@ export const Pipeline = class Pipeline { /// 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 { + if (!actor) { this.remove_pipeline_from_actor(); return; } + this.disconnect_actor_destroy(); + this.actor = actor; + // attach the pipeline let pipeline = this.pipelines_manager.pipelines[this.pipeline_id]; if (!pipeline) { @@ -134,10 +148,23 @@ export const Pipeline = class Pipeline { remove_pipeline_from_actor() { this.remove_all_effects(); - if (this.actor && this.actor_destroy_id) + this.disconnect_actor_destroy(); + this.disconnect_child_added(); + this.actor = null; + } + + disconnect_actor_destroy() { + if (this.actor && this.actor_destroy_id) { this.actor.disconnect(this.actor_destroy_id); + } this.actor_destroy_id = null; - this.actor = null; + } + + disconnect_child_added() { + if (this.actor && this.child_added_id) { + this.actor.disconnect(this.child_added_id); + } + this.child_added_id = null; } /// Update the effects from the given pipeline object, the hard way. @@ -147,7 +174,9 @@ export const Pipeline = class Pipeline { // build the new effects to be added pipeline.effects.forEach(effect => { - if ('new_' + effect.type + '_effect' in this.effects_manager) + if (effect.type === 'pixelize') + this.build_pixelize_effect(effect); + else 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`); @@ -156,32 +185,143 @@ export const Pipeline = class Pipeline { // add the effects to the actor if (this.actor) - this.effects.forEach(effect => this.actor.add_effect(effect)); + this.effects.forEach(effect => { + this.actor.add_effect(effect); + uniforms.mark_dirty(effect); + }); else this._warn(`could not add effect to actor, actor does not exist anymore`); } + build_pixelize_effect(effect_infos) { + const effect_params = this.get_effect_params(effect_infos); + const effect_overrides = this.get_effect_overrides(effect_infos.type, effect_params); + const params = { + ...effect_params, + ...effect_overrides, + }; + + const downscale = this.effects_manager.new_downscale_effect({ + divider: params.factor, + downsampling_mode: params.downsampling_mode, + opacity_factor: params.opacity_factor, + }); + const upscale = this.effects_manager.new_upscale_effect({ + factor: params.factor, + opacity_factor: params.opacity_factor, + }); + + this.setup_effect(downscale, effect_infos, effect_params, 'downscale'); + this.setup_effect(upscale, effect_infos, effect_params, 'upscale'); + } + /// 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); + const effect_params = this.get_effect_params(effect_infos); + const effect_overrides = this.get_effect_overrides(effect_infos.type, effect_params); + let effect = this.effects_manager['new_' + effect_infos.type + '_effect']({ + ...effect_params, + ...effect_overrides, + }); + this.setup_effect(effect, effect_infos, effect_params); + } + + setup_effect(effect, effect_infos, effect_params, pixelize_role = null) { + effect._bms_effect_type = effect_infos.type; + effect._bms_effect_id = effect_infos.id; + effect._bms_effect_params = effect_params; + effect._bms_pixelize_role = pixelize_role; 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] + this.pipeline_id + '::effect-' + effect_infos.id + '-key-removed', (_, key) => { + const default_value = this.get_effect_default_param(effect, key); + effect._bms_effect_params[key] = default_value; + if (!this.apply_effect_override(effect, key)) + this.set_effect_param(effect, key, default_value); + } ); effect._effect_key_updated_id = this.pipelines_manager.connect( - this.pipeline_id + '::effect-' + effect_infos.id + '-key-updated', - (_, key, value) => effect[key] = value + this.pipeline_id + '::effect-' + effect_infos.id + '-key-updated', (_, key, value) => { + effect._bms_effect_params[key] = value; + if (!this.apply_effect_override(effect, key)) + this.set_effect_param(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 + this.pipeline_id + '::effect-' + effect_infos.id + '-key-added', (_, key, value) => { + effect._bms_effect_params[key] = value; + if (!this.apply_effect_override(effect, key)) + this.set_effect_param(effect, key, value); + } ); } + get_effect_params(effect_infos) { + const effect_class = this.effects_manager.SUPPORTED_EFFECTS[effect_infos.type]?.class; + return { + ...(effect_class?.default_params ?? {}), + ...(effect_infos.params ?? {}), + }; + } + + get_effect_default_param(effect, key) { + return this.effects_manager.SUPPORTED_EFFECTS[effect._bms_effect_type] + ?.class + ?.default_params + ?.[key]; + } + + get_effect_overrides(effect_type, effect_params = {}) { + const overrides = this.effect_overrides[effect_type] ?? {}; + return typeof overrides === 'function' ? overrides(effect_params) : overrides; + } + + apply_effect_override(effect, key) { + const overrides = this.get_effect_overrides(effect._bms_effect_type, effect._bms_effect_params); + if (!(key in overrides)) + return false; + + this.set_effect_param(effect, key, overrides[key]); + return true; + } + + apply_effect_overrides(effect_type = null) { + this.effects.forEach(effect => { + if (effect_type && effect._bms_effect_type !== effect_type) + return; + + const overrides = this.get_effect_overrides(effect._bms_effect_type, effect._bms_effect_params); + Object.keys(overrides).forEach(key => this.set_effect_param(effect, key, overrides[key])); + }); + } + + set_effect_param(effect, key, value) { + if (effect._bms_effect_type !== 'pixelize') { + effect[key] = value; + return; + } + + if (key === 'factor') { + if (effect._bms_pixelize_role === 'downscale') + effect.divider = value; + else if (effect._bms_pixelize_role === 'upscale') + effect.factor = value; + return; + } + + if (key === 'downsampling_mode') { + if (effect._bms_pixelize_role === 'downscale') + effect.downsampling_mode = value; + return; + } + + if (key in effect) + 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() { @@ -197,6 +337,10 @@ export const Pipeline = class Pipeline { delete effect._effect_key_removed_id; delete effect._effect_key_updated_id; delete effect._effect_key_added_id; + delete effect._bms_effect_type; + delete effect._bms_effect_id; + delete effect._bms_effect_params; + delete effect._bms_pixelize_role; }); this.effects = []; } @@ -211,7 +355,6 @@ export const Pipeline = class Pipeline { /// 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; @@ -220,4 +363,4 @@ export const Pipeline = class Pipeline { _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/pipeline_settings.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline_settings.js new file mode 100644 index 0000000..eb5c173 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline_settings.js @@ -0,0 +1,136 @@ +import GLib from 'gi://GLib'; + +function is_plain_object(value) { + return value !== null + && typeof value === 'object' + && value.constructor === Object; +} + +function unpack_string(value, label) { + const unpacked = value?.deep_unpack(); + if (typeof unpacked !== 'string') + throw new Error(`${label} is not a string`); + + return unpacked; +} + +function unpack_effect(effect_variant) { + const effect = effect_variant?.deep_unpack(); + if (!is_plain_object(effect)) + throw new Error('effect is not an object'); + if (!('type' in effect)) + throw new Error('effect has no type'); + if (!('id' in effect)) + throw new Error('effect has no id'); + + const params = 'params' in effect ? effect.params.deep_unpack() : {}; + if (!is_plain_object(params)) + throw new Error('effect params is not an object'); + + return { + type: unpack_string(effect.type, 'effect type'), + id: unpack_string(effect.id, 'effect id'), + params: Object.fromEntries( + Object.entries(params).map(([key, value]) => [key, value.deep_unpack()]) + ), + }; +} + +export function unpack_pipelines(value) { + const unpacked = value.deep_unpack(); + if (!is_plain_object(unpacked)) + throw new Error('pipelines is not an object'); + + const pipelines = {}; + for (const [pipeline_id, pipeline] of Object.entries(unpacked)) { + if (!is_plain_object(pipeline)) + throw new Error(`pipeline ${pipeline_id} is not an object`); + if (!('name' in pipeline)) + throw new Error(`pipeline ${pipeline_id} has no name`); + if (!('effects' in pipeline)) + throw new Error(`pipeline ${pipeline_id} has no effects`); + + const effects = pipeline.effects.deep_unpack(); + if (!Array.isArray(effects)) + throw new Error(`pipeline ${pipeline_id} effects is not an array`); + + pipelines[pipeline_id] = { + name: unpack_string(pipeline.name, `pipeline ${pipeline_id} name`), + effects: effects.map(unpack_effect), + }; + } + + return pipelines; +} + +function pack_param(value, label) { + if (typeof value === 'boolean') + return GLib.Variant.new_boolean(value); + if (typeof value === 'number') + return Number.isInteger(value) + ? GLib.Variant.new_int32(value) + : GLib.Variant.new_double(value); + if (typeof value === 'string') + return GLib.Variant.new_string(value); + if ( + Array.isArray(value) + && value.length === 4 + && value.every(component => typeof component === 'number') + ) + return new GLib.Variant('(dddd)', value); + + throw new Error(`${label} has an unsupported type`); +} + +function pack_effect(effect, label) { + if (!is_plain_object(effect)) + throw new Error(`${label} is not an object`); + if (typeof effect.type !== 'string') + throw new Error(`${label} type is not a string`); + if (typeof effect.id !== 'string') + throw new Error(`${label} id is not a string`); + + const params = effect.params ?? {}; + if (!is_plain_object(params)) + throw new Error(`${label} params is not an object`); + + const packed_params = Object.fromEntries( + Object.entries(params).map(([key, value]) => [ + key, + pack_param(value, `${label} parameter ${key}`), + ]) + ); + + return 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}', packed_params), + }); +} + +export function pack_pipelines(pipelines) { + if (!is_plain_object(pipelines)) + throw new Error('pipelines is not an object'); + + const packed = {}; + for (const [pipeline_id, pipeline] of Object.entries(pipelines)) { + if (!is_plain_object(pipeline)) + throw new Error(`pipeline ${pipeline_id} is not an object`); + if (typeof pipeline.name !== 'string') + throw new Error(`pipeline ${pipeline_id} name is not a string`); + if (!Array.isArray(pipeline.effects)) + throw new Error(`pipeline ${pipeline_id} effects is not an array`); + + packed[pipeline_id] = { + name: GLib.Variant.new_string(pipeline.name), + effects: new GLib.Variant( + 'av', + pipeline.effects.map((effect, index) => + pack_effect(effect, `pipeline ${pipeline_id} effect ${index}`) + ) + ), + }; + } + + return new GLib.Variant('a{sa{sv}}', packed); +} 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 index 0fdfe9e..6d9749a 100644 --- 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 @@ -1,5 +1,23 @@ +import GLib from 'gi://GLib'; + const Signals = imports.signals; +function new_id(prefix) { + return `${prefix}_${GLib.uuid_string_random()}`; +} + +function clone_effect(effect) { + return { + ...effect, + params: Object.fromEntries( + Object.entries(effect.params ?? {}).map(([key, value]) => [ + key, + Array.isArray(value) ? [...value] : value, + ]) + ), + }; +} + /// 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 @@ -36,10 +54,8 @@ export class PipelinesManager { } 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)); + const id = new_id('pipeline'); + effects.forEach(effect => effect.id = new_id('effect')); this.pipelines[id] = { name, effects }; this.settings.PIPELINES = this.pipelines; @@ -54,8 +70,10 @@ export class PipelinesManager { return; } const pipeline = this.pipelines[id]; - this.create_pipeline(pipeline.name + " - duplicate", [...pipeline.effects]); - this.settings.PIPELINES = this.pipelines; + this.create_pipeline( + `${pipeline.name} - duplicate`, + pipeline.effects.map(clone_effect) + ); } delete_pipeline(id) { @@ -89,7 +107,7 @@ export class PipelinesManager { this._warn(`could not rename pipeline, id ${id} does not exist`); return; } - this.pipelines[id].name = name.slice(); + this.pipelines[id].name = name; this.settings.PIPELINES = this.pipelines; this._emit(id + '::pipeline-renamed', name); this._emit('pipeline-names-changed'); @@ -98,8 +116,18 @@ export class PipelinesManager { on_pipeline_update() { const old_pipelines = this.pipelines; this.pipelines = this.settings.PIPELINES; + const old_ids = Object.keys(old_pipelines); + const new_ids = Object.keys(this.pipelines); + const list_changed = old_ids.length !== new_ids.length + || old_ids.some(id => !(id in this.pipelines)); + let names_changed = false; + + for (const pipeline_id of new_ids) { + if (!(pipeline_id in old_pipelines)) + this._emit('pipeline-created', pipeline_id, this.pipelines[pipeline_id]); + } - for (var pipeline_id in old_pipelines) { + for (const pipeline_id of old_ids) { // if we find a pipeline that does not exist anymore, signal it if (!(pipeline_id in this.pipelines)) { this._emit(pipeline_id + '::pipeline-destroyed'); @@ -109,6 +137,11 @@ export class PipelinesManager { const old_pipeline = old_pipelines[pipeline_id]; const new_pipeline = this.pipelines[pipeline_id]; + if (old_pipeline.name !== new_pipeline.name) { + this._emit(pipeline_id + '::pipeline-renamed', new_pipeline.name); + names_changed = true; + } + // verify if both pipelines have effects in the same order // if they have, then check for their parameters if ( @@ -144,6 +177,11 @@ export class PipelinesManager { else this._emit(pipeline_id + '::pipeline-updated', new_pipeline); } + + if (list_changed) + this._emit('pipeline-list-changed'); + if (names_changed) + this._emit('pipeline-names-changed'); } destroy() { @@ -165,4 +203,4 @@ export class PipelinesManager { } } -Signals.addSignalMethods(PipelinesManager.prototype); \ No newline at end of file +Signals.addSignalMethods(PipelinesManager.prototype); 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 index 53f8497..337c8c2 100644 --- 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 @@ -1,4 +1,5 @@ import GLib from 'gi://GLib'; +import { pack_pipelines, unpack_pipelines } from './pipeline_settings.js'; const Signals = imports.signals; /// An enum non-extensively describing the type of gsettings key. @@ -122,171 +123,20 @@ export const Settings = class Settings { 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; + try { + return unpack_pipelines(component_settings.get_value(key.name)); + } catch (error) { + this._warn(`impossible to get pipelines, resetting: ${error.message}`); + component_settings.reset(key.name); + return unpack_pipelines(component_settings.get_value(key.name)); + } }, - 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); + set(pipelines) { + try { + component_settings.set_value(key.name, pack_pipelines(pipelines)); + } catch (error) { + this._warn(`impossible to set pipelines: ${error.message}`); + } } }); break; @@ -360,4 +210,4 @@ export const Settings = class Settings { } }; -Signals.addSignalMethods(Settings.prototype); \ No newline at end of file +Signals.addSignalMethods(Settings.prototype); diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/shader_uniforms.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/shader_uniforms.js new file mode 100644 index 0000000..a82b261 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/shader_uniforms.js @@ -0,0 +1,61 @@ +import GObject from 'gi://GObject'; + +const INTEGRAL_UNIFORMS = new Set([ + 'corners_bottom', + 'corners_top', + 'divider', + 'dir', + 'downsampling_mode', + 'factor', + 'iterations', + 'mode', + 'operation', + 'prefer_closer_pixels', + 'straight_corners', + 'use_base_pixel', +]); + +export function set_uniform(effect, name, value) { + if (!effect._bms_uniforms) + effect._bms_uniforms = new Map(); + + effect._bms_uniforms.set(name, value); + effect._bms_uniforms_dirty = true; + effect.queue_repaint(); +} + +export function mark_dirty(effect) { + if (effect._bms_uniforms) + effect._bms_uniforms_dirty = true; +} + +export function upload_uniforms(effect) { + if (!effect._bms_uniforms_dirty || !effect._bms_uniforms || !effect.get_actor()) + return; + + for (const [name, value] of effect._bms_uniforms) { + try { + effect.set_uniform_value(name, get_shader_value(name, value)); + } catch (e) { + if (!effect._bms_uniform_warning_shown) { + effect._bms_uniform_warning_shown = true; + console.warn(`[Blur my Shell] shader uniform upload failed for ${effect.constructor.name}`, e); + } + } + } + + effect._bms_uniforms_dirty = false; +} + +function get_shader_value(name, value) { + if (typeof value !== 'number') + return value; + + if (INTEGRAL_UNIFORMS.has(name)) + return Math.trunc(value); + + const float_value = new GObject.Value(); + float_value.init(GObject.TYPE_FLOAT); + float_value.set_float(value); + return float_value; +} 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 index 20def0b..b7bcff3 100644 --- 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 @@ -1,4 +1,5 @@ import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; export const IS_IN_PREFERENCES = typeof global === 'undefined'; @@ -10,12 +11,32 @@ export async function import_in_shell_only(module) { if (IS_IN_PREFERENCES) return null; try { - return (await import(module)).default; + const imported = await import(module); + return imported.default ?? imported; } catch (e) { return null; } } +const Clutter = await import_in_shell_only('gi://Clutter'); +const Cogl = await import_in_shell_only('gi://Cogl'); +const USES_SHADER_SNIPPET_API = + typeof Clutter?.ShaderEffect?.new_with_snippet === 'function'; + +export function is_usable_blur_module(ns) { + if (!ns) + return false; + try { + const { BlurEffect } = ns; + if (typeof BlurEffect !== 'function' || !BlurEffect.$gtype) + return false; + GObject.type_name(BlurEffect.$gtype); + return true; + } catch (e) { + return false; + } +} + // 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 @@ -39,4 +60,87 @@ export const get_shader_source = (Shell, shader_filename, self_uri) => { console.warn(`[Blur my Shell > effect] error loading shader from ${shader_path}: ${e}`); return null; } -}; \ No newline at end of file +}; + +export function subpixel_stage_offset() { + return USES_SHADER_SNIPPET_API ? 0 : 0.5; +} + +export function static_blur_clip_inset() { + return USES_SHADER_SNIPPET_API ? 1 : 0; +} + +export function register_shader_effect(meta, effect_class, source) { + if (USES_SHADER_SNIPPET_API) { + Object.defineProperty(effect_class.prototype, 'vfunc_get_static_snippet', { + value() { + return create_fragment_shader_snippet(source); + }, + }); + } + + return GObject.registerClass(meta, effect_class); +} + +function split_fragment_shader(source) { + const main_index = source.search(/void\s+main\s*(?:\(\s*(?:void)?\s*\))?\s*\{/); + if (main_index < 0) + return null; + + const declarations = source.slice(0, main_index).trim(); + const brace_index = source.indexOf('{', main_index); + if (brace_index < 0) + return null; + + let depth = 0; + for (let i = brace_index; i < source.length; i++) { + if (source[i] === '{') + depth++; + else if (source[i] === '}') { + depth--; + if (depth === 0) { + return { + declarations, + body: source.slice(brace_index + 1, i).trim(), + }; + } + } + } + + return null; +} + +function create_fragment_shader_snippet(source) { + if (!Cogl || !source) + return null; + + const parts = split_fragment_shader(source); + if (!parts) { + console.warn('[Blur my Shell > effect] could not split shader source'); + return null; + } + + try { + const snippet = Cogl.Snippet.new( + Cogl.SnippetHook.FRAGMENT, + parts.declarations, + null + ); + snippet.set_replace(parts.body); + return snippet; + } catch (e) { + console.warn(`[Blur my Shell > effect] could not create shader snippet: ${e}`); + return null; + } +} + +export function initialize_shader_effect(effect, source) { + if (!source || !effect || USES_SHADER_SNIPPET_API) + return; + + try { + effect.set_shader_source(source); + } catch (e) { + console.warn(`[Blur my Shell > effect] set_shader_source failed: ${e}`); + } +} 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 deleted file mode 100644 index 4f298ad..0000000 --- a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/dbus/iface.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ 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 index 4b1f4f0..0b2f144 100644 --- 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 @@ -3,18 +3,24 @@ 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'; +const IFACE_XML = ` + + + + + + + + + + + + +`; 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); + this.DBusImpl = Gio.DBusExportedObject.wrapJSObject(IFACE_XML, this); } /// Pick Window for Preferences Page, exported to DBus client. @@ -49,7 +55,7 @@ export const ApplicationsService = class ApplicationsService { // inspect window now const inspector = new LookingGlass.Inspector(Main.createLookingGlass()); - inspector.connect('target', (me, target, x, y) => { + inspector.connect('target', (me, target, _x, _y) => { // remove border effect when window is picked. const effect_name = 'lookingGlass_RedBorderEffect'; target 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 index 5df6512..af9b1df 100644 --- 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 @@ -3,6 +3,7 @@ uniform float red; uniform float green; uniform float blue; uniform float blend; +uniform float opacity_factor; uniform int mode; const int NORMAL = 0; @@ -53,7 +54,7 @@ float soft_light_channel(float base, float _blend) { vec3 get_blend(vec3 base, vec3 _blend) { if (mode == MULTIPLY) return base * _blend; - if (mode == SCREEN) return 1 - (1 - base) * (1 - _blend); + if (mode == SCREEN) return 1.0 - (1.0 - base) * (1.0 - _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)); @@ -63,10 +64,10 @@ vec3 get_blend(vec3 base, vec3 _blend) { } 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_DARKER) return base + _blend - vec3(1.0); 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 == COLOR_DODGE) return base / max(vec3(1e-6), 1.0 - _blend); + if (mode == COLOR_BURN) return 1.0 - (1.0 - base) / max(vec3(1e-6), _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)); @@ -78,7 +79,7 @@ vec3 get_blend(vec3 base, vec3 _blend) { 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 == EXCLUSION) return 0.5 - 2.0 * (base - 0.5) * (_blend - 0.5); if (mode == HUE) { vec3 base_hsl = rgb_to_hsl(base); vec3 blend_hsl = rgb_to_hsl(_blend); @@ -106,6 +107,7 @@ 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)); + float amount = blend * opacity_factor; - cogl_color_out = vec4(mix(pix_color, color, blend), 1.); -} \ No newline at end of file + cogl_color_out = vec4(mix(pix_color, color, amount), c.a); +} 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 index 1f4bdf4..95ce4c1 100644 --- 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 @@ -1,20 +1,21 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); const DEFAULT_PARAMS = { color: [0.0, 0.0, 0.0, 0.0], - blend_mode: 0 + blend_mode: 0, + opacity_factor: 1 }; -export const ColorEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const COLOR_EFFECT_META = { GTypeName: "ColorEffect", Properties: { 'red': GObject.ParamSpec.double( @@ -56,31 +57,37 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? GObject.ParamFlags.READWRITE, 0, 17, 0, + ), + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.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 { +}; + +const ColorEffectClass = utils.IS_IN_PREFERENCES ? null : class ColorEffect extends Clutter.ShaderEffect { + constructor(params) { - // initialize without color as a parameter - const { color, ...parent_params } = params; - super(parent_params); + super(); + + utils.initialize_shader_effect(this, SHADER_SOURCE); + 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); + this._opacity_factor = null; // set params; utils.setup_params doesn't work here with color - this.color = 'color' in params ? color : this.constructor.default_params.color; + this.color = 'color' in params ? params.color : this.constructor.default_params.color; this.blend_mode = 'blend_mode' in params ? params.blend_mode : this.constructor.default_params.blend_mode; + this.opacity_factor = 'opacity_factor' in params ? params.opacity_factor : this.constructor.default_params.opacity_factor; } static get default_params() { @@ -95,7 +102,7 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? if (this._red !== value) { this._red = value; - this.set_uniform_value('red', parseFloat(this._red - 1e-6)); + uniforms.set_uniform(this, 'red', parseFloat(this._red - 1e-6)); } } @@ -107,7 +114,7 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? if (this._green !== value) { this._green = value; - this.set_uniform_value('green', parseFloat(this._green - 1e-6)); + uniforms.set_uniform(this, 'green', parseFloat(this._green - 1e-6)); } } @@ -119,7 +126,7 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? if (this._blue !== value) { this._blue = value; - this.set_uniform_value('blue', parseFloat(this._blue - 1e-6)); + uniforms.set_uniform(this, 'blue', parseFloat(this._blue - 1e-6)); } } @@ -131,7 +138,7 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? if (this._blend !== value) { this._blend = value; - this.set_uniform_value('blend', parseFloat(this._blend - 1e-6)); + uniforms.set_uniform(this, 'blend', parseFloat(this._blend - 1e-6)); this.set_enabled(this.blend > 0); } } @@ -144,7 +151,19 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? if (this._blend_mode !== value) { this._blend_mode = value; - this.set_uniform_value('mode', this._blend_mode); + uniforms.set_uniform(this, 'mode', this._blend_mode); + } + } + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; + + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); } } @@ -164,5 +183,16 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? set(params) { this.color = params.color; this.blend_mode = params.blend_mode; + if ('opacity_factor' in params) + this.opacity_factor = params.opacity_factor; } - }); \ No newline at end of file + + vfunc_paint_target(paint_node, paint_context) { + uniforms.upload_uniforms(this); + super.vfunc_paint_target(paint_node, paint_context); + } +}; + +export const ColorEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(COLOR_EFFECT_META, ColorEffectClass, SHADER_SOURCE); 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 index 0b7b0fb..fa5f45c 100644 --- 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 @@ -5,9 +5,9 @@ uniform sampler2D tex; uniform float radius; uniform float width; uniform float height; -uniform bool corners_top; -uniform bool corners_bottom; -uniform bool straight_corners; +uniform int corners_top; +uniform int corners_bottom; +uniform int straight_corners; uniform float clip_x0; uniform float clip_y0; @@ -30,17 +30,20 @@ float circle_bounds(vec2 p, vec2 center, float clip_radius) { } vec4 getTexture(vec2 uv) { - if (uv.x < 2. / width) - uv.x = 2. / width; + float w = max(1.0, width); + float h = max(1.0, height); - if (uv.y < 2. / height) - uv.y = 2. / height; + if (uv.x < 2. / w) + uv.x = 2. / w; - if (uv.x > 1. - 3. / width) - uv.x = 1. - 3. / width; + if (uv.y < 2. / h) + uv.y = 2. / h; - if (uv.y > 1. - 3. / height) - uv.y = 1. - 3. / height; + if (uv.x > 1. - 3. / w) + uv.x = 1. - 3. / w; + + if (uv.y > 1. - 3. / h) + uv.y = 1. - 3. / h; return texture2D(tex, uv); } @@ -66,11 +69,11 @@ float rounded_rect_coverage(vec2 p, vec4 bounds, float clip_radius) { float center_top = bounds.y + clip_radius; float center_bottom = bounds.w - clip_radius; - if (straight_corners) + if (straight_corners != 0) return 1.0; - else if (corners_top && p.y < center_top) + else if (corners_top != 0 && p.y < center_top) center.y = center_top + 2.; - else if (corners_bottom && p.y > center_bottom) + else if (corners_bottom != 0 && p.y > center_bottom) center.y = center_bottom - 1.; else return 1.0; @@ -93,4 +96,4 @@ void main(void) { 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 index 1727e30..6a44430 100644 --- 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 @@ -1,21 +1,24 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); const DEFAULT_PARAMS = { radius: 12, width: 0, height: 0, corners_top: true, corners_bottom: true, - clip: [0, 0, -1, -1] + clip: [0, 0, -1, -1], + // Reset on reuse: `EffectsManager` pools `CornerEffect` instances, and a + // pooled instance could otherwise keep rendering square (see corner.glsl). + straight_corners: false, }; -export const CornerEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const CORNER_EFFECT_META = { GTypeName: "CornerEffect", Properties: { 'radius': GObject.ParamSpec.double( @@ -56,20 +59,15 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? 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 { +}; + +const CornerEffectClass = utils.IS_IN_PREFERENCES ? null : class CornerEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); + + utils.initialize_shader_effect(this, SHADER_SOURCE); this._clip_x0 = null; this._clip_y0 = null; @@ -77,12 +75,6 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? this._clip_height = null; utils.setup_params(this, params); - this.straight_corners = false; - - // 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); @@ -113,7 +105,7 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? 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)); + uniforms.set_uniform(this, 'radius', parseFloat(radius - 1e-6)); } get width() { @@ -121,10 +113,11 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? } set width(value) { - if (this._width !== value) { - this._width = value; + const v = Math.max(1, value || 1); + if (this._width !== v) { + this._width = v; - this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); + uniforms.set_uniform(this, 'width', parseFloat(this._width + 3.0 - 1e-6)); this.update_radius(); } } @@ -134,10 +127,11 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? } set height(value) { - if (this._height !== value) { - this._height = value; + const v = Math.max(1, value || 1); + if (this._height !== v) { + this._height = v; - this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); + uniforms.set_uniform(this, 'height', parseFloat(this._height + 3.0 - 1e-6)); this.update_radius(); } } @@ -150,7 +144,7 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? if (this._corners_top !== value) { this._corners_top = value; - this.set_uniform_value('corners_top', this._corners_top ? 1 : 0); + uniforms.set_uniform(this, 'corners_top', this._corners_top ? 1 : 0); } } @@ -162,7 +156,7 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? if (this._corners_bottom !== value) { this._corners_bottom = value; - this.set_uniform_value('corners_bottom', this._corners_bottom ? 1 : 0); + uniforms.set_uniform(this, 'corners_bottom', this._corners_bottom ? 1 : 0); } } @@ -174,20 +168,37 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? if (this._straight_corners !== value) { this._straight_corners = value; - this.set_uniform_value('straight_corners', this._straight_corners ? 1 : 0); + uniforms.set_uniform(this, 'straight_corners', this._straight_corners ? 1 : 0); } } + detach_actor_clip_sync(actor = this.get_actor()) { + if (!actor || !this._actor_connection_clip_rect_id) + return; + + actor.disconnect(this._actor_connection_clip_rect_id); + + this._actor_connection_clip_rect_id = null; + } + + sync_actor_clip(actor) { + this.detach_actor_clip_sync(actor); + 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]; + }); + } + 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)); + uniforms.set_uniform(this, 'clip_x0', parseFloat(this._clip_x0 - 1e-6)); + uniforms.set_uniform(this, 'clip_y0', parseFloat(this._clip_y0 - 1e-6)); + uniforms.set_uniform(this, 'clip_width', parseFloat(this._clip_width <= 0 ? -1 : this._clip_width + 3 - 1e-6)); + uniforms.set_uniform(this, 'clip_height', parseFloat(this._clip_height <= 0 ? -1 : this._clip_height + 3 - 1e-6)); this.update_radius(); } @@ -196,10 +207,7 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? 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); - } + this.detach_actor_clip_sync(); if (actor) { this.width = actor.width; @@ -209,16 +217,21 @@ export const CornerEffect = utils.IS_IN_PREFERENCES ? 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]; - }); + this.sync_actor_clip(actor); } 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 + + vfunc_paint_target(paint_node, paint_context) { + uniforms.upload_uniforms(this); + super.vfunc_paint_target(paint_node, paint_context); + } +}; + +export const CornerEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(CORNER_EFFECT_META, CornerEffectClass, SHADER_SOURCE); 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 index 64c1682..b497b69 100644 --- 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 @@ -2,21 +2,22 @@ uniform sampler2D tex; uniform int operation; uniform float width; uniform float height; +uniform float opacity_factor; #define CORRECTION 2.25 -#define SIZE_ADDITION 3 +#define SIZE_ADDITION 3.0 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); + vec2 raw_uv = raw_position / vec2(max(1.0, width + SIZE_ADDITION), max(1.0, 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); + any(lessThan(position, vec2(0.0, 0.0)))) { + return vec4(0.0); } else { count++; return get_texture_at_position(position); @@ -31,41 +32,45 @@ ivec2 get_corrected_position() { void main() { ivec2 corrected_position = get_corrected_position(); + vec4 source_color = get_texture_at_position(vec2(corrected_position)); + vec4 effect_color = source_color; // 1-step derivative if (operation == 0) { - vec4 color = vec4(0); + vec4 color = vec4(0.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); + color += try_get_texture_at_position(vec2(corrected_position) + vec2(0.0, 1.0), c); + color -= try_get_texture_at_position(vec2(corrected_position) + vec2(0.0, 0.0), c); + color += try_get_texture_at_position(vec2(corrected_position) + vec2(1.0, 0.0), c); + color -= try_get_texture_at_position(vec2(corrected_position) + vec2(0.0, 0.0), c); if (c < 4) { - color = vec4(0); + color = vec4(0.0); } - cogl_color_out = vec4(color.xyz, 1); + effect_color = vec4(color.xyz, source_color.a); } else // 2-step derivative if (operation == 1) { - vec4 color = vec4(0); + vec4 color = vec4(0.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); + color += try_get_texture_at_position(vec2(corrected_position) + vec2(0.0, 1.0), c); + color -= try_get_texture_at_position(vec2(corrected_position) + vec2(0.0, -1.0), c); + color += try_get_texture_at_position(vec2(corrected_position) + vec2(1.0, 0.0), c); + color -= try_get_texture_at_position(vec2(corrected_position) + vec2(-1.0, 0.0), c); if (c < 4) { - color = vec4(0); + color = vec4(0.0); } - cogl_color_out = vec4(color.xyz / 2, 1); + effect_color = vec4(color.xyz / 2.0, source_color.a); } 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); + vec4 color = vec4(0.0); + color = -4.0 * get_texture_at_position(vec2(corrected_position)); + color += get_texture_at_position(vec2(corrected_position) + vec2(0.0, 1.0)); + color += get_texture_at_position(vec2(corrected_position) + vec2(0.0, -1.0)); + color += get_texture_at_position(vec2(corrected_position) + vec2(1.0, 0.0)); + color += get_texture_at_position(vec2(corrected_position) + vec2(-1.0, 0.0)); + effect_color = vec4(color.xyz, source_color.a); } -} \ No newline at end of file + + cogl_color_out = mix(source_color, effect_color, opacity_factor); +} 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 index 04d6100..a2d2bef 100644 --- 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 @@ -1,18 +1,18 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); const DEFAULT_PARAMS = { - operation: 0, width: 0, height: 0 + operation: 0, opacity_factor: 1, width: 0, height: 0 }; -export const DerivativeEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const DERIVATIVE_EFFECT_META = { GTypeName: "DerivativeEffect", Properties: { 'operation': GObject.ParamSpec.int( @@ -23,6 +23,14 @@ export const DerivativeEffect = utils.IS_IN_PREFERENCES ? 0, 2, 0, ), + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), 'width': GObject.ParamSpec.double( `width`, `Width`, @@ -40,16 +48,17 @@ export const DerivativeEffect = utils.IS_IN_PREFERENCES ? 0.0, ) } - }, class DerivativeEffect extends Clutter.ShaderEffect { +}; + +const DerivativeEffectClass = utils.IS_IN_PREFERENCES ? null : class DerivativeEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); + + utils.initialize_shader_effect(this, SHADER_SOURCE); - 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); + utils.setup_params(this, params); } static get default_params() { @@ -64,7 +73,19 @@ export const DerivativeEffect = utils.IS_IN_PREFERENCES ? if (this._operation !== value) { this._operation = value; - this.set_uniform_value('operation', this._operation); + uniforms.set_uniform(this, 'operation', this._operation); + } + } + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; + + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); } } @@ -73,10 +94,11 @@ export const DerivativeEffect = utils.IS_IN_PREFERENCES ? } set width(value) { - if (this._width !== value) { - this._width = value; + const v = Math.max(1, value || 1); + if (this._width !== v) { + this._width = v; - this.set_uniform_value('width', parseFloat(this._width - 1e-6)); + uniforms.set_uniform(this, 'width', parseFloat(this._width - 1e-6)); } } @@ -85,10 +107,11 @@ export const DerivativeEffect = utils.IS_IN_PREFERENCES ? } set height(value) { - if (this._height !== value) { - this._height = value; + const v = Math.max(1, value || 1); + if (this._height !== v) { + this._height = v; - this.set_uniform_value('height', parseFloat(this._height - 1e-6)); + uniforms.set_uniform(this, 'height', parseFloat(this._height - 1e-6)); } } @@ -112,9 +135,17 @@ export const DerivativeEffect = utils.IS_IN_PREFERENCES ? } vfunc_paint_target(paint_node, paint_context) { - // force setting nearest-neighbour texture filtering - this.get_pipeline().set_layer_filters(0, 9728, 9728); + uniforms.upload_uniforms(this); + + const pipeline = this.get_pipeline(); + if (pipeline) { + pipeline.set_layer_filters(0, 9728, 9728); + } super.vfunc_paint_target(paint_node, paint_context); } - }); \ No newline at end of file +}; + +export const DerivativeEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(DERIVATIVE_EFFECT_META, DerivativeEffectClass, SHADER_SOURCE); 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 index 9871268..8b57367 100644 --- 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 @@ -3,13 +3,14 @@ uniform int divider; uniform float width; uniform float height; uniform int downsampling_mode; +uniform float opacity_factor; #define CORRECTION 2.25 -#define SIZE_ADDITION 3 +#define SIZE_ADDITION 3.0 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); + vec2 raw_uv = raw_position / vec2(max(1.0, width + SIZE_ADDITION), max(1.0, height + SIZE_ADDITION)); return texture2D(tex, raw_uv); } @@ -21,11 +22,14 @@ vec2 get_corrected_position() { } void main() { + vec4 source_color = texture2D(tex, cogl_tex_coord0_in.st); + vec4 effect_color = vec4(0.0); ivec2 corrected_position = ivec2(get_corrected_position()); - vec2 multiplied_position = corrected_position * divider; + vec2 multiplied_position = vec2(corrected_position) * float(divider); if (any(greaterThan(multiplied_position, vec2(width, height)))) { - discard; + cogl_color_out = mix(source_color, effect_color, opacity_factor); + return; } // mode 0: boxcar downsampling @@ -35,15 +39,15 @@ void main() { 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))) && + vec2 lookup_position = multiplied_position + vec2(float(i), float(j)); + if (all(greaterThanEqual(lookup_position, vec2(0.0, 0.0))) && all(lessThan(lookup_position, vec2(width, height)))) { color += get_texture_at_position(lookup_position); count += 1; } } } - cogl_color_out = color / count; + effect_color = color / max(1.0, float(count)); } else // mode 1: triangular downsampling @@ -54,23 +58,25 @@ void main() { 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))) && + vec2 lookup_position = multiplied_position + vec2(float(i), float(j)); + if (all(greaterThanEqual(lookup_position, vec2(0.0, 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; + force = 1 + divider - int(abs(float(divider - i - j))); + color += get_texture_at_position(lookup_position) * float(force); count += force; } } } - cogl_color_out = color / count; + effect_color = color / max(1.0, float(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); + vec2 lookup_position = min(multiplied_position + vec2(float(divider)) * 0.5, vec2(width - 1.0, height - 1.0)); + effect_color = get_texture_at_position(lookup_position); } -} \ No newline at end of file + + cogl_color_out = mix(source_color, effect_color, opacity_factor); +} 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 index 8103486..b6e08c4 100644 --- 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 @@ -1,18 +1,18 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); const DEFAULT_PARAMS = { - divider: 8, downsampling_mode: 0, width: 0, height: 0 + divider: 8, downsampling_mode: 0, opacity_factor: 1, width: 0, height: 0 }; -export const DownscaleEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const DOWNSCALE_EFFECT_META = { GTypeName: "DownscaleEffect", Properties: { 'divider': GObject.ParamSpec.int( @@ -31,6 +31,14 @@ export const DownscaleEffect = utils.IS_IN_PREFERENCES ? 0, 2, 0, ), + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), 'width': GObject.ParamSpec.double( `width`, `Width`, @@ -48,16 +56,17 @@ export const DownscaleEffect = utils.IS_IN_PREFERENCES ? 0.0, ) } - }, class DownscaleEffect extends Clutter.ShaderEffect { +}; + +const DownscaleEffectClass = utils.IS_IN_PREFERENCES ? null : class DownscaleEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); + + utils.initialize_shader_effect(this, SHADER_SOURCE); - 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); + utils.setup_params(this, params); } static get default_params() { @@ -69,10 +78,11 @@ export const DownscaleEffect = utils.IS_IN_PREFERENCES ? } set divider(value) { - if (this._divider !== value) { - this._divider = value; + const v = Math.max(1, value || 1); + if (this._divider !== v) { + this._divider = v; - this.set_uniform_value('divider', this._divider); + uniforms.set_uniform(this, 'divider', this._divider); } } @@ -84,7 +94,19 @@ export const DownscaleEffect = utils.IS_IN_PREFERENCES ? if (this._downsampling_mode !== value) { this._downsampling_mode = value; - this.set_uniform_value('downsampling_mode', this._downsampling_mode); + uniforms.set_uniform(this, 'downsampling_mode', this._downsampling_mode); + } + } + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; + + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); } } @@ -93,10 +115,11 @@ export const DownscaleEffect = utils.IS_IN_PREFERENCES ? } set width(value) { - if (this._width !== value) { - this._width = value; + const v = Math.max(1, value || 1); + if (this._width !== v) { + this._width = v; - this.set_uniform_value('width', parseFloat(this._width - 1e-6)); + uniforms.set_uniform(this, 'width', parseFloat(this._width - 1e-6)); } } @@ -105,10 +128,11 @@ export const DownscaleEffect = utils.IS_IN_PREFERENCES ? } set height(value) { - if (this._height !== value) { - this._height = value; + const v = Math.max(1, value || 1); + if (this._height !== v) { + this._height = v; - this.set_uniform_value('height', parseFloat(this._height - 1e-6)); + uniforms.set_uniform(this, 'height', parseFloat(this._height - 1e-6)); } } @@ -132,9 +156,17 @@ export const DownscaleEffect = utils.IS_IN_PREFERENCES ? } vfunc_paint_target(paint_node, paint_context) { - // force setting nearest-neighbour texture filtering - this.get_pipeline().set_layer_filters(0, 9728, 9728); + uniforms.upload_uniforms(this); + + const pipeline = this.get_pipeline(); + if (pipeline) { + pipeline.set_layer_filters(0, 9728, 9728); + } super.vfunc_paint_target(paint_node, paint_context); } - }); \ No newline at end of file +}; + +export const DownscaleEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(DOWNSCALE_EFFECT_META, DownscaleEffectClass, SHADER_SOURCE); diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effect_groups.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effect_groups.js new file mode 100644 index 0000000..c53a647 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effect_groups.js @@ -0,0 +1,31 @@ +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', + 'refraction', + 'derivative', + 'noise', + 'color', + 'luminosity', + 'rgb_to_hsl', + 'hsl_to_rgb', + ], + }, + shape_effects: { + name: _('Shape effects'), + contains: ['corner'], + }, + }; +} 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 index 4ab5a71..984aa47 100644 --- 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 @@ -12,41 +12,8 @@ import { DerivativeEffect } from './derivative.js'; import { RgbToHslEffect } from './rgb_to_hsl.js'; import { HslToRgbEffect } from './hsl_to_rgb.js'; import { LuminosityEffect } from './luminosity.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", - "luminosity", - "rgb_to_hsl", - "hsl_to_rgb" - ] - }, - shape_effects: { - name: _("Shape effects"), - contains: [ - "corner" - ] - } - }; -}; +import { RefractionEffect } from './refraction.js'; +export { get_effects_groups } from './effect_groups.js'; export function get_supported_effects(_ = () => "") { return { @@ -378,6 +345,140 @@ export function get_supported_effects(_ = () => "") { } }, + refraction: { + class: RefractionEffect, + name: _("Liquid Glass"), + description: _("A glossy translucent material with edge refraction, rim lighting, tint, and inner shadow."), + is_advanced: false, + editable_params: { + strength: { + name: _("Refraction scale"), + description: _("How strongly the glass bends the sampled blur texture."), + type: "float", + min: 0., + max: 1., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + blur_radius: { + name: _("Blur radius"), + description: _("Blurs the sampled backdrop before the liquid-glass shader is applied."), + type: "float", + min: 0., + max: 48., + increment: 1., + big_increment: 10., + digits: 0 + }, + edge_size: { + name: _("Bezel width"), + description: _("How far the liquid-glass lens reaches inward from the edge."), + type: "float", + min: 1., + max: 100., + increment: 1., + big_increment: 10., + digits: 0 + }, + rim_width: { + name: _("Rim spread"), + description: _("How far the refraction eases inward from the glass edge."), + type: "float", + min: 1., + max: 6.5, + increment: 0.1, + big_increment: 0.5, + digits: 2 + }, + falloff: { + name: _("Glass thickness"), + description: _("Depth used by the Snell-style refraction profile."), + type: "float", + min: 0.25, + max: 8., + increment: 0.05, + big_increment: 0.5, + digits: 2 + }, + corner_radius: { + name: _("Corner radius"), + description: _("The rounded shape used for the glass edge and highlight."), + type: "float", + min: 0., + max: 100., + increment: 1., + big_increment: 10., + digits: 0 + }, + gloss: { + name: _("Fresnel glare"), + description: _("Strength of the Schlick fresnel rim glare from the glass edge."), + type: "float", + min: 0., + max: 1., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + tint: { + name: _("Tint strength"), + description: _("Amount of subtle milky glass tint over the blurred texture."), + type: "float", + min: 0., + max: 1., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + tint_color: { + name: _("Tint color"), + description: _("Color blended over the blurred texture, weighted by the tint strength."), + type: "rgba", + use_alpha: true + }, + backdrop_zoom: { + name: _("Backdrop zoom"), + description: _("Zoom level of the backdrop visible through the glass."), + type: "float", + min: 0.1, + max: 4., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + shadow: { + name: _("Inner shadow"), + description: _("Darkens the lower and inner edge for a deeper glass surface."), + type: "float", + min: 0., + max: 1., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + rgb_fringing: { + name: _("Chromatic dispersion"), + description: _("Physical per-channel refraction dispersion at the glass edge."), + type: "float", + min: 0., + max: 1., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + texture_repeat: { + name: _("Edge behavior"), + description: _("How texture coordinates outside the actor are sampled."), + type: "dropdown", + options: [ + _("Clamp"), + _("Mirror") + ] + } + } + }, + rgb_to_hsl: { class: RgbToHslEffect, name: _("RGB to HSL (advanced effect)"), @@ -402,7 +503,7 @@ export function get_supported_effects(_ = () => "") { editable_params: { radius: { name: _("Radius"), - description: _("The radius of the corner. GNOME apps use a radius of 12 px by default."), + description: _("The radius of the corner. GNOME apps use a radius of 15 px by default."), type: "integer", min: 0, max: 150, @@ -421,4 +522,4 @@ export function get_supported_effects(_ = () => "") { } } }; -}; \ 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 index 809cc93..2bc641f 100644 --- 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 @@ -6,30 +6,35 @@ uniform float width; uniform float height; vec4 getTexture(vec2 uv) { - if (uv.x < 3. / width) - uv.x = 3. / width; + float w = max(1.0, width); + float h = max(1.0, height); - if (uv.y < 3. / height) - uv.y = 3. / height; + if (uv.x < 3. / w) + uv.x = 3. / w; - if (uv.x > 1. - 3. / width) - uv.x = 1. - 3. / width; + if (uv.y < 3. / h) + uv.y = 3. / h; - if (uv.y > 1. - 3. / height) - uv.y = 1. - 3. / height; + if (uv.x > 1. - 3. / w) + uv.x = 1. - 3. / w; + + if (uv.y > 1. - 3. / h) + uv.y = 1. - 3. / h; return texture2D(tex, uv); } void main(void) { vec2 uv = cogl_tex_coord_in[0].xy; - vec2 direction = vec2(dir, (1.0 - dir)); + vec2 direction = vec2(float(dir), 1.0 - float(dir)); + float w = max(1.0, width); + float h = max(1.0, height); float pixel_step; if (dir == 0) - pixel_step = 1.0 / height; + pixel_step = 1.0 / h; else - pixel_step = 1.0 / width; + pixel_step = 1.0 / w; vec3 gauss_coefficient; gauss_coefficient.x = 1.0 / (sqrt(2.0 * 3.14159265) * sigma); @@ -67,4 +72,4 @@ void main(void) { } 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 index 113a6fd..631831e 100644 --- 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 @@ -1,20 +1,20 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); 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({ +const GAUSSIAN_BLUR_EFFECT_META = { GTypeName: "GaussianBlurEffect", Properties: { 'radius': GObject.ParamSpec.double( @@ -65,21 +65,22 @@ export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ? GObject.Object, ), } - }, class GaussianBlurEffect extends Clutter.ShaderEffect { +}; + +const GaussianBlurEffectClass = utils.IS_IN_PREFERENCES ? null : class GaussianBlurEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); + + utils.initialize_shader_effect(this, SHADER_SOURCE); - 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); + utils.setup_params(this, params); const theme_context = St.ThemeContext.get_for_stage(global.stage); theme_context.connectObject( 'notify::scale-factor', _ => - this.set_uniform_value('sigma', + uniforms.set_uniform(this, 'sigma', parseFloat(this.radius * theme_context.scale_factor / 2 - 1e-6) ), this @@ -101,7 +102,7 @@ export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ? 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)); + uniforms.set_uniform(this, 'sigma', parseFloat(this._radius * scale_factor / 2 - 1e-6)); this.set_enabled(this.radius > 0.); if (this.chained_effect) @@ -117,7 +118,7 @@ export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ? if (this._brightness !== value) { this._brightness = value; - this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6)); + uniforms.set_uniform(this, 'brightness', parseFloat(this._brightness - 1e-6)); if (this.chained_effect) this.chained_effect.brightness = value; @@ -129,13 +130,14 @@ export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ? } set width(value) { - if (this._width !== value) { - this._width = value; + const v = Math.max(1, value || 1); + if (this._width !== v) { + this._width = v; - this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); + uniforms.set_uniform(this, 'width', parseFloat(this._width + 3.0 - 1e-6)); if (this.chained_effect) - this.chained_effect.width = value; + this.chained_effect.width = v; } } @@ -144,13 +146,14 @@ export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ? } set height(value) { - if (this._height !== value) { - this._height = value; + const v = Math.max(1, value || 1); + if (this._height !== v) { + this._height = v; - this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); + uniforms.set_uniform(this, 'height', parseFloat(this._height + 3.0 - 1e-6)); if (this.chained_effect) - this.chained_effect.height = value; + this.chained_effect.height = v; } } @@ -159,8 +162,10 @@ export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ? } set direction(value) { - if (this._direction !== value) + if (this._direction !== value) { this._direction = value; + uniforms.set_uniform(this, "dir", this._direction); + } } get chained_effect() { @@ -202,12 +207,16 @@ export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ? }); if (actor !== null) actor.add_effect(this.chained_effect); + uniforms.mark_dirty(this.chained_effect); } } vfunc_paint_target(paint_node, paint_context) { - this.set_uniform_value("dir", this.direction); - + uniforms.upload_uniforms(this); super.vfunc_paint_target(paint_node, paint_context); } - }); \ No newline at end of file +}; + +export const GaussianBlurEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(GAUSSIAN_BLUR_EFFECT_META, GaussianBlurEffectClass, SHADER_SOURCE); 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 index 58d2694..8b9990d 100644 --- 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 @@ -1,4 +1,5 @@ uniform sampler2D tex; +uniform float opacity_factor; vec3 hsl_to_rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); @@ -10,5 +11,5 @@ 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 + cogl_color_out = mix(hsla, rgba, opacity_factor); +} 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 index fe53114..b79ee84 100644 --- 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 @@ -1,31 +1,64 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 = {}; +const SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); +const DEFAULT_PARAMS = { + opacity_factor: 1 +}; -export const HslToRgbEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const HSL_TO_RGB_EFFECT_META = { GTypeName: "HslToRgbEffect", - Properties: {} - }, class HslToRgbEffect extends Clutter.ShaderEffect { + Properties: { + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + } +}; + +const HslToRgbEffectClass = utils.IS_IN_PREFERENCES ? null : class HslToRgbEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); - utils.setup_params(this, params); + utils.initialize_shader_effect(this, SHADER_SOURCE); - // set shader source - this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); - if (this._source) - this.set_shader_source(this._source); + + utils.setup_params(this, params); } static get default_params() { return DEFAULT_PARAMS; } - }); \ No newline at end of file + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; + + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); + } + } + + vfunc_paint_target(paint_node, paint_context) { + uniforms.upload_uniforms(this); + super.vfunc_paint_target(paint_node, paint_context); + } +}; + +export const HslToRgbEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(HSL_TO_RGB_EFFECT_META, HslToRgbEffectClass, SHADER_SOURCE); diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/luminosity.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/luminosity.glsl index 4c50ca4..e7cc855 100644 --- a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/luminosity.glsl +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/luminosity.glsl @@ -4,6 +4,7 @@ uniform float brightness_multiplicator; uniform float contrast; uniform float contrast_center; uniform float saturation_multiplicator; +uniform float opacity_factor; vec3 hsl_to_rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); @@ -24,10 +25,16 @@ vec3 rgb_to_hsl(vec3 c) { void main() { vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); + if (c.a <= 0.0) { + cogl_color_out = c; + return; + } + vec3 pix_hsl = rgb_to_hsl(c.xyz) / c.a; pix_hsl.z = clamp(pix_hsl.z * brightness_multiplicator, 0., 1.); pix_hsl.z = clamp((pix_hsl.z - contrast_center) * contrast + contrast_center + brightness_shift, 0., 1.); pix_hsl.y = clamp(pix_hsl.y * saturation_multiplicator, 0., 1.); - cogl_color_out = vec4(hsl_to_rgb(pix_hsl) * c.a, c.a); -} \ No newline at end of file + vec4 effect_color = vec4(hsl_to_rgb(pix_hsl) * c.a, c.a); + cogl_color_out = mix(c, effect_color, opacity_factor); +} diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/luminosity.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/luminosity.js index c22636d..a4b6364 100644 --- a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/luminosity.js +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/luminosity.js @@ -1,18 +1,18 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.js'; const Shell = await utils.import_in_shell_only('gi://Shell'); const Clutter = await utils.import_in_shell_only('gi://Clutter'); const SHADER_FILENAME = 'luminosity.glsl'; +const SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); const DEFAULT_PARAMS = { - brightness_shift: 0., brightness_multiplicator: 1., contrast: 1., contrast_center: 0.5, saturation_multiplicator: 1. + brightness_shift: 0., brightness_multiplicator: 1., contrast: 1., contrast_center: 0.5, saturation_multiplicator: 1., opacity_factor: 1. }; -export const LuminosityEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const LUMINOSITY_EFFECT_META = { GTypeName: "LuminosityEffect", Properties: { 'brightness_shift': GObject.ParamSpec.double( @@ -55,17 +55,26 @@ export const LuminosityEffect = utils.IS_IN_PREFERENCES ? 0.0, 2.0, 1.0, ), + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), } - }, class LuminosityEffect extends Clutter.ShaderEffect { +}; + +const LuminosityEffectClass = utils.IS_IN_PREFERENCES ? null : class LuminosityEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); - utils.setup_params(this, params); + utils.initialize_shader_effect(this, SHADER_SOURCE); - // set shader source - this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); - if (this._source) - this.set_shader_source(this._source); + + utils.setup_params(this, params); } static get default_params() { @@ -80,7 +89,7 @@ export const LuminosityEffect = utils.IS_IN_PREFERENCES ? if (this._brightness_shift !== value) { this._brightness_shift = value; - this.set_uniform_value('brightness_shift', parseFloat(this._brightness_shift - 1e-6)); + uniforms.set_uniform(this, 'brightness_shift', parseFloat(this._brightness_shift - 1e-6)); } } @@ -96,7 +105,7 @@ export const LuminosityEffect = utils.IS_IN_PREFERENCES ? let brightness_mul = 600.; if (value < 1.995) brightness_mul = 3. * (1. / (1. - (value / 2.) ** 2) - 1.); - this.set_uniform_value('brightness_multiplicator', parseFloat(brightness_mul - 1e-6)); + uniforms.set_uniform(this, 'brightness_multiplicator', parseFloat(brightness_mul - 1e-6)); } } @@ -108,7 +117,7 @@ export const LuminosityEffect = utils.IS_IN_PREFERENCES ? if (this._contrast !== value) { this._contrast = value; - this.set_uniform_value('contrast', parseFloat(this._contrast - 1e-6)); + uniforms.set_uniform(this, 'contrast', parseFloat(this._contrast - 1e-6)); } } @@ -120,7 +129,7 @@ export const LuminosityEffect = utils.IS_IN_PREFERENCES ? if (this._contrast_center !== value) { this._contrast_center = value; - this.set_uniform_value('contrast_center', parseFloat(this._contrast_center - 1e-6)); + uniforms.set_uniform(this, 'contrast_center', parseFloat(this._contrast_center - 1e-6)); } } @@ -135,7 +144,28 @@ export const LuminosityEffect = utils.IS_IN_PREFERENCES ? let saturation_mul = 600.; if (value < 1.995) saturation_mul = 3. * (1. / (1. - (value / 2.) ** 2) - 1.); - this.set_uniform_value('saturation_multiplicator', parseFloat(saturation_mul - 1e-6)); + uniforms.set_uniform(this, 'saturation_multiplicator', parseFloat(saturation_mul - 1e-6)); } } - }); \ No newline at end of file + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; + + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); + } + } + + vfunc_paint_target(paint_node, paint_context) { + uniforms.upload_uniforms(this); + super.vfunc_paint_target(paint_node, paint_context); + } +}; + +export const LuminosityEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(LUMINOSITY_EFFECT_META, LuminosityEffectClass, SHADER_SOURCE); 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 index c63d266..ee0c35f 100644 --- 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 @@ -4,8 +4,8 @@ uniform int iterations; uniform float brightness; uniform float width; uniform float height; -uniform bool use_base_pixel; -uniform bool prefer_closer_pixels; +uniform int use_base_pixel; +uniform int prefer_closer_pixels; float srand(vec2 a) { return sin(dot(a, vec2(1233.224, 1743.335))); @@ -18,7 +18,7 @@ float rand(inout float r) { void main() { vec2 uv = cogl_tex_coord0_in.st; - vec2 p = 16 * radius / vec2(width, height); + vec2 p = 16.0 * radius / vec2(width, height); float r = srand(uv); vec2 rv; @@ -35,18 +35,18 @@ void main() { 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) * (iterations - i)) : 1; - c += strength * texture2D(tex, new_uv); + strength = prefer_closer_pixels != 0 ? ((iterations - i) * (iterations - i)) : 1; + c += float(strength) * texture2D(tex, new_uv); count += strength; } } - if (count == 0 || use_base_pixel) { - strength = prefer_closer_pixels ? ((iterations + 1) * (iterations + 1)) : 1; - c += strength * texture2D(tex, uv); + if (count == 0 || use_base_pixel != 0) { + strength = prefer_closer_pixels != 0 ? ((iterations + 1) * (iterations + 1)) : 1; + c += float(strength) * texture2D(tex, uv); count += strength; } c.xyz *= brightness; - cogl_color_out = c / count; -} \ No newline at end of file + cogl_color_out = c / max(1.0, float(count)); +} 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 index 0da56ed..e8deb9c 100644 --- 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 @@ -1,11 +1,13 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); const DEFAULT_PARAMS = { radius: 2., iterations: 5, brightness: .6, width: 0, height: 0, use_base_pixel: true, @@ -13,9 +15,7 @@ const DEFAULT_PARAMS = { }; -export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const MONTE_CARLO_BLUR_EFFECT_META = { GTypeName: "MonteCarloBlurEffect", Properties: { 'radius': GObject.ParamSpec.double( @@ -73,21 +73,22 @@ export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? true, ), } - }, class MonteCarloBlurEffect extends Clutter.ShaderEffect { +}; + +const MonteCarloBlurEffectClass = utils.IS_IN_PREFERENCES ? null : class MonteCarloBlurEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); + + utils.initialize_shader_effect(this, SHADER_SOURCE); - 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); + utils.setup_params(this, params); const theme_context = St.ThemeContext.get_for_stage(global.stage); theme_context.connectObject( 'notify::scale-factor', - _ => this.set_uniform_value('radius', + _ => uniforms.set_uniform(this, 'radius', parseFloat(this._radius * theme_context.scale_factor - 1e-6) ), this @@ -108,7 +109,7 @@ export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? const scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - this.set_uniform_value('radius', parseFloat(this._radius * scale_factor - 1e-6)); + uniforms.set_uniform(this, 'radius', parseFloat(this._radius * scale_factor - 1e-6)); this.set_enabled(this.radius > 0. && this.iterations > 0); } } @@ -121,7 +122,7 @@ export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? if (this._iterations !== value) { this._iterations = value; - this.set_uniform_value('iterations', this._iterations); + uniforms.set_uniform(this, 'iterations', this._iterations); this.set_enabled(this.radius > 0. && this.iterations > 0); } } @@ -134,7 +135,7 @@ export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? if (this._brightness !== value) { this._brightness = value; - this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6)); + uniforms.set_uniform(this, 'brightness', parseFloat(this._brightness - 1e-6)); } } @@ -143,10 +144,11 @@ export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? } set width(value) { - if (this._width !== value) { - this._width = value; + const v = Math.max(1, value || 1); + if (this._width !== v) { + this._width = v; - this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); + uniforms.set_uniform(this, 'width', parseFloat(this._width + 3.0 - 1e-6)); } } @@ -155,10 +157,11 @@ export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? } set height(value) { - if (this._height !== value) { - this._height = value; + const v = Math.max(1, value || 1); + if (this._height !== v) { + this._height = v; - this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); + uniforms.set_uniform(this, 'height', parseFloat(this._height + 3.0 - 1e-6)); } } @@ -170,7 +173,7 @@ export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? if (this._use_base_pixel !== value) { this._use_base_pixel = value; - this.set_uniform_value('use_base_pixel', this._use_base_pixel ? 1 : 0); + uniforms.set_uniform(this, 'use_base_pixel', this._use_base_pixel ? 1 : 0); } } @@ -182,7 +185,7 @@ export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? if (this._prefer_closer_pixels !== value) { this._prefer_closer_pixels = value; - this.set_uniform_value('prefer_closer_pixels', this._prefer_closer_pixels ? 1 : 0); + uniforms.set_uniform(this, 'prefer_closer_pixels', this._prefer_closer_pixels ? 1 : 0); } } @@ -204,4 +207,13 @@ export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? super.vfunc_set_actor(actor); } - }); \ No newline at end of file + + vfunc_paint_target(paint_node, paint_context) { + uniforms.upload_uniforms(this); + super.vfunc_paint_target(paint_node, paint_context); + } +}; + +export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(MONTE_CARLO_BLUR_EFFECT_META, MonteCarloBlurEffectClass, SHADER_SOURCE); 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 index 3df621b..fc24e07 100644 --- 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 @@ -3,55 +3,72 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; const St = await utils.import_in_shell_only('gi://St'); -let BlurOrShell = await utils.import_in_shell_only('gi://Blur'); -let IS_BLUR_MODULE = true; -if (BlurOrShell === null) { - BlurOrShell = await utils.import_in_shell_only('gi://Shell'); - IS_BLUR_MODULE = false; -} +const BlurModule = await utils.import_in_shell_only('gi://Blur'); +const Shell = await utils.import_in_shell_only('gi://Shell'); +const BlurOrShell = utils.is_usable_blur_module(BlurModule) ? BlurModule : Shell; +const SUPPORTS_CORNER_RADIUS = Boolean( + BlurOrShell?.BlurEffect?.list_properties() + .some(property => property.name === 'corner-radius') +); const DEFAULT_PARAMS = { - unscaled_radius: 30, brightness: 0.6, corner_radius: 14 + unscaled_radius: 30, + brightness: 0.6, + unscaled_corner_radius: 0, }; export const NativeDynamicBlurEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : + { default_params: DEFAULT_PARAMS, supports_corner_radius: false } : new GObject.registerClass({ GTypeName: "NativeDynamicBlurEffect" }, class NativeDynamicBlurEffect extends BlurOrShell.BlurEffect { constructor(params) { - const { unscaled_radius, brightness, corner_radius, ...parent_params } = params; - if (IS_BLUR_MODULE) - super({ ...parent_params, mode: BlurOrShell.BlurMode.BACKGROUND, ...{ 'corner_radius': corner_radius } }); - else - super({ ...parent_params, mode: BlurOrShell.BlurMode.BACKGROUND }); + const normalized_params = { ...params }; + if (!('unscaled_radius' in normalized_params) && 'radius' in normalized_params) + normalized_params.unscaled_radius = normalized_params.radius; + delete normalized_params.radius; + + if (!('unscaled_corner_radius' in normalized_params) && 'corner_radius' in normalized_params) + normalized_params.unscaled_corner_radius = normalized_params.corner_radius; + delete normalized_params.corner_radius; + + const parent_params = { ...normalized_params }; + delete parent_params.unscaled_radius; + delete parent_params.brightness; + delete parent_params.unscaled_corner_radius; + super({ ...parent_params, mode: BlurOrShell.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.corner_radius = this.unscaled_corner_radius * this._theme_context.scale_factor; + this.radius = Math.max(0, this.unscaled_radius * this._theme_context.scale_factor); + if (SUPPORTS_CORNER_RADIUS) + this.corner_radius = this.unscaled_corner_radius * this._theme_context.scale_factor; }, this ); - utils.setup_params(this, params); + utils.setup_params(this, normalized_params); } static get default_params() { return DEFAULT_PARAMS; } + static get supports_corner_radius() { + return SUPPORTS_CORNER_RADIUS; + } + get unscaled_radius() { return this._unscaled_radius; } set unscaled_radius(value) { this._unscaled_radius = value; - this.radius = value * this._theme_context.scale_factor; + this.radius = Math.max(0, value * this._theme_context.scale_factor); } get unscaled_corner_radius() { @@ -60,6 +77,7 @@ export const NativeDynamicBlurEffect = utils.IS_IN_PREFERENCES ? set unscaled_corner_radius(value) { this._unscaled_corner_radius = value; - this.corner_radius = value * this._theme_context.scale_factor; + if (SUPPORTS_CORNER_RADIUS) + this.corner_radius = value * this._theme_context.scale_factor; } }); 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 index fe003f5..cc7aa7b 100644 --- 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 @@ -15,17 +15,26 @@ export const NativeStaticBlurEffect = utils.IS_IN_PREFERENCES ? GTypeName: "NativeStaticBlurEffect" }, class NativeStaticBlurEffect extends Shell.BlurEffect { constructor(params) { - const { unscaled_radius, brightness, ...parent_params } = params; + const normalized_params = { ...params }; + if (!('unscaled_radius' in normalized_params) && 'radius' in normalized_params) + normalized_params.unscaled_radius = normalized_params.radius; + delete normalized_params.radius; + + const { + unscaled_radius: _unscaled_radius, + brightness: _brightness, + ...parent_params + } = normalized_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.radius = Math.max(0.5, this.unscaled_radius * this._theme_context.scale_factor), this ); - utils.setup_params(this, params); + utils.setup_params(this, normalized_params); } static get default_params() { @@ -38,6 +47,6 @@ export const NativeStaticBlurEffect = utils.IS_IN_PREFERENCES ? set unscaled_radius(value) { this._unscaled_radius = value; - this.radius = value * this._theme_context.scale_factor; + this.radius = Math.max(0.5, 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 index 6d701b6..df03b71 100644 --- 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 @@ -1,9 +1,10 @@ uniform sampler2D tex; uniform float noise; uniform float lightness; +uniform float opacity_factor; float PHI = 1.61803398874989484820459; -float SEED = 24; +float SEED = 24.0; float noise_gen(in vec2 xy) { float r = fract(tan(distance(xy * PHI, xy) * SEED) * xy.x); @@ -13,8 +14,9 @@ float noise_gen(in vec2 xy) { 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)); + float blend = noise * (1. - noise_gen(gl_FragCoord.xy)) * opacity_factor; + vec3 pix_color = c.rgb; + vec3 noise_color = vec3(lightness); - cogl_color_out = vec4(mix(pix_color, lightness * pix_color, blend), 1.); -} \ No newline at end of file + cogl_color_out = vec4(mix(pix_color, noise_color, blend), c.a); +} 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 index 3049fa1..5b2c2e1 100644 --- 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 @@ -1,18 +1,18 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); const DEFAULT_PARAMS = { - noise: 0.4, lightness: 0.4 + noise: 0.4, lightness: 0.4, opacity_factor: 1 }; -export const NoiseEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const NOISE_EFFECT_META = { GTypeName: "NoiseEffect", Properties: { 'noise': GObject.ParamSpec.double( @@ -31,17 +31,26 @@ export const NoiseEffect = utils.IS_IN_PREFERENCES ? 0.0, 2.0, 0.4, ), + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), } - }, class NoiseEffect extends Clutter.ShaderEffect { +}; + +const NoiseEffectClass = utils.IS_IN_PREFERENCES ? null : class NoiseEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); + + utils.initialize_shader_effect(this, SHADER_SOURCE); - 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); + utils.setup_params(this, params); } static get default_params() { @@ -56,7 +65,7 @@ export const NoiseEffect = utils.IS_IN_PREFERENCES ? if (this._noise !== value) { this._noise = value; - this.set_uniform_value('noise', parseFloat(this._noise - 1e-6)); + uniforms.set_uniform(this, 'noise', parseFloat(this._noise - 1e-6)); this.set_enabled(this.noise > 0. && this.lightness != 1); } } @@ -69,8 +78,29 @@ export const NoiseEffect = utils.IS_IN_PREFERENCES ? if (this._lightness !== value) { this._lightness = value; - this.set_uniform_value('lightness', parseFloat(this._lightness - 1e-6)); + uniforms.set_uniform(this, 'lightness', parseFloat(this._lightness - 1e-6)); this.set_enabled(this.noise > 0. && this.lightness != 1); } } - }); \ No newline at end of file + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; + + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); + } + } + + vfunc_paint_target(paint_node, paint_context) { + uniforms.upload_uniforms(this); + super.vfunc_paint_target(paint_node, paint_context); + } +}; + +export const NoiseEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(NOISE_EFFECT_META, NoiseEffectClass, SHADER_SOURCE); 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 index e9cad9b..e4a833c 100644 --- 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 @@ -3,11 +3,8 @@ 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 + factor: 8, downsampling_mode: 0, opacity_factor: 1 }; @@ -31,15 +28,20 @@ export const PixelizeEffect = utils.IS_IN_PREFERENCES ? GObject.ParamFlags.READWRITE, 0, 2, 0, + ), + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, ) } }, class PixelizeEffect extends Clutter.Effect { constructor(params) { super(); - this.upscale_effect = new UpscaleEffect({}); - this.downscale_effect = new DownscaleEffect({}); - utils.setup_params(this, params); } @@ -48,41 +50,26 @@ export const PixelizeEffect = utils.IS_IN_PREFERENCES ? } get factor() { - // should be the same as `this.downscale_effect.divider` - return this.upscale_effect.factor; + return this._factor; } set factor(value) { - this.upscale_effect.factor = value; - this.downscale_effect.divider = value; + this._factor = value; } get downsampling_mode() { - return this.downscale_effect.downsampling_mode; + return this._downsampling_mode; } set downsampling_mode(value) { - this.downscale_effect.downsampling_mode = value; + this._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); + get opacity_factor() { + return this._opacity_factor; } - 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); + set opacity_factor(value) { + this._opacity_factor = value; } - }); \ No newline at end of file + }); diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.glsl new file mode 100644 index 0000000..5d1d241 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.glsl @@ -0,0 +1,412 @@ +// GLSL port of winaviation-tweaks/liquidass LiquidAssBackboardd/Tweak.mm kShaderSrc. +// The sampling and blur pass are adapted for Blur my Shell's Clutter pipeline. +uniform sampler2D tex; +uniform float width; +uniform float height; +uniform float strength; +uniform float blur_radius; +uniform float edge_size; +uniform float falloff; +uniform float corner_radius; +uniform float rim_width; +uniform float rgb_fringing; +uniform float gloss; +uniform float tint; +uniform float tint_r; +uniform float tint_g; +uniform float tint_b; +uniform float tint_a; +uniform float backdrop_zoom; +uniform float shadow; +uniform int texture_repeat; +uniform int blur_direction; +uniform int private_pass; +uniform float clip_x0; +uniform float clip_y0; +uniform float clip_width; +uniform float clip_height; +uniform float opacity_factor; + +const float PI = 3.14159265; +const float REFRACTIVE_INDEX = 1.52; +const float DISPERSION_SCALE = 20.0; + +const float kDispersionRedIndex = 0.98; +const float kDispersionGreenIndex = 1.00; +const float kDispersionBlueIndex = 1.02; + +float surfaceConvexSquircle(float x) { + return pow(1.0 - pow(1.0 - x, 4.0), 0.25); +} + +vec2 refractRay(vec2 normal, float eta) { + float cosI = -normal.y; + float k = 1.0 - eta * eta * (1.0 - cosI * cosI); + if (k < 0.0) + return vec2(0.0); + + float kSqrt = sqrt(k); + return vec2( + -(eta * cosI + kSqrt) * normal.x, + eta - (eta * cosI + kSqrt) * normal.y + ); +} + +float rawRefraction(float bezelRatio, float glassThickness, float bezelWidth, float eta) { + float x = clamp(bezelRatio, 0.05, 0.95); + float y = surfaceConvexSquircle(x); + float y2 = surfaceConvexSquircle(x + 0.001); + float deriv = (y2 - y) / 0.001; + float mag = sqrt(deriv * deriv + 1.0); + vec2 n = vec2(-deriv / mag, -1.0 / mag); + vec2 r = refractRay(n, eta); + if (length(r) < 0.0001 || abs(r.y) < 0.0001) + return 0.0; + + float remaining = y * bezelWidth + glassThickness; + return r.x * (remaining / r.y); +} + +float displacementAtRatio(float bezelRatio, float glassThickness, float bezelWidth, float eta) { + float peak = rawRefraction(0.05, glassThickness, bezelWidth, eta); + if (abs(peak) < 0.0001) + return 0.0; + + float raw = rawRefraction(bezelRatio, glassThickness, bezelWidth, eta); + float norm = raw / peak; + float profileFalloff = 1.0 - smoothstep(0.0, 1.0, bezelRatio); + return norm * profileFalloff; +} + +float fresnelAtRatio(float bezelRatio, float refractiveIndex) { + float x = clamp(bezelRatio, 0.02, 0.98); + float y0 = surfaceConvexSquircle(max(0.001, x - 0.001)); + float y1 = surfaceConvexSquircle(min(0.999, x + 0.001)); + float slope = (y1 - y0) / 0.002; + float cosTheta = inversesqrt(1.0 + slope * slope); + float f0Base = (refractiveIndex - 1.0) / (refractiveIndex + 1.0); + float f0 = f0Base * f0Base; + float grazing = pow(1.0 - clamp(cosTheta, 0.0, 1.0), 5.0); + float fresnel = f0 + (1.0 - f0) * grazing; + return fresnel * (1.0 - smoothstep(0.0, 1.0, bezelRatio)); +} + +float dispersionOffsetScale(float channelIndex, float strengthValue) { + return 1.0 - (channelIndex - 1.0) * strengthValue; +} + +float luminance(vec3 color) { + return dot(color, vec3(0.2126, 0.7152, 0.0722)); +} + +vec2 clampUV(vec2 uv) { + vec2 px = vec2(1.5 / width, 1.5 / height); + return clamp(uv, px, vec2(1.0) - px); +} + +vec2 resolveUV(vec2 uv) { + if (texture_repeat == 1) { + vec2 mirrored = abs(fract(uv * 0.5) * 2.0 - 1.0); + return clampUV(mirrored); + } + + return clampUV(uv); +} + +vec4 sampleBackdrop(vec2 uv) { + return texture2D(tex, resolveUV(uv)); +} + +vec4 sampleGlassBackdrop(vec2 uv) { + if (blur_radius <= 0.01) + return sampleBackdrop(uv); + + float sigma = max(0.1, blur_radius * 0.5); + float pixelStep = blur_direction == 1 ? 1.0 / width : 1.0 / height; + vec2 direction = vec2(float(blur_direction), 1.0 - float(blur_direction)); + + vec3 gauss; + gauss.x = 1.0 / (sqrt(2.0 * PI) * sigma); + gauss.y = exp(-0.5 / (sigma * sigma)); + gauss.z = gauss.y * gauss.y; + + vec4 accum = sampleBackdrop(uv) * gauss.x; + float weightSum = gauss.x; + + gauss.xy *= gauss.yz; + + int radius = int(ceil(1.5 * sigma)) * 2; + for (int i = 1; i <= radius; i += 2) { + float subtotal = gauss.x; + + gauss.xy *= gauss.yz; + subtotal += gauss.x; + + float gaussRatio = gauss.x / subtotal; + float offset = float(i) + gaussRatio; + vec2 uvOffset = direction * offset * pixelStep; + + accum += sampleBackdrop(uv + uvOffset) * subtotal; + accum += sampleBackdrop(uv - uvOffset) * subtotal; + weightSum += subtotal * 2.0; + + gauss.xy *= gauss.yz; + } + + return accum / weightSum; +} + +vec4 tintFallbackSample() { + return vec4(vec3(tint_r, tint_g, tint_b), 1.0); +} + +vec4 sampleOrTintFallback(vec2 uv) { + vec4 sample = sampleGlassBackdrop(uv); + return sample.a < 0.01 ? tintFallbackSample() : sample; +} + +float roundedBoxDistance(vec2 p, vec2 halfSize, float radius) { + radius = min(radius, min(halfSize.x, halfSize.y)); + vec2 q = abs(p) - halfSize + vec2(radius); + return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius; +} + +float squircleCornerDistance(vec2 p, vec2 halfSize, float radius) { + const float continuousCornerExtent = 1.528; + + vec2 extent = min(vec2(radius * continuousCornerExtent), halfSize); + vec2 core = max(halfSize - extent, vec2(0.0)); + vec2 q = abs(p) - core; + vec2 corner = max(q, vec2(0.0)); + vec2 normalized = corner / max(extent, vec2(0.001)); + float superLength = pow(pow(normalized.x, 4.0) + pow(normalized.y, 4.0), 0.25); + + if (q.x <= 0.0 && q.y <= 0.0) + return -min(halfSize.x - abs(p.x), halfSize.y - abs(p.y)); + + return (superLength - 1.0) * min(extent.x, extent.y); +} + +struct EdgeInfo { + float distance; + float alpha; + vec2 dir; +}; + +EdgeInfo estimateAnalyticEdge(vec2 px, vec2 halfSize, float radius, float shortest) { + vec2 p = px - halfSize; + float signedDistance; + vec2 core; + + if (radius >= shortest * 0.49 || radius < 0.5) { + core = max(halfSize - vec2(radius), vec2(0.0)); + signedDistance = roundedBoxDistance(p, halfSize, radius); + } else { + const float continuousCornerExtent = 1.528; + vec2 extent = min(vec2(radius * continuousCornerExtent), halfSize); + core = max(halfSize - extent, vec2(0.0)); + signedDistance = squircleCornerDistance(p, halfSize, radius); + } + + EdgeInfo info; + info.distance = max(0.0, -signedDistance); + info.alpha = clamp(1.0 - max(0.0, signedDistance), 0.0, 1.0); + + vec2 cornerDelta = max(abs(p) - core, vec2(0.0)); + vec2 normalDelta; + + if (radius < shortest * 0.49 && radius >= 0.5 && + cornerDelta.x > 0.0 && cornerDelta.y > 0.0) { + normalDelta = sign(p) * pow(cornerDelta, vec2(3.0)); + } else { + vec2 nearestCore = clamp(p, -core, core); + normalDelta = p - nearestCore; + } + + float normalLength = length(normalDelta); + + if (normalLength > 0.001) { + info.dir = normalDelta / normalLength; + } else { + vec2 lensPx = px; + float dL = lensPx.x; + float dR = halfSize.x * 2.0 - lensPx.x; + float dT = lensPx.y; + float dB = halfSize.y * 2.0 - lensPx.y; + float dm = min(min(dL, dR), min(dT, dB)); + + info.dir = vec2( + (dL < dR && dL == dm) ? -1.0 : (dR <= dL && dR == dm) ? 1.0 : 0.0, + (dT < dB && dT == dm) ? -1.0 : (dB <= dT && dB == dm) ? 1.0 : 0.0 + ); + } + + return info; +} + +vec2 backdropSampleUV(vec2 sampleUV, vec2 displacementPx) { + vec2 displaced = sampleUV + displacementPx / vec2(width, height); + float zoom = max(backdrop_zoom, 0.01); + + displaced = vec2(0.5) + (displaced - vec2(0.5)) / zoom; + return displaced; +} + +vec4 sampleDispersed(vec2 sampleUV, vec2 dispPx, float dispersion) { + float greenScale = dispersionOffsetScale(kDispersionGreenIndex, dispersion); + vec2 greenUV = resolveUV(backdropSampleUV(sampleUV, dispPx * greenScale)); + vec4 greenSample = sampleGlassBackdrop(greenUV); + + vec4 fallback = vec4(0.0); + bool loadedFallback = false; + if (greenSample.a < 0.01) { + vec2 fallbackUV = resolveUV(backdropSampleUV(sampleUV, vec2(0.0))); + + fallback = sampleOrTintFallback(fallbackUV); + loadedFallback = true; + greenSample = fallback; + } + + if (greenSample.a < 0.01) + return tintFallbackSample(); + + vec4 bg = greenSample; + if (dispersion > 0.001 && dot(dispPx, dispPx) > 0.0001) { + float redScale = dispersionOffsetScale(kDispersionRedIndex, dispersion); + float blueScale = dispersionOffsetScale(kDispersionBlueIndex, dispersion); + + vec2 redUV = resolveUV(backdropSampleUV(sampleUV, dispPx * redScale)); + vec2 blueUV = resolveUV(backdropSampleUV(sampleUV, dispPx * blueScale)); + vec4 redSample = sampleGlassBackdrop(redUV); + vec4 blueSample = sampleGlassBackdrop(blueUV); + + if (redSample.a < 0.01 || blueSample.a < 0.01) { + if (!loadedFallback) { + vec2 fallbackUV = resolveUV(backdropSampleUV(sampleUV, vec2(0.0))); + fallback = sampleOrTintFallback(fallbackUV); + } + + if (redSample.a < 0.01) + redSample = fallback.a < 0.01 ? tintFallbackSample() : fallback; + + if (blueSample.a < 0.01) + blueSample = fallback.a < 0.01 ? tintFallbackSample() : fallback; + } + + bg.r = redSample.r; + bg.g = greenSample.g; + bg.b = blueSample.b; + bg.a = greenSample.a; + } + return bg; +} + +vec4 applyTintAndShadow(vec4 sample, vec2 localUV, float alpha) { + vec3 tintColor = vec3(tint_r, tint_g, tint_b); + vec3 outRGB = mix(sample.rgb, tintColor, tint * tint_a); + + outRGB *= 1.0 - smoothstep(0.25, 1.0, localUV.y) * shadow * 0.20; + + return vec4(clamp(outRGB, 0.0, 1.0) * alpha, alpha); +} + +void main() { + vec2 actorSize = vec2(width, height); + vec2 actorUV = cogl_tex_coord_in[0].xy; + + if (private_pass == 1) { + cogl_color_out = sampleGlassBackdrop(actorUV); + return; + } + + vec2 actorPx = actorUV * actorSize; + vec4 bounds = clip_width < 0.0 || clip_height < 0.0 + ? vec4(0.0, 0.0, width, height) + : vec4(clip_x0, clip_y0, clip_x0 + clip_width, clip_y0 + clip_height); + + vec2 glassSize = max(bounds.zw - bounds.xy, vec2(1.0)); + vec2 glassPx = actorPx - bounds.xy; + vec2 halfSize = glassSize * 0.5; + vec2 localUV = glassPx / glassSize; + + float W = glassSize.x; + float H = glassSize.y; + float shortestSide = min(W, H); + float R = clamp(corner_radius, 0.0, shortestSide * 0.5); + float bezel = max(1.0, min(edge_size, shortestSide * 0.5)); + float glassThickness = max(0.5, edge_size * 0.55 * falloff); + float eta = 1.0 / REFRACTIVE_INDEX; + + bool nearlySquare = abs(W - H) < max(4.0, shortestSide * 0.035); + bool useCircularSurface = nearlySquare && R >= shortestSide * 0.34; + + EdgeInfo edge = estimateAnalyticEdge(glassPx, halfSize, R, shortestSide); + if (edge.alpha <= 0.0) { + cogl_color_out = vec4(0.0); + return; + } + + float distFromSide = edge.distance; + float edgeOpacity = edge.alpha; + float edgeBand = 1.0; + float refractionBand = bezel; + vec2 dir = edge.dir; + + if (useCircularSurface) { + float circleRadius = shortestSide * 0.5; + vec2 circleCenter = glassSize * 0.5; + vec2 fromCenter = glassPx - circleCenter; + float circleDistance = length(fromCenter); + + if (circleDistance > circleRadius + 1.0) { + cogl_color_out = vec4(0.0); + return; + } + + distFromSide = max(0.0, circleRadius - circleDistance); + dir = circleDistance > 0.001 ? normalize(fromCenter) : vec2(0.0, -1.0); + edgeOpacity = clamp(1.0 - max(0.0, circleDistance - circleRadius), 0.0, 1.0); + + float rimRadius = max(1.0, bezel * 0.35); + refractionBand = rimRadius; + edgeBand = clamp(1.0 - (distFromSide / rimRadius), 0.0, 1.0); + } else { + float rimRadius = max(1.0, bezel * 0.35 * max(1.0, rim_width)); + refractionBand = rimRadius; + edgeBand = clamp(1.0 - (distFromSide / rimRadius), 0.0, 1.0); + } + + if (!useCircularSurface && R < shortestSide * 0.45 && distFromSide >= refractionBand) { + vec2 flatUV = backdropSampleUV(actorUV, vec2(0.0)); + vec4 flatSample = sampleOrTintFallback(resolveUV(flatUV)); + float finalOpacity = edgeOpacity * opacity_factor; + + cogl_color_out = applyTintAndShadow(flatSample, localUV, finalOpacity); + return; + } + + float bezelRatio = clamp(distFromSide / refractionBand, 0.0, 1.0); + float normDisp = distFromSide < refractionBand + ? displacementAtRatio(bezelRatio, glassThickness, refractionBand, eta) + : 0.0; + float dispStrength = useCircularSurface ? edgeOpacity : edgeBand; + vec2 dispPx = -dir * normDisp * refractionBand * strength * dispStrength; + + float dispersion = clamp(rgb_fringing * DISPERSION_SCALE, 0.0, 20.0); + vec4 bgColor = sampleDispersed(actorUV, dispPx, dispersion); + if (bgColor.a < 0.01) { + cogl_color_out = vec4(0.0); + return; + } + + vec3 outRGB = mix(bgColor.rgb, vec3(tint_r, tint_g, tint_b), tint * tint_a); + float fresnel = fresnelAtRatio(bezelRatio, REFRACTIVE_INDEX) * edgeOpacity; + float bgLuminance = luminance(outRGB); + float glare = clamp(fresnel * 0.70 * mix(0.40, 1.0, bgLuminance), 0.0, 0.18) + * clamp(gloss, 0.0, 1.0); + outRGB = 1.0 - (1.0 - outRGB) * (1.0 - glare); + outRGB *= 1.0 - smoothstep(0.25, 1.0, localUV.y) * shadow * 0.20; + + float finalOpacity = edgeOpacity * opacity_factor; + cogl_color_out = vec4(clamp(outRGB, 0.0, 1.0) * finalOpacity, finalOpacity); +} diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.js new file mode 100644 index 0000000..27fdcc0 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.js @@ -0,0 +1,849 @@ +import GObject from 'gi://GObject'; +import GLib from 'gi://GLib'; + +import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 = 'refraction.glsl'; +const SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); +const CLIP_STABILIZE_EPSILON = 1.0; +const MAX_BLUR_RADIUS = 48.0; + +const DEFAULT_PARAMS = { + strength: 0.42, + blur_radius: 10, + edge_size: 22, + falloff: 2.4, + corner_radius: 22, + rim_width: 4.8, + rgb_fringing: 0.08, + gloss: 0.55, + webcam_gloss: false, + webcam_device: '', + tint: 0.18, + tint_color: [1.0, 1.0, 1.0, 1.0], + backdrop_zoom: 1.0, + shadow: 0.28, + texture_repeat: 0, + blur_direction: 0, + private_pass: 0, + chained_effect: null, + width: 0, + height: 0, + opacity_factor: 1.0, + clip: [0, 0, -1, -1] +}; + +const REFRACTION_EFFECT_META = { + GTypeName: "RefractionEffect", + Properties: { + 'strength': GObject.ParamSpec.double( + `strength`, + `Strength`, + `Refraction strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.42, + ), + 'edge_size': GObject.ParamSpec.double( + `edge_size`, + `Edge Size`, + `Refraction edge size`, + GObject.ParamFlags.READWRITE, + 1.0, 200.0, + 22.0, + ), + 'blur_radius': GObject.ParamSpec.double( + `blur_radius`, + `Blur Radius`, + `Internal glass blur radius`, + GObject.ParamFlags.READWRITE, + 0.0, MAX_BLUR_RADIUS, + 10.0, + ), + 'falloff': GObject.ParamSpec.double( + `falloff`, + `Falloff`, + `Refraction falloff`, + GObject.ParamFlags.READWRITE, + 0.25, 8.0, + 2.4, + ), + 'corner_radius': GObject.ParamSpec.double( + `corner_radius`, + `Corner Radius`, + `Refraction corner radius`, + GObject.ParamFlags.READWRITE, + 0.0, 200.0, + 22.0, + ), + 'rim_width': GObject.ParamSpec.double( + `rim_width`, + `Rim Width`, + `Refraction rim width`, + GObject.ParamFlags.READWRITE, + 1.0, 6.5, + 4.8, + ), + 'rgb_fringing': GObject.ParamSpec.double( + `rgb_fringing`, + `RGB Fringing`, + `Chromatic offset strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.08, + ), + 'gloss': GObject.ParamSpec.double( + `gloss`, + `Gloss`, + `Specular highlight strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.55, + ), + 'webcam_gloss': GObject.ParamSpec.boolean( + `webcam_gloss`, + `Deprecated Webcam Gloss`, + `Deprecated compatibility property`, + GObject.ParamFlags.READWRITE, + false, + ), + 'webcam_device': GObject.ParamSpec.string( + `webcam_device`, + `Deprecated Webcam Device`, + `Deprecated compatibility property`, + GObject.ParamFlags.READWRITE, + '', + ), + 'tint': GObject.ParamSpec.double( + `tint`, + `Tint`, + `Glass tint strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.18, + ), + 'tint_red': GObject.ParamSpec.double( + `tint_red`, + `Tint Red`, + `Glass tint color red`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + 'tint_green': GObject.ParamSpec.double( + `tint_green`, + `Tint Green`, + `Glass tint color green`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + 'tint_blue': GObject.ParamSpec.double( + `tint_blue`, + `Tint Blue`, + `Glass tint color blue`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + 'tint_alpha': GObject.ParamSpec.double( + `tint_alpha`, + `Tint Alpha`, + `Glass tint color alpha`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + 'backdrop_zoom': GObject.ParamSpec.double( + `backdrop_zoom`, + `Backdrop Zoom`, + `Zoom level of the refracted backdrop`, + GObject.ParamFlags.READWRITE, + 0.1, 4.0, + 1.0, + ), + 'shadow': GObject.ParamSpec.double( + `shadow`, + `Shadow`, + `Inner shadow strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.28, + ), + 'texture_repeat': GObject.ParamSpec.int( + `texture_repeat`, + `Texture Repeat`, + `Texture repeat behavior`, + GObject.ParamFlags.READWRITE, + 0, 1, + 0, + ), + 'blur_direction': GObject.ParamSpec.int( + `blur_direction`, + `Blur Direction`, + `Private Gaussian blur direction`, + GObject.ParamFlags.READWRITE, + 0, 1, + 0, + ), + 'private_pass': GObject.ParamSpec.int( + `private_pass`, + `Private Pass`, + `Private Gaussian blur pass`, + GObject.ParamFlags.READWRITE, + 0, 1, + 0, + ), + 'chained_effect': GObject.ParamSpec.object( + `chained_effect`, + `Chained Effect`, + `Private chained blur effect`, + GObject.ParamFlags.READWRITE, + GObject.Object, + ), + '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, + ), + // See corner.js: this is backed by an array setter, but represented + // as a dummy property so pipeline parameter assignment can reach it. + 'clip': GObject.ParamSpec.double( + `clip`, + `Clip`, + `Clip`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + } +}; + +const RefractionEffectClass = utils.IS_IN_PREFERENCES ? null : class RefractionEffect extends Clutter.ShaderEffect { + + constructor(params) { + const { + webcam_gloss: _webcam_gloss, + webcam_device: _webcam_device, + tint_color: _tint_color, + ...parent_params + } = params; + super({ ...parent_params }); + utils.initialize_shader_effect(this, SHADER_SOURCE); + + this._clip_x0 = null; + this._clip_y0 = null; + this._clip_width = null; + this._clip_height = null; + this._stable_clip_x0 = null; + this._stable_clip_y0 = null; + this._stable_clip_width = null; + this._stable_clip_height = null; + this._stabilize_clip_x = false; + this._stabilize_clip_y = false; + this._clip_settle_timeout_id = null; + + utils.setup_params(this, params); + + this._theme_context = St.ThemeContext.get_for_stage(global.stage); + this._theme_context.connectObject( + 'notify::scale-factor', + _ => this.update_scaled_uniforms(), + this + ); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get strength() { + return this._strength; + } + + set strength(value) { + if (this._strength !== value) { + this._strength = value; + + this.set_uniform_value('strength', parseFloat(this._strength - 1e-6)); + this.set_enabled(this.strength > 0.); + } + } + + get edge_size() { + return this._edge_size; + } + + set edge_size(value) { + if (this._edge_size !== value) { + this._edge_size = value; + + this.update_scaled_uniforms(); + + if (this.chained_effect) + this.chained_effect.edge_size = value; + } + } + + get blur_radius() { + return this._blur_radius; + } + + set blur_radius(value) { + if (this._blur_radius !== value) { + this._blur_radius = Math.min(value, MAX_BLUR_RADIUS); + + this.update_scaled_uniforms(); + + if (this.chained_effect) + this.chained_effect.blur_radius = this._blur_radius; + } + } + + get falloff() { + return this._falloff; + } + + set falloff(value) { + if (this._falloff !== value) { + this._falloff = value; + + this.set_uniform_value('falloff', parseFloat(this._falloff - 1e-6)); + + if (this.chained_effect) + this.chained_effect.falloff = value; + } + } + + get corner_radius() { + return this._corner_radius; + } + + set corner_radius(value) { + if (this._corner_radius !== value) { + this._corner_radius = value; + + this.update_scaled_uniforms(); + + if (this.chained_effect) + this.chained_effect.corner_radius = value; + } + } + + get rim_width() { + return this._rim_width; + } + + set rim_width(value) { + const rim_width = Math.max(1.0, Math.min(value, 6.5)); + if (this._rim_width !== rim_width) { + this._rim_width = rim_width; + + this.set_uniform_value('rim_width', parseFloat(this._rim_width - 1e-6)); + + if (this.chained_effect) + this.chained_effect.rim_width = rim_width; + } + } + + get rgb_fringing() { + return this._rgb_fringing; + } + + set rgb_fringing(value) { + if (this._rgb_fringing !== value) { + this._rgb_fringing = value; + + this.set_uniform_value('rgb_fringing', parseFloat(this._rgb_fringing - 1e-6)); + } + } + + get gloss() { + return this._gloss; + } + + set gloss(value) { + if (this._gloss !== value) { + this._gloss = value; + + this.set_uniform_value('gloss', parseFloat(this._gloss - 1e-6)); + } + } + + // Deprecated no-op compatibility properties for old saved pipelines. + get webcam_gloss() { + return this._webcam_gloss; + } + + set webcam_gloss(value) { + this._webcam_gloss = value; + } + + get webcam_device() { + return this._webcam_device; + } + + set webcam_device(value) { + this._webcam_device = value ?? ''; + } + + get tint() { + return this._tint; + } + + set tint(value) { + if (this._tint !== value) { + this._tint = value; + + this.set_uniform_value('tint', parseFloat(this._tint - 1e-6)); + } + } + + get tint_red() { + return this._tint_red; + } + + set tint_red(value) { + if (this._tint_red !== value) { + this._tint_red = value; + + this.set_uniform_value('tint_r', parseFloat(this._tint_red - 1e-6)); + } + } + + get tint_green() { + return this._tint_green; + } + + set tint_green(value) { + if (this._tint_green !== value) { + this._tint_green = value; + + this.set_uniform_value('tint_g', parseFloat(this._tint_green - 1e-6)); + } + } + + get tint_blue() { + return this._tint_blue; + } + + set tint_blue(value) { + if (this._tint_blue !== value) { + this._tint_blue = value; + + this.set_uniform_value('tint_b', parseFloat(this._tint_blue - 1e-6)); + } + } + + get tint_alpha() { + return this._tint_alpha; + } + + set tint_alpha(value) { + if (this._tint_alpha !== value) { + this._tint_alpha = value; + + this.set_uniform_value('tint_a', parseFloat(this._tint_alpha - 1e-6)); + } + } + + get tint_color() { + return [this.tint_red, this.tint_green, this.tint_blue, this.tint_alpha]; + } + + set tint_color(rgba) { + const [r, g, b, a] = rgba; + this.tint_red = r; + this.tint_green = g; + this.tint_blue = b; + this.tint_alpha = a ?? 1.0; + } + + get backdrop_zoom() { + return this._backdrop_zoom; + } + + set backdrop_zoom(value) { + if (this._backdrop_zoom !== value) { + this._backdrop_zoom = value; + + this.set_uniform_value('backdrop_zoom', parseFloat(this._backdrop_zoom - 1e-6)); + } + } + + get shadow() { + return this._shadow; + } + + set shadow(value) { + if (this._shadow !== value) { + this._shadow = value; + + this.set_uniform_value('shadow', parseFloat(this._shadow - 1e-6)); + } + } + + get texture_repeat() { + return this._texture_repeat; + } + + set texture_repeat(value) { + if (this._texture_repeat !== value) { + this._texture_repeat = value; + + this.set_uniform_value('texture_repeat', this._texture_repeat); + + if (this.chained_effect) + this.chained_effect.texture_repeat = value; + } + } + + get blur_direction() { + return this._blur_direction; + } + + set blur_direction(value) { + if (this._blur_direction !== value) { + this._blur_direction = value; + + this.set_uniform_value('blur_direction', this._blur_direction); + } + } + + get private_pass() { + return this._private_pass; + } + + set private_pass(value) { + if (this._private_pass !== value) { + this._private_pass = value; + + this.set_uniform_value('private_pass', this._private_pass); + if (this._private_pass === 1) + this.set_enabled(this.blur_radius > 0.01); + } + } + + get chained_effect() { + return this._chained_effect; + } + + set chained_effect(value) { + this._chained_effect = value; + } + + set(params) { + utils.setup_params(this, params); + } + + 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_scaled_uniforms(); + + 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)); + this.update_scaled_uniforms(); + + if (this.chained_effect) + this.chained_effect.height = value; + } + } + + get clip() { + return [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height]; + } + + set clip(value) { + const previous_clip = this.clip; + [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height] = value; + + let shader_clip = this._stabilized_clip(previous_clip); + + this.set_uniform_value('clip_x0', parseFloat(shader_clip[0] - 1e-6)); + this.set_uniform_value('clip_y0', parseFloat(shader_clip[1] - 1e-6)); + this.set_uniform_value('clip_width', parseFloat(shader_clip[2] + 3.0 - 1e-6)); + this.set_uniform_value('clip_height', parseFloat(shader_clip[3] + 3.0 - 1e-6)); + this.update_scaled_uniforms(); + } + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; + + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); + + if (this.chained_effect) + this.chained_effect.opacity_factor = value; + } + } + + _stabilized_clip(previous_clip) { + if (this._clip_width < 0 || this._clip_height < 0) { + this._stable_clip_x0 = null; + this._stable_clip_y0 = null; + this._stable_clip_width = null; + this._stable_clip_height = null; + this._stabilize_clip_x = false; + this._stabilize_clip_y = false; + if (this._clip_settle_timeout_id) { + GLib.Source.remove(this._clip_settle_timeout_id); + this._clip_settle_timeout_id = null; + } + return [ + this._clip_x0, + this._clip_y0, + this._clip_width, + this._clip_height + ]; + } + + const [previous_x0, previous_y0, previous_width, previous_height] = previous_clip; + + [this._stable_clip_x0, this._stable_clip_width, this._stabilize_clip_x] = + this._stabilized_clip_axis( + this._clip_x0, + this._clip_width, + previous_x0, + previous_width, + this._stable_clip_x0, + this._stable_clip_width, + this._stabilize_clip_x + ); + [this._stable_clip_y0, this._stable_clip_height, this._stabilize_clip_y] = + this._stabilized_clip_axis( + this._clip_y0, + this._clip_height, + previous_y0, + previous_height, + this._stable_clip_y0, + this._stable_clip_height, + this._stabilize_clip_y + ); + + if (this._clip_settle_timeout_id) + GLib.Source.remove(this._clip_settle_timeout_id); + + if (!this._stabilize_clip_x && !this._stabilize_clip_y) { + this._clip_settle_timeout_id = null; + return [ + this._stable_clip_x0, + this._stable_clip_y0, + this._stable_clip_width, + this._stable_clip_height + ]; + } + + this._clip_settle_timeout_id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 220, () => { + this._stable_clip_x0 = this._clip_x0; + this._stable_clip_y0 = this._clip_y0; + this._stable_clip_width = this._clip_width; + this._stable_clip_height = this._clip_height; + this._stabilize_clip_x = false; + this._stabilize_clip_y = false; + this._clip_settle_timeout_id = null; + this.clip = [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height]; + this.queue_repaint(); + return GLib.SOURCE_REMOVE; + }); + + return [ + this._stable_clip_x0, + this._stable_clip_y0, + this._stable_clip_width, + this._stable_clip_height + ]; + } + + _stabilized_clip_axis( + start, + size, + previous_start, + previous_size, + stable_start, + stable_size, + stabilizing + ) { + const size_changed = + previous_size !== null && + previous_size >= 0 && + Math.abs(size - previous_size) > CLIP_STABILIZE_EPSILON; + + if (!stabilizing && !size_changed) + return [start, size, false]; + + const end = start + size; + const resolved_stable_start = stable_start ?? previous_start ?? start; + const resolved_stable_size = stable_size ?? previous_size ?? size; + const stable_end = resolved_stable_start + resolved_stable_size; + const resolved_start = Math.min(resolved_stable_start, start); + const resolved_end = Math.max(stable_end, end); + + return [resolved_start, resolved_end - resolved_start, true]; + } + + update_scaled_uniforms() { + const scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; + const rect_width = + this._stable_clip_width ?? (this._clip_width >= 0 ? this._clip_width : this.width); + const rect_height = + this._stable_clip_height ?? (this._clip_height >= 0 ? this._clip_height : this.height); + const max_edge = Math.max(1, Math.min(rect_width, rect_height) / 2); + const edge_size = Math.min(this.edge_size * scale_factor, max_edge); + const corner_radius = Math.min(this.corner_radius * scale_factor, max_edge); + + this.set_uniform_value('edge_size', parseFloat(edge_size - 1e-6)); + this.set_uniform_value('corner_radius', parseFloat(corner_radius - 1e-6)); + const blur_radius = Math.min(this.blur_radius, MAX_BLUR_RADIUS) * scale_factor; + this.set_uniform_value('blur_radius', parseFloat(blur_radius - 1e-6)); + if (this.private_pass === 1) + this.set_enabled(blur_radius > 0.01); + } + + vfunc_set_actor(actor) { + if (this.chained_effect) + this.chained_effect.get_actor()?.remove_effect(this.chained_effect); + + 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 (this._clip_settle_timeout_id) { + GLib.Source.remove(this._clip_settle_timeout_id); + this._clip_settle_timeout_id = null; + } + 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; + this._stable_clip_x0 = null; + this._stable_clip_y0 = null; + this._stable_clip_width = null; + this._stable_clip_height = null; + this._stabilize_clip_x = false; + this._stabilize_clip_y = false; + } + + super.vfunc_set_actor(actor); + + if (this.private_pass === 0) { + if (!this.chained_effect) { + const chained_params = { + strength: this.strength, + blur_radius: this.blur_radius, + edge_size: this.edge_size, + falloff: this.falloff, + corner_radius: this.corner_radius, + rim_width: this.rim_width, + rgb_fringing: this.rgb_fringing, + gloss: this.gloss, + tint: this.tint, + shadow: this.shadow, + texture_repeat: this.texture_repeat, + width: this.width, + height: this.height, + clip: this.clip, + blur_direction: 1, + private_pass: 1, + opacity_factor: this._opacity_factor + }; + + this.chained_effect = new RefractionEffect(chained_params); + } + + if (actor !== null) + actor.add_effect(this.chained_effect); + } + } + + vfunc_paint_target(paint_node, paint_context) { + uniforms.upload_uniforms(this); + this.set_uniform_value('blur_direction', this.blur_direction); + this.set_uniform_value('private_pass', this.private_pass); + + super.vfunc_paint_target(paint_node, paint_context); + } + + vfunc_dispose() { + if (this._clip_settle_timeout_id) { + GLib.Source.remove(this._clip_settle_timeout_id); + this._clip_settle_timeout_id = null; + } + + if (this.chained_effect) { + this.chained_effect.get_actor()?.remove_effect(this.chained_effect); + this.chained_effect = null; + } + + this._theme_context?.disconnectObject(this); + this._theme_context = null; + + if (super.vfunc_dispose) + super.vfunc_dispose(); + } +}; + +export const RefractionEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(REFRACTION_EFFECT_META, RefractionEffectClass, SHADER_SOURCE); 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 index b7a35ac..ba09fe0 100644 --- 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 @@ -1,4 +1,5 @@ uniform sampler2D tex; +uniform float opacity_factor; vec3 rgb_to_hsl(vec3 c) { vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); @@ -14,5 +15,5 @@ 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 + cogl_color_out = mix(rgba, hsla, opacity_factor); +} 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 index 5c4eb05..81b3596 100644 --- 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 @@ -1,31 +1,64 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 = {}; +const SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); +const DEFAULT_PARAMS = { + opacity_factor: 1 +}; -export const RgbToHslEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const RGB_TO_HSL_EFFECT_META = { GTypeName: "RgbToHslEffect", - Properties: {} - }, class RgbToHslEffect extends Clutter.ShaderEffect { + Properties: { + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + } +}; + +const RgbToHslEffectClass = utils.IS_IN_PREFERENCES ? null : class RgbToHslEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); - utils.setup_params(this, params); + utils.initialize_shader_effect(this, SHADER_SOURCE); - // set shader source - this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); - if (this._source) - this.set_shader_source(this._source); + + utils.setup_params(this, params); } static get default_params() { return DEFAULT_PARAMS; } - }); \ No newline at end of file + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; + + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); + } + } + + vfunc_paint_target(paint_node, paint_context) { + uniforms.upload_uniforms(this); + super.vfunc_paint_target(paint_node, paint_context); + } +}; + +export const RgbToHslEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(RGB_TO_HSL_EFFECT_META, RgbToHslEffectClass, SHADER_SOURCE); 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 index 5cc06ec..3d743df 100644 --- 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 @@ -2,13 +2,14 @@ uniform sampler2D tex; uniform int factor; uniform float width; uniform float height; +uniform float opacity_factor; #define CORRECTION 2.25 -#define SIZE_ADDITION 3 +#define SIZE_ADDITION 3.0 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); + vec2 raw_uv = raw_position / vec2(max(1.0, width + SIZE_ADDITION), max(1.0, height + SIZE_ADDITION)); return texture2D(tex, raw_uv); } @@ -20,38 +21,41 @@ ivec2 get_corrected_position() { } void main() { + vec4 source_color = texture2D(tex, cogl_tex_coord0_in.st); ivec2 corrected_position = get_corrected_position(); + int safe_factor = max(1, factor); - vec2 adjusted_position = corrected_position / factor; + vec2 adjusted_position = vec2(corrected_position / safe_factor); - cogl_color_out = get_texture_at_position(adjusted_position); + vec4 effect_color = get_texture_at_position(adjusted_position); + cogl_color_out = mix(source_color, effect_color, opacity_factor); // round - if (distance(corrected_position, (floor(adjusted_position) + 0.5) * factor) < factor / 2.5) { + if (distance(vec2(corrected_position), (floor(adjusted_position) + 0.5) * float(safe_factor)) < float(safe_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) { + if (mod(float(corrected_position.x), float(safe_factor)) >= 2.0 && mod(float(corrected_position.y), float(safe_factor)) >= 2.0) { //cogl_color_out = get_texture_at_position(adjusted_position); } else { //cogl_color_out = vec4(0, 0, 0, 1); } // local mix - vec4 color = vec4(0); + vec4 color = vec4(0.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))) { + vec2 lookup_position = adjusted_position + vec2(float(i), float(j)); + if (all(greaterThanEqual(lookup_position, vec2(0.0, 0.0))) && + all(lessThan(lookup_position, vec2(width, height) / float(safe_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 index fb719c3..d29ba8c 100644 --- 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 @@ -1,18 +1,18 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.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 SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); const DEFAULT_PARAMS = { - factor: 8, width: 0, height: 0 + factor: 8, opacity_factor: 1, width: 0, height: 0 }; -export const UpscaleEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ +const UPSCALE_EFFECT_META = { GTypeName: "UpscaleEffect", Properties: { 'factor': GObject.ParamSpec.int( @@ -23,6 +23,14 @@ export const UpscaleEffect = utils.IS_IN_PREFERENCES ? 0, 64, 8, ), + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), 'width': GObject.ParamSpec.double( `width`, `Width`, @@ -40,16 +48,17 @@ export const UpscaleEffect = utils.IS_IN_PREFERENCES ? 0.0, ) } - }, class UpscaleEffect extends Clutter.ShaderEffect { +}; + +const UpscaleEffectClass = utils.IS_IN_PREFERENCES ? null : class UpscaleEffect extends Clutter.ShaderEffect { + constructor(params) { - super(params); + super(); + + utils.initialize_shader_effect(this, SHADER_SOURCE); - 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); + utils.setup_params(this, params); } static get default_params() { @@ -61,10 +70,23 @@ export const UpscaleEffect = utils.IS_IN_PREFERENCES ? } set factor(value) { - if (this._factor !== value) { - this._factor = value; + const v = Math.max(1, value || 1); + if (this._factor !== v) { + this._factor = v; + + uniforms.set_uniform(this, 'factor', this._factor); + } + } + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; - this.set_uniform_value('factor', this._factor); + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); } } @@ -73,10 +95,11 @@ export const UpscaleEffect = utils.IS_IN_PREFERENCES ? } set width(value) { - if (this._width !== value) { - this._width = value; + const v = Math.max(1, value || 1); + if (this._width !== v) { + this._width = v; - this.set_uniform_value('width', parseFloat(this._width - 1e-6)); + uniforms.set_uniform(this, 'width', parseFloat(this._width - 1e-6)); } } @@ -85,10 +108,11 @@ export const UpscaleEffect = utils.IS_IN_PREFERENCES ? } set height(value) { - if (this._height !== value) { - this._height = value; + const v = Math.max(1, value || 1); + if (this._height !== v) { + this._height = v; - this.set_uniform_value('height', parseFloat(this._height - 1e-6)); + uniforms.set_uniform(this, 'height', parseFloat(this._height - 1e-6)); } } @@ -112,9 +136,17 @@ export const UpscaleEffect = utils.IS_IN_PREFERENCES ? } vfunc_paint_target(paint_node, paint_context) { - // force setting nearest-neighbour texture filtering - this.get_pipeline().set_layer_filters(0, 9728, 9728); + uniforms.upload_uniforms(this); + + const pipeline = this.get_pipeline(); + if (pipeline) { + pipeline.set_layer_filters(0, 9728, 9728); + } super.vfunc_paint_target(paint_node, paint_context); } - }); \ No newline at end of file +}; + +export const UpscaleEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(UPSCALE_EFFECT_META, UpscaleEffectClass, SHADER_SOURCE); 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 index b94ac65..2d7309a 100644 --- 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 @@ -6,7 +6,6 @@ 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 { import_in_shell_only} from './conveniences/utils.js'; import { PipelinesManager } from './conveniences/pipelines_manager.js'; import { EffectsManager } from './conveniences/effects_manager.js'; import { Connections } from './conveniences/connections.js'; @@ -22,8 +21,8 @@ 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'; - -const BlurModule = await import_in_shell_only('gi://Blur'); +import { PopupBlur } from './components/popup.js'; +import { NativeDynamicBlurEffect } from './effects/native_dynamic_gaussian_blur.js'; /// The main extension class, created when the GNOME Shell is loaded. @@ -75,6 +74,7 @@ export default class BlurMyShell extends Extension { this._coverflow_alt_tab_blur = new CoverflowAltTabBlur(...init()); this._applications_blur = new ApplicationsBlur(...init()); this._screenshot_blur = new ScreenshotBlur(...init()); + this._popup = new PopupBlur(...init()); // connect each component to preferences change this._connect_to_settings(); @@ -83,7 +83,7 @@ export default class BlurMyShell extends Extension { if (this._settings.lockscreen.BLUR && !this._lockscreen_blur.enabled) this._lockscreen_blur.enable(); - // update whether or not the external rounded corners library was found + // update whether or not the active blur effect supports rounded corners this._update_rounded_blur_found(); // ensure we take the correct action for the current session mode @@ -117,28 +117,14 @@ export default class BlurMyShell extends Extension { // 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); - } + if (this._settings.overview.BLUR && !this._overview_blur.enabled) + this._overview_blur.enable(); + + if (this._settings.dash_to_dock.BLUR && !this._dash_to_dock_blur.enabled) + this._dash_to_dock_blur.enable(); + + if (this._settings.panel.BLUR && !this._panel_blur.enabled) + this._panel_blur.enable(); // 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 @@ -166,7 +152,8 @@ export default class BlurMyShell extends Extension { this._disable_user_session(); this._overview_blur.restore_patched_proto(); - // disable lockscreen blur too + // disable components that stay active outside the user session + this._popup.disable(); this._lockscreen_blur.disable(); // untrack them @@ -179,6 +166,12 @@ export default class BlurMyShell extends Extension { this._coverflow_alt_tab_blur = null; this._applications_blur = null; this._screenshot_blur = null; + this._popup = null; + + this._effects_manager.destroy_all(); + this._pipelines_manager.destroy(); + this._effects_manager = null; + this._pipelines_manager = null; // make sure no settings change can re-enable them this._settings.disconnect_all_settings(); @@ -204,7 +197,7 @@ export default class BlurMyShell extends Extension { _disable_user_session() { this._log("disabling user session mode..."); - // disable every component except lockscreen blur + // disable every component except lockscreen blur and popup blur this._panel_blur.disable(); this._dash_to_dock_blur.disable(); this._overview_blur.disable(); @@ -247,16 +240,14 @@ export default class BlurMyShell extends Extension { } } - /// Verify whether or not the gi://Blur library was found, in order to inform - /// the preferences and instruct the user to install it to have native rounded - /// corners in dynamic blur. + /// Verify whether the active native blur effect supports rounded corners. _update_rounded_blur_found() { - if (BlurModule === null) { + if (!NativeDynamicBlurEffect.supports_corner_radius) { this._settings.ROUNDED_BLUR_FOUND = false; this._log("using original implementation for the native blur effect") } else { this._settings.ROUNDED_BLUR_FOUND = true; - this._log("using external library for the native blur effect") + this._log("using native rounded corners for the blur effect") } } @@ -326,6 +317,9 @@ export default class BlurMyShell extends Extension { if (this._settings.screenshot.BLUR) this._screenshot_blur.enable(); + if (this._settings.popup.BLUR) + this._popup.enable(); + this._log("all components enabled."); } @@ -427,8 +421,10 @@ export default class BlurMyShell extends Extension { // panel override background toggled on/off this._settings.panel.OVERRIDE_BACKGROUND_changed(() => { - if (this._settings.panel.BLUR) + if (this._settings.panel.BLUR) { this._panel_blur.connect_to_windows_and_overview(); + this._panel_blur.reset(); + } }); // panel style changed @@ -439,10 +435,30 @@ export default class BlurMyShell extends Extension { // panel background's dynamic overriding toggled on/off this._settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_changed(() => { - if (this._settings.panel.BLUR) + if (this._settings.panel.BLUR) { this._panel_blur.connect_to_windows_and_overview(); + this._panel_blur.reset(); + } }); + this._settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_MODE_changed(() => { + if (this._settings.panel.BLUR) { + this._panel_blur.connect_to_windows_and_overview(); + this._panel_blur.reset(); + } + }); + + this._settings.panel.GRADIENT_PANEL_changed(() => { + if (this._settings.panel.BLUR) { + this._panel_blur.update_visibility() ; + } + }); + + this._settings.panel.GRADIENT_PANEL_MODE_changed(() => { + if (this._settings.panel.BLUR) { + this._panel_blur.update_visibility(); + } + }); // ---------- DASH TO DOCK ---------- @@ -533,6 +549,12 @@ export default class BlurMyShell extends Extension { this._applications_blur.connect_to_overview(); }); + // application unblur-when-fullscreen changed + this._settings.applications.UNBLUR_WHEN_FULLSCREEN_changed(() => { + if (this._settings.applications.BLUR) + this._applications_blur.update_fullscreen_status(); + }); + // application enable-all changed this._settings.applications.ENABLE_ALL_changed(() => { if (this._settings.applications.BLUR) @@ -630,6 +652,46 @@ export default class BlurMyShell extends Extension { if (this._settings.screenshot.BLUR) this._screenshot_blur.update_pipeline(); }); + + + // ---------- POPUP BLUR ---------- + + // toggled on/off + this._settings.popup.BLUR_changed(() => { + if (this._settings.popup.BLUR) + this._popup.enable(); + else + this._popup.disable(); + }); + + this._settings.popup.STATIC_BLUR_changed(() => { + if (this._settings.popup.BLUR) + this._popup.reset(); + }); + + this._settings.popup.PIPELINE_changed(() => { + if (this._settings.popup.BLUR) + this._popup.update_pipeline(); + }); + + // popup background override toggled on/off + this._settings.popup.OVERRIDE_BACKGROUND_changed(() => { + if (this._settings.popup.BLUR) + this._popup.update_background(); + }); + + // Apply only the popup surface override, leaving shell theme control + // and text styles intact. + this._settings.popup.PRESERVE_SHELL_THEME_changed(() => { + if (this._settings.popup.BLUR) + this._popup.update_background(); + }); + + // popup background style changed + this._settings.popup.STYLE_POPUP_changed(() => { + if (this._settings.popup.BLUR) + this._popup.update_background(); + }); } _log(str) { diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/popup-symbolic.svg b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/popup-symbolic.svg new file mode 100644 index 0000000..70af5e5 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/icons/hicolor/scalable/actions/popup-symbolic.svg @@ -0,0 +1,3 @@ + + + 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 index 91de0ee..42172a1 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 24e8c8e..d4bfa8d 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 2146336..9c61f31 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/eo/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/eo/LC_MESSAGES/blur-my-shell@aunetx.mo index 76f5653..12a8b8d 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/eo/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/eo/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 4d2e14b..41871cb 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 170aa00..dd32109 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ga/LC_MESSAGES/blur-my-shell@aunetx.mo b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ga/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..12af447 Binary files /dev/null and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ga/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index c00a0b0..eb0ac9e 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 57b3f28..8c9ee01 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 4d399d4..c67d148 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index a03d776..8253927 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ml/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ml/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 52a61c4..b01552f 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/mrh/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/mrh/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 0a4628a..50a7c8d 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 5bc86f8..a45493d 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 799ffb8..5f233d2 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index b04ae12..74a6190 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 6503f17..4185f34 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index cfdddf3..e76cac9 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 7b5f217..fa3e5a1 100644 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_CN/LC_MESSAGES/blur-my-shell@aunetx.mo and b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/locale/zh_CN/LC_MESSAGES/blur-my-shell@aunetx.mo 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 index 42d2697..bfeec0f 100644 --- 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 @@ -1,29 +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": [ - "45", "46", "47", "48", "49", - "50" + "50", + "51" ], "url": "https://github.com/aunetx/blur-my-shell", "uuid": "blur-my-shell@aunetx", - "version": 72 + "gettext-domain": "blur-my-shell@aunetx", + "settings-schema": "org.gnome.shell.extensions.blur-my-shell", + "session-modes": [ + "unlock-dialog", + "user" + ], + "original-authors": [ + "me@aunetx.dev" + ], + "donations": { + "github": "aunetx", + "kofi": "aunetx" + }, + "version": 74 } 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 index 49d2245..0884f36 100644 --- 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 @@ -45,6 +45,7 @@ export const Applications = GObject.registerClass({ 'opacity', 'dynamic_opacity', 'blur_on_overview', + 'unblur_when_fullscreen', 'enable_all', 'whitelist', 'add_window_whitelist', @@ -90,6 +91,10 @@ export const Applications = GObject.registerClass({ 'blur-on-overview', this._blur_on_overview, 'active', Gio.SettingsBindFlags.DEFAULT ); + this.preferences.applications.settings.bind( + 'unblur-when-fullscreen', this._unblur_when_fullscreen, 'active', + Gio.SettingsBindFlags.DEFAULT + ); this.preferences.applications.settings.bind( 'enable-all', this._enable_all, 'active', Gio.SettingsBindFlags.DEFAULT 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 index 0fac364..9115d61 100644 --- 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 @@ -25,7 +25,7 @@ export const Other = GObject.registerClass({ 'debug', 'reset' ], -}, class Overview extends Adw.PreferencesPage { +}, class Other extends Adw.PreferencesPage { constructor(preferences, pipelines_manager, pipelines_page) { super({}); @@ -83,4 +83,4 @@ export const Other = GObject.registerClass({ 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/panel.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/panel.js index 1115710..66b3b09 100644 --- 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 @@ -24,6 +24,12 @@ export const Panel = GObject.registerClass({ 'override_background', 'style_panel', 'override_background_dynamically', + 'override_background_dynamically_mode_row', + 'override_background_dynamically_mode', + 'gradient_panel_row', + 'gradient_panel', + 'gradient_panel_mode_row', + 'gradient_panel_mode', 'hidetopbar_compatibility', 'dtp_blur_original_panel' ], @@ -87,6 +93,28 @@ export const Panel = GObject.registerClass({ this._override_background_dynamically, 'active', Gio.SettingsBindFlags.DEFAULT ); + this.preferences.panel.settings.bind( + 'override-background-dynamically-mode', + this._override_background_dynamically_mode, 'selected', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.panel.settings.bind( + 'gradient-panel', this._gradient_panel, 'active', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.panel.settings.bind( + 'gradient-panel-mode', this._gradient_panel_mode, 'selected', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_changed( + () => this.proximity_option_changed() + ); + this.preferences.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_MODE_changed( + () => this.proximity_option_changed() + ); + this.preferences.panel.GRADIENT_PANEL_changed( + () => this.proximity_option_changed() + ); this.preferences.hidetopbar.settings.bind( 'compatibility', this._hidetopbar_compatibility, 'active', Gio.SettingsBindFlags.DEFAULT @@ -97,6 +125,12 @@ export const Panel = GObject.registerClass({ ); } + proximity_option_changed() { + this._override_background_dynamically_mode_row.set_visible(this.preferences.panel.OVERRIDE_BACKGROUND_DYNAMICALLY); + this._gradient_panel_row.set_visible(this.preferences.panel.OVERRIDE_BACKGROUND_DYNAMICALLY && this.preferences.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_MODE == 0); + this._gradient_panel_mode_row.set_visible(this.preferences.panel.OVERRIDE_BACKGROUND_DYNAMICALLY && this.preferences.panel.GRADIENT_PANEL && this.preferences.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_MODE == 0); + } + change_blur_mode(is_static_blur, first_run) { this._mode_static.set_active(is_static_blur); if (first_run) @@ -107,5 +141,7 @@ export const Panel = GObject.registerClass({ this._brightness_row.set_visible(!is_static_blur); this._corner_radius_row.set_visible(!is_static_blur && this.preferences.ROUNDED_BLUR_FOUND); this._corner_radius_not_found_row.set_visible(!is_static_blur && !this.preferences.ROUNDED_BLUR_FOUND); + + this.proximity_option_changed(); } }); 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 index e0c5165..d043bad 100644 --- 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 @@ -73,7 +73,10 @@ export const PipelineChooseRow = GObject.registerClass({ 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)) { + if ( + pipeline_id !== 'create_new' + && !(pipeline_id in this.pipelines_manager.pipelines) + ) { this.create_pipelines_list(); return; } @@ -103,4 +106,4 @@ export const PipelineChooseRow = GObject.registerClass({ 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/popup.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/popup.js new file mode 100644 index 0000000..5d60d8a --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/preferences/popup.js @@ -0,0 +1,121 @@ +import Adw from 'gi://Adw'; +import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; +import Gio from 'gi://Gio'; + + +export const PopupBlur = GObject.registerClass({ + GTypeName: 'PopupBlur', + Template: GLib.uri_resolve_relative(import.meta.url, '../ui/popup.ui', GLib.UriFlags.NONE), + InternalChildren: [ + 'blur', + 'pipeline_choose_row', + 'mode_static', + 'mode_dynamic', + 'sigma_row', + 'sigma', + 'brightness_row', + 'brightness', + 'corner_radius_row', + 'corner_radius', + 'menu_corner_radius', + 'quick_settings_corner_radius', + 'notification_corner_radius', + 'osd_corner_radius', + 'dialog_corner_radius', + 'osk_corner_radius', + 'corner_radius_not_found_row', + 'override_background', + 'preserve_shell_theme', + 'style_popup' + ], +}, class PopupBlur 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.popup.settings.bind( + 'blur', this._blur, 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + this._pipeline_choose_row.initialize( + this.preferences.popup, this.pipelines_manager, this.pipelines_page + ); + + this.change_blur_mode(this.preferences.popup.STATIC_BLUR, true); + + this._mode_static.connect('toggled', + () => this.preferences.popup.STATIC_BLUR = this._mode_static.active + ); + this.preferences.popup.STATIC_BLUR_changed( + () => this.change_blur_mode(this.preferences.popup.STATIC_BLUR, false) + ); + + this.preferences.popup.settings.bind( + 'sigma', this._sigma, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'brightness', this._brightness, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'corner-radius', this._corner_radius, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'menu-corner-radius', this._menu_corner_radius, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'quick-settings-corner-radius', this._quick_settings_corner_radius, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'notification-corner-radius', this._notification_corner_radius, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'osd-corner-radius', this._osd_corner_radius, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'dialog-corner-radius', this._dialog_corner_radius, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'osk-corner-radius', this._osk_corner_radius, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'override-background', + this._override_background, 'enable-expansion', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'preserve-shell-theme', + this._preserve_shell_theme, 'active', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.popup.settings.bind( + 'style-popup', this._style_popup, 'selected', + 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); + this._corner_radius_row.set_visible(is_static_blur || this.preferences.ROUNDED_BLUR_FOUND); + this._corner_radius_not_found_row.set_visible(!is_static_blur && !this.preferences.ROUNDED_BLUR_FOUND); + } +}); 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 index b3d7980..fbfe453 100644 --- 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 @@ -14,6 +14,7 @@ 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 { PopupBlur } from './preferences/popup.js'; import { Other } from './preferences/other.js'; import './preferences/pipelines_management/pipeline_choose_row.js'; @@ -56,6 +57,7 @@ export default class BlurMyShellPreferences extends ExtensionPreferences { 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 PopupBlur(preferences, 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 deleted file mode 100644 index eb8b556..0000000 Binary files a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/schemas/gschemas.compiled and /dev/null 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 index 2c03cc9..588d235 100644 --- 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 @@ -104,6 +104,7 @@ + @@ -276,10 +277,25 @@ 0 Enum to select the style of the panel (0 transparent, 1 light, 2 dark, 3 contrasted) - + false - Boolean, whether to disable blur from this component when a window is close to the panel + Boolean, whether to enable certain effect for this component when a window is close to the panel + + + + 1 + Enum to select the override mode (0 Blur on Window Proximity, 1 Background on Window Proximity). Required "override-background-dynamically" to be enabled. + + + + false + Boolean, whether to enable the gradient panel effect + + + + 0 + Enum to select the gradient panel mode (0 Top, 1 Bottom). Required "gradient-panel" to be enabled. @@ -426,6 +442,11 @@ false Wether or not to blur applications on the overview + + + false + Wether or not to unblur applications when they are fullscreen + false @@ -593,6 +614,86 @@ + + + + + true + Boolean, whether to blur popup menus, notifications, switchers, and dialogs or not + + + + false + Boolean, whether to use a static blur on popup surfaces + + + + "pipeline_default_rounded" + String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used + + + + 30 + Gaussian sigma to use for the blur effect + + + + 0.6 + Brightness to use for the blur effect + + + + 18 + Radius for the corner rounding effect + + + + 20 + Radius for popup menu corner rounding + + + + 36 + Radius for quick settings and calendar corner rounding + + + + 18 + Radius for notification corner rounding + + + + 28 + Radius for OSD and switcher corner rounding + + + + 18 + Radius for dialog corner rounding + + + + 0 + Radius for on-screen keyboard corner rounding + + + + true + Boolean, whether to override the background or not + + + + false + Boolean, whether to preserve the shell theme's popup control styling + + + + 3 + Enum to select the style of popup surfaces (0 transparent, 1 light, 2 dark, 3 automatic) + + + diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/appfolders.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/appfolders.css new file mode 100644 index 0000000..5e8f0d4 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/appfolders.css @@ -0,0 +1,55 @@ +/*** 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; +} + + diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/dash.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/dash.css new file mode 100644 index 0000000..b99da78 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/dash.css @@ -0,0 +1,26 @@ +/*** DASH-TO-DOCK ***/ + +/* +* `.transparent-dash` +*/ +.transparent-dash .dash-background { + background: transparent !important; +} + +/* +* `.light-dash` +*/ +.light-dash .dash-background { + background: rgba(255, 255, 255, 0.58) !important; + border: 1px solid rgba(0, 0, 0, 0.05); +} + +/* +* `.dark-dash` +*/ +.dark-dash .dash-background { + background: rgba(45, 45, 50, 0.22) !important; + border: 1px solid rgba(255, 255, 255, 0.05); +} + + diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/overview.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/overview.css new file mode 100644 index 0000000..4958bd1 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/overview.css @@ -0,0 +1,364 @@ +/*** 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) !important; + 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, +.overview-components-transparent .multimonitor-dock .overview-tile { + background-color: transparent !important; +} + +.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, +.overview-components-transparent .multimonitor-dock .dash-background { + background-color: rgba(0, 0, 0, 0) !important; +} + +.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, +.overview-components-transparent .multimonitor-dock .overview-tile:hover .overview-icon, +.overview-components-transparent .multimonitor-dock .overview-tile:focus .overview-icon, +.overview-components-transparent .multimonitor-dock .show-apps:hover .overview-icon, +.overview-components-transparent .multimonitor-dock .show-apps:focus .overview-icon { + background-color: rgba(230, 230, 230, 0.08) !important; +} + +.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, +.overview-components-transparent .multimonitor-dock .overview-tile:hover .overview-icon, +.overview-components-transparent .multimonitor-dock .overview-tile:focus .overview-icon, +.overview-components-transparent .multimonitor-dock .show-apps:hover .overview-icon, +.overview-components-transparent .multimonitor-dock .show-apps:focus .overview-icon { + background-color: rgba(230, 230, 230, 0.12) !important; +} + +.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, +.overview-components-transparent .multimonitor-dock .show-apps:checked .overview-icon:hover { + background-color: rgba(230, 230, 230, 0.15) !important; +} + + +/* +* `.overview-components-light` +*/ + +.overview-components-light .search-entry { + color: white; + background-color: rgba(200, 200, 200, 0.2) !important; + 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, +.overview-components-light .multimonitor-dock .overview-tile { + background-color: transparent !important; +} + +.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, +.overview-components-light .multimonitor-dock .dash-background { + background-color: rgba(200, 200, 200, 0.2) !important; +} + +.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, +.overview-components-light .multimonitor-dock .overview-tile:hover .overview-icon, +.overview-components-light .multimonitor-dock .overview-tile:focus .overview-icon, +.overview-components-light .multimonitor-dock .show-apps:hover .overview-icon, +.overview-components-light .multimonitor-dock .show-apps:focus .overview-icon { + background-color: rgba(230, 230, 230, 0.2) !important; +} + +.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, +.overview-components-light .multimonitor-dock .overview-tile:hover .overview-icon, +.overview-components-light .multimonitor-dock .overview-tile:focus .overview-icon, +.overview-components-light .multimonitor-dock .show-apps:hover .overview-icon, +.overview-components-light .multimonitor-dock .show-apps:focus .overview-icon { + background-color: rgba(230, 230, 230, 0.25) !important; +} + +.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, +.overview-components-light .multimonitor-dock .show-apps:checked .overview-icon:hover { + background-color: rgba(230, 230, 230, 0.3) !important; +} + + +/* +* `.overview-components-dark` +*/ + +.overview-components-dark .search-entry { + color: white; + background-color: rgba(100, 100, 100, 0.35) !important; + 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, +.overview-components-dark .multimonitor-dock .overview-tile { + background-color: transparent !important; +} + +.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, +.overview-components-dark .multimonitor-dock .dash-background { + background-color: rgba(100, 100, 100, 0.35) !important; +} + +.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, +.overview-components-dark .multimonitor-dock .overview-tile:hover .overview-icon, +.overview-components-dark .multimonitor-dock .overview-tile:focus .overview-icon, +.overview-components-dark .multimonitor-dock .show-apps:hover .overview-icon, +.overview-components-dark .multimonitor-dock .show-apps:focus .overview-icon { + background-color: rgba(120, 120, 120, 0.35) !important; +} + +.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, +.overview-components-dark .multimonitor-dock .overview-tile:hover .overview-icon, +.overview-components-dark .multimonitor-dock .overview-tile:focus .overview-icon, +.overview-components-dark .multimonitor-dock .show-apps:hover .overview-icon, +.overview-components-dark .multimonitor-dock .show-apps:focus .overview-icon { + background-color: rgba(120, 120, 120, 0.4) !important; +} + +.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, +.overview-components-dark .multimonitor-dock .show-apps:checked .overview-icon:hover { + background-color: rgba(120, 120, 120, 0.45) !important; +} + diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/panel-light-text.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/panel-light-text.css new file mode 100644 index 0000000..f868dda --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/panel-light-text.css @@ -0,0 +1,92 @@ +/*** PANEL LIGHT TEXT ***/ + +/* +* `.panel-light-text`, adapted from gnome-shell-light.css +*/ + +.panel-light-text #panel .panel-button, +.panel-light-text #panel .panel-button.clock-display, +.panel-light-text #panel .netSpeedLabel { + color: #f6f5f4; + box-shadow: none; +} + +.panel-light-text #panel .panel-button:active, +.panel-light-text #panel .panel-button:focus, +.panel-light-text #panel .panel-button:checked, +.panel-light-text #panel .panel-button.clock-display:active .clock, +.panel-light-text #panel .panel-button.clock-display:focus .clock, +.panel-light-text #panel .panel-button.clock-display:checked .clock { + box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.25); +} + +.panel-light-text #panel .panel-button:active:hover, +.panel-light-text #panel .panel-button:focus:hover, +.panel-light-text #panel .panel-button:checked:hover, +.panel-light-text #panel .panel-button.clock-display:active:hover, +.panel-light-text #panel .panel-button.clock-display:focus:hover, +.panel-light-text #panel .panel-button.clock-display:checked:hover, +.panel-light-text #panel .panel-button.clock-display:active .clock:hover, +.panel-light-text #panel .panel-button.clock-display:focus .clock:hover, +.panel-light-text #panel .panel-button.clock-display:checked .clock:hover { + box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.35); +} + +.panel-light-text #panel .panel-button:hover, +.panel-light-text #panel .panel-button.clock-display:hover, +.panel-light-text #panel .panel-button.clock-display:hover .clock { + box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.2); +} + +.panel-light-text #panel .panel-button#panelActivities .workspace-dot { + background-color: #f6f5f4; +} + +.panel-light-text #panel .panel-button.clock-display:active, +.panel-light-text #panel .panel-button.clock-display:focus, +.panel-light-text #panel .panel-button.clock-display:checked, +.panel-light-text #panel .panel-button.clock-display:hover { + box-shadow: none !important; +} + +.panel-light-text #panel .panel-button.screen-recording-indicator { + color: #f6f5f4; + box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.8); +} + +.panel-light-text #panel .panel-button.screen-recording-indicator:active, +.panel-light-text #panel .panel-button.screen-recording-indicator:focus, +.panel-light-text #panel .panel-button.screen-recording-indicator:checked { + box-shadow: inset 0 0 0 100px #c01c28; +} + +.panel-light-text #panel .panel-button.screen-recording-indicator:active:hover, +.panel-light-text #panel .panel-button.screen-recording-indicator:focus:hover, +.panel-light-text #panel .panel-button.screen-recording-indicator:checked:hover { + box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.95); +} + +.panel-light-text #panel .panel-button.screen-recording-indicator:hover { + box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.9); +} + +.panel-light-text #panel .panel-button.screen-sharing-indicator { + color: #282828; + box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.8); +} + +.panel-light-text #panel .panel-button.screen-sharing-indicator:active, +.panel-light-text #panel .panel-button.screen-sharing-indicator:focus, +.panel-light-text #panel .panel-button.screen-sharing-indicator:checked { + box-shadow: inset 0 0 0 100px #ff7800; +} + +.panel-light-text #panel .panel-button.screen-sharing-indicator:active:hover, +.panel-light-text #panel .panel-button.screen-sharing-indicator:focus:hover, +.panel-light-text #panel .panel-button.screen-sharing-indicator:checked:hover { + box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.95); +} + +.panel-light-text #panel .panel-button.screen-sharing-indicator:hover { + box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.9); +} diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/panel.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/panel.css new file mode 100644 index 0000000..0273cb5 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/panel.css @@ -0,0 +1,97 @@ +/*** PANEL ***/ + +/* +* `.transparent-panel` +*/ + +#panel.transparent-panel { + background: transparent !important; + transition-duration: 500ms; +} + +/* +* `.dark-panel` +*/ +#panel.dark-panel { + background-color: rgba(100, 100, 100, 0.35) !important; + box-shadow: none !important; + transition-duration: 500ms; +} + +/* +* `.light-panel` +*/ +#panel.light-panel { + background-color: rgba(200, 200, 200, 0.2) !important; + box-shadow: none !important; + transition-duration: 500ms; +} + +/* +* `.contrasted-panel` +*/ +#panel.contrasted-panel { + background-color: transparent !important; + box-shadow: none !important; + transition-duration: 500ms; +} + +/* +* `.gradient-panel` +*/ +/* Internal use */ + +#panel.gradient-panel { + background-color: transparent !important; + background-gradient-direction: vertical !important; + background-gradient-start: rgba(0,0,0,0.5) !important; + background-gradient-end: rgba(0,0,0,0) !important; + box-shadow: none !important; + transition-duration: 500ms; +} + +/* +* `.gradient-panel-reverse` +*/ +/* Internal use */ + +#panel.gradient-panel-reverse { + background-color: transparent !important; + background-gradient-direction: vertical !important; + background-gradient-start: rgba(0,0,0,0) !important; + background-gradient-end: rgba(0,0,0,0.5) !important; + box-shadow: none !important; + 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; +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/base.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/base.css new file mode 100644 index 0000000..a313eed --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/base.css @@ -0,0 +1,729 @@ +/*** POPUP ***/ + +.bms-popup-blurred-widget { + background: rgba(0, 0, 0, 0.01); +} + +.bms-popup-background-transparent .popup-menu-content, +.bms-popup-background-transparent .popup-sub-menu, +.bms-popup-background-transparent .candidate-popup-content, +.bms-popup-background-transparent .quick-settings, +.bms-popup-background-transparent .quick-toggle-menu, +.bms-popup-background-transparent .osd-window, +.bms-popup-background-transparent .resize-popup, +.bms-popup-background-transparent .switcher-list, +.bms-popup-background-transparent .workspace-switcher, +.bms-popup-background-transparent .modal-dialog, +.bms-popup-background-transparent .run-dialog, +.bms-popup-background-transparent .screenshot-ui-panel, +.bms-popup-surface-transparent .popup-menu-content, +.bms-popup-surface-transparent .popup-sub-menu, +.bms-popup-surface-transparent .candidate-popup-content, +.bms-popup-surface-transparent .quick-settings, +.bms-popup-surface-transparent .quick-toggle-menu, +.bms-popup-surface-transparent .osd-window, +.bms-popup-surface-transparent .resize-popup, +.bms-popup-surface-transparent .switcher-list, +.bms-popup-surface-transparent .workspace-switcher, +.bms-popup-surface-transparent .modal-dialog, +.bms-popup-surface-transparent .run-dialog, +.bms-popup-surface-transparent .screenshot-ui-panel { + background: transparent !important; + border-color: transparent; + box-shadow: none; +} + +.bms-popup-background-light .popup-menu-content, +.bms-popup-background-light .popup-sub-menu, +.bms-popup-background-light .candidate-popup-content, +.bms-popup-background-light .quick-settings, +.bms-popup-background-light .quick-toggle-menu, +.bms-popup-background-light .message, +.bms-popup-background-light .osd-window, +.bms-popup-background-light .resize-popup, +.bms-popup-background-light .switcher-list, +.bms-popup-background-light .workspace-switcher, +.bms-popup-background-light .modal-dialog, +.bms-popup-background-light .run-dialog, +.bms-popup-background-light .screenshot-ui-panel { + color: #222226; +} + +.bms-popup-background-light .popup-menu-content, +.bms-popup-background-light .popup-sub-menu, +.bms-popup-background-light .candidate-popup-content, +.bms-popup-background-light .quick-settings, +.bms-popup-background-light .quick-toggle-menu, +.bms-popup-background-light .message, +.bms-popup-background-light .osd-window, +.bms-popup-background-light .resize-popup, +.bms-popup-background-light .switcher-list, +.bms-popup-background-light .workspace-switcher, +.bms-popup-background-light .modal-dialog, +.bms-popup-background-light .run-dialog, +.bms-popup-background-light .screenshot-ui-panel, +.bms-popup-surface-light .popup-menu-content, +.bms-popup-surface-light .popup-sub-menu, +.bms-popup-surface-light .candidate-popup-content, +.bms-popup-surface-light .quick-settings, +.bms-popup-surface-light .quick-toggle-menu, +.bms-popup-surface-light .message, +.bms-popup-surface-light .osd-window, +.bms-popup-surface-light .resize-popup, +.bms-popup-surface-light .switcher-list, +.bms-popup-surface-light .workspace-switcher, +.bms-popup-surface-light .modal-dialog, +.bms-popup-surface-light .run-dialog, +.bms-popup-surface-light .screenshot-ui-panel { + background: rgba(255, 255, 255, 0.58) !important; + border-color: rgba(0, 0, 0, 0.05); + box-shadow: 0 8px 22px rgba(0, 0, 0, 0.08); +} + +.bms-popup-background-light .modal-dialog, +.bms-popup-background-light .run-dialog, +.bms-popup-surface-light .modal-dialog, +.bms-popup-surface-light .run-dialog, +.bms-popup-background-dark .modal-dialog, +.bms-popup-background-dark .run-dialog, +.bms-popup-surface-dark .modal-dialog, +.bms-popup-surface-dark .run-dialog { + border: 1px solid rgba(0, 0, 0, 0.05); +} + +.bms-popup-background-light .message:hover, +.bms-popup-surface-light .message:hover { + background: rgba(255, 255, 255, 0.4) !important; +} + +.bms-popup-background-light .message:active, +.bms-popup-surface-light .message:active, +.bms-popup-background-light .message:focus, +.bms-popup-surface-light .message:focus { + background: rgba(255, 255, 255, 0.7) !important; +} + +.bms-popup-background-dark .popup-menu-content, +.bms-popup-background-dark .popup-sub-menu, +.bms-popup-background-dark .candidate-popup-content, +.bms-popup-background-dark .quick-settings, +.bms-popup-background-dark .quick-toggle-menu, +.bms-popup-background-dark .message, +.bms-popup-background-dark .osd-window, +.bms-popup-background-dark .resize-popup, +.bms-popup-background-dark .switcher-list, +.bms-popup-background-dark .workspace-switcher, +.bms-popup-background-dark .modal-dialog, +.bms-popup-background-dark .run-dialog, +.bms-popup-background-dark .screenshot-ui-panel, +.bms-popup-background-transparent .message { + color: #ffffff; +} + +.bms-popup-background-dark .popup-menu-content, +.bms-popup-background-dark .popup-sub-menu, +.bms-popup-background-dark .candidate-popup-content, +.bms-popup-background-dark .quick-settings, +.bms-popup-background-dark .quick-toggle-menu, +.bms-popup-background-dark .osd-window, +.bms-popup-background-dark .resize-popup, +.bms-popup-background-dark .switcher-list, +.bms-popup-background-dark .workspace-switcher, +.bms-popup-background-dark .modal-dialog, +.bms-popup-background-dark .run-dialog, +.bms-popup-background-dark .screenshot-ui-panel, +.bms-popup-surface-dark .screenshot-ui-panel, +.bms-popup-surface-dark .popup-menu-content, +.bms-popup-surface-dark .popup-sub-menu, +.bms-popup-surface-dark .candidate-popup-content, +.bms-popup-surface-dark .quick-settings, +.bms-popup-surface-dark .quick-toggle-menu, +.bms-popup-surface-dark .osd-window, +.bms-popup-surface-dark .resize-popup, +.bms-popup-surface-dark .switcher-list, +.bms-popup-surface-dark .workspace-switcher, +.bms-popup-surface-dark .modal-dialog, +.bms-popup-surface-dark .run-dialog { + background: rgba(45, 45, 50, 0.22) !important; + border-color: rgba(255, 255, 255, 0.05); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16); +} + +.bms-popup-background-dark .message, +.bms-popup-background-transparent .message, +.bms-popup-surface-dark .message, +.bms-popup-surface-transparent .message { + background: rgba(255, 255, 255, 0.07) !important; + border-color: rgba(255, 255, 255, 0.05); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16); +} + +.bms-popup-background-dark .message:hover, +.bms-popup-background-transparent .message:hover, +.bms-popup-surface-dark .message:hover, +.bms-popup-surface-transparent .message:hover { + background: rgba(255, 255, 255, 0.12) !important; +} + +.bms-popup-background-dark .message:focus, +.bms-popup-background-transparent .message:focus, +.bms-popup-surface-dark .message:focus, +.bms-popup-surface-transparent .message:focus, +.bms-popup-background-dark .message:active, +.bms-popup-background-transparent .message:active, +.bms-popup-surface-dark .message:active, +.bms-popup-surface-transparent .message:active { + background: rgba(255, 255, 255, 0.15) !important; +} + +.bms-popup-background-transparent .message, +.bms-popup-background-light .message, +.bms-popup-background-dark .message, +.bms-popup-surface-transparent .message, +.bms-popup-surface-light .message, +.bms-popup-surface-dark .message { + box-shadow: none; +} + +.bms-popup-background-transparent StScrollBar StBin#trough, +.bms-popup-background-light StScrollBar StBin#trough, +.bms-popup-background-dark StScrollBar StBin#trough { + background-color: transparent; +} + +.bms-popup-background-transparent StScrollBar > .vhandle, +.bms-popup-background-transparent StScrollBar > .hhandle, +.bms-popup-background-dark StScrollBar > .vhandle, +.bms-popup-background-dark StScrollBar > .hhandle { + background-color: rgba(255, 255, 255, 0.28); + border-color: transparent; +} + +.bms-popup-background-transparent StScrollBar > .vhandle:hover, +.bms-popup-background-transparent StScrollBar > .hhandle:hover, +.bms-popup-background-dark StScrollBar > .vhandle:hover, +.bms-popup-background-dark StScrollBar > .hhandle:hover { + background-color: rgba(255, 255, 255, 0.38); +} + +.bms-popup-background-transparent StScrollBar > .vhandle:active, +.bms-popup-background-transparent StScrollBar > .hhandle:active, +.bms-popup-background-dark StScrollBar > .vhandle:active, +.bms-popup-background-dark StScrollBar > .hhandle:active { + background-color: rgba(255, 255, 255, 0.46); +} + +.bms-popup-background-light StScrollBar > .vhandle, +.bms-popup-background-light StScrollBar > .hhandle { + background-color: rgba(34, 34, 38, 0.24); + border-color: transparent; +} + +.bms-popup-background-light StScrollBar > .vhandle:hover, +.bms-popup-background-light StScrollBar > .hhandle:hover { + background-color: rgba(34, 34, 38, 0.34); +} + +.bms-popup-background-light StScrollBar > .vhandle:active, +.bms-popup-background-light StScrollBar > .hhandle:active { + background-color: rgba(34, 34, 38, 0.42); +} + +.bms-popup-background-transparent .osd-window, +.bms-popup-background-light .osd-window, +.bms-popup-background-dark .osd-window, +.bms-popup-background-transparent .resize-popup, +.bms-popup-background-light .resize-popup, +.bms-popup-background-dark .resize-popup, +.bms-popup-background-transparent .workspace-switcher, +.bms-popup-background-light .workspace-switcher, +.bms-popup-background-dark .workspace-switcher, +.bms-popup-surface-transparent .osd-window, +.bms-popup-surface-light .osd-window, +.bms-popup-surface-dark .osd-window, +.bms-popup-surface-transparent .resize-popup, +.bms-popup-surface-light .resize-popup, +.bms-popup-surface-dark .resize-popup, +.bms-popup-surface-transparent .workspace-switcher, +.bms-popup-surface-light .workspace-switcher, +.bms-popup-surface-dark .workspace-switcher { + border-radius: 18px; +} + +.bms-popup-background-light .osd-window .level { + -barlevel-background-color: rgba(0, 0, 0, 0.12); + -barlevel-active-background-color: #222226; + -barlevel-overdrive-color: #c01c28; +} + +.bms-popup-background-dark .osd-window .level { + -barlevel-background-color: rgba(255, 255, 255, 0.14); + -barlevel-active-background-color: #ffffff; + -barlevel-overdrive-color: #f66151; +} + +.bms-popup-background-light .switcher-list .item-box:focus, +.bms-popup-background-light .switcher-list .item-box:selected, +.bms-popup-surface-light .switcher-list .item-box:focus, +.bms-popup-surface-light .switcher-list .item-box:selected { + background-color: rgba(0, 0, 0, 0.12) !important; +} + +.bms-popup-background-dark .switcher-list .item-box:focus, +.bms-popup-background-dark .switcher-list .item-box:selected, +.bms-popup-surface-dark .switcher-list .item-box:focus, +.bms-popup-surface-dark .switcher-list .item-box:selected { + background-color: rgba(255, 255, 255, 0.13) !important; +} + +.bms-popup-background-transparent .switcher-list .item-box:focus, +.bms-popup-background-transparent .switcher-list .item-box:selected, +.bms-popup-surface-transparent .switcher-list .item-box:focus, +.bms-popup-surface-transparent .switcher-list .item-box:selected { + background-color: rgba(255, 255, 255, 0.13) !important; +} + +.bms-popup-background-transparent .popup-sub-menu, +.bms-popup-background-light .popup-sub-menu, +.bms-popup-background-dark .popup-sub-menu, +.bms-popup-surface-transparent .popup-sub-menu, +.bms-popup-surface-light .popup-sub-menu, +.bms-popup-surface-dark .popup-sub-menu { + background: transparent !important; + border-color: transparent; + border-radius: 0 0 13px 13px; + box-shadow: none; +} + +.bms-popup-background-dark .popup-sub-menu > StBoxLayout, +.bms-popup-surface-dark .popup-sub-menu > StBoxLayout { + background-color: rgba(58, 58, 64, 0.36) !important; + border-radius: 0 0 13px 13px; +} + +.bms-popup-background-light .popup-sub-menu > StBoxLayout, +.bms-popup-surface-light .popup-sub-menu > StBoxLayout { + background-color: rgba(255, 255, 255, 0.58) !important; + border-radius: 0 0 13px 13px; +} + +.bms-popup-background-transparent .popup-sub-menu .popup-menu-item, +.bms-popup-background-light .popup-sub-menu .popup-menu-item, +.bms-popup-background-dark .popup-sub-menu .popup-menu-item { + background-color: transparent !important; + border-color: transparent; + border-radius: 0; + box-shadow: none; +} + +.bms-popup-background-transparent .popup-sub-menu .popup-menu-item:insensitive, +.bms-popup-background-light .popup-sub-menu .popup-menu-item:insensitive, +.bms-popup-background-dark .popup-sub-menu .popup-menu-item:insensitive { + background-color: transparent !important; +} + +.bms-popup-background-transparent .screenshot-ui-type-button, +.bms-popup-background-light .screenshot-ui-type-button, +.bms-popup-background-dark .screenshot-ui-type-button, +.bms-popup-background-transparent .screenshot-ui-type-button:insensitive, +.bms-popup-background-light .screenshot-ui-type-button:insensitive, +.bms-popup-background-dark .screenshot-ui-type-button:insensitive { + background-color: transparent !important; +} + +.bms-popup-background-transparent .screenshot-ui-type-button:checked, +.bms-popup-background-transparent .screenshot-ui-type-button:focus, +.bms-popup-background-dark .screenshot-ui-type-button:checked, +.bms-popup-background-dark .screenshot-ui-type-button:focus { + background-color: rgba(255, 255, 255, 0.13) !important +} + +.bms-popup-background-light .screenshot-ui-type-button, +.bms-popup-background-light .screenshot-ui-show-pointer-button, +.bms-popup-background-light .screenshot-ui-shot-cast-button { + color: #1a1a1e !important; +} + +.bms-popup-background-light .screenshot-ui-type-button:insensitive, +.bms-popup-background-light .screenshot-ui-show-pointer-button:insensitive, +.bms-popup-background-light .screenshot-ui-shot-cast-button:insensitive { + color: rgba(26, 26, 30, 0.5) !important; +} + +.bms-popup-background-transparent .screenshot-ui-type-button:hover, +.bms-popup-background-dark .screenshot-ui-type-button:hover { + background-color: rgba(255, 255, 255, 0.20) !important; +} + +.bms-popup-background-transparent .screenshot-ui-type-button:active, +.bms-popup-background-transparent .screenshot-ui-type-button:outlined, +.bms-popup-background-dark .screenshot-ui-type-button:active, +.bms-popup-background-dark .screenshot-ui-type-button:outlined { + background-color: rgba(255, 255, 255, 0.18) !important; +} + +.bms-popup-background-light .screenshot-ui-type-button:hover { + background-color: rgba(0, 0, 0, 0.18) !important; +} + +.bms-popup-background-light .screenshot-ui-type-button:checked, +.bms-popup-background-light .screenshot-ui-type-button:focus { + background-color: rgba(0, 0, 0, 0.12) !important; +} + +.bms-popup-background-light .screenshot-ui-type-button:active, +.bms-popup-background-light .screenshot-ui-type-button:outlined { + background-color: rgba(0, 0, 0, 0.16) !important; +} + +.bms-popup-background-transparent .screenshot-ui-show-pointer-button, +.bms-popup-background-light .screenshot-ui-show-pointer-button, +.bms-popup-background-dark .screenshot-ui-show-pointer-button, +.bms-popup-background-transparent .screenshot-ui-show-pointer-button:insensitive, +.bms-popup-background-light .screenshot-ui-show-pointer-button:insensitive, +.bms-popup-background-dark .screenshot-ui-show-pointer-button:insensitive { + background-color: transparent !important; +} + +.bms-popup-background-light .screenshot-ui-show-pointer-button:hover { + background-color: rgba(0, 0, 0, 0.18) !important; +} + +.bms-popup-background-light .screenshot-ui-show-pointer-button:checked, +.bms-popup-background-light .screenshot-ui-show-pointer-button:focus { + background-color: rgba(0, 0, 0, 0.12) !important; +} + +.bms-popup-background-transparent .screenshot-ui-show-pointer-button:checked, +.bms-popup-background-transparent .screenshot-ui-show-pointer-button:focus, +.bms-popup-background-dark .screenshot-ui-show-pointer-button:checked, +.bms-popup-background-dark .screenshot-ui-show-pointer-button:focus { + background-color: rgba(255, 255, 255, 0.13) !important; +} + +.bms-popup-background-transparent .screenshot-ui-show-pointer-button:hover, +.bms-popup-background-dark .screenshot-ui-show-pointer-button:hover { + background-color: rgba(255, 255, 255, 0.20) !important; +} + +.bms-popup-background-transparent .screenshot-ui-show-pointer-button:active, +.bms-popup-background-transparent .screenshot-ui-show-pointer-button:outlined, +.bms-popup-background-dark .screenshot-ui-show-pointer-button:active, +.bms-popup-background-dark .screenshot-ui-show-pointer-button:outlined { + background-color: rgba(255, 255, 255, 0.18) !important; +} + +.bms-popup-background-light .screenshot-ui-show-pointer-button:active, +.bms-popup-background-light .screenshot-ui-show-pointer-button:outlined { + background-color: rgba(0, 0, 0, 0.16) !important; +} + +.bms-popup-background-light .screenshot-ui-capture-button { + border: 4px #1a1a1e !important; +} + +.bms-popup-background-light .screenshot-ui-capture-button .screenshot-ui-capture-button-circle { + background-color: #1a1a1e !important; +} + +.bms-popup-background-light .screenshot-ui-capture-button:hover .screenshot-ui-capture-button-circle, +.bms-popup-background-light .screenshot-ui-capture-button:focus .screenshot-ui-capture-button-circle { + background-color: #3a3a3e !important; +} + +.bms-popup-background-light .screenshot-ui-capture-button:active .screenshot-ui-capture-button-circle { + background-color: #5a5a5e !important; +} + +.bms-popup-background-light .screenshot-ui-capture-button:cast .screenshot-ui-capture-button-circle { + background-color: #c01c28 !important; +} + +.bms-popup-background-light .screenshot-ui-capture-button:cast:hover .screenshot-ui-capture-button-circle, +.bms-popup-background-light .screenshot-ui-capture-button:cast:focus .screenshot-ui-capture-button-circle { + background-color: #d61f2d !important; +} + +.bms-popup-background-light .screenshot-ui-capture-button:cast:active .screenshot-ui-capture-button-circle { + background-color: #a11722 !important; +} + +.bms-popup-background-light .screenshot-ui-shot-cast-container { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +.bms-popup-background-light .screenshot-ui-shot-cast-button:hover, +.bms-popup-background-light .screenshot-ui-shot-cast-button:focus { + background-color: rgba(0, 0, 0, 0.18) !important; +} + +.bms-popup-background-light .screenshot-ui-shot-cast-button:active { + background-color: rgba(0, 0, 0, 0.28) !important; +} + +.bms-popup-background-light .screenshot-ui-shot-cast-button:checked { + background-color: #1a1a1e !important; + color: #ffffff !important; +} + +.bms-popup-background-light .screenshot-ui-shot-cast-button:insensitive { + color: rgba(26, 26, 30, 0.5) !important; +} + +.bms-popup-background-transparent .popup-sub-menu .popup-menu-section, +.bms-popup-background-light .popup-sub-menu .popup-menu-section, +.bms-popup-background-dark .popup-sub-menu .popup-menu-section { + border-radius: 0 0 12px 12px; +} + +.bms-popup-background-transparent .popup-sub-menu .popup-menu-item:last-child, +.bms-popup-background-transparent .popup-sub-menu .popup-menu-section .popup-menu-item:last-child, +.bms-popup-background-transparent .popup-sub-menu .popup-menu-section:last-child .popup-menu-item:last-child, +.bms-popup-background-light .popup-sub-menu .popup-menu-item:last-child, +.bms-popup-background-light .popup-sub-menu .popup-menu-section .popup-menu-item:last-child, +.bms-popup-background-light .popup-sub-menu .popup-menu-section:last-child .popup-menu-item:last-child, +.bms-popup-background-dark .popup-sub-menu .popup-menu-item:last-child, +.bms-popup-background-dark .popup-sub-menu .popup-menu-section .popup-menu-item:last-child, +.bms-popup-background-dark .popup-sub-menu .popup-menu-section:last-child .popup-menu-item:last-child { + border-radius: 0 0 12px 12px; +} + +.bms-popup-background-dark .bms-keyboard-surface, +.bms-popup-surface-dark .bms-keyboard-surface, +.bms-popup-background-transparent .bms-keyboard-surface, +.bms-popup-surface-transparent .bms-keyboard-surface { + background: rgba(45, 45, 50, 0.22) !important; + border: 1px solid rgba(255, 255, 255, 0.05);; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16); +} + +.bms-popup-background-light .bms-keyboard-surface, +.bms-popup-surface-light .bms-keyboard-surface { + background: rgba(255, 255, 255, 0.58) !important; + border: 1px solid rgba(0, 0, 0, 0.05); + box-shadow: 0 8px 22px rgba(0, 0, 0, 0.08); +} + +.bms-popup-background-dark .keyboard-subkeys, +.bms-popup-background-transparent .keyboard-subkeys { + -arrow-background-color: rgba(35, 35, 35, 0.98); + -arrow-border-color: rgba(255, 255, 255, 0.12); +} + +/* Base Keys */ +.bms-popup-background-dark .keyboard-key, +.bms-popup-background-transparent .keyboard-key, +.bms-popup-background-dark .keyboard-subkeys .keyboard-key, +.bms-popup-background-transparent .keyboard-subkeys .keyboard-key { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.08); + border-color: rgba(255, 255, 255, 0.06); + box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.25); +} + +/* Interactive States */ +.bms-popup-background-dark .keyboard-key:hover, +.bms-popup-background-transparent .keyboard-key:hover, +.bms-popup-background-dark .keyboard-subkeys .keyboard-key:hover, +.bms-popup-background-transparent .keyboard-subkeys .keyboard-key:hover, +.bms-popup-background-dark .keyboard-key:focus:hover, +.bms-popup-background-transparent .keyboard-key:focus:hover, +.bms-popup-background-dark .keyboard-subkeys .keyboard-key:focus:hover, +.bms-popup-background-transparent .keyboard-subkeys .keyboard-key:focus:hover { + background-color: rgba(255, 255, 255, 0.20) !important; + color: #ffffff; +} + +.bms-popup-background-dark .keyboard-key:active, +.bms-popup-background-transparent .keyboard-key:active, +.bms-popup-background-dark .keyboard-subkeys .keyboard-key:active, +.bms-popup-background-transparent .keyboard-subkeys .keyboard-key:active, +.bms-popup-background-dark .keyboard-key:focus:active, +.bms-popup-background-transparent .keyboard-key:focus:active, +.bms-popup-background-dark .keyboard-subkeys .keyboard-key:focus:active, +.bms-popup-background-transparent .keyboard-subkeys .keyboard-key:focus:active { + background-color: rgba(255, 255, 255, 0.18) !important; + color: #ffffff; +} + +.bms-popup-background-dark .keyboard-key:checked, +.bms-popup-background-transparent .keyboard-key:checked, +.bms-popup-background-dark .keyboard-subkeys .keyboard-key:checked, +.bms-popup-background-transparent .keyboard-subkeys .keyboard-key:checked { + background-color: rgba(255, 255, 255, 0.13) !important; + box-shadow: inset 0 0 0 2px rgba(53, 132, 228, 0.6); + color: #ffffff; +} + +.bms-popup-background-dark .keyboard-key:focus, +.bms-popup-background-transparent .keyboard-key:focus, +.bms-popup-background-dark .keyboard-subkeys .keyboard-key:focus, +.bms-popup-background-transparent .keyboard-subkeys .keyboard-key:focus { + background-color: rgba(255, 255, 255, 0.08) !important; + box-shadow: none; + color: #ffffff; +} + +.bms-popup-background-dark .keyboard-key:grayed, +.bms-popup-background-transparent .keyboard-key:grayed { + background-color: rgba(255, 255, 255, 0.03); + color: rgba(255, 255, 255, 0.35); + border-color: rgba(0, 0, 0, 0.4); +} + +/* Modifier & Function Keys */ +.bms-popup-background-dark .keyboard-key.default-key, +.bms-popup-background-transparent .keyboard-key.default-key { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.05); +} + +.bms-popup-background-dark .keyboard-key.default-key:hover, +.bms-popup-background-transparent .keyboard-key.default-key:hover { + background-color: rgba(255, 255, 255, 0.20); +} + +.bms-popup-background-dark .keyboard-key.default-key:active, +.bms-popup-background-transparent .keyboard-key.default-key:active { + background-color: rgba(255, 255, 255, 0.18); +} + +.bms-popup-background-dark .keyboard-key.default-key:checked, +.bms-popup-background-transparent .keyboard-key.default-key:checked { + background-color: rgba(255, 255, 255, 0.13); +} + +.bms-popup-background-dark .keyboard-key.default-key:latched, +.bms-popup-background-transparent .keyboard-key.default-key:latched { + border-color: #4b92e7; + background-color: #3584e4; + color: #ffffff; +} + +/* Enter Key */ +.bms-popup-background-dark .keyboard-key.enter-key, +.bms-popup-background-transparent .keyboard-key.enter-key { + color: #ffffff; + background-color: #428ce6; +} + +.bms-popup-background-dark .keyboard-key.enter-key:hover, +.bms-popup-background-transparent .keyboard-key.enter-key:hover { + background-color: #5497e8; +} + +.bms-popup-background-dark .keyboard-key.enter-key:active, +.bms-popup-background-transparent .keyboard-key.enter-key:active { + background-color: #629fea; +} + +/* Shift Key Uppercase */ +.bms-popup-background-dark .keyboard-key.shift-key-uppercase, +.bms-popup-background-transparent .keyboard-key.shift-key-uppercase { + background-color: rgba(255, 255, 255, 0.35); + color: #1e1e1e; +} + +.bms-popup-background-dark .keyboard-key.shift-key-uppercase:hover, +.bms-popup-background-transparent .keyboard-key.shift-key-uppercase:hover { + background-color: rgba(255, 255, 255, 0.45); +} + +.bms-popup-background-light .keyboard-subkeys { + -arrow-background-color: rgba(240, 240, 240, 0.98); + -arrow-border-color: rgba(0, 0, 0, 0.1); +} + +/* Base Keys */ +.bms-popup-background-light .keyboard-key, +.bms-popup-background-light .keyboard-subkeys .keyboard-key { + color: #1a1a1a; + background-color: rgba(0, 0, 0, 0.07); + border-color: rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.08); +} + +/* Interactive States */ +.bms-popup-background-light .keyboard-key:hover, +.bms-popup-background-light .keyboard-subkeys .keyboard-key:hover, +.bms-popup-background-light .keyboard-key:focus:hover, +.bms-popup-background-light .keyboard-subkeys .keyboard-key:focus:hover { + background-color: rgba(0, 0, 0, 0.18) !important; + color: #000000; +} + +.bms-popup-background-light .keyboard-key:active, +.bms-popup-background-light .keyboard-subkeys .keyboard-key:active, +.bms-popup-background-light .keyboard-key:focus:active, +.bms-popup-background-light .keyboard-subkeys .keyboard-key:focus:active { + background-color: rgba(0, 0, 0, 0.16) !important; + color: #000000; +} + +.bms-popup-background-light .keyboard-key:checked, +.bms-popup-background-light .keyboard-subkeys .keyboard-key:checked { + background-color: rgba(0, 0, 0, 0.12) !important; + box-shadow: inset 0 0 0 2px rgba(53, 132, 228, 0.6); + color: #000000; +} + +.bms-popup-background-light .keyboard-key:focus, +.bms-popup-background-light .keyboard-subkeys .keyboard-key:focus { + background-color: rgba(0, 0, 0, 0.07) !important; + box-shadow: none; + color: #1a1a1a; +} + +.bms-popup-background-light .keyboard-key:grayed { + background-color: rgba(0, 0, 0, 0.03); + color: rgba(0, 0, 0, 0.4); + border-color: transparent; +} + +/* Modifier & Function Keys */ +.bms-popup-background-light .keyboard-key.default-key { + color: #2c2c2c; + background-color: rgba(0, 0, 0, 0.11); +} + +.bms-popup-background-light .keyboard-key.default-key:hover { + background-color: rgba(0, 0, 0, 0.18); +} + +.bms-popup-background-light .keyboard-key.default-key:active { + background-color: rgba(0, 0, 0, 0.16); +} + +.bms-popup-background-light .keyboard-key.default-key:checked { + background-color: rgba(0, 0, 0, 0.12); +} + +.bms-popup-background-light .keyboard-key.default-key:latched { + border-color: #3584e4; + background-color: #3584e4; + color: #ffffff; +} + +/* Enter Key */ +.bms-popup-background-light .keyboard-key.enter-key { + color: #ffffff; + background-color: #3584e4; +} + +.bms-popup-background-light .keyboard-key.enter-key:hover { + background-color: #4b92e7; +} + +.bms-popup-background-light .keyboard-key.enter-key:active { + background-color: #2871cc; +} + +/* Shift Key Uppercase */ +.bms-popup-background-light .keyboard-key.shift-key-uppercase { + background-color: rgba(0, 0, 0, 0.22); + color: #000000; +} + +.bms-popup-background-light .keyboard-key.shift-key-uppercase:hover { + background-color: rgba(0, 0, 0, 0.28); +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/dark.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/dark.css new file mode 100644 index 0000000..460794e --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/dark.css @@ -0,0 +1,258 @@ +.bms-popup-background-dark .message:second-in-stack, +.bms-popup-surface-dark .message:second-in-stack { + background: rgba(255, 255, 255, 0.05) !important; + box-shadow: 0 1px 1px 0 transparent; +} + +.bms-popup-background-dark .message:lower-in-stack, +.bms-popup-surface-dark .message:lower-in-stack { + background: rgba(255, 255, 255, 0.02) !important; + box-shadow: none; +} + +.bms-popup-background-dark .message-media-control, +.bms-popup-surface-dark .message-media-control { + background-color: transparent; +} + +.bms-popup-background-dark .message-media-control:hover, +.bms-popup-surface-dark .message-media-control:hover, +.bms-popup-background-dark .message-expand-button:hover, +.bms-popup-surface-dark .message-expand-button:hover, +.bms-popup-background-dark .switcher-list .item-box:hover, +.bms-popup-surface-dark .switcher-list .item-box:hover { + background-color: rgba(255, 255, 255, 0.20) !important; +} + +.bms-popup-background-dark .message-media-control:active, +.bms-popup-surface-dark .message-media-control:active, +.bms-popup-background-dark .message-expand-button:active, +.bms-popup-surface-dark .message-expand-button:active, +.bms-popup-background-dark .switcher-list .item-box:active, +.bms-popup-surface-dark .switcher-list .item-box:active { + background-color: rgba(255, 255, 255, 0.24) !important; +} + +.bms-popup-background-dark .message-media-control:focus, +.bms-popup-background-dark .message-media-control:checked, +.bms-popup-surface-dark .message-media-control:focus, +.bms-popup-surface-dark .message-media-control:checked, +.bms-popup-background-dark .message-expand-button:focus, +.bms-popup-background-dark .message-expand-button:checked, +.bms-popup-surface-dark .message-expand-button:focus, +.bms-popup-surface-dark .message-expand-button:checked, +.bms-popup-background-dark .message-notification-group StButton:focus, +.bms-popup-background-dark .message-notification-group StButton:checked, +.bms-popup-surface-dark .message-notification-group StButton:focus, +.bms-popup-surface-dark .message-notification-group StButton:checked { + background-color: rgba(255, 255, 255, 0.13) !important; +} + +.bms-popup-background-dark .message-list-controls .message-list-clear-button { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.08) !important; +} + +.bms-popup-background-dark .message-list-controls .message-list-clear-button:hover, +.bms-popup-background-dark .message-list-controls .message-list-clear-button:focus { + background-color: rgba(255, 255, 255, 0.13) !important; +} + +.bms-popup-background-dark .message-list-controls .message-list-clear-button:active { + background-color: rgba(255, 255, 255, 0.18) !important; +} + +.bms-popup-background-dark .modal-dialog .button:insensitive, +.bms-popup-background-dark .modal-dialog .modal-dialog-button-box .modal-dialog-button:insensitive { + background-color: rgba(255, 255, 255, 0.08) !important; +} + +.bms-popup-background-dark .quick-toggle, +.bms-popup-background-dark .quick-toggle-has-menu .quick-toggle-menu-button, +.bms-popup-background-dark .notification-button { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.11) !important; + border-color: rgba(255, 255, 255, 0.08); +} + +.bms-popup-background-dark .quick-settings .icon-button, +.bms-popup-background-dark .quick-settings-system-item .button, +.bms-popup-background-dark .quick-settings-system-item .power-item { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.08) !important; + border-color: rgba(255, 255, 255, 0.06); + box-shadow: none; +} + +.bms-popup-background-dark .quick-toggle:hover, +.bms-popup-background-dark .quick-toggle-has-menu .quick-toggle-menu-button:hover, +.bms-popup-background-dark .notification-button:hover { + background-color: rgba(255, 255, 255, 0.18) !important; +} + +.bms-popup-background-dark .quick-settings .icon-button:hover, +.bms-popup-background-dark .quick-settings .icon-button:focus, +.bms-popup-background-dark .quick-settings-system-item .button:hover, +.bms-popup-background-dark .quick-settings-system-item .button:focus, +.bms-popup-background-dark .quick-settings-system-item .power-item:hover, +.bms-popup-background-dark .quick-settings-system-item .power-item:focus { + background-color: rgba(255, 255, 255, 0.13) !important; +} + +.bms-popup-background-dark .quick-settings .icon-button:active, +.bms-popup-background-dark .quick-settings-system-item .button:active, +.bms-popup-background-dark .quick-settings-system-item .power-item:active { + background-color: rgba(255, 255, 255, 0.18) !important; +} + +.bms-popup-background-dark .calendar { + color: #ffffff; + background-color: transparent; + border-color: transparent; + box-shadow: none; +} + +.bms-popup-background-dark .datemenu-today-button { + background-color: transparent !important; + box-shadow: none; +} + +.bms-popup-background-dark .datemenu-today-button:hover, +.bms-popup-background-dark .datemenu-today-button:focus { + background-color: rgba(255, 255, 255, 0.08) !important; +} + +.bms-popup-background-dark .datemenu-today-button:active, +.bms-popup-background-dark .datemenu-today-button:checked { + background-color: rgba(255, 255, 255, 0.12) !important; +} + +.bms-popup-background-dark .datemenu-today-button StLabel, +.bms-popup-background-dark .datemenu-today-button .date-label { + color: #ffffff !important; +} + +.bms-popup-background-dark .datemenu-today-button .day-label { + color: rgba(255, 255, 255, 0.68) !important; +} + +.bms-popup-background-dark .events-button, +.bms-popup-background-dark .world-clocks-button, +.bms-popup-background-dark .weather-button { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.07) !important; + border-color: rgba(255, 255, 255, 0.05); + box-shadow: none; +} + +.bms-popup-background-dark .events-button:hover, +.bms-popup-background-dark .world-clocks-button:hover, +.bms-popup-background-dark .weather-button:hover { + background-color: rgba(255, 255, 255, 0.12) !important; +} + +.bms-popup-background-dark .calendar .calendar-month-header .calendar-month-label, +.bms-popup-background-dark .calendar .calendar-month-header .pager-button { + color: #ffffff !important; + background-color: transparent !important; + box-shadow: none; +} + +.bms-popup-background-dark .calendar .calendar-day-heading, +.bms-popup-background-dark .calendar .calendar-day { + color: #ffffff !important; + background-color: transparent !important; + box-shadow: none; +} + +.bms-popup-background-dark .calendar .calendar-day-heading { + color: rgba(255, 255, 255, 0.68) !important; +} + +.bms-popup-background-dark .calendar .calendar-day.calendar-weekend { + color: rgba(255, 255, 255, 0.68) !important; +} + +.bms-popup-background-dark .calendar .calendar-day.calendar-other-month, +.bms-popup-background-dark .calendar .calendar-day.calendar-other-month.calendar-weekend { + color: rgba(255, 255, 255, 0.5) !important; +} + +.bms-popup-background-dark .calendar-day:selected, +.bms-popup-background-dark .calendar-day:checked, +.bms-popup-background-dark .calendar-day.calendar-today { + color: #ffffff !important; + background-color: #3584e4 !important; + color: -st-accent-fg-color !important; + background-color: -st-accent-color !important; +} + +.bms-popup-background-dark .calendar .calendar-day:hover, +.bms-popup-background-dark .calendar .calendar-month-header .pager-button:hover { + background-color: rgba(255, 255, 255, 0.1) !important; +} + +.bms-popup-background-dark .calendar-day:selected:hover, +.bms-popup-background-dark .calendar-day:checked:hover, +.bms-popup-background-dark .calendar-day.calendar-today:hover { + color: #ffffff !important; + background-color: #4990e7 !important; + color: -st-accent-fg-color !important; + background-color: st-lighten(-st-accent-color, 4%) !important; +} + +.bms-popup-background-dark .quick-toggle:checked, +.bms-popup-background-dark .quick-toggle-has-menu .quick-toggle:checked { + color: #ffffff; + background-color: #3584e4 !important; + color: -st-accent-fg-color; + background-color: -st-accent-color !important; +} + +.bms-popup-background-dark .quick-toggle-has-menu:checked .quick-toggle-menu-button, +.bms-popup-background-dark .quick-toggle-has-menu .quick-toggle-menu-button:checked { + color: #ffffff; + background-color: #4f96e8 !important; + color: -st-accent-fg-color; + background-color: st-mix(-st-accent-color, #ffffff, 85%) !important; +} + +.bms-popup-background-dark .quick-toggle:checked:hover, +.bms-popup-background-dark .quick-toggle-has-menu .quick-toggle:checked:hover { + color: #ffffff; + background-color: #4990e7 !important; + color: -st-accent-fg-color; + background-color: st-lighten(-st-accent-color, 4%) !important; +} + +.bms-popup-background-dark .quick-toggle-has-menu:checked .quick-toggle-menu-button:hover, +.bms-popup-background-dark .quick-toggle-has-menu .quick-toggle-menu-button:checked:hover { + color: #ffffff; + background-color: #62a0ea !important; + color: -st-accent-fg-color; + background-color: st-lighten(st-mix(-st-accent-color, #ffffff, 85%), 4%) !important; +} + +.bms-popup-background-dark .quick-toggle-has-menu:checked .quick-toggle-separator { + background-color: rgba(255, 255, 255, 0.3); + background-color: st-mix(-st-accent-fg-color, -st-accent-color, 30%); +} + +.bms-popup-background-dark StEntry { + background-color: rgba(255, 255, 255, 0.08) !important; + color: rgba(255, 255, 255, 0.7) !important; +} + +.bms-popup-background-dark StEntry:focus { + background-color: rgba(255, 255, 255, 0.13) !important; + color: #ffffff !important; +} + +.bms-popup-background-dark StEntry:insensitive { + background-color: rgba(255, 255, 255, 0.05) !important; + color: rgba(255, 255, 255, 0.5) !important; +} + +.bms-popup-background-dark StEntry StLabel.hint-text { + color: rgba(255, 255, 255, 0.5) !important; +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/light.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/light.css new file mode 100644 index 0000000..7c70ed3 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/light.css @@ -0,0 +1,335 @@ +.bms-popup-background-light .message:second-in-stack, +.bms-popup-surface-light .message:second-in-stack { + background: rgba(255, 255, 255, 0.54) !important; + box-shadow: 0 1px 1px 0 transparent; +} + +.bms-popup-background-light .message:lower-in-stack, +.bms-popup-surface-light .message:lower-in-stack { + background: rgba(255, 255, 255, 0.44) !important; + box-shadow: none; +} + +.bms-popup-background-light .message-media-control, +.bms-popup-surface-light .message-media-control { + background-color: transparent; +} + +.bms-popup-background-light .message-media-control:hover, +.bms-popup-surface-light .message-media-control:hover, +.bms-popup-background-light .message-expand-button:hover, +.bms-popup-surface-light .message-expand-button:hover, +.bms-popup-background-light .message-notification-group StButton:hover, +.bms-popup-surface-light .message-notification-group StButton:hover, +.bms-popup-background-light .switcher-list .item-box:hover, +.bms-popup-surface-light .switcher-list .item-box:hover { + background-color: rgba(0, 0, 0, 0.18) !important; +} + +.bms-popup-background-light .message-media-control:active, +.bms-popup-surface-light .message-media-control:active, +.bms-popup-background-light .message-expand-button:active, +.bms-popup-surface-light .message-expand-button:active, +.bms-popup-background-light .message-notification-group StButton:active, +.bms-popup-surface-light .message-notification-group StButton:active, +.bms-popup-background-light .switcher-list .item-box:active, +.bms-popup-surface-light .switcher-list .item-box:active { + background-color: rgba(0, 0, 0, 0.22) !important; +} + +.bms-popup-background-light .message-media-control:focus, +.bms-popup-background-light .message-media-control:checked, +.bms-popup-surface-light .message-media-control:focus, +.bms-popup-surface-light .message-media-control:checked, +.bms-popup-background-light .message-expand-button:focus, +.bms-popup-background-light .message-expand-button:checked, +.bms-popup-surface-light .message-expand-button:focus, +.bms-popup-surface-light .message-expand-button:checked, +.bms-popup-background-light .message-notification-group StButton:focus, +.bms-popup-background-light .message-notification-group StButton:checked, +.bms-popup-surface-light .message-notification-group StButton:focus, +.bms-popup-surface-light .message-notification-group StButton:checked { + background-color: rgba(0, 0, 0, 0.12) !important; +} + +.bms-popup-background-light .message .message-header, +.bms-popup-background-light .message .message-header .message-header-content .event-time { + color: rgba(34, 34, 38, 0.68); +} + +.bms-popup-background-light .message .message-header .message-header-content .message-source-title, +.bms-popup-background-light .message .message-box .message-content .message-title { + color: #222226; +} + +.bms-popup-background-light .message .message-header .message-source-icon { + color: rgba(34, 34, 38, 0.74); +} + +.bms-popup-background-light .message .message-header .message-expand-button, +.bms-popup-background-light .message .message-header .message-close-button, +.bms-popup-background-light .message-notification-group .message-collapse-button { + color: #222226; + background-color: rgba(0, 0, 0, 0.08) !important; +} + +.bms-popup-background-light .message .message-header .message-expand-button:hover, +.bms-popup-background-light .message .message-header .message-close-button:hover, +.bms-popup-background-light .message-notification-group .message-collapse-button:hover { + background-color: rgba(0, 0, 0, 0.12) !important; +} + +.bms-popup-background-light .message .message-header .message-expand-button:active, +.bms-popup-background-light .message .message-header .message-close-button:active, +.bms-popup-background-light .message-notification-group .message-collapse-button:active { + background-color: rgba(0, 0, 0, 0.16) !important; +} + +.bms-popup-background-light .message-list-controls .message-list-clear-button { + color: #222226; + background-color: rgba(0, 0, 0, 0.08) !important; +} + +.bms-popup-background-light .message-list-controls .message-list-clear-button:hover, +.bms-popup-background-light .message-list-controls .message-list-clear-button:focus { + background-color: rgba(0, 0, 0, 0.12) !important; +} + +.bms-popup-background-light .message-list-controls .message-list-clear-button:active { + background-color: rgba(0, 0, 0, 0.16) !important; +} + +.bms-popup-background-light .modal-dialog .button, +.bms-popup-background-light .modal-dialog .modal-dialog-button-box .modal-dialog-button { + color: #222226 !important; + background-color: rgba(255, 255, 255, 0.42) !important; + border-color: rgba(0, 0, 0, 0.08); +} + +.bms-popup-background-light .modal-dialog .button:hover, +.bms-popup-background-light .modal-dialog .button:focus, +.bms-popup-background-light .modal-dialog .modal-dialog-button-box .modal-dialog-button:hover, +.bms-popup-background-light .modal-dialog .modal-dialog-button-box .modal-dialog-button:focus { + color: #222226 !important; + background-color: rgba(255, 255, 255, 0.54) !important; +} + +.bms-popup-background-light .modal-dialog .button:active, +.bms-popup-background-light .modal-dialog .button:checked, +.bms-popup-background-light .modal-dialog .modal-dialog-button-box .modal-dialog-button:active, +.bms-popup-background-light .modal-dialog .modal-dialog-button-box .modal-dialog-button:checked { + color: #222226 !important; + background-color: rgba(0, 0, 0, 0.1) !important; +} + +.bms-popup-background-light .modal-dialog .button:insensitive, +.bms-popup-background-light .modal-dialog .modal-dialog-button-box .modal-dialog-button:insensitive { + color: rgba(34, 34, 38, 0.5) !important; + background-color: rgba(255, 255, 255, 0.28) !important; +} + +.bms-popup-background-light .quick-toggle, +.bms-popup-background-light .quick-toggle-has-menu .quick-toggle-menu-button, +.bms-popup-background-light .notification-button { + color: #222226; + background-color: rgba(255, 255, 255, 0.62) !important; + border-color: rgba(0, 0, 0, 0.08); +} + +.bms-popup-background-light .quick-settings .icon-button, +.bms-popup-background-light .quick-settings-system-item .button, +.bms-popup-background-light .quick-settings-system-item .power-item { + color: #222226; + background-color: rgba(0, 0, 0, 0.08) !important; + border-color: rgba(0, 0, 0, 0.05); + box-shadow: none; +} + +.bms-popup-background-light .quick-toggle:hover, +.bms-popup-background-light .quick-toggle-has-menu .quick-toggle-menu-button:hover, +.bms-popup-background-light .notification-button:hover { + background-color: rgba(255, 255, 255, 0.78) !important; +} + +.bms-popup-background-light .quick-settings .icon-button:hover, +.bms-popup-background-light .quick-settings .icon-button:focus, +.bms-popup-background-light .quick-settings-system-item .button:hover, +.bms-popup-background-light .quick-settings-system-item .button:focus, +.bms-popup-background-light .quick-settings-system-item .power-item:hover, +.bms-popup-background-light .quick-settings-system-item .power-item:focus { + background-color: rgba(0, 0, 0, 0.12) !important; +} + +.bms-popup-background-light .quick-settings .icon-button:active, +.bms-popup-background-light .quick-settings-system-item .button:active, +.bms-popup-background-light .quick-settings-system-item .power-item:active { + background-color: rgba(0, 0, 0, 0.16) !important; +} + +.bms-popup-background-light .calendar { + color: #222226; + background-color: transparent; + border-color: transparent; + box-shadow: none; +} + +.bms-popup-background-light .datemenu-today-button { + background-color: transparent !important; + box-shadow: none; +} + +.bms-popup-background-light .datemenu-today-button:hover, +.bms-popup-background-light .datemenu-today-button:focus { + background-color: rgba(0, 0, 0, 0.06) !important; +} + +.bms-popup-background-light .datemenu-today-button:active, +.bms-popup-background-light .datemenu-today-button:checked { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +.bms-popup-background-light .datemenu-today-button StLabel, +.bms-popup-background-light .datemenu-today-button .date-label { + color: #222226 !important; +} + +.bms-popup-background-light .datemenu-today-button .day-label { + color: rgba(34, 34, 38, 0.68) !important; +} + +.bms-popup-background-light .events-button, +.bms-popup-background-light .world-clocks-button, +.bms-popup-background-light .weather-button { + color: #222226; + background-color: rgba(255, 255, 255, 0.28) !important; + border-color: rgba(0, 0, 0, 0.04); + box-shadow: none; +} + +.bms-popup-background-light .events-button:hover, +.bms-popup-background-light .world-clocks-button:hover, +.bms-popup-background-light .weather-button:hover { + background-color: rgba(255, 255, 255, 0.4) !important; +} + +.bms-popup-background-light .calendar .calendar-month-header .calendar-month-label, +.bms-popup-background-light .calendar .calendar-month-header .pager-button { + color: #222226 !important; + background-color: transparent !important; + box-shadow: none; +} + +.bms-popup-background-light .calendar .calendar-day-heading, +.bms-popup-background-light .calendar .calendar-day { + color: #222226 !important; + background-color: transparent !important; + box-shadow: none; +} + +.bms-popup-background-light .calendar .calendar-day-heading { + color: rgba(34, 34, 38, 0.68) !important; +} + +.bms-popup-background-light .calendar .calendar-day.calendar-weekend { + color: rgba(34, 34, 38, 0.72) !important; +} + +.bms-popup-background-light .calendar .calendar-day.calendar-other-month, +.bms-popup-background-light .calendar .calendar-day.calendar-other-month.calendar-weekend { + color: rgba(34, 34, 38, 0.42) !important; +} + +.bms-popup-background-light .calendar .calendar-day:hover, +.bms-popup-background-light .calendar .calendar-day:focus, +.bms-popup-background-light .calendar .calendar-month-header .pager-button:hover, +.bms-popup-background-light .calendar .calendar-month-header .pager-button:focus { + background-color: rgba(0, 0, 0, 0.08) !important; +} + +.bms-popup-background-light .calendar .calendar-day:active, +.bms-popup-background-light .calendar .calendar-day:selected, +.bms-popup-background-light .calendar .calendar-day:checked { + color: #222226 !important; + background-color: rgba(0, 0, 0, 0.12) !important; +} + +.bms-popup-background-light .calendar .calendar-day:active:hover, +.bms-popup-background-light .calendar .calendar-day:selected:hover, +.bms-popup-background-light .calendar .calendar-day:checked:hover { + background-color: rgba(0, 0, 0, 0.16) !important; +} + +.bms-popup-background-light .calendar .calendar-day.calendar-today, +.bms-popup-background-light .calendar .calendar-day.calendar-today:selected, +.bms-popup-background-light .calendar .calendar-day.calendar-today:checked { + color: #ffffff !important; + background-color: #3584e4 !important; + color: -st-accent-fg-color !important; + background-color: -st-accent-color !important; +} + +.bms-popup-background-light .calendar .calendar-day.calendar-today:hover, +.bms-popup-background-light .calendar .calendar-day.calendar-today:selected:hover, +.bms-popup-background-light .calendar .calendar-day.calendar-today:checked:hover { + color: #ffffff !important; + background-color: #1c71d8 !important; + color: -st-accent-fg-color !important; + background-color: st-darken(-st-accent-color, 8%) !important; +} + +.bms-popup-background-light .quick-toggle:checked, +.bms-popup-background-light .quick-toggle-has-menu .quick-toggle:checked { + color: #ffffff; + background-color: #3584e4 !important; + color: -st-accent-fg-color; + background-color: -st-accent-color !important; +} + +.bms-popup-background-light .quick-toggle-has-menu:checked .quick-toggle-menu-button, +.bms-popup-background-light .quick-toggle-has-menu .quick-toggle-menu-button:checked { + color: #222226; + background-color: #4f96e8 !important; + background-color: st-mix(-st-accent-color, #ffffff, 85%) !important; +} + +.bms-popup-background-light .quick-toggle:checked:hover, +.bms-popup-background-light .quick-toggle-has-menu .quick-toggle:checked:hover { + color: #ffffff; + background-color: #1c71d8 !important; + color: -st-accent-fg-color; + background-color: st-darken(-st-accent-color, 4%) !important; +} + +.bms-popup-background-light .quick-toggle-has-menu:checked .quick-toggle-menu-button:hover, +.bms-popup-background-light .quick-toggle-has-menu:checked .quick-toggle-menu-button:focus, +.bms-popup-background-light .quick-toggle-has-menu .quick-toggle-menu-button:checked:hover, +.bms-popup-background-light .quick-toggle-has-menu .quick-toggle-menu-button:checked:focus { + color: #222226; + background-color: #62a0ea !important; + background-color: st-lighten(st-mix(-st-accent-color, #ffffff, 85%), 4%) !important; +} + +.bms-popup-background-light .quick-toggle-has-menu:checked .quick-toggle-separator { + background-color: rgba(255, 255, 255, 0.3); + background-color: st-mix(-st-accent-fg-color, -st-accent-color, 20%); +} + +.bms-popup-background-light StEntry { + color: #222226 !important; + background-color: rgba(255, 255, 255, 0.42) !important; + border-color: rgba(0, 0, 0, 0.08); +} + +.bms-popup-background-light StEntry:focus { + color: #222226 !important; + background-color: rgba(255, 255, 255, 0.54) !important; +} + +.bms-popup-background-light StEntry:insensitive { + color: rgba(34, 34, 38, 0.5) !important; + background-color: rgba(255, 255, 255, 0.28) !important; +} + +.bms-popup-background-light StEntry StLabel.hint-text { + color: rgba(34, 34, 38, 0.5) !important; +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/menu-items.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/menu-items.css new file mode 100644 index 0000000..ac06da4 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/menu-items.css @@ -0,0 +1,120 @@ +.bms-popup-background-transparent .quick-settings .quick-slider, +.bms-popup-background-transparent .quick-settings .quick-slider:hover, +.bms-popup-background-transparent .quick-settings .quick-slider:focus, +.bms-popup-background-transparent .quick-settings .quick-slider:active, +.bms-popup-background-transparent .quick-settings .quick-slider:checked, +.bms-popup-background-light .quick-settings .quick-slider, +.bms-popup-background-light .quick-settings .quick-slider:hover, +.bms-popup-background-light .quick-settings .quick-slider:focus, +.bms-popup-background-light .quick-settings .quick-slider:active, +.bms-popup-background-light .quick-settings .quick-slider:checked, +.bms-popup-background-dark .quick-settings .quick-slider, +.bms-popup-background-dark .quick-settings .quick-slider:hover, +.bms-popup-background-dark .quick-settings .quick-slider:focus, +.bms-popup-background-dark .quick-settings .quick-slider:active, +.bms-popup-background-dark .quick-settings .quick-slider:checked, +.bms-popup-background-transparent .quick-slider .slider-bin, +.bms-popup-background-transparent .quick-slider .slider-bin:hover, +.bms-popup-background-transparent .quick-slider .slider-bin:focus, +.bms-popup-background-transparent .quick-slider .icon-button, +.bms-popup-background-transparent .quick-slider .button, +.bms-popup-background-light .quick-slider .slider-bin, +.bms-popup-background-light .quick-slider .slider-bin:hover, +.bms-popup-background-light .quick-slider .slider-bin:focus, +.bms-popup-background-light .quick-slider .icon-button, +.bms-popup-background-light .quick-slider .button, +.bms-popup-background-dark .quick-slider .slider-bin, +.bms-popup-background-dark .quick-slider .slider-bin:hover, +.bms-popup-background-dark .quick-slider .slider-bin:focus, +.bms-popup-background-dark .quick-slider .icon-button, +.bms-popup-background-dark .quick-slider .button { + background-color: transparent !important; + border-color: transparent; + box-shadow: none; +} + +.bms-popup-background-transparent .quick-slider .icon-button:hover, +.bms-popup-background-transparent .quick-slider .icon-button:focus, +.bms-popup-background-transparent .quick-slider .button:hover, +.bms-popup-background-transparent .quick-slider .button:focus { + background-color: rgba(255, 255, 255, 0.08) !important; +} + +.bms-popup-background-transparent .quick-slider .icon-button:active, +.bms-popup-background-transparent .quick-slider .button:active { + background-color: rgba(255, 255, 255, 0.12) !important; +} + +.bms-popup-background-light .quick-slider .icon-button:hover, +.bms-popup-background-light .quick-slider .icon-button:focus, +.bms-popup-background-light .quick-slider .button:hover, +.bms-popup-background-light .quick-slider .button:focus { + background-color: rgba(0, 0, 0, 0.08) !important; +} + +.bms-popup-background-light .quick-slider .icon-button:active, +.bms-popup-background-light .quick-slider .button:active { + background-color: rgba(0, 0, 0, 0.12) !important; +} + +.bms-popup-background-dark .quick-slider .icon-button:hover, +.bms-popup-background-dark .quick-slider .icon-button:focus, +.bms-popup-background-dark .quick-slider .button:hover, +.bms-popup-background-dark .quick-slider .button:focus { + background-color: rgba(255, 255, 255, 0.12) !important; +} + +.bms-popup-background-dark .quick-slider .icon-button:active, +.bms-popup-background-dark .quick-slider .button:active { + background-color: rgba(255, 255, 255, 0.18) !important; +} + +.bms-popup-background-transparent .popup-menu-item:hover, +.bms-popup-background-transparent .popup-menu-item:focus, +.bms-popup-background-transparent .popup-menu-item:selected { + background-color: rgba(255, 255, 255, 0.08) !important; +} + +.bms-popup-background-transparent .popup-menu-item:active { + background-color: rgba(255, 255, 255, 0.12) !important; +} + +.bms-popup-background-transparent .popup-menu-item:checked, +.bms-popup-background-transparent .popup-menu-item:open { + background-color: transparent !important; +} + +.bms-popup-background-light .popup-menu-item, +.bms-popup-background-light .popup-menu-item:hover, +.bms-popup-background-light .popup-menu-item:focus, +.bms-popup-background-light .popup-menu-item:selected, +.bms-popup-background-light .popup-menu-item:active, +.bms-popup-background-light .popup-menu-item:checked { + color: #222226; +} + +.bms-popup-background-light .popup-menu-item:insensitive { + color: rgba(34, 34, 38, 0.5); +} + +.bms-popup-background-light .popup-menu-item:hover, +.bms-popup-background-light .popup-menu-item:focus { + background-color: rgba(0, 0, 0, 0.06) !important; +} + +.bms-popup-background-light .popup-menu-item:active, +.bms-popup-background-light .popup-menu-item:open, +.bms-popup-background-light .popup-menu-item:checked { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +.bms-popup-background-dark .popup-menu-item:hover, +.bms-popup-background-dark .popup-menu-item:focus { + background-color: rgba(255, 255, 255, 0.1) !important; +} + +.bms-popup-background-dark .popup-menu-item:active, +.bms-popup-background-dark .popup-menu-item:open, +.bms-popup-background-dark .popup-menu-item:checked { + background-color: rgba(255, 255, 255, 0.14) !important; +} diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/transparent.css b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/transparent.css new file mode 100644 index 0000000..460ff3d --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/styles/popup/transparent.css @@ -0,0 +1,262 @@ +.bms-popup-background-transparent .message:second-in-stack, +.bms-popup-surface-transparent .message:second-in-stack { + background: rgba(255, 255, 255, 0.05) !important; + box-shadow: 0 1px 1px 0 transparent; +} + +.bms-popup-background-transparent .message:lower-in-stack, +.bms-popup-surface-transparent .message:lower-in-stack { + background: rgba(255, 255, 255, 0.02) !important; + box-shadow: none; +} + +.bms-popup-background-transparent .message-media-control, +.bms-popup-surface-transparent .message-media-control { + background-color: transparent; +} + +.bms-popup-background-transparent .message-media-control:hover, +.bms-popup-surface-transparent .message-media-control:hover, +.bms-popup-background-transparent .message-expand-button:hover, +.bms-popup-surface-transparent .message-expand-button:hover, +.bms-popup-background-transparent .message-notification-group StButton:hover, +.bms-popup-surface-transparent .message-notification-group StButton:hover, +.bms-popup-background-transparent .switcher-list .item-box:hover, +.bms-popup-surface-transparent .switcher-list .item-box:hover { + background-color: rgba(255, 255, 255, 0.20) !important; +} + +.bms-popup-background-transparent .message-media-control:active, +.bms-popup-surface-transparent .message-media-control:active, +.bms-popup-background-transparent .message-expand-button:active, +.bms-popup-surface-transparent .message-expand-button:active, +.bms-popup-background-transparent .message-notification-group StButton:active, +.bms-popup-surface-transparent .message-notification-group StButton:active, +.bms-popup-background-transparent .switcher-list .item-box:active, +.bms-popup-surface-transparent .switcher-list .item-box:active { + background-color: rgba(255, 255, 255, 0.24) !important; +} + +.bms-popup-background-transparent .message-media-control:focus, +.bms-popup-background-transparent .message-media-control:checked, +.bms-popup-surface-transparent .message-media-control:focus, +.bms-popup-surface-transparent .message-media-control:checked, +.bms-popup-background-transparent .message-expand-button:focus, +.bms-popup-background-transparent .message-expand-button:checked, +.bms-popup-surface-transparent .message-expand-button:focus, +.bms-popup-surface-transparent .message-expand-button:checked, +.bms-popup-background-transparent .message-notification-group StButton:focus, +.bms-popup-background-transparent .message-notification-group StButton:checked, +.bms-popup-surface-transparent .message-notification-group StButton:focus, +.bms-popup-surface-transparent .message-notification-group StButton:checked { + background-color: rgba(255, 255, 255, 0.13) !important; +} + +.bms-popup-background-transparent .message-list-controls .message-list-clear-button { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.08) !important; +} + +.bms-popup-background-transparent .message-list-controls .message-list-clear-button:hover, +.bms-popup-background-transparent .message-list-controls .message-list-clear-button:focus { + background-color: rgba(255, 255, 255, 0.13) !important; +} + +.bms-popup-background-transparent .message-list-controls .message-list-clear-button:active { + background-color: rgba(255, 255, 255, 0.18) !important; +} + +.bms-popup-background-transparent .modal-dialog .button:insensitive, +.bms-popup-background-transparent .modal-dialog .modal-dialog-button-box .modal-dialog-button:insensitive { + background-color: rgba(255, 255, 255, 0.08) !important; +} + +.bms-popup-background-transparent .quick-toggle, +.bms-popup-background-transparent .quick-toggle-has-menu .quick-toggle-menu-button, +.bms-popup-background-transparent .notification-button { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.11) !important; + border-color: rgba(255, 255, 255, 0.08); +} + +.bms-popup-background-transparent .quick-settings .icon-button, +.bms-popup-background-transparent .quick-settings-system-item .button, +.bms-popup-background-transparent .quick-settings-system-item .power-item { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.08) !important; + border-color: rgba(255, 255, 255, 0.06); + box-shadow: none; +} + +.bms-popup-background-transparent .quick-toggle:hover, +.bms-popup-background-transparent .quick-toggle-has-menu .quick-toggle-menu-button:hover, +.bms-popup-background-transparent .notification-button:hover { + background-color: rgba(255, 255, 255, 0.18) !important; +} + +.bms-popup-background-transparent .quick-settings .icon-button:hover, +.bms-popup-background-transparent .quick-settings .icon-button:focus, +.bms-popup-background-transparent .quick-settings-system-item .button:hover, +.bms-popup-background-transparent .quick-settings-system-item .button:focus, +.bms-popup-background-transparent .quick-settings-system-item .power-item:hover, +.bms-popup-background-transparent .quick-settings-system-item .power-item:focus { + background-color: rgba(255, 255, 255, 0.13) !important; +} + +.bms-popup-background-transparent .quick-settings .icon-button:active, +.bms-popup-background-transparent .quick-settings-system-item .button:active, +.bms-popup-background-transparent .quick-settings-system-item .power-item:active { + background-color: rgba(255, 255, 255, 0.18) !important; +} + +.bms-popup-background-transparent .calendar { + color: #ffffff; + background-color: transparent; + border-color: transparent; + box-shadow: none; +} + +.bms-popup-background-transparent .datemenu-today-button { + background-color: transparent !important; + box-shadow: none; +} + +.bms-popup-background-transparent .datemenu-today-button:hover, +.bms-popup-background-transparent .datemenu-today-button:focus { + background-color: rgba(255, 255, 255, 0.08) !important; +} + +.bms-popup-background-transparent .datemenu-today-button:active, +.bms-popup-background-transparent .datemenu-today-button:checked { + background-color: rgba(255, 255, 255, 0.12) !important; +} + +.bms-popup-background-transparent .datemenu-today-button StLabel, +.bms-popup-background-transparent .datemenu-today-button .date-label { + color: #ffffff !important; +} + +.bms-popup-background-transparent .datemenu-today-button .day-label { + color: rgba(255, 255, 255, 0.68) !important; +} + +.bms-popup-background-transparent .events-button, +.bms-popup-background-transparent .world-clocks-button, +.bms-popup-background-transparent .weather-button { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.07) !important; + border-color: rgba(255, 255, 255, 0.05); + box-shadow: none; +} + +.bms-popup-background-transparent .events-button:hover, +.bms-popup-background-transparent .world-clocks-button:hover, +.bms-popup-background-transparent .weather-button:hover { + background-color: rgba(255, 255, 255, 0.12) !important; +} + +.bms-popup-background-transparent .calendar .calendar-month-header .calendar-month-label, +.bms-popup-background-transparent .calendar .calendar-month-header .pager-button { + color: #ffffff !important; + background-color: transparent !important; + box-shadow: none; +} + +.bms-popup-background-transparent .calendar .calendar-day-heading, +.bms-popup-background-transparent .calendar .calendar-day { + color: #ffffff !important; + background-color: transparent !important; + box-shadow: none; +} + +.bms-popup-background-transparent .calendar .calendar-day-heading { + color: rgba(255, 255, 255, 0.68) !important; +} + +.bms-popup-background-transparent .calendar .calendar-day.calendar-weekend { + color: rgba(255, 255, 255, 0.68) !important; +} + +.bms-popup-background-transparent .calendar .calendar-day.calendar-other-month, +.bms-popup-background-transparent .calendar .calendar-day.calendar-other-month.calendar-weekend { + color: rgba(255, 255, 255, 0.5) !important; +} + +.bms-popup-background-transparent .calendar-day:selected, +.bms-popup-background-transparent .calendar-day:checked, +.bms-popup-background-transparent .calendar-day.calendar-today { + color: #ffffff !important; + background-color: #3584e4 !important; + color: -st-accent-fg-color !important; + background-color: -st-accent-color !important; +} + +.bms-popup-background-transparent .calendar .calendar-day:hover, +.bms-popup-background-transparent .calendar .calendar-month-header .pager-button:hover { + background-color: rgba(255, 255, 255, 0.1) !important; +} + +.bms-popup-background-transparent .calendar-day:selected:hover, +.bms-popup-background-transparent .calendar-day:checked:hover, +.bms-popup-background-transparent .calendar-day.calendar-today:hover { + color: #ffffff !important; + background-color: #4990e7 !important; + color: -st-accent-fg-color !important; + background-color: st-lighten(-st-accent-color, 4%) !important; +} + +.bms-popup-background-transparent .quick-toggle:checked, +.bms-popup-background-transparent .quick-toggle-has-menu .quick-toggle:checked { + color: #ffffff; + background-color: #3584e4 !important; + color: -st-accent-fg-color; + background-color: -st-accent-color !important; +} + +.bms-popup-background-transparent .quick-toggle-has-menu:checked .quick-toggle-menu-button, +.bms-popup-background-transparent .quick-toggle-has-menu .quick-toggle-menu-button:checked { + color: #ffffff; + background-color: #4f96e8 !important; + color: -st-accent-fg-color; + background-color: st-mix(-st-accent-color, #ffffff, 85%) !important; +} + +.bms-popup-background-transparent .quick-toggle:checked:hover, +.bms-popup-background-transparent .quick-toggle-has-menu .quick-toggle:checked:hover { + color: #ffffff; + background-color: #4990e7 !important; + color: -st-accent-fg-color; + background-color: st-lighten(-st-accent-color, 4%) !important; +} + +.bms-popup-background-transparent .quick-toggle-has-menu:checked .quick-toggle-menu-button:hover, +.bms-popup-background-transparent .quick-toggle-has-menu .quick-toggle-menu-button:checked:hover { + color: #ffffff; + background-color: #62a0ea !important; + color: -st-accent-fg-color; + background-color: st-lighten(st-mix(-st-accent-color, #ffffff, 85%), 4%) !important; +} + +.bms-popup-background-transparent .quick-toggle-has-menu:checked .quick-toggle-separator { + background-color: rgba(255, 255, 255, 0.3); + background-color: st-mix(-st-accent-fg-color, -st-accent-color, 30%); +} + +.bms-popup-background-transparent StEntry { + background-color: rgba(255, 255, 255, 0.08) !important; + color: rgba(255, 255, 255, 0.7) !important; +} + +.bms-popup-background-transparent StEntry:focus { + background-color: rgba(255, 255, 255, 0.13) !important; + color: #ffffff !important; +} + +.bms-popup-background-transparent StEntry:insensitive { + background-color: rgba(255, 255, 255, 0.05) !important; + color: rgba(255, 255, 255, 0.5) !important; +} + +.bms-popup-background-transparent StEntry StLabel.hint-text { + color: rgba(255, 255, 255, 0.5) !important; +} \ 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 index b61e530..f8c3312 100644 --- 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 @@ -1,573 +1,10 @@ -/*** 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 +@import url("styles/panel.css"); +@import url("styles/dash.css"); +@import url("styles/popup/base.css"); +@import url("styles/popup/transparent.css"); +@import url("styles/popup/light.css"); +@import url("styles/popup/dark.css"); +@import url("styles/popup/menu-items.css"); +@import url("styles/overview.css"); +@import url("styles/appfolders.css"); +@import url("styles/panel-light-text.css"); 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 index e7b57fa..2774271 100644 --- 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 @@ -9,7 +9,7 @@ Applications blur 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. +To get the best results possible, although with reduced performances, you can choose the option “No artifact” in the “Other → Artifact handling” tab. center @@ -118,7 +118,7 @@ To get the best results possible, although with reduced performances, you can ch - external-link-symbolic + adw-external-link-symbolic center link.open-gnome-rounded-blur @@ -203,6 +203,21 @@ This may cause some latency or performance issues. + + + Unblur when Fullscreen + Forces the blur to be removed when a window is in fullscreen mode. + unblur_when_fullscreen + + + + + center + + + + + Enable all by default 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 index e95f606..e7bfbe4 100644 --- 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 @@ -117,7 +117,7 @@ - external-link-symbolic + adw-external-link-symbolic center link.open-gnome-rounded-blur 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 index e136e38..2e00846 100644 --- 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 @@ -120,9 +120,8 @@ - Hack level - 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. + Artifact handling + Controls how aggressively dynamic blur is repainted. The “No artifact” option disables clipped redraws globally and can reduce GNOME Shell performance. hack_level @@ -200,9 +199,9 @@ The “No artifact” option will entirely disable clipped redraws in GNOME shel - High performances + High performance Default No artifact - \ 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 index eb9df61..cd11c0b 100644 --- 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 @@ -117,7 +117,7 @@ - external-link-symbolic + adw-external-link-symbolic center link.open-gnome-rounded-blur @@ -174,8 +174,8 @@ Recommended unless you want to customize your GNOME theme. - Disable when a window is near - Disables the transparency of the panel when a window is near it. + Override background dynamically + Override the background of the panel and apply certain effect when a window is near it. override_background_dynamically @@ -185,6 +185,52 @@ Recommended unless you want to customize your GNOME theme. + + + + When window is near: + Blur on Window Proximity: Blur only when a window is near the panel and transparent when it is not. +Background on Window Proximity: Solid color background when a window is near the panel and blur when it is not + override_background_dynamically_mode + + + + center + override_background_dynamically_mode_model + + + + + + + + Gradient background + Apply a gradient effect to the panel background. + gradient_panel + + + + center + + + + + + + + Gradient direction + Change the direction of the gradient background. + gradient_panel_mode + + + + center + gradient_panel_mode_model + + + + + @@ -252,6 +298,20 @@ Recommended unless you want to customize your GNOME theme. + + + Blur on Window Proximity + Background on Window Proximity + + + + + + Top + Bottom + + + 0 100 diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/popup.ui b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/popup.ui new file mode 100644 index 0000000..ec8853c --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/ui/popup.ui @@ -0,0 +1,288 @@ + + + + + + 0 + 100 + 1 + + + + 0.0 + 1.0 + 0.01 + + + + 0 + 150 + 1 + + + + 0 + 150 + 1 + + + + 0 + 150 + 1 + + + + 0 + 150 + 1 + + + + 0 + 150 + 1 + + + + 0 + 150 + 1 + + + + 0 + 150 + 1 + + + + + Transparent + Light + Dark + Automatic + + + -- cgit v1.3