diff --git a/resources/ui/applications.ui b/resources/ui/applications.ui
index 0b4b83ca..54b0a02b 100644
--- a/resources/ui/applications.ui
+++ b/resources/ui/applications.ui
@@ -27,7 +27,7 @@ To get the best results possible, make sure to choose the option “No artifact
+
+
+ 0
+ 50
+ 1
+
\ No newline at end of file
diff --git a/resources/ui/panel.ui b/resources/ui/panel.ui
index 4e14b004..f7a40e0d 100644
--- a/resources/ui/panel.ui
+++ b/resources/ui/panel.ui
@@ -36,21 +36,6 @@
-
-
- Disable in overview
- Disables the blur from the panel when entering the overview.
- unblur_in_overview
-
-
-
-
- center
-
-
-
-
-
Force light text
@@ -104,6 +89,21 @@ Recommended unless you want to customize your GNOME theme.
+
+
+
+ Disable in overview
+ Disables the blur from the panel when entering the overview.
+ unblur_in_overview
+
+
+
+
+ center
+
+
+
+
diff --git a/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml b/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml
index 2ae8267d..1e237e7b 100644
--- a/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml
+++ b/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml
@@ -1,11 +1,12 @@
-
+
30
- Global sigma (gaussian blur radius) to use
+ Global gaussian sigma to use
@@ -56,7 +57,8 @@
-
+
true
@@ -70,7 +72,7 @@
30
- Sigma (gaussian blur radius) to use for the blur effect
+ Gaussian sigma to use for the blur effect
@@ -100,7 +102,8 @@
-
+
true
@@ -114,7 +117,7 @@
30
- Sigma (gaussian blur radius) to use for the blur effect
+ Gaussian sigma to use for the blur effect
@@ -144,7 +147,8 @@
-
+
true
@@ -158,7 +162,7 @@
30
- Sigma (gaussian blur radius) to use for the blur effect
+ Gaussian sigma to use for the blur effect
@@ -213,7 +217,8 @@
-
+
false
@@ -227,7 +232,7 @@
30
- Sigma (gaussian blur radius) to use for the blur effect
+ Gaussian sigma to use for the blur effect
@@ -269,10 +274,16 @@
false
Boolean, whether to disable blur from this component when opening the overview or not
+
+
+ 12
+ Radius for the corner rounding effect
+
-
+
false
@@ -286,7 +297,7 @@
30
- Sigma (gaussian blur radius) to use for the blur effect
+ Gaussian sigma to use for the blur effect
@@ -336,7 +347,8 @@
-
+
true
@@ -350,7 +362,7 @@
30
- Sigma (gaussian blur radius) to use for the blur effect
+ Gaussian sigma to use for the blur effect
@@ -375,7 +387,8 @@
-
+
true
@@ -389,7 +402,7 @@
30
- Sigma (gaussian blur radius) to use for the blur effect
+ Gaussian sigma to use for the blur effect
@@ -414,7 +427,8 @@
-
+
true
@@ -428,7 +442,7 @@
30
- Sigma (gaussian blur radius) to use for the blur effect
+ Gaussian sigma to use for the blur effect
@@ -453,7 +467,8 @@
-
+
false
@@ -462,7 +477,8 @@
-
+
true
diff --git a/src/components/dash_to_dock.js b/src/components/dash_to_dock.js
index 3c56588e..80f42319 100644
--- a/src/components/dash_to_dock.js
+++ b/src/components/dash_to_dock.js
@@ -1,9 +1,12 @@
import St from 'gi://St';
import Shell from 'gi://Shell';
+import Meta from 'gi://Meta';
+import Mtk from 'gi://Mtk';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
const Signals = imports.signals;
import { PaintSignals } from '../effects/paint_signals.js';
+import { BlurEffect } from '../effects/blur_effect.js';
const DASH_STYLES = [
"transparent-dash",
@@ -12,72 +15,192 @@ const DASH_STYLES = [
];
+// An helper function to find the monitor in which an actor is situated,
+/// there might be a pre-existing function in GLib already
+function find_monitor_for(actor) {
+ let extents = actor.get_transformed_extents();
+ let rect = new Mtk.Rectangle({
+ x: extents.get_x(),
+ y: extents.get_y(),
+ width: extents.get_width(),
+ height: extents.get_height(),
+ });
+
+ let index = global.display.get_monitor_index_for_rect(rect);
+
+ return Main.layoutManager.monitors[index];
+}
+
+
/// This type of object is created for every dash found, and talks to the main
/// DashBlur thanks to signals.
///
/// This allows to dynamically track the created dashes for each screen.
class DashInfos {
- constructor(dash_blur, dash, background_parent, effect, settings) {
+ constructor(dash_blur, dash, dash_container, dash_background, background, background_parent, effect) {
// the parent DashBlur object, to communicate
this.dash_blur = dash_blur;
+ this.dash_container = dash_container;
// the blurred dash
this.dash = dash;
+ this.dash_background = dash_background;
this.background_parent = background_parent;
+ this.background = background;
this.effect = effect;
- this.settings = settings;
+ this.settings = dash_blur.settings;
this.old_style = this.dash._background.style;
dash_blur.connections.connect(dash_blur, 'remove-dashes', () => {
this._log("removing blur from dash");
this.dash.get_parent().remove_child(this.background_parent);
- this.dash._background.style = this.old_style;
-
- DASH_STYLES.forEach(
- style => this.dash.remove_style_class_name(style)
- );
+ this.remove_style();
});
dash_blur.connections.connect(dash_blur, 'update-sigma', () => {
- this.effect.sigma = this.dash_blur.sigma;
+ if (this.dash_blur.is_static) {
+ this.dash_blur.update_size();
+ this.effect.radius = 2 * this.dash_blur.sigma * this.effect.scale;
+ } else
+ this.effect.sigma = this.dash_blur.sigma * this.effect.scale;
});
dash_blur.connections.connect(dash_blur, 'update-brightness', () => {
this.effect.brightness = this.dash_blur.brightness;
});
- dash_blur.connections.connect(dash_blur, 'override-background', () => {
- this.dash._background.style = null;
+ dash_blur.connections.connect(dash_blur, 'update-corner-radius', () => {
+ if (this.dash_blur.is_static) {
+ let monitor = find_monitor_for(this.dash);
+ let corner_radius = this.dash_blur.corner_radius * monitor.geometry_scale;
+ this.effect.corner_radius = Math.min(
+ corner_radius, this.effect.width / 2, this.effect.height / 2
+ );
+ }
+ });
- DASH_STYLES.forEach(
- style => this.dash.remove_style_class_name(style)
- );
+ dash_blur.connections.connect(dash_blur, 'override-background', () => {
+ this.remove_style();
this.dash.set_style_class_name(
DASH_STYLES[this.settings.dash_to_dock.STYLE_DASH_TO_DOCK]
);
});
- dash_blur.connections.connect(dash_blur, 'reset-background', () => {
- this.dash._background.style = this.old_style;
-
- DASH_STYLES.forEach(
- style => this.dash.remove_style_class_name(style)
- );
- });
+ dash_blur.connections.connect(dash_blur, 'reset-background', () => this.remove_style());
dash_blur.connections.connect(dash_blur, 'show', () => {
- this.effect.sigma = this.dash_blur.sigma;
+ if (this.dash_blur.is_static)
+ this.background_parent.show();
+ else
+ this.effect.sigma = this.dash_blur.sigma * this.effect.scale;
});
dash_blur.connections.connect(dash_blur, 'hide', () => {
- this.effect.sigma = 0;
+ if (this.dash_blur.is_static)
+ this.background_parent.hide();
+ else
+ this.effect.sigma = 0;
+ });
+
+ dash_blur.connections.connect(dash_blur, 'update-wallpaper', () => {
+ if (this.dash_blur.is_static) {
+ let bg = Main.layoutManager._backgroundGroup.get_child_at_index(
+ Main.layoutManager.monitors.length
+ - find_monitor_for(this.dash).index - 1
+ );
+ if (bg && bg.get_content()) {
+ this.background.content.set({
+ background: bg.get_content().background
+ });
+ this._log('wallpaper updated');
+ } else {
+ this._warn("could not get background for dash-to-dock");
+ }
+ }
});
+
+ dash_blur.connections.connect(dash_blur, 'update-size', () => {
+ if (this.dash_blur.is_static) {
+ let [x, y] = this.get_dash_position(this.dash_container, this.dash_background);
+
+ this.background.x = -x;
+ this.background.y = -y;
+
+ this.effect.width = this.dash_background.width;
+ this.effect.height = this.dash_background.height;
+
+ this.dash_blur.set_corner_radius(this.dash_blur.corner_radius);
+
+ if (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 (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 (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 (dash_container.get_style_class_name().includes("right")) {
+ this.background.set_clip(x + this.dash.x + this.dash_background.x, y + this.dash.y + this.dash_background.y, this.dash_background.width, this.dash_background.height);
+ }
+ } else {
+ this.background.width = this.dash_background.width;
+ this.background.height = this.dash_background.height;
+
+ this.background.x = this.dash_background.x;
+ this.background.y = this.dash_background.y + this.dash.y;
+ }
+ });
+
+ dash_blur.connections.connect(dash_blur, 'change-blur-type', () => {
+ this.background_parent.remove_child(this.background);
+ if (this.effect.chained_effect)
+ this.effect.get_actor()?.remove_effect(this.effect.chained_effect);
+ this.effect.get_actor()?.remove_effect(this.effect);
+
+ let [background, effect] = this.dash_blur.add_blur(this.dash, this.dash_background, this.dash_container);
+ this.background = background;
+ this.effect = effect;
+ this.background_parent.add_child(this.background);
+ });
+ }
+
+ remove_style() {
+ this.dash._background.style = this.old_style;
+
+ DASH_STYLES.forEach(
+ style => this.dash.remove_style_class_name(style)
+ );
+ }
+
+ get_dash_position(dash_container, dash_background) {
+ var x, y;
+
+ let monitor = find_monitor_for(dash_container);
+ let dash_box = dash_container._slider.get_child();
+
+ if (dash_container.get_style_class_name().includes("top")) {
+ x = (monitor.width - dash_background.width) / 2;
+ y = dash_box.y;
+ } else if (dash_container.get_style_class_name().includes("bottom")) {
+ x = (monitor.width - dash_background.width) / 2;
+ y = monitor.height - dash_container.height;
+ } else if (dash_container.get_style_class_name().includes("left")) {
+ x = dash_box.x;
+ y = dash_container.y + (dash_container.height - dash_background.height) / 2 - dash_background.y;
+ } else if (dash_container.get_style_class_name().includes("right")) {
+ x = monitor.width - dash_container.width;
+ y = dash_container.y + (dash_container.height - dash_background.height) / 2 - dash_background.y;
+ }
+
+ return [x, y];
}
_log(str) {
if (this.settings.DEBUG)
console.log(`[Blur my Shell > dash] ${str}`);
}
+
+ _warn(str) {
+ console.warn(`[Blur my Shell > dash] ${str}`);
+ }
}
export const DashBlur = class DashBlur {
@@ -92,6 +215,8 @@ export const DashBlur = class DashBlur {
this.brightness = this.settings.dash_to_dock.CUSTOMIZE
? this.settings.dash_to_dock.BRIGHTNESS
: this.settings.BRIGHTNESS;
+ this.corner_radius = this.settings.dash_to_dock.CORNER_RADIUS;
+ this.is_static = this.settings.dash_to_dock.STATIC_BLUR;
this.enabled = false;
}
@@ -107,6 +232,9 @@ export const DashBlur = class DashBlur {
this.blur_existing_dashes();
this.connect_to_overview();
+ this.update_wallpaper();
+ this.update_size();
+
this.enabled = true;
}
@@ -143,13 +271,6 @@ export const DashBlur = class DashBlur {
// Blurs the dash and returns a `DashInfos` containing its information
blur_dash_from(dash, dash_container) {
- // the effect to be applied
- let effect = new Shell.BlurEffect({
- brightness: this.brightness,
- sigma: this.sigma,
- mode: Shell.BlurMode.BACKGROUND
- });
-
// dash background parent, not visible
let background_parent = new St.Widget({
name: 'dash-blurred-background-parent',
@@ -158,99 +279,179 @@ export const DashBlur = class DashBlur {
height: 0
});
- // dash background widget
- let background = new St.Widget({
- name: 'dash-blurred-background',
- style_class: 'dash-blurred-background',
- x: 0,
- y: dash_container._slider.y,
- width: dash.width,
- height: dash.height,
+ // finally blur the dash
+ let dash_background = dash.get_children().find(child => {
+ return child.get_style_class_name() === 'dash-background';
});
+ let [background, effect] = this.add_blur(dash, dash_background, dash_container);
+
+ this.update_wallpaper();
+ this.update_size();
+
// updates size and position on change
- this.connections.connect(dash_container._slider, 'notify::y', _ => {
- background.y = dash_container._slider.y;
- });
this.connections.connect(dash, 'notify::width', _ => {
- background.width = dash.width;
+ this.update_size();
});
this.connections.connect(dash, 'notify::height', _ => {
- background.height = dash.height;
+ this.update_size();
+ });
+ this.connections.connect(dash_container, 'notify::width', _ => {
+ this.update_size();
+ });
+ this.connections.connect(dash_container, 'notify::height', _ => {
+ this.update_size();
+ });
+ this.connections.connect(dash_container, 'notify::y', _ => {
+ this.update_wallpaper();
+ this.update_size();
+ });
+ this.connections.connect(dash_container, 'notify::x', _ => {
+ this.update_wallpaper();
+ this.update_size();
});
- // add the widget to the dash
- background.add_effect(effect);
background_parent.add_child(background);
dash.get_parent().insert_child_at_index(background_parent, 0);
- // 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("dash hack level 1");
- this.paint_signals.disconnect_all();
-
- let rp = () => {
- effect.queue_repaint();
- };
-
- dash._box.get_children().forEach((icon) => {
- try {
- let zone = icon.get_child_at_index(0);
-
- this.connections.connect(zone, [
- 'enter-event', 'leave-event', 'button-press-event'
- ], rp);
- } catch (e) {
- this._warn(`${e}, continuing`);
- }
- });
+ // create infos
+ let infos = new DashInfos(
+ this,
+ dash,
+ dash_container,
+ dash_background,
+ background,
+ background_parent,
+ effect
+ );
- this.connections.connect(dash._box, 'actor-added', (_, actor) => {
- try {
- let zone = actor.get_child_at_index(0);
+ // update the background
+ this.update_background();
- this.connections.connect(zone, [
- 'enter-event', 'leave-event', 'button-press-event'
- ], rp);
- } catch (e) {
- this._warn(`${e}, continuing`);
- }
- });
+ // returns infos
+ return infos;
+ }
- let show_apps = dash._showAppsIcon;
+ add_blur(dash, dash_background, dash_container) {
+ let monitor = find_monitor_for(dash);
- this.connections.connect(show_apps, [
- 'enter-event', 'leave-event', 'button-press-event'
- ], rp);
+ // dash background widget
+ let background = this.is_static
+ ? new Meta.BackgroundActor({
+ meta_display: global.display,
+ monitor: monitor.index,
+ })
+ : new St.Widget({
+ name: 'dash-blurred-background',
+ style_class: 'dash-blurred-background',
+ x: dash_background.x,
+ y: dash_background.y + dash.y,
+ width: dash_background.width,
+ height: dash_background.height,
+ });
- this.connections.connect(dash, 'leave-event', rp);
- } else if (this.settings.HACKS_LEVEL === 2) {
- this._log("dash hack level 2");
+ // the effect to be applied
+ let effect;
+ if (this.is_static) {
+ let corner_radius = this.corner_radius * monitor.geometry_scale;
+ corner_radius = Math.min(corner_radius, dash_background.width / 2, dash_background.height / 2);
+
+ effect = new BlurEffect({
+ radius: 2 * this.sigma * monitor.geometry_scale,
+ brightness: this.brightness,
+ width: dash_background.width,
+ height: dash_background.height,
+ corner_radius: corner_radius
+ });
- this.paint_signals.connect(background, effect);
+ // connect to every background change (even without changing image)
+ // FIXME this signal is fired very often, so we should find another one
+ // fired only when necessary (but that still catches all cases)
+ this.connections.connect(
+ Main.layoutManager._backgroundGroup,
+ 'notify',
+ _ => this.update_wallpaper()
+ );
} else {
- this.paint_signals.disconnect_all();
+ effect = new Shell.BlurEffect({
+ brightness: this.brightness,
+ sigma: this.sigma * monitor.geometry_scale,
+ mode: Shell.BlurMode.BACKGROUND
+ });
+
+ // 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("dash hack level 1");
+ this.paint_signals.disconnect_all();
+
+ let rp = () => {
+ effect.queue_repaint();
+ };
+
+ dash._box.get_children().forEach((icon) => {
+ try {
+ let zone = icon.get_child_at_index(0);
+
+ this.connections.connect(zone, [
+ 'enter-event', 'leave-event', 'button-press-event'
+ ], rp);
+ } catch (e) {
+ this._warn(`${e}, continuing`);
+ }
+ });
+
+ this.connections.connect(dash._box, 'actor-added', (_, actor) => {
+ try {
+ let zone = actor.get_child_at_index(0);
+
+ this.connections.connect(zone, [
+ 'enter-event', 'leave-event', 'button-press-event'
+ ], rp);
+ } catch (e) {
+ this._warn(`${e}, continuing`);
+ }
+ });
+
+ let show_apps = dash._showAppsIcon;
+
+ this.connections.connect(show_apps, [
+ 'enter-event', 'leave-event', 'button-press-event'
+ ], rp);
+
+ this.connections.connect(dash, 'leave-event', rp);
+ } else if (this.settings.HACKS_LEVEL === 2) {
+ this._log("dash hack level 2");
+
+ this.paint_signals.connect(background, effect);
+ } else {
+ this.paint_signals.disconnect_all();
+ }
}
- // create infos
- let infos = new DashInfos(
- this, dash, background_parent, effect, this.settings
- );
+ // store the scale in the effect in order to retrieve it in set_sigma
+ effect.scale = monitor.geometry_scale;
- // update the background
- this.update_background();
+ background.add_effect(effect);
- // returns infos
- return infos;
+ return [background, effect];
+ }
+
+ change_blur_type() {
+ this.is_static = this.settings.dash_to_dock.STATIC_BLUR;
+ this.emit('change-blur-type', true);
+
+ this.update_wallpaper();
+ this.update_background();
+ this.update_size();
}
/// Connect when overview if opened/closed to hide/show the blur accordingly
@@ -276,6 +477,15 @@ export const DashBlur = class DashBlur {
this.emit('reset-background', true);
}
+ update_wallpaper() {
+ if (this.is_static)
+ this.emit('update-wallpaper', true);
+ }
+
+ update_size() {
+ this.emit('update-size', true);
+ }
+
set_sigma(sigma) {
this.sigma = sigma;
this.emit('update-sigma', true);
@@ -286,6 +496,11 @@ export const DashBlur = class DashBlur {
this.emit('update-brightness', true);
}
+ set_corner_radius(radius) {
+ this.corner_radius = radius;
+ this.emit('update-corner-radius', true);
+ }
+
// not implemented for dynamic blur
set_color(c) { }
set_noise_amount(n) { }
diff --git a/src/components/panel.js b/src/components/panel.js
index b034a36e..ba587950 100644
--- a/src/components/panel.js
+++ b/src/components/panel.js
@@ -320,7 +320,7 @@ export const PanelBlur = class PanelBlur {
Main.layoutManager.monitors.length
- this.find_monitor_for(actors.widgets.panel).index - 1
);
- if (bg)
+ if (bg && bg.get_content())
actors.widgets.background.content.set({
background: bg.get_content().background
});
diff --git a/src/conveniences/keys.js b/src/conveniences/keys.js
index 115bb206..71a357c2 100644
--- a/src/conveniences/keys.js
+++ b/src/conveniences/keys.js
@@ -68,6 +68,7 @@ export const Keys = [
{ type: Type.B, name: "unblur-in-overview" },
{ type: Type.B, name: "override-background" },
{ type: Type.I, name: "style-dash-to-dock" },
+ { type: Type.I, name: "corner-radius" },
]
},
{
diff --git a/src/effects/blur_effect.glsl b/src/effects/blur_effect.glsl
new file mode 100644
index 00000000..567105db
--- /dev/null
+++ b/src/effects/blur_effect.glsl
@@ -0,0 +1,97 @@
+uniform sampler2D tex;
+uniform float sigma;
+uniform int dir;
+uniform float brightness;
+uniform float corner_radius;
+uniform float width;
+uniform float height;
+
+float circleBounds(vec2 p, vec2 center, float clip_radius) {
+ vec2 delta = p - center;
+ float dist_squared = dot(delta, delta);
+
+ float outer_radius = clip_radius + 0.5;
+ if (dist_squared >= (outer_radius * outer_radius))
+ return 0.0;
+
+ float inner_radius = clip_radius - 0.5;
+ if (dist_squared <= (inner_radius * inner_radius))
+ return 1.0;
+
+ return outer_radius - sqrt(dist_squared);
+}
+
+vec4 shapeCorner(vec4 pixel, vec2 p, vec2 center, float clip_radius) {
+ float alpha = circleBounds(p, center, clip_radius);
+ return vec4(pixel.rgb * alpha, min(alpha, pixel.a));
+}
+
+void main(void) {
+ vec2 uv = cogl_tex_coord_in[0].xy;
+ vec2 direction = vec2(dir, (1.0 - dir));
+
+ float pixel_step;
+ if (dir == 0)
+ pixel_step = 1.0 / height;
+ else
+ pixel_step = 1.0 / width;
+
+ vec3 gauss_coefficient;
+ gauss_coefficient.x = 1.0 / (sqrt(2.0 * 3.14159265) * sigma);
+ gauss_coefficient.y = exp(-0.5 / (sigma * sigma));
+ gauss_coefficient.z = gauss_coefficient.y * gauss_coefficient.y;
+
+ float gauss_coefficient_total = gauss_coefficient.x;
+
+ vec4 ret = texture2D(tex, uv) * gauss_coefficient.x;
+ gauss_coefficient.xy *= gauss_coefficient.yz;
+
+ int n_steps = int(ceil(1.5 * sigma)) * 2;
+
+ for (int i = 1; i <= n_steps; i += 2) {
+ float coefficient_subtotal = gauss_coefficient.x;
+ gauss_coefficient.xy *= gauss_coefficient.yz;
+ coefficient_subtotal += gauss_coefficient.x;
+
+ float gauss_ratio = gauss_coefficient.x / coefficient_subtotal;
+
+ float foffset = float(i) + gauss_ratio;
+ vec2 offset = direction * foffset * pixel_step;
+
+ ret += texture2D(tex, uv + offset) * coefficient_subtotal;
+ ret += texture2D(tex, uv - offset) * coefficient_subtotal;
+
+ gauss_coefficient_total += 2.0 * coefficient_subtotal;
+ gauss_coefficient.xy *= gauss_coefficient.yz;
+ }
+ vec4 outColor = ret / gauss_coefficient_total;
+
+ // apply brightness and rounding on the second pass (dir==0 comes last)
+ if (dir == 0) {
+ vec2 pos = uv * vec2(width, height);
+
+ // left side
+ if (pos.x < corner_radius) {
+ // top left corner
+ if (pos.y < corner_radius) {
+ outColor = shapeCorner(outColor, pos, vec2(corner_radius + 2., corner_radius + 2.), corner_radius);
+ // bottom left corner
+ } else if (pos.y > height - corner_radius) {
+ outColor = shapeCorner(outColor, pos, vec2(corner_radius + 2., height - corner_radius - 1.), corner_radius);
+ }
+ // right side
+ } else if (pos.x > width - corner_radius) {
+ // top right corner
+ if (pos.y < corner_radius) {
+ outColor = shapeCorner(outColor, pos, vec2(width - corner_radius - 1., corner_radius + 2.), corner_radius);
+ // bottom right corner
+ } else if (pos.y > height - corner_radius) {
+ outColor = shapeCorner(outColor, pos, vec2(width - corner_radius - 1., height - corner_radius - 1.), corner_radius);
+ }
+ }
+
+ outColor.rgb *= brightness;
+ }
+
+ cogl_color_out = outColor;
+}
\ No newline at end of file
diff --git a/src/effects/blur_effect.js b/src/effects/blur_effect.js
new file mode 100644
index 00000000..2bc385f0
--- /dev/null
+++ b/src/effects/blur_effect.js
@@ -0,0 +1,237 @@
+import GLib from 'gi://GLib';
+import GObject from 'gi://GObject';
+import Clutter from 'gi://Clutter';
+import Shell from 'gi://Shell';
+
+const SHADER_PATH = GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, 'blur_effect.glsl', GLib.UriFlags.NONE))[0];
+
+
+const get_shader_source = _ => {
+ try {
+ return Shell.get_file_contents_utf8_sync(SHADER_PATH);
+ } catch (e) {
+ console.warn(`[Blur my Shell] error loading shader from ${SHADER_PATH}: ${e}`);
+ return null;
+ }
+};
+
+export const BlurEffect = new GObject.registerClass({
+ GTypeName: "BlurEffect",
+ Properties: {
+ 'radius': GObject.ParamSpec.double(
+ `radius`,
+ `Radius`,
+ `Blur radius`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 2000.0,
+ 200.0,
+ ),
+ 'brightness': GObject.ParamSpec.double(
+ `brightness`,
+ `Brightness`,
+ `Blur brightness`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, 1.0,
+ 0.6,
+ ),
+ 'width': GObject.ParamSpec.double(
+ `width`,
+ `Width`,
+ `Width`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'height': GObject.ParamSpec.double(
+ `height`,
+ `Height`,
+ `Height`,
+ GObject.ParamFlags.READWRITE,
+ 0.0, Number.MAX_SAFE_INTEGER,
+ 0.0,
+ ),
+ 'corner_radius': GObject.ParamSpec.double(
+ `corner_radius`,
+ `Corner Radius`,
+ `Corner Radius`,
+ GObject.ParamFlags.READWRITE,
+ 0, Number.MAX_SAFE_INTEGER,
+ 0,
+ ),
+ 'direction': GObject.ParamSpec.int(
+ `direction`,
+ `Direction`,
+ `Direction`,
+ GObject.ParamFlags.READWRITE,
+ 0, 1,
+ 0,
+ ),
+ 'chained_effect': GObject.ParamSpec.object(
+ `chained_effect`,
+ `Chained Effect`,
+ `Chained Effect`,
+ GObject.ParamFlags.READABLE,
+ GObject.Object,
+ ),
+ }
+}, class BlurEffect extends Clutter.ShaderEffect {
+ constructor(params, settings) {
+ super(params);
+
+ this._sigma = null;
+ this._brightness = null;
+ this._width = null;
+ this._height = null;
+ this._corner_radius = null;
+
+ this._static = true;
+ this._settings = settings;
+
+ this._tex = null;
+
+ this._direction = 0;
+
+ this._chained_effect = null;
+
+ if (params.sigma)
+ this.sigma = params.sigma;
+ if (params.brightness)
+ this.brightness = params.brightness;
+ if (params.width)
+ this.width = params.width;
+ if (params.height)
+ this.height = params.height;
+ if (params.corner_radius)
+ this.corner_radius = params.corner_radius;
+ if (params.direction)
+ this.direction = params.direction;
+
+ // set shader source
+ this._source = get_shader_source();
+ if (this._source)
+ this.set_shader_source(this._source);
+ }
+
+ get radius() {
+ return this._radius;
+ }
+
+ set radius(value) {
+ if (this._radius !== value) {
+ this._radius = value;
+
+ // like Clutter, we use the assumption radius = 2*sigma
+ this.set_uniform_value('sigma', parseFloat(this._radius / 2 - 1e-6));
+
+ if (this._chained_effect) {
+ this._chained_effect.radius = value;
+ }
+ }
+ }
+
+ get brightness() {
+ return this._brightness;
+ }
+
+ set brightness(value) {
+ if (this._brightness !== value) {
+ this._brightness = value;
+
+ this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6));
+
+ if (this._chained_effect) {
+ this._chained_effect.brightness = value;
+ }
+ }
+ }
+
+ get width() {
+ return this._width;
+ }
+
+ set width(value) {
+ if (this._width !== value) {
+ this._width = value;
+
+ this.set_uniform_value('width', parseFloat(this._width - 1e-6));
+
+ if (this._chained_effect) {
+ this._chained_effect.width = value;
+ }
+ }
+ }
+
+ get height() {
+ return this._height;
+ }
+
+ set height(value) {
+ if (this._height !== value) {
+ this._height = value;
+
+ this.set_uniform_value('height', parseFloat(this._height - 1e-6));
+
+ if (this._chained_effect) {
+ this._chained_effect.height = value;
+ }
+ }
+ }
+
+ get corner_radius() {
+ return this._corner_radius;
+ }
+
+ set corner_radius(value) {
+ if (this._corner_radius !== value) {
+ this._corner_radius = value;
+
+ this.set_uniform_value('corner_radius', parseFloat(this._corner_radius - 1e-6));
+
+ if (this._chained_effect) {
+ this._chained_effect.corner_radius = value;
+ }
+ }
+ }
+
+ get direction() {
+ return this._direction;
+ }
+
+ set direction(value) {
+ if (this._direction !== value) {
+ this._direction = value;
+ }
+ }
+
+ get chained_effect() {
+ return this._chained_effect;
+ }
+
+ vfunc_set_actor(actor) {
+ super.vfunc_set_actor(actor);
+
+ if (this._direction == 0) {
+ this._chained_effect = new BlurEffect({
+ radius: this.radius,
+ brightness: this.brightness,
+ width: this.width,
+ height: this.height,
+ corner_radius: this.corner_radius,
+ direction: 1
+ });
+ actor.add_effect(this._chained_effect);
+ }
+ }
+
+ vfunc_paint_target(paint_node = null, paint_context = null) {
+ this.set_uniform_value("tex", 0);
+ this.set_uniform_value("dir", this._direction);
+
+ if (paint_node && paint_context)
+ super.vfunc_paint_target(paint_node, paint_context);
+ else if (paint_node)
+ super.vfunc_paint_target(paint_node);
+ else
+ super.vfunc_paint_target();
+ }
+});
\ No newline at end of file
diff --git a/src/extension.js b/src/extension.js
index fb933aa4..556f3722 100644
--- a/src/extension.js
+++ b/src/extension.js
@@ -364,11 +364,16 @@ export default class BlurMyShell extends Extension {
}
});
- // TODO implement static blur for dash
// static blur toggled on/off
this._settings.dash_to_dock.STATIC_BLUR_changed(() => {
- //if (this._settings.dash_to_dock.BLUR)
- // this._dash_to_dock_blur.change_blur_type();
+ if (this._settings.dash_to_dock.BLUR)
+ this._dash_to_dock_blur.change_blur_type();
+ });
+
+ // dash-to-dock corner radius changed
+ this._settings.dash_to_dock.CORNER_RADIUS_changed(() => {
+ if (this._settings.dash_to_dock.STATIC_BLUR)
+ this._dash_to_dock_blur.set_corner_radius(this._settings.dash_to_dock.CORNER_RADIUS);
});
// dash-to-dock override background toggled on/off
diff --git a/src/preferences/dash.js b/src/preferences/dash.js
index ef8d9ed2..3a42ff20 100644
--- a/src/preferences/dash.js
+++ b/src/preferences/dash.js
@@ -10,6 +10,8 @@ export const Dash = GObject.registerClass({
InternalChildren: [
'blur',
'customize',
+ 'static_blur',
+ 'corner_radius',
'override_background',
'style_dash_to_dock',
'unblur_in_overview'
@@ -24,6 +26,16 @@ export const Dash = GObject.registerClass({
'blur', this._blur, 'active',
Gio.SettingsBindFlags.DEFAULT
);
+ this.preferences.dash_to_dock.settings.bind(
+ 'static-blur',
+ this._static_blur, 'active',
+ Gio.SettingsBindFlags.DEFAULT
+ );
+ this.preferences.dash_to_dock.settings.bind(
+ 'corner-radius',
+ this._corner_radius, 'value',
+ Gio.SettingsBindFlags.DEFAULT
+ );
this.preferences.dash_to_dock.settings.bind(
'override-background',
this._override_background, 'enable-expansion',