From f619ce4fa7078d5c3332361e898c9e9767021950 Mon Sep 17 00:00:00 2001 From: June Date: Fri, 27 Sep 2024 03:24:47 +0200 Subject: [PATCH] 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. --- ...l.extensions.top-bar-organizer.gschema.xml | 8 +++++ src/extension.js | 30 ++++++++++++------- src/extensionModules/BoxOrderManager.js | 20 ++++++++++++- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/data/org.gnome.shell.extensions.top-bar-organizer.gschema.xml b/data/org.gnome.shell.extensions.top-bar-organizer.gschema.xml index 24e17fe..8b143e7 100644 --- a/data/org.gnome.shell.extensions.top-bar-organizer.gschema.xml +++ b/data/org.gnome.shell.extensions.top-bar-organizer.gschema.xml @@ -13,5 +13,13 @@ Order of items in the right box of the top bar. [] + + Top bar items to (forcefully) hide. + [] + + + Top bar items to (forcefully) show. + [] + diff --git a/src/extension.js b/src/extension.js index 94778e9..353cfe9 100644 --- a/src/extension.js +++ b/src/extension.js @@ -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(); } } diff --git a/src/extensionModules/BoxOrderManager.js b/src/extensionModules/BoxOrderManager.js index 5febb5f..bb27391 100644 --- a/src/extensionModules/BoxOrderManager.js +++ b/src/extensionModules/BoxOrderManager.js @@ -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"