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' ;
2024-02-12 18:10:25 +01:00
import * as MessageTray from '../ui/messageTray.js' ;
2024-02-07 13:03:11 +01:00
import * as ModalDialog from '../ui/modalDialog.js' ;
2023-07-10 02:53:00 -07:00
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 ;
2024-02-12 18:10:25 +01:00
const _CONFLICTING _SESSION _DIALOG _TIMEOUT = 60 ;
2011-08-23 22:12:57 -04:00
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 ,
2023-12-06 15:46:12 +01:00
x _expand : true ,
2019-10-17 23:40:24 +02:00
} ) ;
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
2024-02-07 13:03:11 +01:00
export const ConflictingSessionDialog = GObject . registerClass ( {
Signals : {
'cancel' : { } ,
'force-stop' : { } ,
} ,
} , class ConflictingSessionDialog extends ModalDialog . ModalDialog {
_init ( conflictingSession , greeterSession , userName ) {
super . _init ( ) ;
let bannerText ;
if ( greeterSession . Remote && conflictingSession . Remote )
/* Translators: is running for <username> */
bannerText = _ ( 'Remote login is not possible because a remote session is already running for %s. To login remotely, you must log out from the remote session or force stop it.' ) . format ( userName ) ;
else if ( ! greeterSession . Remote && conflictingSession . Remote )
/* Translators: is running for <username> */
bannerText = _ ( 'Login is not possible because a remote session is already running for %s. To login, you must log out from the remote session or force stop it.' ) . format ( userName ) ;
else if ( greeterSession . Remote && ! conflictingSession . Remote )
/* Translators: is running for <username> */
bannerText = _ ( 'Remote login is not possible because a local session is already running for %s. To login remotely, you must log out from the local session or force stop it.' ) . format ( userName ) ;
else
/* Translators: is running for <username> */
bannerText = _ ( 'Login is not possible because a session is already running for %s. To login, you must log out from the session or force stop it.' ) . format ( userName ) ;
let textLayout = new St . BoxLayout ( {
style _class : 'conflicting-session-dialog-content' ,
vertical : true ,
x _expand : true ,
} ) ;
let title = new St . Label ( {
text : _ ( 'Session Already Running' ) ,
style _class : 'conflicting-session-dialog-title' ,
} ) ;
let banner = new St . Label ( {
text : bannerText ,
style _class : 'conflicting-session-dialog-desc' ,
} ) ;
banner . clutter _text . ellipsize = Pango . EllipsizeMode . NONE ;
banner . clutter _text . line _wrap = true ;
let warningBanner = new St . Label ( {
text : _ ( 'Force stopping will quit any running apps and processes, and could result in data loss.' ) ,
style _class : 'conflicting-session-dialog-desc-warning' ,
} ) ;
warningBanner . clutter _text . ellipsize = Pango . EllipsizeMode . NONE ;
warningBanner . clutter _text . line _wrap = true ;
textLayout . add _child ( title ) ;
textLayout . add _child ( banner ) ;
textLayout . add _child ( warningBanner ) ;
this . contentLayout . add _child ( textLayout ) ;
this . addButton ( {
label : _ ( 'Cancel' ) ,
action : ( ) => {
this . emit ( 'cancel' ) ;
} ,
key : Clutter . KEY _Escape ,
default : true ,
} ) ;
this . addButton ( {
label : _ ( 'Force Stop' ) ,
action : ( ) => {
this . emit ( 'force-stop' ) ;
} ,
} ) ;
}
} ) ;
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
2024-02-12 18:10:25 +01:00
_notifyConflictingSessionDialogClosed ( userName ) {
const source = new MessageTray . SystemNotificationSource ( ) ;
Main . messageTray . add ( source ) ;
this . _conflictingSessionNotification = new MessageTray . Notification ( source ,
_ ( 'Stop conflicting session dialog closed' ) ,
_ ( 'Try to login again to start a session for user %s.' ) . format ( userName ) ) ;
this . _conflictingSessionNotification . setUrgency ( MessageTray . Urgency . CRITICAL ) ;
this . _conflictingSessionNotification . setTransient ( true ) ;
this . _conflictingSessionNotification . connect ( 'destroy' , ( ) => {
this . _conflictingSessionNotification = null ;
} ) ;
source . showNotification ( this . _conflictingSessionNotification ) ;
}
2024-02-07 13:05:17 +01:00
_showConflictingSessionDialog ( serviceName , conflictingSession ) {
let conflictingSessionDialog = new ConflictingSessionDialog ( conflictingSession ,
this . _greeterSessionProxy ,
this . _user . get _user _name ( ) ) ;
conflictingSessionDialog . connect ( 'cancel' , ( ) => {
this . _authPrompt . reset ( ) ;
conflictingSessionDialog . close ( ) ;
} ) ;
conflictingSessionDialog . connect ( 'force-stop' , ( ) => {
this . _greeter . call _stop _conflicting _session _sync ( null ) ;
} ) ;
const loginManager = LoginManager . getLoginManager ( ) ;
loginManager . connectObject ( 'session-removed' , ( lm , sessionId ) => {
if ( sessionId === conflictingSession . Id ) {
conflictingSessionDialog . close ( ) ;
this . _authPrompt . finish ( ( ) => this . _startSession ( serviceName ) ) ;
}
} , conflictingSessionDialog ) ;
2024-02-12 18:10:25 +01:00
const closeDialogTimeoutId = GLib . timeout _add _seconds ( GLib . PRIORITY _DEFAULT , _CONFLICTING _SESSION _DIALOG _TIMEOUT , ( ) => {
this . _notifyConflictingSessionDialogClosed ( this . _user . get _user _name ( ) ) ;
conflictingSessionDialog . close ( ) ;
this . _authPrompt . reset ( ) ;
return GLib . SOURCE _REMOVE ;
} ) ;
conflictingSessionDialog . connect ( 'closed' , ( ) => {
GLib . source _remove ( closeDialogTimeoutId ) ;
} ) ;
2024-02-07 13:05:17 +01:00
conflictingSessionDialog . open ( ) ;
}
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
2024-02-07 13:05:17 +01:00
async _findConflictingSession ( ignoreSessionId ) {
const userName = this . _user . get _user _name ( ) ;
const loginManager = LoginManager . getLoginManager ( ) ;
const sessions = await loginManager . listSessions ( ) ;
for ( const session of sessions . map ( ( [ id , , user , , path ] ) => ( { id , user , path } ) ) ) {
if ( ignoreSessionId === session . id )
continue ;
if ( userName !== session . user )
continue ;
const sessionProxy = loginManager . getSession ( session . path ) ;
if ( sessionProxy . Type !== 'wayland' && sessionProxy . Type !== 'x11' )
continue ;
if ( sessionProxy . State !== 'active' && sessionProxy . State !== 'online' )
continue ;
return sessionProxy ;
}
return null ;
}
async _onSessionOpened ( client , serviceName , sessionId ) {
if ( sessionId ) {
const conflictingSession = await this . _findConflictingSession ( sessionId ) ;
if ( conflictingSession ) {
this . _showConflictingSessionDialog ( serviceName , conflictingSession ) ;
return ;
}
}
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 ( ) ;
2024-02-12 18:10:25 +01:00
if ( this . _conflictingSessionNotification )
this . _conflictingSessionNotification . destroy ( ) ;
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
} ) ;