feature: make it possible to (forcefully) hide or show top bar items

This is only the core extension logic for now, settings UI still needs
to follow.
The logic only acts on the indicator container, not the indicator
itself, meaning that e.g. a screen recording indicator, which is hidden
on the indicator level, can be forcefully hidden, but not forcefully
shown. Because of that and because forcefully hiding it breaks controls
for screen recording, a potential settings implementation should exclude
visiblity controls for some elements like e.g. the screen recording
indicator.
This commit is contained in:
June 2024-09-27 03:24:47 +02:00
parent 80f394d2d4
commit f619ce4fa7
No known key found for this signature in database
3 changed files with 47 additions and 11 deletions

View File

@ -13,5 +13,13 @@
<description>Order of items in the right box of the top bar.</description>
<default>[]</default>
</key>
<key name="hide" type="as">
<description>Top bar items to (forcefully) hide.</description>
<default>[]</default>
</key>
<key name="show" type="as">
<description>Top bar items to (forcefully) show.</description>
<default>[]</default>
</key>
</schema>
</schemalist>

View File

@ -24,17 +24,19 @@ export default class TopBarOrganizerExtension extends Extension {
this.#handleNewItemsAndOrderTopBar();
});
// Handle changes of configured box orders.
// Handle changes of settings.
this._settingsHandlerIds = [];
const addConfiguredBoxOrderChangeHandler = (box) => {
let handlerId = this._settings.connect(`changed::${box}-box-order`, () => {
const addSettingsChangeHandler = (settingsName) => {
const handlerId = this._settings.connect(`changed::${settingsName}`, () => {
this.#handleNewItemsAndOrderTopBar();
});
this._settingsHandlerIds.push(handlerId);
};
addConfiguredBoxOrderChangeHandler("left");
addConfiguredBoxOrderChangeHandler("center");
addConfiguredBoxOrderChangeHandler("right");
addSettingsChangeHandler("left-box-order");
addSettingsChangeHandler("center-box-order");
addSettingsChangeHandler("right-box-order");
addSettingsChangeHandler("hide");
addSettingsChangeHandler("show");
}
disable() {
@ -115,9 +117,9 @@ export default class TopBarOrganizerExtension extends Extension {
/// Go through the items of the validBoxOrder and order the GNOME Shell
/// top bar box accordingly.
for (let i = 0; i < validBoxOrder.length; i++) {
const role = validBoxOrder[i].role;
const item = validBoxOrder[i];
// Get the indicator container associated with the current role.
const associatedIndicatorContainer = Main.panel.statusArea[role].container;
const associatedIndicatorContainer = Main.panel.statusArea[item.role].container;
// Save whether or not the indicator container is visible.
const isVisible = associatedIndicatorContainer.visible;
@ -141,8 +143,16 @@ export default class TopBarOrganizerExtension extends Extension {
panelBox.insert_child_at_index(associatedIndicatorContainer, i);
}
// Hide the indicator container again, if it wasn't visible.
if (!isVisible) {
// Hide the indicator container...
// - ...if it wasn't visible before and the hide property of the
// item is "default".
// - if the hide property of the item is "hide".
// In all other cases have the item show.
// An e.g. screen recording indicator still wouldn't show tho, since
// this here acts on the indicator container, but a screen recording
// indicator is hidden on the indicator level.
if ((!isVisible && item.hide === "default") ||
item.hide === "hide") {
associatedIndicatorContainer.hide();
}
}

View File

@ -5,10 +5,13 @@ import GObject from "gi://GObject";
import * as Main from "resource:///org/gnome/shell/ui/main.js";
/**
* A resolved box order item containing the items role and settings identifier.
* A resolved box order item containing the items role, settings identifier and
* additional information.
* @typedef {Object} ResolvedBoxOrderItem
* @property {string} settingsId - The settings identifier of the item.
* @property {string} role - The role of the item.
* @property {string} hide - Whether the item should be (forcefully) hidden
* (hide), shown (show) or just be left as is (default).
*/
/**
@ -135,6 +138,7 @@ export default class BoxOrderManager extends GObject.Object {
* Gets a resolved box order for the given top bar box, where all
* AppIndicator items got resolved using their roles, meaning they might be
* present multiple times or not at all depending on the roles stored.
* The items of the box order also have additional information stored.
* @param {string} box - The top bar box for which to get the resolved box order.
* Must be one of the following values:
* - "left"
@ -145,13 +149,26 @@ export default class BoxOrderManager extends GObject.Object {
#getResolvedBoxOrder(box) {
let boxOrder = this.#getBoxOrder(box);
const itemsToHide = this.#settings.get_strv("hide");
const itemsToShow = this.#settings.get_strv("show");
let resolvedBoxOrder = [];
for (const itemSettingsId of boxOrder) {
const resolvedBoxOrderItem = {
settingsId: itemSettingsId,
role: "",
hide: "",
};
// Set the hide state of the item.
if (itemsToHide.includes(resolvedBoxOrderItem.settingsId)) {
resolvedBoxOrderItem.hide = "hide";
} else if (itemsToShow.includes(resolvedBoxOrderItem.settingsId)) {
resolvedBoxOrderItem.hide = "show";
} else {
resolvedBoxOrderItem.hide = "default";
}
// If the items settings identifier doesn't indicate that the item
// is an AppIndicator/KStatusNotifierItem item, then its identifier
// is the role and it can just be added to the resolved box order.
@ -202,6 +219,7 @@ export default class BoxOrderManager extends GObject.Object {
* Gets a valid box order for the given top bar box, where all AppIndicator
* items got resolved and where only items are included, which are in some
* GNOME Shell top bar box.
* The items of the box order also have additional information stored.
* @param {string} box - The top bar box to return the valid box order for.
* Must be one of the following values:
* - "left"