Blob Blame History Raw
From 946db74f6a0c750c950e5da7957480abb7cecfec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 16 Nov 2018 23:08:34 +0100
Subject: [PATCH 1/6] Remove compatibility with older shell versions

By now this is completely untested code we are somewhat dragging
along. Those versions are better covered by old extension versions,
and the simpler code will make it easier to move forward.
---
 extensions/top-icons/extension.js | 135 ++++--------------------------
 1 file changed, 16 insertions(+), 119 deletions(-)

diff --git a/extensions/top-icons/extension.js b/extensions/top-icons/extension.js
index 7312a26..c4c5084 100644
--- a/extensions/top-icons/extension.js
+++ b/extensions/top-icons/extension.js
@@ -1,69 +1,41 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const Clutter = imports.gi.Clutter;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 const Main = imports.ui.main;
-const GLib = imports.gi.GLib;
-const Lang = imports.lang;
-const Panel = imports.ui.panel;
 const PanelMenu = imports.ui.panelMenu;
 const Meta = imports.gi.Meta;
 const Mainloop = imports.mainloop;
-const NotificationDaemon = imports.ui.notificationDaemon;
 const System = imports.system;
 
-let trayAddedId = 0;
-let trayRemovedId = 0;
-let getSource = null;
 let icons = [];
-let notificationDaemon = null;
 let sysTray = null;
 
 const PANEL_ICON_SIZE = 24;
 
+const STANDARD_TRAY_ICON_IMPLEMENTATIONS = [
+    'bluetooth-applet',
+    'gnome-sound-applet',
+    'nm-applet',
+    'gnome-power-manager',
+    'keyboard',
+    'a11y-keyboard',
+    'kbd-scrolllock',
+    'kbd-numlock',
+    'kbd-capslock',
+    'ibus-ui-gtk'
+];
+
 function init() {
-    if (Main.legacyTray) {
-        notificationDaemon = Main.legacyTray;
-        NotificationDaemon.STANDARD_TRAY_ICON_IMPLEMENTATIONS = imports.ui.legacyTray.STANDARD_TRAY_ICON_IMPLEMENTATIONS;
-    }
-    else if (Main.notificationDaemon._fdoNotificationDaemon &&
-             Main.notificationDaemon._fdoNotificationDaemon._trayManager) {
-        notificationDaemon = Main.notificationDaemon._fdoNotificationDaemon;
-        getSource = Lang.bind(notificationDaemon, NotificationDaemon.FdoNotificationDaemon.prototype._getSource);
-    }
-    else if (Main.notificationDaemon._trayManager) {
-        notificationDaemon = Main.notificationDaemon;
-        getSource = Lang.bind(notificationDaemon, NotificationDaemon.NotificationDaemon.prototype._getSource);
-    }
-    else {
-        NotificationDaemon.STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
-            'bluetooth-applet': 1, 'gnome-sound-applet': 1, 'nm-applet': 1,
-            'gnome-power-manager': 1, 'keyboard': 1, 'a11y-keyboard': 1,
-            'kbd-scrolllock': 1, 'kbd-numlock': 1, 'kbd-capslock': 1, 'ibus-ui-gtk': 1
-        };
-    }
 }
 
 function enable() {
-    if (notificationDaemon)
-        GLib.idle_add(GLib.PRIORITY_LOW, moveToTop);
-    else
-        createTray();
+    createTray();
 }
 
-function createSource (title, pid, ndata, sender, trayIcon) {
-  if (trayIcon) {
-    onTrayIconAdded(this, trayIcon, title);
-    return null;
-  }
-
-  return getSource(title, pid, ndata, sender, trayIcon);
-};
-
 function onTrayIconAdded(o, icon, role) {
     let wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : '';
-    if (NotificationDaemon.STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass] !== undefined)
+    if (STANDARD_TRAY_ICON_IMPLEMENTATIONS.includes(wmClass))
         return;
 
     let buttonBox = new PanelMenu.ButtonBox();
@@ -145,81 +117,6 @@ function destroyTray() {
     System.gc(); // force finalizing tray to unmanage screen
 }
 
-function moveToTop() {
-    notificationDaemon._trayManager.disconnect(notificationDaemon._trayIconAddedId);
-    notificationDaemon._trayManager.disconnect(notificationDaemon._trayIconRemovedId);
-    trayAddedId = notificationDaemon._trayManager.connect('tray-icon-added', onTrayIconAdded);
-    trayRemovedId = notificationDaemon._trayManager.connect('tray-icon-removed', onTrayIconRemoved);
-
-    notificationDaemon._getSource = createSource;
-
-    let toDestroy = [];
-    if (notificationDaemon._sources) {
-        for (let i = 0; i < notificationDaemon._sources.length; i++) {
-            let source = notificationDaemon._sources[i];
-            if (!source.trayIcon)
-                continue;
-            let parent = source.trayIcon.get_parent();
-            parent.remove_actor(source.trayIcon);
-            onTrayIconAdded(this, source.trayIcon, source.initialTitle);
-            toDestroy.push(source);
-        }
-    }
-    else {
-        for (let i = 0; i < notificationDaemon._iconBox.get_n_children(); i++) {
-            let button = notificationDaemon._iconBox.get_child_at_index(i);
-            let icon = button.child;
-            button.remove_actor(icon);
-            onTrayIconAdded(this, icon, '');
-            toDestroy.push(button);
-        }
-    }
-
-    for (let i = 0; i < toDestroy.length; i++) {
-        toDestroy[i].destroy();
-    }
-}
-
-function moveToTray() {
-    if (trayAddedId != 0) {
-        notificationDaemon._trayManager.disconnect(trayAddedId);
-        trayAddedId = 0;
-    }
-
-    if (trayRemovedId != 0) {
-        notificationDaemon._trayManager.disconnect(trayRemovedId);
-        trayRemovedId = 0;
-    }
-
-    notificationDaemon._trayIconAddedId = notificationDaemon._trayManager.connect('tray-icon-added',
-                                                Lang.bind(notificationDaemon, notificationDaemon._onTrayIconAdded));
-    notificationDaemon._trayIconRemovedId = notificationDaemon._trayManager.connect('tray-icon-removed',
-                                                Lang.bind(notificationDaemon, notificationDaemon._onTrayIconRemoved));
-
-    notificationDaemon._getSource = getSource;
-
-    for (let i = 0; i < icons.length; i++) {
-        let icon = icons[i];
-        let parent = icon.get_parent();
-        if (icon._clicked) {
-            icon.disconnect(icon._clicked);
-        }
-        icon._clicked = undefined;
-        if (icon._proxyAlloc) {
-            Main.panel._rightBox.disconnect(icon._proxyAlloc);
-        }
-        icon._clickProxy.destroy();
-        parent.remove_actor(icon);
-        parent.destroy();
-        notificationDaemon._onTrayIconAdded(notificationDaemon, icon);
-    }
-
-    icons = [];
-}
-
 function disable() {
-    if (notificationDaemon)
-        moveToTray();
-    else
-        destroyTray();
+    destroyTray();
 }
-- 
2.26.2


From d0f2d28a7dcabe79a538edb946c566c15d7bd9aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 15 Feb 2019 03:12:00 +0100
Subject: [PATCH 2/6] Fix double-destroy error

A parent will destroy all its children when destroyed, so we don't
need to explicitly destroy the icon as well. In fact, gjs now treats
this as a fatal error.
---
 extensions/top-icons/extension.js | 1 -
 1 file changed, 1 deletion(-)

diff --git a/extensions/top-icons/extension.js b/extensions/top-icons/extension.js
index c4c5084..6456189 100644
--- a/extensions/top-icons/extension.js
+++ b/extensions/top-icons/extension.js
@@ -98,7 +98,6 @@ function onTrayIconAdded(o, icon, role) {
 function onTrayIconRemoved(o, icon) {
     let parent = icon.get_parent();
     parent.destroy();
-    icon.destroy();
     icons.splice(icons.indexOf(icon), 1);
 }
 
-- 
2.26.2


From fda29d0517b56dac3ddfa7a9749a52a40c1bbb6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Sat, 17 Nov 2018 00:57:53 +0100
Subject: [PATCH 3/6] Stop using a "click proxy"

It's a terrible work-around for an issue with status icon support
on wayland[0], which is the cause of crashes now that gjs is much
stricter about accessing already released objects.

Crashing is worse than the original problem (which will hopefully
soon be fixed anyway), so drop the work-around.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/191
---
 extensions/top-icons/extension.js | 38 +++----------------------------
 1 file changed, 3 insertions(+), 35 deletions(-)

diff --git a/extensions/top-icons/extension.js b/extensions/top-icons/extension.js
index 6456189..b617284 100644
--- a/extensions/top-icons/extension.js
+++ b/extensions/top-icons/extension.js
@@ -4,8 +4,6 @@ const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 const Main = imports.ui.main;
 const PanelMenu = imports.ui.panelMenu;
-const Meta = imports.gi.Meta;
-const Mainloop = imports.mainloop;
 const System = imports.system;
 
 let icons = [];
@@ -56,42 +54,12 @@ function onTrayIconAdded(o, icon, role) {
     icons.push(icon);
     Main.panel._rightBox.insert_child_at_index(box, 0);
 
-    let clickProxy = new St.Bin({ width: iconSize, height: iconSize });
-    clickProxy.reactive = true;
-    Main.uiGroup.add_actor(clickProxy);
-
-    icon._proxyAlloc = Main.panel._rightBox.connect('allocation-changed', function() {
-        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, function() {
-            let [x, y] = icon.get_transformed_position();
-            clickProxy.set_position(x, y);
-        });
-    });
-
-    icon.connect("destroy", function() {
-        Main.panel._rightBox.disconnect(icon._proxyAlloc);
-        clickProxy.destroy();
-    });
-
-    clickProxy.connect('button-release-event', function(actor, event) {
+    icon.connect('button-release-event', function(actor, event) {
         icon.click(event);
     });
 
-    icon._clickProxy = clickProxy;
-
-    /* Fixme: HACK */
-    Meta.later_add(Meta.LaterType.BEFORE_REDRAW, function() {
-        let [x, y] = icon.get_transformed_position();
-        clickProxy.set_position(x, y);
-        return false;
-    });
-    let timerId = 0;
-    let i = 0;
-    timerId = Mainloop.timeout_add(500, function() {
-        icon.set_size(icon.width == iconSize ? iconSize - 1 : iconSize,
-                      icon.width == iconSize ? iconSize - 1 : iconSize);
-        i++;
-        if (i == 2)
-            Mainloop.source_remove(timerId);
+    icon.connect('destroy', function() {
+        box.destroy();
     });
 }
 
-- 
2.26.2


From 20f4b27ace58d7b6c5df4936c5e5d11d13992fbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 15 Feb 2019 17:33:41 +0100
Subject: [PATCH 4/6] Slightly improve integration with top bar

It is lost in the mists of time why we are using a base class and
meddle around with its hierarchy, instead of using the preferred
API for top bar items.

While at it, also support activation by keynav.
---
 extensions/top-icons/extension.js | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/extensions/top-icons/extension.js b/extensions/top-icons/extension.js
index b617284..59e91d5 100644
--- a/extensions/top-icons/extension.js
+++ b/extensions/top-icons/extension.js
@@ -31,36 +31,34 @@ function enable() {
     createTray();
 }
 
-function onTrayIconAdded(o, icon, role) {
+function onTrayIconAdded(o, icon) {
     let wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : '';
     if (STANDARD_TRAY_ICON_IMPLEMENTATIONS.includes(wmClass))
         return;
 
-    let buttonBox = new PanelMenu.ButtonBox();
-    let box = buttonBox.actor;
-    let parent = box.get_parent();
+    let button = new PanelMenu.Button(0.5, null, true);
 
     let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
     let iconSize = PANEL_ICON_SIZE * scaleFactor;
 
     icon.set_size(iconSize, iconSize);
-    box.add_actor(icon);
-
-    icon.reactive = true;
-
-    if (parent)
-        parent.remove_actor(box);
+    button.actor.add_actor(icon);
 
     icons.push(icon);
-    Main.panel._rightBox.insert_child_at_index(box, 0);
 
-    icon.connect('button-release-event', function(actor, event) {
+    button.actor.connect('button-release-event', function(actor, event) {
+        icon.click(event);
+    });
+    button.actor.connect('key-press-event', function(actor, event) {
         icon.click(event);
     });
 
     icon.connect('destroy', function() {
-        box.destroy();
+        button.destroy();
     });
+
+    let role = wmClass || `${icon}`;
+    Main.panel.addToStatusArea(role, button);
 }
 
 function onTrayIconRemoved(o, icon) {
-- 
2.26.2


From 866cbb3a7d2226b93d1d682db682f8f8ef247ddf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 31 May 2019 18:57:42 +0200
Subject: [PATCH 5/6] Fix icon sizing issue

PanelMenu.Button is a custom actor that expands its child to the
available height and adds horizontal padding. So in order to not
distort the icon, don't add it directly but add an intermediate
container for alignment.

Also lower the icon size to the standard top bar 16px.
---
 extensions/top-icons/extension.js | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/extensions/top-icons/extension.js b/extensions/top-icons/extension.js
index 59e91d5..f0da96f 100644
--- a/extensions/top-icons/extension.js
+++ b/extensions/top-icons/extension.js
@@ -1,5 +1,6 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
+const Clutter = imports.gi.Clutter;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 const Main = imports.ui.main;
@@ -9,7 +10,7 @@ const System = imports.system;
 let icons = [];
 let sysTray = null;
 
-const PANEL_ICON_SIZE = 24;
+const PANEL_ICON_SIZE = 16;
 
 const STANDARD_TRAY_ICON_IMPLEMENTATIONS = [
     'bluetooth-applet',
@@ -42,7 +43,14 @@ function onTrayIconAdded(o, icon) {
     let iconSize = PANEL_ICON_SIZE * scaleFactor;
 
     icon.set_size(iconSize, iconSize);
-    button.actor.add_actor(icon);
+    icon.set_x_align(Clutter.ActorAlign.CENTER);
+    icon.set_y_align(Clutter.ActorAlign.CENTER);
+
+    let iconBin = new St.Widget({
+        layout_manager: new Clutter.BinLayout(),
+    });
+    iconBin.add_actor(icon);
+    button.actor.add_actor(iconBin);
 
     icons.push(icon);
 
-- 
2.26.2


From 4e2ac2ff096265db9916d323255f7d57ab742d6e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Wed, 27 May 2020 22:01:06 +0200
Subject: [PATCH 6/6] Set icons' accessible name

Status icons aren't great as far as accessibility is concerned (well,
they aren't great, full stop). But we can at least do slightly better
than stuffing an anonymous actor in the top bar by using the icon's
title for the accessible name.
---
 extensions/top-icons/extension.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/extensions/top-icons/extension.js b/extensions/top-icons/extension.js
index f0da96f..3611f59 100644
--- a/extensions/top-icons/extension.js
+++ b/extensions/top-icons/extension.js
@@ -1,6 +1,7 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 const Main = imports.ui.main;
@@ -45,6 +46,9 @@ function onTrayIconAdded(o, icon) {
     icon.set_size(iconSize, iconSize);
     icon.set_x_align(Clutter.ActorAlign.CENTER);
     icon.set_y_align(Clutter.ActorAlign.CENTER);
+    icon.bind_property('title',
+        button.actor, 'accessible-name',
+        GObject.BindingFlags.SYNC_CREATE);
 
     let iconBin = new St.Widget({
         layout_manager: new Clutter.BinLayout(),
-- 
2.26.2