/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ const Gdm = imports.gi.Gdm; const GLib = imports.gi.GLib; const Lang = imports.lang; const Shell = imports.gi.Shell; const St = imports.gi.St; const Gettext = imports.gettext.domain('gnome-shell'); const _ = Gettext.gettext; const GnomeSession = imports.misc.gnomeSession; const Main = imports.ui.main; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; // Adapted from gdm/gui/user-switch-applet/applet.c // // Copyright (C) 2004-2005 James M. Cape . // Copyright (C) 2008,2009 Red Hat, Inc. function StatusMenuButton() { this._init(); } StatusMenuButton.prototype = { __proto__: PanelMenu.Button.prototype, _init: function() { PanelMenu.Button.prototype._init.call(this, St.Align.START); let box = new St.BoxLayout({ name: 'panelStatusMenu' }); this.actor.set_child(box); this._gdm = Gdm.UserManager.ref_default(); this._gdm.queue_load() this._user = this._gdm.get_user(GLib.get_user_name()); this._presence = new GnomeSession.Presence(); this._presenceItems = {}; this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this._iconBox = new St.Bin(); box.add(this._iconBox, { y_align: St.Align.MIDDLE, y_fill: false }); let textureCache = St.TextureCache.get_default(); this._availableIcon = textureCache.load_icon_name('user-available', St.IconType.SYMBOLIC, 16); this._busyIcon = textureCache.load_icon_name('user-busy', St.IconType.SYMBOLIC, 16); this._invisibleIcon = textureCache.load_icon_name('user-invisible', St.IconType.SYMBOLIC, 16); this._idleIcon = textureCache.load_icon_name('user-idle', St.IconType.SYMBOLIC, 16); this._presence.connect('StatusChanged', Lang.bind(this, this._updatePresenceIcon)); this._presence.getStatus(Lang.bind(this, this._updatePresenceIcon)); this._name = new St.Label(); box.add(this._name, { y_align: St.Align.MIDDLE, y_fill: false }); this._userLoadedId = this._user.connect('notify::is-loaded', Lang.bind(this, this._updateUserName)); this._userChangedId = this._user.connect('changed', Lang.bind(this, this._updateUserName)); this._createSubMenu(); this._gdm.connect('notify::is-loaded', Lang.bind(this, this._updateSwitchUser)); this._gdm.connect('user-added', Lang.bind(this, this._updateSwitchUser)); this._gdm.connect('user-removed', Lang.bind(this, this._updateSwitchUser)); }, _onDestroy: function() { this._user.disconnect(this._userLoadedId); this._user.disconnect(this._userChangedId); }, _updateUserName: function() { if (this._user.is_loaded) this._name.set_text(this._user.get_real_name()); else this._name.set_text(""); }, _updateSwitchUser: function() { if (this._gdm.can_switch ()) this._loginScreenItem.actor.show(); else this._loginScreenItem.actor.hide(); }, _updatePresenceIcon: function(presence, status) { if (status == GnomeSession.PresenceStatus.AVAILABLE) this._iconBox.child = this._availableIcon; else if (status == GnomeSession.PresenceStatus.BUSY) this._iconBox.child = this._busyIcon; else if (status == GnomeSession.PresenceStatus.INVISIBLE) this._iconBox.child = this._invisibleIcon; else this._iconBox.child = this._idleIcon; for (let itemStatus in this._presenceItems) this._presenceItems[itemStatus].setShowDot(itemStatus == status); }, _createSubMenu: function() { let item; item = new PopupMenu.PopupImageMenuItem(_("Available"), 'user-available', true); item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.AVAILABLE)); this.menu.addMenuItem(item); this._presenceItems[GnomeSession.PresenceStatus.AVAILABLE] = item; item = new PopupMenu.PopupImageMenuItem(_("Busy"), 'user-busy', true); item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.BUSY)); this.menu.addMenuItem(item); this._presenceItems[GnomeSession.PresenceStatus.BUSY] = item; item = new PopupMenu.PopupImageMenuItem(_("Invisible"), 'user-invisible', true); item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.INVISIBLE)); this.menu.addMenuItem(item); this._presenceItems[GnomeSession.PresenceStatus.INVISIBLE] = item; item = new PopupMenu.PopupSeparatorMenuItem(); this.menu.addMenuItem(item); item = new PopupMenu.PopupMenuItem(_("My Account...")); item.connect('activate', Lang.bind(this, this._onMyAccountActivate)); this.menu.addMenuItem(item); item = new PopupMenu.PopupMenuItem(_("System Preferences...")); 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); 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); item = new PopupMenu.PopupSeparatorMenuItem(); this.menu.addMenuItem(item); item = new PopupMenu.PopupMenuItem(_("Suspend")); item.connect('activate', Lang.bind(this, this._onShutDownActivate)); this.menu.addMenuItem(item); item = new PopupMenu.PopupMenuItem(_("Restart...")); item.connect('activate', Lang.bind(this, this._onShutDownActivate)); this.menu.addMenuItem(item); item = new PopupMenu.PopupMenuItem(_("Shut Down...")); item.connect('activate', Lang.bind(this, this._onShutDownActivate)); this.menu.addMenuItem(item); }, _setPresenceStatus: function(item, event, status) { this._presence.setStatus(status); }, _onMyAccountActivate: function() { Main.overview.hide(); this._spawn(['gnome-about-me']); }, _onPreferencesActivate: function() { Main.overview.hide(); this._spawn(['gnome-control-center']); }, _onLockScreenActivate: function() { Main.overview.hide(); this._spawn(['gnome-screensaver-command', '--lock']); }, _onLoginScreenActivate: function() { Main.overview.hide(); this._gdm.goto_login_session(); this._onLockScreenActivate(); }, _onQuitSessionActivate: function() { Main.overview.hide(); this._spawn(['gnome-session-save', '--logout-dialog']); }, _onShutDownActivate: function() { Main.overview.hide(); this._spawn(['gnome-session-save', '--shutdown-dialog']); }, _spawn: function(args) { // FIXME: once Shell.Process gets support for signalling // errors we should pop up an error dialog or something here // on failure let p = new Shell.Process({'args' : args}); p.run(); } };