[gnome] Fix extension locations
This commit is contained in:
@ -0,0 +1,261 @@
|
||||
import Shell from 'gi://Shell';
|
||||
import Clutter from 'gi://Clutter';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
|
||||
import { PaintSignals } from '../effects/paint_signals.js';
|
||||
const Tweener = imports.tweener.tweener;
|
||||
|
||||
const transparent = Clutter.Color.from_pixel(0x00000000);
|
||||
const FOLDER_DIALOG_ANIMATION_TIME = 200;
|
||||
|
||||
const DIALOGS_STYLES = [
|
||||
"appfolder-dialogs-transparent",
|
||||
"appfolder-dialogs-light",
|
||||
"appfolder-dialogs-dark"
|
||||
];
|
||||
|
||||
let original_zoomAndFadeIn = null;
|
||||
let original_zoomAndFadeOut = null;
|
||||
let sigma;
|
||||
let brightness;
|
||||
|
||||
let _zoomAndFadeIn = function () {
|
||||
let [sourceX, sourceY] =
|
||||
this._source.get_transformed_position();
|
||||
let [dialogX, dialogY] =
|
||||
this.child.get_transformed_position();
|
||||
|
||||
this.child.set({
|
||||
translation_x: sourceX - dialogX,
|
||||
translation_y: sourceY - dialogY,
|
||||
scale_x: this._source.width / this.child.width,
|
||||
scale_y: this._source.height / this.child.height,
|
||||
opacity: 0,
|
||||
});
|
||||
|
||||
this.set_background_color(transparent);
|
||||
|
||||
let blur_effect = this.get_effect("appfolder-blur");
|
||||
|
||||
blur_effect.sigma = 0;
|
||||
blur_effect.brightness = 1.0;
|
||||
Tweener.addTween(blur_effect,
|
||||
{
|
||||
sigma: sigma,
|
||||
brightness: brightness,
|
||||
time: FOLDER_DIALOG_ANIMATION_TIME / 1000,
|
||||
transition: 'easeOutQuad'
|
||||
}
|
||||
);
|
||||
|
||||
this.child.ease({
|
||||
translation_x: 0,
|
||||
translation_y: 0,
|
||||
scale_x: 1,
|
||||
scale_y: 1,
|
||||
opacity: 255,
|
||||
duration: FOLDER_DIALOG_ANIMATION_TIME,
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
});
|
||||
|
||||
this._needsZoomAndFade = false;
|
||||
|
||||
if (this._sourceMappedId === 0) {
|
||||
this._sourceMappedId = this._source.connect(
|
||||
'notify::mapped', this._zoomAndFadeOut.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
let _zoomAndFadeOut = function () {
|
||||
if (!this._isOpen)
|
||||
return;
|
||||
|
||||
if (!this._source.mapped) {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
let [sourceX, sourceY] =
|
||||
this._source.get_transformed_position();
|
||||
let [dialogX, dialogY] =
|
||||
this.child.get_transformed_position();
|
||||
|
||||
this.set_background_color(transparent);
|
||||
|
||||
let blur_effect = this.get_effect("appfolder-blur");
|
||||
Tweener.addTween(blur_effect,
|
||||
{
|
||||
sigma: 0,
|
||||
brightness: 1.0,
|
||||
time: FOLDER_DIALOG_ANIMATION_TIME / 1000,
|
||||
transition: 'easeInQuad'
|
||||
}
|
||||
);
|
||||
|
||||
this.child.ease({
|
||||
translation_x: sourceX - dialogX,
|
||||
translation_y: sourceY - dialogY,
|
||||
scale_x: this._source.width / this.child.width,
|
||||
scale_y: this._source.height / this.child.height,
|
||||
opacity: 0,
|
||||
duration: FOLDER_DIALOG_ANIMATION_TIME,
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
onComplete: () => {
|
||||
this.child.set({
|
||||
translation_x: 0,
|
||||
translation_y: 0,
|
||||
scale_x: 1,
|
||||
scale_y: 1,
|
||||
opacity: 255,
|
||||
});
|
||||
this.hide();
|
||||
|
||||
this._popdownCallbacks.forEach(func => func());
|
||||
this._popdownCallbacks = [];
|
||||
},
|
||||
});
|
||||
|
||||
this._needsZoomAndFade = false;
|
||||
};
|
||||
|
||||
|
||||
export const AppFoldersBlur = class AppFoldersBlur {
|
||||
constructor(connections, settings, _) {
|
||||
this.connections = connections;
|
||||
this.paint_signals = new PaintSignals(connections);
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._log("blurring appfolders");
|
||||
|
||||
brightness = this.settings.appfolder.CUSTOMIZE
|
||||
? this.settings.appfolder.BRIGHTNESS
|
||||
: this.settings.BRIGHTNESS;
|
||||
sigma = this.settings.appfolder.CUSTOMIZE
|
||||
? this.settings.appfolder.SIGMA
|
||||
: this.settings.SIGMA;
|
||||
|
||||
let appDisplay = Main.overview._overview.controls._appDisplay;
|
||||
|
||||
if (appDisplay._folderIcons.length > 0) {
|
||||
this.blur_appfolders();
|
||||
}
|
||||
|
||||
this.connections.connect(
|
||||
appDisplay, 'view-loaded', this.blur_appfolders.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
blur_appfolders() {
|
||||
let appDisplay = Main.overview._overview.controls._appDisplay;
|
||||
|
||||
if (this.settings.HACKS_LEVEL === 1 || this.settings.HACKS_LEVEL === 2)
|
||||
this._log(`appfolders hack level ${this.settings.HACKS_LEVEL}`);
|
||||
|
||||
appDisplay._folderIcons.forEach(icon => {
|
||||
icon._ensureFolderDialog();
|
||||
|
||||
if (original_zoomAndFadeIn == null) {
|
||||
original_zoomAndFadeIn = icon._dialog._zoomAndFadeIn;
|
||||
}
|
||||
if (original_zoomAndFadeOut == null) {
|
||||
original_zoomAndFadeOut = icon._dialog._zoomAndFadeOut;
|
||||
}
|
||||
|
||||
let blur_effect = new Shell.BlurEffect({
|
||||
name: "appfolder-blur",
|
||||
sigma: sigma,
|
||||
brightness: brightness,
|
||||
mode: Shell.BlurMode.BACKGROUND
|
||||
});
|
||||
|
||||
icon._dialog.remove_effect_by_name("appfolder-blur");
|
||||
icon._dialog.add_effect(blur_effect);
|
||||
|
||||
DIALOGS_STYLES.forEach(
|
||||
style => icon._dialog._viewBox.remove_style_class_name(style)
|
||||
);
|
||||
|
||||
if (this.settings.appfolder.STYLE_DIALOGS > 0)
|
||||
icon._dialog._viewBox.add_style_class_name(
|
||||
DIALOGS_STYLES[this.settings.appfolder.STYLE_DIALOGS - 1]
|
||||
);
|
||||
|
||||
// finally override the builtin functions
|
||||
icon._dialog._zoomAndFadeIn = _zoomAndFadeIn;
|
||||
icon._dialog._zoomAndFadeOut = _zoomAndFadeOut;
|
||||
|
||||
|
||||
// HACK
|
||||
//
|
||||
//`Shell.BlurEffect` does not repaint when shadows are under it. [1]
|
||||
//
|
||||
// This does not entirely fix this bug (shadows caused by windows
|
||||
// still cause artifacts), but it prevents the shadows of the panel
|
||||
// buttons to cause artifacts on the panel itself
|
||||
//
|
||||
// [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857
|
||||
|
||||
if (this.settings.HACKS_LEVEL === 1 || this.settings.HACKS_LEVEL === 2) {
|
||||
this.paint_signals.disconnect_all_for_actor(icon._dialog);
|
||||
this.paint_signals.connect(icon._dialog, blur_effect);
|
||||
} else {
|
||||
this.paint_signals.disconnect_all();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
set_sigma(s) {
|
||||
sigma = s;
|
||||
if (this.settings.appfolder.BLUR)
|
||||
this.blur_appfolders();
|
||||
}
|
||||
|
||||
set_brightness(b) {
|
||||
brightness = b;
|
||||
if (this.settings.appfolder.BLUR)
|
||||
this.blur_appfolders();
|
||||
}
|
||||
|
||||
// not implemented for dynamic blur
|
||||
set_color(c) { }
|
||||
set_noise_amount(n) { }
|
||||
set_noise_lightness(l) { }
|
||||
|
||||
disable() {
|
||||
this._log("removing blur from appfolders");
|
||||
|
||||
let appDisplay = Main.overview._overview.controls._appDisplay;
|
||||
|
||||
if (original_zoomAndFadeIn != null) {
|
||||
appDisplay._folderIcons.forEach(icon => {
|
||||
if (icon._dialog)
|
||||
icon._dialog._zoomAndFadeIn = original_zoomAndFadeIn;
|
||||
});
|
||||
}
|
||||
|
||||
if (original_zoomAndFadeOut != null) {
|
||||
appDisplay._folderIcons.forEach(icon => {
|
||||
if (icon._dialog)
|
||||
icon._dialog._zoomAndFadeOut = original_zoomAndFadeOut;
|
||||
});
|
||||
}
|
||||
|
||||
appDisplay._folderIcons.forEach(icon => {
|
||||
if (icon._dialog) {
|
||||
icon._dialog.remove_effect_by_name("appfolder-blur");
|
||||
DIALOGS_STYLES.forEach(
|
||||
s => icon._dialog._viewBox.remove_style_class_name(s)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
this.connections.disconnect_all();
|
||||
}
|
||||
|
||||
_log(str) {
|
||||
if (this.settings.DEBUG)
|
||||
console.log(`[Blur my Shell > appfolders] ${str}`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,548 @@
|
||||
import Shell from 'gi://Shell';
|
||||
import Clutter from 'gi://Clutter';
|
||||
import Meta from 'gi://Meta';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
|
||||
import { PaintSignals } from '../effects/paint_signals.js';
|
||||
import { ApplicationsService } from '../dbus/services.js';
|
||||
|
||||
|
||||
export const ApplicationsBlur = class ApplicationsBlur {
|
||||
constructor(connections, settings, _) {
|
||||
this.connections = connections;
|
||||
this.settings = settings;
|
||||
this.paint_signals = new PaintSignals(connections);
|
||||
|
||||
// stores every blurred window
|
||||
this.window_map = new Map();
|
||||
// stores every blur actor
|
||||
this.blur_actor_map = new Map();
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._log("blurring applications...");
|
||||
|
||||
// export dbus service for preferences
|
||||
this.service = new ApplicationsService;
|
||||
this.service.export();
|
||||
|
||||
// blur already existing windows
|
||||
this.update_all_windows();
|
||||
|
||||
// blur every new window
|
||||
this.connections.connect(
|
||||
global.display,
|
||||
'window-created',
|
||||
(_meta_display, meta_window) => {
|
||||
this._log("window created");
|
||||
|
||||
if (meta_window) {
|
||||
let window_actor = meta_window.get_compositor_private();
|
||||
this.track_new(window_actor, meta_window);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
this.connect_to_overview();
|
||||
}
|
||||
|
||||
/// Connect to the overview being opened/closed to force the blur being
|
||||
/// shown on every window of the workspaces viewer.
|
||||
connect_to_overview() {
|
||||
this.connections.disconnect_all_for(Main.overview);
|
||||
|
||||
if (this.settings.applications.BLUR_ON_OVERVIEW) {
|
||||
// when the overview is opened, show every window actors (which
|
||||
// allows the blur to be shown too)
|
||||
this.connections.connect(
|
||||
Main.overview, 'showing',
|
||||
_ => this.window_map.forEach((meta_window, _pid) => {
|
||||
let window_actor = meta_window.get_compositor_private();
|
||||
window_actor.show();
|
||||
})
|
||||
);
|
||||
|
||||
// when the overview is closed, hide every actor that is not on the
|
||||
// current workspace (to mimic the original behaviour)
|
||||
this.connections.connect(
|
||||
Main.overview, 'hidden',
|
||||
_ => {
|
||||
let active_workspace =
|
||||
global.workspace_manager.get_active_workspace();
|
||||
|
||||
this.window_map.forEach((meta_window, _pid) => {
|
||||
let window_actor = meta_window.get_compositor_private();
|
||||
|
||||
if (
|
||||
meta_window.get_workspace() !== active_workspace
|
||||
)
|
||||
window_actor.hide();
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate through all existing windows and add blur as needed.
|
||||
update_all_windows() {
|
||||
// remove all previously blurred windows, in the case where the
|
||||
// whitelist was changed
|
||||
this.window_map.forEach(((_meta_window, pid) => {
|
||||
this.remove_blur(pid);
|
||||
}));
|
||||
|
||||
for (
|
||||
let i = 0;
|
||||
i < global.workspace_manager.get_n_workspaces();
|
||||
++i
|
||||
) {
|
||||
let workspace = global.workspace_manager.get_workspace_by_index(i);
|
||||
let windows = workspace.list_windows();
|
||||
|
||||
windows.forEach(meta_window => {
|
||||
let window_actor = meta_window.get_compositor_private();
|
||||
|
||||
// disconnect previous signals
|
||||
this.connections.disconnect_all_for(window_actor);
|
||||
|
||||
this.track_new(window_actor, meta_window);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds the needed signals to every new tracked window, and adds blur if
|
||||
/// needed.
|
||||
track_new(window_actor, meta_window) {
|
||||
let pid = ("" + Math.random()).slice(2, 16);
|
||||
|
||||
window_actor['blur_provider_pid'] = pid;
|
||||
meta_window['blur_provider_pid'] = pid;
|
||||
|
||||
// remove the blur when the window is destroyed
|
||||
this.connections.connect(window_actor, 'destroy', window_actor => {
|
||||
let pid = window_actor.blur_provider_pid;
|
||||
if (this.blur_actor_map.has(pid)) {
|
||||
this.remove_blur(pid);
|
||||
}
|
||||
this.window_map.delete(pid);
|
||||
});
|
||||
|
||||
// update the blur when mutter-hint or wm-class is changed
|
||||
for (const prop of ['mutter-hints', 'wm-class']) {
|
||||
this.connections.connect(
|
||||
meta_window,
|
||||
`notify::${prop}`,
|
||||
_ => {
|
||||
let pid = meta_window.blur_provider_pid;
|
||||
this._log(`${prop} changed for pid ${pid}`);
|
||||
|
||||
let window_actor = meta_window.get_compositor_private();
|
||||
this.check_blur(pid, window_actor, meta_window);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// update the position and size when the window size changes
|
||||
this.connections.connect(meta_window, 'size-changed', () => {
|
||||
if (this.blur_actor_map.has(pid)) {
|
||||
let allocation = this.compute_allocation(meta_window);
|
||||
let blur_actor = this.blur_actor_map.get(pid);
|
||||
blur_actor.x = allocation.x;
|
||||
blur_actor.y = allocation.y;
|
||||
blur_actor.width = allocation.width;
|
||||
blur_actor.height = allocation.height;
|
||||
}
|
||||
});
|
||||
|
||||
this.check_blur(pid, window_actor, meta_window);
|
||||
}
|
||||
|
||||
/// Checks if the given actor needs to be blurred.
|
||||
///
|
||||
/// In order to be blurred, a window either:
|
||||
/// - is whitelisted in the user preferences if not enable-all
|
||||
/// - is not blacklisted if enable-all
|
||||
/// - has a correct mutter hint, set to `blur-provider=sigma_value`
|
||||
check_blur(pid, window_actor, meta_window) {
|
||||
let mutter_hint = meta_window.get_mutter_hints();
|
||||
let window_wm_class = meta_window.get_wm_class();
|
||||
|
||||
let enable_all = this.settings.applications.ENABLE_ALL;
|
||||
let whitelist = this.settings.applications.WHITELIST;
|
||||
let blacklist = this.settings.applications.BLACKLIST;
|
||||
|
||||
this._log(`checking blur for ${pid}`);
|
||||
|
||||
// either the window is included in whitelist
|
||||
if (window_wm_class !== ""
|
||||
&& ((enable_all && !blacklist.includes(window_wm_class))
|
||||
|| (!enable_all && whitelist.includes(window_wm_class))
|
||||
)
|
||||
&& [
|
||||
Meta.FrameType.NORMAL,
|
||||
Meta.FrameType.DIALOG,
|
||||
Meta.FrameType.MODAL_DIALOG
|
||||
].includes(meta_window.get_frame_type())
|
||||
) {
|
||||
this._log(`application ${pid} listed, blurring it`);
|
||||
|
||||
// get blur effect parameters
|
||||
|
||||
let brightness, sigma;
|
||||
|
||||
if (this.settings.applications.CUSTOMIZE) {
|
||||
brightness = this.settings.applications.BRIGHTNESS;
|
||||
sigma = this.settings.applications.SIGMA;
|
||||
} else {
|
||||
brightness = this.settings.BRIGHTNESS;
|
||||
sigma = this.settings.SIGMA;
|
||||
}
|
||||
|
||||
this.update_blur(pid, window_actor, meta_window, brightness, sigma);
|
||||
}
|
||||
|
||||
// or blur is asked by window itself
|
||||
else if (
|
||||
mutter_hint != null &&
|
||||
mutter_hint.includes("blur-provider")
|
||||
) {
|
||||
this._log(`application ${pid} has hint ${mutter_hint}, parsing`);
|
||||
|
||||
// get blur effect parameters
|
||||
let [brightness, sigma] = this.parse_xprop(mutter_hint);
|
||||
|
||||
this.update_blur(pid, window_actor, meta_window, brightness, sigma);
|
||||
}
|
||||
|
||||
// remove blur if the mutter hint is no longer valid, and the window
|
||||
// is not explicitly whitelisted or un-blacklisted
|
||||
else if (this.blur_actor_map.has(pid)) {
|
||||
this.remove_blur(pid);
|
||||
}
|
||||
}
|
||||
|
||||
/// When given the xprop property, returns the brightness and sigma values
|
||||
/// matching. If one of the two values is invalid, or missing, then it uses
|
||||
/// default values.
|
||||
///
|
||||
/// An xprop property is valid if it is in one of the following formats:
|
||||
///
|
||||
/// blur-provider=sigma:60,brightness:0.9
|
||||
/// blur-provider=s:10,brightness:0.492
|
||||
/// blur-provider=b:1.0,s:16
|
||||
///
|
||||
/// Brightness is a floating-point between 0.0 and 1.0 included.
|
||||
/// Sigma is an integer between 0 and 999 included.
|
||||
///
|
||||
/// If sigma is set to 0, then the blur is removed.
|
||||
/// Setting "default" instead of the two values will make the
|
||||
/// extension use its default value.
|
||||
///
|
||||
/// Note that no space can be inserted.
|
||||
///
|
||||
parse_xprop(property) {
|
||||
// set brightness and sigma to default values
|
||||
let brightness, sigma;
|
||||
if (this.settings.applications.CUSTOMIZE) {
|
||||
brightness = this.settings.applications.BRIGHTNESS;
|
||||
sigma = this.settings.applications.SIGMA;
|
||||
} else {
|
||||
brightness = this.settings.BRIGHTNESS;
|
||||
sigma = this.settings.SIGMA;
|
||||
}
|
||||
|
||||
// get the argument of the property
|
||||
let arg = property.match("blur-provider=(.*)");
|
||||
this._log(`argument = ${arg}`);
|
||||
|
||||
// if argument is valid, parse it
|
||||
if (arg != null) {
|
||||
// verify if there is only one value: in this case, this is sigma
|
||||
let maybe_sigma = parseInt(arg[1]);
|
||||
|
||||
if (
|
||||
!isNaN(maybe_sigma) &&
|
||||
maybe_sigma >= 0 &&
|
||||
maybe_sigma <= 999
|
||||
) {
|
||||
sigma = maybe_sigma;
|
||||
} else {
|
||||
// perform pattern matching
|
||||
let res_b = arg[1].match("(brightness|b):(default|0?1?\.[0-9]*)");
|
||||
let res_s = arg[1].match("(sigma|s):(default|\\d{1,3})");
|
||||
|
||||
// if values are valid and not default, change them to the xprop one
|
||||
if (
|
||||
res_b != null && res_b[2] !== 'default'
|
||||
) {
|
||||
brightness = parseFloat(res_b[2]);
|
||||
}
|
||||
|
||||
if (
|
||||
res_s != null && res_s[2] !== 'default'
|
||||
) {
|
||||
sigma = parseInt(res_s[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._log(`brightness = ${brightness}, sigma = ${sigma}`);
|
||||
|
||||
return [brightness, sigma];
|
||||
}
|
||||
|
||||
/// Updates the blur on a window which needs to be blurred.
|
||||
update_blur(pid, window_actor, meta_window, brightness, sigma) {
|
||||
// the window is already blurred, update its blur effect
|
||||
if (this.blur_actor_map.has(pid)) {
|
||||
// window is already blurred, but sigma is null: remove the blur
|
||||
if (sigma === 0) {
|
||||
this.remove_blur(pid);
|
||||
}
|
||||
// window is already blurred and sigma is non-null: update it
|
||||
else {
|
||||
this.update_blur_effect(
|
||||
this.blur_actor_map.get(pid),
|
||||
brightness,
|
||||
sigma
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// the window is not blurred, and sigma is a non-null value: blur it
|
||||
else if (sigma !== 0) {
|
||||
// window is not blurred, blur it
|
||||
this.create_blur_effect(
|
||||
pid,
|
||||
window_actor,
|
||||
meta_window,
|
||||
brightness,
|
||||
sigma
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Add the blur effect to the window.
|
||||
create_blur_effect(pid, window_actor, meta_window, brightness, sigma) {
|
||||
let blur_effect = new Shell.BlurEffect({
|
||||
sigma: sigma,
|
||||
brightness: brightness,
|
||||
mode: Shell.BlurMode.BACKGROUND
|
||||
});
|
||||
|
||||
let blur_actor = this.create_blur_actor(
|
||||
meta_window,
|
||||
window_actor,
|
||||
blur_effect
|
||||
);
|
||||
|
||||
// if hacks are selected, force to repaint the window
|
||||
if (this.settings.HACKS_LEVEL === 1 || this.settings.HACKS_LEVEL === 2) {
|
||||
this._log("applications hack level 1 or 2");
|
||||
|
||||
this.paint_signals.disconnect_all();
|
||||
this.paint_signals.connect(blur_actor, blur_effect);
|
||||
} else {
|
||||
this.paint_signals.disconnect_all();
|
||||
}
|
||||
|
||||
// insert the blurred widget
|
||||
window_actor.insert_child_at_index(blur_actor, 0);
|
||||
|
||||
// make sure window is blurred in overview
|
||||
if (this.settings.applications.BLUR_ON_OVERVIEW)
|
||||
this.enforce_window_visibility_on_overview_for(window_actor);
|
||||
|
||||
// set the window actor's opacity
|
||||
this.set_window_opacity(window_actor, this.settings.applications.OPACITY);
|
||||
|
||||
this.connections.connect(
|
||||
window_actor,
|
||||
'notify::opacity',
|
||||
_ => this.set_window_opacity(window_actor, this.settings.applications.OPACITY)
|
||||
);
|
||||
|
||||
// register the blur actor/effect
|
||||
blur_actor['blur_provider_pid'] = pid;
|
||||
this.blur_actor_map.set(pid, blur_actor);
|
||||
this.window_map.set(pid, meta_window);
|
||||
|
||||
// hide the blur if window is invisible
|
||||
if (!window_actor.visible) {
|
||||
blur_actor.hide();
|
||||
}
|
||||
|
||||
// hide the blur if window becomes invisible
|
||||
this.connections.connect(
|
||||
window_actor,
|
||||
'notify::visible',
|
||||
window_actor => {
|
||||
let pid = window_actor.blur_provider_pid;
|
||||
if (window_actor.visible) {
|
||||
this.blur_actor_map.get(pid).show();
|
||||
} else {
|
||||
this.blur_actor_map.get(pid).hide();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// Makes sure that, when the overview is visible, the window actor will
|
||||
/// stay visible no matter what.
|
||||
/// We can instead hide the last child of the window actor, which will
|
||||
/// improve performances without hiding the blur effect.
|
||||
enforce_window_visibility_on_overview_for(window_actor) {
|
||||
this.connections.connect(window_actor, 'notify::visible',
|
||||
_ => {
|
||||
if (this.settings.applications.BLUR_ON_OVERVIEW) {
|
||||
if (
|
||||
!window_actor.visible
|
||||
&& Main.overview.visible
|
||||
) {
|
||||
window_actor.show();
|
||||
window_actor.get_last_child().hide();
|
||||
}
|
||||
else if (
|
||||
window_actor.visible
|
||||
)
|
||||
window_actor.get_last_child().show();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// Set the opacity of the window actor that sits on top of the blur effect.
|
||||
set_window_opacity(window_actor, opacity) {
|
||||
window_actor.get_children().forEach(child => {
|
||||
if (child.name !== "blur-actor" && child.opacity != opacity)
|
||||
child.opacity = opacity;
|
||||
});
|
||||
}
|
||||
|
||||
/// Compute the size and position for a blur actor.
|
||||
/// On wayland, it seems like we need to divide by the scale to get the
|
||||
/// correct result.
|
||||
compute_allocation(meta_window) {
|
||||
const is_wayland = Meta.is_wayland_compositor();
|
||||
const monitor_index = meta_window.get_monitor();
|
||||
// check if the window is using wayland, or xwayland/xorg for rendering
|
||||
const scale = is_wayland && meta_window.get_client_type() == 0
|
||||
? Main.layoutManager.monitors[monitor_index].geometry_scale
|
||||
: 1;
|
||||
|
||||
let frame = meta_window.get_frame_rect();
|
||||
let buffer = meta_window.get_buffer_rect();
|
||||
|
||||
return {
|
||||
x: (frame.x - buffer.x) / scale,
|
||||
y: (frame.y - buffer.y) / scale,
|
||||
width: frame.width / scale,
|
||||
height: frame.height / scale
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns a new already blurred widget, configured to follow the size and
|
||||
/// position of its target window.
|
||||
create_blur_actor(meta_window, window_actor, blur_effect) {
|
||||
// compute the size and position
|
||||
let allocation = this.compute_allocation(meta_window);
|
||||
|
||||
// create the actor
|
||||
let blur_actor = new Clutter.Actor({
|
||||
x: allocation.x,
|
||||
y: allocation.y,
|
||||
width: allocation.width,
|
||||
height: allocation.height
|
||||
});
|
||||
|
||||
// add the effect
|
||||
blur_actor.add_effect_with_name('blur-effect', blur_effect);
|
||||
|
||||
return blur_actor;
|
||||
}
|
||||
|
||||
/// Updates the blur effect by overwriting its sigma and brightness values.
|
||||
update_blur_effect(blur_actor, brightness, sigma) {
|
||||
let effect = blur_actor.get_effect('blur-effect');
|
||||
effect.sigma = sigma;
|
||||
effect.brightness = brightness;
|
||||
}
|
||||
|
||||
/// Removes the blur actor from the shell and unregister it.
|
||||
remove_blur(pid) {
|
||||
this._log(`removing blur for pid ${pid}`);
|
||||
|
||||
let meta_window = this.window_map.get(pid);
|
||||
// disconnect needed signals and untrack window
|
||||
if (meta_window) {
|
||||
this.window_map.delete(pid);
|
||||
let window_actor = meta_window.get_compositor_private();
|
||||
|
||||
let blur_actor = this.blur_actor_map.get(pid);
|
||||
if (blur_actor) {
|
||||
this.blur_actor_map.delete(pid);
|
||||
|
||||
if (window_actor) {
|
||||
// reset the opacity
|
||||
this.set_window_opacity(window_actor, 255);
|
||||
|
||||
// remove the blurred actor
|
||||
window_actor.remove_child(blur_actor);
|
||||
|
||||
// disconnect the signals about overview animation etc
|
||||
this.connections.disconnect_all_for(window_actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._log("removing blur from applications...");
|
||||
|
||||
this.service?.unexport();
|
||||
|
||||
this.blur_actor_map.forEach(((_blur_actor, pid) => {
|
||||
this.remove_blur(pid);
|
||||
}));
|
||||
|
||||
this.connections.disconnect_all();
|
||||
this.paint_signals.disconnect_all();
|
||||
}
|
||||
|
||||
/// Update the opacity of all window actors.
|
||||
set_opacity() {
|
||||
let opacity = this.settings.applications.OPACITY;
|
||||
|
||||
this.window_map.forEach(((meta_window, _pid) => {
|
||||
let window_actor = meta_window.get_compositor_private();
|
||||
this.set_window_opacity(window_actor, opacity);
|
||||
}));
|
||||
}
|
||||
|
||||
/// Updates each blur effect to use new sigma value
|
||||
// FIXME set_sigma and set_brightness are called when the extension is
|
||||
// loaded and when sigma is changed, and do not respect the per-app
|
||||
// xprop behaviour
|
||||
set_sigma(s) {
|
||||
this.blur_actor_map.forEach((actor, _) => {
|
||||
actor.get_effect('blur-effect').set_sigma(s);
|
||||
});
|
||||
}
|
||||
|
||||
/// Updates each blur effect to use new brightness value
|
||||
set_brightness(b) {
|
||||
this.blur_actor_map.forEach((actor, _) => {
|
||||
actor.get_effect('blur-effect').set_brightness(b);
|
||||
});
|
||||
}
|
||||
|
||||
// not implemented for dynamic blur
|
||||
set_color(c) { }
|
||||
set_noise_amount(n) { }
|
||||
set_noise_lightness(l) { }
|
||||
|
||||
_log(str) {
|
||||
if (this.settings.DEBUG)
|
||||
console.log(`[Blur my Shell > applications] ${str}`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,322 @@
|
||||
import St from 'gi://St';
|
||||
import Shell from 'gi://Shell';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
const Signals = imports.signals;
|
||||
|
||||
import { PaintSignals } from '../effects/paint_signals.js';
|
||||
|
||||
const DASH_STYLES = [
|
||||
"transparent-dash",
|
||||
"light-dash",
|
||||
"dark-dash"
|
||||
];
|
||||
|
||||
|
||||
/// This type of object is created for every dash found, and talks to the main
|
||||
/// DashBlur thanks to signals.
|
||||
///
|
||||
/// This allows to dynamically track the created dashes for each screen.
|
||||
class DashInfos {
|
||||
constructor(dash_blur, dash, background_parent, effect, settings) {
|
||||
// the parent DashBlur object, to communicate
|
||||
this.dash_blur = dash_blur;
|
||||
// the blurred dash
|
||||
this.dash = dash;
|
||||
this.background_parent = background_parent;
|
||||
this.effect = effect;
|
||||
this.settings = 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)
|
||||
);
|
||||
});
|
||||
|
||||
dash_blur.connections.connect(dash_blur, 'update-sigma', () => {
|
||||
this.effect.sigma = this.dash_blur.sigma;
|
||||
});
|
||||
|
||||
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_STYLES.forEach(
|
||||
style => this.dash.remove_style_class_name(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, 'show', () => {
|
||||
this.effect.sigma = this.dash_blur.sigma;
|
||||
});
|
||||
|
||||
dash_blur.connections.connect(dash_blur, 'hide', () => {
|
||||
this.effect.sigma = 0;
|
||||
});
|
||||
}
|
||||
|
||||
_log(str) {
|
||||
if (this.settings.DEBUG)
|
||||
console.log(`[Blur my Shell > dash] ${str}`);
|
||||
}
|
||||
}
|
||||
|
||||
export const DashBlur = class DashBlur {
|
||||
constructor(connections, settings, _) {
|
||||
this.dashes = [];
|
||||
this.connections = connections;
|
||||
this.settings = settings;
|
||||
this.paint_signals = new PaintSignals(connections);
|
||||
this.sigma = this.settings.dash_to_dock.CUSTOMIZE
|
||||
? this.settings.dash_to_dock.SIGMA
|
||||
: this.settings.SIGMA;
|
||||
this.brightness = this.settings.dash_to_dock.CUSTOMIZE
|
||||
? this.settings.dash_to_dock.BRIGHTNESS
|
||||
: this.settings.BRIGHTNESS;
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.connections.connect(Main.uiGroup, 'actor-added', (_, actor) => {
|
||||
if (
|
||||
(actor.get_name() === "dashtodockContainer") &&
|
||||
(actor.constructor.name === 'DashToDock')
|
||||
)
|
||||
this.try_blur(actor);
|
||||
});
|
||||
|
||||
this.blur_existing_dashes();
|
||||
this.connect_to_overview();
|
||||
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
// Finds all existing dashes on every monitor, and call `try_blur` on them
|
||||
// We cannot only blur `Main.overview.dash`, as there could be several
|
||||
blur_existing_dashes() {
|
||||
this._log("searching for dash");
|
||||
|
||||
// blur every dash found, filtered by name
|
||||
Main.uiGroup.get_children().filter((child) => {
|
||||
return (child.get_name() === "dashtodockContainer") &&
|
||||
(child.constructor.name === 'DashToDock');
|
||||
}).forEach(this.try_blur.bind(this));
|
||||
}
|
||||
|
||||
// Tries to blur the dash contained in the given actor
|
||||
try_blur(dash_container) {
|
||||
let dash_box = dash_container._slider.get_child();
|
||||
|
||||
// verify that we did not already blur that dash
|
||||
if (!dash_box.get_children().some((child) => {
|
||||
return child.get_name() === "dash-blurred-background-parent";
|
||||
})) {
|
||||
this._log("dash to dock found, blurring it");
|
||||
|
||||
// finally blur the dash
|
||||
let dash = dash_box.get_children().find(child => {
|
||||
return child.get_name() === 'dash';
|
||||
});
|
||||
|
||||
this.dashes.push(this.blur_dash_from(dash, dash_container));
|
||||
}
|
||||
}
|
||||
|
||||
// Blurs the dash and returns a `DashInfos` containing its information
|
||||
blur_dash_from(dash, dash_container) {
|
||||
// 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',
|
||||
style_class: 'dash-blurred-background-parent',
|
||||
width: 0,
|
||||
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,
|
||||
});
|
||||
|
||||
// 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.connections.connect(dash, 'notify::height', _ => {
|
||||
background.height = dash.height;
|
||||
});
|
||||
|
||||
// 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`);
|
||||
}
|
||||
});
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
// update the background
|
||||
this.update_background();
|
||||
|
||||
// returns infos
|
||||
return infos;
|
||||
}
|
||||
|
||||
/// Connect when overview if opened/closed to hide/show the blur accordingly
|
||||
connect_to_overview() {
|
||||
this.connections.disconnect_all_for(Main.overview);
|
||||
|
||||
if (this.settings.dash_to_dock.UNBLUR_IN_OVERVIEW) {
|
||||
this.connections.connect(
|
||||
Main.overview, 'showing', this.hide.bind(this)
|
||||
);
|
||||
this.connections.connect(
|
||||
Main.overview, 'hidden', this.show.bind(this)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/// Updates the background to either remove it or not, according to the
|
||||
/// user preferences.
|
||||
update_background() {
|
||||
if (this.settings.dash_to_dock.OVERRIDE_BACKGROUND)
|
||||
this.emit('override-background', true);
|
||||
else
|
||||
this.emit('reset-background', true);
|
||||
}
|
||||
|
||||
set_sigma(sigma) {
|
||||
this.sigma = sigma;
|
||||
this.emit('update-sigma', true);
|
||||
}
|
||||
|
||||
set_brightness(brightness) {
|
||||
this.brightness = brightness;
|
||||
this.emit('update-brightness', true);
|
||||
}
|
||||
|
||||
// not implemented for dynamic blur
|
||||
set_color(c) { }
|
||||
set_noise_amount(n) { }
|
||||
set_noise_lightness(l) { }
|
||||
|
||||
disable() {
|
||||
this._log("removing blur from dashes");
|
||||
|
||||
this.emit('remove-dashes', true);
|
||||
|
||||
this.dashes = [];
|
||||
this.connections.disconnect_all();
|
||||
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
show() {
|
||||
this.emit('show', true);
|
||||
}
|
||||
hide() {
|
||||
this.emit('hide', true);
|
||||
}
|
||||
|
||||
_log(str) {
|
||||
if (this.settings.DEBUG)
|
||||
console.log(`[Blur my Shell > dash manager] ${str}`);
|
||||
}
|
||||
|
||||
_warn(str) {
|
||||
console.warn(`[Blur my Shell > dash manager] ${str}`);
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(DashBlur.prototype);
|
||||
@ -0,0 +1,167 @@
|
||||
import St from 'gi://St';
|
||||
import Shell from 'gi://Shell';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
import * as Background from 'resource:///org/gnome/shell/ui/background.js';
|
||||
import { UnlockDialog } from 'resource:///org/gnome/shell/ui/unlockDialog.js';
|
||||
|
||||
let sigma;
|
||||
let brightness;
|
||||
let color;
|
||||
let noise;
|
||||
let lightness;
|
||||
|
||||
const original_createBackground =
|
||||
UnlockDialog.prototype._createBackground;
|
||||
const original_updateBackgroundEffects =
|
||||
UnlockDialog.prototype._updateBackgroundEffects;
|
||||
|
||||
|
||||
export const LockscreenBlur = class LockscreenBlur {
|
||||
constructor(connections, settings, effects_manager) {
|
||||
this.connections = connections;
|
||||
this.settings = settings;
|
||||
this.effects_manager = effects_manager;
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._log("blurring lockscreen");
|
||||
|
||||
brightness = this.settings.lockscreen.CUSTOMIZE
|
||||
? this.settings.lockscreen.BRIGHTNESS
|
||||
: this.settings.BRIGHTNESS;
|
||||
sigma = this.settings.lockscreen.CUSTOMIZE
|
||||
? this.settings.lockscreen.SIGMA
|
||||
: this.settings.SIGMA;
|
||||
color = this.settings.lockscreen.CUSTOMIZE
|
||||
? this.settings.lockscreen.COLOR
|
||||
: this.settings.COLOR;
|
||||
noise = this.settings.lockscreen.CUSTOMIZE
|
||||
? this.settings.lockscreen.NOISE_AMOUNT
|
||||
: this.settings.NOISE_AMOUNT;
|
||||
lightness = this.settings.lockscreen.CUSTOMIZE
|
||||
? this.settings.lockscreen.NOISE_LIGHTNESS
|
||||
: this.settings.NOISE_LIGHTNESS;
|
||||
|
||||
this.update_lockscreen();
|
||||
}
|
||||
|
||||
update_lockscreen() {
|
||||
UnlockDialog.prototype._createBackground =
|
||||
this._createBackground;
|
||||
UnlockDialog.prototype._updateBackgroundEffects =
|
||||
this._updateBackgroundEffects;
|
||||
}
|
||||
|
||||
_createBackground(monitorIndex) {
|
||||
let monitor = Main.layoutManager.monitors[monitorIndex];
|
||||
let widget = new St.Widget({
|
||||
style_class: "screen-shield-background",
|
||||
x: monitor.x,
|
||||
y: monitor.y,
|
||||
width: monitor.width,
|
||||
height: monitor.height,
|
||||
});
|
||||
|
||||
let blur_effect = new Shell.BlurEffect({
|
||||
name: 'blur',
|
||||
sigma: sigma,
|
||||
brightness: brightness
|
||||
});
|
||||
|
||||
// store the scale in the effect in order to retrieve later
|
||||
blur_effect.scale = monitor.geometry_scale;
|
||||
|
||||
let color_effect = global.blur_my_shell._lockscreen_blur.effects_manager.new_color_effect({
|
||||
name: 'color',
|
||||
color: color
|
||||
}, this.settings);
|
||||
|
||||
let noise_effect = global.blur_my_shell._lockscreen_blur.effects_manager.new_noise_effect({
|
||||
name: 'noise',
|
||||
noise: noise,
|
||||
lightness: lightness
|
||||
}, this.settings);
|
||||
|
||||
widget.add_effect(color_effect);
|
||||
widget.add_effect(noise_effect);
|
||||
widget.add_effect(blur_effect);
|
||||
|
||||
let bgManager = new Background.BackgroundManager({
|
||||
container: widget,
|
||||
monitorIndex,
|
||||
controlPosition: false,
|
||||
});
|
||||
|
||||
this._bgManagers.push(bgManager);
|
||||
|
||||
this._backgroundGroup.add_child(widget);
|
||||
}
|
||||
|
||||
_updateBackgroundEffects() {
|
||||
for (const widget of this._backgroundGroup) {
|
||||
const color_effect = widget.get_effect('color');
|
||||
const noise_effect = widget.get_effect('noise');
|
||||
const blur_effect = widget.get_effect('blur');
|
||||
|
||||
if (color_effect)
|
||||
color_effect.set({
|
||||
color: color
|
||||
});
|
||||
|
||||
if (noise_effect) {
|
||||
noise_effect.set({
|
||||
noise: noise,
|
||||
lightness: lightness,
|
||||
});
|
||||
}
|
||||
|
||||
if (blur_effect) {
|
||||
blur_effect.set({
|
||||
brightness: brightness,
|
||||
sigma: sigma * blur_effect.scale,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_sigma(s) {
|
||||
sigma = s;
|
||||
this.update_lockscreen();
|
||||
}
|
||||
|
||||
set_brightness(b) {
|
||||
brightness = b;
|
||||
this.update_lockscreen();
|
||||
}
|
||||
|
||||
set_color(c) {
|
||||
color = c;
|
||||
this.update_lockscreen();
|
||||
}
|
||||
|
||||
set_noise_amount(n) {
|
||||
noise = n;
|
||||
this.update_lockscreen();
|
||||
}
|
||||
|
||||
set_noise_lightness(l) {
|
||||
lightness = l;
|
||||
this.update_lockscreen();
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._log("removing blur from lockscreen");
|
||||
|
||||
UnlockDialog.prototype._createBackground =
|
||||
original_createBackground;
|
||||
UnlockDialog.prototype._updateBackgroundEffects =
|
||||
original_updateBackgroundEffects;
|
||||
|
||||
this.connections.disconnect_all();
|
||||
}
|
||||
|
||||
_log(str) {
|
||||
if (this.settings.DEBUG)
|
||||
console.log(`[Blur my Shell > lockscreen] ${str}`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,309 @@
|
||||
import Shell from 'gi://Shell';
|
||||
import Meta from 'gi://Meta';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
|
||||
import { WorkspaceAnimationController } from 'resource:///org/gnome/shell/ui/workspaceAnimation.js';
|
||||
const wac_proto = WorkspaceAnimationController.prototype;
|
||||
|
||||
const OVERVIEW_COMPONENTS_STYLE = [
|
||||
"overview-components-light",
|
||||
"overview-components-dark",
|
||||
"overview-components-transparent"
|
||||
];
|
||||
|
||||
|
||||
export const OverviewBlur = class OverviewBlur {
|
||||
constructor(connections, settings, effects_manager) {
|
||||
this.connections = connections;
|
||||
this.effects = [];
|
||||
this.settings = settings;
|
||||
this.effects_manager = effects_manager;
|
||||
this._workspace_switch_bg_actors = [];
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._log("blurring overview");
|
||||
|
||||
// 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._log("updated background");
|
||||
this.update_backgrounds();
|
||||
}
|
||||
);
|
||||
|
||||
// connect to monitors change
|
||||
this.connections.connect(
|
||||
Main.layoutManager,
|
||||
'monitors-changed',
|
||||
_ => {
|
||||
if (Main.screenShield && !Main.screenShield.locked) {
|
||||
this._log("changed monitors");
|
||||
this.update_backgrounds();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// add css class name for workspace-switch background
|
||||
Main.uiGroup.add_style_class_name("blurred-overview");
|
||||
|
||||
// add css class name to make components semi-transparent if wanted
|
||||
this.update_components_classname();
|
||||
|
||||
// update backgrounds when the component is enabled
|
||||
this.update_backgrounds();
|
||||
|
||||
|
||||
// part for the workspace animation switch
|
||||
|
||||
// make sure not to do this part if the extension was enabled prior, as
|
||||
// the functions would call themselves and cause infinite recursion
|
||||
if (!this.enabled) {
|
||||
// store original workspace switching methods for restoring them on
|
||||
// disable()
|
||||
this._original_PrepareSwitch = wac_proto._prepareWorkspaceSwitch;
|
||||
this._original_FinishSwitch = wac_proto._finishWorkspaceSwitch;
|
||||
|
||||
const w_m = global.workspace_manager;
|
||||
const outer_this = this;
|
||||
|
||||
// create a blurred background actor for each monitor during a
|
||||
// workspace switch
|
||||
wac_proto._prepareWorkspaceSwitch = function (...params) {
|
||||
outer_this._log("prepare workspace switch");
|
||||
outer_this._original_PrepareSwitch.apply(this, params);
|
||||
|
||||
// this permits to show the blur behind windows that are on
|
||||
// workspaces on the left and right
|
||||
if (
|
||||
outer_this.settings.applications.BLUR
|
||||
) {
|
||||
let ws_index = w_m.get_active_workspace_index();
|
||||
[ws_index - 1, ws_index + 1].forEach(
|
||||
i => w_m.get_workspace_by_index(i)?.list_windows().forEach(
|
||||
window => window.get_compositor_private().show()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Main.layoutManager.monitors.forEach(monitor => {
|
||||
if (
|
||||
!(
|
||||
Meta.prefs_get_workspaces_only_on_primary() &&
|
||||
(monitor !== Main.layoutManager.primaryMonitor)
|
||||
)
|
||||
) {
|
||||
const bg_actor = outer_this.create_background_actor(
|
||||
monitor, true
|
||||
);
|
||||
|
||||
Main.uiGroup.insert_child_above(
|
||||
bg_actor,
|
||||
global.window_group
|
||||
);
|
||||
|
||||
// store the actors so that we can delete them later
|
||||
outer_this._workspace_switch_bg_actors.push(bg_actor);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// remove the workspace-switch actors when the switch is done
|
||||
wac_proto._finishWorkspaceSwitch = function (...params) {
|
||||
outer_this._log("finish workspace switch");
|
||||
outer_this._original_FinishSwitch.apply(this, params);
|
||||
|
||||
// this hides windows that are not on the current workspace
|
||||
if (
|
||||
outer_this.settings.applications.BLUR
|
||||
)
|
||||
for (let i = 0; i < w_m.get_n_workspaces(); i++) {
|
||||
if (i != w_m.get_active_workspace_index())
|
||||
w_m.get_workspace_by_index(i)?.list_windows().forEach(
|
||||
window => window.get_compositor_private().hide()
|
||||
);
|
||||
}
|
||||
|
||||
outer_this.effects = outer_this.effects.filter(
|
||||
effects_group => !effects_group.is_transition
|
||||
);
|
||||
|
||||
outer_this._workspace_switch_bg_actors.forEach(actor => {
|
||||
actor.destroy();
|
||||
});
|
||||
outer_this._workspace_switch_bg_actors = [];
|
||||
};
|
||||
}
|
||||
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
update_backgrounds() {
|
||||
// remove every old background
|
||||
this.remove_background_actors();
|
||||
|
||||
// add new backgrounds
|
||||
Main.layoutManager.monitors.forEach(monitor => {
|
||||
const bg_actor = this.create_background_actor(monitor, false);
|
||||
|
||||
Main.layoutManager.overviewGroup.insert_child_at_index(
|
||||
bg_actor,
|
||||
monitor.index
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
create_background_actor(monitor, is_transition) {
|
||||
let bg_actor = new Meta.BackgroundActor({
|
||||
meta_display: global.display,
|
||||
monitor: monitor.index
|
||||
});
|
||||
let background_group = Main.layoutManager._backgroundGroup
|
||||
.get_children()
|
||||
.filter((child) => child instanceof Meta.BackgroundActor);
|
||||
let background =
|
||||
background_group[
|
||||
Main.layoutManager.monitors.length - monitor.index - 1
|
||||
];
|
||||
|
||||
if (!background) {
|
||||
this._warn("could not get background for overview");
|
||||
return bg_actor;
|
||||
}
|
||||
|
||||
bg_actor.content.set({
|
||||
background: background.get_content().background
|
||||
});
|
||||
|
||||
let blur_effect = new Shell.BlurEffect({
|
||||
brightness: this.settings.overview.CUSTOMIZE
|
||||
? this.settings.overview.BRIGHTNESS
|
||||
: this.settings.BRIGHTNESS,
|
||||
sigma: this.settings.overview.CUSTOMIZE
|
||||
? this.settings.overview.SIGMA
|
||||
: this.settings.SIGMA
|
||||
* monitor.geometry_scale,
|
||||
mode: Shell.BlurMode.ACTOR
|
||||
});
|
||||
|
||||
// store the scale in the effect in order to retrieve it in set_sigma
|
||||
blur_effect.scale = monitor.geometry_scale;
|
||||
|
||||
let color_effect = this.effects_manager.new_color_effect({
|
||||
color: this.settings.overview.CUSTOMIZE
|
||||
? this.settings.overview.COLOR
|
||||
: this.settings.COLOR
|
||||
}, this.settings);
|
||||
|
||||
let noise_effect = this.effects_manager.new_noise_effect({
|
||||
noise: this.settings.overview.CUSTOMIZE
|
||||
? this.settings.overview.NOISE_AMOUNT
|
||||
: this.settings.NOISE_AMOUNT,
|
||||
lightness: this.settings.overview.CUSTOMIZE
|
||||
? this.settings.overview.NOISE_LIGHTNESS
|
||||
: this.settings.NOISE_LIGHTNESS
|
||||
}, this.settings);
|
||||
|
||||
bg_actor.add_effect(color_effect);
|
||||
bg_actor.add_effect(noise_effect);
|
||||
bg_actor.add_effect(blur_effect);
|
||||
this.effects.push({ blur_effect, color_effect, noise_effect, is_transition });
|
||||
|
||||
bg_actor.set_x(monitor.x);
|
||||
bg_actor.set_y(monitor.y);
|
||||
|
||||
return bg_actor;
|
||||
}
|
||||
|
||||
/// Updates the classname to style overview components with semi-transparent
|
||||
/// backgrounds.
|
||||
update_components_classname() {
|
||||
OVERVIEW_COMPONENTS_STYLE.forEach(
|
||||
style => Main.uiGroup.remove_style_class_name(style)
|
||||
);
|
||||
|
||||
if (this.settings.overview.STYLE_COMPONENTS > 0)
|
||||
Main.uiGroup.add_style_class_name(
|
||||
OVERVIEW_COMPONENTS_STYLE[this.settings.overview.STYLE_COMPONENTS - 1]
|
||||
);
|
||||
}
|
||||
|
||||
set_sigma(s) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.blur_effect.sigma = s * effect.blur_effect.scale;
|
||||
});
|
||||
}
|
||||
|
||||
set_brightness(b) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.blur_effect.brightness = b;
|
||||
});
|
||||
}
|
||||
|
||||
set_color(c) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.color_effect.color = c;
|
||||
});
|
||||
}
|
||||
|
||||
set_noise_amount(n) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.noise_effect.noise = n;
|
||||
});
|
||||
}
|
||||
|
||||
set_noise_lightness(l) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.noise_effect.lightness = l;
|
||||
});
|
||||
}
|
||||
|
||||
remove_background_actors() {
|
||||
Main.layoutManager.overviewGroup.get_children().forEach(actor => {
|
||||
if (actor.constructor.name === 'Meta_BackgroundActor') {
|
||||
actor.get_effects().forEach(effect => {
|
||||
this.effects_manager.remove(effect);
|
||||
});
|
||||
Main.layoutManager.overviewGroup.remove_child(actor);
|
||||
actor.destroy();
|
||||
}
|
||||
});
|
||||
this.effects = [];
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._log("removing blur from overview");
|
||||
this.remove_background_actors();
|
||||
Main.uiGroup.remove_style_class_name("blurred-overview");
|
||||
OVERVIEW_COMPONENTS_STYLE.forEach(
|
||||
style => Main.uiGroup.remove_style_class_name(style)
|
||||
);
|
||||
|
||||
// make sure to absolutely not do this if the component was not enabled
|
||||
// prior, as this would cause infinite recursion
|
||||
if (this.enabled) {
|
||||
// restore original behavior
|
||||
if (this._original_PrepareSwitch)
|
||||
wac_proto._prepareWorkspaceSwitch = this._original_PrepareSwitch;
|
||||
if (this._original_FinishSwitch)
|
||||
wac_proto._finishWorkspaceSwitch = this._original_FinishSwitch;
|
||||
}
|
||||
|
||||
this.connections.disconnect_all();
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
_log(str) {
|
||||
if (this.settings.DEBUG)
|
||||
console.log(`[Blur my Shell > overview] ${str}`);
|
||||
}
|
||||
|
||||
_warn(str) {
|
||||
console.warn(`[Blur my Shell > overview] ${str}`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,695 @@
|
||||
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';
|
||||
|
||||
import { PaintSignals } from '../effects/paint_signals.js';
|
||||
|
||||
const DASH_TO_PANEL_UUID = 'dash-to-panel@jderose9.github.com';
|
||||
const PANEL_STYLES = [
|
||||
"transparent-panel",
|
||||
"light-panel",
|
||||
"dark-panel",
|
||||
"contrasted-panel"
|
||||
];
|
||||
|
||||
|
||||
export const PanelBlur = class PanelBlur {
|
||||
constructor(connections, settings, effects_manager) {
|
||||
this.connections = connections;
|
||||
this.window_signal_ids = new Map();
|
||||
this.settings = settings;
|
||||
this.effects_manager = effects_manager;
|
||||
this.actors_list = [];
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._log("blurring top panel");
|
||||
|
||||
// check for panels when Dash to Panel is activated
|
||||
this.connections.connect(
|
||||
Main.extensionManager,
|
||||
'extension-state-changed',
|
||||
(_, extension) => {
|
||||
if (extension.uuid === DASH_TO_PANEL_UUID
|
||||
&& extension.state === 1
|
||||
) {
|
||||
this.connections.connect(
|
||||
global.dashToPanel,
|
||||
'panels-created',
|
||||
_ => this.blur_dtp_panels()
|
||||
);
|
||||
|
||||
this.blur_existing_panels();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
this.blur_existing_panels();
|
||||
|
||||
// connect to overview being opened/closed, and dynamically show or not
|
||||
// the blur when a window is near a panel
|
||||
this.connect_to_windows_and_overview();
|
||||
|
||||
// connect to 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.actors_list.forEach(actors =>
|
||||
this.update_wallpaper(actors)
|
||||
)
|
||||
);
|
||||
|
||||
// connect to monitors change
|
||||
this.connections.connect(
|
||||
Main.layoutManager,
|
||||
'monitors-changed',
|
||||
_ => {
|
||||
if (Main.screenShield && !Main.screenShield.locked) {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._log("resetting...");
|
||||
|
||||
this.disable();
|
||||
setTimeout(_ => this.enable(), 1);
|
||||
}
|
||||
|
||||
/// Check for already existing panels and blur them if they are not already
|
||||
blur_existing_panels() {
|
||||
// check if dash-to-panel is present
|
||||
if (global.dashToPanel) {
|
||||
// blur already existing ones
|
||||
if (global.dashToPanel.panels)
|
||||
this.blur_dtp_panels();
|
||||
} else {
|
||||
// if no dash-to-panel, blur the main and only panel
|
||||
this.maybe_blur_panel(Main.panel);
|
||||
}
|
||||
}
|
||||
|
||||
blur_dtp_panels() {
|
||||
// FIXME when Dash to Panel changes its size, it seems it creates new
|
||||
// panels; but I can't get to delete old widgets
|
||||
|
||||
// blur every panel found
|
||||
global.dashToPanel.panels.forEach(p => {
|
||||
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.maybe_blur_panel(Main.panel);
|
||||
};
|
||||
|
||||
/// Blur a panel only if it is not already blurred (contained in the list)
|
||||
maybe_blur_panel(panel) {
|
||||
// check if the panel is contained in the list
|
||||
let actors = this.actors_list.find(
|
||||
actors => actors.widgets.panel == panel
|
||||
);
|
||||
|
||||
if (!actors)
|
||||
// if the actors is not blurred, blur it
|
||||
this.blur_panel(panel);
|
||||
else
|
||||
// if it is blurred, update the blur anyway
|
||||
this.change_blur_type(actors);
|
||||
}
|
||||
|
||||
/// Blur a panel
|
||||
blur_panel(panel) {
|
||||
let panel_box = panel.get_parent();
|
||||
let is_dtp_panel = false;
|
||||
if (!panel_box.name) {
|
||||
is_dtp_panel = true;
|
||||
panel_box = panel_box.get_parent();
|
||||
}
|
||||
|
||||
let monitor = this.find_monitor_for(panel);
|
||||
if (!monitor)
|
||||
return;
|
||||
|
||||
let background_parent = new St.Widget({
|
||||
name: 'topbar-blurred-background-parent',
|
||||
x: 0, y: 0, width: 0, height: 0
|
||||
});
|
||||
|
||||
let background = this.settings.panel.STATIC_BLUR
|
||||
? new Meta.BackgroundActor({
|
||||
meta_display: global.display,
|
||||
monitor: monitor.index
|
||||
})
|
||||
: new St.Widget;
|
||||
|
||||
background_parent.add_child(background);
|
||||
|
||||
// insert background parent
|
||||
panel_box.insert_child_at_index(background_parent, 0);
|
||||
|
||||
let blur = new Shell.BlurEffect({
|
||||
brightness: this.settings.panel.CUSTOMIZE
|
||||
? this.settings.panel.BRIGHTNESS
|
||||
: this.settings.BRIGHTNESS,
|
||||
sigma: this.settings.panel.CUSTOMIZE
|
||||
? this.settings.panel.SIGMA
|
||||
: this.settings.SIGMA
|
||||
* monitor.geometry_scale,
|
||||
mode: this.settings.panel.STATIC_BLUR
|
||||
? Shell.BlurMode.ACTOR
|
||||
: Shell.BlurMode.BACKGROUND
|
||||
});
|
||||
|
||||
// store the scale in the effect in order to retrieve it in set_sigma
|
||||
blur.scale = monitor.geometry_scale;
|
||||
|
||||
let color = this.effects_manager.new_color_effect({
|
||||
color: this.settings.panel.CUSTOMIZE
|
||||
? this.settings.panel.COLOR
|
||||
: this.settings.COLOR
|
||||
}, this.settings);
|
||||
|
||||
let noise = this.effects_manager.new_noise_effect({
|
||||
noise: this.settings.panel.CUSTOMIZE
|
||||
? this.settings.panel.NOISE_AMOUNT
|
||||
: this.settings.NOISE_AMOUNT,
|
||||
lightness: this.settings.panel.CUSTOMIZE
|
||||
? this.settings.panel.NOISE_LIGHTNESS
|
||||
: this.settings.NOISE_LIGHTNESS
|
||||
}, this.settings);
|
||||
|
||||
let paint_signals = new PaintSignals(this.connections);
|
||||
|
||||
let actors = {
|
||||
widgets: { panel, panel_box, background, background_parent },
|
||||
effects: { blur, color, noise },
|
||||
paint_signals,
|
||||
monitor,
|
||||
is_dtp_panel
|
||||
};
|
||||
|
||||
this.actors_list.push(actors);
|
||||
|
||||
// perform updates
|
||||
this.change_blur_type(actors);
|
||||
|
||||
// connect to panel, panel_box and its parent position or size change
|
||||
// this should fire update_size every time one of its params change
|
||||
this.connections.connect(
|
||||
panel,
|
||||
'notify::position',
|
||||
_ => this.update_size(actors)
|
||||
);
|
||||
this.connections.connect(
|
||||
panel_box,
|
||||
['notify::size', 'notify::position'],
|
||||
_ => this.update_size(actors)
|
||||
);
|
||||
this.connections.connect(
|
||||
panel_box.get_parent(),
|
||||
'notify::position',
|
||||
_ => this.update_size(actors)
|
||||
);
|
||||
}
|
||||
|
||||
update_all_blur_type() {
|
||||
this.actors_list.forEach(actors => this.change_blur_type(actors));
|
||||
}
|
||||
|
||||
change_blur_type(actors) {
|
||||
let is_static = this.settings.panel.STATIC_BLUR;
|
||||
|
||||
// reset widgets to right state
|
||||
actors.widgets.background_parent.remove_child(actors.widgets.background);
|
||||
this.effects_manager.remove(actors.effects.blur);
|
||||
this.effects_manager.remove(actors.effects.color);
|
||||
this.effects_manager.remove(actors.effects.noise);
|
||||
|
||||
// create new background actor
|
||||
actors.widgets.background = is_static
|
||||
? new Meta.BackgroundActor({
|
||||
meta_display: global.display,
|
||||
monitor: this.find_monitor_for(actors.widgets.panel).index
|
||||
})
|
||||
: new St.Widget;
|
||||
|
||||
// change blur mode
|
||||
actors.effects.blur.set_mode(is_static ? 0 : 1);
|
||||
|
||||
// disable other effects if the blur is dynamic, as they makes it opaque
|
||||
actors.effects.color._static = is_static;
|
||||
actors.effects.noise._static = is_static;
|
||||
actors.effects.color.update_enabled();
|
||||
actors.effects.noise.update_enabled();
|
||||
|
||||
// add the effects in order
|
||||
actors.widgets.background.add_effect(actors.effects.color);
|
||||
actors.widgets.background.add_effect(actors.effects.noise);
|
||||
actors.widgets.background.add_effect(actors.effects.blur);
|
||||
|
||||
// add the background actor behing the panel
|
||||
actors.widgets.background_parent.add_child(actors.widgets.background);
|
||||
|
||||
// perform updates
|
||||
this.update_wallpaper(actors);
|
||||
this.update_size(actors);
|
||||
|
||||
|
||||
// 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 (!is_static) {
|
||||
if (this.settings.HACKS_LEVEL === 1) {
|
||||
this._log("panel hack level 1");
|
||||
actors.paint_signals.disconnect_all();
|
||||
|
||||
let rp = () => { actors.effects.blur.queue_repaint(); };
|
||||
|
||||
this.connections.connect(actors.widgets.panel, [
|
||||
'enter-event', 'leave-event', 'button-press-event'
|
||||
], rp);
|
||||
|
||||
actors.widgets.panel.get_children().forEach(child => {
|
||||
this.connections.connect(child, [
|
||||
'enter-event', 'leave-event', 'button-press-event'
|
||||
], rp);
|
||||
});
|
||||
} else if (this.settings.HACKS_LEVEL === 2) {
|
||||
this._log("panel hack level 2");
|
||||
actors.paint_signals.disconnect_all();
|
||||
|
||||
actors.paint_signals.connect(
|
||||
actors.widgets.background, actors.effects.blur
|
||||
);
|
||||
} else {
|
||||
actors.paint_signals.disconnect_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_wallpaper(actors) {
|
||||
// if static blur, get right wallpaper and update blur with it
|
||||
if (this.settings.panel.STATIC_BLUR) {
|
||||
let bg = Main.layoutManager._backgroundGroup.get_child_at_index(
|
||||
Main.layoutManager.monitors.length
|
||||
- this.find_monitor_for(actors.widgets.panel).index - 1
|
||||
);
|
||||
if (bg)
|
||||
actors.widgets.background.content.set({
|
||||
background: bg.get_content().background
|
||||
});
|
||||
else
|
||||
this._warn("could not get background for panel");
|
||||
}
|
||||
}
|
||||
|
||||
update_size(actors) {
|
||||
let panel = actors.widgets.panel;
|
||||
let panel_box = actors.widgets.panel_box;
|
||||
let background = actors.widgets.background;
|
||||
let monitor = this.find_monitor_for(panel);
|
||||
if (!monitor)
|
||||
return;
|
||||
|
||||
let [width, height] = panel_box.get_size();
|
||||
background.width = width;
|
||||
background.height = height;
|
||||
|
||||
// if static blur, need to clip the background
|
||||
if (this.settings.panel.STATIC_BLUR) {
|
||||
// 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;
|
||||
let y = p_y + p_p_y - monitor.y;
|
||||
|
||||
background.set_clip(x, y, width, height);
|
||||
background.x = -x;
|
||||
background.y = -y;
|
||||
|
||||
// fixes a bug where the blur is washed away when changing the sigma
|
||||
this.invalidate_blur(actors);
|
||||
} else {
|
||||
background.x = panel.x;
|
||||
background.y = panel.y;
|
||||
}
|
||||
|
||||
// update the monitor panel is on
|
||||
actors.monitor = this.find_monitor_for(panel);
|
||||
}
|
||||
|
||||
/// An helper function to find the monitor in which an actor is situated,
|
||||
/// there might be a pre-existing function in GLib already
|
||||
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];
|
||||
}
|
||||
|
||||
/// Connect when overview if opened/closed to hide/show the blur accordingly
|
||||
///
|
||||
/// If HIDETOPBAR is set, we need just to hide the blur when showing appgrid
|
||||
/// (so no shadow is cropped)
|
||||
connect_to_overview() {
|
||||
// may be called when panel blur is disabled, if hidetopbar
|
||||
// compatibility is toggled on/off
|
||||
// if this is the case, do nothing as only the panel blur interfers with
|
||||
// hidetopbar
|
||||
if (
|
||||
this.settings.panel.BLUR &&
|
||||
this.settings.panel.UNBLUR_IN_OVERVIEW
|
||||
) {
|
||||
if (!this.settings.hidetopbar.COMPATIBILITY) {
|
||||
this.connections.connect(
|
||||
Main.overview, 'showing', this.hide.bind(this)
|
||||
);
|
||||
this.connections.connect(
|
||||
Main.overview, 'hidden', this.show.bind(this)
|
||||
);
|
||||
} else {
|
||||
let appDisplay = Main.overview._overview._controls._appDisplay;
|
||||
|
||||
this.connections.connect(
|
||||
appDisplay, 'show', this.hide.bind(this)
|
||||
);
|
||||
this.connections.connect(
|
||||
appDisplay, 'hide', this.show.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// Connect to windows disable transparency when a window is too close
|
||||
connect_to_windows() {
|
||||
if (
|
||||
this.settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY
|
||||
) {
|
||||
// connect to overview opening/closing
|
||||
this.connections.connect(Main.overview, ['showing', 'hiding'],
|
||||
this.update_visibility.bind(this)
|
||||
);
|
||||
|
||||
// connect to session mode update
|
||||
this.connections.connect(Main.sessionMode, 'updated',
|
||||
this.update_visibility.bind(this)
|
||||
);
|
||||
|
||||
// manage already-existing windows
|
||||
for (const meta_window_actor of global.get_window_actors()) {
|
||||
this.on_window_actor_added(
|
||||
meta_window_actor.get_parent(), meta_window_actor
|
||||
);
|
||||
}
|
||||
|
||||
// manage windows at their creation/removal
|
||||
this.connections.connect(global.window_group, 'actor-added',
|
||||
this.on_window_actor_added.bind(this)
|
||||
);
|
||||
this.connections.connect(global.window_group, 'actor-removed',
|
||||
this.on_window_actor_removed.bind(this)
|
||||
);
|
||||
|
||||
// connect to a workspace change
|
||||
this.connections.connect(global.window_manager, 'switch-workspace',
|
||||
this.update_visibility.bind(this)
|
||||
);
|
||||
|
||||
// perform early update
|
||||
this.update_visibility();
|
||||
} else {
|
||||
// reset transparency for every panels
|
||||
this.actors_list.forEach(
|
||||
actors => this.set_should_override_panel(actors, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// An helper to connect to both the windows and overview signals.
|
||||
/// This is the only function that should be directly called, to prevent
|
||||
/// inconsistencies with signals not being disconnected.
|
||||
connect_to_windows_and_overview() {
|
||||
this.disconnect_from_windows_and_overview();
|
||||
this.connect_to_overview();
|
||||
this.connect_to_windows();
|
||||
}
|
||||
|
||||
/// Disconnect all the connections created by connect_to_windows
|
||||
disconnect_from_windows_and_overview() {
|
||||
// disconnect the connections to actors
|
||||
for (const actor of [
|
||||
Main.overview, Main.sessionMode,
|
||||
global.window_group, global.window_manager,
|
||||
Main.overview._overview._controls._appDisplay
|
||||
]) {
|
||||
this.connections.disconnect_all_for(actor);
|
||||
}
|
||||
|
||||
// disconnect the connections from windows
|
||||
for (const [actor, ids] of this.window_signal_ids) {
|
||||
for (const id of ids) {
|
||||
actor.disconnect(id);
|
||||
}
|
||||
}
|
||||
this.window_signal_ids = new Map();
|
||||
}
|
||||
|
||||
/// Callback when a new window is added
|
||||
on_window_actor_added(container, meta_window_actor) {
|
||||
this.window_signal_ids.set(meta_window_actor, [
|
||||
meta_window_actor.connect('notify::allocation',
|
||||
_ => this.update_visibility()
|
||||
),
|
||||
meta_window_actor.connect('notify::visible',
|
||||
_ => this.update_visibility()
|
||||
)
|
||||
]);
|
||||
this.update_visibility();
|
||||
}
|
||||
|
||||
/// Callback when a window is removed
|
||||
on_window_actor_removed(container, meta_window_actor) {
|
||||
for (const signalId of this.window_signal_ids.get(meta_window_actor)) {
|
||||
meta_window_actor.disconnect(signalId);
|
||||
}
|
||||
this.window_signal_ids.delete(meta_window_actor);
|
||||
this.update_visibility();
|
||||
}
|
||||
|
||||
/// Update the visibility of the blur effect
|
||||
update_visibility() {
|
||||
if (
|
||||
Main.panel.has_style_pseudo_class('overview')
|
||||
|| !Main.sessionMode.hasWindows
|
||||
) {
|
||||
this.actors_list.forEach(
|
||||
actors => this.set_should_override_panel(actors, true)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Main.layoutManager.primaryMonitor)
|
||||
return;
|
||||
|
||||
// get all the windows in the active workspace that are visible
|
||||
const workspace = global.workspace_manager.get_active_workspace();
|
||||
const windows = workspace.list_windows().filter(meta_window =>
|
||||
meta_window.showing_on_its_workspace()
|
||||
&& !meta_window.is_hidden()
|
||||
&& meta_window.get_window_type() !== Meta.WindowType.DESKTOP
|
||||
// exclude Desktop Icons NG
|
||||
&& meta_window.get_gtk_application_id() !== "com.rastersoft.ding"
|
||||
);
|
||||
|
||||
// check if at least one window is near enough to each panel and act
|
||||
// accordingly
|
||||
const scale = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
this.actors_list
|
||||
// do not apply for dtp panels, as it would only cause bugs and it
|
||||
// can be done from its preferences anyway
|
||||
.filter(actors => !actors.is_dtp_panel)
|
||||
.forEach(actors => {
|
||||
let panel = actors.widgets.panel;
|
||||
let panel_top = panel.get_transformed_position()[1];
|
||||
let panel_bottom = panel_top + panel.get_height();
|
||||
|
||||
// check if at least a window is near enough the panel
|
||||
let window_overlap_panel = false;
|
||||
windows.forEach(meta_window => {
|
||||
let window_monitor_i = meta_window.get_monitor();
|
||||
let same_monitor = actors.monitor.index == window_monitor_i;
|
||||
|
||||
let window_vertical_pos = meta_window.get_frame_rect().y;
|
||||
|
||||
// if so, and if in the same monitor, then it overlaps
|
||||
if (same_monitor
|
||||
&&
|
||||
window_vertical_pos < panel_bottom + 5 * scale
|
||||
)
|
||||
window_overlap_panel = true;
|
||||
});
|
||||
|
||||
// if no window overlaps, then the panel is transparent
|
||||
this.set_should_override_panel(
|
||||
actors, !window_overlap_panel
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Choose wether or not the panel background should be overriden, in
|
||||
/// respect to its argument and the `override-background` setting.
|
||||
set_should_override_panel(actors, should_override) {
|
||||
let panel = actors.widgets.panel;
|
||||
|
||||
PANEL_STYLES.forEach(style => panel.remove_style_class_name(style));
|
||||
|
||||
if (
|
||||
this.settings.panel.OVERRIDE_BACKGROUND
|
||||
&&
|
||||
should_override
|
||||
)
|
||||
panel.add_style_class_name(
|
||||
PANEL_STYLES[this.settings.panel.STYLE_PANEL]
|
||||
);
|
||||
}
|
||||
|
||||
/// Fixes a bug where the blur is washed away when changing the sigma, or
|
||||
/// enabling/disabling other effects.
|
||||
invalidate_blur(actors) {
|
||||
if (this.settings.panel.STATIC_BLUR && actors.widgets.background)
|
||||
actors.widgets.background.get_content().invalidate();
|
||||
}
|
||||
|
||||
invalidate_all_blur() {
|
||||
this.actors_list.forEach(actors => this.invalidate_blur(actors));
|
||||
}
|
||||
|
||||
set_sigma(s) {
|
||||
this.actors_list.forEach(actors => {
|
||||
actors.effects.blur.sigma = s * actors.effects.blur.scale;
|
||||
this.invalidate_blur(actors);
|
||||
});
|
||||
}
|
||||
|
||||
set_brightness(b) {
|
||||
this.actors_list.forEach(actors => {
|
||||
actors.effects.blur.brightness = b;
|
||||
});
|
||||
}
|
||||
|
||||
set_color(c) {
|
||||
this.actors_list.forEach(actors => {
|
||||
actors.effects.color.color = c;
|
||||
});
|
||||
}
|
||||
|
||||
set_noise_amount(n) {
|
||||
this.actors_list.forEach(actors => {
|
||||
actors.effects.noise.noise = n;
|
||||
});
|
||||
}
|
||||
|
||||
set_noise_lightness(l) {
|
||||
this.actors_list.forEach(actors => {
|
||||
actors.effects.noise.lightness = l;
|
||||
});
|
||||
}
|
||||
|
||||
show() {
|
||||
this.actors_list.forEach(actors => {
|
||||
actors.widgets.background_parent.show();
|
||||
});
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.actors_list.forEach(actors => {
|
||||
actors.widgets.background_parent.hide();
|
||||
});
|
||||
}
|
||||
|
||||
// destroy every blurred background left, necessary after sleep
|
||||
destroy_blur_effects() {
|
||||
Main.panel?.get_parent()?.get_children().forEach(
|
||||
child => {
|
||||
if (child.name === 'topbar-blurred-background-parent') {
|
||||
child.get_children().forEach(meta_background_actor => {
|
||||
meta_background_actor.get_effects().forEach(effect => {
|
||||
this.effects_manager.remove(effect);
|
||||
});
|
||||
});
|
||||
child.destroy_all_children();
|
||||
child.destroy();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._log("removing blur from top panel");
|
||||
|
||||
this.disconnect_from_windows_and_overview();
|
||||
|
||||
this.actors_list.forEach(actors => {
|
||||
this.set_should_override_panel(actors, false);
|
||||
this.effects_manager.remove(actors.effects.noise);
|
||||
this.effects_manager.remove(actors.effects.color);
|
||||
this.effects_manager.remove(actors.effects.blur);
|
||||
try {
|
||||
actors.widgets.panel_box.remove_child(
|
||||
actors.widgets.background_parent
|
||||
);
|
||||
} catch (e) { }
|
||||
actors.widgets.background_parent?.destroy();
|
||||
});
|
||||
|
||||
this.destroy_blur_effects();
|
||||
|
||||
this.actors_list = [];
|
||||
|
||||
this.connections.disconnect_all();
|
||||
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
_log(str) {
|
||||
if (this.settings.DEBUG)
|
||||
console.log(`[Blur my Shell > panel] ${str}`);
|
||||
}
|
||||
|
||||
_warn(str) {
|
||||
console.warn(`[Blur my Shell > panel] ${str}`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,173 @@
|
||||
import Shell from 'gi://Shell';
|
||||
import Meta from 'gi://Meta';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
|
||||
|
||||
export const ScreenshotBlur = class ScreenshotBlur {
|
||||
constructor(connections, settings, effects_manager) {
|
||||
this.connections = connections;
|
||||
this.effects = [];
|
||||
this.settings = settings;
|
||||
this.effects_manager = effects_manager;
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._log("blurring screenshot's window selector");
|
||||
|
||||
// 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._log("updated background for screenshot's window selector");
|
||||
this.update_backgrounds();
|
||||
}
|
||||
);
|
||||
|
||||
// connect to monitors change
|
||||
this.connections.connect(
|
||||
Main.layoutManager,
|
||||
'monitors-changed',
|
||||
_ => {
|
||||
if (Main.screenShield && !Main.screenShield.locked) {
|
||||
this._log("changed monitors for screenshot's window selector");
|
||||
this.update_backgrounds();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// update backgrounds when the component is enabled
|
||||
this.update_backgrounds();
|
||||
}
|
||||
|
||||
update_backgrounds() {
|
||||
// remove every old background
|
||||
this.remove();
|
||||
|
||||
// add new backgrounds
|
||||
for (let i = 0; i < Main.screenshotUI._windowSelectors.length; i++) {
|
||||
const actor = Main.screenshotUI._windowSelectors[i];
|
||||
const monitor = Main.layoutManager.monitors[i];
|
||||
|
||||
if (!monitor)
|
||||
continue;
|
||||
|
||||
const bg_actor = this.create_background_actor(monitor);
|
||||
actor.insert_child_at_index(bg_actor, 0);
|
||||
actor._blur_actor = bg_actor;
|
||||
}
|
||||
}
|
||||
|
||||
create_background_actor(monitor) {
|
||||
let bg_actor = new Meta.BackgroundActor({
|
||||
meta_display: global.display,
|
||||
monitor: monitor.index
|
||||
});
|
||||
let background = Main.layoutManager._backgroundGroup.get_child_at_index(
|
||||
Main.layoutManager.monitors.length - monitor.index - 1
|
||||
);
|
||||
|
||||
if (!background) {
|
||||
this._warn("could not get background for screenshot's window selector");
|
||||
return bg_actor;
|
||||
}
|
||||
|
||||
bg_actor.content.set({
|
||||
background: background.get_content().background
|
||||
});
|
||||
|
||||
let blur_effect = new Shell.BlurEffect({
|
||||
brightness: this.settings.screenshot.CUSTOMIZE
|
||||
? this.settings.screenshot.BRIGHTNESS
|
||||
: this.settings.BRIGHTNESS,
|
||||
sigma: this.settings.screenshot.CUSTOMIZE
|
||||
? this.settings.screenshot.SIGMA
|
||||
: this.settings.SIGMA
|
||||
* monitor.geometry_scale,
|
||||
mode: Shell.BlurMode.ACTOR
|
||||
});
|
||||
|
||||
// store the scale in the effect in order to retrieve it in set_sigma
|
||||
blur_effect.scale = monitor.geometry_scale;
|
||||
|
||||
let color_effect = this.effects_manager.new_color_effect({
|
||||
color: this.settings.screenshot.CUSTOMIZE
|
||||
? this.settings.screenshot.COLOR
|
||||
: this.settings.COLOR
|
||||
}, this.settings);
|
||||
|
||||
let noise_effect = this.effects_manager.new_noise_effect({
|
||||
noise: this.settings.screenshot.CUSTOMIZE
|
||||
? this.settings.screenshot.NOISE_AMOUNT
|
||||
: this.settings.NOISE_AMOUNT,
|
||||
lightness: this.settings.screenshot.CUSTOMIZE
|
||||
? this.settings.screenshot.NOISE_LIGHTNESS
|
||||
: this.settings.NOISE_LIGHTNESS
|
||||
}, this.settings);
|
||||
|
||||
bg_actor.add_effect(color_effect);
|
||||
bg_actor.add_effect(noise_effect);
|
||||
bg_actor.add_effect(blur_effect);
|
||||
this.effects.push({ blur_effect, color_effect, noise_effect });
|
||||
|
||||
return bg_actor;
|
||||
}
|
||||
|
||||
set_sigma(s) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.blur_effect.sigma = s * effect.blur_effect;
|
||||
});
|
||||
}
|
||||
|
||||
set_brightness(b) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.blur_effect.brightness = b;
|
||||
});
|
||||
}
|
||||
|
||||
set_color(c) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.color_effect.color = c;
|
||||
});
|
||||
}
|
||||
|
||||
set_noise_amount(n) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.noise_effect.noise = n;
|
||||
});
|
||||
}
|
||||
|
||||
set_noise_lightness(l) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.noise_effect.lightness = l;
|
||||
});
|
||||
}
|
||||
|
||||
remove() {
|
||||
Main.screenshotUI._windowSelectors.forEach(actor => {
|
||||
if (actor._blur_actor) {
|
||||
actor.remove_child(actor._blur_actor);
|
||||
actor._blur_actor.destroy();
|
||||
}
|
||||
});
|
||||
this.effects = [];
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._log("removing blur from screenshot's window selector");
|
||||
|
||||
this.remove();
|
||||
this.connections.disconnect_all();
|
||||
}
|
||||
|
||||
_log(str) {
|
||||
if (this.settings.DEBUG)
|
||||
console.log(`[Blur my Shell > screenshot] ${str}`);
|
||||
}
|
||||
|
||||
_warn(str) {
|
||||
console.warn(`[Blur my Shell > screenshot] ${str}`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,162 @@
|
||||
import Shell from 'gi://Shell';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
|
||||
import { PaintSignals } from '../effects/paint_signals.js';
|
||||
|
||||
|
||||
export const WindowListBlur = class WindowListBlur {
|
||||
constructor(connections, settings, _) {
|
||||
this.connections = connections;
|
||||
this.settings = settings;
|
||||
this.paint_signals = new PaintSignals(connections);
|
||||
this.effects = [];
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._log("blurring window list");
|
||||
|
||||
// blur if window-list is found
|
||||
Main.layoutManager.uiGroup.get_children().forEach(
|
||||
child => this.try_blur(child)
|
||||
);
|
||||
|
||||
// listen to new actors in `Main.layoutManager.uiGroup` and blur it if
|
||||
// if is window-list
|
||||
this.connections.connect(
|
||||
Main.layoutManager.uiGroup,
|
||||
'actor-added',
|
||||
(_, child) => this.try_blur(child)
|
||||
);
|
||||
|
||||
// connect to overview
|
||||
this.connections.connect(Main.overview, 'showing', _ => {
|
||||
this.hide();
|
||||
});
|
||||
this.connections.connect(Main.overview, 'hidden', _ => {
|
||||
this.show();
|
||||
});
|
||||
}
|
||||
|
||||
try_blur(child) {
|
||||
if (
|
||||
child.constructor.name === "WindowList" &&
|
||||
child.style !== "background:transparent;"
|
||||
) {
|
||||
this._log("found window list to blur");
|
||||
|
||||
let blur_effect = new Shell.BlurEffect({
|
||||
name: 'window-list-blur',
|
||||
sigma: this.settings.window_list.CUSTOMIZE
|
||||
? this.settings.window_list.SIGMA
|
||||
: this.settings.SIGMA,
|
||||
brightness: this.settings.window_list.CUSTOMIZE
|
||||
? this.settings.window_list.BRIGHTNESS
|
||||
: this.settings.BRIGHTNESS,
|
||||
mode: Shell.BlurMode.BACKGROUND
|
||||
});
|
||||
|
||||
child.set_style("background:transparent;");
|
||||
child.add_effect(blur_effect);
|
||||
this.effects.push({ blur_effect });
|
||||
|
||||
child._windowList.get_children().forEach(
|
||||
window => this.blur_window_button(window)
|
||||
);
|
||||
|
||||
this.connections.connect(
|
||||
child._windowList,
|
||||
'actor-added',
|
||||
(_, window) => this.blur_window_button(window)
|
||||
);
|
||||
|
||||
|
||||
// HACK
|
||||
//
|
||||
//`Shell.BlurEffect` does not repaint when shadows are under it. [1]
|
||||
//
|
||||
// This does not entirely fix this bug (shadows caused by windows
|
||||
// still cause artifacts), but it prevents the shadows of the panel
|
||||
// buttons to cause artifacts on the panel itself
|
||||
//
|
||||
// [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857
|
||||
|
||||
if (this.settings.HACKS_LEVEL === 1) {
|
||||
this._log("window list hack level 1");
|
||||
|
||||
this.paint_signals.connect(child, blur_effect);
|
||||
|
||||
} else if (this.settings.HACKS_LEVEL === 2) {
|
||||
this._log("window list hack level 2");
|
||||
|
||||
this.paint_signals.connect(child, blur_effect);
|
||||
} else {
|
||||
this.paint_signals.disconnect_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blur_window_button(window) {
|
||||
window.get_child_at_index(0).set_style(
|
||||
"box-shadow:none; background-color:rgba(0,0,0,0.2); border-radius:5px;"
|
||||
);
|
||||
}
|
||||
|
||||
try_remove_blur(child) {
|
||||
if (
|
||||
child.constructor.name === "WindowList" &&
|
||||
child.style === "background:transparent;"
|
||||
) {
|
||||
child.style = null;
|
||||
child.remove_effect_by_name('window-list-blur');
|
||||
|
||||
child._windowList.get_children().forEach(
|
||||
child => child.get_child_at_index(0).set_style(null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
set_sigma(s) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.blur_effect.sigma = s;
|
||||
});
|
||||
}
|
||||
|
||||
set_brightness(b) {
|
||||
this.effects.forEach(effect => {
|
||||
effect.blur_effect.brightness = b;
|
||||
});
|
||||
}
|
||||
|
||||
// not implemented for dynamic blur
|
||||
set_color(c) { }
|
||||
set_noise_amount(n) { }
|
||||
set_noise_lightness(l) { }
|
||||
|
||||
hide() {
|
||||
this.set_sigma(0);
|
||||
}
|
||||
|
||||
show() {
|
||||
this.set_sigma(
|
||||
this.settings.window_list.CUSTOMIZE
|
||||
? this.settings.window_list.SIGMA
|
||||
: this.settings.SIGMA
|
||||
);
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._log("removing blur from window list");
|
||||
|
||||
Main.layoutManager.uiGroup.get_children().forEach(
|
||||
child => this.try_remove_blur(child)
|
||||
);
|
||||
|
||||
this.effects = [];
|
||||
this.connections.disconnect_all();
|
||||
}
|
||||
|
||||
_log(str) {
|
||||
if (this.settings.DEBUG)
|
||||
console.log(`[Blur my Shell > window list] ${str}`);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user