a28d639c3b
The design calls for the curtain to appear in the gdm greeter too. Implement this by having the screenshield manage the login dialog (delegating its creation to SessionMode). https://bugzilla.gnome.org/show_bug.cgi?id=619955
228 lines
8.0 KiB
JavaScript
228 lines
8.0 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;
|
|
|
|
// 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: 'unlock-dialog-user-name' });
|
|
this.actor.add(this._label,
|
|
{ expand: true,
|
|
x_fill: true,
|
|
y_fill: true });
|
|
|
|
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._greeterClient = new Gdm.Client();
|
|
this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient);
|
|
|
|
this._userVerifier.connect('reset', Lang.bind(this, this._reset));
|
|
this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion));
|
|
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
|
|
this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed));
|
|
|
|
this._userVerifier.connect('show-fingerprint-prompt', Lang.bind(this, this._showFingerprintPrompt));
|
|
this._userVerifier.connect('hide-fingerprint-prompt', Lang.bind(this, this._hideFingerprintPrompt));
|
|
|
|
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: false });
|
|
|
|
this._promptLabel = new St.Label({ style_class: 'login-dialog-prompt-label' });
|
|
this._promptLayout.add(this._promptLabel,
|
|
{ expand: false,
|
|
x_fill: true,
|
|
y_fill: true,
|
|
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,
|
|
y_fill: false,
|
|
x_align: St.Align.START });
|
|
|
|
this.contentLayout.add_actor(this._promptLayout);
|
|
|
|
// Translators: this message is shown below the password entry field
|
|
// to indicate the user can swipe their finger instead
|
|
this._promptFingerprintMessage = new St.Label({ text: _("(or swipe finger)"),
|
|
style_class: 'login-dialog-prompt-fingerprint-message' });
|
|
this._promptFingerprintMessage.hide();
|
|
this.contentLayout.add_actor(this._promptFingerprintMessage);
|
|
|
|
let otherUserLabel = new St.Label({ text: _("Login 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.contentLayout.add(this._otherUserButton,
|
|
{ x_align: St.Align.START,
|
|
x_fill: false });
|
|
|
|
this._okButton = { label: _("Unlock"),
|
|
action: Lang.bind(this, this._doUnlock),
|
|
default: true };
|
|
this.setButtons([this._okButton]);
|
|
|
|
this._updateOkButton(false);
|
|
this._reset();
|
|
|
|
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
|
this.emit('loaded');
|
|
return false;
|
|
}));
|
|
},
|
|
|
|
_updateOkButton: function(sensitive) {
|
|
this._okButton.button.reactive = sensitive;
|
|
},
|
|
|
|
_reset: function() {
|
|
this._userVerifier.begin(this._userName, new Batch.Hold());
|
|
},
|
|
|
|
_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);
|
|
},
|
|
|
|
_showFingerprintPrompt: function() {
|
|
GdmUtil.fadeInActor(this._promptFingerprintMessage);
|
|
},
|
|
|
|
_hideFingerprintPrompt: function() {
|
|
GdmUtil.fadeOutActor(this._promptFingerprintMessage);
|
|
},
|
|
|
|
_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');
|
|
},
|
|
|
|
_onVerificationFailed: function() {
|
|
this._userVerifier.cancel();
|
|
this.emit('failed');
|
|
},
|
|
|
|
_otherUserClicked: function(button, event) {
|
|
this._userManager.goto_login_session();
|
|
|
|
this._userVerifier.cancel();
|
|
this.emit('failed');
|
|
},
|
|
|
|
destroy: function() {
|
|
this._userVerifier.clear();
|
|
this.parent();
|
|
},
|
|
|
|
cancel: function() {
|
|
this._userVerifier.cancel(null);
|
|
|
|
this.destroy();
|
|
},
|
|
});
|