forked from dorkbox/SystemTray
Works in UbuntuGnome
This commit is contained in:
parent
ad509db696
commit
83cea322f1
@ -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.
|
||||
* <p/>
|
||||
@ -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_;
|
||||
|
@ -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,27 +141,38 @@ 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;
|
||||
@ -151,8 +192,11 @@ function installHook() {
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user