diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js index faea47f22..70d091f2e 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -746,7 +746,12 @@ const LoginDialog = new Lang.Class({ this._promptEntry.show(); this._promptLoginHint.opacity = 0; this._promptLoginHint.show(); + this._promptBox.opacity = 0; this._promptBox.show(); + Tweener.addTween(this._promptBox, + { opacity: 255, + time: _FADE_ANIMATION_TIME, + transition: 'easeOutQuad' }); if (!this._user || (this._user.is_logged_in() && this._verifyingUser)) this._sessionList.actor.show(); @@ -1065,6 +1070,7 @@ const LoginDialog = new Lang.Class({ _hideUserListAndLogIn: function() { this._setUserListExpanded(false); + GdmUtil.cloneAndFadeOutActor(this._userSelectionBox); this._askForUsernameAndLogIn(); }, @@ -1082,15 +1088,31 @@ const LoginDialog = new Lang.Class({ return hold; }, - _onUserListActivated: function(activatedItem) { + _beginVerificationForItem: function(item) { let userWidget = new UserWidget.UserWidget(item.user); this._promptUser.set_child(userWidget.actor); - this._setUserListExpanded(false); + let tasks = [function() { + let userName = item.user.get_user_name(); + return this._beginVerificationForUser(userName); + }]; + let batch = new Batch.ConsecutiveBatch(this, tasks); + return batch.run(); + }, + + _onUserListActivated: function(activatedItem) { + let tasks = [function() { + return GdmUtil.cloneAndFadeOutActor(this._userSelectionBox); + }, + function() { + this._setUserListExpanded(false); + }]; this._user = activatedItem.user; - let userName = activatedItem.user.get_user_name(); - this._beginVerificationForUser(userName); + + let batch = new Batch.ConcurrentBatch(this, [new Batch.ConsecutiveBatch(this, tasks), + this._beginVerificationForItem(activatedItem)]); + batch.run(); }, _onDestroy: function() { diff --git a/js/gdm/util.js b/js/gdm/util.js index 881d85916..6b69f33ee 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -1,5 +1,6 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- +const Clutter = imports.gi.Clutter; const Gio = imports.gi.Gio; const Lang = imports.lang; const Mainloop = imports.mainloop; @@ -15,6 +16,7 @@ const Tweener = imports.ui.tweener; const PASSWORD_SERVICE_NAME = 'gdm-password'; const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; const FADE_ANIMATION_TIME = 0.16; +const CLONE_FADE_ANIMATION_TIME = 0.25; const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen'; const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication'; @@ -71,6 +73,34 @@ function fadeOutActor(actor) { return hold; } +function cloneAndFadeOutActor(actor) { + // Immediately hide actor so its sibling can have its space + // and position, but leave a non-reactive clone on-screen, + // so from the user's point of view it smoothly fades away + // and reveals its sibling. + actor.hide(); + + let clone = new Clutter.Clone({ source: actor, + reactive: false }); + + Main.uiGroup.add_child(clone); + + let [x, y] = actor.get_transformed_position(); + clone.set_position(x, y); + + let hold = new Batch.Hold(); + Tweener.addTween(clone, + { opacity: 0, + time: CLONE_FADE_ANIMATION_TIME, + transition: 'easeOutQuad', + onComplete: function() { + clone.destroy(); + hold.release(); + } + }); + return hold; +} + const ShellUserVerifier = new Lang.Class({ Name: 'ShellUserVerifier',