Compare commits

...

2 Commits

Author SHA1 Message Date
Ray Strode
36c11009f5 loginDialog: make spinner and session menu button share position
They never need to be shown at the same time, and the design has
the UI fade between them.

This commit implements that.

https://bugzilla.gnome.org/show_bug.cgi?id=702818
2013-06-26 10:05:32 -04:00
Jasper St. Pierre
df6f6b7368 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, it's current position makes the "dialog" tall and unwieldy when
you add things like messages for finger print readers or authentication errors.

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

Some updates to patch by Ray Strode.

https://bugzilla.gnome.org/show_bug.cgi?id=702818
2013-06-26 10:05:04 -04:00
2 changed files with 126 additions and 198 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,183 +290,101 @@ const UserList = new Lang.Class({
}); });
Signals.addSignalMethods(UserList.prototype); Signals.addSignalMethods(UserList.prototype);
const SessionListItem = new Lang.Class({
Name: 'SessionListItem',
_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({ const SessionList = new Lang.Class({
Name: 'SessionList', 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,
Gtk.PolicyType.AUTOMATIC);
this._box.add_actor(this._scrollView);
this._itemList = new St.BoxLayout({ style_class: 'login-dialog-session-item-list',
vertical: true });
this._scrollView.add_actor(this._itemList);
this._scrollView.hide();
this.isOpen = false;
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 else
this.close(); this._button.remove_style_pseudo_class('active');
}));
let subtitle = new PopupMenu.PopupMenuItem(_("Session"), { style_class: 'popup-subtitle-menu-item',
reactive: false });
this._menu.addMenuItem(subtitle);
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();
}, },
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);
})); }));
} }
} }
@ -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,
@ -655,6 +564,26 @@ const LoginDialog = new Lang.Class({
this._onUserListActivated(item); this._onUserListActivated(item);
})); }));
this._defaultButtonWell = new St.Widget();
this._sessionList = new SessionList();
this._sessionList.connect('session-activated',
Lang.bind(this, function(list, sessionId) {
this._greeter.call_select_session_sync (sessionId, null);
}));
this._sessionList.actor.opacity = 0;
this._sessionList.actor.show();
this._defaultButtonWell.add_child(this._sessionList.actor);
let spinnerIcon = global.datadir + '/theme/process-working.svg';
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, _WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
this._workSpinner.actor.show();
this._defaultButtonWell.add_child(this._workSpinner.actor);
this._sessionList.actor.add_constraint(new Clutter.AlignConstraint({ source: this._workSpinner.actor,
align_axis: Clutter.AlignAxis.BOTH,
factor: 0.5 }));
}, },
_updateDisableUserList: function() { _updateDisableUserList: function() {
@ -722,6 +651,14 @@ const LoginDialog = new Lang.Class({
Tweener.removeTweens(this._workSpinner.actor); Tweener.removeTweens(this._workSpinner.actor);
if (working) { if (working) {
if (this._sessionList.actor.opacity > 0)
Tweener.addTween(this._sessionList.actor,
{ opacity: 0,
delay: _WORK_SPINNER_ANIMATION_DELAY,
time: _WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
this._workSpinner.play(); this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor, Tweener.addTween(this._workSpinner.actor,
{ opacity: 255, { opacity: 255,
@ -730,6 +667,13 @@ const LoginDialog = new Lang.Class({
transition: 'linear' transition: 'linear'
}); });
} else { } else {
if (this._sessionList.actor.opacity == 0 && this._shouldShowSessionList())
Tweener.addTween(this._sessionList.actor,
{ opacity: 255,
delay: _WORK_SPINNER_ANIMATION_DELAY,
time: _WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
Tweener.addTween(this._workSpinner.actor, Tweener.addTween(this._workSpinner.actor,
{ opacity: 0, { opacity: 0,
time: _WORK_SPINNER_ANIMATION_TIME, time: _WORK_SPINNER_ANIMATION_TIME,
@ -782,8 +726,20 @@ const LoginDialog = new Lang.Class({
this._reset(); this._reset();
}, },
_shouldShowSessionList: function() {
if (this._verifyingUser)
return true;
if (!this._user)
return false;
if (this._user.is_logged_in)
return false;
return true;
},
_showPrompt: function(forSecret) { _showPrompt: function(forSecret) {
this._sessionList.actor.hide();
this._promptLabel.show(); this._promptLabel.show();
this._promptEntry.show(); this._promptEntry.show();
this._promptLoginHint.opacity = 0; this._promptLoginHint.opacity = 0;
@ -795,8 +751,11 @@ const LoginDialog = new Lang.Class({
time: _FADE_ANIMATION_TIME, time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' }); transition: 'easeOutQuad' });
if ((this._user && !this._user.is_logged_in()) || this._verifyingUser) if (this._shouldShowSessionList()) {
this._sessionList.actor.show(); this._sessionList.actor.opacity = 255;
} else {
this._sessionList.actor.opacity = 0;
}
this._promptEntry.grab_key_focus(); this._promptEntry.grab_key_focus();
@ -814,7 +773,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',
@ -827,22 +786,19 @@ const LoginDialog = new Lang.Class({
this.cancel(); this.cancel();
})); }));
this._buttonBox.add(this._cancelButton, this._buttonBox.add(this._cancelButton,
{ expand: true, { expand: false,
x_fill: false, x_fill: false,
y_fill: false, y_fill: false,
x_align: St.Align.START, x_align: St.Align.START,
y_align: St.Align.END }); y_align: St.Align.END });
} }
let spinnerIcon = global.datadir + '/theme/process-working.svg'; this._buttonBox.add(this._defaultButtonWell,
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, _WORK_SPINNER_ICON_SIZE); { expand: true,
this._workSpinner.actor.opacity = 0; x_fill: false,
this._workSpinner.actor.show(); y_fill: false,
x_align: St.Align.END,
this._buttonBox.add(this._workSpinner.actor, y_align: St.Align.MIDDLE });
{ 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,
@ -854,7 +810,7 @@ const LoginDialog = new Lang.Class({
})); }));
this._signInButton.add_style_pseudo_class('default'); this._signInButton.add_style_pseudo_class('default');
this._buttonBox.add(this._signInButton, this._buttonBox.add(this._signInButton,
{ expand: true, { expand: false,
x_fill: false, x_fill: false,
y_fill: false, y_fill: false,
x_align: St.Align.END, x_align: St.Align.END,
@ -889,8 +845,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;
@ -913,7 +867,7 @@ const LoginDialog = new Lang.Class({
this._sessionList.close(); this._sessionList.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;
}, },