From 2e65c852c3717e2b9b166dc276fda2c3ae401f99 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Thu, 22 Aug 2013 14:35:28 -0400 Subject: [PATCH] endSessionDialog: List other users and sessions in with the inhibitors Instead of in a separate dialog. This does not meet the designs right now, but it's a good first start. https://bugzilla.gnome.org/show_bug.cgi?id=706612 --- js/ui/endSessionDialog.js | 130 ++++++++++++++++++++++++++++---------- js/ui/status/system.js | 121 +---------------------------------- 2 files changed, 98 insertions(+), 153 deletions(-) diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js index 28c5a67e6..7ab3ff212 100644 --- a/js/ui/endSessionDialog.js +++ b/js/ui/endSessionDialog.js @@ -31,7 +31,7 @@ const St = imports.gi.St; const Shell = imports.gi.Shell; const GnomeSession = imports.misc.gnomeSession; -const Main = imports.ui.main; +const LoginManager = imports.misc.loginManager; const ModalDialog = imports.ui.modalDialog; const Tweener = imports.ui.tweener; const UserWidget = imports.ui.userWidget; @@ -116,6 +116,18 @@ const DialogContent = { 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */: restartDialogContent }; +const MAX_USERS_IN_SESSION_DIALOG = 5; + +const LogindSessionIface = + + + + + +; + +const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface); + function findAppFromInhibitor(inhibitor) { let desktopFile; try { @@ -136,43 +148,33 @@ function findAppFromInhibitor(inhibitor) { const ListItem = new Lang.Class({ Name: 'ListItem', - _init: function(app, reason) { - this._app = app; - this._reason = reason; - - if (this._reason == null) - this._reason = ''; - - let layout = new St.BoxLayout({ vertical: false}); + _init: function(icon, name, description) { + let layout = new St.BoxLayout({ vertical: false }); this.actor = new St.Bin({ style_class: 'end-session-dialog-app-list-item', - can_focus: true, - child: layout, - x_align: St.Align.START, - x_fill: true }); - - this._icon = this._app.create_icon_texture(_ITEM_ICON_SIZE); + can_focus: true, + child: layout, + x_align: St.Align.START, + x_fill: true }); let iconBin = new St.Bin({ style_class: 'end-session-dialog-app-list-item-icon', - child: this._icon }); + child: icon }); layout.add(iconBin); let textLayout = new St.BoxLayout({ style_class: 'end-session-dialog-app-list-item-text-box', - vertical: true }); + vertical: true }); layout.add(textLayout); - this._nameLabel = new St.Label({ text: this._app.get_name(), - style_class: 'end-session-dialog-app-list-item-name' }); - textLayout.add(this._nameLabel, - { expand: false, - x_fill: true }); + let nameLabel = new St.Label({ text: name, + style_class: 'end-session-dialog-app-list-item-name' }); + textLayout.add(nameLabel, { expand: false, x_fill: true }); + this.actor.label_actor = nameLabel; - this._descriptionLabel = new St.Label({ text: this._reason, - style_class: 'end-session-dialog-app-list-item-description' }); - this.actor.label_actor = this._nameLabel; - textLayout.add(this._descriptionLabel, - { expand: true, - x_fill: true }); + if (description) { + let descriptionLabel = new St.Label({ text: description, + style_class: 'end-session-dialog-app-list-item-description' }); + textLayout.add(descriptionLabel, { expand: true, x_fill: true }); + } }, }); @@ -226,11 +228,14 @@ const EndSessionDialog = new Lang.Class({ this.parent({ styleClass: 'end-session-dialog', destroyOnClose: false }); - this._user = AccountsService.UserManager.get_default().get_user(GLib.get_user_name()); + this._loginManager = LoginManager.getLoginManager(); + this._userManager = AccountsService.UserManager.get_default(); + this._user = this._userManager.get_user(GLib.get_user_name()); this._secondsLeft = 0; this._totalSecondsToStayOpen = 0; this._inhibitors = []; + this._sessions = []; this.connect('destroy', Lang.bind(this, this._onDestroy)); @@ -305,6 +310,10 @@ const EndSessionDialog = new Lang.Class({ this._user.disconnect(this._userChangedId); }, + _hasInhibitors: function() { + return (this._inhibitors.length > 0) || (this._sessions.length > 0); + }, + _updateDescription: function() { if (this.state != ModalDialog.State.OPENING && this.state != ModalDialog.State.OPENED) @@ -315,10 +324,10 @@ const EndSessionDialog = new Lang.Class({ let subject = dialogContent.subject; let description; - if (this._inhibitors.length > 0) { + if (this._hasInhibitors()) { this._stopTimer(); description = dialogContent.inhibitedDescription; - } else if (this._secondsLeft > 0 && this._inhibitors.length == 0) { + } else if (this._secondsLeft > 0) { let displayTime = _roundSecondsToInterval(this._totalSecondsToStayOpen, this._secondsLeft, 10); @@ -411,7 +420,7 @@ const EndSessionDialog = new Lang.Class({ }, _onOpened: function() { - if (this._inhibitors.length == 0) + if (!this._hasInhibitors()) this._startTimer(); }, @@ -458,7 +467,7 @@ const EndSessionDialog = new Lang.Class({ if (app) { let [reason] = inhibitor.GetReasonSync(); - let item = new ListItem(app, reason); + let item = new ListItem(app.create_icon_texture(_ITEM_ICON_SIZE), app.get_name(), reason); this._applicationList.add(item.actor, { x_fill: true }); this._stopTimer(); } else { @@ -469,6 +478,59 @@ const EndSessionDialog = new Lang.Class({ this._updateContent(); }, + _loadSessions: function() { + this._loginManager.listSessions(Lang.bind(this, function(result) { + let n = 0; + for (let i = 0; i < result.length; i++) { + let[id, uid, userName, seat, sessionPath] = result[i]; + let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath); + + if (proxy.Class != 'user') + continue; + + if (proxy.State == 'closing') + continue; + + if (proxy.Id == GLib.getenv('XDG_SESSION_ID')) + continue; + + let session = { user: this._userManager.get_user(userName), + username: userName, + type: proxy.Type, + remote: proxy.Remote }; + this._sessions.push(session); + + let avatar = new UserWidget.Avatar(session.user, { iconSize: _ITEM_ICON_SIZE }); + avatar.update(); + + let userLabel = session.user.get_real_name() ? session.user.get_real_name() : userName; + let userLabelText; + + if (session.remote) + /* Translators: Remote here refers to a remote session, like a ssh login */ + userLabelText = _("%s (remote)").format(userName); + else if (session.type == "tty") + /* Translators: Console here refers to a tty like a VT console */ + userLabelText = _("%s (console)").format(userName); + else + userLabelText = userName; + + let item = new ListItem(avatar.actor, userLabelText); + + // XXX -- put them in their own inhibitor section + this._applicationList.add(item.actor, { x_fill: true }); + + // limit the number of entries + n++; + if (n == MAX_USERS_IN_SESSION_DIALOG) + break; + } + + if (n > 0) + this._stopTimer(); + })); + }, + OpenAsync: function(parameters, invocation) { let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters; this._totalSecondsToStayOpen = totalSecondsToStayOpen; @@ -490,6 +552,8 @@ const EndSessionDialog = new Lang.Class({ this._inhibitors.push(inhibitor); } + this._loadSessions(); + this._updateButtons(); if (!this.open(timestamp)) { diff --git a/js/ui/status/system.js b/js/ui/status/system.js index a75303ba1..1bae58ef1 100644 --- a/js/ui/status/system.js +++ b/js/ui/status/system.js @@ -4,21 +4,16 @@ const AccountsService = imports.gi.AccountsService; const Gdm = imports.gi.Gdm; const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; -const Gtk = imports.gi.Gtk; const Lang = imports.lang; const Shell = imports.gi.Shell; const St = imports.gi.St; -const Clutter = imports.gi.Clutter; const BoxPointer = imports.ui.boxpointer; const GnomeSession = imports.misc.gnomeSession; const LoginManager = imports.misc.loginManager; const Main = imports.ui.main; -const ModalDialog = imports.ui.modalDialog; const PanelMenu = imports.ui.panelMenu; const PopupMenu = imports.ui.popupMenu; -const Util = imports.misc.util; -const UserWidget = imports.ui.userWidget; const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown'; const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver'; @@ -28,18 +23,6 @@ const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen'; const DISABLE_LOG_OUT_KEY = 'disable-log-out'; const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out'; -const MAX_USERS_IN_SESSION_DIALOG = 5; - -const SystemdLoginSessionIface = - - - - - -; - -const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface); - const Indicator = new Lang.Class({ Name: 'SystemIndicator', Extends: PanelMenu.SystemIndicator, @@ -55,7 +38,6 @@ const Indicator = new Lang.Class({ this._session = new GnomeSession.SessionManager(); this._haveShutdown = true; - this._loginManager = LoginManager.getLoginManager(); this._userManager = AccountsService.UserManager.get_default(); this._user = this._userManager.get_user(GLib.get_user_name()); @@ -317,110 +299,9 @@ const Indicator = new Lang.Class({ this._session.LogoutRemote(0); }, - _openSessionWarnDialog: function(sessions) { - let dialog = new ModalDialog.ModalDialog(); - let subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject', - text: _("Other users are logged in.") }); - dialog.contentLayout.add(subjectLabel, { y_fill: true, - y_align: St.Align.START }); - - let descriptionLabel = new St.Label({ style_class: 'end-session-dialog-description'}); - descriptionLabel.set_text(_("Shutting down might cause them to lose unsaved work.")); - descriptionLabel.clutter_text.line_wrap = true; - dialog.contentLayout.add(descriptionLabel, { x_fill: true, - y_fill: true, - y_align: St.Align.START }); - - let scrollView = new St.ScrollView({ style_class: 'end-session-dialog-app-list' }); - scrollView.add_style_class_name('vfade'); - scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); - dialog.contentLayout.add(scrollView, { x_fill: true, y_fill: true }); - - let userList = new St.BoxLayout({ vertical: true }); - scrollView.add_actor(userList); - - for (let i = 0; i < sessions.length; i++) { - let session = sessions[i]; - let userEntry = new St.BoxLayout({ style_class: 'login-dialog-user-list-item', - vertical: false }); - let avatar = new UserWidget.Avatar(session.user); - avatar.update(); - userEntry.add(avatar.actor); - - let userLabelText = "";; - let userName = session.user.get_real_name() ? - session.user.get_real_name() : session.username; - - if (session.info.remote) - /* Translators: Remote here refers to a remote session, like a ssh login */ - userLabelText = _("%s (remote)").format(userName); - else if (session.info.type == "tty") - /* Translators: Console here refers to a tty like a VT console */ - userLabelText = _("%s (console)").format(userName); - else - userLabelText = userName; - - let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box', - vertical: true }); - textLayout.add(new St.Label({ text: userLabelText }), - { y_fill: false, - y_align: St.Align.MIDDLE, - expand: true }); - userEntry.add(textLayout, { expand: true }); - userList.add(userEntry, { x_fill: true }); - } - - let cancelButton = { label: _("Cancel"), - action: function() { dialog.close(); }, - key: Clutter.Escape }; - - let powerOffButton = { label: _("Power Off"), action: Lang.bind(this, function() { - dialog.close(); - this._session.ShutdownRemote(); - }), default: true }; - - dialog.setButtons([cancelButton, powerOffButton]); - - dialog.open(); - }, - _onPowerOffClicked: function() { this.menu.itemActivated(); Main.overview.hide(); - this._loginManager.listSessions(Lang.bind(this, function(result) { - let sessions = []; - let n = 0; - for (let i = 0; i < result.length; i++) { - let[id, uid, userName, seat, sessionPath] = result[i]; - let proxy = new SystemdLoginSession(Gio.DBus.system, - 'org.freedesktop.login1', - sessionPath); - - if (proxy.Class != 'user') - continue; - - if (proxy.State == 'closing') - continue; - - if (proxy.Id == GLib.getenv('XDG_SESSION_ID')) - continue; - - sessions.push({ user: this._userManager.get_user(userName), - username: userName, - info: { type: proxy.Type, - remote: proxy.Remote } - }); - - // limit the number of entries - n++; - if (n == MAX_USERS_IN_SESSION_DIALOG) - break; - } - - if (n != 0) - this._openSessionWarnDialog(sessions); - else - this._session.ShutdownRemote(); - })); + this._session.ShutdownRemote(0); } });