From 83cea322f1e93fffcd2135f4b3504e00e0ad00fe Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 21 Sep 2016 22:13:13 +0200 Subject: [PATCH] Works in UbuntuGnome --- .../systemTray/linux/GtkSystemTray.java | 10 +- src/dorkbox/systemTray/linux/extension.js | 179 ++++++++++++------ 2 files changed, 132 insertions(+), 57 deletions(-) diff --git a/src/dorkbox/systemTray/linux/GtkSystemTray.java b/src/dorkbox/systemTray/linux/GtkSystemTray.java index c8cad3eb..e2910ef1 100644 --- a/src/dorkbox/systemTray/linux/GtkSystemTray.java +++ b/src/dorkbox/systemTray/linux/GtkSystemTray.java @@ -15,17 +15,18 @@ */ package dorkbox.systemTray.linux; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + import com.sun.jna.NativeLong; import com.sun.jna.Pointer; + import dorkbox.systemTray.linux.jna.GEventCallback; import dorkbox.systemTray.linux.jna.GdkEventButton; import dorkbox.systemTray.linux.jna.Gobject; import dorkbox.systemTray.linux.jna.Gtk; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - /** * Class for handling all system tray interactions via GTK. *

@@ -53,6 +54,7 @@ class GtkSystemTray extends GtkTypeSystemTray { public void run() { final Pointer trayIcon_ = Gtk.gtk_status_icon_new(); + Gtk.gtk_status_icon_set_title(trayIcon_, "SystemTray"); // necessary for gnome placement Gtk.gtk_status_icon_set_name(trayIcon_, "SystemTray"); trayIcon = trayIcon_; diff --git a/src/dorkbox/systemTray/linux/extension.js b/src/dorkbox/systemTray/linux/extension.js index 5031727e..9c9c68d2 100644 --- a/src/dorkbox/systemTray/linux/extension.js +++ b/src/dorkbox/systemTray/linux/extension.js @@ -1,4 +1,3 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- /* * Copyright 2015 dorkbox, llc * @@ -21,6 +20,16 @@ * this is considered as released by the original sources as public domain. * * Vladimir's email address is unknown. + * + * Viewing the log messages can be performed by one of the following: + * gnome-shell --replace (you will see the log messages in the console) + * journalctl + * .cache/gdm/session.log + * .xsession-errors + * /var/log/messages + * alt-F2 -> lg -> extensions + * ~/.cache/upstart/gnome-session.log + * journalctl /usr/bin/gnome-shell -f -o cat */ const Clutter = imports.gi.Clutter; @@ -34,35 +43,56 @@ const PanelMenu = imports.ui.panelMenu; const Meta = imports.gi.Meta; const Mainloop = imports.mainloop; const NotificationDaemon = imports.ui.notificationDaemon; +const Config = imports.misc.config +const MessageTray = imports.ui.messageTray; -let APP_NAME = "SystemTray@Dorkbox"; +let APP_NAME = "SystemTray"; let trayAddedId = 0; let orig_onTrayIconAdded; let trayRemovedId = 0; let orig_onTrayIconRemoved; +let tray = null; let orig_getSource = null; let icons = []; -let notificationDaemon; +let DEBUG = true; // this value is hardcoded into the display manager -const PANEL_ICON_SIZE = 24; +let PANEL_ICON_SIZE = 24; + +// Workarounds... +let currentArray = Config.PACKAGE_VERSION.split('.'); +if (currentArray[0] == 3 && currentArray[1] < 5) { + // Gnome Shell 3.3 or 3.4 + PANEL_ICON_SIZE = MessageTray.Source.prototype.ICON_SIZE; +} else if (currentArray[0] == 3 && currentArray[1] < 7) { + // Gnome Shell 3.5 or 3.6 + PANEL_ICON_SIZE = MessageTray.NOTIFICATION_ICON_SIZE; +} else { + // Gnome Shell 3.7 and higher + PANEL_ICON_SIZE = MessageTray.Source.prototype.SOURCE_ICON_SIZE; +} + + function init() { if (Main.legacyTray) { - notificationDaemon = Main.legacyTray; - NotificationDaemon.STANDARD_TRAY_ICON_IMPLEMENTATIONS = imports.ui.legacyTray.STANDARD_TRAY_ICON_IMPLEMENTATIONS; + global.log("Legacy tray") + tray = Main.legacyTray; + tray.STANDARD_TRAY_ICON_IMPLEMENTATIONS = imports.ui.legacyTray.STANDARD_TRAY_ICON_IMPLEMENTATIONS; } else if (Main.notificationDaemon._fdoNotificationDaemon) { - notificationDaemon = Main.notificationDaemon._fdoNotificationDaemon; - orig_getSource = Lang.bind(notificationDaemon, NotificationDaemon.FdoNotificationDaemon.prototype._getSource); + global.log("FDO Notification tray") + tray = Main.notificationDaemon._fdoNotificationDaemon; + orig_getSource = Lang.bind(tray, NotificationDaemon.FdoNotificationDaemon.prototype._getSource); } else { - notificationDaemon = Main.notificationDaemon; - orig_getSource = Lang.bind(notificationDaemon, NotificationDaemon.NotificationDaemon.prototype._getSource); + global.log("Notification tray") + tray = Main.notificationDaemon; + orig_getSource = Lang.bind(tray, NotificationDaemon.NotificationDaemon.prototype._getSource); } } @@ -72,19 +102,19 @@ function enable() { function disable() { if (trayAddedId != 0) { - notificationDaemon._trayManager.disconnect(trayAddedId); + tray._trayManager.disconnect(trayAddedId); trayAddedId = 0; } if (trayRemovedId != 0) { - notificationDaemon._trayManager.disconnect(trayRemovedId); + tray._trayManager.disconnect(trayRemovedId); trayRemovedId = 0; } - notificationDaemon._trayIconAddedId = notificationDaemon._trayManager.connect('tray-icon-added', orig_onTrayIconAdded); - notificationDaemon._trayIconRemovedId = notificationDaemon._trayManager.connect('tray-icon-removed', orig_onTrayIconRemoved); + tray._trayIconAddedId = tray._trayManager.connect('tray-icon-added', orig_onTrayIconAdded); + tray._trayIconRemovedId = tray._trayManager.connect('tray-icon-removed', orig_onTrayIconRemoved); - notificationDaemon._getSource = orig_getSource; + tray._getSource = orig_getSource; for (let i = 0; i < icons.length; i++) { let icon = icons[i]; @@ -102,7 +132,7 @@ function disable() { parent.remove_actor(icon); parent.destroy(); - notificationDaemon._onTrayIconAdded(notificationDaemon, icon); + tray._onTrayIconAdded(tray, icon); } icons = []; @@ -111,48 +141,62 @@ function disable() { function installHook() { - //global.log("Installing hook") + if (DEBUG) { + global.log("Installing hook") + } // disable the "normal" method of adding icons - notificationDaemon._trayManager.disconnect(notificationDaemon._trayIconAddedId); - notificationDaemon._trayManager.disconnect(notificationDaemon._trayIconRemovedId); + if (tray._trayIconAddedId) { + tray._trayManager.disconnect(tray._trayIconAddedId); + } + + if (tray._trayIconRemovedId) { + tray._trayManager.disconnect(tray._trayIconRemovedId); + } + // save the original method - orig_onTrayIconAdded = Lang.bind(notificationDaemon, notificationDaemon._onTrayIconAdded); - orig_onTrayIconRemoved = Lang.bind(notificationDaemon, notificationDaemon._onTrayIconRemoved) + orig_onTrayIconAdded = Lang.bind(tray, tray._onTrayIconAdded); + orig_onTrayIconRemoved = Lang.bind(tray, tray._onTrayIconRemoved) // add our hook. If our icon doesn't have our specific title, it calls the original method - trayAddedId = notificationDaemon._trayManager.connect('tray-icon-added', onTrayIconAdded); - trayRemovedId = notificationDaemon._trayManager.connect('tray-icon-removed', onTrayIconRemoved); + trayAddedId = tray._trayManager.connect('tray-icon-added', onTrayIconAdded); + trayRemovedId = tray._trayManager.connect('tray-icon-removed', onTrayIconRemoved); - notificationDaemon._getSource = getSourceHook; + tray._getSource = getSourceHook; // move icons to top let toDestroy = []; - if (notificationDaemon._sources) { - for (let i = 0; i < notificationDaemon._sources.length; i++) { - let source = notificationDaemon._sources[i]; + if (tray._sources) { + if (DEBUG) { + global.log("Adding to sources") + } + for (let i = 0; i < tray._sources.length; i++) { + let source = tray._sources[i]; - if (!source.trayIcon) { - continue; - } + if (!source.trayIcon) { + continue; + } - let icon = source.trayIcon; + let icon = source.trayIcon; - if (icon.title !== APP_NAME) { - continue; - } + if (icon.title !== APP_NAME) { + continue; + } - let parent = icon.get_parent(); - parent.remove_actor(icon); + let parent = icon.get_parent(); + parent.remove_actor(icon); - onTrayIconAdded(this, icon); - toDestroy.push(source); - } + onTrayIconAdded(this, icon); + toDestroy.push(source); + } } else { - for (let i = 0; i < notificationDaemon._iconBox.get_n_children(); i++) { - let button = notificationDaemon._iconBox.get_child_at_index(i); + if (DEBUG) { + global.log("Adding to children") + } + for (let i = 0; i < tray._iconBox.get_n_children(); i++) { + let button = tray._iconBox.get_child_at_index(0); let icon = button.child; if (icon.title !== APP_NAME) { @@ -163,6 +207,7 @@ function installHook() { onTrayIconAdded(this, icon); toDestroy.push(button); + break; } } @@ -173,7 +218,9 @@ function installHook() { function getSourceHook (title, pid, ndata, sender, trayIcon) { if (trayIcon && title === APP_NAME) { - //global.log("create source"); + if (DEBUG) { + global.log("create source"); + } onTrayIconAdded(this, trayIcon); return null; } @@ -183,41 +230,57 @@ function getSourceHook (title, pid, ndata, sender, trayIcon) { // this is the hook that lets us only add ourselves. function onTrayIconAdded(o, icon) { - //global.log("adding tray icon 1 " + icon.title); + if (DEBUG) { + global.log("adding tray icon 1 " + icon.title); + } let wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : ''; - if (NotificationDaemon.STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass] !== undefined) { + if (tray.STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass] !== undefined) { + if (DEBUG) { + global.log("Cannot add tray icon, invalid implementation"); + } return; } if (icon.title !== APP_NAME) { + if (DEBUG) { + global.log("Cannot add tray icon, wrong name: " + icon.title + " Expecting: " + APP_NAME); + } orig_onTrayIconAdded(o, icon); return; } - //global.log("adding tray icon 2 " + icon.title); + if (DEBUG) { + global.log("adding tray icon 2 " + icon.title); + } - let buttonBox = new PanelMenu.ButtonBox(); - let box = buttonBox.actor; - let parent = box.get_parent(); + // An empty ButtonBox will still display padding, so create it without visibility. + let buttonBox = new PanelMenu.ButtonBox({visible: false}); + let boxActor = buttonBox.actor; + let parent = boxActor.get_parent(); + + // size let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let iconSize = PANEL_ICON_SIZE * scaleFactor; - + // icon.get_parent().set_size(iconSize, iconSize); icon.set_size(iconSize, iconSize); - box.add_actor(icon); + boxActor.add_actor(icon); + // Reactive actors will receive events. icon.set_reactive(true); + icon.reactive = true; if (parent) { // remove from the (if present) "collapsy tab icon thing" - parent.remove_actor(box); + parent.remove_actor(boxActor); } // setup proxy for handling click notifications, make it a little larger than the icon let clickProxy = new St.Bin({ width: iconSize + 4, height: iconSize + 4}); clickProxy.set_reactive(true); + clickProxy.reactive = true; icon._proxyAlloc = Main.panel._rightBox.connect('allocation-changed', function() { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, function() { @@ -229,6 +292,7 @@ function onTrayIconAdded(o, icon) { icon.connect("destroy", function() { Main.panel._rightBox.disconnect(icon._proxyAlloc); + icon.clear_effects(); clickProxy.destroy(); }); @@ -242,13 +306,22 @@ function onTrayIconAdded(o, icon) { Main.uiGroup.add_actor(clickProxy); // add the box to the right panel, always at position 0 - Main.panel._rightBox.insert_child_at_index(box, 0); + Main.panel._rightBox.insert_child_at_index(boxActor, 0); + + GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, Lang.bind(this, function() + { + clickProxy.visible = true; + boxActor.visible = true; + return GLib.SOURCE_REMOVE; + })); icons.push(icon); } function onTrayIconRemoved(o, icon) { - //global.log("removing tray icon " + icon.title); + if (DEBUG) { + global.log("removing tray icon " + icon.title); + } if (icon.title !== APP_NAME) { orig_onTrayIconRemoved(o, icon);