alternative-status-menu: make it coexist with other extensions
Instead of destroying the whole menu and recreating it, find the right position and just destroy/recreate the items we care about. Based on a patch by Andrea Santilli <andreasantilli@gmx.com>
This commit is contained in:
@@ -1,15 +1,17 @@
|
||||
/* -*- mode: js2 - indent-tabs-mode: nil - js2-basic-offset: 4 -*- */
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const GnomeSession = imports.misc.gnomeSession;
|
||||
const UserMenu = imports.ui.userMenu;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
let suspend_item = null;
|
||||
let hibernate_item = null;
|
||||
let poweroff_item = null;
|
||||
let suspend_signal_id = 0, hibernate_signal_id = 0;
|
||||
|
||||
function updateSuspend(object, pspec, item) {
|
||||
item.actor.visible = object.get_can_suspend();
|
||||
}
|
||||
@@ -35,69 +37,7 @@ function onHibernateActivate(item) {
|
||||
}
|
||||
|
||||
function createSubMenu() {
|
||||
let item;
|
||||
|
||||
item = new UserMenu.IMStatusChooserItem();
|
||||
item.connect('activate', Lang.bind(this, this._onMyAccountActivate));
|
||||
this.menu.addMenuItem(item);
|
||||
|
||||
item = new PopupMenu.PopupSwitchMenuItem(_("Notifications"));
|
||||
item.connect('activate', Lang.bind(this, this._updatePresenceStatus));
|
||||
this.menu.addMenuItem(item);
|
||||
this._notificationsSwitch = item;
|
||||
|
||||
item = new PopupMenu.PopupSeparatorMenuItem();
|
||||
this.menu.addMenuItem(item);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Online Accounts"));
|
||||
item.connect('activate', Lang.bind(this, this._onOnlineAccountsActivate));
|
||||
this.menu.addMenuItem(item);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("System Settings"));
|
||||
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
|
||||
this.menu.addMenuItem(item);
|
||||
|
||||
item = new PopupMenu.PopupSeparatorMenuItem();
|
||||
this.menu.addMenuItem(item);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Lock Screen"));
|
||||
item.connect('activate', Lang.bind(this, this._onLockScreenActivate));
|
||||
this.menu.addMenuItem(item);
|
||||
this._lockScreenItem = item;
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Switch User"));
|
||||
item.connect('activate', Lang.bind(this, this._onLoginScreenActivate));
|
||||
this.menu.addMenuItem(item);
|
||||
this._loginScreenItem = item;
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Log Out..."));
|
||||
item.connect('activate', Lang.bind(this, this._onQuitSessionActivate));
|
||||
this.menu.addMenuItem(item);
|
||||
this._logoutItem = item;
|
||||
|
||||
item = new PopupMenu.PopupSeparatorMenuItem();
|
||||
this.menu.addMenuItem(item);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Suspend"));
|
||||
item.connect('activate', Lang.bind(this, onSuspendActivate));
|
||||
this._upClient.connect('notify::can-suspend', Lang.bind(this, updateSuspend, item));
|
||||
updateSuspend(this._upClient, null, item);
|
||||
this.menu.addMenuItem(item);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Hibernate"));
|
||||
item.connect('activate', Lang.bind(this, onHibernateActivate));
|
||||
this._upClient.connect('notify::can-hibernate', Lang.bind(this, updateHibernate, item));
|
||||
updateHibernate(this._upClient, null, item);
|
||||
this.menu.addMenuItem(item);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Power Off..."));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
this._session.ShutdownRemote();
|
||||
}));
|
||||
this.menu.addMenuItem(item);
|
||||
|
||||
// clear out this to avoid criticals
|
||||
this._suspendOrPowerOffItem = null;
|
||||
}
|
||||
|
||||
// Put your extension initialization code here
|
||||
@@ -106,25 +46,81 @@ function init(metadata) {
|
||||
me.convenience.initTranslations(metadata);
|
||||
}
|
||||
|
||||
function reset(statusMenu) {
|
||||
statusMenu._updateSwitchUser();
|
||||
statusMenu._updateLogout();
|
||||
statusMenu._updateLockScreen();
|
||||
|
||||
statusMenu._updateSwitch(statusMenu._presence.status);
|
||||
function resetMenu() {
|
||||
}
|
||||
|
||||
function enable() {
|
||||
let statusMenu = Main.panel._statusArea.userMenu;
|
||||
statusMenu.menu.removeAll();
|
||||
createSubMenu.call(statusMenu);
|
||||
reset(statusMenu);
|
||||
|
||||
let children = statusMenu.menu._getMenuItems();
|
||||
let index = children.length;
|
||||
|
||||
/* find and destroy the old entry */
|
||||
for (let i = children.length - 1; i >= 0; i--) {
|
||||
if (children[i] == statusMenu._suspendOrPowerOffItem) {
|
||||
children[i].destroy();
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add the new entries */
|
||||
suspend_item = new PopupMenu.PopupMenuItem(_("Suspend"));
|
||||
suspend_item.connect('activate', Lang.bind(statusMenu, onSuspendActivate));
|
||||
suspend_signal_id = statusMenu._upClient.connect('notify::can-suspend', Lang.bind(statusMenu, updateSuspend, suspend_item));
|
||||
updateSuspend(statusMenu._upClient, null, suspend_item);
|
||||
|
||||
hibernate_item = new PopupMenu.PopupMenuItem(_("Hibernate"));
|
||||
hibernate_item.connect('activate', Lang.bind(statusMenu, onHibernateActivate));
|
||||
hibernate_signal_id = statusMenu._upClient.connect('notify::can-hibernate', Lang.bind(statusMenu, updateHibernate, hibernate_item));
|
||||
updateHibernate(statusMenu._upClient, null, hibernate_item);
|
||||
|
||||
poweroff_item = new PopupMenu.PopupMenuItem(_("Power Off..."), { style_class: 'popup-alternating-menu-item' });
|
||||
poweroff_item.actor.add_style_pseudo_class('alternate');
|
||||
poweroff_item.connect('activate', Lang.bind(statusMenu, function() {
|
||||
this._session.ShutdownRemote();
|
||||
}));
|
||||
|
||||
/* insert the entries at the found position */
|
||||
statusMenu.menu.addMenuItem(suspend_item, index);
|
||||
statusMenu.menu.addMenuItem(hibernate_item, index + 1);
|
||||
statusMenu.menu.addMenuItem(poweroff_item, index + 2);
|
||||
|
||||
// clear out this to avoid criticals (we don't mess with
|
||||
// updateSuspendOrPowerOff)
|
||||
statusMenu._suspendOrPowerOffItem = null;
|
||||
}
|
||||
|
||||
function disable() {
|
||||
// not guarranteed to work, if more extensions operate in the same place
|
||||
let statusMenu = Main.panel._statusArea.userMenu;
|
||||
statusMenu.menu.removeAll();
|
||||
statusMenu._createSubMenu();
|
||||
reset(statusMenu);
|
||||
|
||||
let children = statusMenu.menu._getMenuItems();
|
||||
let index = children.length;
|
||||
|
||||
/* find the index for the previously created suspend entry */
|
||||
for (let i = children.length - 1; i >= 0; i--) {
|
||||
if (children[i] == suspend_item) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* disconnect signals */
|
||||
statusMenu._upClient.disconnect(suspend_signal_id);
|
||||
statusMenu._upClient.disconnect(hibernate_signal_id);
|
||||
suspend_signal_id = hibernate_signal_id = 0;
|
||||
|
||||
/* destroy the entries we had created */
|
||||
suspend_item.destroy();
|
||||
hibernate_item.destroy();
|
||||
poweroff_item.destroy();
|
||||
|
||||
/* create a new suspend/poweroff entry */
|
||||
/* empty strings are fine for the labels, since we immediately call updateSuspendOrPowerOff */
|
||||
let item = new PopupMenu.PopupAlternatingMenuItem("", "");
|
||||
/* restore the userMenu field */
|
||||
statusMenu._suspendOrPowerOffItem = item;
|
||||
statusMenu.menu.addMenuItem(item, index);
|
||||
item.connect('activate', Lang.bind(statusMenu, statusMenu._onSuspendOrPowerOffActivate));
|
||||
statusMenu._updateSuspendOrPowerOff();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user