loginDialog: Move the session list to a PopupMenu

There are some issues with the existing session menu. First, it looks
kinda bad. It seems like it's hanging around there, but it doesn't really know
what to do with itself.

Second, when it expands down it requires that the buttons below move
down with it. This kind of movement is awkward and looks a bit weird.

Third, its current position makes the "dialog" tall and unwieldy when
you add things like messages for fingerprint readers or authentication errors.

This commit moves the session list to a menu behind a button to address
the above problems.

Based on a patch by Jasper St. Pierre.

https://bugzilla.gnome.org/show_bug.cgi?id=702818
This commit is contained in:
Ray Strode 2013-06-23 23:14:10 -04:00
parent 10b1c7e8a3
commit 8d7649eaec
2 changed files with 81 additions and 192 deletions

View File

@ -2350,43 +2350,17 @@ StScrollBar StButton#vhandle:active {
width: 15em; width: 15em;
} }
.login-dialog-session-list, .login-dialog-session-list-button StIcon {
.login-dialog-session-list-item { icon-size: 1.25em;
color: #babdb6;
}
.login-dialog-session-list-button:focus,
.login-dialog-session-list-button:active,
.login-dialog-session-list-button:hover,
.login-dialog-session-list-item:focus,
.login-dialog-session-list-item:hover {
color: white;
} }
.login-dialog-session-list-button { .login-dialog-session-list-button {
padding: 4px; color: #8b8b8b;
} }
.login-dialog-session-list-scroll-view { .login-dialog-session-list-button:hover,
padding: 6px; .login-dialog-session-list-button:active {
} color: white;
.login-dialog-session-list-item {
padding-bottom: 6px;
}
.login-dialog-session-list-triangle {
padding-right: 6px;
}
.login-dialog-session-list-item-box {
padding-left: 6px;
spacing: 6px;
}
.login-dialog-session-list-item-dot {
width: 10px;
height: 10px;
} }
.login-dialog-logo-bin { .login-dialog-logo-bin {

View File

@ -34,10 +34,12 @@ const St = imports.gi.St;
const Animation = imports.ui.animation; const Animation = imports.ui.animation;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const BoxPointer = imports.ui.boxpointer;
const CtrlAltTab = imports.ui.ctrlAltTab; const CtrlAltTab = imports.ui.ctrlAltTab;
const GdmUtil = imports.gdm.util; const GdmUtil = imports.gdm.util;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const Realmd = imports.gdm.realmd; const Realmd = imports.gdm.realmd;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget; const UserWidget = imports.ui.userWidget;
@ -288,188 +290,106 @@ const UserList = new Lang.Class({
}); });
Signals.addSignalMethods(UserList.prototype); Signals.addSignalMethods(UserList.prototype);
const SessionListItem = new Lang.Class({ const SessionMenuButton = new Lang.Class({
Name: 'SessionListItem', Name: 'SessionMenuButton',
_init: function(id, name) {
this.id = id;
this.actor = new St.Button({ style_class: 'login-dialog-session-list-item',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
reactive: true,
x_fill: true,
x_align: St.Align.START });
this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list-item-box' });
this.actor.add_actor(this._box);
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this._dot = new St.DrawingArea({ style_class: 'login-dialog-session-list-item-dot' });
this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot));
this._box.add_actor(this._dot);
this.setShowDot(false);
let label = new St.Label({ style_class: 'login-dialog-session-list-item-label',
text: name });
this.actor.label_actor = label;
this._box.add_actor(label);
},
setShowDot: function(show) {
if (show)
this._dot.opacity = 255;
else
this._dot.opacity = 0;
},
_onRepaintDot: function(area) {
let cr = area.get_context();
let [width, height] = area.get_surface_size();
let color = area.get_theme_node().get_foreground_color();
cr.setSourceRGBA (color.red / 255,
color.green / 255,
color.blue / 255,
color.alpha / 255);
cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
cr.fill();
cr.$dispose();
},
_onClicked: function() {
this.emit('activate');
}
});
Signals.addSignalMethods(SessionListItem.prototype);
const SessionList = new Lang.Class({
Name: 'SessionList',
_init: function() { _init: function() {
this.actor = new St.Bin(); let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' });
this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list',
vertical: true});
this.actor.child = this._box;
this._button = new St.Button({ style_class: 'login-dialog-session-list-button', this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, reactive: true,
track_hover: true,
can_focus: true, can_focus: true,
x_fill: true, accessible_name: _("Choose Session"),
y_fill: true }); accessible_role: Atk.Role.MENU,
let box = new St.BoxLayout(); child: gearIcon });
this._button.add_actor(box);
this._triangle = new St.Label({ style_class: 'login-dialog-session-list-triangle', this.actor = new St.Bin({ child: this._button });
text: '\u25B8' });
box.add_actor(this._triangle);
let label = new St.Label({ style_class: 'login-dialog-session-list-label', this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP);
text: _("Session…") }); Main.uiGroup.add_actor(this._menu.actor);
box.add_actor(label); this._menu.actor.hide();
this._button.connect('clicked', this._menu.connect('open-state-changed',
Lang.bind(this, this._onClicked)); Lang.bind(this, function(menu, isOpen) {
this._box.add_actor(this._button); if (isOpen)
this._scrollView = new St.ScrollView({ style_class: 'login-dialog-session-list-scroll-view'}); this._button.add_style_pseudo_class('active');
this._scrollView.set_policy(Gtk.PolicyType.NEVER, else
Gtk.PolicyType.AUTOMATIC); this._button.remove_style_pseudo_class('active');
this._box.add_actor(this._scrollView); }));
this._itemList = new St.BoxLayout({ style_class: 'login-dialog-session-item-list',
vertical: true }); let subtitle = new PopupMenu.PopupMenuItem(_("Session"), { style_class: 'popup-subtitle-menu-item',
this._scrollView.add_actor(this._itemList); reactive: false });
this._scrollView.hide(); this._menu.addMenuItem(subtitle);
this.isOpen = false;
this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
this._manager.addMenu(this._menu);
this._button.connect('clicked', Lang.bind(this, function() {
this._menu.toggle();
}));
this._items = {};
this._activeSessionId = null;
this._populate(); this._populate();
}, },
open: function() {
if (this.isOpen)
return;
this._button.add_style_pseudo_class('open');
this._scrollView.show();
this._triangle.set_text('\u25BE');
this.isOpen = true;
},
close: function() {
if (!this.isOpen)
return;
this._button.remove_style_pseudo_class('open');
this._scrollView.hide();
this._triangle.set_text('\u25B8');
this.isOpen = false;
},
_onClicked: function() {
if (!this.isOpen)
this.open();
else
this.close();
},
updateSensitivity: function(sensitive) { updateSensitivity: function(sensitive) {
this._button.reactive = sensitive; this._button.reactive = sensitive;
this._button.can_focus = sensitive; this._button.can_focus = sensitive;
this._menu.close(BoxPointer.PopupAnimation.NONE);
},
for (let id in this._items) _updateOrnament: function() {
this._items[id].actor.reactive = sensitive; let itemIds = Object.keys(this._items);
for (let i = 0; i < itemIds.length; i++) {
if (itemIds[i] == this._activeSessionId)
this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.DOT);
else
this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.NONE);
}
}, },
setActiveSession: function(sessionId) { setActiveSession: function(sessionId) {
if (sessionId == this._activeSessionId) if (sessionId == this._activeSessionId)
return; return;
if (this._activeSessionId)
this._items[this._activeSessionId].setShowDot(false);
this._items[sessionId].setShowDot(true);
this._activeSessionId = sessionId; this._activeSessionId = sessionId;
this._updateOrnament();
this.emit('session-activated', this._activeSessionId); this.emit('session-activated', this._activeSessionId);
}, },
_populate: function() { close: function() {
this._itemList.destroy_all_children(); this._menu.close();
this._activeSessionId = null; },
this._items = {};
_populate: function() {
let ids = Gdm.get_session_ids(); let ids = Gdm.get_session_ids();
ids.sort(); ids.sort();
if (ids.length <= 1) { if (ids.length <= 1) {
this._box.hide();
this._button.hide(); this._button.hide();
} else { return;
this._button.show();
this._box.show();
} }
for (let i = 0; i < ids.length; i++) { for (let i = 0; i < ids.length; i++) {
let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]); let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
let item = new SessionListItem(ids[i], sessionName); let id = ids[i];
this._itemList.add_actor(item.actor); let item = new PopupMenu.PopupMenuItem(sessionName);
this._items[ids[i]] = item; this._menu.addMenuItem(item);
this._items[id] = item;
if (!this._activeSessionId) if (!this._activeSessionId)
this.setActiveSession(ids[i]); this.setActiveSession(id);
item.connect('activate', item.connect('activate', Lang.bind(this, function() {
Lang.bind(this, function() { this.setActiveSession(id);
this.setActiveSession(item.id); }));
}));
} }
} }
}); });
Signals.addSignalMethods(SessionList.prototype); Signals.addSignalMethods(SessionMenuButton.prototype);
const LoginDialog = new Lang.Class({ const LoginDialog = new Lang.Class({
Name: 'LoginDialog', Name: 'LoginDialog',
@ -585,17 +505,6 @@ const LoginDialog = new Lang.Class({
this._promptLoginHint.hide(); this._promptLoginHint.hide();
this._promptBox.add(this._promptLoginHint); this._promptBox.add(this._promptLoginHint);
this._sessionList = new SessionList();
this._sessionList.connect('session-activated',
Lang.bind(this, function(list, sessionId) {
this._greeter.call_select_session_sync (sessionId, null);
}));
this._promptBox.add(this._sessionList.actor,
{ expand: true,
x_fill: false,
y_fill: true,
x_align: St.Align.START });
this._buttonBox = new St.BoxLayout({ style_class: 'modal-dialog-button-box', this._buttonBox = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
vertical: false }); vertical: false });
this._promptBox.add(this._buttonBox, this._promptBox.add(this._buttonBox,
@ -656,6 +565,11 @@ const LoginDialog = new Lang.Class({
this._onUserListActivated(item); this._onUserListActivated(item);
})); }));
this._sessionMenuButton = new SessionMenuButton();
this._sessionMenuButton.connect('session-activated',
Lang.bind(this, function(button, sessionId) {
this._greeter.call_select_session_sync (sessionId, null);
}));
}, },
_updateDisableUserList: function() { _updateDisableUserList: function() {
@ -752,7 +666,7 @@ const LoginDialog = new Lang.Class({
}, },
_onDefaultSessionChanged: function(client, sessionId) { _onDefaultSessionChanged: function(client, sessionId) {
this._sessionList.setActiveSession(sessionId); this._sessionMenuButton.setActiveSession(sessionId);
}, },
_showMessage: function(userVerifier, message, styleClass) { _showMessage: function(userVerifier, message, styleClass) {
@ -784,7 +698,7 @@ const LoginDialog = new Lang.Class({
}, },
_showPrompt: function(forSecret) { _showPrompt: function(forSecret) {
this._sessionList.actor.hide(); this._sessionMenuButton.actor.hide();
this._promptLabel.show(); this._promptLabel.show();
this._promptEntry.show(); this._promptEntry.show();
this._promptLoginHint.opacity = 0; this._promptLoginHint.opacity = 0;
@ -797,7 +711,7 @@ const LoginDialog = new Lang.Class({
transition: 'easeOutQuad' }); transition: 'easeOutQuad' });
if ((this._user && !this._user.is_logged_in()) || this._verifyingUser) if ((this._user && !this._user.is_logged_in()) || this._verifyingUser)
this._sessionList.actor.show(); this._sessionMenuButton.actor.show();
this._promptEntry.grab_key_focus(); this._promptEntry.grab_key_focus();
@ -815,7 +729,7 @@ const LoginDialog = new Lang.Class({
_prepareDialog: function(forSecret, hold) { _prepareDialog: function(forSecret, hold) {
this._buttonBox.visible = true; this._buttonBox.visible = true;
this._buttonBox.destroy_all_children(); this._buttonBox.remove_all_children();
if (!this._disableUserList || this._verifyingUser) { if (!this._disableUserList || this._verifyingUser) {
this._cancelButton = new St.Button({ style_class: 'modal-dialog-button', this._cancelButton = new St.Button({ style_class: 'modal-dialog-button',
@ -844,6 +758,9 @@ const LoginDialog = new Lang.Class({
{ expand: false, { expand: false,
x_align: St.Align.END }); x_align: St.Align.END });
this._buttonBox.add(this._sessionMenuButton.actor,
{ expand: false,
x_align: St.Align.END });
this._signInButton = new St.Button({ style_class: 'modal-dialog-button', this._signInButton = new St.Button({ style_class: 'modal-dialog-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true, reactive: true,
@ -878,7 +795,7 @@ const LoginDialog = new Lang.Class({
_updateSensitivity: function(sensitive) { _updateSensitivity: function(sensitive) {
this._promptEntry.reactive = sensitive; this._promptEntry.reactive = sensitive;
this._promptEntry.clutter_text.editable = sensitive; this._promptEntry.clutter_text.editable = sensitive;
this._sessionList.updateSensitivity(sensitive); this._sessionMenuButton.updateSensitivity(sensitive);
this._updateSignInButtonSensitivity(sensitive); this._updateSignInButtonSensitivity(sensitive);
}, },
@ -890,8 +807,6 @@ const LoginDialog = new Lang.Class({
}, },
_hidePrompt: function() { _hidePrompt: function() {
this._buttonBox.destroy_all_children();
if (this._promptEntryTextChangedId > 0) { if (this._promptEntryTextChangedId > 0) {
this._promptEntry.clutter_text.disconnect(this._promptEntryTextChangedId); this._promptEntry.clutter_text.disconnect(this._promptEntryTextChangedId);
this._promptEntryTextChangedId = 0; this._promptEntryTextChangedId = 0;
@ -911,10 +826,10 @@ const LoginDialog = new Lang.Class({
this._updateSensitivity(true); this._updateSensitivity(true);
this._promptEntry.set_text(''); this._promptEntry.set_text('');
this._sessionList.close(); this._sessionMenuButton.close();
this._promptLoginHint.hide(); this._promptLoginHint.hide();
this._buttonBox.destroy_all_children(); this._buttonBox.remove_all_children();
this._signInButton = null; this._signInButton = null;
this._cancelButton = null; this._cancelButton = null;
}, },