ffbc1fd190
The code here was trying to center the label, but that didn't happen because we allocated the entire space to the label, which still plonks it at the top.
252 lines
8.7 KiB
JavaScript
252 lines
8.7 KiB
JavaScript
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
|
|
const AccountsService = imports.gi.AccountsService;
|
|
const Clutter = imports.gi.Clutter;
|
|
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 Signals = imports.signals;
|
|
const Shell = imports.gi.Shell;
|
|
const St = imports.gi.St;
|
|
|
|
const Main = imports.ui.main;
|
|
const ModalDialog = imports.ui.modalDialog;
|
|
const ShellEntry = imports.ui.shellEntry;
|
|
const Tweener = imports.ui.tweener;
|
|
const UserMenu = imports.ui.userMenu;
|
|
|
|
const Batch = imports.gdm.batch;
|
|
const GdmUtil = imports.gdm.util;
|
|
|
|
// The timeout before going back automatically to the lock screen (in seconds)
|
|
const IDLE_TIMEOUT = 2 * 60;
|
|
|
|
// A widget showing the user avatar and name
|
|
const UserWidget = new Lang.Class({
|
|
Name: 'UserWidget',
|
|
|
|
_init: function(user) {
|
|
this._user = user;
|
|
|
|
this.actor = new St.BoxLayout({ style_class: 'unlock-dialog-user-name-container',
|
|
vertical: false });
|
|
|
|
this._avatar = new UserMenu.UserAvatarWidget(user);
|
|
this.actor.add(this._avatar.actor,
|
|
{ x_fill: true, y_fill: true });
|
|
|
|
this._label = new St.Label({ style_class: 'login-dialog-username' });
|
|
this.actor.add(this._label,
|
|
{ expand: true,
|
|
x_fill: true,
|
|
y_fill: false,
|
|
y_align: St.Align.MIDDLE });
|
|
|
|
this._userLoadedId = this._user.connect('notify::is-loaded',
|
|
Lang.bind(this, this._updateUser));
|
|
this._userChangedId = this._user.connect('changed',
|
|
Lang.bind(this, this._updateUser));
|
|
if (this._user.is_loaded)
|
|
this._updateUser();
|
|
},
|
|
|
|
destroy: function() {
|
|
if (this._userLoadedId != 0) {
|
|
this._user.disconnect(this._userLoadedId);
|
|
this._userLoadedId = 0;
|
|
}
|
|
|
|
if (this._userChangedId != 0) {
|
|
this._user.disconnect(this._userChangedId);
|
|
this._userChangedId = 0;
|
|
}
|
|
|
|
this.actor.destroy();
|
|
},
|
|
|
|
_updateUser: function() {
|
|
if (this._user.is_loaded)
|
|
this._label.text = this._user.get_real_name();
|
|
else
|
|
this._label.text = '';
|
|
|
|
this._avatar.update();
|
|
}
|
|
});
|
|
|
|
const UnlockDialog = new Lang.Class({
|
|
Name: 'UnlockDialog',
|
|
Extends: ModalDialog.ModalDialog,
|
|
|
|
_init: function(parentActor) {
|
|
this.parent({ shellReactive: true,
|
|
styleClass: 'login-dialog',
|
|
parentActor: parentActor
|
|
});
|
|
|
|
this._userManager = AccountsService.UserManager.get_default();
|
|
this._userName = GLib.get_user_name();
|
|
this._user = this._userManager.get_user(this._userName);
|
|
|
|
this._failCounter = 0;
|
|
|
|
this._greeterClient = new Gdm.Client();
|
|
this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient, { reauthenticationOnly: true });
|
|
|
|
this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion));
|
|
this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
|
|
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
|
|
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
|
|
|
|
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
|
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
|
|
|
|
this._userWidget = new UserWidget(this._user);
|
|
this.contentLayout.add_actor(this._userWidget.actor);
|
|
|
|
this._promptLayout = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
|
|
vertical: true });
|
|
|
|
this._promptLabel = new St.Label({ style_class: 'login-dialog-prompt-label' });
|
|
this._promptLayout.add(this._promptLabel,
|
|
{ x_align: St.Align.START });
|
|
|
|
this._promptEntry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
|
|
can_focus: true });
|
|
ShellEntry.addContextMenu(this._promptEntry);
|
|
this.setInitialKeyFocus(this._promptEntry);
|
|
this._promptEntry.clutter_text.connect('activate', Lang.bind(this, this._doUnlock));
|
|
|
|
this._promptLayout.add(this._promptEntry,
|
|
{ expand: true,
|
|
x_fill: true });
|
|
|
|
this.contentLayout.add_actor(this._promptLayout);
|
|
|
|
this._promptMessage = new St.Label({ visible: false });
|
|
this.contentLayout.add(this._promptMessage, { x_fill: true });
|
|
|
|
this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint' });
|
|
this._promptLoginHint.hide();
|
|
this.contentLayout.add_actor(this._promptLoginHint);
|
|
|
|
let cancelButton = { label: _("Cancel"),
|
|
action: Lang.bind(this, this._escape),
|
|
key: Clutter.KEY_Escape };
|
|
this._okButton = { label: _("Unlock"),
|
|
action: Lang.bind(this, this._doUnlock),
|
|
default: true };
|
|
this.setButtons([cancelButton, this._okButton]);
|
|
|
|
this._updateOkButton(false);
|
|
|
|
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
|
|
style_class: 'login-dialog-not-listed-label' });
|
|
this._otherUserButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
|
|
can_focus: true,
|
|
child: otherUserLabel,
|
|
reactive: true,
|
|
x_align: St.Align.START,
|
|
x_fill: true });
|
|
this._otherUserButton.connect('clicked', Lang.bind(this, this._otherUserClicked));
|
|
this.dialogLayout.add(this._otherUserButton,
|
|
{ x_align: St.Align.START,
|
|
x_fill: false });
|
|
|
|
let batch = new Batch.Hold();
|
|
this._userVerifier.begin(this._userName, batch);
|
|
|
|
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
|
this.emit('loaded');
|
|
return false;
|
|
}));
|
|
|
|
this._idleMonitor = Shell.IdleMonitor.get();
|
|
// this dialog is only created after user activity (curtain drag or
|
|
// escape key press), so the timeout will fire after IDLE_TIMEOUT seconds of inactivity
|
|
this._idleWatchId = this._idleMonitor.add_watch(IDLE_TIMEOUT * 1000, Lang.bind(this, this._escape));
|
|
},
|
|
|
|
_updateOkButton: function(sensitive) {
|
|
this._okButton.button.reactive = sensitive;
|
|
},
|
|
|
|
_showMessage: function(userVerifier, message, styleClass) {
|
|
this._promptMessage.text = message;
|
|
this._promptMessage.styleClass = styleClass;
|
|
GdmUtil.fadeInActor(this._promptMessage);
|
|
},
|
|
|
|
_onAskQuestion: function(verifier, serviceName, question, passwordChar) {
|
|
this._promptLabel.text = question;
|
|
|
|
this._promptEntry.text = '';
|
|
this._promptEntry.clutter_text.set_password_char(passwordChar);
|
|
this._promptEntry.menu.isPassword = passwordChar != '';
|
|
|
|
this._currentQuery = serviceName;
|
|
this._updateOkButton(true);
|
|
},
|
|
|
|
_showLoginHint: function(verifier, message) {
|
|
this._promptLoginHint.set_text(message)
|
|
GdmUtil.fadeInActor(this._promptLoginHint);
|
|
},
|
|
|
|
_hideLoginHint: function() {
|
|
GdmUtil.fadeOutActor(this._promptLoginHint);
|
|
},
|
|
|
|
_doUnlock: function() {
|
|
if (!this._currentQuery)
|
|
return;
|
|
|
|
let query = this._currentQuery;
|
|
this._currentQuery = null;
|
|
|
|
this._updateOkButton(false);
|
|
|
|
this._userVerifier.answerQuery(query, this._promptEntry.text);
|
|
},
|
|
|
|
_onVerificationComplete: function() {
|
|
this._userVerifier.clear();
|
|
this.emit('unlocked');
|
|
},
|
|
|
|
_onReset: function() {
|
|
this.emit('failed');
|
|
},
|
|
|
|
_escape: function() {
|
|
this._userVerifier.cancel();
|
|
this.emit('failed');
|
|
},
|
|
|
|
_otherUserClicked: function(button, event) {
|
|
Gdm.goto_login_session_sync(null);
|
|
|
|
this._userVerifier.cancel();
|
|
this.emit('failed');
|
|
},
|
|
|
|
destroy: function() {
|
|
this._userVerifier.clear();
|
|
|
|
if (this._idleWatchId) {
|
|
this._idleMonitor.remove_watch(this._idleWatchId);
|
|
this._idleWatchId = 0;
|
|
}
|
|
|
|
this.parent();
|
|
},
|
|
|
|
cancel: function() {
|
|
this._userVerifier.cancel(null);
|
|
|
|
this.destroy();
|
|
},
|
|
});
|