2011-09-28 09:16:26 -04:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
|
|
/*
|
2011-08-23 22:12:57 -04:00
|
|
|
* Copyright 2011 Red Hat, Inc
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2014-01-08 04:32:37 +07:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2011-08-23 22:12:57 -04:00
|
|
|
*/
|
|
|
|
|
2023-07-10 02:53:00 -07:00
|
|
|
import AccountsService from 'gi://AccountsService';
|
|
|
|
import Atk from 'gi://Atk';
|
|
|
|
import Clutter from 'gi://Clutter';
|
|
|
|
import Gdm from 'gi://Gdm';
|
|
|
|
import Gio from 'gi://Gio';
|
|
|
|
import GLib from 'gi://GLib';
|
|
|
|
import GObject from 'gi://GObject';
|
|
|
|
import Meta from 'gi://Meta';
|
|
|
|
import Pango from 'gi://Pango';
|
|
|
|
import Shell from 'gi://Shell';
|
|
|
|
import St from 'gi://St';
|
|
|
|
|
|
|
|
import * as AuthPrompt from './authPrompt.js';
|
|
|
|
import * as Batch from './batch.js';
|
|
|
|
import * as BoxPointer from '../ui/boxpointer.js';
|
|
|
|
import * as CtrlAltTab from '../ui/ctrlAltTab.js';
|
|
|
|
import * as GdmUtil from './util.js';
|
|
|
|
import * as Layout from '../ui/layout.js';
|
|
|
|
import * as LoginManager from '../misc/loginManager.js';
|
|
|
|
import * as Main from '../ui/main.js';
|
|
|
|
import * as PopupMenu from '../ui/popupMenu.js';
|
|
|
|
import * as Realmd from './realmd.js';
|
|
|
|
import * as UserWidget from '../ui/userWidget.js';
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2019-08-02 01:13:10 +02:00
|
|
|
const _FADE_ANIMATION_TIME = 250;
|
|
|
|
const _SCROLL_ANIMATION_TIME = 500;
|
2011-08-23 22:12:57 -04:00
|
|
|
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
|
|
|
|
|
2023-07-10 02:53:00 -07:00
|
|
|
export const UserListItem = GObject.registerClass({
|
2023-08-07 00:40:20 +02:00
|
|
|
Signals: {'activate': {}},
|
2019-07-16 11:24:13 +02:00
|
|
|
}, class UserListItem extends St.Button {
|
|
|
|
_init(user) {
|
2019-10-17 23:40:24 +02:00
|
|
|
let layout = new St.BoxLayout({
|
|
|
|
vertical: true,
|
|
|
|
});
|
2019-07-16 11:24:13 +02:00
|
|
|
super._init({
|
|
|
|
style_class: 'login-dialog-user-list-item',
|
|
|
|
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
|
|
|
|
can_focus: true,
|
2019-10-21 20:44:00 +02:00
|
|
|
x_expand: true,
|
2019-07-16 11:24:13 +02:00
|
|
|
child: layout,
|
|
|
|
reactive: true,
|
|
|
|
});
|
|
|
|
|
2011-08-23 22:12:57 -04:00
|
|
|
this.user = user;
|
2021-08-16 00:36:59 +02:00
|
|
|
this.user.connectObject('changed', this._onUserChanged.bind(this), this);
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2019-07-16 11:24:13 +02:00
|
|
|
this.connect('notify::hover', () => {
|
|
|
|
this._setSelected(this.hover);
|
2017-06-09 17:34:43 +02:00
|
|
|
});
|
|
|
|
|
2013-08-26 18:41:29 -04:00
|
|
|
this._userWidget = new UserWidget.UserWidget(this.user);
|
2023-11-07 10:47:14 +00:00
|
|
|
layout.add_child(this._userWidget);
|
2012-07-14 00:43:58 +02:00
|
|
|
|
2023-08-07 01:45:22 +02:00
|
|
|
this._userWidget.bind_property('label-actor',
|
|
|
|
this, 'label-actor',
|
|
|
|
GObject.BindingFlags.SYNC_CREATE);
|
2015-03-06 16:56:11 +01:00
|
|
|
|
2020-03-29 23:51:13 +02:00
|
|
|
this._timedLoginIndicator = new St.Bin({
|
|
|
|
style_class: 'login-dialog-timed-login-indicator',
|
|
|
|
scale_x: 0,
|
|
|
|
visible: false,
|
|
|
|
});
|
2023-11-07 10:47:14 +00:00
|
|
|
layout.add_child(this._timedLoginIndicator);
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2012-09-01 08:06:41 -03:00
|
|
|
this._onUserChanged();
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2019-07-16 11:24:13 +02:00
|
|
|
vfunc_key_focus_in() {
|
|
|
|
super.vfunc_key_focus_in();
|
|
|
|
this._setSelected(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
vfunc_key_focus_out() {
|
|
|
|
super.vfunc_key_focus_out();
|
|
|
|
this._setSelected(false);
|
|
|
|
}
|
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_onUserChanged() {
|
2012-07-09 20:04:23 +02:00
|
|
|
this._updateLoggedIn();
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2012-07-09 23:46:35 +02:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_updateLoggedIn() {
|
2012-07-09 20:04:23 +02:00
|
|
|
if (this.user.is_logged_in())
|
2019-07-16 11:24:13 +02:00
|
|
|
this.add_style_pseudo_class('logged-in');
|
2012-07-09 20:04:23 +02:00
|
|
|
else
|
2019-07-16 11:24:13 +02:00
|
|
|
this.remove_style_pseudo_class('logged-in');
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2012-07-09 20:04:23 +02:00
|
|
|
|
2019-09-10 07:42:48 +02:00
|
|
|
vfunc_clicked() {
|
2011-08-23 22:12:57 -04:00
|
|
|
this.emit('activate');
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_setSelected(selected) {
|
2017-06-09 17:34:43 +02:00
|
|
|
if (selected) {
|
2019-07-16 11:24:13 +02:00
|
|
|
this.add_style_pseudo_class('selected');
|
|
|
|
this.grab_key_focus();
|
2017-06-09 17:34:43 +02:00
|
|
|
} else {
|
2019-07-16 11:24:13 +02:00
|
|
|
this.remove_style_pseudo_class('selected');
|
2017-06-09 17:34:43 +02:00
|
|
|
}
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2017-06-09 17:34:43 +02:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
showTimedLoginIndicator(time) {
|
2011-08-23 22:12:57 -04:00
|
|
|
let hold = new Batch.Hold();
|
|
|
|
|
2012-07-14 00:43:58 +02:00
|
|
|
this.hideTimedLoginIndicator();
|
2015-08-18 12:02:17 -04:00
|
|
|
|
2018-04-07 21:23:13 +02:00
|
|
|
this._timedLoginIndicator.visible = true;
|
|
|
|
|
2015-08-18 12:02:17 -04:00
|
|
|
let startTime = GLib.get_monotonic_time();
|
|
|
|
|
2019-08-19 19:55:49 +02:00
|
|
|
this._timedLoginTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 33,
|
2017-10-31 01:38:18 +01:00
|
|
|
() => {
|
|
|
|
let currentTime = GLib.get_monotonic_time();
|
|
|
|
let elapsedTime = (currentTime - startTime) / GLib.USEC_PER_SEC;
|
|
|
|
this._timedLoginIndicator.scale_x = elapsedTime / time;
|
|
|
|
if (elapsedTime >= time) {
|
|
|
|
this._timedLoginTimeoutId = 0;
|
|
|
|
hold.release();
|
|
|
|
return GLib.SOURCE_REMOVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GLib.SOURCE_CONTINUE;
|
|
|
|
});
|
2015-08-18 12:02:17 -04:00
|
|
|
|
|
|
|
GLib.Source.set_name_by_id(this._timedLoginTimeoutId, '[gnome-shell] this._timedLoginTimeoutId');
|
|
|
|
|
2011-08-23 22:12:57 -04:00
|
|
|
return hold;
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2012-07-14 00:43:58 +02:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
hideTimedLoginIndicator() {
|
2015-08-18 12:02:17 -04:00
|
|
|
if (this._timedLoginTimeoutId) {
|
|
|
|
GLib.source_remove(this._timedLoginTimeoutId);
|
|
|
|
this._timedLoginTimeoutId = 0;
|
|
|
|
}
|
2018-04-07 21:23:13 +02:00
|
|
|
|
|
|
|
this._timedLoginIndicator.visible = false;
|
2012-07-14 00:43:58 +02:00
|
|
|
this._timedLoginIndicator.scale_x = 0.;
|
2011-08-23 22:12:57 -04:00
|
|
|
}
|
2019-07-16 11:24:13 +02:00
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2023-07-10 02:53:00 -07:00
|
|
|
const UserList = GObject.registerClass({
|
2019-07-16 11:24:13 +02:00
|
|
|
Signals: {
|
2023-08-07 00:40:20 +02:00
|
|
|
'activate': {param_types: [UserListItem.$gtype]},
|
|
|
|
'item-added': {param_types: [UserListItem.$gtype]},
|
2019-08-20 23:43:54 +02:00
|
|
|
},
|
2019-07-16 11:24:13 +02:00
|
|
|
}, class UserList extends St.ScrollView {
|
|
|
|
_init() {
|
2019-10-21 20:44:00 +02:00
|
|
|
super._init({
|
|
|
|
style_class: 'login-dialog-user-list-view',
|
|
|
|
x_expand: true,
|
|
|
|
y_expand: true,
|
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2020-03-29 23:51:13 +02:00
|
|
|
this._box = new St.BoxLayout({
|
|
|
|
vertical: true,
|
|
|
|
style_class: 'login-dialog-user-list',
|
|
|
|
pseudo_class: 'expanded',
|
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2023-11-07 10:47:14 +00:00
|
|
|
this.child = this._box;
|
2011-08-23 22:12:57 -04:00
|
|
|
this._items = {};
|
2019-09-10 07:42:48 +02:00
|
|
|
}
|
2011-10-17 02:56:44 -04:00
|
|
|
|
2019-09-10 07:42:48 +02:00
|
|
|
vfunc_key_focus_in() {
|
2020-03-26 23:40:38 +01:00
|
|
|
super.vfunc_key_focus_in();
|
2019-09-10 07:42:48 +02:00
|
|
|
this._moveFocusToItems();
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-10-17 02:56:44 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_moveFocusToItems() {
|
2011-10-17 02:56:44 -04:00
|
|
|
let hasItems = Object.keys(this._items).length > 0;
|
|
|
|
|
|
|
|
if (!hasItems)
|
|
|
|
return;
|
|
|
|
|
2023-08-07 02:51:19 +02:00
|
|
|
if (global.stage.get_key_focus() !== this)
|
2011-10-17 02:56:44 -04:00
|
|
|
return;
|
|
|
|
|
2019-07-16 11:24:13 +02:00
|
|
|
let focusSet = this.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
2012-10-05 10:00:32 +02:00
|
|
|
if (!focusSet) {
|
2022-09-07 20:23:38 +02:00
|
|
|
const laters = global.compositor.get_laters();
|
|
|
|
laters.add(Meta.LaterType.BEFORE_REDRAW, () => {
|
2012-10-05 10:00:32 +02:00
|
|
|
this._moveFocusToItems();
|
|
|
|
return false;
|
2017-10-31 01:38:18 +01:00
|
|
|
});
|
2012-10-05 10:00:32 +02:00
|
|
|
}
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_onItemActivated(activatedItem) {
|
2011-08-23 22:12:57 -04:00
|
|
|
this.emit('activate', activatedItem);
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
updateStyle(isExpanded) {
|
2013-02-06 16:37:47 -05:00
|
|
|
if (isExpanded)
|
|
|
|
this._box.add_style_pseudo_class('expanded');
|
|
|
|
else
|
|
|
|
this._box.remove_style_pseudo_class('expanded');
|
2013-02-04 16:50:46 -05:00
|
|
|
|
2011-08-23 22:12:57 -04:00
|
|
|
for (let userName in this._items) {
|
|
|
|
let item = this._items[userName];
|
2019-07-16 11:24:13 +02:00
|
|
|
item.sync_hover();
|
2011-08-23 22:12:57 -04:00
|
|
|
}
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
scrollToItem(item) {
|
2019-07-16 11:24:13 +02:00
|
|
|
let box = item.get_allocation_box();
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2023-11-15 14:31:37 +01:00
|
|
|
const adjustment = this.vadjustment;
|
2011-08-23 22:12:57 -04:00
|
|
|
|
|
|
|
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
|
2019-07-24 21:03:17 +02:00
|
|
|
adjustment.ease(value, {
|
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
2019-08-20 23:43:54 +02:00
|
|
|
duration: _SCROLL_ANIMATION_TIME,
|
2019-07-24 21:03:17 +02:00
|
|
|
});
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
jumpToItem(item) {
|
2019-07-16 11:24:13 +02:00
|
|
|
let box = item.get_allocation_box();
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2023-11-15 14:31:37 +01:00
|
|
|
const adjustment = this.vadjustment;
|
2011-08-23 22:12:57 -04:00
|
|
|
|
|
|
|
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
|
|
|
|
|
|
|
|
adjustment.set_value(value);
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
getItemFromUserName(userName) {
|
2011-08-23 22:12:57 -04:00
|
|
|
let item = this._items[userName];
|
|
|
|
|
|
|
|
if (!item)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
return item;
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
containsUser(user) {
|
2015-11-23 18:24:19 -06:00
|
|
|
return this._items[user.get_user_name()] != null;
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2015-11-23 18:24:19 -06:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
addUser(user) {
|
2011-08-23 22:12:57 -04:00
|
|
|
if (!user.is_loaded)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (user.is_system_account())
|
|
|
|
return;
|
|
|
|
|
2012-04-09 18:43:44 +02:00
|
|
|
if (user.locked)
|
2019-01-29 20:36:54 +01:00
|
|
|
return;
|
2012-04-09 18:43:44 +02:00
|
|
|
|
2011-08-23 22:12:57 -04:00
|
|
|
let userName = user.get_user_name();
|
|
|
|
|
|
|
|
if (!userName)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.removeUser(user);
|
|
|
|
|
|
|
|
let item = new UserListItem(user);
|
2019-10-21 20:44:00 +02:00
|
|
|
this._box.add_child(item);
|
2011-08-23 22:12:57 -04:00
|
|
|
|
|
|
|
this._items[userName] = item;
|
|
|
|
|
2017-12-02 01:27:35 +01:00
|
|
|
item.connect('activate', this._onItemActivated.bind(this));
|
2011-08-23 22:12:57 -04:00
|
|
|
|
|
|
|
// Try to keep the focused item front-and-center
|
2019-07-16 11:24:13 +02:00
|
|
|
item.connect('key-focus-in', () => this.scrollToItem(item));
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2011-10-17 02:56:44 -04:00
|
|
|
this._moveFocusToItems();
|
|
|
|
|
2011-08-23 22:12:57 -04:00
|
|
|
this.emit('item-added', item);
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
removeUser(user) {
|
2011-08-23 22:12:57 -04:00
|
|
|
if (!user.is_loaded)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let userName = user.get_user_name();
|
|
|
|
|
|
|
|
if (!userName)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let item = this._items[userName];
|
|
|
|
|
|
|
|
if (!item)
|
|
|
|
return;
|
|
|
|
|
2019-07-16 11:24:13 +02:00
|
|
|
item.destroy();
|
2011-08-23 22:12:57 -04:00
|
|
|
delete this._items[userName];
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2017-07-07 14:47:23 +08:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
numItems() {
|
2017-07-07 14:47:23 +08:00
|
|
|
return Object.keys(this._items).length;
|
2011-08-23 22:12:57 -04:00
|
|
|
}
|
2019-07-16 11:24:13 +02:00
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2023-07-10 02:53:00 -07:00
|
|
|
const SessionMenuButton = GObject.registerClass({
|
2023-08-07 00:40:20 +02:00
|
|
|
Signals: {'session-activated': {param_types: [GObject.TYPE_STRING]}},
|
2019-07-16 11:24:13 +02:00
|
|
|
}, class SessionMenuButton extends St.Bin {
|
|
|
|
_init() {
|
|
|
|
let button = new St.Button({
|
2022-12-01 14:44:04 -03:30
|
|
|
style_class: 'login-dialog-button login-dialog-session-list-button',
|
2022-03-21 16:44:24 +01:00
|
|
|
icon_name: 'emblem-system-symbolic',
|
2019-07-16 11:24:13 +02:00
|
|
|
reactive: true,
|
|
|
|
track_hover: true,
|
|
|
|
can_focus: true,
|
2023-08-07 00:34:20 +02:00
|
|
|
accessible_name: _('Choose Session'),
|
2019-07-16 11:24:13 +02:00
|
|
|
accessible_role: Atk.Role.MENU,
|
2020-01-28 23:22:30 +05:30
|
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
|
|
y_align: Clutter.ActorAlign.CENTER,
|
2019-07-16 11:24:13 +02:00
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2023-08-07 00:40:20 +02:00
|
|
|
super._init({child: button});
|
2019-07-16 11:24:13 +02:00
|
|
|
this._button = button;
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2020-01-16 12:13:29 +05:30
|
|
|
this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.BOTTOM);
|
2023-11-07 10:47:14 +00:00
|
|
|
Main.uiGroup.add_child(this._menu.actor);
|
2013-06-23 23:14:10 -04:00
|
|
|
this._menu.actor.hide();
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:38:18 +01:00
|
|
|
this._menu.connect('open-state-changed', (menu, isOpen) => {
|
2019-01-29 20:36:54 +01:00
|
|
|
if (isOpen)
|
|
|
|
this._button.add_style_pseudo_class('active');
|
|
|
|
else
|
|
|
|
this._button.remove_style_pseudo_class('active');
|
2017-10-31 01:38:18 +01:00
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2019-04-09 18:23:59 -05:00
|
|
|
this._manager = new PopupMenu.PopupMenuManager(this._button,
|
2023-08-07 01:45:22 +02:00
|
|
|
{actionMode: Shell.ActionMode.NONE});
|
2013-06-23 23:14:10 -04:00
|
|
|
this._manager.addMenu(this._menu);
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2019-01-28 01:42:00 +01:00
|
|
|
this._button.connect('clicked', () => this._menu.toggle());
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2013-06-23 23:14:10 -04:00
|
|
|
this._items = {};
|
|
|
|
this._activeSessionId = null;
|
|
|
|
this._populate();
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
updateSensitivity(sensitive) {
|
2012-11-18 22:36:17 +01:00
|
|
|
this._button.reactive = sensitive;
|
|
|
|
this._button.can_focus = sensitive;
|
2020-01-16 12:13:29 +05:30
|
|
|
this.opacity = sensitive ? 255 : 0;
|
2013-06-23 23:14:10 -04:00
|
|
|
this._menu.close(BoxPointer.PopupAnimation.NONE);
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2012-11-18 22:36:17 +01:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_updateOrnament() {
|
2013-06-23 23:14:10 -04:00
|
|
|
let itemIds = Object.keys(this._items);
|
|
|
|
for (let i = 0; i < itemIds.length; i++) {
|
2023-08-07 02:51:19 +02:00
|
|
|
if (itemIds[i] === this._activeSessionId)
|
2013-06-23 23:14:10 -04:00
|
|
|
this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.DOT);
|
|
|
|
else
|
2023-11-23 11:16:18 -03:30
|
|
|
this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.NO_DOT);
|
2013-06-23 23:14:10 -04:00
|
|
|
}
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2012-11-18 22:36:17 +01:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
setActiveSession(sessionId) {
|
2023-08-07 02:51:19 +02:00
|
|
|
if (sessionId === this._activeSessionId)
|
2019-01-29 20:36:54 +01:00
|
|
|
return;
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2019-01-29 20:36:54 +01:00
|
|
|
this._activeSessionId = sessionId;
|
|
|
|
this._updateOrnament();
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
close() {
|
2013-06-23 23:14:10 -04:00
|
|
|
this._menu.close();
|
2017-10-31 02:19:44 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_populate() {
|
2012-05-20 01:19:25 +02:00
|
|
|
let ids = Gdm.get_session_ids();
|
2011-08-23 22:12:57 -04:00
|
|
|
ids.sort();
|
|
|
|
|
2011-10-11 13:34:04 -04:00
|
|
|
if (ids.length <= 1) {
|
|
|
|
this._button.hide();
|
2013-06-23 23:14:10 -04:00
|
|
|
return;
|
2011-10-11 13:34:04 -04:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
|
|
|
for (let i = 0; i < ids.length; i++) {
|
2019-01-31 15:08:00 +01:00
|
|
|
let [sessionName, sessionDescription_] = Gdm.get_session_name_and_description(ids[i]);
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2013-06-23 23:14:10 -04:00
|
|
|
let id = ids[i];
|
|
|
|
let item = new PopupMenu.PopupMenuItem(sessionName);
|
|
|
|
this._menu.addMenuItem(item);
|
|
|
|
this._items[id] = item;
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:38:18 +01:00
|
|
|
item.connect('activate', () => {
|
2013-06-23 23:14:10 -04:00
|
|
|
this.setActiveSession(id);
|
2014-11-13 09:26:52 -05:00
|
|
|
this.emit('session-activated', this._activeSessionId);
|
2017-10-31 01:38:18 +01:00
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
}
|
|
|
|
}
|
2019-07-16 11:24:13 +02:00
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2023-07-10 02:53:00 -07:00
|
|
|
export const LoginDialog = GObject.registerClass({
|
2019-11-28 18:22:55 -03:00
|
|
|
Signals: {
|
|
|
|
'failed': {},
|
|
|
|
'wake-up-screen': {},
|
|
|
|
},
|
2017-10-31 02:23:39 +01:00
|
|
|
}, class LoginDialog extends St.Widget {
|
2017-10-31 01:03:21 +01:00
|
|
|
_init(parentActor) {
|
2023-08-07 00:40:20 +02:00
|
|
|
super._init({style_class: 'login-dialog', visible: false});
|
2013-06-25 12:55:21 -04:00
|
|
|
|
2018-07-07 13:30:18 +02:00
|
|
|
this.get_accessible().set_role(Atk.Role.WINDOW);
|
|
|
|
|
2023-08-07 00:40:20 +02:00
|
|
|
this.add_constraint(new Layout.MonitorConstraint({primary: true}));
|
2018-07-07 13:30:18 +02:00
|
|
|
this.connect('destroy', this._onDestroy.bind(this));
|
|
|
|
parentActor.add_child(this);
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2019-01-29 02:18:52 +01:00
|
|
|
this._userManager = AccountsService.UserManager.get_default();
|
2015-01-22 13:39:46 -05:00
|
|
|
this._gdmClient = new Gdm.Client();
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-07-17 16:48:03 -04:00
|
|
|
try {
|
|
|
|
this._gdmClient.set_enabled_extensions([Gdm.UserVerifierChoiceList.interface_info().name]);
|
|
|
|
} catch (e) {
|
|
|
|
}
|
|
|
|
|
2023-08-07 00:40:20 +02:00
|
|
|
this._settings = new Gio.Settings({schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA});
|
2012-07-17 20:54:07 +02:00
|
|
|
|
2022-02-07 15:14:06 +01:00
|
|
|
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_KEY}`,
|
2023-08-07 01:45:22 +02:00
|
|
|
this._updateBanner.bind(this));
|
2022-02-07 15:14:06 +01:00
|
|
|
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_TEXT_KEY}`,
|
2023-08-07 01:45:22 +02:00
|
|
|
this._updateBanner.bind(this));
|
2022-02-07 15:14:06 +01:00
|
|
|
this._settings.connect(`changed::${GdmUtil.DISABLE_USER_LIST_KEY}`,
|
2023-08-07 01:45:22 +02:00
|
|
|
this._updateDisableUserList.bind(this));
|
2022-02-07 15:14:06 +01:00
|
|
|
this._settings.connect(`changed::${GdmUtil.LOGO_KEY}`,
|
2023-08-07 01:45:22 +02:00
|
|
|
this._updateLogo.bind(this));
|
2013-03-23 01:27:22 +01:00
|
|
|
|
|
|
|
this._textureCache = St.TextureCache.get_default();
|
2021-08-16 00:36:59 +02:00
|
|
|
this._textureCache.connectObject('texture-file-changed',
|
|
|
|
this._updateLogoTexture.bind(this), this);
|
2011-09-06 08:37:16 -04:00
|
|
|
|
2020-03-29 23:51:13 +02:00
|
|
|
this._userSelectionBox = new St.BoxLayout({
|
|
|
|
style_class: 'login-dialog-user-selection-box',
|
|
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
|
|
vertical: true,
|
|
|
|
visible: false,
|
|
|
|
});
|
2018-07-07 13:30:18 +02:00
|
|
|
this.add_child(this._userSelectionBox);
|
2013-02-06 16:37:47 -05:00
|
|
|
|
2012-10-04 18:31:50 +02:00
|
|
|
this._userList = new UserList();
|
2019-10-21 20:44:00 +02:00
|
|
|
this._userSelectionBox.add_child(this._userList);
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2015-01-22 13:39:46 -05:00
|
|
|
this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
|
2017-12-02 01:27:35 +01:00
|
|
|
this._authPrompt.connect('prompted', this._onPrompted.bind(this));
|
|
|
|
this._authPrompt.connect('reset', this._onReset.bind(this));
|
2013-07-15 17:56:44 -04:00
|
|
|
this._authPrompt.hide();
|
2019-07-16 11:24:13 +02:00
|
|
|
this.add_child(this._authPrompt);
|
2013-06-26 12:36:10 -04:00
|
|
|
|
2011-10-29 12:36:51 -04:00
|
|
|
// translators: this message is shown below the user list on the
|
|
|
|
// login screen. It can be activated to reveal an entry for
|
|
|
|
// manually entering the username.
|
2019-10-17 23:40:24 +02:00
|
|
|
let notListedLabel = new St.Label({
|
2023-08-07 00:34:20 +02:00
|
|
|
text: _('Not listed?'),
|
2019-10-17 23:40:24 +02:00
|
|
|
style_class: 'login-dialog-not-listed-label',
|
|
|
|
});
|
|
|
|
this._notListedButton = new St.Button({
|
|
|
|
style_class: 'login-dialog-not-listed-button',
|
|
|
|
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
|
|
|
|
can_focus: true,
|
|
|
|
child: notListedLabel,
|
|
|
|
reactive: true,
|
2020-02-25 18:15:49 +01:00
|
|
|
x_align: Clutter.ActorAlign.START,
|
2021-01-13 12:29:35 -08:00
|
|
|
label_actor: notListedLabel,
|
2019-10-17 23:40:24 +02:00
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-12-02 01:27:35 +01:00
|
|
|
this._notListedButton.connect('clicked', this._hideUserListAskForUsernameAndBeginVerification.bind(this));
|
2013-07-28 17:49:50 -04:00
|
|
|
|
2013-06-26 10:52:02 -04:00
|
|
|
this._notListedButton.hide();
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2019-10-21 20:44:00 +02:00
|
|
|
this._userSelectionBox.add_child(this._notListedButton);
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2023-11-07 10:47:14 +00:00
|
|
|
const bannerBox = new St.BoxLayout({vertical: true});
|
|
|
|
|
2020-03-29 23:51:13 +02:00
|
|
|
this._bannerView = new St.ScrollView({
|
|
|
|
style_class: 'login-dialog-banner-view',
|
|
|
|
opacity: 0,
|
2023-11-07 10:47:14 +00:00
|
|
|
child: bannerBox,
|
2020-03-29 23:51:13 +02:00
|
|
|
});
|
2018-07-07 13:30:18 +02:00
|
|
|
this.add_child(this._bannerView);
|
2014-11-11 09:11:01 -05:00
|
|
|
|
2020-03-29 23:51:13 +02:00
|
|
|
this._bannerLabel = new St.Label({
|
|
|
|
style_class: 'login-dialog-banner',
|
|
|
|
text: '',
|
|
|
|
});
|
2014-11-11 09:11:01 -05:00
|
|
|
this._bannerLabel.clutter_text.line_wrap = true;
|
|
|
|
this._bannerLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
|
|
|
bannerBox.add_child(this._bannerLabel);
|
|
|
|
this._updateBanner();
|
|
|
|
|
2020-01-16 12:13:29 +05:30
|
|
|
this._sessionMenuButton = new SessionMenuButton();
|
|
|
|
this._sessionMenuButton.connect('session-activated',
|
|
|
|
(list, sessionId) => {
|
|
|
|
this._greeter.call_select_session_sync(sessionId, null);
|
|
|
|
});
|
|
|
|
this._sessionMenuButton.opacity = 0;
|
|
|
|
this._sessionMenuButton.show();
|
|
|
|
this.add_child(this._sessionMenuButton);
|
|
|
|
|
2020-03-29 23:51:13 +02:00
|
|
|
this._logoBin = new St.Widget({
|
|
|
|
style_class: 'login-dialog-logo-bin',
|
|
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
|
|
y_align: Clutter.ActorAlign.END,
|
|
|
|
});
|
2017-11-30 02:34:42 +01:00
|
|
|
this._logoBin.connect('resource-scale-changed', () => {
|
|
|
|
this._updateLogoTexture(this._textureCache, this._logoFile);
|
|
|
|
});
|
2018-07-07 13:30:18 +02:00
|
|
|
this.add_child(this._logoBin);
|
2013-03-23 01:27:22 +01:00
|
|
|
this._updateLogo();
|
|
|
|
|
2017-10-31 01:38:18 +01:00
|
|
|
this._userList.connect('activate', (userList, item) => {
|
|
|
|
this._onUserListActivated(item);
|
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2014-03-07 16:04:01 +01:00
|
|
|
this._disableUserList = undefined;
|
|
|
|
this._userListLoaded = false;
|
|
|
|
|
2015-02-26 15:40:56 -05:00
|
|
|
this._realmManager = new Realmd.Manager();
|
2021-08-16 00:36:59 +02:00
|
|
|
this._realmManager.connectObject('login-format-changed',
|
|
|
|
this._showRealmLoginHint.bind(this), this);
|
2015-02-26 15:40:56 -05:00
|
|
|
|
2022-06-23 15:45:44 +02:00
|
|
|
this._getGreeterSessionProxy();
|
2014-03-07 19:35:02 -05:00
|
|
|
|
2014-03-07 16:04:01 +01:00
|
|
|
// If the user list is enabled, it should take key focus; make sure the
|
|
|
|
// screen shield is initialized first to prevent it from stealing the
|
|
|
|
// focus later
|
2021-08-16 00:36:59 +02:00
|
|
|
Main.layoutManager.connectObject('startup-complete',
|
|
|
|
this._updateDisableUserList.bind(this), this);
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2014-03-07 16:04:01 +01:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_getBannerAllocation(dialogBox) {
|
2014-11-11 09:11:01 -05:00
|
|
|
let actorBox = new Clutter.ActorBox();
|
|
|
|
|
2019-02-01 14:41:55 +01:00
|
|
|
let [, , natWidth, natHeight] = this._bannerView.get_preferred_size();
|
2014-11-11 09:11:01 -05:00
|
|
|
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
|
|
|
|
|
2015-03-27 22:19:47 +01:00
|
|
|
actorBox.x1 = Math.floor(centerX - natWidth / 2);
|
2014-11-11 09:11:01 -05:00
|
|
|
actorBox.y1 = dialogBox.y1 + Main.layoutManager.panelBox.height;
|
|
|
|
actorBox.x2 = actorBox.x1 + natWidth;
|
|
|
|
actorBox.y2 = actorBox.y1 + natHeight;
|
|
|
|
|
|
|
|
return actorBox;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2014-11-11 09:11:01 -05:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_getLogoBinAllocation(dialogBox) {
|
2014-11-10 14:36:07 -05:00
|
|
|
let actorBox = new Clutter.ActorBox();
|
|
|
|
|
2019-02-01 14:41:55 +01:00
|
|
|
let [, , natWidth, natHeight] = this._logoBin.get_preferred_size();
|
2014-11-10 14:36:07 -05:00
|
|
|
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
|
|
|
|
|
2015-03-27 22:19:47 +01:00
|
|
|
actorBox.x1 = Math.floor(centerX - natWidth / 2);
|
2014-11-10 14:36:07 -05:00
|
|
|
actorBox.y1 = dialogBox.y2 - natHeight;
|
|
|
|
actorBox.x2 = actorBox.x1 + natWidth;
|
|
|
|
actorBox.y2 = actorBox.y1 + natHeight;
|
|
|
|
|
|
|
|
return actorBox;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2014-11-10 14:36:07 -05:00
|
|
|
|
2020-01-16 12:13:29 +05:30
|
|
|
_getSessionMenuButtonAllocation(dialogBox) {
|
|
|
|
let actorBox = new Clutter.ActorBox();
|
|
|
|
|
|
|
|
let [, , natWidth, natHeight] = this._sessionMenuButton.get_preferred_size();
|
|
|
|
|
|
|
|
if (this.get_text_direction() === Clutter.TextDirection.RTL)
|
|
|
|
actorBox.x1 = dialogBox.x1 + natWidth;
|
|
|
|
else
|
|
|
|
actorBox.x1 = dialogBox.x2 - (natWidth * 2);
|
|
|
|
|
|
|
|
actorBox.y1 = dialogBox.y2 - (natHeight * 2);
|
|
|
|
actorBox.x2 = actorBox.x1 + natWidth;
|
|
|
|
actorBox.y2 = actorBox.y1 + natHeight;
|
|
|
|
|
|
|
|
return actorBox;
|
|
|
|
}
|
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_getCenterActorAllocation(dialogBox, actor) {
|
2014-11-10 14:36:07 -05:00
|
|
|
let actorBox = new Clutter.ActorBox();
|
|
|
|
|
2019-02-01 14:41:55 +01:00
|
|
|
let [, , natWidth, natHeight] = actor.get_preferred_size();
|
2014-11-10 14:36:07 -05:00
|
|
|
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
|
|
|
|
let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
|
|
|
|
|
2015-07-10 18:58:05 +02:00
|
|
|
natWidth = Math.min(natWidth, dialogBox.x2 - dialogBox.x1);
|
|
|
|
natHeight = Math.min(natHeight, dialogBox.y2 - dialogBox.y1);
|
|
|
|
|
2015-03-27 22:19:47 +01:00
|
|
|
actorBox.x1 = Math.floor(centerX - natWidth / 2);
|
|
|
|
actorBox.y1 = Math.floor(centerY - natHeight / 2);
|
2014-11-10 14:36:07 -05:00
|
|
|
actorBox.x2 = actorBox.x1 + natWidth;
|
|
|
|
actorBox.y2 = actorBox.y1 + natHeight;
|
|
|
|
|
|
|
|
return actorBox;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2014-11-10 14:36:07 -05:00
|
|
|
|
2020-05-09 21:30:26 +02:00
|
|
|
vfunc_allocate(dialogBox) {
|
|
|
|
this.set_allocation(dialogBox);
|
2018-07-07 13:30:18 +02:00
|
|
|
|
|
|
|
let themeNode = this.get_theme_node();
|
|
|
|
dialogBox = themeNode.get_content_box(dialogBox);
|
|
|
|
|
2014-11-11 09:11:01 -05:00
|
|
|
let dialogWidth = dialogBox.x2 - dialogBox.x1;
|
2014-11-10 14:36:07 -05:00
|
|
|
let dialogHeight = dialogBox.y2 - dialogBox.y1;
|
|
|
|
|
|
|
|
// First find out what space the children require
|
2014-11-11 09:11:01 -05:00
|
|
|
let bannerAllocation = null;
|
|
|
|
let bannerHeight = 0;
|
|
|
|
if (this._bannerView.visible) {
|
2021-10-30 15:22:25 -07:00
|
|
|
bannerAllocation = this._getBannerAllocation(dialogBox);
|
2014-11-11 09:11:01 -05:00
|
|
|
bannerHeight = bannerAllocation.y2 - bannerAllocation.y1;
|
|
|
|
}
|
|
|
|
|
2014-11-10 14:36:07 -05:00
|
|
|
let authPromptAllocation = null;
|
2014-11-11 09:11:01 -05:00
|
|
|
let authPromptWidth = 0;
|
2019-07-16 11:24:13 +02:00
|
|
|
if (this._authPrompt.visible) {
|
|
|
|
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt);
|
2014-11-11 09:11:01 -05:00
|
|
|
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
|
2014-11-11 09:11:01 -05:00
|
|
|
}
|
2014-11-10 14:36:07 -05:00
|
|
|
|
|
|
|
let userSelectionAllocation = null;
|
|
|
|
let userSelectionHeight = 0;
|
|
|
|
if (this._userSelectionBox.visible) {
|
|
|
|
userSelectionAllocation = this._getCenterActorAllocation(dialogBox, this._userSelectionBox);
|
|
|
|
userSelectionHeight = userSelectionAllocation.y2 - userSelectionAllocation.y1;
|
|
|
|
}
|
|
|
|
|
|
|
|
let logoAllocation = null;
|
|
|
|
let logoHeight = 0;
|
|
|
|
if (this._logoBin.visible) {
|
|
|
|
logoAllocation = this._getLogoBinAllocation(dialogBox);
|
|
|
|
logoHeight = logoAllocation.y2 - logoAllocation.y1;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:13:29 +05:30
|
|
|
let sessionMenuButtonAllocation = null;
|
|
|
|
if (this._sessionMenuButton.visible)
|
|
|
|
sessionMenuButtonAllocation = this._getSessionMenuButtonAllocation(dialogBox);
|
|
|
|
|
2014-11-11 09:11:01 -05:00
|
|
|
// Then figure out if we're overly constrained and need to
|
|
|
|
// try a different layout, or if we have what extra space we
|
|
|
|
// can hand out
|
2014-11-11 09:11:01 -05:00
|
|
|
if (bannerAllocation) {
|
2015-06-25 15:39:58 -04:00
|
|
|
let bannerSpace;
|
|
|
|
|
|
|
|
if (authPromptAllocation)
|
|
|
|
bannerSpace = authPromptAllocation.y1 - bannerAllocation.y1;
|
|
|
|
else
|
|
|
|
bannerSpace = 0;
|
|
|
|
|
|
|
|
let leftOverYSpace = bannerSpace - bannerHeight;
|
2014-11-11 09:11:01 -05:00
|
|
|
|
|
|
|
if (leftOverYSpace > 0) {
|
2019-01-29 20:36:54 +01:00
|
|
|
// First figure out how much left over space is up top
|
|
|
|
let leftOverTopSpace = leftOverYSpace / 2;
|
2014-11-10 14:36:07 -05:00
|
|
|
|
2019-01-29 20:36:54 +01:00
|
|
|
// Then, shift the banner into the middle of that extra space
|
|
|
|
let yShift = Math.floor(leftOverTopSpace / 2);
|
2014-11-11 09:11:01 -05:00
|
|
|
|
2019-01-29 20:36:54 +01:00
|
|
|
bannerAllocation.y1 += yShift;
|
|
|
|
bannerAllocation.y2 += yShift;
|
2014-11-11 09:11:01 -05:00
|
|
|
} else {
|
2019-01-29 20:36:54 +01:00
|
|
|
// Then figure out how much space there would be if we switched to a
|
|
|
|
// wide layout with banner on one side and authprompt on the other.
|
|
|
|
let leftOverXSpace = dialogWidth - authPromptWidth;
|
|
|
|
|
|
|
|
// In a wide view, half of the available space goes to the banner,
|
|
|
|
// and the other half goes to the margins.
|
|
|
|
let wideBannerWidth = leftOverXSpace / 2;
|
|
|
|
let wideSpacing = leftOverXSpace - wideBannerWidth;
|
|
|
|
|
|
|
|
// If we do go with a wide layout, we need there to be at least enough
|
|
|
|
// space for the banner and the auth prompt to be the same width,
|
|
|
|
// so it doesn't look unbalanced.
|
|
|
|
if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
|
|
|
|
let centerX = dialogBox.x1 + dialogWidth / 2;
|
|
|
|
let centerY = dialogBox.y1 + dialogHeight / 2;
|
|
|
|
|
|
|
|
// A small portion of the spacing goes down the center of the
|
|
|
|
// screen to help delimit the two columns of the wide view
|
|
|
|
let centerGap = wideSpacing / 8;
|
|
|
|
|
|
|
|
// place the banner along the left edge of the center margin
|
|
|
|
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
|
|
|
|
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
|
|
|
|
|
|
|
|
// figure out how tall it would like to be and try to accommodate
|
|
|
|
// but don't let it get too close to the logo
|
2019-02-01 14:41:55 +01:00
|
|
|
let [, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
|
2019-01-29 20:36:54 +01:00
|
|
|
|
|
|
|
let maxWideHeight = dialogHeight - 3 * logoHeight;
|
|
|
|
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
|
|
|
|
bannerAllocation.y1 = Math.floor(centerY - wideBannerHeight / 2);
|
|
|
|
bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
|
|
|
|
|
|
|
|
// place the auth prompt along the right edge of the center margin
|
|
|
|
authPromptAllocation.x1 = Math.floor(centerX + centerGap / 2);
|
|
|
|
authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
|
|
|
|
} else {
|
|
|
|
// If we aren't going to do a wide view, then we need to limit
|
|
|
|
// the height of the banner so it will present scrollbars
|
|
|
|
|
|
|
|
// First figure out how much space there is without the banner
|
|
|
|
leftOverYSpace += bannerHeight;
|
|
|
|
|
|
|
|
// Then figure out how much of that space is up top
|
|
|
|
let availableTopSpace = Math.floor(leftOverYSpace / 2);
|
|
|
|
|
|
|
|
// Then give all of that space to the banner
|
|
|
|
bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
|
|
|
|
}
|
2014-11-11 09:11:01 -05:00
|
|
|
}
|
|
|
|
} else if (userSelectionAllocation) {
|
|
|
|
// Grow the user list to fill the space
|
|
|
|
let leftOverYSpace = dialogHeight - userSelectionHeight - logoHeight;
|
2014-11-10 14:36:07 -05:00
|
|
|
|
2014-11-11 09:11:01 -05:00
|
|
|
if (leftOverYSpace > 0) {
|
2015-03-27 22:19:47 +01:00
|
|
|
let topExpansion = Math.floor(leftOverYSpace / 2);
|
2014-11-10 14:36:07 -05:00
|
|
|
let bottomExpansion = topExpansion;
|
|
|
|
|
|
|
|
userSelectionAllocation.y1 -= topExpansion;
|
|
|
|
userSelectionAllocation.y2 += bottomExpansion;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally hand out the allocations
|
2019-08-20 02:51:42 +02:00
|
|
|
if (bannerAllocation)
|
2020-05-09 21:30:26 +02:00
|
|
|
this._bannerView.allocate(bannerAllocation);
|
2014-11-11 09:11:01 -05:00
|
|
|
|
2014-11-10 14:36:07 -05:00
|
|
|
if (authPromptAllocation)
|
2020-05-09 21:30:26 +02:00
|
|
|
this._authPrompt.allocate(authPromptAllocation);
|
2014-11-10 14:36:07 -05:00
|
|
|
|
|
|
|
if (userSelectionAllocation)
|
2020-05-09 21:30:26 +02:00
|
|
|
this._userSelectionBox.allocate(userSelectionAllocation);
|
2014-11-10 14:36:07 -05:00
|
|
|
|
|
|
|
if (logoAllocation)
|
2020-05-09 21:30:26 +02:00
|
|
|
this._logoBin.allocate(logoAllocation);
|
2020-01-16 12:13:29 +05:30
|
|
|
|
|
|
|
if (sessionMenuButtonAllocation)
|
2020-05-09 21:30:26 +02:00
|
|
|
this._sessionMenuButton.allocate(sessionMenuButtonAllocation);
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2014-11-10 14:36:07 -05:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_ensureUserListLoaded() {
|
2014-04-10 19:26:52 +02:00
|
|
|
if (!this._userManager.is_loaded) {
|
2021-08-16 00:36:59 +02:00
|
|
|
this._userManager.connectObject('notify::is-loaded',
|
2017-10-31 01:38:18 +01:00
|
|
|
() => {
|
|
|
|
if (this._userManager.is_loaded) {
|
2021-08-16 00:36:59 +02:00
|
|
|
this._userManager.disconnectObject(this);
|
2017-10-31 01:38:18 +01:00
|
|
|
this._loadUserList();
|
|
|
|
}
|
|
|
|
});
|
2014-04-10 19:26:52 +02:00
|
|
|
} else {
|
2017-12-02 01:27:35 +01:00
|
|
|
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._loadUserList.bind(this));
|
2014-04-10 19:26:52 +02:00
|
|
|
GLib.Source.set_name_by_id(id, '[gnome-shell] _loadUserList');
|
|
|
|
}
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-09-06 16:17:08 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_updateDisableUserList() {
|
2012-10-30 13:26:30 -04:00
|
|
|
let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
|
|
|
|
|
2017-07-07 14:47:23 +08:00
|
|
|
// Disable user list when there are no users.
|
2023-08-07 02:51:19 +02:00
|
|
|
if (this._userListLoaded && this._userList.numItems() === 0)
|
2017-07-07 14:47:23 +08:00
|
|
|
disableUserList = true;
|
|
|
|
|
2023-08-07 02:51:19 +02:00
|
|
|
if (disableUserList !== this._disableUserList) {
|
2012-10-30 13:26:30 -04:00
|
|
|
this._disableUserList = disableUserList;
|
|
|
|
|
2023-08-07 02:51:19 +02:00
|
|
|
if (this._authPrompt.verificationStatus === AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
2013-07-28 15:55:09 -04:00
|
|
|
this._authPrompt.reset();
|
2021-04-13 10:59:49 -04:00
|
|
|
|
|
|
|
if (this._disableUserList && this._timedLoginUserListHold)
|
|
|
|
this._timedLoginUserListHold.release();
|
2012-10-30 13:26:30 -04:00
|
|
|
}
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2012-10-30 13:26:30 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_updateCancelButton() {
|
2013-07-28 20:55:12 -04:00
|
|
|
let cancelVisible;
|
|
|
|
|
|
|
|
// Hide the cancel button if the user list is disabled and we're asking for
|
|
|
|
// a username
|
2023-08-07 02:51:19 +02:00
|
|
|
if (this._authPrompt.verificationStatus === AuthPrompt.AuthPromptStatus.NOT_VERIFYING &&
|
|
|
|
this._disableUserList)
|
2013-07-28 20:55:12 -04:00
|
|
|
cancelVisible = false;
|
|
|
|
else
|
|
|
|
cancelVisible = true;
|
|
|
|
|
|
|
|
this._authPrompt.cancelButton.visible = cancelVisible;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-07-28 20:55:12 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_updateBanner() {
|
2012-07-17 20:54:07 +02:00
|
|
|
let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
|
|
|
|
let text = this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY);
|
2012-07-05 21:11:22 -04:00
|
|
|
|
|
|
|
if (enabled && text) {
|
|
|
|
this._bannerLabel.set_text(text);
|
2013-02-04 16:50:46 -05:00
|
|
|
this._bannerLabel.show();
|
2012-07-05 21:11:22 -04:00
|
|
|
} else {
|
2013-02-04 16:50:46 -05:00
|
|
|
this._bannerLabel.hide();
|
2012-07-05 21:11:22 -04:00
|
|
|
}
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2012-07-05 21:11:22 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_fadeInBannerView() {
|
2015-01-22 14:00:01 -05:00
|
|
|
this._bannerView.show();
|
2018-07-20 21:46:19 +02:00
|
|
|
this._bannerView.ease({
|
|
|
|
opacity: 255,
|
|
|
|
duration: _FADE_ANIMATION_TIME,
|
2019-08-20 23:43:54 +02:00
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
2018-07-20 21:46:19 +02:00
|
|
|
});
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2014-11-11 09:11:01 -05:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_hideBannerView() {
|
2018-07-20 21:46:19 +02:00
|
|
|
this._bannerView.remove_all_transitions();
|
2014-11-11 09:11:01 -05:00
|
|
|
this._bannerView.opacity = 0;
|
2015-01-22 14:00:01 -05:00
|
|
|
this._bannerView.hide();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2014-11-11 09:11:01 -05:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_updateLogoTexture(cache, file) {
|
2014-10-14 19:59:29 -07:00
|
|
|
if (this._logoFile && !this._logoFile.equal(file))
|
2013-03-23 01:27:22 +01:00
|
|
|
return;
|
|
|
|
|
2013-08-26 15:47:52 -04:00
|
|
|
this._logoBin.destroy_all_children();
|
2020-05-28 14:47:17 +02:00
|
|
|
const resourceScale = this._logoBin.get_resource_scale();
|
|
|
|
if (this._logoFile) {
|
2023-08-07 01:45:22 +02:00
|
|
|
const scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
|
|
|
const texture = this._textureCache.load_file_async(
|
|
|
|
this._logoFile,
|
|
|
|
-1, -1,
|
|
|
|
scaleFactor, resourceScale);
|
|
|
|
this._logoBin.add_child(texture);
|
2014-03-22 21:05:53 -07:00
|
|
|
}
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-03-23 01:27:22 +01:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_updateLogo() {
|
2013-03-23 01:27:22 +01:00
|
|
|
let path = this._settings.get_string(GdmUtil.LOGO_KEY);
|
|
|
|
|
2014-09-18 17:04:00 -07:00
|
|
|
this._logoFile = path ? Gio.file_new_for_path(path) : null;
|
|
|
|
this._updateLogoTexture(this._textureCache, this._logoFile);
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-03-23 01:27:22 +01:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_onPrompted() {
|
2020-01-16 12:13:29 +05:30
|
|
|
const showSessionMenu = this._shouldShowSessionMenuButton();
|
|
|
|
|
|
|
|
this._sessionMenuButton.updateSensitivity(showSessionMenu);
|
|
|
|
this._sessionMenuButton.visible = showSessionMenu;
|
2013-07-22 11:07:35 -04:00
|
|
|
this._showPrompt();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-07-22 11:07:35 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_resetGreeterProxy() {
|
2023-08-07 02:51:19 +02:00
|
|
|
if (GLib.getenv('GDM_GREETER_TEST') !== '1') {
|
2019-08-20 02:51:42 +02:00
|
|
|
if (this._greeter)
|
2015-01-22 13:39:46 -05:00
|
|
|
this._greeter.run_dispose();
|
2019-08-20 02:51:42 +02:00
|
|
|
|
2015-01-22 13:39:46 -05:00
|
|
|
this._greeter = this._gdmClient.get_greeter_sync(null);
|
|
|
|
|
2021-08-16 00:36:59 +02:00
|
|
|
this._greeter.connectObject(
|
|
|
|
'default-session-name-changed', this._onDefaultSessionChanged.bind(this),
|
|
|
|
'session-opened', this._onSessionOpened.bind(this),
|
|
|
|
'timed-login-requested', this._onTimedLoginRequested.bind(this), this);
|
2015-01-22 13:39:46 -05:00
|
|
|
}
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2015-01-22 13:39:46 -05:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_onReset(authPrompt, beginRequest) {
|
2015-01-22 13:39:46 -05:00
|
|
|
this._resetGreeterProxy();
|
2013-07-22 11:07:35 -04:00
|
|
|
this._sessionMenuButton.updateSensitivity(true);
|
2013-07-15 17:56:44 -04:00
|
|
|
|
2021-02-01 13:10:45 +01:00
|
|
|
const previousUser = this._user;
|
2011-08-23 22:12:57 -04:00
|
|
|
this._user = null;
|
|
|
|
|
loginDialog: fix cancel button in ask for username mode
If the user clicks Not Listed? to enter ask for username mode, clicks
cancel, and then attempts to log in via the user list, the user will see
"Authentication failed" after correctly typing the password, and then
will become stuck in an empty screen with just the gray noise background.
The problem is, we forgot to disconnect from the signal that's waiting
for the next button to be pressed on the username entry screen. Since
the signal handler that executes here is expecting the username to be
input, and isn't prepared for us to have switched back to user list,
various bad things happen. We try to start two gdm-password
conversations at once, for instance, one using the user's password as
the username. I stopped investigating here, because it's easy to fix by
disconnecting from the signal at the right time.
https://bugzilla.gnome.org/show_bug.cgi?id=770328
2016-09-10 12:55:20 -05:00
|
|
|
if (this._nextSignalId) {
|
|
|
|
this._authPrompt.disconnect(this._nextSignalId);
|
|
|
|
this._nextSignalId = 0;
|
|
|
|
}
|
|
|
|
|
2021-02-01 13:10:45 +01:00
|
|
|
if (previousUser && beginRequest === AuthPrompt.BeginRequestType.REUSE_USERNAME) {
|
|
|
|
this._user = previousUser;
|
|
|
|
this._authPrompt.setUser(this._user);
|
2023-08-07 00:40:20 +02:00
|
|
|
this._authPrompt.begin({userName: previousUser.get_user_name()});
|
2021-02-01 13:10:45 +01:00
|
|
|
} else if (beginRequest === AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
|
2013-08-22 16:18:20 -04:00
|
|
|
if (!this._disableUserList)
|
|
|
|
this._showUserList();
|
|
|
|
else
|
|
|
|
this._hideUserListAskForUsernameAndBeginVerification();
|
|
|
|
} else {
|
2013-08-22 15:12:46 -04:00
|
|
|
this._hideUserListAndBeginVerification();
|
2013-08-22 16:18:20 -04:00
|
|
|
}
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_onDefaultSessionChanged(client, sessionId) {
|
2015-03-18 12:43:58 -04:00
|
|
|
this._sessionMenuButton.setActiveSession(sessionId);
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_shouldShowSessionMenuButton() {
|
2023-08-07 02:51:19 +02:00
|
|
|
if (this._authPrompt.verificationStatus !== AuthPrompt.AuthPromptStatus.VERIFYING &&
|
|
|
|
this._authPrompt.verificationStatus !== AuthPrompt.AuthPromptStatus.VERIFICATION_FAILED)
|
2019-01-29 20:36:54 +01:00
|
|
|
return false;
|
2013-06-25 13:35:38 -04:00
|
|
|
|
2013-08-22 16:18:20 -04:00
|
|
|
if (this._user && this._user.is_loaded && this._user.is_logged_in())
|
2019-01-29 20:36:54 +01:00
|
|
|
return false;
|
2013-06-25 13:35:38 -04:00
|
|
|
|
|
|
|
return true;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-06-25 13:35:38 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_showPrompt() {
|
2019-07-16 11:24:13 +02:00
|
|
|
if (this._authPrompt.visible)
|
2013-07-22 11:07:35 -04:00
|
|
|
return;
|
2019-07-16 11:24:13 +02:00
|
|
|
this._authPrompt.opacity = 0;
|
|
|
|
this._authPrompt.show();
|
|
|
|
this._authPrompt.ease({
|
2018-07-20 21:46:19 +02:00
|
|
|
opacity: 255,
|
|
|
|
duration: _FADE_ANIMATION_TIME,
|
2019-08-20 23:43:54 +02:00
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
2018-07-20 21:46:19 +02:00
|
|
|
});
|
2014-11-11 09:11:01 -05:00
|
|
|
this._fadeInBannerView();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_showRealmLoginHint(realmManager, hint) {
|
2013-04-19 09:07:04 +02:00
|
|
|
if (!hint)
|
|
|
|
return;
|
|
|
|
|
|
|
|
hint = hint.replace(/%U/g, 'user');
|
|
|
|
hint = hint.replace(/%D/g, 'DOMAIN');
|
|
|
|
hint = hint.replace(/%[^UD]/g, '');
|
|
|
|
|
|
|
|
// Translators: this message is shown below the username entry field
|
|
|
|
// to clue the user in on how to login to the local network realm
|
2023-08-07 00:34:20 +02:00
|
|
|
this._authPrompt.setMessage(_('(e.g., user or %s)').format(hint), GdmUtil.MessageType.HINT);
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-04-19 09:07:04 +02:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_askForUsernameAndBeginVerification() {
|
2020-02-06 16:24:32 -03:00
|
|
|
this._authPrompt.setUser(null);
|
2020-02-14 22:11:27 +01:00
|
|
|
this._authPrompt.setQuestion(_('Username'));
|
2012-10-30 15:06:44 -04:00
|
|
|
|
2015-02-26 15:40:56 -05:00
|
|
|
this._showRealmLoginHint(this._realmManager.loginFormat);
|
|
|
|
|
|
|
|
if (this._nextSignalId)
|
|
|
|
this._authPrompt.disconnect(this._nextSignalId);
|
|
|
|
this._nextSignalId = this._authPrompt.connect('next',
|
2017-10-31 01:38:18 +01:00
|
|
|
() => {
|
|
|
|
this._authPrompt.disconnect(this._nextSignalId);
|
|
|
|
this._nextSignalId = 0;
|
|
|
|
this._authPrompt.updateSensitivity(false);
|
|
|
|
let answer = this._authPrompt.getAnswer();
|
|
|
|
this._user = this._userManager.get_user(answer);
|
|
|
|
this._authPrompt.clear();
|
2023-08-07 00:40:20 +02:00
|
|
|
this._authPrompt.begin({userName: answer});
|
2017-10-31 01:38:18 +01:00
|
|
|
this._updateCancelButton();
|
|
|
|
});
|
2013-07-28 20:55:12 -04:00
|
|
|
this._updateCancelButton();
|
2014-10-07 14:30:34 -04:00
|
|
|
|
2017-04-19 13:29:59 +08:00
|
|
|
this._sessionMenuButton.updateSensitivity(false);
|
2014-10-07 14:30:34 -04:00
|
|
|
this._authPrompt.updateSensitivity(true);
|
2013-07-22 11:07:35 -04:00
|
|
|
this._showPrompt();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2012-10-30 15:06:44 -04:00
|
|
|
|
2019-07-26 01:13:59 +00:00
|
|
|
_bindOpacity() {
|
|
|
|
this._bindings = Main.layoutManager.uiGroup.get_children()
|
2023-08-07 02:51:19 +02:00
|
|
|
.filter(c => c !== Main.layoutManager.screenShieldGroup)
|
2019-07-26 01:13:59 +00:00
|
|
|
.map(c => this.bind_property('opacity', c, 'opacity', 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
_unbindOpacity() {
|
|
|
|
this._bindings.forEach(b => b.unbind());
|
|
|
|
}
|
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_loginScreenSessionActivated() {
|
2023-08-07 02:51:19 +02:00
|
|
|
if (this.opacity === 255 &&
|
|
|
|
this._authPrompt.verificationStatus === AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
2014-03-07 19:35:02 -05:00
|
|
|
return;
|
|
|
|
|
2020-07-27 10:58:49 -04:00
|
|
|
if (this._authPrompt.verificationStatus !== AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
|
|
|
this._authPrompt.reset();
|
|
|
|
|
2019-07-26 01:13:59 +00:00
|
|
|
this._bindOpacity();
|
2019-09-20 13:09:13 +02:00
|
|
|
this.ease({
|
2018-07-20 21:46:19 +02:00
|
|
|
opacity: 255,
|
|
|
|
duration: _FADE_ANIMATION_TIME,
|
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
2020-07-27 10:58:49 -04:00
|
|
|
onComplete: () => this._unbindOpacity(),
|
2018-07-20 21:46:19 +02:00
|
|
|
});
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2014-03-07 19:35:02 -05:00
|
|
|
|
2022-06-23 15:45:44 +02:00
|
|
|
async _getGreeterSessionProxy() {
|
|
|
|
const loginManager = LoginManager.getLoginManager();
|
|
|
|
this._greeterSessionProxy = await loginManager.getCurrentSessionProxy();
|
2022-08-08 13:33:53 +02:00
|
|
|
this._greeterSessionProxy?.connectObject('g-properties-changed', (proxy, properties) => {
|
|
|
|
const activeChanged = !!properties.lookup_value('Active', null);
|
|
|
|
if (activeChanged && proxy.Active)
|
2021-08-16 00:36:59 +02:00
|
|
|
this._loginScreenSessionActivated();
|
|
|
|
}, this);
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2014-03-07 19:35:02 -05:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_startSession(serviceName) {
|
2019-07-26 01:13:59 +00:00
|
|
|
this._bindOpacity();
|
2019-09-20 13:09:13 +02:00
|
|
|
this.ease({
|
2018-07-20 21:46:19 +02:00
|
|
|
opacity: 0,
|
|
|
|
duration: _FADE_ANIMATION_TIME,
|
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
|
|
onComplete: () => {
|
|
|
|
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
|
|
|
|
this._unbindOpacity();
|
2019-08-20 23:43:54 +02:00
|
|
|
},
|
2018-07-20 21:46:19 +02:00
|
|
|
});
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_onSessionOpened(client, serviceName) {
|
2019-01-28 01:42:00 +01:00
|
|
|
this._authPrompt.finish(() => this._startSession(serviceName));
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-03-18 00:59:56 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_waitForItemForUser(userName) {
|
2011-08-23 22:12:57 -04:00
|
|
|
let item = this._userList.getItemFromUserName(userName);
|
|
|
|
|
|
|
|
if (item)
|
2019-01-29 20:36:54 +01:00
|
|
|
return null;
|
2011-08-23 22:12:57 -04:00
|
|
|
|
|
|
|
let hold = new Batch.Hold();
|
|
|
|
let signalId = this._userList.connect('item-added',
|
2017-10-31 01:38:18 +01:00
|
|
|
() => {
|
2019-08-20 02:20:08 +02:00
|
|
|
item = this._userList.getItemFromUserName(userName);
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:38:18 +01:00
|
|
|
if (item)
|
|
|
|
hold.release();
|
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2019-01-28 01:42:00 +01:00
|
|
|
hold.connect('release', () => this._userList.disconnect(signalId));
|
2011-08-23 22:12:57 -04:00
|
|
|
|
|
|
|
return hold;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_blockTimedLoginUntilIdle() {
|
2011-08-23 22:12:57 -04:00
|
|
|
let hold = new Batch.Hold();
|
|
|
|
|
2018-04-17 16:43:06 +02:00
|
|
|
this._timedLoginIdleTimeOutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, _TIMED_LOGIN_IDLE_THRESHOLD,
|
2017-10-31 01:38:18 +01:00
|
|
|
() => {
|
2018-04-17 14:51:20 +02:00
|
|
|
this._timedLoginIdleTimeOutId = 0;
|
2017-10-31 01:38:18 +01:00
|
|
|
hold.release();
|
|
|
|
return GLib.SOURCE_REMOVE;
|
|
|
|
});
|
2018-04-17 23:09:31 +02:00
|
|
|
GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] this._timedLoginIdleTimeOutId');
|
2011-08-23 22:12:57 -04:00
|
|
|
return hold;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_startTimedLogin(userName, delay) {
|
2018-04-17 15:04:04 +02:00
|
|
|
let firstRun = true;
|
|
|
|
|
2018-04-17 14:38:36 +02:00
|
|
|
// Cancel execution of old batch
|
|
|
|
if (this._timedLoginBatch) {
|
|
|
|
this._timedLoginBatch.cancel();
|
|
|
|
this._timedLoginBatch = null;
|
2018-04-17 15:04:04 +02:00
|
|
|
firstRun = false;
|
2018-04-17 14:38:36 +02:00
|
|
|
}
|
|
|
|
|
2018-04-17 14:51:20 +02:00
|
|
|
// Reset previous idle-timeout
|
|
|
|
if (this._timedLoginIdleTimeOutId) {
|
|
|
|
GLib.source_remove(this._timedLoginIdleTimeOutId);
|
|
|
|
this._timedLoginIdleTimeOutId = 0;
|
|
|
|
}
|
|
|
|
|
2018-04-17 15:19:44 +02:00
|
|
|
let loginItem = null;
|
|
|
|
let animationTime;
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2021-04-14 09:31:40 -04:00
|
|
|
let tasks = [
|
2021-04-13 10:59:49 -04:00
|
|
|
() => {
|
|
|
|
if (this._disableUserList)
|
2022-01-18 23:46:57 +01:00
|
|
|
return null;
|
2021-04-13 10:59:49 -04:00
|
|
|
|
|
|
|
this._timedLoginUserListHold = this._waitForItemForUser(userName);
|
2022-01-18 23:46:57 +01:00
|
|
|
return this._timedLoginUserListHold;
|
2021-04-13 10:59:49 -04:00
|
|
|
},
|
2021-04-14 09:31:40 -04:00
|
|
|
|
|
|
|
() => {
|
2021-04-13 10:59:49 -04:00
|
|
|
this._timedLoginUserListHold = null;
|
|
|
|
|
|
|
|
if (this._disableUserList)
|
|
|
|
loginItem = this._authPrompt;
|
|
|
|
else
|
|
|
|
loginItem = this._userList.getItemFromUserName(userName);
|
2021-04-14 09:31:40 -04:00
|
|
|
|
|
|
|
// If there is an animation running on the item, reset it.
|
|
|
|
loginItem.hideTimedLoginIndicator();
|
|
|
|
},
|
|
|
|
|
|
|
|
() => {
|
2021-04-13 10:59:49 -04:00
|
|
|
if (this._disableUserList)
|
|
|
|
return;
|
|
|
|
|
2021-04-14 09:31:40 -04:00
|
|
|
// If we're just starting out, start on the right item.
|
|
|
|
if (!this._userManager.is_loaded)
|
|
|
|
this._userList.jumpToItem(loginItem);
|
|
|
|
},
|
|
|
|
|
|
|
|
() => {
|
|
|
|
// This blocks the timed login animation until a few
|
|
|
|
// seconds after the user stops interacting with the
|
|
|
|
// login screen.
|
|
|
|
|
|
|
|
// We skip this step if the timed login delay is very short.
|
|
|
|
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD) {
|
|
|
|
animationTime = delay - _TIMED_LOGIN_IDLE_THRESHOLD;
|
|
|
|
return this._blockTimedLoginUntilIdle();
|
|
|
|
} else {
|
|
|
|
animationTime = delay;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
() => {
|
2021-04-13 10:59:49 -04:00
|
|
|
if (this._disableUserList)
|
|
|
|
return;
|
|
|
|
|
2021-04-14 09:31:40 -04:00
|
|
|
// If idle timeout is done, make sure the timed login indicator is shown
|
|
|
|
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD &&
|
|
|
|
this._authPrompt.visible)
|
|
|
|
this._authPrompt.cancel();
|
|
|
|
|
|
|
|
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD || firstRun) {
|
|
|
|
this._userList.scrollToItem(loginItem);
|
|
|
|
loginItem.grab_key_focus();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
() => loginItem.showTimedLoginIndicator(animationTime),
|
|
|
|
|
|
|
|
() => {
|
|
|
|
this._timedLoginBatch = null;
|
|
|
|
this._greeter.call_begin_auto_login_sync(userName, null);
|
|
|
|
},
|
|
|
|
];
|
2011-08-23 22:12:57 -04:00
|
|
|
|
|
|
|
this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks);
|
|
|
|
|
|
|
|
return this._timedLoginBatch.run();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_onTimedLoginRequested(client, userName, seconds) {
|
2018-04-17 22:51:40 +02:00
|
|
|
if (this._timedLoginBatch)
|
|
|
|
return;
|
|
|
|
|
2011-08-23 22:12:57 -04:00
|
|
|
this._startTimedLogin(userName, seconds);
|
|
|
|
|
2018-04-17 14:30:05 +02:00
|
|
|
// Restart timed login on user interaction
|
2017-10-31 01:38:18 +01:00
|
|
|
global.stage.connect('captured-event', (actor, event) => {
|
2023-08-07 02:51:19 +02:00
|
|
|
if (event.type() === Clutter.EventType.KEY_PRESS ||
|
|
|
|
event.type() === Clutter.EventType.BUTTON_PRESS)
|
2019-01-29 20:36:54 +01:00
|
|
|
this._startTimedLogin(userName, seconds);
|
2017-10-31 01:38:18 +01:00
|
|
|
|
2019-01-29 20:36:54 +01:00
|
|
|
return Clutter.EVENT_PROPAGATE;
|
2017-10-31 01:38:18 +01:00
|
|
|
});
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_setUserListExpanded(expanded) {
|
2013-02-06 16:37:47 -05:00
|
|
|
this._userList.updateStyle(expanded);
|
|
|
|
this._userSelectionBox.visible = expanded;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-02-06 16:37:47 -05:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_hideUserList() {
|
2013-02-06 16:37:47 -05:00
|
|
|
this._setUserListExpanded(false);
|
2013-07-18 10:13:32 -04:00
|
|
|
if (this._userSelectionBox.visible)
|
|
|
|
GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-07-28 17:49:50 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_hideUserListAskForUsernameAndBeginVerification() {
|
2013-07-28 17:49:50 -04:00
|
|
|
this._hideUserList();
|
|
|
|
this._askForUsernameAndBeginVerification();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-07-28 17:49:50 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_hideUserListAndBeginVerification() {
|
2013-07-28 17:49:50 -04:00
|
|
|
this._hideUserList();
|
|
|
|
this._authPrompt.begin();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_showUserList() {
|
2014-03-07 16:04:01 +01:00
|
|
|
this._ensureUserListLoaded();
|
2013-07-15 17:56:44 -04:00
|
|
|
this._authPrompt.hide();
|
2014-11-11 09:11:01 -05:00
|
|
|
this._hideBannerView();
|
2013-07-15 17:56:44 -04:00
|
|
|
this._sessionMenuButton.close();
|
2020-02-13 12:39:13 -03:00
|
|
|
this._sessionMenuButton.hide();
|
2013-02-06 16:37:47 -05:00
|
|
|
this._setUserListExpanded(true);
|
2013-06-26 10:52:02 -04:00
|
|
|
this._notListedButton.show();
|
2019-07-16 11:24:13 +02:00
|
|
|
this._userList.grab_key_focus();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2012-05-20 01:19:25 +02:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_beginVerificationForItem(item) {
|
2013-07-15 17:56:44 -04:00
|
|
|
this._authPrompt.setUser(item.user);
|
2013-02-06 16:17:27 -05:00
|
|
|
|
2013-07-22 11:07:35 -04:00
|
|
|
let userName = item.user.get_user_name();
|
|
|
|
let hold = new Batch.Hold();
|
|
|
|
|
2023-08-07 00:40:20 +02:00
|
|
|
this._authPrompt.begin({userName, hold});
|
2013-07-22 11:07:35 -04:00
|
|
|
return hold;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-02-06 14:18:26 -05:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_onUserListActivated(activatedItem) {
|
2011-08-23 22:12:57 -04:00
|
|
|
this._user = activatedItem.user;
|
2013-02-06 14:18:26 -05:00
|
|
|
|
2013-07-28 20:55:12 -04:00
|
|
|
this._updateCancelButton();
|
|
|
|
|
2020-03-27 14:18:34 +01:00
|
|
|
const batch = new Batch.ConcurrentBatch(this, [
|
|
|
|
GdmUtil.cloneAndFadeOutActor(this._userSelectionBox),
|
|
|
|
this._beginVerificationForItem(activatedItem),
|
|
|
|
]);
|
2013-02-06 14:18:26 -05:00
|
|
|
batch.run();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_onDestroy() {
|
2014-10-09 14:10:12 -04:00
|
|
|
if (this._settings) {
|
|
|
|
this._settings.run_dispose();
|
|
|
|
this._settings = null;
|
|
|
|
}
|
2021-08-16 00:36:59 +02:00
|
|
|
this._greeter = null;
|
|
|
|
this._greeterSessionProxy = null;
|
|
|
|
this._realmManager?.release();
|
|
|
|
this._realmManager = null;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
_loadUserList() {
|
2014-03-07 16:04:01 +01:00
|
|
|
if (this._userListLoaded)
|
|
|
|
return GLib.SOURCE_REMOVE;
|
|
|
|
|
|
|
|
this._userListLoaded = true;
|
|
|
|
|
2011-08-23 22:12:57 -04:00
|
|
|
let users = this._userManager.list_users();
|
|
|
|
|
2019-08-20 02:51:42 +02:00
|
|
|
for (let i = 0; i < users.length; i++)
|
2011-08-23 22:12:57 -04:00
|
|
|
this._userList.addUser(users[i]);
|
|
|
|
|
2017-07-07 14:47:23 +08:00
|
|
|
this._updateDisableUserList();
|
|
|
|
|
2021-08-16 00:36:59 +02:00
|
|
|
this._userManager.connectObject(
|
|
|
|
'user-added', (userManager, user) => {
|
2017-10-31 01:38:18 +01:00
|
|
|
this._userList.addUser(user);
|
|
|
|
this._updateDisableUserList();
|
2021-08-16 00:36:59 +02:00
|
|
|
},
|
|
|
|
'user-removed', (userManager, user) => {
|
2017-10-31 01:38:18 +01:00
|
|
|
this._userList.removeUser(user);
|
|
|
|
this._updateDisableUserList();
|
2021-08-16 00:36:59 +02:00
|
|
|
},
|
|
|
|
'user-changed', (userManager, user) => {
|
2017-10-31 01:38:18 +01:00
|
|
|
if (this._userList.containsUser(user) && user.locked)
|
|
|
|
this._userList.removeUser(user);
|
|
|
|
else if (!this._userList.containsUser(user) && !user.locked)
|
|
|
|
this._userList.addUser(user);
|
|
|
|
this._updateDisableUserList();
|
2021-08-16 00:36:59 +02:00
|
|
|
}, this);
|
2015-11-23 18:24:19 -06:00
|
|
|
|
2014-03-07 16:16:20 +01:00
|
|
|
return GLib.SOURCE_REMOVE;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2020-01-30 11:44:43 -03:00
|
|
|
activate() {
|
|
|
|
this._userList.grab_key_focus();
|
|
|
|
this.show();
|
|
|
|
}
|
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
open() {
|
2018-07-07 13:30:18 +02:00
|
|
|
Main.ctrlAltTabManager.addGroup(this,
|
2023-08-07 01:45:22 +02:00
|
|
|
_('Login Window'),
|
|
|
|
'dialog-password-symbolic',
|
|
|
|
{sortGroup: CtrlAltTab.SortGroup.MIDDLE});
|
2020-01-30 11:44:43 -03:00
|
|
|
this.activate();
|
|
|
|
|
2018-07-07 13:30:18 +02:00
|
|
|
this.opacity = 0;
|
2013-08-26 18:04:09 -04:00
|
|
|
|
2023-08-07 00:40:20 +02:00
|
|
|
this._grab = Main.pushModal(global.stage, {actionMode: Shell.ActionMode.LOGIN_SCREEN});
|
2014-07-27 08:18:51 -04:00
|
|
|
|
2018-07-20 21:46:19 +02:00
|
|
|
this.ease({
|
|
|
|
opacity: 255,
|
|
|
|
duration: 1000,
|
2019-08-20 23:43:54 +02:00
|
|
|
mode: Clutter.AnimationMode.EASE_IN_QUAD,
|
2018-07-20 21:46:19 +02:00
|
|
|
});
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2013-06-25 12:55:21 -04:00
|
|
|
return true;
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-08-23 22:12:57 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
close() {
|
2021-11-25 10:49:42 +01:00
|
|
|
Main.popModal(this._grab);
|
|
|
|
this._grab = null;
|
2018-07-07 13:30:18 +02:00
|
|
|
Main.ctrlAltTabManager.removeGroup(this);
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-03-05 00:55:54 -05:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
cancel() {
|
2013-11-26 20:52:24 +01:00
|
|
|
this._authPrompt.cancel();
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-11-26 20:52:24 +01:00
|
|
|
|
2019-01-31 15:08:10 +01:00
|
|
|
addCharacter(_unichar) {
|
2016-05-09 08:59:46 -04:00
|
|
|
// Don't allow type ahead at the login screen
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2013-08-26 18:02:04 -04:00
|
|
|
|
2017-10-31 01:03:21 +01:00
|
|
|
finish(onComplete) {
|
2013-08-26 18:02:04 -04:00
|
|
|
this._authPrompt.finish(onComplete);
|
2017-10-31 02:23:39 +01:00
|
|
|
}
|
2011-11-20 16:32:59 +01:00
|
|
|
});
|