Top-Bar-Organizer/src/extension.js
Julian Schacher 40cf8de1a8
Fix: Don't affect (or interact with) panel of unlock screen
The panel gets set to the state it should have for the unlock screen
before extension disable. Because of this the extension makes icons
show, which shouldn't show. So fix that by not ordering the panel, if
the current session mode isn't "user".
Also generally don't interact with the panel, if the current session
mode isn't "user".
2023-01-30 14:46:56 +01:00

174 lines
6.8 KiB
JavaScript

"use strict";
/* exported init */
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const BoxOrderManager = Me.imports.extensionModules.BoxOrderManager;
class Extension {
constructor() {
}
enable() {
this._settings = ExtensionUtils.getSettings();
this._boxOrderManager = new BoxOrderManager.BoxOrderManager();
/// Stuff to do on startup(extension enable).
// Initially handle new top bar items and order top bar boxes.
this.#handleNewItemsAndOrderTopBar();
// Overwrite `Panel._addToPanelBox` method with one handling new items
// and also handle AppIndicators getting ready, to handle new items.
this.#overwritePanelAddToPanelBox();
this._boxOrderManager.connect("appIndicatorReady", () => {
this.#handleNewItemsAndOrderTopBar();
});
// Handle changes of configured box orders.
this._settingsHandlerIds = [];
const addConfiguredBoxOrderChangeHandler = (box) => {
let handlerId = this._settings.connect(`changed::${box}-box-order`, () => {
this.#handleNewItemsAndOrderTopBar();
});
this._settingsHandlerIds.push(handlerId);
};
addConfiguredBoxOrderChangeHandler("left");
addConfiguredBoxOrderChangeHandler("center");
addConfiguredBoxOrderChangeHandler("right");
}
disable() {
// Revert the overwrite of `Panel._addToPanelBox`.
Panel.Panel.prototype._addToPanelBox = Panel.Panel.prototype._originalAddToPanelBox;
// Set `Panel._originalAddToPanelBox` to `undefined`.
Panel._originalAddToPanelBox = undefined;
// Disconnect signals.
for (const handlerId of this._settingsHandlerIds) {
this._settings.disconnect(handlerId);
}
this._boxOrderManager.disconnectSignals();
this._settings = null;
this._boxOrderManager = null;
}
////////////////////////////////////////////////////////////////////////////
/// Methods used on extension enable. ///
////////////////////////////////////////////////////////////////////////////
/**
* Overwrite `Panel._addToPanelBox` with a custom method, which simply calls
* the original one and handles new items and orders the top bar afterwards.
*/
#overwritePanelAddToPanelBox() {
// Add the original `Panel._addToPanelBox` method as
// `Panel._originalAddToPanelBox`.
Panel.Panel.prototype._originalAddToPanelBox = Panel.Panel.prototype._addToPanelBox;
const handleNewItemsAndOrderTopBar = () => {
this.#handleNewItemsAndOrderTopBar();
};
// Overwrite `Panel._addToPanelBox`.
Panel.Panel.prototype._addToPanelBox = function(role, indicator, position, box) {
// Simply call the original `_addToPanelBox` and order the top bar
// and handle new items afterwards.
this._originalAddToPanelBox(role, indicator, position, box);
handleNewItemsAndOrderTopBar();
};
}
////////////////////////////////////////////////////////////////////////////
/// Helper methods holding logic needed by other methods. ///
////////////////////////////////////////////////////////////////////////////
/**
* This method orders the top bar items of the specified box according to
* the configured box orders.
* @param {string} box - The box to order.
*/
#orderTopBarItems(box) {
// Only run, when in "user" session mode.
if(Main.sessionMode.currentMode !== "user") {
return;
}
// Get the valid box order.
const validBoxOrder = this._boxOrderManager.createValidBoxOrder(box);
// Get the relevant box of `Main.panel`.
let panelBox;
switch (box) {
case "left":
panelBox = Main.panel._leftBox;
break;
case "center":
panelBox = Main.panel._centerBox;
break;
case "right":
panelBox = Main.panel._rightBox;
break;
}
/// Go through the items (or rather their roles) of the validBoxOrder
/// and order the panelBox accordingly.
for (let i = 0; i < validBoxOrder.length; i++) {
const role = validBoxOrder[i];
// Get the indicator container associated with the current role.
const associatedIndicatorContainer = Main.panel.statusArea[role].container;
associatedIndicatorContainer.get_parent().remove_child(associatedIndicatorContainer);
if (box === "right") {
// If the target panel box is the right panel box, insert the
// indicator container at index `-1`, which just adds it to the
// end (correct order is ensured, since `validBoxOrder` is
// sorted correctly and we're looping over it in order).
// This way unaccounted-for indicator containers will be at the
// left, which is preferred, since the box is logically
// right-to-left.
// The same applies for indicator containers, which are just
// temporarily unaccounted for (like for indicator containers of
// not yet ready app indicators), since them being at the right
// for a probably temporary stay causes all the indicator
// containers to shift.
panelBox.insert_child_at_index(associatedIndicatorContainer, -1);
} else {
panelBox.insert_child_at_index(associatedIndicatorContainer, i);
}
}
// To handle the case, where the box order got set to a permutation
// of an outdated box order, it would be wise, if the caller updated the
// box order now to include the items present in the top bar.
}
/**
* This method handles all new items currently present in the top bar and
* orders the items of all top bar boxes.
*/
#handleNewItemsAndOrderTopBar() {
// Only run, when in "user" session mode.
if(Main.sessionMode.currentMode !== "user") {
return;
}
this._boxOrderManager.saveNewTopBarItems();
this.#orderTopBarItems("left");
this.#orderTopBarItems("center");
this.#orderTopBarItems("right");
// In `this.#orderTopBarItems` it says to update the box orders to
// include potentially new items, since the ordering might have been
// based on an outdated box order. However, since we already handle new
// top bar items at the beginning of this method, this isn't a concern.
}
}
function init() {
return new Extension();
}