diff --git a/extension.js b/extension.js
index f385b79..b32f939 100644
--- a/extension.js
+++ b/extension.js
@@ -44,19 +44,11 @@ import TVEffect from './src/effects/TVEffect.js';
import TVGlitch from './src/effects/TVGlitch.js';
import Wisps from './src/effects/Wisps.js';
-const Main = imports.ui.main;
-const Workspace = imports.ui.workspace.Workspace;
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import {Workspace} from 'resource:///org/gnome/shell/ui/workspace.js';
+import {WindowPreview} from 'resource:///org/gnome/shell/ui/windowPreview.js';
+import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
-// The WindowPreview class is only available on GNOME Shell 3.38+;
-let WindowPreview = null;
-try {
- WindowPreview = imports.ui.windowPreview.WindowPreview;
-} catch (error) {
- // Nothing to be done, we are on GNOME Shell 3.36.
-}
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
//////////////////////////////////////////////////////////////////////////////////////////
// This extensions modifies the window-close and window-open animations with all kinds //
@@ -67,7 +59,7 @@ const Me = imports.misc.extensionUtils.getCurrentExtension();
// to get this working. For more details, read the other comments in this file... //
//////////////////////////////////////////////////////////////////////////////////////////
-export default class Extension {
+export default class BurnMyWindows extends Extension {
// ------------------------------------------------------------------------ public stuff
@@ -101,22 +93,23 @@ export default class Extension {
];
// Load all of our resources.
- this._resources = Gio.Resource.load(Me.path + '/resources/burn-my-windows.gresource');
+ this._resources =
+ Gio.Resource.load(this.path + '/resources/burn-my-windows.gresource');
Gio.resources_register(this._resources);
// Store a reference to the settings object.
- this._settings = ExtensionUtils.getSettings();
+ this._settings = this.getSettings();
// Now we check whether the extension settings need to be migrated from a previous
// version. If this is the case, we defer the profile loading until this is finished.
const lastVersion = this._settings.get_int('last-extension-version');
- if (lastVersion < Me.metadata.version) {
+ if (lastVersion < this.metadata.version) {
if (lastVersion <= 26) {
// If the profile migration fails for some reason, the callback will create a
// default profile instead.
fromVersion26().finally(() => {
this._loadProfiles();
- this._settings.set_int('last-extension-version', Me.metadata.version);
+ this._settings.set_int('last-extension-version', this.metadata.version);
});
} else {
this._loadProfiles();
@@ -324,53 +317,50 @@ export default class Extension {
};
// With the code below, we hide the window-overlay (icon, label, close button) in the
- // overview once the close-animation is running. As the WindowPreview class is only
- // available on GNOME 3.38 and beyond, we cannot hide the overlay on GNOME 3.36.
- if (WindowPreview) {
+ // overview once the close-animation is running.
- // We will monkey-patch these methods.
- this._origDeleteAll = WindowPreview.prototype._deleteAll;
- this._origRestack = WindowPreview.prototype._restack;
- this._origInit = WindowPreview.prototype._init;
+ // We will monkey-patch these methods.
+ this._origDeleteAll = WindowPreview.prototype._deleteAll;
+ this._origRestack = WindowPreview.prototype._restack;
+ this._origInit = WindowPreview.prototype._init;
- // Whenever a WindowPreview is created, we connect to the referenced Meta.Window's
- // 'unmanaged' signal to hide the overlay.
- WindowPreview.prototype._init = function(...params) {
- extensionThis._origInit.apply(this, params);
+ // Whenever a WindowPreview is created, we connect to the referenced Meta.Window's
+ // 'unmanaged' signal to hide the overlay.
+ WindowPreview.prototype._init = function(...params) {
+ extensionThis._origInit.apply(this, params);
- // Hide the window's icon, name, and close button.
- const connectionID = this.metaWindow.connect('unmanaged', () => {
- if (this.window_container) {
- this.overlayEnabled = false;
- this._icon.visible = false;
- }
- });
-
- // Make sure to not call the callback above if the Meta.Window was not unmanaged
- // before leaving the overview.
- this.connect('destroy', () => {
- this.metaWindow.disconnect(connectionID);
- });
- };
-
- // The _deleteAll is called when the user clicks the X in the overview. We should
- // not attempt to close windows twice. Due to the animation in the overview, the
- // close button can be clicked twice which normally would lead to a crash.
- WindowPreview.prototype._deleteAll = function() {
- if (!this._closeRequested) {
- extensionThis._origDeleteAll.apply(this);
+ // Hide the window's icon, name, and close button.
+ const connectionID = this.metaWindow.connect('unmanaged', () => {
+ if (this.window_container) {
+ this.overlayEnabled = false;
+ this._icon.visible = false;
}
- };
+ });
- // This is required, else WindowPreview's _restack() which is called by the
- // "this.overlayEnabled = false", sometimes tries to access an already delete
- // WindowPreview.
- WindowPreview.prototype._restack = function() {
- if (!this._closeRequested) {
- extensionThis._origRestack.apply(this);
- }
- };
- }
+ // Make sure to not call the callback above if the Meta.Window was not unmanaged
+ // before leaving the overview.
+ this.connect('destroy', () => {
+ this.metaWindow.disconnect(connectionID);
+ });
+ };
+
+ // The _deleteAll is called when the user clicks the X in the overview. We should
+ // not attempt to close windows twice. Due to the animation in the overview, the
+ // close button can be clicked twice which normally would lead to a crash.
+ WindowPreview.prototype._deleteAll = function() {
+ if (!this._closeRequested) {
+ extensionThis._origDeleteAll.apply(this);
+ }
+ };
+
+ // This is required, else WindowPreview's _restack() which is called by the
+ // "this.overlayEnabled = false", sometimes tries to access an already delete
+ // WindowPreview.
+ WindowPreview.prototype._restack = function() {
+ if (!this._closeRequested) {
+ extensionThis._origRestack.apply(this);
+ }
+ };
}
// This function could be called after the extension is uninstalled, disabled in GNOME
@@ -395,11 +385,9 @@ export default class Extension {
Main.wm._shouldAnimateActor = this._origShouldAnimateActor;
Main.wm._waitForOverviewToHide = this._origWaitForOverviewToHide;
- if (WindowPreview) {
- WindowPreview.prototype._deleteAll = this._origDeleteAll;
- WindowPreview.prototype._restack = this._origRestack;
- WindowPreview.prototype._init = this._origInit;
- }
+ WindowPreview.prototype._deleteAll = this._origDeleteAll;
+ WindowPreview.prototype._restack = this._origRestack;
+ WindowPreview.prototype._init = this._origInit;
this._settings = null;
}
@@ -415,7 +403,7 @@ export default class Extension {
_loadProfiles() {
// Get all currently available profiles.
- const profileManager = new ProfileManager();
+ const profileManager = new ProfileManager(this.metadata);
this._profiles = profileManager.getProfiles();
// Whenever the properties of a profile is changed in the settings, we may have to
@@ -666,8 +654,3 @@ export default class Extension {
return shader == null;
}
}
-
-// This function is called once when the extension is loaded, not enabled.
-function init() {
- return new Extension();
-}
diff --git a/prefs.js b/prefs.js
index ecb9f64..d47c0cd 100644
--- a/prefs.js
+++ b/prefs.js
@@ -45,10 +45,7 @@ import TVEffect from './src/effects/TVEffect.js';
import TVGlitch from './src/effects/TVGlitch.js';
import Wisps from './src/effects/Wisps.js';
-const _ = imports.gettext.domain('burn-my-windows').gettext;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
+import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
//////////////////////////////////////////////////////////////////////////////////////////
// The preferences dialog is organized in pages, each of which is loaded from a //
@@ -56,15 +53,10 @@ const Me = imports.misc.extensionUtils.getCurrentExtension();
// from the respective effects. //
//////////////////////////////////////////////////////////////////////////////////////////
-export default class ExtensionPreferences {
+export default class BurnMyWindowsPreferences extends ExtensionPreferences {
// ------------------------------------------------------------ constructor / destructor
- // This is used for setting up the translations.
- constructor() {
- ExtensionUtils.initTranslations();
- }
-
fillPreferencesWindow(window) {
window.set_default_size(650, 750);
@@ -94,7 +86,8 @@ export default class ExtensionPreferences {
];
// Load all of our resources.
- this._resources = Gio.Resource.load(Me.path + '/resources/burn-my-windows.gresource');
+ this._resources =
+ Gio.Resource.load(this.path + '/resources/burn-my-windows.gresource');
Gio.resources_register(this._resources);
// Load the CSS file for the settings dialog. If using libadwaita, we do not need an
@@ -125,10 +118,10 @@ export default class ExtensionPreferences {
this._builder.add_from_resource(`/ui/${getUIDir()}/prefs.ui`);
// Store a reference to the general settings object.
- this._settings = ExtensionUtils.getSettings();
+ this._settings = this.getSettings();
// This tracks all available effect profiles.
- this._profileManager = new ProfileManager();
+ this._profileManager = new ProfileManager(this.metadata);
// This is used to track all connections to properties of the current effect profile.
// Whenever the current effect profile changes, all connections are disconnected.
@@ -396,7 +389,7 @@ export default class ExtensionPreferences {
const window = isGTK4() ? widget.get_root() : widget.get_toplevel();
// Show the version number in the title bar.
- window.set_title(`Burn-My-Windows ${Me.metadata.version}`);
+ window.set_title(`Burn-My-Windows ${this.metadata.version}`);
this._loadActiveProfile();
this._updateProfileMenu();
@@ -404,7 +397,7 @@ export default class ExtensionPreferences {
// Show an Adw.Toast or a Gtk.InfoBar whenever Burn-My-Windows was updated. We use a
// small timeout so that it is not shown instantaneously.
const lastVersion = this._settings.get_int('last-prefs-version');
- if (lastVersion < Me.metadata.version) {
+ if (lastVersion < this.metadata.version) {
this._showUpdateInfoTimeout =
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 2000, () => {
this._showUpdateInfoTimeout = 0;
@@ -415,15 +408,15 @@ export default class ExtensionPreferences {
toast.set_action_name('prefs.changelog');
toast.set_timeout(0);
- toast.connect(
- 'dismissed',
- () => this._settings.set_int('last-prefs-version', Me.metadata.version));
+ toast.connect('dismissed',
+ () => this._settings.set_int('last-prefs-version',
+ this.metadata.version));
window.add_toast(toast);
} else {
const infoBar = this._builder.get_object('update-info');
infoBar.connect('response', i => {
- this._settings.set_int('last-prefs-version', Me.metadata.version);
+ this._settings.set_int('last-prefs-version', this.metadata.version);
i.set_revealed(false);
});
infoBar.set_revealed(true);
@@ -555,7 +548,7 @@ GitHub: https://github.com/spon
null,
'https://github.com/Schneegans/Burn-My-Windows/blob/main/docs/changelog.md',
Gdk.CURRENT_TIME);
- this._settings.set_int('last-prefs-version', Me.metadata.version)
+ this._settings.set_int('last-prefs-version', this.metadata.version)
});
group.add_action(changelogAction);
@@ -588,7 +581,7 @@ GitHub: https://github.com/spon
dialog = new Adw.AboutWindow({transient_for: window, modal: true});
dialog.set_application_icon('burn-my-windows-symbolic');
dialog.set_application_name('Burn-My-Windows');
- dialog.set_version(`${Me.metadata.version}`);
+ dialog.set_version(`${this.metadata.version}`);
dialog.set_developer_name('Simon Schneegans');
dialog.set_issue_url('https://github.com/Schneegans/Burn-My-Windows/issues');
if (sponsors.gold.length > 0) {
@@ -621,7 +614,7 @@ GitHub: https://github.com/spon
dialog = new Gtk.AboutDialog({transient_for: window, modal: true});
dialog.set_logo_icon_name('burn-my-windows-symbolic');
- dialog.set_program_name(`Burn-My-Windows ${Me.metadata.version}`);
+ dialog.set_program_name(`Burn-My-Windows ${this.metadata.version}`);
dialog.set_authors(['Simon Schneegans']);
if (sponsors.gold.length > 0) {
dialog.add_credit_section(_('Gold Sponsors'),
@@ -904,7 +897,7 @@ GitHub: https://github.com/spon
// configuration option of the profile is changed.
_updateProfileButton() {
this._builder.get_object('choose-profile-button').label =
- this._profileManager.getProfileName(this.getProfileSettings());
+ this._getProfileName(this.getProfileSettings());
}
// This updates the list of available profiles in the dropdown of the profile-selection
@@ -918,7 +911,7 @@ GitHub: https://github.com/spon
// Then add an entry for each available profile.
this._profileManager.getProfiles().forEach(profile => {
- const label = this._profileManager.getProfileName(profile.settings);
+ const label = this._getProfileName(profile.settings);
const item = Gio.MenuItem.new(label, 'prefs.active-profile');
item.set_action_and_target_value('prefs.active-profile',
GLib.Variant.new_string(profile.path));
@@ -926,6 +919,58 @@ GitHub: https://github.com/spon
});
}
+ // Profiles are named according to their configuration. This method returns a localized
+ // string describing the settings of the profile.
+ _getProfileName(settings) {
+ let items = [];
+
+ // If an app is configured, use it as first component for the profile's name.
+ const app = settings.get_string('profile-app');
+ if (app != '') {
+ items.push(app);
+ }
+
+ // Now add components to the name for each non-default profile option. Make sure that
+ // these are the same strings as used in the UI files!
+ const addComponent = (settingsKey, options) => {
+ const option = settings.get_int(settingsKey);
+ if (option > 0) {
+ items.push(options[option - 1]);
+ }
+ };
+
+ // clang-format off
+ addComponent('profile-animation-type', [_('Opening Windows'),
+ _('Closing Windows')]);
+ addComponent('profile-window-type', [_('Normal Windows'),
+ _('Dialog Windows')]);
+ addComponent('profile-color-scheme', [_('Default Color Scheme'),
+ _('Dark Color Scheme')]);
+ addComponent('profile-power-mode', [_('On Battery'),
+ _('Plugged In')]);
+ addComponent('profile-power-profile', [_('Power-Saver Mode'),
+ _('Balanced Mode'),
+ _('Performance Mode'),
+ _('Power Saver or Balanced'),
+ _('Balanced or Performance')]);
+ // clang-format on
+
+ // If the profile is a high-priority profile, also add this..
+ if (settings.get_boolean('profile-high-priority')) {
+ items.push(_('High Priority'));
+ }
+
+ let name = '';
+
+ if (items.length == 0) {
+ name = _('Standard Profile');
+ } else {
+ name = items.join(' · ');
+ }
+
+ return name;
+ }
+
// This wrapper connects a given callback to a profile settings key. Use this instead of
// the direct connect() call on the profile settings to make sure that the callback is
// disconnected when the active profile changes.
diff --git a/src/ProfileManager.js b/src/ProfileManager.js
index 1d43014..38201d1 100644
--- a/src/ProfileManager.js
+++ b/src/ProfileManager.js
@@ -17,10 +17,6 @@
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
-const _ = imports.gettext.domain('burn-my-windows').gettext;
-
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-
//////////////////////////////////////////////////////////////////////////////////////////
// Burn-My-Windows allows applying different sets of effect settings under specific //
// circumstances. These settings are called "effect profiles". The ProfileManager //
@@ -33,7 +29,9 @@ const Me = imports.misc.extensionUtils.getCurrentExtension();
export class ProfileManager {
// ------------------------------------------------------------------------- constructor
- constructor() {
+ constructor(metadata) {
+ this._metadata = metadata;
+
this._makeProfilesDir();
this.reloadProfiles();
}
@@ -150,58 +148,6 @@ export class ProfileManager {
return priority;
}
- // Profiles are named according to their configuration. This method returns a localized
- // string describing the settings of the profile.
- getProfileName(settings) {
- let items = [];
-
- // If an app is configured, use it as first component for the profile's name.
- const app = settings.get_string('profile-app');
- if (app != '') {
- items.push(app);
- }
-
- // Now add components to the name for each non-default profile option. Make sure that
- // these are the same strings as used in the UI files!
- const addComponent = (settingsKey, options) => {
- const option = settings.get_int(settingsKey);
- if (option > 0) {
- items.push(options[option - 1]);
- }
- };
-
- // clang-format off
- addComponent('profile-animation-type', [_('Opening Windows'),
- _('Closing Windows')]);
- addComponent('profile-window-type', [_('Normal Windows'),
- _('Dialog Windows')]);
- addComponent('profile-color-scheme', [_('Default Color Scheme'),
- _('Dark Color Scheme')]);
- addComponent('profile-power-mode', [_('On Battery'),
- _('Plugged In')]);
- addComponent('profile-power-profile', [_('Power-Saver Mode'),
- _('Balanced Mode'),
- _('Performance Mode'),
- _('Power Saver or Balanced'),
- _('Balanced or Performance')]);
- // clang-format on
-
- // If the profile is a high-priority profile, also add this..
- if (settings.get_boolean('profile-high-priority')) {
- items.push(_('High Priority'));
- }
-
- let name = '';
-
- if (items.length == 0) {
- name = _('Standard Profile');
- } else {
- name = items.join(' · ');
- }
-
- return name;
- }
-
// ----------------------------------------------------------------------- private stuff
// Creates the directory ~/.config/burn-my-windows/profiles if it does not yet exist.
@@ -220,7 +166,7 @@ export class ProfileManager {
// Expect USER extensions to have a schemas/ subfolder, otherwise assume a
// SYSTEM extension that has been installed in the same prefix as the shell
- const schemaDir = Me.dir.get_child('schemas');
+ const schemaDir = this._metadata.dir.get_child('schemas');
let source;
if (schemaDir.query_exists(null)) {
source = Gio.SettingsSchemaSource.new_from_directory(
diff --git a/src/WindowPicker.js b/src/WindowPicker.js
index 0cd2945..157ef28 100644
--- a/src/WindowPicker.js
+++ b/src/WindowPicker.js
@@ -18,8 +18,8 @@
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
-const Main = imports.ui.main;
-const LookingGlass = imports.ui.lookingGlass;
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js';
import {getStringResource} from './utils.js';
diff --git a/src/utils.js b/src/utils.js
index 6999fa9..1c5b0c6 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -33,12 +33,9 @@ function toNumericVersion(x) {
return x;
}
-const Me = imports.misc.extensionUtils.getCurrentExtension();
const Config = imports.misc.config;
const [GS_MAJOR, GS_MINOR] = Config.PACKAGE_VERSION.split('.').map(toNumericVersion);
-const _ = imports.gettext.domain('burn-my-windows').gettext;
-
// This method can be used to write a message to GNOME Shell's log. This is enhances
// the standard log() functionality by prepending the extension's name and the location
// where the message was logged. As the extensions name is part of the location, you
@@ -54,9 +51,10 @@ export function debug(message) {
// Find the index of the extension directory (e.g. particles@schneegans.github.com) in
// the stack entry. We do not want to print the entire absolute file path.
- const extensionRoot = stack[0].indexOf(Me.metadata.uuid);
+ // const extensionRoot = stack[0].indexOf(Extension.uuid);
- log('[' + stack[0].slice(extensionRoot) + '] ' + message);
+ log('[' + stack[0] + '] ' + message);
+ // log('[' + stack[0].slice(extensionRoot) + '] ' + message);
}
// This method simply returns true if we are currently using GTK4.