[gnome] Fix extension locations
@ -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}`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,101 @@
|
||||
import GObject from 'gi://GObject';
|
||||
|
||||
/// An object to easily manage signals.
|
||||
export const Connections = class Connections {
|
||||
constructor() {
|
||||
this.buffer = [];
|
||||
}
|
||||
|
||||
/// Adds a connection.
|
||||
///
|
||||
/// Takes as arguments:
|
||||
/// - an actor, which fires the signal
|
||||
/// - signal(s) (string or array of strings), which are watched for
|
||||
/// - a callback, which is called when the signal is fired
|
||||
connect(actor, signals, handler) {
|
||||
if (signals instanceof Array) {
|
||||
signals.forEach(signal => {
|
||||
let id = actor.connect(signal, handler);
|
||||
this.process_connection(actor, id);
|
||||
});
|
||||
} else {
|
||||
let id = actor.connect(signals, handler);
|
||||
this.process_connection(actor, id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Process the given actor and id.
|
||||
///
|
||||
/// This makes sure that the signal is disconnected when the actor is
|
||||
/// destroyed, and that the signal can be managed through other Connections
|
||||
/// methods.
|
||||
process_connection(actor, id) {
|
||||
let infos = {
|
||||
actor: actor,
|
||||
id: id
|
||||
};
|
||||
|
||||
// remove the signal when the actor is destroyed
|
||||
if (
|
||||
actor.connect &&
|
||||
(
|
||||
!(actor instanceof GObject.Object) ||
|
||||
GObject.signal_lookup('destroy', actor)
|
||||
)
|
||||
) {
|
||||
let destroy_id = actor.connect('destroy', () => {
|
||||
actor.disconnect(id);
|
||||
actor.disconnect(destroy_id);
|
||||
|
||||
let index = this.buffer.indexOf(infos);
|
||||
if (index >= 0) {
|
||||
this.buffer.splice(index, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.buffer.push(infos);
|
||||
}
|
||||
|
||||
/// Disconnects every connection found for an actor.
|
||||
disconnect_all_for(actor) {
|
||||
// get every connection stored for the actor
|
||||
let actor_connections = this.buffer.filter(
|
||||
infos => infos.actor === actor
|
||||
);
|
||||
|
||||
// remove each of them
|
||||
actor_connections.forEach((connection) => {
|
||||
// disconnect
|
||||
try {
|
||||
connection.actor.disconnect(connection.id);
|
||||
} catch (e) {
|
||||
this._warn(`error removing connection: ${e}; continuing`);
|
||||
}
|
||||
|
||||
// remove from buffer
|
||||
let index = this.buffer.indexOf(connection);
|
||||
this.buffer.splice(index, 1);
|
||||
});
|
||||
}
|
||||
|
||||
/// Disconnect every connection for each actor.
|
||||
disconnect_all() {
|
||||
this.buffer.forEach((connection) => {
|
||||
// disconnect
|
||||
try {
|
||||
connection.actor.disconnect(connection.id);
|
||||
} catch (e) {
|
||||
this._warn(`error removing connection: ${e}; continuing`);
|
||||
}
|
||||
});
|
||||
|
||||
// reset buffer
|
||||
this.buffer = [];
|
||||
}
|
||||
|
||||
_warn(str) {
|
||||
console.warn(`[Blur my Shell > connections] ${str}`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,89 @@
|
||||
import { ColorEffect } from '../effects/color_effect.js';
|
||||
import { NoiseEffect } from '../effects/noise_effect.js';
|
||||
|
||||
|
||||
/// An object to manage effects (by not destroying them all the time)
|
||||
export const EffectsManager = class EffectsManager {
|
||||
constructor(connections) {
|
||||
this.connections = connections;
|
||||
this.used = [];
|
||||
this.color_effects = [];
|
||||
this.noise_effects = [];
|
||||
}
|
||||
|
||||
connect_to_destroy(effect) {
|
||||
effect.old_actor = effect.get_actor();
|
||||
if (effect.old_actor)
|
||||
effect.old_actor_id = effect.old_actor.connect('destroy', _ => {
|
||||
this.remove(effect);
|
||||
});
|
||||
|
||||
this.connections.connect(effect, 'notify::actor', _ => {
|
||||
let actor = effect.get_actor();
|
||||
|
||||
if (effect.old_actor && actor != effect.old_actor)
|
||||
effect.old_actor.disconnect(effect.old_actor_id);
|
||||
|
||||
if (actor) {
|
||||
effect.old_actor_id = actor.connect('destroy', _ => {
|
||||
this.remove(effect);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
new_color_effect(params, settings) {
|
||||
let effect;
|
||||
if (this.color_effects.length > 0) {
|
||||
effect = this.color_effects.splice(0, 1)[0];
|
||||
effect.set(params);
|
||||
} else
|
||||
effect = new ColorEffect(params, settings);
|
||||
|
||||
this.used.push(effect);
|
||||
this.connect_to_destroy(effect);
|
||||
return effect;
|
||||
}
|
||||
|
||||
new_noise_effect(params, settings) {
|
||||
let effect;
|
||||
if (this.noise_effects.length > 0) {
|
||||
effect = this.noise_effects.splice(0, 1)[0];
|
||||
effect.set(params);
|
||||
} else
|
||||
effect = new NoiseEffect(params, settings);
|
||||
|
||||
this.used.push(effect);
|
||||
this.connect_to_destroy(effect);
|
||||
return effect;
|
||||
}
|
||||
|
||||
remove(effect) {
|
||||
effect.get_actor()?.remove_effect(effect);
|
||||
if (effect.old_actor)
|
||||
effect.old_actor.disconnect(effect.old_actor_id);
|
||||
delete effect.old_actor;
|
||||
delete effect.old_actor_id;
|
||||
|
||||
let index = this.used.indexOf(effect);
|
||||
if (index >= 0) {
|
||||
this.used.splice(index, 1);
|
||||
|
||||
if (effect instanceof ColorEffect)
|
||||
this.color_effects.push(effect);
|
||||
else if (effect instanceof NoiseEffect)
|
||||
this.noise_effects.push(effect);
|
||||
}
|
||||
}
|
||||
|
||||
destroy_all() {
|
||||
this.used.forEach(effect => { this.remove(effect); });
|
||||
[
|
||||
this.used,
|
||||
this.color_effects,
|
||||
this.noise_effects
|
||||
].forEach(array => {
|
||||
array.splice(0, array.length);
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,131 @@
|
||||
import { Type } from './settings.js';
|
||||
|
||||
// This lists the preferences keys
|
||||
export const Keys = [
|
||||
{
|
||||
component: "general", schemas: [
|
||||
{ type: Type.I, name: "sigma" },
|
||||
{ type: Type.D, name: "brightness" },
|
||||
{ type: Type.C, name: "color" },
|
||||
{ type: Type.D, name: "noise-amount" },
|
||||
{ type: Type.D, name: "noise-lightness" },
|
||||
{ type: Type.B, name: "color-and-noise" },
|
||||
{ type: Type.I, name: "hacks-level" },
|
||||
{ type: Type.B, name: "debug" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "overview", schemas: [
|
||||
{ type: Type.B, name: "blur" },
|
||||
{ type: Type.B, name: "customize" },
|
||||
{ type: Type.I, name: "sigma" },
|
||||
{ type: Type.D, name: "brightness" },
|
||||
{ type: Type.C, name: "color" },
|
||||
{ type: Type.D, name: "noise-amount" },
|
||||
{ type: Type.D, name: "noise-lightness" },
|
||||
{ type: Type.I, name: "style-components" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "appfolder", schemas: [
|
||||
{ type: Type.B, name: "blur" },
|
||||
{ type: Type.B, name: "customize" },
|
||||
{ type: Type.I, name: "sigma" },
|
||||
{ type: Type.D, name: "brightness" },
|
||||
{ type: Type.C, name: "color" },
|
||||
{ type: Type.D, name: "noise-amount" },
|
||||
{ type: Type.D, name: "noise-lightness" },
|
||||
{ type: Type.I, name: "style-dialogs" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "panel", schemas: [
|
||||
{ type: Type.B, name: "blur" },
|
||||
{ type: Type.B, name: "customize" },
|
||||
{ type: Type.I, name: "sigma" },
|
||||
{ type: Type.D, name: "brightness" },
|
||||
{ type: Type.C, name: "color" },
|
||||
{ type: Type.D, name: "noise-amount" },
|
||||
{ type: Type.D, name: "noise-lightness" },
|
||||
{ type: Type.B, name: "static-blur" },
|
||||
{ type: Type.B, name: "unblur-in-overview" },
|
||||
{ type: Type.B, name: "override-background" },
|
||||
{ type: Type.I, name: "style-panel" },
|
||||
{ type: Type.B, name: "override-background-dynamically" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "dash-to-dock", schemas: [
|
||||
{ type: Type.B, name: "blur" },
|
||||
{ type: Type.B, name: "customize" },
|
||||
{ type: Type.I, name: "sigma" },
|
||||
{ type: Type.D, name: "brightness" },
|
||||
{ type: Type.C, name: "color" },
|
||||
{ type: Type.D, name: "noise-amount" },
|
||||
{ type: Type.D, name: "noise-lightness" },
|
||||
{ type: Type.B, name: "static-blur" },
|
||||
{ type: Type.B, name: "unblur-in-overview" },
|
||||
{ type: Type.B, name: "override-background" },
|
||||
{ type: Type.I, name: "style-dash-to-dock" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "applications", schemas: [
|
||||
{ type: Type.B, name: "blur" },
|
||||
{ type: Type.B, name: "customize" },
|
||||
{ type: Type.I, name: "sigma" },
|
||||
{ type: Type.D, name: "brightness" },
|
||||
{ type: Type.C, name: "color" },
|
||||
{ type: Type.D, name: "noise-amount" },
|
||||
{ type: Type.D, name: "noise-lightness" },
|
||||
{ type: Type.I, name: "opacity" },
|
||||
{ type: Type.B, name: "blur-on-overview" },
|
||||
{ type: Type.B, name: "enable-all" },
|
||||
{ type: Type.AS, name: "whitelist" },
|
||||
{ type: Type.AS, name: "blacklist" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "lockscreen", schemas: [
|
||||
{ type: Type.B, name: "blur" },
|
||||
{ type: Type.B, name: "customize" },
|
||||
{ type: Type.I, name: "sigma" },
|
||||
{ type: Type.D, name: "brightness" },
|
||||
{ type: Type.C, name: "color" },
|
||||
{ type: Type.D, name: "noise-amount" },
|
||||
{ type: Type.D, name: "noise-lightness" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "window-list", schemas: [
|
||||
{ type: Type.B, name: "blur" },
|
||||
{ type: Type.B, name: "customize" },
|
||||
{ type: Type.I, name: "sigma" },
|
||||
{ type: Type.D, name: "brightness" },
|
||||
{ type: Type.C, name: "color" },
|
||||
{ type: Type.D, name: "noise-amount" },
|
||||
{ type: Type.D, name: "noise-lightness" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "screenshot", schemas: [
|
||||
{ type: Type.B, name: "blur" },
|
||||
{ type: Type.B, name: "customize" },
|
||||
{ type: Type.I, name: "sigma" },
|
||||
{ type: Type.D, name: "brightness" },
|
||||
{ type: Type.C, name: "color" },
|
||||
{ type: Type.D, name: "noise-amount" },
|
||||
{ type: Type.D, name: "noise-lightness" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "hidetopbar", schemas: [
|
||||
{ type: Type.B, name: "compatibility" },
|
||||
]
|
||||
},
|
||||
{
|
||||
component: "dash-to-panel", schemas: [
|
||||
{ type: Type.B, name: "blur-original-panel" },
|
||||
]
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,182 @@
|
||||
import GLib from 'gi://GLib';
|
||||
|
||||
const Signals = imports.signals;
|
||||
|
||||
/// An enum non-extensively describing the type of gsettings key.
|
||||
export const Type = {
|
||||
B: 'Boolean',
|
||||
I: 'Integer',
|
||||
D: 'Double',
|
||||
S: 'String',
|
||||
C: 'Color',
|
||||
AS: 'StringArray'
|
||||
};
|
||||
|
||||
/// An object to get and manage the gsettings preferences.
|
||||
///
|
||||
/// Should be initialized with an array of keys, for example:
|
||||
///
|
||||
/// let settings = new Settings([
|
||||
/// { type: Type.I, name: "panel-corner-radius" },
|
||||
/// { type: Type.B, name: "debug" }
|
||||
/// ]);
|
||||
///
|
||||
/// Each {type, name} object represents a gsettings key, which must be created
|
||||
/// in the gschemas.xml file of the extension.
|
||||
export const Settings = class Settings {
|
||||
constructor(keys, settings) {
|
||||
this.settings = settings;
|
||||
this.keys = keys;
|
||||
|
||||
this.keys.forEach(bundle => {
|
||||
let component = this;
|
||||
let component_settings = settings;
|
||||
if (bundle.component !== "general") {
|
||||
let bundle_component = bundle.component.replaceAll('-', '_');
|
||||
this[bundle_component] = {
|
||||
settings: this.settings.get_child(bundle.component)
|
||||
};
|
||||
component = this[bundle_component];
|
||||
component_settings = settings.get_child(bundle.component);
|
||||
}
|
||||
|
||||
|
||||
bundle.schemas.forEach(key => {
|
||||
let property_name = this.get_property_name(key.name);
|
||||
|
||||
switch (key.type) {
|
||||
case Type.B:
|
||||
Object.defineProperty(component, property_name, {
|
||||
get() {
|
||||
return component_settings.get_boolean(key.name);
|
||||
},
|
||||
set(v) {
|
||||
component_settings.set_boolean(key.name, v);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case Type.I:
|
||||
Object.defineProperty(component, property_name, {
|
||||
get() {
|
||||
return component_settings.get_int(key.name);
|
||||
},
|
||||
set(v) {
|
||||
component_settings.set_int(key.name, v);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case Type.D:
|
||||
Object.defineProperty(component, property_name, {
|
||||
get() {
|
||||
return component_settings.get_double(key.name);
|
||||
},
|
||||
set(v) {
|
||||
component_settings.set_double(key.name, v);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case Type.S:
|
||||
Object.defineProperty(component, property_name, {
|
||||
get() {
|
||||
return component_settings.get_string(key.name);
|
||||
},
|
||||
set(v) {
|
||||
component_settings.set_string(key.name, v);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case Type.C:
|
||||
Object.defineProperty(component, property_name, {
|
||||
// returns the array [red, blue, green, alpha] with
|
||||
// values between 0 and 1
|
||||
get() {
|
||||
let val = component_settings.get_value(key.name);
|
||||
return val.deep_unpack();
|
||||
},
|
||||
// takes an array [red, blue, green, alpha] with
|
||||
// values between 0 and 1
|
||||
set(v) {
|
||||
let val = new GLib.Variant("(dddd)", v);
|
||||
component_settings.set_value(key.name, val);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case Type.AS:
|
||||
Object.defineProperty(component, property_name, {
|
||||
get() {
|
||||
let val = component_settings.get_value(key.name);
|
||||
return val.deep_unpack();
|
||||
},
|
||||
set(v) {
|
||||
let val = new GLib.Variant("as", v);
|
||||
component_settings.set_value(key.name, val);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
component[property_name + '_reset'] = function () {
|
||||
return component_settings.reset(key.name);
|
||||
};
|
||||
|
||||
component[property_name + '_changed'] = function (cb) {
|
||||
return component_settings.connect('changed::' + key.name, cb);
|
||||
};
|
||||
|
||||
component[property_name + '_disconnect'] = function () {
|
||||
return component_settings.disconnect.apply(
|
||||
component_settings, arguments
|
||||
);
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/// Reset the preferences.
|
||||
reset() {
|
||||
this.keys.forEach(bundle => {
|
||||
let component = this;
|
||||
if (bundle.component !== "general") {
|
||||
let bundle_component = bundle.component.replaceAll('-', '_');
|
||||
component = this[bundle_component];
|
||||
}
|
||||
|
||||
bundle.schemas.forEach(key => {
|
||||
let property_name = this.get_property_name(key.name);
|
||||
component[property_name + '_reset']();
|
||||
});
|
||||
});
|
||||
|
||||
this.emit('reset', true);
|
||||
}
|
||||
|
||||
/// From the gschema name, returns the name of the associated property on
|
||||
/// the Settings object.
|
||||
get_property_name(name) {
|
||||
return name.replaceAll('-', '_').toUpperCase();
|
||||
}
|
||||
|
||||
/// Remove all connections managed by the Settings object, i.e. created with
|
||||
/// `settings.PROPERTY_changed(callback)`.
|
||||
disconnect_all_settings() {
|
||||
this.keys.forEach(bundle => {
|
||||
let component = this;
|
||||
if (bundle.component !== "general") {
|
||||
let bundle_component = bundle.component.replaceAll('-', '_');
|
||||
component = this[bundle_component];
|
||||
}
|
||||
|
||||
bundle.schemas.forEach(key => {
|
||||
let property_name = this.get_property_name(key.name);
|
||||
component[property_name + '_disconnect']();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(Settings.prototype);
|
||||
@ -0,0 +1,58 @@
|
||||
import Gio from 'gi://Gio';
|
||||
|
||||
const bus_name = 'org.gnome.Shell';
|
||||
const iface_name = 'dev.aunetx.BlurMyShell';
|
||||
const obj_path = '/dev/aunetx/BlurMyShell';
|
||||
|
||||
|
||||
/// Call pick() from the DBus service, it will open the Inspector from
|
||||
/// gnome-shell to pick an actor on stage.
|
||||
export function pick() {
|
||||
Gio.DBus.session.call(
|
||||
bus_name,
|
||||
obj_path,
|
||||
iface_name,
|
||||
'pick',
|
||||
null,
|
||||
null,
|
||||
Gio.DBusCallFlags.NO_AUTO_START,
|
||||
-1,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
/// Connect to DBus 'picking' signal, which will be emitted when the inspector
|
||||
/// is picking a window.
|
||||
export function on_picking(cb) {
|
||||
const id = Gio.DBus.session.signal_subscribe(
|
||||
bus_name,
|
||||
iface_name,
|
||||
'picking',
|
||||
obj_path,
|
||||
null,
|
||||
Gio.DBusSignalFlags.NONE,
|
||||
_ => {
|
||||
cb();
|
||||
Gio.DBus.session.signal_unsubscribe(id);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// Connect to DBus 'picked' signal, which will be emitted when a window is
|
||||
/// picked.
|
||||
export function on_picked(cb) {
|
||||
const id = Gio.DBus.session.signal_subscribe(
|
||||
bus_name,
|
||||
iface_name,
|
||||
'picked',
|
||||
obj_path,
|
||||
null,
|
||||
Gio.DBusSignalFlags.NONE,
|
||||
(conn, sender, obj_path, iface, signal, params) => {
|
||||
const val = params.get_child_value(0);
|
||||
cb(val.get_string()[0]);
|
||||
Gio.DBus.session.signal_unsubscribe(id);
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
<node>
|
||||
<interface name="dev.aunetx.BlurMyShell">
|
||||
<!-- This method is called in preferences to pick a window -->
|
||||
<method name="pick" />
|
||||
<!-- When window is picking, send a signal to preferences -->
|
||||
<signal name="picking"></signal>
|
||||
<!-- If window is picked, send a signal to preferences -->
|
||||
<signal name="picked">
|
||||
<arg name="window" type="s" />
|
||||
</signal>
|
||||
</interface>
|
||||
</node>
|
||||
@ -0,0 +1,90 @@
|
||||
import Gio from 'gi://Gio';
|
||||
import GLib from 'gi://GLib';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js';
|
||||
|
||||
|
||||
export const ApplicationsService = class ApplicationsService {
|
||||
constructor() {
|
||||
let decoder = new TextDecoder();
|
||||
let path = GLib.filename_from_uri(GLib.uri_resolve_relative(
|
||||
import.meta.url, 'iface.xml', GLib.UriFlags.NONE)
|
||||
)[0];
|
||||
let [, buffer] = GLib.file_get_contents(path);
|
||||
let iface = decoder.decode(buffer);
|
||||
GLib.free(buffer);
|
||||
|
||||
this.DBusImpl = Gio.DBusExportedObject.wrapJSObject(iface, this);
|
||||
}
|
||||
|
||||
/// Pick Window for Preferences Page, exported to DBus client.
|
||||
pick() {
|
||||
// emit `picking` signal to know we are listening
|
||||
const send_picking_signal = _ =>
|
||||
this.DBusImpl.emit_signal(
|
||||
'picking',
|
||||
null
|
||||
);
|
||||
|
||||
// emit `picked` signal to send wm_class
|
||||
const send_picked_signal = wm_class =>
|
||||
this.DBusImpl.emit_signal(
|
||||
'picked',
|
||||
new GLib.Variant('(s)', [wm_class])
|
||||
);
|
||||
|
||||
// notify the preferences that we are listening
|
||||
send_picking_signal();
|
||||
|
||||
// A very interesting way to pick a window:
|
||||
// 1. Open LookingGlass to mask all event handles of window
|
||||
// 2. Use inspector to pick window, thats is also lookingGlass do
|
||||
// 3. Close LookingGlass when done
|
||||
// It will restore event handles of window
|
||||
|
||||
// open then hide LookingGlass
|
||||
const looking_class = Main.createLookingGlass();
|
||||
looking_class.open();
|
||||
looking_class.hide();
|
||||
|
||||
// inspect window now
|
||||
const inspector = new LookingGlass.Inspector(Main.createLookingGlass());
|
||||
inspector.connect('target', (me, target, x, y) => {
|
||||
// remove border effect when window is picked.
|
||||
const effect_name = 'lookingGlass_RedBorderEffect';
|
||||
target
|
||||
.get_effects()
|
||||
.filter(e => e.toString().includes(effect_name))
|
||||
.forEach(e => target.remove_effect(e));
|
||||
|
||||
// get wm_class_instance property of window, then pass it to DBus
|
||||
// client
|
||||
const type_str = target.toString();
|
||||
|
||||
let actor = target;
|
||||
if (type_str.includes('MetaSurfaceActor'))
|
||||
actor = target.get_parent();
|
||||
|
||||
if (!actor.toString().includes('WindowActor'))
|
||||
return send_picked_signal('window-not-found');
|
||||
|
||||
send_picked_signal(
|
||||
actor.meta_window.get_wm_class() ?? 'window-not-found'
|
||||
);
|
||||
});
|
||||
|
||||
// close LookingGlass when we're done
|
||||
inspector.connect('closed', _ => looking_class.close());
|
||||
}
|
||||
|
||||
export() {
|
||||
this.DBusImpl.export(
|
||||
Gio.DBus.session,
|
||||
'/dev/aunetx/BlurMyShell'
|
||||
);
|
||||
};
|
||||
|
||||
unexport() {
|
||||
this.DBusImpl.unexport();
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,13 @@
|
||||
uniform sampler2D tex;
|
||||
uniform float red;
|
||||
uniform float green;
|
||||
uniform float blue;
|
||||
uniform float blend;
|
||||
|
||||
void main() {
|
||||
vec4 c = texture2D(tex, cogl_tex_coord_in[0].st);
|
||||
vec3 pix_color = c.xyz;
|
||||
vec3 color = vec3(red, green, blue);
|
||||
|
||||
cogl_color_out = vec4(mix(pix_color, color, blend), 1.);
|
||||
}
|
||||
@ -0,0 +1,181 @@
|
||||
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, 'color_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;
|
||||
}
|
||||
};
|
||||
|
||||
/// New Clutter Shader Effect that simply mixes a color in, the class applies
|
||||
/// the GLSL shader programmed into vfunc_get_static_shader_source and applies
|
||||
/// it to an Actor.
|
||||
///
|
||||
/// Clutter Shader Source Code:
|
||||
/// https://github.com/GNOME/clutter/blob/master/clutter/clutter-shader-effect.c
|
||||
///
|
||||
/// GJS Doc:
|
||||
/// https://gjs-docs.gnome.org/clutter10~10_api/clutter.shadereffect
|
||||
export const ColorEffect = new GObject.registerClass({
|
||||
GTypeName: "ColorEffect",
|
||||
Properties: {
|
||||
'red': GObject.ParamSpec.double(
|
||||
`red`,
|
||||
`Red`,
|
||||
`Red value in shader`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
'green': GObject.ParamSpec.double(
|
||||
`green`,
|
||||
`Green`,
|
||||
`Green value in shader`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
'blue': GObject.ParamSpec.double(
|
||||
`blue`,
|
||||
`Blue`,
|
||||
`Blue value in shader`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
'blend': GObject.ParamSpec.double(
|
||||
`blend`,
|
||||
`Blend`,
|
||||
`Amount of blending between the colors`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
}
|
||||
}, class ColorShader extends Clutter.ShaderEffect {
|
||||
constructor(params, settings) {
|
||||
// initialize without color as a parameter
|
||||
let _color = params.color;
|
||||
delete params.color;
|
||||
|
||||
super(params);
|
||||
|
||||
this._red = null;
|
||||
this._green = null;
|
||||
this._blue = null;
|
||||
this._blend = null;
|
||||
|
||||
this._static = true;
|
||||
this._settings = settings;
|
||||
|
||||
// set shader source
|
||||
this._source = get_shader_source();
|
||||
if (this._source)
|
||||
this.set_shader_source(this._source);
|
||||
|
||||
// set shader color
|
||||
if (_color)
|
||||
this.color = _color;
|
||||
|
||||
this.update_enabled();
|
||||
}
|
||||
|
||||
get red() {
|
||||
return this._red;
|
||||
}
|
||||
|
||||
set red(value) {
|
||||
if (this._red !== value) {
|
||||
this._red = value;
|
||||
|
||||
this.set_uniform_value('red', parseFloat(this._red - 1e-6));
|
||||
}
|
||||
}
|
||||
|
||||
get green() {
|
||||
return this._green;
|
||||
}
|
||||
|
||||
set green(value) {
|
||||
if (this._green !== value) {
|
||||
this._green = value;
|
||||
|
||||
this.set_uniform_value('green', parseFloat(this._green - 1e-6));
|
||||
}
|
||||
}
|
||||
|
||||
get blue() {
|
||||
return this._blue;
|
||||
}
|
||||
|
||||
set blue(value) {
|
||||
if (this._blue !== value) {
|
||||
this._blue = value;
|
||||
|
||||
this.set_uniform_value('blue', parseFloat(this._blue - 1e-6));
|
||||
}
|
||||
}
|
||||
|
||||
get blend() {
|
||||
return this._blend;
|
||||
}
|
||||
|
||||
set blend(value) {
|
||||
if (this._blend !== value) {
|
||||
this._blend = value;
|
||||
|
||||
this.set_uniform_value('blend', parseFloat(this._blend - 1e-6));
|
||||
}
|
||||
this.update_enabled();
|
||||
}
|
||||
|
||||
set color(rgba) {
|
||||
let [r, g, b, a] = rgba;
|
||||
this.red = r;
|
||||
this.green = g;
|
||||
this.blue = b;
|
||||
this.blend = a;
|
||||
}
|
||||
|
||||
get color() {
|
||||
return [this.red, this.green, this.blue, this.blend];
|
||||
}
|
||||
|
||||
/// False set function, only cares about the color. Too hard to change.
|
||||
set(params) {
|
||||
this.color = params.color;
|
||||
}
|
||||
|
||||
update_enabled() {
|
||||
// don't anything if this._settings is undefined (when calling super)
|
||||
if (this._settings === undefined)
|
||||
return;
|
||||
|
||||
this.set_enabled(
|
||||
this.blend > 0 &&
|
||||
this._settings.COLOR_AND_NOISE &&
|
||||
this._static
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
vfunc_paint_target(paint_node = null, paint_context = null) {
|
||||
this.set_uniform_value("tex", 0);
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,20 @@
|
||||
uniform sampler2D tex;
|
||||
uniform float noise;
|
||||
uniform float lightness;
|
||||
|
||||
float PHI = 1.61803398874989484820459;
|
||||
float SEED = 24;
|
||||
|
||||
float noise_gen(in vec2 xy) {
|
||||
float r = fract(tan(distance(xy * PHI, xy) * SEED) * xy.x);
|
||||
r = r != r ? 0.0 : r;
|
||||
return r;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 c = texture2D(tex, cogl_tex_coord_in[0].st);
|
||||
vec3 pix_color = c.xyz;
|
||||
float blend = noise * (1. - noise_gen(gl_FragCoord.xy));
|
||||
|
||||
cogl_color_out = vec4(mix(pix_color, lightness * pix_color, blend), 1.);
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
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, 'noise_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 NoiseEffect = new GObject.registerClass({
|
||||
GTypeName: "NoiseEffect",
|
||||
Properties: {
|
||||
'noise': GObject.ParamSpec.double(
|
||||
`noise`,
|
||||
`Noise`,
|
||||
`Amount of noise integrated with the image`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
'lightness': GObject.ParamSpec.double(
|
||||
`lightness`,
|
||||
`Lightness`,
|
||||
`Lightness of the grey used for the noise`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 2.0,
|
||||
0.4,
|
||||
),
|
||||
}
|
||||
}, class NoiseShader extends Clutter.ShaderEffect {
|
||||
constructor(params, settings) {
|
||||
super(params);
|
||||
|
||||
this._noise = null;
|
||||
this._lightness = null;
|
||||
|
||||
this._static = true;
|
||||
this._settings = settings;
|
||||
|
||||
if (params.noise)
|
||||
this.noise = params.noise;
|
||||
if (params.lightness)
|
||||
this.lightness = params.lightness;
|
||||
|
||||
// set shader source
|
||||
this._source = get_shader_source();
|
||||
if (this._source)
|
||||
this.set_shader_source(this._source);
|
||||
|
||||
this.update_enabled();
|
||||
}
|
||||
|
||||
get noise() {
|
||||
return this._noise;
|
||||
}
|
||||
|
||||
set noise(value) {
|
||||
if (this._noise !== value) {
|
||||
this._noise = value;
|
||||
|
||||
this.set_uniform_value('noise', parseFloat(this._noise - 1e-6));
|
||||
}
|
||||
this.update_enabled();
|
||||
}
|
||||
|
||||
get lightness() {
|
||||
return this._lightness;
|
||||
}
|
||||
|
||||
set lightness(value) {
|
||||
if (this._lightness !== value) {
|
||||
this._lightness = value;
|
||||
|
||||
this.set_uniform_value('lightness', parseFloat(this._lightness - 1e-6));
|
||||
}
|
||||
}
|
||||
|
||||
update_enabled() {
|
||||
// don't anything if this._settings is undefined (when calling super)
|
||||
if (this._settings === undefined)
|
||||
return;
|
||||
|
||||
this.set_enabled(
|
||||
this.noise > 0 &&
|
||||
this._settings.COLOR_AND_NOISE &&
|
||||
this._static
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
vfunc_paint_target(paint_node = null, paint_context = null) {
|
||||
this.set_uniform_value("tex", 0);
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,89 @@
|
||||
import GObject from 'gi://GObject';
|
||||
import Clutter from 'gi://Clutter';
|
||||
|
||||
|
||||
export const PaintSignals = class PaintSignals {
|
||||
constructor(connections) {
|
||||
this.buffer = [];
|
||||
this.connections = connections;
|
||||
}
|
||||
|
||||
connect(actor, blur_effect) {
|
||||
let paint_effect = new EmitPaintSignal();
|
||||
let infos = {
|
||||
actor: actor,
|
||||
paint_effect: paint_effect
|
||||
};
|
||||
let counter = 0;
|
||||
|
||||
actor.add_effect(paint_effect);
|
||||
this.connections.connect(paint_effect, 'update-blur', () => {
|
||||
try {
|
||||
// checking if blur_effect.queue_repaint() has been recently called
|
||||
if (counter === 0) {
|
||||
counter = 2;
|
||||
blur_effect.queue_repaint();
|
||||
}
|
||||
else counter--;
|
||||
} catch (e) { }
|
||||
});
|
||||
|
||||
// remove the actor from buffer when it is destroyed
|
||||
if (
|
||||
actor.connect &&
|
||||
(
|
||||
!(actor instanceof GObject.Object) ||
|
||||
GObject.signal_lookup('destroy', actor)
|
||||
)
|
||||
)
|
||||
this.connections.connect(actor, 'destroy', () => {
|
||||
this.buffer.forEach(infos => {
|
||||
if (infos.actor === actor) {
|
||||
// remove from buffer
|
||||
let index = this.buffer.indexOf(infos);
|
||||
this.buffer.splice(index, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.buffer.push(infos);
|
||||
}
|
||||
|
||||
disconnect_all_for_actor(actor) {
|
||||
this.buffer.forEach(infos => {
|
||||
if (infos.actor === actor) {
|
||||
this.connections.disconnect_all_for(infos.paint_effect);
|
||||
infos.actor.remove_effect(infos.paint_effect);
|
||||
|
||||
// remove from buffer
|
||||
let index = this.buffer.indexOf(infos);
|
||||
this.buffer.splice(index, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
disconnect_all() {
|
||||
this.buffer.forEach(infos => {
|
||||
this.connections.disconnect_all_for(infos.paint_effect);
|
||||
infos.actor.remove_effect(infos.paint_effect);
|
||||
});
|
||||
|
||||
this.buffer = [];
|
||||
}
|
||||
};
|
||||
|
||||
export const EmitPaintSignal = GObject.registerClass({
|
||||
GTypeName: 'EmitPaintSignal',
|
||||
Signals: {
|
||||
'update-blur': {
|
||||
param_types: []
|
||||
},
|
||||
}
|
||||
},
|
||||
class EmitPaintSignal extends Clutter.Effect {
|
||||
vfunc_paint(node, paint_context, paint_flags) {
|
||||
this.emit("update-blur");
|
||||
super.vfunc_paint(node, paint_context, paint_flags);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -0,0 +1,641 @@
|
||||
import Meta from 'gi://Meta';
|
||||
import Clutter from 'gi://Clutter';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
|
||||
import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js';
|
||||
|
||||
import { EffectsManager } from './conveniences/effects_manager.js';
|
||||
import { Connections } from './conveniences/connections.js';
|
||||
import { Settings } from './conveniences/settings.js';
|
||||
import { Keys } from './conveniences/keys.js';
|
||||
|
||||
import { PanelBlur } from './components/panel.js';
|
||||
import { OverviewBlur } from './components/overview.js';
|
||||
import { DashBlur } from './components/dash_to_dock.js';
|
||||
import { LockscreenBlur } from './components/lockscreen.js';
|
||||
import { AppFoldersBlur } from './components/appfolders.js';
|
||||
import { WindowListBlur } from './components/window_list.js';
|
||||
import { ApplicationsBlur } from './components/applications.js';
|
||||
import { ScreenshotBlur } from './components/screenshot.js';
|
||||
|
||||
// This lists the components that need to be connected in order to either use
|
||||
// general sigma/brightness or their own.
|
||||
const INDEPENDENT_COMPONENTS = [
|
||||
"overview", "appfolder", "panel", "dash_to_dock", "applications",
|
||||
"lockscreen", "window_list", "screenshot"
|
||||
];
|
||||
|
||||
|
||||
/// The main extension class, created when the GNOME Shell is loaded.
|
||||
export default class BlurMyShell extends Extension {
|
||||
/// Enables the extension
|
||||
enable() {
|
||||
// add the extension to global to make it accessible to other extensions
|
||||
// create it first as it is very useful when debugging crashes
|
||||
global.blur_my_shell = this;
|
||||
|
||||
// create a Settings instance, to manage extension's preferences
|
||||
// it needs to be loaded before logging, as it checks for DEBUG
|
||||
this._settings = new Settings(Keys, this.getSettings());
|
||||
|
||||
this._log("enabling extension...");
|
||||
|
||||
// create main extension Connections instance
|
||||
this._connection = new Connections;
|
||||
|
||||
// store it in a global array
|
||||
this._connections = [this._connection];
|
||||
|
||||
// create a global effects manager (to prevent RAM bleeding)
|
||||
this._effects_manager = new EffectsManager(this._connection);
|
||||
|
||||
// create an instance of each component, with its associated Connections
|
||||
let init = _ => {
|
||||
// create a Connections instance, to manage signals
|
||||
let connection = new Connections;
|
||||
|
||||
// store it to keeps track of them globally
|
||||
this._connections.push(connection);
|
||||
|
||||
return [connection, this._settings, this._effects_manager];
|
||||
};
|
||||
|
||||
this._panel_blur = new PanelBlur(...init());
|
||||
this._dash_to_dock_blur = new DashBlur(...init());
|
||||
this._overview_blur = new OverviewBlur(...init());
|
||||
this._lockscreen_blur = new LockscreenBlur(...init());
|
||||
this._appfolder_blur = new AppFoldersBlur(...init());
|
||||
this._window_list_blur = new WindowListBlur(...init());
|
||||
this._applications_blur = new ApplicationsBlur(...init());
|
||||
this._screenshot_blur = new ScreenshotBlur(...init());
|
||||
|
||||
// maybe disable clipped redraw
|
||||
this._update_clipped_redraws();
|
||||
|
||||
// connect each component to preferences change
|
||||
this._connect_to_settings();
|
||||
|
||||
// enable every component
|
||||
// if the shell is still starting up, wait for it to be entirely loaded;
|
||||
// this should prevent bugs like #136 and #137
|
||||
if (Main.layoutManager._startingUp) {
|
||||
this._connection.connect(
|
||||
Main.layoutManager,
|
||||
'startup-complete',
|
||||
this._enable_components.bind(this)
|
||||
);
|
||||
} else {
|
||||
this._enable_components();
|
||||
}
|
||||
|
||||
// try to enable the components as soon as possible anyway, this way the
|
||||
// overview may load before the user sees it
|
||||
try {
|
||||
if (this._settings.overview.BLUR && !this._overview_blur.enabled)
|
||||
this._overview_blur.enable();
|
||||
} catch (e) {
|
||||
this._log("Could not enable overview blur directly");
|
||||
this._log(e);
|
||||
}
|
||||
try {
|
||||
if (this._settings.dash_to_dock.BLUR
|
||||
&& !this._dash_to_dock_blur.enabled)
|
||||
this._dash_to_dock_blur.enable();
|
||||
} catch (e) {
|
||||
this._log("Could not enable dash-to-dock blur directly");
|
||||
this._log(e);
|
||||
}
|
||||
try {
|
||||
if (this._settings.panel.BLUR && !this._panel_blur.enabled)
|
||||
this._panel_blur.enable();
|
||||
} catch (e) {
|
||||
this._log("Could not enable panel blur directly");
|
||||
this._log(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Disables the extension
|
||||
disable() {
|
||||
this._log("disabling extension...");
|
||||
|
||||
// disable every component
|
||||
this._panel_blur.disable();
|
||||
this._dash_to_dock_blur.disable();
|
||||
this._overview_blur.disable();
|
||||
this._lockscreen_blur.disable();
|
||||
this._appfolder_blur.disable();
|
||||
this._window_list_blur.disable();
|
||||
this._applications_blur.disable();
|
||||
this._screenshot_blur.disable();
|
||||
|
||||
// untrack them
|
||||
this._panel_blur = null;
|
||||
this._dash_to_dock_blur = null;
|
||||
this._overview_blur = null;
|
||||
this._lockscreen_blur = null;
|
||||
this._appfolder_blur = null;
|
||||
this._window_list_blur = null;
|
||||
this._applications_blur = null;
|
||||
|
||||
// make sure no settings change can re-enable them
|
||||
this._settings.disconnect_all_settings();
|
||||
|
||||
// force disconnecting every signal, even if component crashed
|
||||
this._connections.forEach((connections) => {
|
||||
connections.disconnect_all();
|
||||
});
|
||||
this._connections = [];
|
||||
|
||||
// remove the clipped redraws flag
|
||||
this._reenable_clipped_redraws();
|
||||
|
||||
// remove the extension from GJS's global
|
||||
delete global.blur_my_shell;
|
||||
|
||||
this._log("extension disabled.");
|
||||
|
||||
this._settings = null;
|
||||
}
|
||||
|
||||
/// Restart the extension.
|
||||
_restart() {
|
||||
this._log("restarting...");
|
||||
|
||||
this.disable();
|
||||
this.enable();
|
||||
|
||||
this._log("restarted.");
|
||||
}
|
||||
|
||||
/// Add or remove the clutter debug flag to disable clipped redraws.
|
||||
/// This will entirely fix the blur effect, but should not be used except if
|
||||
/// the user really needs it, as clipped redraws are a huge performance
|
||||
/// boost for the compositor.
|
||||
_update_clipped_redraws() {
|
||||
if (this._settings.HACKS_LEVEL === 3)
|
||||
this._disable_clipped_redraws();
|
||||
else
|
||||
this._reenable_clipped_redraws();
|
||||
}
|
||||
|
||||
/// Add the Clutter debug flag.
|
||||
_disable_clipped_redraws() {
|
||||
Meta.add_clutter_debug_flags(
|
||||
null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null
|
||||
);
|
||||
}
|
||||
|
||||
/// Remove the Clutter debug flag.
|
||||
_reenable_clipped_redraws() {
|
||||
Meta.remove_clutter_debug_flags(
|
||||
null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null
|
||||
);
|
||||
}
|
||||
|
||||
/// Enables every component needed, should be called when the shell is
|
||||
/// entirely loaded as the `enable` methods interact with it.
|
||||
_enable_components() {
|
||||
// enable each component if needed, and if it is not already enabled
|
||||
|
||||
if (this._settings.panel.BLUR && !this._panel_blur.enabled)
|
||||
this._panel_blur.enable();
|
||||
|
||||
if (this._settings.dash_to_dock.BLUR && !this._dash_to_dock_blur.enabled)
|
||||
this._dash_to_dock_blur.enable();
|
||||
|
||||
if (this._settings.overview.BLUR && !this._overview_blur.enabled)
|
||||
this._overview_blur.enable();
|
||||
|
||||
if (this._settings.lockscreen.BLUR)
|
||||
this._lockscreen_blur.enable();
|
||||
|
||||
if (this._settings.appfolder.BLUR)
|
||||
this._appfolder_blur.enable();
|
||||
|
||||
if (this._settings.applications.BLUR)
|
||||
this._applications_blur.enable();
|
||||
|
||||
if (this._settings.window_list.BLUR)
|
||||
this._window_list_blur.enable();
|
||||
|
||||
if (this._settings.screenshot.BLUR)
|
||||
this._screenshot_blur.enable();
|
||||
|
||||
this._log("all components enabled.");
|
||||
}
|
||||
|
||||
/// Updates needed things in each component when a preference changed
|
||||
_connect_to_settings() {
|
||||
|
||||
// global blur values changed, update everybody
|
||||
|
||||
this._settings.SIGMA_changed(() => {
|
||||
this._update_sigma();
|
||||
});
|
||||
this._settings.BRIGHTNESS_changed(() => {
|
||||
this._update_brightness();
|
||||
});
|
||||
this._settings.COLOR_changed(() => {
|
||||
this._update_color();
|
||||
});
|
||||
this._settings.NOISE_AMOUNT_changed(() => {
|
||||
this._update_noise_amount();
|
||||
});
|
||||
this._settings.NOISE_LIGHTNESS_changed(() => {
|
||||
this._update_noise_lightness();
|
||||
});
|
||||
this._settings.COLOR_AND_NOISE_changed(() => {
|
||||
// both updating noise amount and color calls `update_enabled` on
|
||||
// each color and noise effects
|
||||
this._update_noise_amount();
|
||||
this._update_color();
|
||||
});
|
||||
|
||||
// restart the extension when hacks level is changed, easier than
|
||||
// restarting individual components and should not happen often either
|
||||
this._settings.HACKS_LEVEL_changed(_ => this._restart());
|
||||
|
||||
// connect each component to use the proper sigma/brightness/color
|
||||
INDEPENDENT_COMPONENTS.forEach(component => {
|
||||
this._connect_to_individual_settings(component);
|
||||
});
|
||||
|
||||
// other component's preferences changed
|
||||
|
||||
// ---------- OVERVIEW ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.overview.BLUR_changed(() => {
|
||||
if (this._settings.overview.BLUR) {
|
||||
this._overview_blur.enable();
|
||||
} else {
|
||||
this._overview_blur.disable();
|
||||
}
|
||||
});
|
||||
|
||||
// overview components style changed
|
||||
this._settings.overview.STYLE_COMPONENTS_changed(() => {
|
||||
if (this._settings.overview.BLUR) {
|
||||
this._overview_blur.update_components_classname();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ---------- APPFOLDER ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.appfolder.BLUR_changed(() => {
|
||||
if (this._settings.appfolder.BLUR) {
|
||||
this._appfolder_blur.enable();
|
||||
} else {
|
||||
this._appfolder_blur.disable();
|
||||
}
|
||||
});
|
||||
|
||||
// appfolder dialogs style changed
|
||||
this._settings.appfolder.STYLE_DIALOGS_changed(() => {
|
||||
if (this._settings.appfolder.BLUR)
|
||||
this._appfolder_blur.blur_appfolders();
|
||||
});
|
||||
|
||||
|
||||
// ---------- PANEL ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.panel.BLUR_changed(() => {
|
||||
if (this._settings.panel.BLUR) {
|
||||
this._panel_blur.enable();
|
||||
} else {
|
||||
this._panel_blur.disable();
|
||||
}
|
||||
});
|
||||
|
||||
this._settings.COLOR_AND_NOISE_changed(() => {
|
||||
// permits making sure that the blur is not washed out when disabling
|
||||
// the other effects
|
||||
if (this._settings.panel.BLUR)
|
||||
this._panel_blur.invalidate_all_blur();
|
||||
});
|
||||
|
||||
// static blur toggled on/off
|
||||
this._settings.panel.STATIC_BLUR_changed(() => {
|
||||
if (this._settings.panel.BLUR)
|
||||
this._panel_blur.update_all_blur_type();
|
||||
});
|
||||
|
||||
// panel blur's overview connection toggled on/off
|
||||
this._settings.panel.UNBLUR_IN_OVERVIEW_changed(() => {
|
||||
this._panel_blur.connect_to_windows_and_overview();
|
||||
});
|
||||
|
||||
// panel override background toggled on/off
|
||||
this._settings.panel.OVERRIDE_BACKGROUND_changed(() => {
|
||||
if (this._settings.panel.BLUR)
|
||||
this._panel_blur.connect_to_windows_and_overview();
|
||||
});
|
||||
|
||||
// panel style changed
|
||||
this._settings.panel.STYLE_PANEL_changed(() => {
|
||||
if (this._settings.panel.BLUR)
|
||||
this._panel_blur.connect_to_windows_and_overview();
|
||||
});
|
||||
|
||||
// panel background's dynamic overriding toggled on/off
|
||||
this._settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_changed(() => {
|
||||
if (this._settings.panel.BLUR)
|
||||
this._panel_blur.connect_to_windows_and_overview();
|
||||
});
|
||||
|
||||
|
||||
// ---------- DASH TO DOCK ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.dash_to_dock.BLUR_changed(() => {
|
||||
if (this._settings.dash_to_dock.BLUR) {
|
||||
this._dash_to_dock_blur.enable();
|
||||
} else {
|
||||
this._dash_to_dock_blur.disable();
|
||||
}
|
||||
});
|
||||
|
||||
// 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();
|
||||
});
|
||||
|
||||
// dash-to-dock override background toggled on/off
|
||||
this._settings.dash_to_dock.OVERRIDE_BACKGROUND_changed(() => {
|
||||
if (this._settings.dash_to_dock.BLUR)
|
||||
this._dash_to_dock_blur.update_background();
|
||||
});
|
||||
|
||||
// dash-to-dock style changed
|
||||
this._settings.dash_to_dock.STYLE_DASH_TO_DOCK_changed(() => {
|
||||
if (this._settings.dash_to_dock.BLUR)
|
||||
this._dash_to_dock_blur.update_background();
|
||||
});
|
||||
|
||||
// dash-to-dock blur's overview connection toggled on/off
|
||||
this._settings.dash_to_dock.UNBLUR_IN_OVERVIEW_changed(() => {
|
||||
if (this._settings.dash_to_dock.BLUR)
|
||||
this._dash_to_dock_blur.connect_to_overview();
|
||||
});
|
||||
|
||||
|
||||
// ---------- APPLICATIONS ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.applications.BLUR_changed(() => {
|
||||
if (this._settings.applications.BLUR) {
|
||||
this._applications_blur.enable();
|
||||
} else {
|
||||
this._applications_blur.disable();
|
||||
}
|
||||
});
|
||||
|
||||
// application opacity changed
|
||||
this._settings.applications.OPACITY_changed(_ => {
|
||||
if (this._settings.applications.BLUR)
|
||||
this._applications_blur.set_opacity(
|
||||
this._settings.applications.OPACITY
|
||||
);
|
||||
});
|
||||
|
||||
// application blur-on-overview changed
|
||||
this._settings.applications.BLUR_ON_OVERVIEW_changed(_ => {
|
||||
if (this._settings.applications.BLUR)
|
||||
this._applications_blur.connect_to_overview();
|
||||
});
|
||||
|
||||
// application enable-all changed
|
||||
this._settings.applications.ENABLE_ALL_changed(_ => {
|
||||
if (this._settings.applications.BLUR)
|
||||
this._applications_blur.update_all_windows();
|
||||
});
|
||||
|
||||
// application whitelist changed
|
||||
this._settings.applications.WHITELIST_changed(_ => {
|
||||
if (
|
||||
this._settings.applications.BLUR
|
||||
&& !this._settings.applications.ENABLE_ALL
|
||||
)
|
||||
this._applications_blur.update_all_windows();
|
||||
});
|
||||
|
||||
// application blacklist changed
|
||||
this._settings.applications.BLACKLIST_changed(_ => {
|
||||
if (
|
||||
this._settings.applications.BLUR
|
||||
&& this._settings.applications.ENABLE_ALL
|
||||
)
|
||||
this._applications_blur.update_all_windows();
|
||||
});
|
||||
|
||||
|
||||
// ---------- LOCKSCREEN ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.lockscreen.BLUR_changed(() => {
|
||||
if (this._settings.lockscreen.BLUR) {
|
||||
this._lockscreen_blur.enable();
|
||||
} else {
|
||||
this._lockscreen_blur.disable();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ---------- WINDOW LIST ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.window_list.BLUR_changed(() => {
|
||||
if (this._settings.window_list.BLUR) {
|
||||
this._window_list_blur.enable();
|
||||
} else {
|
||||
this._window_list_blur.disable();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ---------- HIDETOPBAR ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.hidetopbar.COMPATIBILITY_changed(() => {
|
||||
// no need to verify if it is enabled or not, it is done anyway
|
||||
this._panel_blur.connect_to_windows_and_overview();
|
||||
});
|
||||
|
||||
|
||||
// ---------- DASH TO PANEL ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.dash_to_panel.BLUR_ORIGINAL_PANEL_changed(() => {
|
||||
if (this._settings.panel.BLUR)
|
||||
this._panel_blur.reset();
|
||||
});
|
||||
|
||||
|
||||
// ---------- SCREENSHOT ----------
|
||||
|
||||
// toggled on/off
|
||||
this._settings.screenshot.BLUR_changed(() => {
|
||||
if (this._settings.screenshot.BLUR) {
|
||||
this._screenshot_blur.enable();
|
||||
} else {
|
||||
this._screenshot_blur.disable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Select the component by its name and connect it to its preferences
|
||||
/// changes for general values, sigma and brightness.
|
||||
///
|
||||
/// Doing this in such a way is less accessible but prevents a lot of
|
||||
/// boilerplate and headaches.
|
||||
_connect_to_individual_settings(name) {
|
||||
// get component and preferences needed
|
||||
let component = this['_' + name + '_blur'];
|
||||
let component_settings = this._settings[name];
|
||||
|
||||
// general values switch is toggled
|
||||
component_settings.CUSTOMIZE_changed(() => {
|
||||
if (component_settings.CUSTOMIZE) {
|
||||
component.set_sigma(component_settings.SIGMA);
|
||||
component.set_brightness(component_settings.BRIGHTNESS);
|
||||
component.set_color(component_settings.COLOR);
|
||||
component.set_noise_amount(component_settings.NOISE_AMOUNT);
|
||||
component.set_noise_lightness(component_settings.NOISE_LIGHTNESS);
|
||||
}
|
||||
else {
|
||||
component.set_sigma(this._settings.SIGMA);
|
||||
component.set_brightness(this._settings.BRIGHTNESS);
|
||||
component.set_color(this._settings.COLOR);
|
||||
component.set_noise_amount(this._settings.NOISE_AMOUNT);
|
||||
component.set_noise_lightness(this._settings.NOISE_LIGHTNESS);
|
||||
}
|
||||
});
|
||||
|
||||
// sigma is changed
|
||||
component_settings.SIGMA_changed(() => {
|
||||
if (component_settings.CUSTOMIZE)
|
||||
component.set_sigma(component_settings.SIGMA);
|
||||
else
|
||||
component.set_sigma(this._settings.SIGMA);
|
||||
});
|
||||
|
||||
// brightness is changed
|
||||
component_settings.BRIGHTNESS_changed(() => {
|
||||
if (component_settings.CUSTOMIZE)
|
||||
component.set_brightness(component_settings.BRIGHTNESS);
|
||||
else
|
||||
component.set_brightness(this._settings.BRIGHTNESS);
|
||||
});
|
||||
|
||||
// color is changed
|
||||
component_settings.COLOR_changed(() => {
|
||||
if (component_settings.CUSTOMIZE)
|
||||
component.set_color(component_settings.COLOR);
|
||||
else
|
||||
component.set_color(this._settings.COLOR);
|
||||
});
|
||||
|
||||
// noise amount is changed
|
||||
component_settings.NOISE_AMOUNT_changed(() => {
|
||||
if (component_settings.CUSTOMIZE)
|
||||
component.set_noise_amount(component_settings.NOISE_AMOUNT);
|
||||
else
|
||||
component.set_noise_amount(this._settings.NOISE_AMOUNT);
|
||||
});
|
||||
|
||||
// noise lightness is changed
|
||||
component_settings.NOISE_LIGHTNESS_changed(() => {
|
||||
if (component_settings.CUSTOMIZE)
|
||||
component.set_noise_lightness(component_settings.NOISE_LIGHTNESS);
|
||||
else
|
||||
component.set_noise_lightness(this._settings.NOISE_LIGHTNESS);
|
||||
});
|
||||
}
|
||||
|
||||
/// Update each component's sigma value
|
||||
_update_sigma() {
|
||||
INDEPENDENT_COMPONENTS.forEach(name => {
|
||||
// get component and preferences needed
|
||||
let component = this['_' + name + '_blur'];
|
||||
let component_settings = this._settings[name];
|
||||
|
||||
// update sigma accordingly
|
||||
if (component_settings.CUSTOMIZE) {
|
||||
component.set_sigma(component_settings.SIGMA);
|
||||
}
|
||||
else {
|
||||
component.set_sigma(this._settings.SIGMA);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Update each component's brightness value
|
||||
_update_brightness() {
|
||||
INDEPENDENT_COMPONENTS.forEach(name => {
|
||||
// get component and preferences needed
|
||||
let component = this['_' + name + '_blur'];
|
||||
let component_settings = this._settings[name];
|
||||
|
||||
// update brightness accordingly
|
||||
if (component_settings.CUSTOMIZE)
|
||||
component.set_brightness(component_settings.BRIGHTNESS);
|
||||
else
|
||||
component.set_brightness(this._settings.BRIGHTNESS);
|
||||
});
|
||||
}
|
||||
|
||||
/// Update each component's color value
|
||||
_update_color() {
|
||||
INDEPENDENT_COMPONENTS.forEach(name => {
|
||||
// get component and preferences needed
|
||||
let component = this['_' + name + '_blur'];
|
||||
let component_settings = this._settings[name];
|
||||
|
||||
// update color accordingly
|
||||
if (component_settings.CUSTOMIZE)
|
||||
component.set_color(component_settings.COLOR);
|
||||
else
|
||||
component.set_color(this._settings.COLOR);
|
||||
});
|
||||
}
|
||||
|
||||
/// Update each component's noise amount value
|
||||
_update_noise_amount() {
|
||||
INDEPENDENT_COMPONENTS.forEach(name => {
|
||||
// get component and preferences needed
|
||||
let component = this['_' + name + '_blur'];
|
||||
let component_settings = this._settings[name];
|
||||
|
||||
// update color accordingly
|
||||
if (component_settings.CUSTOMIZE)
|
||||
component.set_noise_amount(component_settings.NOISE_AMOUNT);
|
||||
else
|
||||
component.set_noise_amount(this._settings.NOISE_AMOUNT);
|
||||
});
|
||||
}
|
||||
|
||||
/// Update each component's noise lightness value
|
||||
_update_noise_lightness() {
|
||||
INDEPENDENT_COMPONENTS.forEach(name => {
|
||||
// get component and preferences needed
|
||||
let component = this['_' + name + '_blur'];
|
||||
let component_settings = this._settings[name];
|
||||
|
||||
// update color accordingly
|
||||
if (component_settings.CUSTOMIZE)
|
||||
component.set_noise_lightness(component_settings.NOISE_LIGHTNESS);
|
||||
else
|
||||
component.set_noise_lightness(this._settings.NOISE_LIGHTNESS);
|
||||
});
|
||||
}
|
||||
|
||||
_log(str) {
|
||||
if (this._settings.DEBUG)
|
||||
console.log(`[Blur my Shell > extension] ${str}`);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="2" y="7" width="11" height="1" fill="#363636"/>
|
||||
<rect transform="rotate(90)" x="2" y="-8" width="11" height="1" fill="#363636"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 249 B |
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg7"
|
||||
sodipodi:docname="applications.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview9"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="44.6875"
|
||||
inkscape:cx="5.5944056"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-width="1500"
|
||||
inkscape:window-height="963"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg7" />
|
||||
<defs
|
||||
id="defs3">
|
||||
<style
|
||||
id="current-color-scheme"
|
||||
type="text/css">.ColorScheme-Text { color:#363636; }</style>
|
||||
</defs>
|
||||
<path
|
||||
d="M 2,1 C 0.892,1 0,1.892 0,3 v 9 c 0,1.108 0.892,2 2,2 h 12 c 1.108,0 2,-0.892 2,-2 V 3 C 16,1.892 15.108,1 14,1 Z m 0,1 h 12 c 0.554,0 1,0.446 1,1 H 1 C 1,2.446 1.446,2 2,2 Z M 1,3 h 14 v 9 c 0,0.554 -0.446,1 -1,1 H 2 C 1.446,13 1,12.554 1,12 Z"
|
||||
style="fill:currentColor"
|
||||
class="ColorScheme-Text"
|
||||
id="path5"
|
||||
sodipodi:nodetypes="sssssssssssccsccssssc" />
|
||||
<g
|
||||
id="g68"
|
||||
transform="translate(0.3993007,0.15314685)">
|
||||
<path
|
||||
d="M 9.5,4 C 9.223,4 9,4.223 9,4.5 v 2 A 0.499,0.499 0 0 0 9.5,7 h 2 C 11.777,7 12,6.777 12,6.5 v -2 C 12,4.223 11.777,4 11.5,4 Z M 10,5 h 1 v 1 h -1 z"
|
||||
fill="#363636"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M 4,6 C 3.446,6 3,6.446 3,7 v 3 c 0,0.554 0.446,1 1,1 h 3 c 0.554,0 1,-0.446 1,-1 V 7 C 8,6.446 7.554,6 7,6 Z m 0,1 h 3 v 3 H 4 Z"
|
||||
fill="#363636"
|
||||
id="path8" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg7"
|
||||
sodipodi:docname="panel.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview9"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="44.6875"
|
||||
inkscape:cx="5.5944056"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-width="1500"
|
||||
inkscape:window-height="963"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg7" />
|
||||
<defs
|
||||
id="defs3">
|
||||
<style
|
||||
id="current-color-scheme"
|
||||
type="text/css">.ColorScheme-Text { color:#363636; }</style>
|
||||
</defs>
|
||||
<path
|
||||
d="M 2,1 C 0.892,1 0,1.892 0,3 v 9 c 0,1.108 0.892,2 2,2 h 12 c 1.108,0 2,-0.892 2,-2 V 3 C 16,1.892 15.108,1 14,1 Z m 0,1 h 12 c 0.554,0 1,0.446 1,1 H 1 C 1,2.446 1.446,2 2,2 Z M 1,4 h 14 v 8 c 0,0.554 -0.446,1 -1,1 H 2 C 1.446,13 1,12.554 1,12 Z"
|
||||
style="fill:currentColor"
|
||||
class="ColorScheme-Text"
|
||||
id="path5"
|
||||
sodipodi:nodetypes="sssssssssssccsccssssc" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg7"
|
||||
sodipodi:docname="top-panel.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview9"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="44.6875"
|
||||
inkscape:cx="5.5944056"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-width="1500"
|
||||
inkscape:window-height="963"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg7" />
|
||||
<defs
|
||||
id="defs3">
|
||||
<style
|
||||
id="current-color-scheme"
|
||||
type="text/css">.ColorScheme-Text { color:#363636; }</style>
|
||||
</defs>
|
||||
<path
|
||||
d="M 2,1 C 0.892,1 0,1.892 0,3 v 9 c 0,1.108 0.892,2 2,2 h 12 c 1.108,0 2,-0.892 2,-2 V 3 C 16,1.892 15.108,1 14,1 Z m 0,1 h 12 c 0.554,0 1,0.446 1,1 H 1 C 1,2.446 1.446,2 2,2 Z M 1,3 h 14 v 9 c 0,0.554 -0.446,1 -1,1 H 2 C 1.446,13 1,12.554 1,12 Z m 3,7 c -0.554,0 -1,0.446 -1,1 0,0.554 0.446,1 1,1 h 8 c 0.554,0 1,-0.446 1,-1 0,-0.554 -0.446,-1 -1,-1 z"
|
||||
style="fill:currentColor"
|
||||
class="ColorScheme-Text"
|
||||
id="path5"
|
||||
sodipodi:nodetypes="sssssssssssccsccsssscsssssss" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
enable-background="new"
|
||||
version="1.1"
|
||||
id="svg16"
|
||||
sodipodi:docname="general-symbolic.svg"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs20" />
|
||||
<sodipodi:namedview
|
||||
id="namedview18"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="24.174578"
|
||||
inkscape:cx="13.98163"
|
||||
inkscape:cy="8.3765683"
|
||||
inkscape:window-width="1500"
|
||||
inkscape:window-height="963"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g14" />
|
||||
<g
|
||||
fill="#363636"
|
||||
id="g14"
|
||||
transform="rotate(90,7.75,8.25)">
|
||||
<path
|
||||
d="m 2.9500144,1 c -0.277,0 -0.5,0.223 -0.5,0.5 v 6.5547 a 2.5,2.5 0 0 1 0.5,-0.054688 2.5,2.5 0 0 1 0.5,0.050781 v -6.5508 c 0,-0.277 -0.223,-0.5 -0.5,-0.5 z m 0.5,11.945 a 2.5,2.5 0 0 1 -0.5,0.05469 2.5,2.5 0 0 1 -0.5,-0.05078 v 1.5508 c 0,0.277 0.223,0.5 0.5,0.5 0.277,0 0.5,-0.223 0.5,-0.5 v -1.5547 z"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M 7.5,1 C 7.223,1 7,1.223 7,1.5 V 3.0547 A 2.5,2.5 0 0 1 7.5,3.000012 2.5,2.5 0 0 1 8,3.050793 v -1.5508 c 0,-0.277 -0.223,-0.5 -0.5,-0.5 z M 8,7.9453 A 2.5,2.5 0 0 1 7.5,7.999988 2.5,2.5 0 0 1 7,7.949207 v 6.5508 c 0,0.277 0.223,0.5 0.5,0.5 0.277,0 0.5,-0.223 0.5,-0.5 v -6.5547 z"
|
||||
id="path4" />
|
||||
<path
|
||||
d="m 12.049986,1.0001482 c -0.277,0 -0.5,0.223 -0.5,0.5 v 6.5547 a 2.5,2.5 0 0 1 0.5,-0.054688 2.5,2.5 0 0 1 0.5,0.050781 v -6.5508 c 0,-0.277 -0.223,-0.5 -0.5,-0.5 z m 0.5,11.9450008 a 2.5,2.5 0 0 1 -0.5,0.05469 2.5,2.5 0 0 1 -0.5,-0.05078 v 1.5508 c 0,0.276999 0.223,0.5 0.5,0.5 0.277,0 0.5,-0.223001 0.5,-0.5 v -1.5547 z"
|
||||
id="path6" />
|
||||
<circle
|
||||
cx="2.9500144"
|
||||
cy="10.5"
|
||||
id="circle8"
|
||||
r="1.5" />
|
||||
<circle
|
||||
cx="7.5"
|
||||
cy="5.5"
|
||||
r="1.5"
|
||||
id="circle10" />
|
||||
<circle
|
||||
cx="12.049986"
|
||||
cy="10.500149"
|
||||
id="circle12"
|
||||
r="1.5" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg7"
|
||||
sodipodi:docname="heart-filled-symbolic.svg"
|
||||
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview9"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="31.598834"
|
||||
inkscape:cx="4.6046002"
|
||||
inkscape:cy="6.2344072"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg7"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:deskcolor="#d1d1d1" /><defs
|
||||
id="defs3"><style
|
||||
id="current-color-scheme"
|
||||
type="text/css">.ColorScheme-Text { color:#363636; }</style></defs><path
|
||||
d="M 11.846993,1.3381264 C 10.739505,1.3069919 9.6587026,1.7072882 8.8403186,2.4589575 L 7.981904,3.2284167 7.1190425,2.4589575 C 5.9848678,1.4359762 4.3836806,1.1023952 2.9337159,1.5827525 1.4793039,2.0586601 0.3940558,3.2773422 0.08716067,4.7762309 -0.21973329,6.2751198 0.29620488,7.8229343 1.4392744,8.8370195 L 7.981904,14.663563 14.520086,8.8370195 C 15.854409,7.685054 16.343662,5.8303457 15.75211,4.171338 15.160562,2.5123304 13.608299,1.3870507 11.846993,1.3381264 Z m 0,0"
|
||||
fill="#222222"
|
||||
id="path866"
|
||||
style="stroke-width:1.13863" /></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" enable-background="new"><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend mode="darken" in2="BackgroundImage"/></filter></defs><g transform="matrix(0 -1 -1 0 -413 -83.997)" color="#000" fill="#dedede"><rect y="-418" x="-92.997" width="2" style="marker:none" ry="1" rx="1" height="2" overflow="visible" enable-background="new"/><rect y="-422" x="-92.997" width="2" style="marker:none" ry="1" rx="1" height="2" overflow="visible" enable-background="new"/><rect y="-426" x="-92.997" width="2" style="marker:none" ry="1" rx="1" height="2" overflow="visible" enable-background="new"/></g></svg>
|
||||
|
After Width: | Height: | Size: 667 B |
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg7"
|
||||
sodipodi:docname="overview.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview9"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="44.6875"
|
||||
inkscape:cx="5.5944056"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-width="1500"
|
||||
inkscape:window-height="963"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g68"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true" />
|
||||
<defs
|
||||
id="defs3">
|
||||
<style
|
||||
id="current-color-scheme"
|
||||
type="text/css">.ColorScheme-Text { color:#363636; }</style>
|
||||
</defs>
|
||||
<path
|
||||
d="M 2,1 C 0.892,1 0,1.892 0,3 v 9 c 0,1.108 0.892,2 2,2 h 12 c 1.108,0 2,-0.892 2,-2 V 3 C 16,1.892 15.108,1 14,1 Z m 0,1 h 12 c 0.554,0 1,0.446 1,1 H 1 C 1,2.446 1.446,2 2,2 Z M 1,3 h 14 v 9 c 0,0.554 -0.446,1 -1,1 H 2 C 1.446,13 1,12.554 1,12 Z"
|
||||
style="fill:currentColor"
|
||||
class="ColorScheme-Text"
|
||||
id="path5"
|
||||
sodipodi:nodetypes="sssssssssssccsccssssc" />
|
||||
<g
|
||||
id="g68"
|
||||
transform="translate(0.3993007,0.15314685)">
|
||||
<path
|
||||
d="m 3.1756095,3.5602457 c -0.8440582,0 -1,0.446 -1,1 v 5.5732153 c 0,0.677136 0.446,1 1,1 H 12.02579 c 0.554,0 0.999999,-0.446 0.999999,-1 V 4.5602457 c 0,-0.554 -0.445999,-1 -0.999999,-1 z m 0,1 H 12.02579 V 10.133461 H 3.1756095 Z"
|
||||
fill="#363636"
|
||||
id="path8"
|
||||
sodipodi:nodetypes="sssssssssccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m4.4647 3.9648c-0.12775 0-0.2555 0.048567-0.35339 0.14649-0.19578 0.19586-0.19578 0.51116 0 0.70703l3.1816 3.1816-3.1816 3.1816c-0.19578 0.19586-0.19578 0.51116 0 0.70703 0.19578 0.19586 0.51118 0.19586 0.70704 0l3.1816-3.1816 3.1816 3.1816c0.19578 0.19586 0.51114 0.19586 0.70704 0 0.19578-0.19586 0.19578-0.51116 0-0.70703l-3.1816-3.1816 3.1816-3.1816c0.19578-0.19586 0.19578-0.51116 0-0.70703-0.19578-0.19586-0.51118-0.19586-0.70704 0l-3.1816 3.1816-3.1816-3.1816c-0.09789-0.097928-0.22564-0.14649-0.35339-0.14649z" fill="#363636" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.9149" style="paint-order:stroke fill markers"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 740 B |
@ -0,0 +1,7 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#363636">
|
||||
<path d="m8 3a6 6 0 0 0-6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6h-1a5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5z"/>
|
||||
<path d="m8.1719 0.67188-0.70703 0.70703 2.1211 2.1211-2.1211 2.1211 0.70703 0.70703 2.8281-2.8281-0.70703-0.70703z"/>
|
||||
<rect x="8" y="3" width="2" height="1"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 406 B |
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 2.953125 1.074219 l 2.417969 13.210937 l 3.238281 -2.398437 l 2.054687 2.648437 c 1.03125 1.433594 3.148438 -0.210937 2.011719 -1.5625 l -2.015625 -2.59375 l 2.984375 -2.175781 z m 0 0" fill="#222222"/></svg>
|
||||
|
After Width: | Height: | Size: 346 B |
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 2.953125 1.074219 l 2.417969 13.210937 l 3.238281 -2.398437 l 2.054687 2.648437 c 1.03125 1.433594 3.148438 -0.210937 2.011719 -1.5625 l -2.015625 -2.59375 l 2.984375 -2.175781 z m 0 0" fill="#222222"/></svg>
|
||||
|
After Width: | Height: | Size: 346 B |
@ -0,0 +1,20 @@
|
||||
{
|
||||
"_generated": "Generated by SweetTooth, do not edit",
|
||||
"description": "Adds a blur look to different parts of the GNOME Shell, including the top panel, dash and overview.\n\nYou can support my work by sponsoring me on:\n- github: https://github.com/sponsors/aunetx\n- ko-fi: https://ko-fi.com/aunetx\n\nNote: if the extension shows an error after updating, please make sure to restart your session to see if it persists. This is due to a bug in gnome shell, which I can't fix by myself.",
|
||||
"donations": {
|
||||
"github": "aunetx",
|
||||
"kofi": "aunetx"
|
||||
},
|
||||
"gettext-domain": "blur-my-shell",
|
||||
"name": "Blur my Shell",
|
||||
"original-authors": [
|
||||
"me@aunetx.dev"
|
||||
],
|
||||
"settings-schema": "org.gnome.shell.extensions.blur-my-shell",
|
||||
"shell-version": [
|
||||
"45"
|
||||
],
|
||||
"url": "https://github.com/aunetx/gnome-shell-extension-blur-my-shell",
|
||||
"uuid": "blur-my-shell@aunetx",
|
||||
"version": 54
|
||||
}
|
||||
@ -0,0 +1,174 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
|
||||
import { WindowRow } from './window_row.js';
|
||||
|
||||
|
||||
const make_array = prefs_group => {
|
||||
let list_box = prefs_group
|
||||
.get_first_child()
|
||||
.get_last_child()
|
||||
.get_first_child();
|
||||
|
||||
let elements = [];
|
||||
let i = 0;
|
||||
let element = list_box.get_row_at_index(i);
|
||||
while (element) {
|
||||
elements.push(element);
|
||||
i++;
|
||||
element = list_box.get_row_at_index(i);
|
||||
}
|
||||
|
||||
return elements;
|
||||
};
|
||||
|
||||
|
||||
export const Applications = GObject.registerClass({
|
||||
GTypeName: 'Applications',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/applications.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'blur',
|
||||
'customize',
|
||||
'opacity',
|
||||
'blur_on_overview',
|
||||
'enable_all',
|
||||
'whitelist',
|
||||
'add_window_whitelist',
|
||||
'blacklist',
|
||||
'add_window_blacklist'
|
||||
],
|
||||
}, class Applications extends Adw.PreferencesPage {
|
||||
constructor(preferences, preferences_window) {
|
||||
super({});
|
||||
this._preferences_window = preferences_window;
|
||||
|
||||
this.preferences = preferences;
|
||||
|
||||
this.preferences.applications.settings.bind(
|
||||
'blur', this._blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.applications.settings.bind(
|
||||
'opacity', this._opacity, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.applications.settings.bind(
|
||||
'blur-on-overview', this._blur_on_overview, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.applications.settings.bind(
|
||||
'enable-all', this._enable_all, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._customize.connect_to(this.preferences, this.preferences.applications, false);
|
||||
|
||||
// connect 'enable all' button to whitelist/blacklist visibility
|
||||
this._enable_all.bind_property(
|
||||
'active', this._whitelist, 'visible',
|
||||
GObject.BindingFlags.INVERT_BOOLEAN
|
||||
);
|
||||
this._enable_all.bind_property(
|
||||
'active', this._blacklist, 'visible',
|
||||
GObject.BindingFlags.DEFAULT
|
||||
);
|
||||
|
||||
// make sure that blacklist / whitelist is correctly hidden
|
||||
if (this._enable_all.active)
|
||||
this._whitelist.visible = false;
|
||||
this._blacklist.visible = !this._whitelist.visible;
|
||||
|
||||
// listen to app row addition
|
||||
this._add_window_whitelist.connect('clicked',
|
||||
_ => this.add_to_whitelist()
|
||||
);
|
||||
this._add_window_blacklist.connect('clicked',
|
||||
_ => this.add_to_blacklist()
|
||||
);
|
||||
|
||||
// add initial applications
|
||||
this.add_widgets_from_lists();
|
||||
|
||||
this.preferences.connect('reset', _ => {
|
||||
this.remove_all_widgets();
|
||||
this.add_widgets_from_lists();
|
||||
});
|
||||
}
|
||||
|
||||
// A way to retriew the whitelist widgets.
|
||||
get _whitelist_elements() {
|
||||
return make_array(this._whitelist);
|
||||
}
|
||||
|
||||
// A way to retriew the blacklist widgets.
|
||||
get _blacklist_elements() {
|
||||
return make_array(this._blacklist);
|
||||
}
|
||||
|
||||
add_widgets_from_lists() {
|
||||
this.preferences.applications.WHITELIST.forEach(
|
||||
app_name => this.add_to_whitelist(app_name)
|
||||
);
|
||||
|
||||
this.preferences.applications.BLACKLIST.forEach(
|
||||
app_name => this.add_to_blacklist(app_name)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
close_all_expanded_rows() {
|
||||
this._whitelist_elements.forEach(
|
||||
element => element.set_expanded(false)
|
||||
);
|
||||
this._blacklist_elements.forEach(
|
||||
element => element.set_expanded(false)
|
||||
);
|
||||
}
|
||||
|
||||
remove_all_widgets() {
|
||||
this._whitelist_elements.forEach(
|
||||
element => this._whitelist.remove(element)
|
||||
);
|
||||
this._blacklist_elements.forEach(
|
||||
element => this._blacklist.remove(element)
|
||||
);
|
||||
}
|
||||
|
||||
add_to_whitelist(app_name = null) {
|
||||
let window_row = new WindowRow('whitelist', this, app_name);
|
||||
this._whitelist.add(window_row);
|
||||
}
|
||||
|
||||
add_to_blacklist(app_name = null) {
|
||||
let window_row = new WindowRow('blacklist', this, app_name);
|
||||
this._blacklist.add(window_row);
|
||||
}
|
||||
|
||||
update_whitelist_titles() {
|
||||
let titles = this._whitelist_elements
|
||||
.map(element => element._window_class.buffer.text)
|
||||
.filter(title => title != "");
|
||||
|
||||
this.preferences.applications.WHITELIST = titles;
|
||||
}
|
||||
|
||||
update_blacklist_titles() {
|
||||
let titles = this._blacklist_elements
|
||||
.map(element => element._window_class.buffer.text)
|
||||
.filter(title => title != "");
|
||||
|
||||
this.preferences.applications.BLACKLIST = titles;
|
||||
}
|
||||
|
||||
remove_from_whitelist(widget) {
|
||||
this._whitelist.remove(widget);
|
||||
this.update_whitelist_titles();
|
||||
}
|
||||
|
||||
remove_from_blacklist(widget) {
|
||||
this._blacklist.remove(widget);
|
||||
this.update_blacklist_titles();
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,163 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
import Gtk from 'gi://Gtk';
|
||||
|
||||
|
||||
/// Given a component (described by its preferences node), a gschema key and
|
||||
/// a Gtk.ColorButton, binds everything transparently.
|
||||
let bind_color = function (component, key, widget) {
|
||||
let property_name = key.replaceAll('-', '_').toUpperCase();
|
||||
|
||||
let parse_color = _ => {
|
||||
let [r, g, b, a] = component[property_name];
|
||||
let w = widget.rgba;
|
||||
w.red = r;
|
||||
w.green = g;
|
||||
w.blue = b;
|
||||
w.alpha = a;
|
||||
widget.rgba = w;
|
||||
};
|
||||
component.settings.connect('changed::' + key, parse_color);
|
||||
|
||||
widget.connect('color-set', _ => {
|
||||
let c = widget.rgba;
|
||||
component[property_name] = [c.red, c.green, c.blue, c.alpha];
|
||||
});
|
||||
|
||||
parse_color();
|
||||
};
|
||||
|
||||
export const CustomizeRow = GObject.registerClass({
|
||||
GTypeName: 'CustomizeRow',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/customize-row.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'sigma',
|
||||
'brightness',
|
||||
'color',
|
||||
'color_row',
|
||||
'noise_amount',
|
||||
'noise_amount_row',
|
||||
'noise_lightness',
|
||||
'noise_lightness_row',
|
||||
'noise_color_notice'
|
||||
],
|
||||
}, class CustomizeRow extends Adw.ExpanderRow {
|
||||
/// Makes the required connections between the widgets and the preferences.
|
||||
///
|
||||
/// This function may be bound to another object than CustomizeRow, if we
|
||||
/// are using it for the General page; some things will then change (no
|
||||
/// expansion row, and no notice)
|
||||
///
|
||||
/// The color_and_noise parameter is either a boolean (true by default) or
|
||||
/// a widget; and permits selecting weather or not we want to show the color
|
||||
/// and noise buttons to the user. If it is a widget, it means we need to
|
||||
/// dynamically update their visibility, according to the widget's state.
|
||||
connect_to(settings, component_settings, color_and_noise = true) {
|
||||
let s = component_settings.settings;
|
||||
|
||||
// is not fired if in General page
|
||||
if (this instanceof CustomizeRow)
|
||||
// bind the customize button
|
||||
s.bind(
|
||||
'customize', this, 'enable-expansion',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
// bind sigma and brightness
|
||||
s.bind(
|
||||
'sigma', this._sigma, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
s.bind(
|
||||
'brightness', this._brightness, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
// bind the color button
|
||||
bind_color(component_settings, 'color', this._color);
|
||||
|
||||
// bind noise sliders
|
||||
s.bind(
|
||||
'noise-amount', this._noise_amount, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
s.bind(
|
||||
'noise-lightness', this._noise_lightness, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
// color_and_noise is either a boolean or a widget, if true, or it is a
|
||||
// widget, this will appropriately show the required preferences about
|
||||
// setting the color and noise
|
||||
if (color_and_noise) {
|
||||
// if we gave the static_blur widget, we are dealing with the panel,
|
||||
// and binding it to enable/disable the required components when
|
||||
// switching between static and dynamic blur
|
||||
if (color_and_noise instanceof Gtk.Switch) {
|
||||
// bind its state to dynamically toggle the notice and rows
|
||||
color_and_noise.bind_property(
|
||||
'active', this._color_row, 'visible',
|
||||
GObject.BindingFlags.SYNC_CREATE
|
||||
);
|
||||
color_and_noise.bind_property(
|
||||
'active', this._noise_amount_row, 'visible',
|
||||
GObject.BindingFlags.SYNC_CREATE
|
||||
);
|
||||
color_and_noise.bind_property(
|
||||
'active', this._noise_lightness_row, 'visible',
|
||||
GObject.BindingFlags.SYNC_CREATE
|
||||
);
|
||||
color_and_noise.bind_property(
|
||||
'active', this._noise_color_notice, 'visible',
|
||||
GObject.BindingFlags.INVERT_BOOLEAN
|
||||
);
|
||||
|
||||
// only way to get the correct state when first opening the
|
||||
// window...
|
||||
setTimeout(_ => {
|
||||
let is_visible = color_and_noise.active;
|
||||
this._color_row.visible = is_visible;
|
||||
this._noise_amount_row.visible = is_visible;
|
||||
this._noise_lightness_row.visible = is_visible;
|
||||
this._noise_color_notice.visible = !is_visible;
|
||||
}, 10);
|
||||
}
|
||||
|
||||
// if in General page, there is no notice at all
|
||||
if (this instanceof CustomizeRow) {
|
||||
// disable the notice
|
||||
this._noise_color_notice.visible = false;
|
||||
}
|
||||
} else {
|
||||
// enable the notice and disable color and noise preferences
|
||||
this._color_row.visible = false;
|
||||
this._noise_amount_row.visible = false;
|
||||
this._noise_lightness_row.visible = false;
|
||||
this._noise_color_notice.visible = true;
|
||||
}
|
||||
|
||||
// now we bind the color-and-noise preference to the sensitivity of the
|
||||
// associated widgets, this will grey them out if the user choose not to
|
||||
// have color and noise enabled
|
||||
// note: I would love to bind to the visibility instead, but this part
|
||||
// is already dirty enough, it would look like I obfuscate my code
|
||||
// intentionally... (I am not)
|
||||
settings.settings.bind(
|
||||
'color-and-noise',
|
||||
this._color_row, 'sensitive',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
settings.settings.bind(
|
||||
'color-and-noise',
|
||||
this._noise_amount_row, 'sensitive',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
settings.settings.bind(
|
||||
'color-and-noise',
|
||||
this._noise_lightness_row, 'sensitive',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
};
|
||||
});
|
||||
@ -0,0 +1,43 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
|
||||
|
||||
export const Dash = GObject.registerClass({
|
||||
GTypeName: 'Dash',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/dash.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'blur',
|
||||
'customize',
|
||||
'override_background',
|
||||
'style_dash_to_dock',
|
||||
'unblur_in_overview'
|
||||
],
|
||||
}, class Dash extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
|
||||
this.preferences.dash_to_dock.settings.bind(
|
||||
'blur', this._blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.dash_to_dock.settings.bind(
|
||||
'override-background',
|
||||
this._override_background, 'enable-expansion',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.dash_to_dock.settings.bind(
|
||||
'style-dash-to-dock', this._style_dash_to_dock, 'selected',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.dash_to_dock.settings.bind(
|
||||
'unblur-in-overview', this._unblur_in_overview, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._customize.connect_to(this.preferences, this.preferences.dash_to_dock, false);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,49 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
|
||||
import { CustomizeRow } from './customize_row.js';
|
||||
|
||||
|
||||
export const General = GObject.registerClass({
|
||||
GTypeName: 'General',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/general.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'sigma',
|
||||
'brightness',
|
||||
'color',
|
||||
'color_row',
|
||||
'noise_amount',
|
||||
'noise_amount_row',
|
||||
'noise_lightness',
|
||||
'noise_lightness_row',
|
||||
'color_and_noise',
|
||||
'hack_level',
|
||||
'debug',
|
||||
'reset'
|
||||
],
|
||||
}, class General extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
|
||||
CustomizeRow.prototype.connect_to.call(this, preferences, preferences);
|
||||
|
||||
this.preferences.settings.bind(
|
||||
'color-and-noise', this._color_and_noise, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.settings.bind(
|
||||
'hacks-level', this._hack_level, 'selected',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.settings.bind(
|
||||
'debug', this._debug, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._reset.connect('clicked', _ => this.preferences.reset());
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,67 @@
|
||||
import Gdk from 'gi://Gdk';
|
||||
import Gtk from 'gi://Gtk';
|
||||
import Gio from 'gi://Gio';
|
||||
import GLib from 'gi://GLib';
|
||||
|
||||
|
||||
export function addMenu(window) {
|
||||
const builder = new Gtk.Builder();
|
||||
|
||||
// add a dummy page and remove it immediately, to access headerbar
|
||||
builder.add_from_file(GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, '../ui/menu.ui', GLib.UriFlags.NONE))[0]);
|
||||
let menu_util = builder.get_object('menu_util');
|
||||
window.add(menu_util);
|
||||
try {
|
||||
addMenuToHeader(window, builder);
|
||||
} catch (error) {
|
||||
// could not add menu... not so bad
|
||||
}
|
||||
window.remove(menu_util);
|
||||
}
|
||||
|
||||
function addMenuToHeader(window, builder) {
|
||||
// a little hack to get to the headerbar
|
||||
const page = builder.get_object('menu_util');
|
||||
const pages_stack = page.get_parent(); // AdwViewStack
|
||||
const content_stack = pages_stack.get_parent().get_parent(); // GtkStack
|
||||
const preferences = content_stack.get_parent(); // GtkBox
|
||||
const headerbar = preferences.get_first_child(); // AdwHeaderBar
|
||||
headerbar.pack_start(builder.get_object('info_menu'));
|
||||
|
||||
// setup menu actions
|
||||
const actionGroup = new Gio.SimpleActionGroup();
|
||||
window.insert_action_group('prefs', actionGroup);
|
||||
|
||||
// a list of actions with their associated link
|
||||
const actions = [
|
||||
{
|
||||
name: 'open-bug-report',
|
||||
link: 'https://github.com/aunetx/blur-my-shell/issues'
|
||||
},
|
||||
{
|
||||
name: 'open-readme',
|
||||
link: 'https://github.com/aunetx/blur-my-shell'
|
||||
},
|
||||
{
|
||||
name: 'open-license',
|
||||
link: 'https://github.com/aunetx/blur-my-shell/blob/master/LICENSE'
|
||||
},
|
||||
{
|
||||
name: 'donate-github',
|
||||
link: 'https://github.com/sponsors/aunetx'
|
||||
},
|
||||
{
|
||||
name: 'donate-kofi',
|
||||
link: 'https://ko-fi.com/aunetx'
|
||||
},
|
||||
];
|
||||
|
||||
actions.forEach(action => {
|
||||
let act = new Gio.SimpleAction({ name: action.name });
|
||||
act.connect(
|
||||
'activate',
|
||||
_ => Gtk.show_uri(window, action.link, Gdk.CURRENT_TIME)
|
||||
);
|
||||
actionGroup.add_action(act);
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
|
||||
|
||||
export const Other = GObject.registerClass({
|
||||
GTypeName: 'Other',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/other.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'lockscreen_blur',
|
||||
'lockscreen_customize',
|
||||
|
||||
'screenshot_blur',
|
||||
'screenshot_customize',
|
||||
|
||||
'window_list_blur',
|
||||
'window_list_customize',
|
||||
],
|
||||
}, class Overview extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
|
||||
this.preferences.lockscreen.settings.bind(
|
||||
'blur', this._lockscreen_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._lockscreen_customize.connect_to(this.preferences, this.preferences.lockscreen);
|
||||
|
||||
this.preferences.screenshot.settings.bind(
|
||||
'blur', this._screenshot_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._screenshot_customize.connect_to(this.preferences, this.preferences.screenshot);
|
||||
|
||||
this.preferences.window_list.settings.bind(
|
||||
'blur', this._window_list_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._window_list_customize.connect_to(
|
||||
this.preferences, this.preferences.window_list, false
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,47 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
|
||||
|
||||
export const Overview = GObject.registerClass({
|
||||
GTypeName: 'Overview',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/overview.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'overview_blur',
|
||||
'overview_customize',
|
||||
'overview_style_components',
|
||||
|
||||
'appfolder_blur',
|
||||
'appfolder_customize',
|
||||
'appfolder_style_dialogs'
|
||||
],
|
||||
}, class Overview extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
|
||||
this.preferences.overview.settings.bind(
|
||||
'blur', this._overview_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.overview.settings.bind(
|
||||
'style-components', this._overview_style_components, 'selected',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._overview_customize.connect_to(this.preferences, this.preferences.overview);
|
||||
|
||||
this.preferences.appfolder.settings.bind(
|
||||
'blur', this._appfolder_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.appfolder.settings.bind(
|
||||
'style-dialogs', this._appfolder_style_dialogs, 'selected',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._appfolder_customize.connect_to(this.preferences, this.preferences.appfolder, false);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,65 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
|
||||
|
||||
export const Panel = GObject.registerClass({
|
||||
GTypeName: 'Panel',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/panel.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'blur',
|
||||
'customize',
|
||||
'static_blur',
|
||||
'unblur_in_overview',
|
||||
'override_background',
|
||||
'style_panel',
|
||||
'override_background_dynamically',
|
||||
'hidetopbar_compatibility',
|
||||
'dtp_blur_original_panel'
|
||||
],
|
||||
}, class Panel extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
|
||||
this.preferences.panel.settings.bind(
|
||||
'blur', this._blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.panel.settings.bind(
|
||||
'static-blur', this._static_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.panel.settings.bind(
|
||||
'unblur-in-overview', this._unblur_in_overview, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.panel.settings.bind(
|
||||
'override-background',
|
||||
this._override_background, 'enable-expansion',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.panel.settings.bind(
|
||||
'style-panel', this._style_panel, 'selected',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.panel.settings.bind(
|
||||
'override-background-dynamically',
|
||||
this._override_background_dynamically, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._customize.connect_to(this.preferences, this.preferences.panel, this._static_blur);
|
||||
|
||||
this.preferences.hidetopbar.settings.bind(
|
||||
'compatibility', this._hidetopbar_compatibility, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.dash_to_panel.settings.bind(
|
||||
'blur-original-panel', this._dtp_blur_original_panel, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,109 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
import Gtk from 'gi://Gtk';
|
||||
|
||||
import { pick, on_picking, on_picked } from '../dbus/client.js';
|
||||
|
||||
|
||||
|
||||
export const WindowRow = GObject.registerClass({
|
||||
GTypeName: 'WindowRow',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/window-row.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'window_picker',
|
||||
'window_class',
|
||||
'picking_failure_toast'
|
||||
],
|
||||
}, class WindowRow extends Adw.ExpanderRow {
|
||||
constructor(list, app_page, app_name) {
|
||||
super({});
|
||||
this._list = list;
|
||||
this._app_page = app_page;
|
||||
|
||||
// add a 'remove' button before the text
|
||||
let action_row = this.child.get_first_child().get_first_child();
|
||||
let remove_button = new Gtk.Button({
|
||||
'icon-name': 'remove-window-symbolic',
|
||||
'width-request': 38,
|
||||
'height-request': 38,
|
||||
'margin-top': 6,
|
||||
'margin-bottom': 6,
|
||||
});
|
||||
remove_button.add_css_class('circular');
|
||||
remove_button.add_css_class('flat');
|
||||
action_row.add_prefix(remove_button);
|
||||
|
||||
// connect the button to the whitelist / blacklist removal
|
||||
remove_button.connect('clicked', _ => this._remove_row());
|
||||
|
||||
// bind row title to text buffer
|
||||
this._window_class.buffer.bind_property(
|
||||
'text', this, 'title',
|
||||
Gio.SettingsBindFlags.BIDIRECTIONNAL
|
||||
);
|
||||
|
||||
// set application name if it exists, or open the revealer and pick one
|
||||
if (app_name)
|
||||
this._window_class.buffer.text = app_name;
|
||||
else {
|
||||
app_page.close_all_expanded_rows();
|
||||
this.set_expanded(true);
|
||||
this._do_pick_window(true);
|
||||
}
|
||||
|
||||
// pick a window when the picker button is clicked
|
||||
this._window_picker.connect('clicked', _ => this._do_pick_window());
|
||||
|
||||
// update list on text buffer change
|
||||
this._window_class.connect('changed',
|
||||
_ => this._update_rows_titles()
|
||||
);
|
||||
}
|
||||
|
||||
_remove_row() {
|
||||
this._app_page["remove_from_" + this._list](this);
|
||||
}
|
||||
|
||||
_update_rows_titles() {
|
||||
this._app_page["update_" + this._list + "_titles"](this);
|
||||
}
|
||||
|
||||
_do_pick_window(remove_if_failed = false) {
|
||||
// a mechanism to know if the extension is listening correcly
|
||||
let has_responded = false;
|
||||
let should_take_answer = true;
|
||||
setTimeout(_ => {
|
||||
if (!has_responded) {
|
||||
// show toast about failure
|
||||
this._app_page._preferences_window.add_toast(
|
||||
this._picking_failure_toast
|
||||
);
|
||||
|
||||
// prevent title from changing with later picks
|
||||
should_take_answer = false;
|
||||
|
||||
// remove row if asked
|
||||
if (remove_if_failed)
|
||||
this._remove_row();
|
||||
}
|
||||
}, 15);
|
||||
|
||||
on_picking(_ =>
|
||||
has_responded = true
|
||||
);
|
||||
|
||||
on_picked(wm_class => {
|
||||
if (should_take_answer) {
|
||||
if (wm_class == 'window-not-found') {
|
||||
console.warn("Can't pick window from here");
|
||||
return;
|
||||
}
|
||||
this._window_class.buffer.text = wm_class;
|
||||
}
|
||||
});
|
||||
|
||||
pick();
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,41 @@
|
||||
import Gdk from 'gi://Gdk';
|
||||
import Gtk from 'gi://Gtk';
|
||||
import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
||||
|
||||
import { Settings } from './conveniences/settings.js';
|
||||
import { Keys } from './conveniences/keys.js';
|
||||
|
||||
import { addMenu } from './preferences/menu.js';
|
||||
import { General } from './preferences/general.js';
|
||||
import { Panel } from './preferences/panel.js';
|
||||
import { Overview } from './preferences/overview.js';
|
||||
import { Dash } from './preferences/dash.js';
|
||||
import { Applications } from './preferences/applications.js';
|
||||
import { Other } from './preferences/other.js';
|
||||
|
||||
|
||||
export default class BlurMyShellPreferences extends ExtensionPreferences {
|
||||
constructor(metadata) {
|
||||
super(metadata);
|
||||
|
||||
// load the icon theme
|
||||
let iconPath = this.dir.get_child("icons").get_path();
|
||||
let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default());
|
||||
iconTheme.add_search_path(iconPath);
|
||||
}
|
||||
|
||||
fillPreferencesWindow(window) {
|
||||
addMenu(window);
|
||||
|
||||
const preferences = new Settings(Keys, this.getSettings());
|
||||
|
||||
window.add(new General(preferences));
|
||||
window.add(new Panel(preferences));
|
||||
window.add(new Overview(preferences));
|
||||
window.add(new Dash(preferences));
|
||||
window.add(new Applications(preferences, window));
|
||||
window.add(new Other(preferences));
|
||||
|
||||
window.search_enabled = true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,467 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schemalist>
|
||||
<!-- GENERAL -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell" path="/org/gnome/shell/extensions/blur-my-shell/">
|
||||
<!-- SIGMA -->
|
||||
<key type="i" name="sigma">
|
||||
<default>30</default>
|
||||
<summary>Global sigma (gaussian blur radius) to use</summary>
|
||||
</key>
|
||||
<!-- BRIGHTNESS -->
|
||||
<key type="d" name="brightness">
|
||||
<default>0.6</default>
|
||||
<summary>Global brightness to use</summary>
|
||||
</key>
|
||||
<!-- COLOR -->
|
||||
<key type="(dddd)" name="color">
|
||||
<default>(0.,0.,0.,0.)</default>
|
||||
<summary>Color to mix with the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE AMOUNT -->
|
||||
<key type="d" name="noise-amount">
|
||||
<default>0.</default>
|
||||
<summary>Amount of noise to add to the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE LIGHTNESS -->
|
||||
<key type="d" name="noise-lightness">
|
||||
<default>0.</default>
|
||||
<summary>Lightness of the noise added to the blur effect</summary>
|
||||
</key>
|
||||
<!-- COLOR AND NOISE -->
|
||||
<key type="b" name="color-and-noise">
|
||||
<default>true</default>
|
||||
<summary>Boolean, controls wether or not the color and noise effects are in use globally</summary>
|
||||
</key>
|
||||
<!-- HACKS LEVEL -->
|
||||
<key type="i" name="hacks-level">
|
||||
<default>1</default>
|
||||
<summary>Level of hacks to use (from 0 to 3, 3 disabling clipped redraws entirely)</summary>
|
||||
</key>
|
||||
<!-- DEBUG -->
|
||||
<key type="b" name="debug">
|
||||
<default>false</default>
|
||||
<summary>Boolean, set to true to activate debug mode (more verbose journalctl logs)</summary>
|
||||
</key>
|
||||
|
||||
<child name='overview' schema='org.gnome.shell.extensions.blur-my-shell.overview'></child>
|
||||
<child name='appfolder' schema='org.gnome.shell.extensions.blur-my-shell.appfolder'></child>
|
||||
<child name='panel' schema='org.gnome.shell.extensions.blur-my-shell.panel'></child>
|
||||
<child name='dash-to-dock' schema='org.gnome.shell.extensions.blur-my-shell.dash-to-dock'></child>
|
||||
<child name='applications' schema='org.gnome.shell.extensions.blur-my-shell.applications'></child>
|
||||
<child name='screenshot' schema='org.gnome.shell.extensions.blur-my-shell.screenshot'></child>
|
||||
<child name='lockscreen' schema='org.gnome.shell.extensions.blur-my-shell.lockscreen'></child>
|
||||
<child name='window-list' schema='org.gnome.shell.extensions.blur-my-shell.window-list'></child>
|
||||
<child name='hidetopbar' schema='org.gnome.shell.extensions.blur-my-shell.hidetopbar'></child>
|
||||
<child name='dash-to-panel' schema='org.gnome.shell.extensions.blur-my-shell.dash-to-panel'></child>
|
||||
</schema>
|
||||
|
||||
<!-- OVERVIEW -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.overview" path="/org/gnome/shell/extensions/blur-my-shell/overview/">
|
||||
<!-- BLUR -->
|
||||
<key type="b" name="blur">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to blur activate the blur for this component or not</summary>
|
||||
</key>
|
||||
<!-- CUSTOMIZE -->
|
||||
<key type="b" name="customize">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
|
||||
</key>
|
||||
<!-- SIGMA -->
|
||||
<key type="i" name="sigma">
|
||||
<default>30</default>
|
||||
<summary>Sigma (gaussian blur radius) to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- BRIGHTNESS -->
|
||||
<key type="d" name="brightness">
|
||||
<default>0.6</default>
|
||||
<summary>Brightness to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- COLOR -->
|
||||
<key type="(dddd)" name="color">
|
||||
<default>(0.,0.,0.,0.)</default>
|
||||
<summary>Color to mix with the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE AMOUNT -->
|
||||
<key type="d" name="noise-amount">
|
||||
<default>0.</default>
|
||||
<summary>Amount of noise to add to the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE LIGHTNESS -->
|
||||
<key type="d" name="noise-lightness">
|
||||
<default>0.</default>
|
||||
<summary>Lightness of the noise added to the blur effect</summary>
|
||||
</key>
|
||||
<!-- STYLE COMPONENTS -->
|
||||
<key type="i" name="style-components">
|
||||
<default>1</default>
|
||||
<summary>Enum to select the style of the components in overview (0 not styled, 1 light, 2 dark, 3 transparent)</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- APPFOLDER -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.appfolder" path="/org/gnome/shell/extensions/blur-my-shell/appfolder/">
|
||||
<!-- BLUR -->
|
||||
<key type="b" name="blur">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to blur activate the blur for this component or not</summary>
|
||||
</key>
|
||||
<!-- CUSTOMIZE -->
|
||||
<key type="b" name="customize">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
|
||||
</key>
|
||||
<!-- SIGMA -->
|
||||
<key type="i" name="sigma">
|
||||
<default>30</default>
|
||||
<summary>Sigma (gaussian blur radius) to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- BRIGHTNESS -->
|
||||
<key type="d" name="brightness">
|
||||
<default>0.6</default>
|
||||
<summary>Brightness to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- COLOR -->
|
||||
<key type="(dddd)" name="color">
|
||||
<default>(0.,0.,0.,0.)</default>
|
||||
<summary>Color to mix with the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE AMOUNT -->
|
||||
<key type="d" name="noise-amount">
|
||||
<default>0.</default>
|
||||
<summary>Amount of noise to add to the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE LIGHTNESS -->
|
||||
<key type="d" name="noise-lightness">
|
||||
<default>0.</default>
|
||||
<summary>Lightness of the noise added to the blur effect</summary>
|
||||
</key>
|
||||
<!-- STYLE DIALOGS -->
|
||||
<key type="i" name="style-dialogs">
|
||||
<default>1</default>
|
||||
<summary>Enum to select the style of the appfolder dialogs (0 not styled, 1 transparent, 2 light, 3 dark)</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- PANEL -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.panel" path="/org/gnome/shell/extensions/blur-my-shell/panel/">
|
||||
<!-- BLUR -->
|
||||
<key type="b" name="blur">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to blur activate the blur for this component or not</summary>
|
||||
</key>
|
||||
<!-- CUSTOMIZE -->
|
||||
<key type="b" name="customize">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
|
||||
</key>
|
||||
<!-- SIGMA -->
|
||||
<key type="i" name="sigma">
|
||||
<default>30</default>
|
||||
<summary>Sigma (gaussian blur radius) to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- BRIGHTNESS -->
|
||||
<key type="d" name="brightness">
|
||||
<default>0.6</default>
|
||||
<summary>Brightness to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- COLOR -->
|
||||
<key type="(dddd)" name="color">
|
||||
<default>(0.,0.,0.,0.)</default>
|
||||
<summary>Color to mix with the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE AMOUNT -->
|
||||
<key type="d" name="noise-amount">
|
||||
<default>0.</default>
|
||||
<summary>Amount of noise to add to the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE LIGHTNESS -->
|
||||
<key type="d" name="noise-lightness">
|
||||
<default>0.</default>
|
||||
<summary>Lightness of the noise added to the blur effect</summary>
|
||||
</key>
|
||||
<!-- STATIC BLUR -->
|
||||
<key type="b" name="static-blur">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to use a static or dynamic blur for this component</summary>
|
||||
</key>
|
||||
<!-- UNBLUR IN OVERVIEW -->
|
||||
<key type="b" name="unblur-in-overview">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to disable blur from this component when opening the overview or not</summary>
|
||||
</key>
|
||||
<!-- OVERRIDE BACKGROUND -->
|
||||
<key type="b" name="override-background">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to override the background or not</summary>
|
||||
</key>
|
||||
<!-- STYLE PANEL -->
|
||||
<key type="i" name="style-panel">
|
||||
<default>0</default>
|
||||
<summary>Enum to select the style of the panel (0 transparent, 1 light, 2 dark, 3 contrasted)</summary>
|
||||
</key>
|
||||
<!-- UNBLUR DYNAMICALLY -->
|
||||
<key type="b" name="override-background-dynamically">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to disable blur from this component when a window is close to the panel</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- DASH TO DOCK -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.dash-to-dock" path="/org/gnome/shell/extensions/blur-my-shell/dash-to-dock/">
|
||||
<!-- BLUR -->
|
||||
<key type="b" name="blur">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to blur activate the blur for this component or not</summary>
|
||||
</key>
|
||||
<!-- CUSTOMIZE -->
|
||||
<key type="b" name="customize">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
|
||||
</key>
|
||||
<!-- SIGMA -->
|
||||
<key type="i" name="sigma">
|
||||
<default>30</default>
|
||||
<summary>Sigma (gaussian blur radius) to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- BRIGHTNESS -->
|
||||
<key type="d" name="brightness">
|
||||
<default>0.6</default>
|
||||
<summary>Brightness to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- COLOR -->
|
||||
<key type="(dddd)" name="color">
|
||||
<default>(0.,0.,0.,0.)</default>
|
||||
<summary>Color to mix with the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE AMOUNT -->
|
||||
<key type="d" name="noise-amount">
|
||||
<default>0.</default>
|
||||
<summary>Amount of noise to add to the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE LIGHTNESS -->
|
||||
<key type="d" name="noise-lightness">
|
||||
<default>0.</default>
|
||||
<summary>Lightness of the noise added to the blur effect</summary>
|
||||
</key>
|
||||
<!-- STATIC BLUR -->
|
||||
<key type="b" name="static-blur">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to use static or dynamic blur for this component</summary>
|
||||
</key>
|
||||
<!-- OVERRIDE BACKGROUND -->
|
||||
<key type="b" name="override-background">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to override the background or not</summary>
|
||||
</key>
|
||||
<!-- STYLE DASH TO DOCK -->
|
||||
<key type="i" name="style-dash-to-dock">
|
||||
<default>1</default>
|
||||
<summary>Enum to select the style of dash to dock (0 transparent, 1 light, 2 dark)</summary>
|
||||
</key>
|
||||
<!-- UNBLUR IN OVERVIEW -->
|
||||
<key type="b" name="unblur-in-overview">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to disable blur from this component when opening the overview or not</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- APPLICATIONS -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.applications" path="/org/gnome/shell/extensions/blur-my-shell/applications/">
|
||||
<!-- BLUR -->
|
||||
<key type="b" name="blur">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to blur activate the blur for this component or not</summary>
|
||||
</key>
|
||||
<!-- CUSTOMIZE -->
|
||||
<key type="b" name="customize">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
|
||||
</key>
|
||||
<!-- SIGMA -->
|
||||
<key type="i" name="sigma">
|
||||
<default>30</default>
|
||||
<summary>Sigma (gaussian blur radius) to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- BRIGHTNESS -->
|
||||
<key type="d" name="brightness">
|
||||
<default>1.</default>
|
||||
<summary>Brightness to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- COLOR -->
|
||||
<key type="(dddd)" name="color">
|
||||
<default>(0.,0.,0.,0.)</default>
|
||||
<summary>Color to mix with the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE AMOUNT -->
|
||||
<key type="d" name="noise-amount">
|
||||
<default>0.</default>
|
||||
<summary>Amount of noise to add to the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE LIGHTNESS -->
|
||||
<key type="d" name="noise-lightness">
|
||||
<default>0.</default>
|
||||
<summary>Lightness of the noise added to the blur effect</summary>
|
||||
</key>
|
||||
<!-- OPACITY -->
|
||||
<key type="i" name="opacity">
|
||||
<default>230</default>
|
||||
<summary>Opacity of the window actor on top of the blur effect</summary>
|
||||
</key>
|
||||
<!-- BLUR ON OVERVIEW -->
|
||||
<key type="b" name="blur-on-overview">
|
||||
<default>false</default>
|
||||
<summary>Wether or not to blur applications on the overview</summary>
|
||||
</key>
|
||||
<!-- ENABLE ALL -->
|
||||
<key type="b" name="enable-all">
|
||||
<default>false</default>
|
||||
<summary>Wether or not to blur all applications by default</summary>
|
||||
</key>
|
||||
<!-- WHITELIST -->
|
||||
<key type="as" name="whitelist">
|
||||
<default>[]</default>
|
||||
<summary>List of applications to blur</summary>
|
||||
</key>
|
||||
<!-- BLACKLIST -->
|
||||
<key type="as" name="blacklist">
|
||||
<default>["Plank"]</default>
|
||||
<summary>List of applications not to blur</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- SCREENSHOT -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.screenshot" path="/org/gnome/shell/extensions/blur-my-shell/screenshot/">
|
||||
<!-- BLUR -->
|
||||
<key type="b" name="blur">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to blur activate the blur for this component or not</summary>
|
||||
</key>
|
||||
<!-- CUSTOMIZE -->
|
||||
<key type="b" name="customize">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
|
||||
</key>
|
||||
<!-- SIGMA -->
|
||||
<key type="i" name="sigma">
|
||||
<default>30</default>
|
||||
<summary>Sigma (gaussian blur radius) to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- BRIGHTNESS -->
|
||||
<key type="d" name="brightness">
|
||||
<default>0.6</default>
|
||||
<summary>Brightness to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- COLOR -->
|
||||
<key type="(dddd)" name="color">
|
||||
<default>(0.,0.,0.,0.)</default>
|
||||
<summary>Color to mix with the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE AMOUNT -->
|
||||
<key type="d" name="noise-amount">
|
||||
<default>0.</default>
|
||||
<summary>Amount of noise to add to the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE LIGHTNESS -->
|
||||
<key type="d" name="noise-lightness">
|
||||
<default>0.</default>
|
||||
<summary>Lightness of the noise added to the blur effect</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- LOCKSCREEN -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.lockscreen" path="/org/gnome/shell/extensions/blur-my-shell/lockscreen/">
|
||||
<!-- BLUR -->
|
||||
<key type="b" name="blur">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to blur activate the blur for this component or not</summary>
|
||||
</key>
|
||||
<!-- CUSTOMIZE -->
|
||||
<key type="b" name="customize">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
|
||||
</key>
|
||||
<!-- SIGMA -->
|
||||
<key type="i" name="sigma">
|
||||
<default>30</default>
|
||||
<summary>Sigma (gaussian blur radius) to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- BRIGHTNESS -->
|
||||
<key type="d" name="brightness">
|
||||
<default>0.6</default>
|
||||
<summary>Brightness to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- COLOR -->
|
||||
<key type="(dddd)" name="color">
|
||||
<default>(0.,0.,0.,0.)</default>
|
||||
<summary>Color to mix with the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE AMOUNT -->
|
||||
<key type="d" name="noise-amount">
|
||||
<default>0.</default>
|
||||
<summary>Amount of noise to add to the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE LIGHTNESS -->
|
||||
<key type="d" name="noise-lightness">
|
||||
<default>0.</default>
|
||||
<summary>Lightness of the noise added to the blur effect</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- WINDOW LIST -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.window-list" path="/org/gnome/shell/extensions/blur-my-shell/window-list/">
|
||||
<!-- BLUR -->
|
||||
<key type="b" name="blur">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to blur activate the blur for this component or not</summary>
|
||||
</key>
|
||||
<!-- CUSTOMIZE -->
|
||||
<key type="b" name="customize">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to customize the blur effect sigma/brightness or use general values</summary>
|
||||
</key>
|
||||
<!-- SIGMA -->
|
||||
<key type="i" name="sigma">
|
||||
<default>30</default>
|
||||
<summary>Sigma (gaussian blur radius) to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- BRIGHTNESS -->
|
||||
<key type="d" name="brightness">
|
||||
<default>0.6</default>
|
||||
<summary>Brightness to use for the blur effect</summary>
|
||||
</key>
|
||||
<!-- COLOR -->
|
||||
<key type="(dddd)" name="color">
|
||||
<default>(0.,0.,0.,0.)</default>
|
||||
<summary>Color to mix with the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE AMOUNT -->
|
||||
<key type="d" name="noise-amount">
|
||||
<default>0.</default>
|
||||
<summary>Amount of noise to add to the blur effect</summary>
|
||||
</key>
|
||||
<!-- NOISE LIGHTNESS -->
|
||||
<key type="d" name="noise-lightness">
|
||||
<default>0.</default>
|
||||
<summary>Lightness of the noise added to the blur effect</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- HIDETOPBAR -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.hidetopbar" path="/org/gnome/shell/extensions/blur-my-shell/hidetopbar/">
|
||||
<!-- COMPATIBILITY -->
|
||||
<key type="b" name="compatibility">
|
||||
<default>false</default>
|
||||
<summary>Boolean, whether to try compatibility with hidetopbar@mathieu.bidon.ca or not</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- DASH TO PANEL -->
|
||||
<schema id="org.gnome.shell.extensions.blur-my-shell.dash-to-panel" path="/org/gnome/shell/extensions/blur-my-shell/dash-to-panel/">
|
||||
<!-- COMPATIBILITY -->
|
||||
<key type="b" name="blur-original-panel">
|
||||
<default>true</default>
|
||||
<summary>Boolean, whether to blur the original panel (if option selected) with Dash to Panel</summary>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
@ -0,0 +1,334 @@
|
||||
/*** PANEL ***/
|
||||
|
||||
/*
|
||||
* `.transparent-panel`
|
||||
*/
|
||||
#panel.transparent-panel {
|
||||
background: transparent;
|
||||
transition-duration: 500ms;
|
||||
}
|
||||
|
||||
/*
|
||||
* `.dark-panel`
|
||||
*/
|
||||
#panel.dark-panel {
|
||||
background-color: rgba(100, 100, 100, 0.35);
|
||||
box-shadow: none;
|
||||
transition-duration: 500ms;
|
||||
}
|
||||
|
||||
/*
|
||||
* `.light-panel`
|
||||
*/
|
||||
#panel.light-panel {
|
||||
background-color: rgba(200, 200, 200, 0.2);
|
||||
box-shadow: none;
|
||||
transition-duration: 500ms;
|
||||
}
|
||||
|
||||
/*
|
||||
* `.contrasted-panel`
|
||||
*/
|
||||
#panel.contrasted-panel {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
transition-duration: 500ms;
|
||||
}
|
||||
|
||||
.contrasted-panel .panel-button,
|
||||
.contrasted-panel .clock,
|
||||
.contrasted-panel .clock-display StIcon {
|
||||
color: #ffffff;
|
||||
border-radius: 14px;
|
||||
border: 3px solid transparent;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
|
||||
.contrasted-panel .clock-display StIcon {
|
||||
padding: 8px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.contrasted-panel .panel-button:hover,
|
||||
.contrasted-panel .panel-button:hover .clock {
|
||||
color: #ffffff;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
.contrasted-panel .clock-display {
|
||||
background-color: transparent !important;
|
||||
box-shadow: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.contrasted-panel .clock {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
/*** DASH ***/
|
||||
|
||||
/*
|
||||
* `.transparent-dash`
|
||||
*/
|
||||
.transparent-dash .dash-background {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* `.light-dash`
|
||||
*/
|
||||
.light-dash .dash-background {
|
||||
background-color: rgba(200, 200, 200, 0.2) !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* `.dark-dash`
|
||||
*/
|
||||
.dark-dash .dash-background {
|
||||
background-color: rgba(100, 100, 100, 0.35) !important;
|
||||
}
|
||||
|
||||
|
||||
/*** OVERVIEW ***/
|
||||
|
||||
/*
|
||||
* Add transparency to the workspace animation (between workspaces)
|
||||
*/
|
||||
.blurred-overview .workspace-animation {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* `.overview-components-transparent`
|
||||
*/
|
||||
|
||||
.overview-components-transparent .workspace-thumbnail {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border: 1px solid rgba(100, 100, 100, 0.35);
|
||||
}
|
||||
|
||||
.overview-components-transparent .search-entry {
|
||||
color: white;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.overview-components-transparent .search-entry .search-entry-icon {
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
}
|
||||
|
||||
.overview-components-transparent .search-section-content {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.overview-components-transparent .search-section-content,
|
||||
.overview-components-transparent .app-folder .overview-icon {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* prevents the extension from interfering with Just Perfection */
|
||||
.overview-components-transparent.just-perfection .search-section-content {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.overview-components-transparent .app-folder .overview-icon {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.overview-components-transparent .app-folder:hover .overview-icon,
|
||||
.overview-components-transparent .app-folder:focus .overview-icon {
|
||||
background-color: rgba(230, 230, 230, 0.08);
|
||||
}
|
||||
|
||||
.overview-components-transparent .app-folder:active .overview-icon,
|
||||
.overview-components-transparent .app-folder:focus:hover .overview-icon,
|
||||
.overview-components-transparent .app-folder:drop .overview-icon {
|
||||
background-color: rgba(230, 230, 230, 0.12);
|
||||
}
|
||||
|
||||
.overview-components-transparent .app-folder:focus:active .overview-icon {
|
||||
background-color: rgba(230, 230, 230, 0.15);
|
||||
}
|
||||
|
||||
/* this shouldn't apply to Dash to Dock */
|
||||
.overview-components-transparent StBoxLayout>StWidget>#dash>.dash-background {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* `.overview-components-light`
|
||||
*/
|
||||
|
||||
.overview-components-light .workspace-thumbnail {
|
||||
background-color: rgba(200, 200, 200, 0.2);
|
||||
}
|
||||
|
||||
.overview-components-light .search-entry {
|
||||
color: white;
|
||||
background-color: rgba(200, 200, 200, 0.2);
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.overview-components-light .search-entry .search-entry-icon {
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
}
|
||||
|
||||
.overview-components-light .search-section-content {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.overview-components-light .search-section-content,
|
||||
.overview-components-light .app-folder .overview-icon {
|
||||
background-color: rgba(200, 200, 200, 0.2);
|
||||
}
|
||||
|
||||
/* prevents the extension from interfering with Just Perfection */
|
||||
.overview-components-light.just-perfection .search-section-content {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.overview-components-light .app-folder .overview-icon {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.overview-components-light .app-folder:hover .overview-icon,
|
||||
.overview-components-light .app-folder:focus .overview-icon {
|
||||
background-color: rgba(230, 230, 230, 0.2);
|
||||
}
|
||||
|
||||
.overview-components-light .app-folder:active .overview-icon,
|
||||
.overview-components-light .app-folder:focus:hover .overview-icon,
|
||||
.overview-components-light .app-folder:drop .overview-icon {
|
||||
background-color: rgba(230, 230, 230, 0.25);
|
||||
}
|
||||
|
||||
.overview-components-light .app-folder:focus:active .overview-icon {
|
||||
background-color: rgba(230, 230, 230, 0.3);
|
||||
}
|
||||
|
||||
/* this shouldn't apply to Dash to Dock */
|
||||
.overview-components-light StBoxLayout>StWidget>#dash>.dash-background {
|
||||
background-color: rgba(200, 200, 200, 0.2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* `.overview-components-dark`
|
||||
*/
|
||||
|
||||
.overview-components-dark .workspace-thumbnail {
|
||||
background-color: rgba(100, 100, 100, 0.35);
|
||||
}
|
||||
|
||||
.overview-components-dark .search-entry {
|
||||
color: white;
|
||||
background-color: rgba(100, 100, 100, 0.35);
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.overview-components-dark .search-entry .search-entry-icon {
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
}
|
||||
|
||||
.overview-components-dark .search-section-content {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.overview-components-dark .search-section-content,
|
||||
.overview-components-dark .app-folder .overview-icon {
|
||||
background-color: rgba(100, 100, 100, 0.35);
|
||||
}
|
||||
|
||||
/* prevents the extension from interfering with Just Perfection */
|
||||
.overview-components-dark.just-perfection .search-section-content {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.overview-components-dark .app-folder .overview-icon {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.overview-components-dark .app-folder:hover .overview-icon,
|
||||
.overview-components-dark .app-folder:focus .overview-icon {
|
||||
background-color: rgba(120, 120, 120, 0.35);
|
||||
}
|
||||
|
||||
.overview-components-dark .app-folder:active .overview-icon,
|
||||
.overview-components-dark .app-folder:focus:hover .overview-icon,
|
||||
.overview-components-dark .app-folder:drop .overview-icon {
|
||||
background-color: rgba(120, 120, 120, 0.4);
|
||||
}
|
||||
|
||||
.overview-components-dark .app-folder:focus:active .overview-icon {
|
||||
background-color: rgba(120, 120, 120, 0.45);
|
||||
}
|
||||
|
||||
/* this shouldn't apply to Dash to Dock */
|
||||
.overview-components-dark StBoxLayout>StWidget>#dash>.dash-background {
|
||||
background-color: rgba(100, 100, 100, 0.35);
|
||||
}
|
||||
|
||||
|
||||
/*** APPFOLDER DIALOG ***/
|
||||
|
||||
/*
|
||||
* `.appfolder-dialogs-transparent`
|
||||
*/
|
||||
|
||||
.appfolder-dialogs-transparent {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.appfolder-dialogs-transparent .folder-name-entry {
|
||||
color: white;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* `.appfolder-dialogs-light`
|
||||
*/
|
||||
|
||||
.appfolder-dialogs-light {
|
||||
background-color: rgba(200, 200, 200, 0.2);
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.appfolder-dialogs-light .folder-name-entry {
|
||||
color: white;
|
||||
background-color: rgba(200, 200, 200, 0.2);
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* `.appfolder-dialogs-dark`
|
||||
*/
|
||||
|
||||
.appfolder-dialogs-dark {
|
||||
background-color: rgba(100, 100, 100, 0.35);
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.appfolder-dialogs-dark .folder-name-entry {
|
||||
color: white;
|
||||
background-color: rgba(100, 100, 100, 0.35);
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="blur-my-shell@aunetx">
|
||||
<template class="Applications" parent="AdwPreferencesPage">
|
||||
<property name="name">applications</property>
|
||||
<property name="title" translatable="yes">Applications</property>
|
||||
<property name="icon-name">applications-symbolic</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Applications blur (beta)</property>
|
||||
<property name="description" translatable="yes">Adds blur to the applications. This is still beta functionality.
|
||||
To get the best results possible, make sure to choose the option “No artifact” in the “General → Hack level” preference.
|
||||
</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkSwitch" id="blur">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<child>
|
||||
<object class="CustomizeRow" id="customize">
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Opacity</property>
|
||||
<property name="subtitle" translatable="yes">The opacity of the window on top of the blur effect, a higher value will be more legible.</property>
|
||||
<property name="activatable-widget">opacity</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="GtkScale" id="opacity_scale">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">200px</property>
|
||||
<property name="draw-value">true</property>
|
||||
<property name="value-pos">right</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="digits">0</property>
|
||||
<property name="adjustment">opacity</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Blur on overview</property>
|
||||
<property name="subtitle" translatable="yes">Forces the blur to be properly shown on all workspaces on overview.
|
||||
This may cause some latency or performance issues.</property>
|
||||
<property name="activatable-widget">blur_on_overview</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="GtkSwitch" id="blur_on_overview">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Enable all by default</property>
|
||||
<property name="subtitle" translatable="yes">Adds blur behind all windows by default.
|
||||
Not recommended because of performance and stability issues.</property>
|
||||
<property name="activatable-widget">enable_all</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="GtkSwitch" id="enable_all">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="whitelist">
|
||||
<property name="title" translatable="yes">Whitelist</property>
|
||||
<property name="description" translatable="yes">A list of windows to blur.</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
<property name="header-suffix">
|
||||
<object class="GtkButton" id="add_window_whitelist">
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">12</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="margin-end">6</property>
|
||||
<property name="icon-name">add-window-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">Add Window</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="circular" />
|
||||
<class name="suggested-action" />
|
||||
</style>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<!-- WINDOW ROW WIDGETS GO HERE -->
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="blacklist">
|
||||
<property name="title" translatable="yes">Blacklist</property>
|
||||
<property name="description" translatable="yes">A list of windows not to blur.</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
<property name="header-suffix">
|
||||
<object class="GtkButton" id="add_window_blacklist">
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">12</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="margin-end">6</property>
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">Add Window</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="circular" />
|
||||
<class name="suggested-action" />
|
||||
</style>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<!-- WINDOW ROW WIDGETS GO HERE -->
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
<object class="GtkAdjustment" id="opacity">
|
||||
<property name="lower">25</property>
|
||||
<property name="upper">255</property>
|
||||
<property name="step-increment">1</property>
|
||||
</object>
|
||||
</interface>
|
||||
@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="blur-my-shell@aunetx">
|
||||
<template class="CustomizeRow" parent="AdwExpanderRow">
|
||||
<property name="title" translatable="yes">Customize properties</property>
|
||||
<property name="subtitle" translatable="yes">Uses customized blur properties, instead of the ones set in the General page.</property>
|
||||
<property name="show-enable-switch">true</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Sigma</property>
|
||||
<property name="subtitle" translatable="yes">The intensity of the blur.</property>
|
||||
<property name="activatable-widget">sigma_scale</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkScale" id="sigma_scale">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">200px</property>
|
||||
<property name="draw-value">true</property>
|
||||
<property name="value-pos">right</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="digits">0</property>
|
||||
<property name="adjustment">sigma</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Brightness</property>
|
||||
<property name="subtitle" translatable="yes">The brightness of the blur effect, a high value might make the text harder to read.</property>
|
||||
<property name="activatable-widget">brightness_scale</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkScale" id="brightness_scale">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">200px</property>
|
||||
<property name="draw-value">true</property>
|
||||
<property name="value-pos">right</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="digits">2</property>
|
||||
<property name="adjustment">brightness</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow" id="color_row">
|
||||
<property name="title" translatable="yes">Color</property>
|
||||
<property name="subtitle" translatable="yes">Changes the color of the blur. The opacity of the color controls how much it is blended into the blur effect.</property>
|
||||
<property name="activatable-widget">color</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkColorButton" id="color">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">false</property>
|
||||
<property name="width-request">70px</property>
|
||||
<property name="height-request">45px</property>
|
||||
<property name="show-editor">true</property>
|
||||
<property name="use-alpha">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow" id="noise_amount_row">
|
||||
<property name="title" translatable="yes">Noise amount</property>
|
||||
<property name="subtitle" translatable="yes">The amount of noise to add to the blur effect, useful on low-contrast screens or for aesthetic purpose.</property>
|
||||
<property name="activatable-widget">noise_amount_scale</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkScale" id="noise_amount_scale">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">200px</property>
|
||||
<property name="draw-value">true</property>
|
||||
<property name="value-pos">right</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="digits">2</property>
|
||||
<property name="adjustment">noise_amount</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow" id="noise_lightness_row">
|
||||
<property name="title" translatable="yes">Noise lightness</property>
|
||||
<property name="subtitle" translatable="yes">The lightness of the noise added to the blur effect.</property>
|
||||
<property name="activatable-widget">noise_lightness_scale</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkScale" id="noise_lightness_scale">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">200px</property>
|
||||
<property name="draw-value">true</property>
|
||||
<property name="value-pos">right</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="digits">2</property>
|
||||
<property name="adjustment">noise_lightness</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow" id="noise_color_notice">
|
||||
<property name="title" translatable="yes">Notice</property>
|
||||
<property name="subtitle" translatable="yes">Noise and color can't be activated on dynamically blurred components, such as this one.</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</template>
|
||||
|
||||
<object class="GtkAdjustment" id="sigma">
|
||||
<property name="lower">0</property>
|
||||
<property name="upper">200</property>
|
||||
<property name="step-increment">1</property>
|
||||
</object>
|
||||
|
||||
<object class="GtkAdjustment" id="brightness">
|
||||
<property name="lower">0.0</property>
|
||||
<property name="upper">1.0</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
</object>
|
||||
|
||||
<object class="GtkAdjustment" id="noise_amount">
|
||||
<property name="lower">0.0</property>
|
||||
<property name="upper">1.0</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
</object>
|
||||
|
||||
<object class="GtkAdjustment" id="noise_lightness">
|
||||
<property name="lower">0.0</property>
|
||||
<property name="upper">2.0</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
</object>
|
||||
</interface>
|
||||
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="blur-my-shell@aunetx">
|
||||
<template class="Dash" parent="AdwPreferencesPage">
|
||||
<property name="name">dash</property>
|
||||
<property name="title" translatable="yes">Dash</property>
|
||||
<property name="icon-name">dash-symbolic</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Dash to Dock blur</property>
|
||||
<property name="description" translatable="yes">Blur the background of the Dash to Dock extension, if it is used.</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkSwitch" id="blur">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<child>
|
||||
<object class="CustomizeRow" id="customize">
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwExpanderRow" id="override_background">
|
||||
<property name="title" translatable="yes">Override background</property>
|
||||
<property name="subtitle" translatable="yes">Makes the background either transparent or semi-transparent, disable this to use Dash to Dock preferences instead.</property>
|
||||
<property name="show-enable-switch">true</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Background style</property>
|
||||
<property name="subtitle" translatable="yes">The transparent/semi-transparent style for the dock background.</property>
|
||||
<property name="activatable-widget">style_dash_to_dock</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkDropDown" id="style_dash_to_dock">
|
||||
<property name="valign">center</property>
|
||||
<property name="model">style_dash_to_dock_model</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Disable in overview</property>
|
||||
<property name="subtitle" translatable="yes">Disables the blur from Dash to Dock when entering the overview.</property>
|
||||
<property name="activatable-widget">unblur_in_overview</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="GtkSwitch" id="unblur_in_overview">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
<object class="GtkStringList" id="style_dash_to_dock_model">
|
||||
<items>
|
||||
<item translatable="yes">Transparent</item>
|
||||
<item translatable="yes">Light</item>
|
||||
<item translatable="yes">Dark</item>
|
||||
</items>
|
||||
</object>
|
||||
</interface>
|
||||
@ -0,0 +1,234 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="blur-my-shell@aunetx">
|
||||
<template class="General" parent="AdwPreferencesPage">
|
||||
<property name="name">general</property>
|
||||
<property name="title" translatable="yes">General</property>
|
||||
<property name="icon-name">general-symbolic</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Blur preferences</property>
|
||||
<property name="description" translatable="yes">Global blur preferences, used by all components by default.</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Sigma</property>
|
||||
<property name="subtitle" translatable="yes">The intensity of the blur.</property>
|
||||
<property name="activatable-widget">sigma_scale</property>
|
||||
<child>
|
||||
<object class="GtkScale" id="sigma_scale">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">200px</property>
|
||||
<property name="draw-value">true</property>
|
||||
<property name="value-pos">right</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="digits">0</property>
|
||||
<property name="adjustment">sigma</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Brightness</property>
|
||||
<property name="subtitle" translatable="yes">The brightness of the blur effect, a high value might make the text harder to read.</property>
|
||||
<property name="activatable-widget">brightness_scale</property>
|
||||
<child>
|
||||
<object class="GtkScale" id="brightness_scale">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">200px</property>
|
||||
<property name="draw-value">true</property>
|
||||
<property name="value-pos">right</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="digits">2</property>
|
||||
<property name="adjustment">brightness</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow" id="color_row">
|
||||
<property name="title" translatable="yes">Color</property>
|
||||
<property name="subtitle" translatable="yes">Changes the color of the blur. The opacity of the color controls how much it is blended into the blur effect.</property>
|
||||
<property name="activatable-widget">color</property>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="color">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">false</property>
|
||||
<property name="width-request">70px</property>
|
||||
<property name="height-request">45px</property>
|
||||
<property name="show-editor">true</property>
|
||||
<property name="use-alpha">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow" id="noise_amount_row">
|
||||
<property name="title" translatable="yes">Noise amount</property>
|
||||
<property name="subtitle" translatable="yes">The amount of noise to add to the blur effect, useful on low-contrast screens or for aesthetic purpose.</property>
|
||||
<property name="activatable-widget">noise_amount_scale</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkScale" id="noise_amount_scale">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">200px</property>
|
||||
<property name="draw-value">true</property>
|
||||
<property name="value-pos">right</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="digits">2</property>
|
||||
<property name="adjustment">noise_amount</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow" id="noise_lightness_row">
|
||||
<property name="title" translatable="yes">Noise lightness</property>
|
||||
<property name="subtitle" translatable="yes">The lightness of the noise added to the blur effect.</property>
|
||||
<property name="activatable-widget">noise_lightness_scale</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkScale" id="noise_lightness_scale">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">200px</property>
|
||||
<property name="draw-value">true</property>
|
||||
<property name="value-pos">right</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="digits">2</property>
|
||||
<property name="adjustment">noise_lightness</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Performance</property>
|
||||
<property name="description" translatable="yes">Various options to tweak the performance.</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Color and noise effects</property>
|
||||
<property name="subtitle" translatable="yes">Globally disables noise and color effects which may improve performance on low-end systems.</property>
|
||||
<property name="activatable-widget">color_and_noise</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="color_and_noise">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Hack level</property>
|
||||
<property name="subtitle" translatable="yes">Changes the behaviour of the dynamic blur effect.
|
||||
The default value is highly recommended unless you use application blur, in which case “No artifact” is better.
|
||||
This option will entirely disable clipped redraws in GNOME shell, and may impact performance significantly but will completely fix the blur effect.</property>
|
||||
<property name="activatable-widget">hack_level</property>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="hack_level">
|
||||
<property name="valign">center</property>
|
||||
<property name="model">hack_level_model</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Debug</property>
|
||||
<property name="subtitle" translatable="yes">Makes the extension verbose in logs, activate when you need to report an issue.</property>
|
||||
<property name="activatable-widget">debug</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="debug">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Reset preferences</property>
|
||||
<property name="description" translatable="yes">Resets preferences of Blur my Shell irreversibly.</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkButton" id="reset">
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">20</property>
|
||||
<property name="margin-end">20</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="margin-end">6</property>
|
||||
<property name="icon-name">reset-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">Reset</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="circular" />
|
||||
<class name="destructive-action" />
|
||||
</style>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
<object class="GtkAdjustment" id="sigma">
|
||||
<property name="lower">0</property>
|
||||
<property name="upper">200</property>
|
||||
<property name="step-increment">1</property>
|
||||
</object>
|
||||
|
||||
<object class="GtkAdjustment" id="brightness">
|
||||
<property name="lower">0.0</property>
|
||||
<property name="upper">1.0</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
</object>
|
||||
|
||||
<object class="GtkAdjustment" id="noise_amount">
|
||||
<property name="lower">0.0</property>
|
||||
<property name="upper">1.0</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
</object>
|
||||
|
||||
<object class="GtkAdjustment" id="noise_lightness">
|
||||
<property name="lower">0.0</property>
|
||||
<property name="upper">2.0</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
</object>
|
||||
|
||||
<object class="GtkStringList" id="hack_level_model">
|
||||
<items>
|
||||
<item translatable="yes">High performances</item>
|
||||
<item translatable="yes">Default</item>
|
||||
<item translatable="yes">High quality</item>
|
||||
<item translatable="yes">No artifact</item>
|
||||
</items>
|
||||
</object>
|
||||
</interface>
|
||||
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="blur-my-shell@aunetx">
|
||||
<menu id="info_menu_model">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Project page</attribute>
|
||||
<attribute name="action">prefs.open-readme</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Report a Bug</attribute>
|
||||
<attribute name="action">prefs.open-bug-report</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">License</attribute>
|
||||
<attribute name="action">prefs.open-license</attribute>
|
||||
</item>
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">Donate</attribute>
|
||||
<item>
|
||||
<attribute name="label">GitHub</attribute>
|
||||
<attribute name="action">prefs.donate-github</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label">Ko-fi</attribute>
|
||||
<attribute name="action">prefs.donate-kofi</attribute>
|
||||
</item>
|
||||
</submenu>
|
||||
</section>
|
||||
</menu>
|
||||
|
||||
<object class="GtkMenuButton" id="info_menu">
|
||||
<property name="menu-model">info_menu_model</property>
|
||||
<property name="icon-name">heart-filled-symbolic</property>
|
||||
</object>
|
||||
|
||||
<object class="AdwPreferencesPage" id="menu_util"></object>
|
||||
</interface>
|
||||
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="blur-my-shell@aunetx">
|
||||
<template class="Other" parent="AdwPreferencesPage">
|
||||
<property name="name">other</property>
|
||||
<property name="title" translatable="yes">Other</property>
|
||||
<property name="icon-name">other-symbolic</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Lockscreen blur</property>
|
||||
<property name="description" translatable="yes">Change the blur of the lockscreen to use this extension's preferences.</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkSwitch" id="lockscreen_blur">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<child>
|
||||
<object class="CustomizeRow" id="lockscreen_customize">
|
||||
<property name="sensitive" bind-source="lockscreen_blur" bind-property="state" bind-flags="sync-create" />
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Screenshot blur</property>
|
||||
<property name="description" translatable="yes">Add blur to the background of the window selector in the screenshot UI.</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkSwitch" id="screenshot_blur">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<child>
|
||||
<object class="CustomizeRow" id="screenshot_customize">
|
||||
<property name="sensitive" bind-source="screenshot_blur" bind-property="state" bind-flags="sync-create" />
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Window list extension blur</property>
|
||||
<property name="description" translatable="yes">Make the window-list extension blurred, if it is used.</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkSwitch" id="window_list_blur">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<child>
|
||||
<object class="CustomizeRow" id="window_list_customize">
|
||||
<property name="sensitive" bind-source="window_list_blur" bind-property="state" bind-flags="sync-create" />
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="blur-my-shell@aunetx">
|
||||
<template class="Overview" parent="AdwPreferencesPage">
|
||||
<property name="name">overview</property>
|
||||
<property name="title" translatable="yes">Overview</property>
|
||||
<property name="icon-name">overview-symbolic</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Background blur</property>
|
||||
<property name="description" translatable="yes">Add blur to the overview background, using the wallpaper picture.</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkSwitch" id="overview_blur">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<child>
|
||||
<object class="CustomizeRow" id="overview_customize">
|
||||
<property name="sensitive" bind-source="overview_blur" bind-property="state" bind-flags="sync-create" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Overview components style</property>
|
||||
<property name="subtitle" translatable="yes">The semi-transparent style for the dash, search entry/results, and application folders.</property>
|
||||
<property name="sensitive" bind-source="overview_blur" bind-property="state" bind-flags="sync-create" />
|
||||
<property name="activatable-widget">overview_style_components</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkDropDown" id="overview_style_components">
|
||||
<property name="valign">center</property>
|
||||
<property name="model">overview_style_components_model</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Application folder blur</property>
|
||||
<property name="description" translatable="yes">Makes the background of application folder dialogs blurred.</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkSwitch" id="appfolder_blur">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<child>
|
||||
<object class="CustomizeRow" id="appfolder_customize">
|
||||
<property name="sensitive" bind-source="appfolder_blur" bind-property="state" bind-flags="sync-create" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Application folder dialogs style</property>
|
||||
<property name="subtitle" translatable="yes">The semi-transparent style for the application folder dialogs.</property>
|
||||
<property name="sensitive" bind-source="appfolder_blur" bind-property="state" bind-flags="sync-create" />
|
||||
<property name="activatable-widget">appfolder_style_dialogs</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkDropDown" id="appfolder_style_dialogs">
|
||||
<property name="valign">center</property>
|
||||
<property name="model">appfolder_style_dialogs_model</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
<object class="GtkStringList" id="overview_style_components_model">
|
||||
<items>
|
||||
<item translatable="yes">Do not style</item>
|
||||
<item translatable="yes">Light</item>
|
||||
<item translatable="yes">Dark</item>
|
||||
<item translatable="yes">Transparent</item>
|
||||
</items>
|
||||
</object>
|
||||
|
||||
<object class="GtkStringList" id="appfolder_style_dialogs_model">
|
||||
<items>
|
||||
<item translatable="yes">Do not style</item>
|
||||
<item translatable="yes">Transparent</item>
|
||||
<item translatable="yes">Light</item>
|
||||
<item translatable="yes">Dark</item>
|
||||
</items>
|
||||
</object>
|
||||
</interface>
|
||||
@ -0,0 +1,141 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="blur-my-shell@aunetx">
|
||||
<template class="Panel" parent="AdwPreferencesPage">
|
||||
<property name="name">panel</property>
|
||||
<property name="title" translatable="yes">Panel</property>
|
||||
<property name="icon-name">bottom-panel-symbolic</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Panel blur</property>
|
||||
<property name="description" translatable="yes">Blur the top panel using the background image.</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkSwitch" id="blur">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<child>
|
||||
<object class="CustomizeRow" id="customize">
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Static blur</property>
|
||||
<property name="subtitle" translatable="yes">Uses a static blurred image, more performant and stable.</property>
|
||||
<property name="activatable-widget">static_blur</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="GtkSwitch" id="static_blur">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Disable in overview</property>
|
||||
<property name="subtitle" translatable="yes">Disables the blur from the panel when entering the overview.</property>
|
||||
<property name="activatable-widget">unblur_in_overview</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="GtkSwitch" id="unblur_in_overview">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwExpanderRow" id="override_background">
|
||||
<property name="title" translatable="yes">Override background</property>
|
||||
<property name="subtitle" translatable="yes">Override the background of the panel to use a transparent or semi-transparent one.
|
||||
Recommended unless you want to customize your GNOME theme.</property>
|
||||
<property name="show-enable-switch">true</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Background style</property>
|
||||
<property name="subtitle" translatable="yes">The transparent/semi-transparent style for the panel background.</property>
|
||||
<property name="activatable-widget">style_panel</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkDropDown" id="style_panel">
|
||||
<property name="valign">center</property>
|
||||
<property name="model">style_panel_model</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Disable when a window is near</property>
|
||||
<property name="subtitle" translatable="yes">Disables the transparency of the panel when a window is near it.</property>
|
||||
<property name="activatable-widget">override_background_dynamically</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkSwitch" id="override_background_dynamically">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Compatibility</property>
|
||||
<property name="description" translatable="yes">Various options to provide compatibility with other extensions.</property>
|
||||
<property name="sensitive" bind-source="blur" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Hidetopbar extension</property>
|
||||
<property name="subtitle" translatable="yes">Does not disable the blur in overview, best used with static blur.</property>
|
||||
<property name="activatable-widget">hidetopbar_compatibility</property>
|
||||
<property name="sensitive" bind-source="unblur_in_overview" bind-property="state" bind-flags="sync-create" />
|
||||
|
||||
<child>
|
||||
<object class="GtkSwitch" id="hidetopbar_compatibility">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Blur original panel with Dash to Panel</property>
|
||||
<property name="subtitle" translatable="yes">Enables the blurring of the original panel with Dash to Panel, if selected in the extension's options.</property>
|
||||
<property name="activatable-widget">dtp_blur_original_panel</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkSwitch" id="dtp_blur_original_panel">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
<object class="GtkStringList" id="style_panel_model">
|
||||
<items>
|
||||
<item translatable="yes">Transparent</item>
|
||||
<item translatable="yes">Light</item>
|
||||
<item translatable="yes">Dark</item>
|
||||
<item translatable="yes">Contrasted</item>
|
||||
</items>
|
||||
</object>
|
||||
</interface>
|
||||
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="blur-my-shell@aunetx">
|
||||
<template class="WindowRow" parent="AdwExpanderRow">
|
||||
<property name="title" translatable="yes">Window Name</property>
|
||||
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Select window</property>
|
||||
<property name="subtitle" translatable="yes">Pick a window or select it by its classname.</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox" id="window_selector">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="width-request">175px</property>
|
||||
<style>
|
||||
<class name="linked" />
|
||||
</style>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton" id="window_picker">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="icon-name">select-window-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkEntry" id="window_class">
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
<object class="AdwToast" id="picking_failure_toast">
|
||||
<property name="title">Could not pick window, make sure that the extension is enabled.</property>
|
||||
</object>
|
||||
</interface>
|
||||