[gnome] Fix extension locations

This commit is contained in:
2024-01-23 15:31:15 -05:00
parent 2f029aee37
commit 5ac7107501
331 changed files with 2 additions and 0 deletions

View File

@ -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();
}
});

View File

@ -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
);
};
});

View File

@ -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);
}
});

View File

@ -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());
}
});

View File

@ -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);
});
}

View File

@ -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
);
}
});

View File

@ -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);
}
});

View File

@ -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
);
}
});

View File

@ -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();
}
});