🎉 Implement profile selection

This commit is contained in:
Simon Schneegans
2023-01-30 13:57:33 +01:00
parent 35860c7b2d
commit 99b90377c5
5 changed files with 185 additions and 52 deletions
+77 -30
View File
@@ -32,6 +32,7 @@ const ExtensionUtils = imports.misc.extensionUtils;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const utils = Me.imports.src.utils;
const ProfileManager = Me.imports.src.ProfileManager.ProfileManager;
const WindowPicker = Me.imports.src.WindowPicker.WindowPicker;
//////////////////////////////////////////////////////////////////////////////////////////
// This extensions modifies the window-close and window-open animations with all kinds //
@@ -90,6 +91,13 @@ class Extension {
this._loadProfiles();
// This is used to get the desktop's color scheme.
this._shellSettings = new Gio.Settings({schema: 'org.gnome.desktop.interface'});
// Enable the window-picking D-Bus API for the preferences dialog.
this._windowPicker = new WindowPicker();
this._windowPicker.export();
// We will use extensionThis to refer to the extension inside the patched methods.
const extensionThis = this;
@@ -348,6 +356,9 @@ class Extension {
// Unregister our resources.
Gio.resources_unregister(this._resources);
// Disable the window-picking D-Bus API.
this._windowPicker.unexport();
// Restore the original window-open and window-close animations.
global.window_manager.disconnect(this._destroyConnection);
global.display.disconnect(this._windowCreatedConnection);
@@ -373,41 +384,50 @@ class Extension {
// ----------------------------------------------------------------------- private stuff
// This loads all effect profiles and assigns a priority to each profile. Whenever a
// window is opened or closed, the matching effect profile with the highest priority
// will be chosen.
// This method is called whenever the currently edited profile in the/ preferences
// dialog changes. This is most likely a bit too often, but it will also happen whenever
// a new profile is created and whenever an old profile is deleted.
_loadProfiles() {
// Get all currently available profiles.
const profileManager = new ProfileManager();
this._profiles = profileManager.getProfiles();
utils.debug('load profiles!');
// Whenever the properties of a profile is changed in the settings, we may have to
// resort all profiles according to their priority.
const updatePriority = (p) => {
utils.debug('sort profiles!');
p.priority = profileManager.getProfilePriority(p.settings);
this._profiles.sort((a, b) => b.priority - a.priority);
};
this._profiles = profileManager.getProfiles();
// For each profile, assign an initial priority and update the priority whenever a
// related setting changes.
this._profiles.forEach(p => {
p.priority = profileManager.getProfilePriority(p.settings);
p.settings.connect('changed::profile-app', () => updatePriority(p));
p.settings.connect('changed::profile-animation-type', () => updatePriority(p));
p.settings.connect('changed::profile-window-type', () => updatePriority(p));
p.settings.connect('changed::profile-desktop-style', () => updatePriority(p));
p.settings.connect('changed::profile-color-scheme', () => updatePriority(p));
p.settings.connect('changed::profile-power-mode', () => updatePriority(p));
p.settings.connect('changed::profile-power-profile', () => updatePriority(p));
p.priority = profileManager.getProfilePriority(p.settings);
});
utils.debug('sort profiles!');
// Sort all profiles initially according to their initial priority.
this._profiles.sort((a, b) => b.priority - a.priority);
}
// This method adds one of the configured effects to the given actor. If forOpening is
// set to true, a effect from the enabled window-open animations is chosen, else an
// enabled window-close animation is used. This will also tweak the transitions of the
// given actor (e.g. scale it up if required).
// This method adds one of the configured effects to the given actor. First, a profile
// matching the current circumstances is chosen. Then a random effect from its enabled
// effects will be selected. This will also tweak the transitions of the given actor
// (e.g. scale it up if required).
_setupEffect(actor, forOpening) {
// In case we return early, make sure that the animation times are reset properly.
this._fixAnimationTimes(forOpening, null);
// Only add effects to normal windows and dialog windows.
// For now, we only add effects to normal windows and dialog windows.
const isNormalWindow = actor.meta_window.window_type == Meta.WindowType.NORMAL;
const isDialogWindow =
actor.meta_window.window_type == Meta.WindowType.MODAL_DIALOG ||
@@ -417,20 +437,6 @@ class Extension {
return;
}
// TODO!.
// We may have to do nothing if running on battery power or if in power-save mode.
// let disableOnBattery =
// this._settings.get_boolean('disable-on-battery') && this._upowerProxy.OnBattery;
// let disableOnPowerSave = this._settings.get_boolean('disable-on-power-save') &&
// this._powerProfilesProxy && this._powerProfilesProxy.ActiveProfile ==
// 'power-saver';
// if (!skip! && previewNick == '') {
// return;
// }
// There is the weird case where an animation is already ongoing. This happens when a
// window is closed which has been created before the session was started (e.g. when
// GNOME Shell has been restarted in the meantime).
@@ -441,7 +447,7 @@ class Extension {
oldShader.returnToFactory();
}
// ------------------------------------------------------------------ choose an effect
// ----------------------------------------------- choose a profile and then an effect
// Usually, we use the effect profile with the highest priority which matches the
// current circumstances. From this profile, we choose a random effect. However, if an
@@ -468,22 +474,62 @@ class Extension {
// effect.
else {
// These numbers match the indices in the Gtk.StringLists defined in the UI files
// (e.g. resources/ui/adw/prefs.ui).
const animationType = forOpening ? 1 : 2;
const windowType = isNormalWindow ? 1 : 2;
const powerMode = this._upowerProxy.OnBattery ? 1 : 2;
// Get the first profile whose constraints match the circumstances. The list is
// sorted by priority, so we are good to take the first match.
profile = this._profiles.find(p => {
const profileApp = p.settings.get_string('profile-app');
const profileAnimationType = p.settings.get_int('profile-animation-type');
const profileWindowType = p.settings.get_int('profile-window-type');
const profileDesktopStyle = p.settings.get_int('profile-desktop-style');
const profilePowerMode = p.settings.get_int('profile-power-mode');
const profileColorScheme = p.settings.get_int('profile-color-scheme');
const profilePowerProfile = p.settings.get_int('profile-power-profile');
return (profileAnimationType == 0 || profileAnimationType == animationType) &&
// First we check whether the animation type, window type, and power mode are
// matching.
let matches =
(profileAnimationType == 0 || profileAnimationType == animationType) &&
(profileWindowType == 0 || profileWindowType == windowType) &&
(profilePowerMode == 0 || profilePowerMode == powerMode);
// If that was the case, we also check the application name.
if (matches && profileApp != '') {
const app = actor.meta_window.get_wm_class().toLowerCase();
matches = app == profileApp.toLowerCase();
}
// If the profile is still matching, we also check the color scheme.
if (matches && profileColorScheme != 0 && utils.shellVersionIsAtLeast(42, 0)) {
const colorScheme = this._shellSettings.get_string('color-scheme');
matches &= (profileColorScheme == 1 && colorScheme == 'default') ||
(profileColorScheme == 2 && colorScheme == 'prefer-dark');
}
// Finally, we may also have to check the power profile.
if (matches && profilePowerProfile != 0 && this._powerProfilesProxy) {
const powerProfile = this._powerProfilesProxy.ActiveProfile;
// To understand the numbers, please refer to the indices in the Gtk.StringList
// of the profile-power-profile Adw.ComboRow in resources/ui/adw/prefs.ui.
if (powerProfile == 'power-saver') {
matches &= profilePowerProfile == 1 || profilePowerProfile == 4;
} else if (powerProfile == 'balanced') {
matches &= profilePowerProfile == 2 || profilePowerProfile == 4 ||
profilePowerProfile == 5;
} else {
matches &= profilePowerProfile == 3 || profilePowerProfile == 5;
}
}
return matches;
});
// If we found a matching profile, choose a random effect from it.
if (profile) {
// Create a list of all enabled effects of this profile.
@@ -503,6 +549,7 @@ class Extension {
return;
}
// ----------------------------------------------------------- tweak actor transitions
// If we are currently performing integration test, all animations are set to a fixed