diff --git a/extensions/alternative-status-menu/extension.js b/extensions/alternative-status-menu/extension.js index c0b36469..96751961 100644 --- a/extensions/alternative-status-menu/extension.js +++ b/extensions/alternative-status-menu/extension.js @@ -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(); }