Compare commits
	
		
			15 Commits
		
	
	
		
			wip/gestur
			...
			wip/reorg
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d985477a9d | ||
| 
						 | 
					b188d57609 | ||
| 
						 | 
					412af26e4e | ||
| 
						 | 
					7b440f3864 | ||
| 
						 | 
					2d98903c90 | ||
| 
						 | 
					9a0d0d2fd3 | ||
| 
						 | 
					9451c04a09 | ||
| 
						 | 
					ca9099997c | ||
| 
						 | 
					4de18f2d4b | ||
| 
						 | 
					73d8f6c993 | ||
| 
						 | 
					2141138a6f | ||
| 
						 | 
					4f135be89a | ||
| 
						 | 
					026ec2d4c2 | ||
| 
						 | 
					a82fae3a2f | ||
| 
						 | 
					892d224cd7 | 
@@ -381,6 +381,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
/* Entries */
 | 
			
		||||
 | 
			
		||||
#searchEntry,
 | 
			
		||||
.login-dialog StEntry,
 | 
			
		||||
.notification StEntry,
 | 
			
		||||
.modal-dialog StEntry {
 | 
			
		||||
    color: rgb(64, 64, 64);
 | 
			
		||||
@@ -392,6 +393,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#searchEntry,
 | 
			
		||||
.login-dialog StEntry,
 | 
			
		||||
.run-dialog-entry,
 | 
			
		||||
.notification StEntry {
 | 
			
		||||
    border: 2px solid rgba(245,245,245,0.2);
 | 
			
		||||
@@ -404,6 +406,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
 | 
			
		||||
#searchEntry:focus,
 | 
			
		||||
#searchEntry:hover,
 | 
			
		||||
.login-dialog StEntry:focus,
 | 
			
		||||
.notification StEntry:focus,
 | 
			
		||||
.modal-dialog StEntry {
 | 
			
		||||
    border: 2px solid rgb(136,138,133);
 | 
			
		||||
@@ -413,6 +416,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog StEntry:focus,
 | 
			
		||||
.notification StEntry:focus,
 | 
			
		||||
.modal-dialog StEntry:focus {
 | 
			
		||||
    border: 2px solid #3465a4;
 | 
			
		||||
@@ -436,6 +440,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    transition-duration: 0ms;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog StEntry,
 | 
			
		||||
.notification StEntry,
 | 
			
		||||
.modal-dialog StEntry {
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
@@ -449,6 +454,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    padding: 0 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog StEntry:insensitive,
 | 
			
		||||
.modal-dialog StEntry:insensitive {
 | 
			
		||||
    border-color: #666666;
 | 
			
		||||
    color: #9f9f9f;
 | 
			
		||||
@@ -2234,8 +2240,13 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    min-width: 350px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-button-box {
 | 
			
		||||
    spacing: 21px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-login-hint-message {
 | 
			
		||||
    font-size: 10.5pt;
 | 
			
		||||
    min-width: 480px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-view {
 | 
			
		||||
@@ -2342,7 +2353,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-entry {
 | 
			
		||||
    width: 15em;
 | 
			
		||||
    width: 480px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list,
 | 
			
		||||
 
 | 
			
		||||
@@ -17,13 +17,8 @@ misc/config.js: misc/config.js.in Makefile
 | 
			
		||||
jsdir = $(pkgdatadir)/js
 | 
			
		||||
 | 
			
		||||
nobase_dist_js_DATA = 	\
 | 
			
		||||
	gdm/batch.js		\
 | 
			
		||||
	gdm/fingerprint.js	\
 | 
			
		||||
	gdm/loginDialog.js	\
 | 
			
		||||
	gdm/powerMenu.js	\
 | 
			
		||||
	gdm/realmd.js		\
 | 
			
		||||
	gdm/util.js		\
 | 
			
		||||
	extensionPrefs/main.js	\
 | 
			
		||||
	misc/batch.js		\
 | 
			
		||||
	misc/config.js		\
 | 
			
		||||
	misc/extensionUtils.js	\
 | 
			
		||||
	misc/fileUtils.js	\
 | 
			
		||||
@@ -37,6 +32,7 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	misc/util.js		\
 | 
			
		||||
	perf/core.js		\
 | 
			
		||||
	ui/altTab.js		\
 | 
			
		||||
	ui/animation.js		\
 | 
			
		||||
	ui/appDisplay.js	\
 | 
			
		||||
	ui/appFavorites.js	\
 | 
			
		||||
	ui/backgroundMenu.js	\
 | 
			
		||||
@@ -95,7 +91,7 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	ui/status/bluetooth.js	\
 | 
			
		||||
	ui/switcherPopup.js	\
 | 
			
		||||
	ui/tweener.js		\
 | 
			
		||||
	ui/unlockDialog.js	\
 | 
			
		||||
	ui/userAvatar.js	\
 | 
			
		||||
	ui/userMenu.js		\
 | 
			
		||||
	ui/userWidget.js	\
 | 
			
		||||
	ui/viewSelector.js	\
 | 
			
		||||
@@ -107,6 +103,14 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	ui/workspacesView.js	\
 | 
			
		||||
	ui/workspaceSwitcherPopup.js    \
 | 
			
		||||
	ui/xdndHandler.js	\
 | 
			
		||||
	ui/auth/fingerprint.js	\
 | 
			
		||||
	ui/auth/loginDialog.js	\
 | 
			
		||||
	ui/auth/powerMenu.js	\
 | 
			
		||||
	ui/auth/realmd.js	\
 | 
			
		||||
	ui/auth/sessionList.js	\
 | 
			
		||||
	ui/auth/unlockDialog.js	\
 | 
			
		||||
	ui/auth/userList.js	\
 | 
			
		||||
	ui/auth/util.js		\
 | 
			
		||||
	ui/components/__init__.js		\
 | 
			
		||||
	ui/components/autorunManager.js		\
 | 
			
		||||
	ui/components/automountManager.js	\
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										84
									
								
								js/ui/animation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								js/ui/animation.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
 | 
			
		||||
const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
 | 
			
		||||
 | 
			
		||||
const Animation = new Lang.Class({
 | 
			
		||||
    Name: 'Animation',
 | 
			
		||||
 | 
			
		||||
    _init: function(filename, width, height, speed) {
 | 
			
		||||
        this.actor = new St.Bin();
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
        this._speed = speed;
 | 
			
		||||
 | 
			
		||||
        this._isLoaded = false;
 | 
			
		||||
        this._isPlaying = false;
 | 
			
		||||
        this._timeoutId = 0;
 | 
			
		||||
        this._frame = 0;
 | 
			
		||||
        this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height,
 | 
			
		||||
                                                                            Lang.bind(this, this._animationsLoaded));
 | 
			
		||||
        this.actor.set_child(this._animations);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    play: function() {
 | 
			
		||||
        if (this._isLoaded && this._timeoutId == 0) {
 | 
			
		||||
            if (this._frame == 0)
 | 
			
		||||
                this._showFrame(0);
 | 
			
		||||
 | 
			
		||||
            this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._isPlaying = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    stop: function() {
 | 
			
		||||
        if (this._timeoutId > 0) {
 | 
			
		||||
            Mainloop.source_remove(this._timeoutId);
 | 
			
		||||
            this._timeoutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._isPlaying = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showFrame: function(frame) {
 | 
			
		||||
        let oldFrameActor = this._animations.get_child_at_index(this._frame);
 | 
			
		||||
        if (oldFrameActor)
 | 
			
		||||
            oldFrameActor.hide();
 | 
			
		||||
 | 
			
		||||
        this._frame = (frame % this._animations.get_n_children());
 | 
			
		||||
 | 
			
		||||
        let newFrameActor = this._animations.get_child_at_index(this._frame);
 | 
			
		||||
        if (newFrameActor)
 | 
			
		||||
            newFrameActor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _update: function() {
 | 
			
		||||
        this._showFrame(this._frame + 1);
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _animationsLoaded: function() {
 | 
			
		||||
        this._isLoaded = true;
 | 
			
		||||
 | 
			
		||||
        if (this._isPlaying)
 | 
			
		||||
            this.play();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
        this.stop();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const AnimatedIcon = new Lang.Class({
 | 
			
		||||
    Name: 'AnimatedIcon',
 | 
			
		||||
    Extends: Animation,
 | 
			
		||||
 | 
			
		||||
    _init: function(filename, size) {
 | 
			
		||||
        this.parent(filename, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const AccountsService = imports.gi.AccountsService;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const CtrlAltTab = imports.ui.ctrlAltTab;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
@@ -28,464 +29,50 @@ const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Realmd = imports.gdm.realmd;
 | 
			
		||||
const Realmd = imports.ui.auth.realmd;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Gdm = imports.gi.Gdm;
 | 
			
		||||
 | 
			
		||||
const Batch = imports.gdm.batch;
 | 
			
		||||
const Fprint = imports.gdm.fingerprint;
 | 
			
		||||
const GdmUtil = imports.gdm.util;
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Animation = imports.ui.animation;
 | 
			
		||||
const AuthUtil = imports.ui.auth.util;
 | 
			
		||||
const Batch = imports.misc.batch;
 | 
			
		||||
const Fprint = imports.ui.auth.fingerprint;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const SessionList = imports.ui.auth.sessionList;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const UserMenu = imports.ui.userMenu;
 | 
			
		||||
const UserAvatar = imports.ui.userAvatar;
 | 
			
		||||
const UserList = imports.ui.auth.userList;
 | 
			
		||||
const UserWidget = imports.ui.userWidget;
 | 
			
		||||
 | 
			
		||||
const _FADE_ANIMATION_TIME = 0.25;
 | 
			
		||||
const _SCROLL_ANIMATION_TIME = 0.5;
 | 
			
		||||
const _WORK_SPINNER_ICON_SIZE = 24;
 | 
			
		||||
const _WORK_SPINNER_ANIMATION_DELAY = 1.0;
 | 
			
		||||
const _WORK_SPINNER_ANIMATION_TIME = 0.3;
 | 
			
		||||
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
 | 
			
		||||
const _LOGO_ICON_HEIGHT = 48;
 | 
			
		||||
 | 
			
		||||
let _loginDialog = null;
 | 
			
		||||
 | 
			
		||||
const UserListItem = new Lang.Class({
 | 
			
		||||
    Name: 'UserListItem',
 | 
			
		||||
 | 
			
		||||
    _init: function(user) {
 | 
			
		||||
        this.user = user;
 | 
			
		||||
        this._userChangedId = this.user.connect('changed',
 | 
			
		||||
                                                 Lang.bind(this, this._onUserChanged));
 | 
			
		||||
 | 
			
		||||
        let layout = new St.BoxLayout({ vertical: false });
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     child: layout,
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._userAvatar = new UserMenu.UserAvatarWidget(this.user,
 | 
			
		||||
                                                         { styleClass: 'login-dialog-user-list-item-icon' });
 | 
			
		||||
        layout.add(this._userAvatar.actor);
 | 
			
		||||
        let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box',
 | 
			
		||||
                                            vertical:    true });
 | 
			
		||||
        layout.add(textLayout, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._nameLabel = new St.Label({ style_class: 'login-dialog-user-list-item-name' });
 | 
			
		||||
        this.actor.label_actor = this._nameLabel;
 | 
			
		||||
        textLayout.add(this._nameLabel,
 | 
			
		||||
                       { y_fill: false,
 | 
			
		||||
                         y_align: St.Align.MIDDLE,
 | 
			
		||||
                         expand: true });
 | 
			
		||||
 | 
			
		||||
        this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
 | 
			
		||||
                                                 scale_x: 0 });
 | 
			
		||||
        textLayout.add(this._timedLoginIndicator,
 | 
			
		||||
                       { x_fill: true,
 | 
			
		||||
                         x_align: St.Align.MIDDLE,
 | 
			
		||||
                         y_fill: false,
 | 
			
		||||
                         y_align: St.Align.END });
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
 | 
			
		||||
        this._onUserChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onUserChanged: function() {
 | 
			
		||||
        this._nameLabel.set_text(this.user.get_real_name());
 | 
			
		||||
        this._userAvatar.update();
 | 
			
		||||
        this._updateLoggedIn();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    syncStyleClasses: function() {
 | 
			
		||||
        this._updateLoggedIn();
 | 
			
		||||
 | 
			
		||||
        if (global.stage.get_key_focus() == this.actor)
 | 
			
		||||
            this.actor.add_style_pseudo_class('focus');
 | 
			
		||||
        else
 | 
			
		||||
            this.actor.remove_style_pseudo_class('focus');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateLoggedIn: function() {
 | 
			
		||||
        if (this.user.is_logged_in())
 | 
			
		||||
            this.actor.add_style_pseudo_class('logged-in');
 | 
			
		||||
        else
 | 
			
		||||
            this.actor.remove_style_pseudo_class('logged-in');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showTimedLoginIndicator: function(time) {
 | 
			
		||||
        let hold = new Batch.Hold();
 | 
			
		||||
 | 
			
		||||
        this.hideTimedLoginIndicator();
 | 
			
		||||
        Tweener.addTween(this._timedLoginIndicator,
 | 
			
		||||
                         { scale_x: 1.,
 | 
			
		||||
                           time: time,
 | 
			
		||||
                           transition: 'linear',
 | 
			
		||||
                           onComplete: function() {
 | 
			
		||||
                               hold.release();
 | 
			
		||||
                           },
 | 
			
		||||
                           onCompleteScope: this
 | 
			
		||||
                         });
 | 
			
		||||
        return hold;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideTimedLoginIndicator: function() {
 | 
			
		||||
        Tweener.removeTweens(this._timedLoginIndicator);
 | 
			
		||||
        this._timedLoginIndicator.scale_x = 0.;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(UserListItem.prototype);
 | 
			
		||||
 | 
			
		||||
const UserList = new Lang.Class({
 | 
			
		||||
    Name: 'UserList',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
 | 
			
		||||
        this.actor.set_policy(Gtk.PolicyType.NEVER,
 | 
			
		||||
                              Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                       style_class: 'login-dialog-user-list',
 | 
			
		||||
                                       pseudo_class: 'expanded' });
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(this._box);
 | 
			
		||||
        this._items = {};
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('key-focus-in', Lang.bind(this, this._moveFocusToItems));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _moveFocusToItems: function() {
 | 
			
		||||
        let hasItems = Object.keys(this._items).length > 0;
 | 
			
		||||
 | 
			
		||||
        if (!hasItems)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (global.stage.get_key_focus() != this.actor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
        if (!focusSet) {
 | 
			
		||||
            Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
 | 
			
		||||
                this._moveFocusToItems();
 | 
			
		||||
                return false;
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onItemActivated: function(activatedItem) {
 | 
			
		||||
        this.emit('activate', activatedItem);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateStyle: function(isExpanded) {
 | 
			
		||||
        let tasks = [];
 | 
			
		||||
 | 
			
		||||
        if (isExpanded)
 | 
			
		||||
            this._box.add_style_pseudo_class('expanded');
 | 
			
		||||
        else
 | 
			
		||||
            this._box.remove_style_pseudo_class('expanded');
 | 
			
		||||
 | 
			
		||||
        for (let userName in this._items) {
 | 
			
		||||
            let item = this._items[userName];
 | 
			
		||||
            item.actor.sync_hover();
 | 
			
		||||
            item.syncStyleClasses();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    scrollToItem: function(item) {
 | 
			
		||||
        let box = item.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
 | 
			
		||||
 | 
			
		||||
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
 | 
			
		||||
        Tweener.removeTweens(adjustment);
 | 
			
		||||
        Tweener.addTween (adjustment,
 | 
			
		||||
                          { value: value,
 | 
			
		||||
                            time: _SCROLL_ANIMATION_TIME,
 | 
			
		||||
                            transition: 'easeOutQuad' });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    jumpToItem: function(item) {
 | 
			
		||||
        let box = item.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
 | 
			
		||||
 | 
			
		||||
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
 | 
			
		||||
 | 
			
		||||
        adjustment.set_value(value);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getItemFromUserName: function(userName) {
 | 
			
		||||
        let item = this._items[userName];
 | 
			
		||||
 | 
			
		||||
        if (!item)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        return item;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addUser: function(user) {
 | 
			
		||||
        if (!user.is_loaded)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (user.is_system_account())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (user.locked)
 | 
			
		||||
           return;
 | 
			
		||||
 | 
			
		||||
        let userName = user.get_user_name();
 | 
			
		||||
 | 
			
		||||
        if (!userName)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.removeUser(user);
 | 
			
		||||
 | 
			
		||||
        let item = new UserListItem(user);
 | 
			
		||||
        this._box.add(item.actor, { x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._items[userName] = item;
 | 
			
		||||
 | 
			
		||||
        item.connect('activate',
 | 
			
		||||
                     Lang.bind(this, this._onItemActivated));
 | 
			
		||||
 | 
			
		||||
        // Try to keep the focused item front-and-center
 | 
			
		||||
        item.actor.connect('key-focus-in',
 | 
			
		||||
                           Lang.bind(this,
 | 
			
		||||
                                     function() {
 | 
			
		||||
                                         this.scrollToItem(item);
 | 
			
		||||
                                     }));
 | 
			
		||||
 | 
			
		||||
        this._moveFocusToItems();
 | 
			
		||||
 | 
			
		||||
        this.emit('item-added', item);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeUser: function(user) {
 | 
			
		||||
        if (!user.is_loaded)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let userName = user.get_user_name();
 | 
			
		||||
 | 
			
		||||
        if (!userName)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let item = this._items[userName];
 | 
			
		||||
 | 
			
		||||
        if (!item)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        item.actor.destroy();
 | 
			
		||||
        delete this._items[userName];
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(UserList.prototype);
 | 
			
		||||
 | 
			
		||||
const SessionListItem = new Lang.Class({
 | 
			
		||||
    Name: 'SessionListItem',
 | 
			
		||||
 | 
			
		||||
    _init: function(id, name) {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'login-dialog-session-list-item',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     x_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list-item-box' });
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(this._box);
 | 
			
		||||
        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
 | 
			
		||||
 | 
			
		||||
        this._dot = new St.DrawingArea({ style_class: 'login-dialog-session-list-item-dot' });
 | 
			
		||||
        this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot));
 | 
			
		||||
        this._box.add_actor(this._dot);
 | 
			
		||||
        this.setShowDot(false);
 | 
			
		||||
 | 
			
		||||
        let label = new St.Label({ style_class: 'login-dialog-session-list-item-label',
 | 
			
		||||
                                   text: name });
 | 
			
		||||
        this.actor.label_actor = label;
 | 
			
		||||
 | 
			
		||||
        this._box.add_actor(label);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setShowDot: function(show) {
 | 
			
		||||
        if (show)
 | 
			
		||||
            this._dot.opacity = 255;
 | 
			
		||||
        else
 | 
			
		||||
            this._dot.opacity = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onRepaintDot: function(area) {
 | 
			
		||||
        let cr = area.get_context();
 | 
			
		||||
        let [width, height] = area.get_surface_size();
 | 
			
		||||
        let color = area.get_theme_node().get_foreground_color();
 | 
			
		||||
 | 
			
		||||
        cr.setSourceRGBA (color.red / 255,
 | 
			
		||||
                          color.green / 255,
 | 
			
		||||
                          color.blue / 255,
 | 
			
		||||
                          color.alpha / 255);
 | 
			
		||||
        cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SessionListItem.prototype);
 | 
			
		||||
 | 
			
		||||
const SessionList = new Lang.Class({
 | 
			
		||||
    Name: 'SessionList',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.Bin();
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list',
 | 
			
		||||
                                       vertical: true});
 | 
			
		||||
        this.actor.child = this._box;
 | 
			
		||||
 | 
			
		||||
        this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
 | 
			
		||||
                                       button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                       can_focus: true,
 | 
			
		||||
                                       x_fill: true,
 | 
			
		||||
                                       y_fill: true });
 | 
			
		||||
        let box = new St.BoxLayout();
 | 
			
		||||
        this._button.add_actor(box);
 | 
			
		||||
 | 
			
		||||
        this._triangle = new St.Label({ style_class: 'login-dialog-session-list-triangle',
 | 
			
		||||
                                        text: '\u25B8' });
 | 
			
		||||
        box.add_actor(this._triangle);
 | 
			
		||||
 | 
			
		||||
        let label = new St.Label({ style_class: 'login-dialog-session-list-label',
 | 
			
		||||
                                   text: _("Session…") });
 | 
			
		||||
        box.add_actor(label);
 | 
			
		||||
 | 
			
		||||
        this._button.connect('clicked',
 | 
			
		||||
                             Lang.bind(this, this._onClicked));
 | 
			
		||||
        this._box.add_actor(this._button);
 | 
			
		||||
        this._scrollView = new St.ScrollView({ style_class: 'login-dialog-session-list-scroll-view'});
 | 
			
		||||
        this._scrollView.set_policy(Gtk.PolicyType.NEVER,
 | 
			
		||||
                                    Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
        this._box.add_actor(this._scrollView);
 | 
			
		||||
        this._itemList = new St.BoxLayout({ style_class: 'login-dialog-session-item-list',
 | 
			
		||||
                                            vertical: true });
 | 
			
		||||
        this._scrollView.add_actor(this._itemList);
 | 
			
		||||
        this._scrollView.hide();
 | 
			
		||||
        this.isOpen = false;
 | 
			
		||||
        this._populate();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    open: function() {
 | 
			
		||||
        if (this.isOpen)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._button.add_style_pseudo_class('open');
 | 
			
		||||
        this._scrollView.show();
 | 
			
		||||
        this._triangle.set_text('\u25BE');
 | 
			
		||||
 | 
			
		||||
        this.isOpen = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    close: function() {
 | 
			
		||||
        if (!this.isOpen)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._button.remove_style_pseudo_class('open');
 | 
			
		||||
        this._scrollView.hide();
 | 
			
		||||
        this._triangle.set_text('\u25B8');
 | 
			
		||||
 | 
			
		||||
        this.isOpen = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
        if (!this.isOpen)
 | 
			
		||||
            this.open();
 | 
			
		||||
        else
 | 
			
		||||
            this.close();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateSensitivity: function(sensitive) {
 | 
			
		||||
        this._button.reactive = sensitive;
 | 
			
		||||
        this._button.can_focus = sensitive;
 | 
			
		||||
 | 
			
		||||
        for (let id in this._items)
 | 
			
		||||
            this._items[id].actor.reactive = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setActiveSession: function(sessionId) {
 | 
			
		||||
         if (sessionId == this._activeSessionId)
 | 
			
		||||
             return;
 | 
			
		||||
 | 
			
		||||
         if (this._activeSessionId)
 | 
			
		||||
             this._items[this._activeSessionId].setShowDot(false);
 | 
			
		||||
 | 
			
		||||
         this._items[sessionId].setShowDot(true);
 | 
			
		||||
         this._activeSessionId = sessionId;
 | 
			
		||||
 | 
			
		||||
         this.emit('session-activated', this._activeSessionId);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _populate: function() {
 | 
			
		||||
        this._itemList.destroy_all_children();
 | 
			
		||||
        this._activeSessionId = null;
 | 
			
		||||
        this._items = {};
 | 
			
		||||
 | 
			
		||||
        let ids = Gdm.get_session_ids();
 | 
			
		||||
        ids.sort();
 | 
			
		||||
 | 
			
		||||
        if (ids.length <= 1) {
 | 
			
		||||
            this._box.hide();
 | 
			
		||||
            this._button.hide();
 | 
			
		||||
        } else {
 | 
			
		||||
            this._button.show();
 | 
			
		||||
            this._box.show();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < ids.length; i++) {
 | 
			
		||||
            let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
 | 
			
		||||
 | 
			
		||||
            let item = new SessionListItem(ids[i], sessionName);
 | 
			
		||||
            this._itemList.add_actor(item.actor);
 | 
			
		||||
            this._items[ids[i]] = item;
 | 
			
		||||
 | 
			
		||||
            if (!this._activeSessionId)
 | 
			
		||||
                this.setActiveSession(ids[i]);
 | 
			
		||||
 | 
			
		||||
            item.connect('activate',
 | 
			
		||||
                         Lang.bind(this, function() {
 | 
			
		||||
                             this.setActiveSession(item.id);
 | 
			
		||||
                         }));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SessionList.prototype);
 | 
			
		||||
 | 
			
		||||
const LoginDialog = new Lang.Class({
 | 
			
		||||
    Name: 'LoginDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function(parentActor) {
 | 
			
		||||
        this.parent({ shellReactive: true,
 | 
			
		||||
                      styleClass: 'login-dialog',
 | 
			
		||||
                      parentActor: parentActor,
 | 
			
		||||
                      keybindingMode: Shell.KeyBindingMode.LOGIN_SCREEN,
 | 
			
		||||
                      shouldFadeIn: false });
 | 
			
		||||
        this.connect('destroy',
 | 
			
		||||
                     Lang.bind(this, this._onDestroy));
 | 
			
		||||
        this.connect('opened',
 | 
			
		||||
                     Lang.bind(this, this._onOpened));
 | 
			
		||||
        this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
 | 
			
		||||
                                     style_class: 'login-dialog' });
 | 
			
		||||
 | 
			
		||||
        this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
        parentActor.add_child(this.actor);
 | 
			
		||||
 | 
			
		||||
        Main.ctrlAltTabManager.addGroup(this.actor,
 | 
			
		||||
                                        _("Login Window"),
 | 
			
		||||
                                        'dialog-password-symbolic',
 | 
			
		||||
                                        { sortGroup: CtrlAltTab.SortGroup.MIDDLE });
 | 
			
		||||
        this._userManager = AccountsService.UserManager.get_default()
 | 
			
		||||
        this._greeterClient = new Gdm.Client();
 | 
			
		||||
 | 
			
		||||
@@ -501,24 +88,24 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                                  Lang.bind(this, this._onTimedLoginRequested));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient);
 | 
			
		||||
        this._userVerifier = new AuthUtil.ShellUserVerifier(this._greeterClient);
 | 
			
		||||
        this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
 | 
			
		||||
        this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
 | 
			
		||||
        this._userVerifier.connect('show-message', Lang.bind(this, this._onShowMessage));
 | 
			
		||||
        this._userVerifier.connect('verification-failed', Lang.bind(this, this._verificationFailed));
 | 
			
		||||
        this._userVerifier.connect('reset', Lang.bind(this, this._reset));
 | 
			
		||||
        this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
 | 
			
		||||
        this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
 | 
			
		||||
        this._verifyingUser = false;
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: AuthUtil.LOGIN_SCREEN_SCHEMA });
 | 
			
		||||
 | 
			
		||||
        this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
 | 
			
		||||
        this._settings.connect('changed::' + AuthUtil.BANNER_MESSAGE_KEY,
 | 
			
		||||
                               Lang.bind(this, this._updateBanner));
 | 
			
		||||
        this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
 | 
			
		||||
        this._settings.connect('changed::' + AuthUtil.BANNER_MESSAGE_TEXT_KEY,
 | 
			
		||||
                               Lang.bind(this, this._updateBanner));
 | 
			
		||||
        this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
 | 
			
		||||
        this._settings.connect('changed::' + AuthUtil.DISABLE_USER_LIST_KEY,
 | 
			
		||||
                               Lang.bind(this, this._updateDisableUserList));
 | 
			
		||||
        this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
 | 
			
		||||
        this._settings.connect('changed::' + AuthUtil.LOGO_KEY,
 | 
			
		||||
                               Lang.bind(this, this._updateLogo));
 | 
			
		||||
 | 
			
		||||
        this._textureCache = St.TextureCache.get_default();
 | 
			
		||||
@@ -527,28 +114,31 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
 | 
			
		||||
                                                    vertical: true });
 | 
			
		||||
        this.contentLayout.add(this._userSelectionBox);
 | 
			
		||||
 | 
			
		||||
        this._userSelectionBox.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
 | 
			
		||||
                                                                            align_axis: Clutter.AlignAxis.BOTH,
 | 
			
		||||
                                                                            factor: 0.5 }));
 | 
			
		||||
        this.actor.add_child(this._userSelectionBox);
 | 
			
		||||
 | 
			
		||||
        this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
 | 
			
		||||
                                           text: '' });
 | 
			
		||||
        this._userSelectionBox.add(this._bannerLabel);
 | 
			
		||||
        this._updateBanner();
 | 
			
		||||
 | 
			
		||||
        this._userList = new UserList();
 | 
			
		||||
        this._userList = new UserList.UserList();
 | 
			
		||||
        this._userSelectionBox.add(this._userList.actor,
 | 
			
		||||
                                   { expand: true,
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     y_fill: true });
 | 
			
		||||
 | 
			
		||||
        this.setInitialKeyFocus(this._userList.actor);
 | 
			
		||||
        this._userList.actor.grab_key_focus();
 | 
			
		||||
 | 
			
		||||
        this._promptBox = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
 | 
			
		||||
                                             vertical: true });
 | 
			
		||||
        this.contentLayout.add(this._promptBox,
 | 
			
		||||
                               { expand: true,
 | 
			
		||||
                                 x_fill: true,
 | 
			
		||||
                                 y_fill: true,
 | 
			
		||||
                                 x_align: St.Align.START });
 | 
			
		||||
        this._promptBox.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
 | 
			
		||||
                                                                     align_axis: Clutter.AlignAxis.BOTH,
 | 
			
		||||
                                                                     factor: 0.5 }));
 | 
			
		||||
        this.actor.add_child(this._promptBox);
 | 
			
		||||
        this._promptUser = new St.Bin({ x_fill: true,
 | 
			
		||||
                                        x_align: St.Align.START });
 | 
			
		||||
        this._promptBox.add(this._promptUser,
 | 
			
		||||
@@ -568,21 +158,29 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        this._promptEntryTextChangedId = 0;
 | 
			
		||||
        this._promptEntryActivateId = 0;
 | 
			
		||||
        this._promptBox.add(this._promptEntry,
 | 
			
		||||
                            { expand: true,
 | 
			
		||||
                              x_fill: true,
 | 
			
		||||
                              y_fill: false,
 | 
			
		||||
                              x_align: St.Align.START });
 | 
			
		||||
                            { expand: false,
 | 
			
		||||
                              x_fill: false });
 | 
			
		||||
 | 
			
		||||
        this._promptMessage = new St.Label({ visible: false });
 | 
			
		||||
        this._promptBox.add(this._promptMessage, { x_fill: true });
 | 
			
		||||
        this._promptMessage = new St.Label({ opacity: 0 });
 | 
			
		||||
        this.actor.add_child(this._promptMessage);
 | 
			
		||||
 | 
			
		||||
        this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint-message' });
 | 
			
		||||
        this._promptLoginHint.hide();
 | 
			
		||||
        this._promptBox.add(this._promptLoginHint);
 | 
			
		||||
        this._promptMessagePlaceholder = new Clutter.Actor({ width: 1, height: 1 });
 | 
			
		||||
        this._promptBox.add_child(this._promptMessagePlaceholder);
 | 
			
		||||
 | 
			
		||||
        this._signInButton = null;
 | 
			
		||||
        this._promptMessagePlaceholder.add_constraint(new Clutter.BindConstraint({ source: this._promptMessage,
 | 
			
		||||
                                                                                   coordinate: Clutter.BindCoordinate.HEIGHT }));
 | 
			
		||||
 | 
			
		||||
        this._sessionList = new SessionList();
 | 
			
		||||
        this._promptMessage.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
 | 
			
		||||
                                                                         align_axis: Clutter.AlignAxis.X_AXIS,
 | 
			
		||||
                                                                         factor: 0.5 }));
 | 
			
		||||
 | 
			
		||||
        this._promptMessagePlaceholder.connect("notify::y", Lang.bind(this, function() {
 | 
			
		||||
                                                   let [placeholderX , placeholderY] = this._promptMessagePlaceholder.get_transformed_position();
 | 
			
		||||
                                                   let [actorX, actorY] = this.actor.get_transformed_position();
 | 
			
		||||
                                                   this._promptMessage.y = placeholderY - actorY;
 | 
			
		||||
                                               }));
 | 
			
		||||
 | 
			
		||||
        this._sessionList = new SessionList.SessionList();
 | 
			
		||||
        this._sessionList.connect('session-activated',
 | 
			
		||||
                                  Lang.bind(this, function(list, sessionId) {
 | 
			
		||||
                                                this._greeter.call_select_session_sync (sessionId, null);
 | 
			
		||||
@@ -593,6 +191,16 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                              x_fill: false,
 | 
			
		||||
                              y_fill: true,
 | 
			
		||||
                              x_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
 | 
			
		||||
                                             vertical: false });
 | 
			
		||||
        this._promptBox.add(this._buttonBox,
 | 
			
		||||
                            { expand:  true,
 | 
			
		||||
                              x_align: St.Align.MIDDLE,
 | 
			
		||||
                              y_align: St.Align.END });
 | 
			
		||||
        this._cancelButton = null;
 | 
			
		||||
        this._signInButton = null;
 | 
			
		||||
 | 
			
		||||
        this._promptBox.hide();
 | 
			
		||||
 | 
			
		||||
        // translators: this message is shown below the user list on the
 | 
			
		||||
@@ -617,7 +225,13 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._logoBin = new St.Bin({ style_class: 'login-dialog-logo-bin', y_expand: true });
 | 
			
		||||
        this._logoBin.set_y_align(Clutter.ActorAlign.END);
 | 
			
		||||
        this.backgroundStack.add_actor(this._logoBin);
 | 
			
		||||
        this._logoBin.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
 | 
			
		||||
                                                                   align_axis: Clutter.AlignAxis.X_AXIS,
 | 
			
		||||
                                                                   factor: 0.5 }));
 | 
			
		||||
        this._logoBin.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
 | 
			
		||||
                                                                   align_axis: Clutter.AlignAxis.Y_AXIS,
 | 
			
		||||
                                                                   factor: 1.0 }));
 | 
			
		||||
        this.actor.add_actor(this._logoBin);
 | 
			
		||||
        this._updateLogo();
 | 
			
		||||
 | 
			
		||||
        if (!this._userManager.is_loaded)
 | 
			
		||||
@@ -640,7 +254,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
   },
 | 
			
		||||
 | 
			
		||||
    _updateDisableUserList: function() {
 | 
			
		||||
        let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
 | 
			
		||||
        let disableUserList = this._settings.get_boolean(AuthUtil.DISABLE_USER_LIST_KEY);
 | 
			
		||||
 | 
			
		||||
        // If this is the first time around, set initial focus
 | 
			
		||||
        if (this._disableUserList == undefined && disableUserList)
 | 
			
		||||
@@ -655,8 +269,8 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateBanner: function() {
 | 
			
		||||
        let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
 | 
			
		||||
        let text = this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY);
 | 
			
		||||
        let enabled = this._settings.get_boolean(AuthUtil.BANNER_MESSAGE_KEY);
 | 
			
		||||
        let text = this._settings.get_string(AuthUtil.BANNER_MESSAGE_TEXT_KEY);
 | 
			
		||||
 | 
			
		||||
        if (enabled && text) {
 | 
			
		||||
            this._bannerLabel.set_text(text);
 | 
			
		||||
@@ -678,7 +292,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateLogo: function() {
 | 
			
		||||
        let path = this._settings.get_string(GdmUtil.LOGO_KEY);
 | 
			
		||||
        let path = this._settings.get_string(AuthUtil.LOGO_KEY);
 | 
			
		||||
 | 
			
		||||
        this._logoFileUri = path ? Gio.file_new_for_path(path).get_uri() : null;
 | 
			
		||||
        this._updateLogoTexture(this._textureCache, this._logoFileUri);
 | 
			
		||||
@@ -688,7 +302,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        this._userVerifier.clear();
 | 
			
		||||
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
        this._promptMessage.hide();
 | 
			
		||||
        this._promptMessage.opacity = 0;
 | 
			
		||||
        this._user = null;
 | 
			
		||||
        this._verifyingUser = false;
 | 
			
		||||
 | 
			
		||||
@@ -698,36 +312,69 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
            this._showUserList();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setWorking: function(working) {
 | 
			
		||||
        if (!this._workSpinner)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        Tweener.removeTweens(this._workSpinner.actor);
 | 
			
		||||
        if (working) {
 | 
			
		||||
            this._workSpinner.play();
 | 
			
		||||
            Tweener.addTween(this._workSpinner.actor,
 | 
			
		||||
                             { opacity: 255,
 | 
			
		||||
                               delay: _WORK_SPINNER_ANIMATION_DELAY,
 | 
			
		||||
                               time: _WORK_SPINNER_ANIMATION_TIME,
 | 
			
		||||
                               transition: 'linear'
 | 
			
		||||
                             });
 | 
			
		||||
        } else {
 | 
			
		||||
            Tweener.addTween(this._workSpinner.actor,
 | 
			
		||||
                             { opacity: 0,
 | 
			
		||||
                               time: _WORK_SPINNER_ANIMATION_TIME,
 | 
			
		||||
                               transition: 'linear',
 | 
			
		||||
                               onCompleteScope: this,
 | 
			
		||||
                               onComplete: function() {
 | 
			
		||||
                                   if (this._workSpinner)
 | 
			
		||||
                                       this._workSpinner.stop();
 | 
			
		||||
                               }
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _verificationFailed: function() {
 | 
			
		||||
        this._promptEntry.text = '';
 | 
			
		||||
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
        this.setWorking(false);
 | 
			
		||||
        this._setWorking(false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDefaultSessionChanged: function(client, sessionId) {
 | 
			
		||||
        this._sessionList.setActiveSession(sessionId);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showMessage: function(userVerifier, message, styleClass) {
 | 
			
		||||
    _showMessage: function(message, styleClass) {
 | 
			
		||||
        if (message) {
 | 
			
		||||
            this._promptMessage.text = message;
 | 
			
		||||
            this._promptMessage.styleClass = styleClass;
 | 
			
		||||
            this._promptMessage.show();
 | 
			
		||||
            this._promptMessage.opacity = 255;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._promptMessage.hide();
 | 
			
		||||
            this._promptMessage.opacity = 0;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onShowMessage: function(userVerifier, message, styleClass) {
 | 
			
		||||
        this._showMessage(message, styleClass);
 | 
			
		||||
        this._loginHintShown = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showLoginHint: function(verifier, message) {
 | 
			
		||||
        this._promptLoginHint.set_text(message)
 | 
			
		||||
        this._promptLoginHint.show();
 | 
			
		||||
        this._promptLoginHint.opacity = 255;
 | 
			
		||||
        this._showMessage(message, 'login-dialog-prompt-login-hint-message');
 | 
			
		||||
        this._loginHintShown = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideLoginHint: function() {
 | 
			
		||||
        this._promptLoginHint.hide();
 | 
			
		||||
        this._promptLoginHint.set_text('');
 | 
			
		||||
        if (!this._loginHintShown)
 | 
			
		||||
            return;
 | 
			
		||||
        this._showMessage('', 'login-dialog-prompt-login-hint-message');
 | 
			
		||||
        this._loginHintShown = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cancel: function() {
 | 
			
		||||
@@ -741,8 +388,6 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        this._sessionList.actor.hide();
 | 
			
		||||
        this._promptLabel.show();
 | 
			
		||||
        this._promptEntry.show();
 | 
			
		||||
        this._promptLoginHint.opacity = 0;
 | 
			
		||||
        this._promptLoginHint.show();
 | 
			
		||||
        this._promptBox.opacity = 0;
 | 
			
		||||
        this._promptBox.show();
 | 
			
		||||
        Tweener.addTween(this._promptBox,
 | 
			
		||||
@@ -768,33 +413,62 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _prepareDialog: function(forSecret, hold) {
 | 
			
		||||
        this.buttonLayout.visible = true;
 | 
			
		||||
        this.clearButtons();
 | 
			
		||||
        this._buttonBox.visible = true;
 | 
			
		||||
        this._buttonBox.destroy_all_children();
 | 
			
		||||
 | 
			
		||||
        if (!this._disableUserList || this._verifyingUser)
 | 
			
		||||
            this.addButton({ action: Lang.bind(this, this.cancel),
 | 
			
		||||
                             label: _("Cancel"),
 | 
			
		||||
                             key: Clutter.Escape },
 | 
			
		||||
                           { expand: true,
 | 
			
		||||
                             x_fill: false,
 | 
			
		||||
                             y_fill: false,
 | 
			
		||||
                             x_align: St.Align.START,
 | 
			
		||||
                             y_align: St.Align.MIDDLE });
 | 
			
		||||
        this.placeSpinner({ expand: false,
 | 
			
		||||
                            x_fill: false,
 | 
			
		||||
                            y_fill: false,
 | 
			
		||||
                            x_align: St.Align.END,
 | 
			
		||||
                            y_align: St.Align.MIDDLE });
 | 
			
		||||
        this._signInButton = this.addButton({ action: Lang.bind(this, function() {
 | 
			
		||||
                                                          hold.release();
 | 
			
		||||
                                                      }),
 | 
			
		||||
                                              label: forSecret ? C_("button", "Sign In") : _("Next"),
 | 
			
		||||
                                              default: true },
 | 
			
		||||
                                            { expand: false,
 | 
			
		||||
                                              x_fill: false,
 | 
			
		||||
                                              y_fill: false,
 | 
			
		||||
                                              x_align: St.Align.END,
 | 
			
		||||
                                              y_align: St.Align.MIDDLE });
 | 
			
		||||
        if (!this._disableUserList || this._verifyingUser) {
 | 
			
		||||
            this._cancelButton = new St.Button({ style_class: 'modal-dialog-button',
 | 
			
		||||
                                                 button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                                 reactive: true,
 | 
			
		||||
                                                 can_focus: true,
 | 
			
		||||
                                                 label: _("Cancel") });
 | 
			
		||||
            this._cancelButton.connect('clicked',
 | 
			
		||||
                                       Lang.bind(this, function() {
 | 
			
		||||
                                           this.cancel();
 | 
			
		||||
                                       }));
 | 
			
		||||
            global.stage.connect('captured-event',
 | 
			
		||||
                                 Lang.bind(this, function(actor, event) {
 | 
			
		||||
                                    if (event.type() == Clutter.EventType.KEY_PRESS &&
 | 
			
		||||
                                        event.get_key_symbol() == Clutter.KEY_Escape) {
 | 
			
		||||
                                        this.cancel();
 | 
			
		||||
                                    }
 | 
			
		||||
                                 }));
 | 
			
		||||
            this._buttonBox.add(this._cancelButton,
 | 
			
		||||
                                { expand: true,
 | 
			
		||||
                                  x_fill: false,
 | 
			
		||||
                                  y_fill: false,
 | 
			
		||||
                                  x_align: St.Align.START,
 | 
			
		||||
                                  y_align: St.Align.END });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let spinnerIcon = global.datadir + '/theme/process-working.svg';
 | 
			
		||||
        this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, _WORK_SPINNER_ICON_SIZE);
 | 
			
		||||
        this._workSpinner.actor.opacity = 0;
 | 
			
		||||
        this._workSpinner.actor.show();
 | 
			
		||||
 | 
			
		||||
        this._buttonBox.add(this._workSpinner.actor,
 | 
			
		||||
                            { expand: false,
 | 
			
		||||
                              x_fill: false,
 | 
			
		||||
                              y_fill: false,
 | 
			
		||||
                              x_align: St.Align.END,
 | 
			
		||||
                              y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        this._signInButton = new St.Button({ style_class: 'modal-dialog-button',
 | 
			
		||||
                                             button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                             reactive: true,
 | 
			
		||||
                                             can_focus: true,
 | 
			
		||||
                                             label: forSecret ? C_("button", "Sign In") : _("Next") });
 | 
			
		||||
        this._signInButton.connect('clicked',
 | 
			
		||||
                                   Lang.bind(this, function() {
 | 
			
		||||
                                       hold.release();
 | 
			
		||||
                                   }));
 | 
			
		||||
        this._signInButton.add_style_pseudo_class('default');
 | 
			
		||||
        this._buttonBox.add(this._signInButton,
 | 
			
		||||
                            { expand: true,
 | 
			
		||||
                              x_fill: false,
 | 
			
		||||
                              y_fill: false,
 | 
			
		||||
                              x_align: St.Align.END,
 | 
			
		||||
                              y_align: St.Align.END });
 | 
			
		||||
 | 
			
		||||
        this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
 | 
			
		||||
 | 
			
		||||
@@ -804,10 +478,10 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                                                        this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
 | 
			
		||||
                                                    }));
 | 
			
		||||
 | 
			
		||||
        this._promptEntryActivateId =
 | 
			
		||||
            this._promptEntry.clutter_text.connect('activate', function() {
 | 
			
		||||
                hold.release();
 | 
			
		||||
            });
 | 
			
		||||
         this._promptEntryActivateId =
 | 
			
		||||
             this._promptEntry.clutter_text.connect('activate', function() {
 | 
			
		||||
                 hold.release();
 | 
			
		||||
             });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateSensitivity: function(sensitive) {
 | 
			
		||||
@@ -825,7 +499,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hidePrompt: function() {
 | 
			
		||||
        this.setButtons([]);
 | 
			
		||||
        this._buttonBox.destroy_all_children();
 | 
			
		||||
 | 
			
		||||
        if (this._promptEntryTextChangedId > 0) {
 | 
			
		||||
            this._promptEntry.clutter_text.disconnect(this._promptEntryTextChangedId);
 | 
			
		||||
@@ -837,9 +511,8 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
            this._promptEntryActivateId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.setWorking(false);
 | 
			
		||||
        this._setWorking(false);
 | 
			
		||||
        this._promptBox.hide();
 | 
			
		||||
        this._promptLoginHint.hide();
 | 
			
		||||
 | 
			
		||||
        this._promptUser.set_child(null);
 | 
			
		||||
 | 
			
		||||
@@ -847,10 +520,10 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        this._promptEntry.set_text('');
 | 
			
		||||
 | 
			
		||||
        this._sessionList.close();
 | 
			
		||||
        this._promptLoginHint.hide();
 | 
			
		||||
 | 
			
		||||
        this.clearButtons();
 | 
			
		||||
        this._buttonBox.destroy_all_children();
 | 
			
		||||
        this._signInButton = null;
 | 
			
		||||
        this._cancelButton = null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _askQuestion: function(verifier, serviceName, question, passwordChar) {
 | 
			
		||||
@@ -867,7 +540,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                     function() {
 | 
			
		||||
                         let text = this._promptEntry.get_text();
 | 
			
		||||
                         this._updateSensitivity(false);
 | 
			
		||||
                         this.setWorking(true);
 | 
			
		||||
                         this._setWorking(true);
 | 
			
		||||
                         this._userVerifier.answerQuery(serviceName, text);
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
@@ -916,7 +589,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _startSession: function(serviceName) {
 | 
			
		||||
        Tweener.addTween(this.dialogLayout,
 | 
			
		||||
        Tweener.addTween(this.actor,
 | 
			
		||||
                         { opacity: 0,
 | 
			
		||||
                           time: _FADE_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
@@ -925,7 +598,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
                               for (let i = 0; i < children.length; i++) {
 | 
			
		||||
                                   if (children[i] != Main.layoutManager.screenShieldGroup)
 | 
			
		||||
                                       children[i].opacity = this.dialogLayout.opacity;
 | 
			
		||||
                                       children[i].opacity = this.actor.opacity;
 | 
			
		||||
                               }
 | 
			
		||||
                           },
 | 
			
		||||
                           onUpdateScope: this,
 | 
			
		||||
@@ -1081,7 +754,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _hideUserListAndLogIn: function() {
 | 
			
		||||
        this._setUserListExpanded(false);
 | 
			
		||||
        GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
 | 
			
		||||
        AuthUtil.cloneAndFadeOutActor(this._userSelectionBox);
 | 
			
		||||
        this._askForUsernameAndLogIn();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -1113,7 +786,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onUserListActivated: function(activatedItem) {
 | 
			
		||||
        let tasks = [function() {
 | 
			
		||||
                         return GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
 | 
			
		||||
                         return AuthUtil.cloneAndFadeOutActor(this._userSelectionBox);
 | 
			
		||||
                     },
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this._setUserListExpanded(false);
 | 
			
		||||
@@ -1131,6 +804,8 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
            this._userManager.disconnect(this._userManagerLoadedId);
 | 
			
		||||
            this._userManagerLoadedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Main.ctrlAltTabManager.removeGroup(this.actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _loadUserList: function() {
 | 
			
		||||
@@ -1153,20 +828,6 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                                  }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onOpened: function() {
 | 
			
		||||
        Main.ctrlAltTabManager.addGroup(this.dialogLayout,
 | 
			
		||||
                                        _("Login Window"),
 | 
			
		||||
                                        'dialog-password-symbolic',
 | 
			
		||||
                                        { sortGroup: CtrlAltTab.SortGroup.MIDDLE });
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    close: function() {
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        Main.ctrlAltTabManager.removeGroup(this.dialogLayout);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addCharacter: function(unichar) {
 | 
			
		||||
        this._promptEntry.clutter_text.insert_unichar(unichar);
 | 
			
		||||
    },
 | 
			
		||||
@@ -23,7 +23,7 @@ const Lang = imports.lang;
 | 
			
		||||
 | 
			
		||||
const LoginManager = imports.misc.loginManager;
 | 
			
		||||
 | 
			
		||||
const GdmUtil = imports.gdm.util;
 | 
			
		||||
const AuthUtil = imports.ui.auth.util;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
@@ -37,7 +37,7 @@ const PowerMenuButton = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._loginManager = LoginManager.getLoginManager();
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: AuthUtil.LOGIN_SCREEN_SCHEMA });
 | 
			
		||||
        this._settings.connect('changed::disable-restart-buttons',
 | 
			
		||||
                               Lang.bind(this, this._updateVisibility));
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										230
									
								
								js/ui/auth/sessionList.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								js/ui/auth/sessionList.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,230 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Gdm = imports.gi.Gdm;
 | 
			
		||||
 | 
			
		||||
const SessionListItem = new Lang.Class({
 | 
			
		||||
    Name: 'SessionListItem',
 | 
			
		||||
 | 
			
		||||
    _init: function(id, name) {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'login-dialog-session-list-item',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     x_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list-item-box' });
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(this._box);
 | 
			
		||||
        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
 | 
			
		||||
 | 
			
		||||
        this._dot = new St.DrawingArea({ style_class: 'login-dialog-session-list-item-dot' });
 | 
			
		||||
        this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot));
 | 
			
		||||
        this._box.add_actor(this._dot);
 | 
			
		||||
        this.setShowDot(false);
 | 
			
		||||
 | 
			
		||||
        let label = new St.Label({ style_class: 'login-dialog-session-list-item-label',
 | 
			
		||||
                                   text: name });
 | 
			
		||||
        this.actor.label_actor = label;
 | 
			
		||||
 | 
			
		||||
        this._box.add_actor(label);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setShowDot: function(show) {
 | 
			
		||||
        if (show)
 | 
			
		||||
            this._dot.opacity = 255;
 | 
			
		||||
        else
 | 
			
		||||
            this._dot.opacity = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onRepaintDot: function(area) {
 | 
			
		||||
        let cr = area.get_context();
 | 
			
		||||
        let [width, height] = area.get_surface_size();
 | 
			
		||||
        let color = area.get_theme_node().get_foreground_color();
 | 
			
		||||
 | 
			
		||||
        cr.setSourceRGBA (color.red / 255,
 | 
			
		||||
                          color.green / 255,
 | 
			
		||||
                          color.blue / 255,
 | 
			
		||||
                          color.alpha / 255);
 | 
			
		||||
        cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SessionListItem.prototype);
 | 
			
		||||
 | 
			
		||||
const SessionList = new Lang.Class({
 | 
			
		||||
    Name: 'SessionList',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.Bin();
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list',
 | 
			
		||||
                                       vertical: true});
 | 
			
		||||
        this.actor.child = this._box;
 | 
			
		||||
 | 
			
		||||
        this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
 | 
			
		||||
                                       button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                       can_focus: true,
 | 
			
		||||
                                       x_fill: true,
 | 
			
		||||
                                       y_fill: true });
 | 
			
		||||
        let box = new St.BoxLayout();
 | 
			
		||||
        this._button.add_actor(box);
 | 
			
		||||
 | 
			
		||||
        this._triangle = new St.Label({ style_class: 'login-dialog-session-list-triangle',
 | 
			
		||||
                                        text: '\u25B8' });
 | 
			
		||||
        box.add_actor(this._triangle);
 | 
			
		||||
 | 
			
		||||
        let label = new St.Label({ style_class: 'login-dialog-session-list-label',
 | 
			
		||||
                                   text: _("Session…") });
 | 
			
		||||
        box.add_actor(label);
 | 
			
		||||
 | 
			
		||||
        this._button.connect('clicked',
 | 
			
		||||
                             Lang.bind(this, this._onClicked));
 | 
			
		||||
        this._box.add_actor(this._button);
 | 
			
		||||
        this._scrollView = new St.ScrollView({ style_class: 'login-dialog-session-list-scroll-view'});
 | 
			
		||||
        this._scrollView.set_policy(Gtk.PolicyType.NEVER,
 | 
			
		||||
                                    Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
        this._box.add_actor(this._scrollView);
 | 
			
		||||
        this._itemList = new St.BoxLayout({ style_class: 'login-dialog-session-item-list',
 | 
			
		||||
                                            vertical: true });
 | 
			
		||||
        this._scrollView.add_actor(this._itemList);
 | 
			
		||||
        this._hideSessions();
 | 
			
		||||
        this.isOpen = false;
 | 
			
		||||
        this._populate();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideSessions: function() {
 | 
			
		||||
        this._itemList.can_focus = false;
 | 
			
		||||
        this._itemList.reactive = false;
 | 
			
		||||
        this._scrollView.opacity = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showSessions: function() {
 | 
			
		||||
        this._scrollView.opacity = 255;
 | 
			
		||||
        this._itemList.reactive = true;
 | 
			
		||||
        this._itemList.can_focus = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    open: function() {
 | 
			
		||||
        if (this.isOpen)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._button.add_style_pseudo_class('open');
 | 
			
		||||
        this._showSessions();
 | 
			
		||||
        this._triangle.set_text('\u25BE');
 | 
			
		||||
 | 
			
		||||
        this.isOpen = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    close: function() {
 | 
			
		||||
        if (!this.isOpen)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._button.remove_style_pseudo_class('open');
 | 
			
		||||
        this._hideSessions();
 | 
			
		||||
        this._triangle.set_text('\u25B8');
 | 
			
		||||
 | 
			
		||||
        this.isOpen = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
        if (!this.isOpen)
 | 
			
		||||
            this.open();
 | 
			
		||||
        else
 | 
			
		||||
            this.close();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateSensitivity: function(sensitive) {
 | 
			
		||||
        this._button.reactive = sensitive;
 | 
			
		||||
        this._button.can_focus = sensitive;
 | 
			
		||||
 | 
			
		||||
        for (let id in this._items)
 | 
			
		||||
            this._items[id].actor.reactive = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setActiveSession: function(sessionId) {
 | 
			
		||||
         if (sessionId == this._activeSessionId)
 | 
			
		||||
             return;
 | 
			
		||||
 | 
			
		||||
         if (this._activeSessionId)
 | 
			
		||||
             this._items[this._activeSessionId].setShowDot(false);
 | 
			
		||||
 | 
			
		||||
         this._items[sessionId].setShowDot(true);
 | 
			
		||||
         this._activeSessionId = sessionId;
 | 
			
		||||
 | 
			
		||||
         this.emit('session-activated', this._activeSessionId);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _populate: function() {
 | 
			
		||||
        this._itemList.destroy_all_children();
 | 
			
		||||
        this._activeSessionId = null;
 | 
			
		||||
        this._items = {};
 | 
			
		||||
 | 
			
		||||
        let ids = Gdm.get_session_ids();
 | 
			
		||||
        ids.sort();
 | 
			
		||||
 | 
			
		||||
        if (ids.length <= 1) {
 | 
			
		||||
            this._box.hide();
 | 
			
		||||
            this._button.hide();
 | 
			
		||||
        } else {
 | 
			
		||||
            this._button.show();
 | 
			
		||||
            this._box.show();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < ids.length; i++) {
 | 
			
		||||
            let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
 | 
			
		||||
 | 
			
		||||
            let item = new SessionListItem(ids[i], sessionName);
 | 
			
		||||
            this._itemList.add_actor(item.actor);
 | 
			
		||||
            this._items[ids[i]] = item;
 | 
			
		||||
 | 
			
		||||
            if (!this._activeSessionId)
 | 
			
		||||
                this.setActiveSession(ids[i]);
 | 
			
		||||
 | 
			
		||||
            item.connect('activate',
 | 
			
		||||
                         Lang.bind(this, function() {
 | 
			
		||||
                             this.setActiveSession(item.id);
 | 
			
		||||
                         }));
 | 
			
		||||
 | 
			
		||||
            item.actor.can_focus = this._itemList.can_focus;
 | 
			
		||||
            let signalId = this._itemList.connect('notify::can-focus',
 | 
			
		||||
                                                  Lang.bind(this, function() {
 | 
			
		||||
                                                      item.actor.can_focus = this._itemList.can_focus;
 | 
			
		||||
                                                  }));
 | 
			
		||||
            item.actor.connect('destroy',
 | 
			
		||||
                               Lang.bind(this, function() {
 | 
			
		||||
                                   this._itemList.disconnect(signalId);
 | 
			
		||||
                               }));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SessionList.prototype);
 | 
			
		||||
@@ -6,23 +6,17 @@ const Gdm  = imports.gi.Gdm;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const GnomeDesktop = imports.gi.GnomeDesktop;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const Panel = imports.ui.panel;
 | 
			
		||||
const ShellEntry = imports.ui.shellEntry;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const UserMenu = imports.ui.userMenu;
 | 
			
		||||
const UserWidget = imports.ui.userWidget;
 | 
			
		||||
 | 
			
		||||
const Batch = imports.gdm.batch;
 | 
			
		||||
const GdmUtil = imports.gdm.util;
 | 
			
		||||
const LoginDialog = imports.gdm.loginDialog;
 | 
			
		||||
const AuthUtil = imports.ui.auth.util;
 | 
			
		||||
const Batch = imports.misc.batch;
 | 
			
		||||
 | 
			
		||||
// The timeout before going back automatically to the lock screen (in seconds)
 | 
			
		||||
const IDLE_TIMEOUT = 2 * 60;
 | 
			
		||||
@@ -46,7 +40,7 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
        this._firstQuestion = true;
 | 
			
		||||
 | 
			
		||||
        this._greeterClient = new Gdm.Client();
 | 
			
		||||
        this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient, { reauthenticationOnly: true });
 | 
			
		||||
        this._userVerifier = new AuthUtil.ShellUserVerifier(this._greeterClient, { reauthenticationOnly: true });
 | 
			
		||||
        this._userVerified = false;
 | 
			
		||||
 | 
			
		||||
        this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion));
 | 
			
		||||
@@ -163,9 +157,9 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
        if (message) {
 | 
			
		||||
            this._promptMessage.text = message;
 | 
			
		||||
            this._promptMessage.styleClass = styleClass;
 | 
			
		||||
            GdmUtil.fadeInActor(this._promptMessage);
 | 
			
		||||
            AuthUtil.fadeInActor(this._promptMessage);
 | 
			
		||||
        } else {
 | 
			
		||||
            GdmUtil.fadeOutActor(this._promptMessage);
 | 
			
		||||
            AuthUtil.fadeOutActor(this._promptMessage);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -194,11 +188,11 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _showLoginHint: function(verifier, message) {
 | 
			
		||||
        this._promptLoginHint.set_text(message)
 | 
			
		||||
        GdmUtil.fadeInActor(this._promptLoginHint);
 | 
			
		||||
        AuthUtil.fadeInActor(this._promptLoginHint);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideLoginHint: function() {
 | 
			
		||||
        GdmUtil.fadeOutActor(this._promptLoginHint);
 | 
			
		||||
        AuthUtil.fadeOutActor(this._promptLoginHint);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _doUnlock: function() {
 | 
			
		||||
							
								
								
									
										251
									
								
								js/ui/auth/userList.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								js/ui/auth/userList.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,251 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const AccountsService = imports.gi.AccountsService;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Gdm = imports.gi.Gdm;
 | 
			
		||||
 | 
			
		||||
const Batch = imports.misc.batch;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const UserAvatar = imports.ui.userAvatar;
 | 
			
		||||
 | 
			
		||||
const _SCROLL_ANIMATION_TIME = 0.5;
 | 
			
		||||
 | 
			
		||||
const UserListItem = new Lang.Class({
 | 
			
		||||
    Name: 'UserListItem',
 | 
			
		||||
 | 
			
		||||
    _init: function(user) {
 | 
			
		||||
        this.user = user;
 | 
			
		||||
        this._userChangedId = this.user.connect('changed',
 | 
			
		||||
                                                 Lang.bind(this, this._onUserChanged));
 | 
			
		||||
 | 
			
		||||
        let layout = new St.BoxLayout({ vertical: false });
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     child: layout,
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._userAvatar = new UserAvatar.UserAvatar(this.user,
 | 
			
		||||
                                                     { styleClass: 'login-dialog-user-list-item-icon' });
 | 
			
		||||
        layout.add(this._userAvatar.actor);
 | 
			
		||||
        let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box',
 | 
			
		||||
                                            vertical:    true });
 | 
			
		||||
        layout.add(textLayout, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._nameLabel = new St.Label({ style_class: 'login-dialog-user-list-item-name' });
 | 
			
		||||
        this.actor.label_actor = this._nameLabel;
 | 
			
		||||
        textLayout.add(this._nameLabel,
 | 
			
		||||
                       { y_fill: false,
 | 
			
		||||
                         y_align: St.Align.MIDDLE,
 | 
			
		||||
                         expand: true });
 | 
			
		||||
 | 
			
		||||
        this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
 | 
			
		||||
                                                 scale_x: 0 });
 | 
			
		||||
        textLayout.add(this._timedLoginIndicator,
 | 
			
		||||
                       { x_fill: true,
 | 
			
		||||
                         x_align: St.Align.MIDDLE,
 | 
			
		||||
                         y_fill: false,
 | 
			
		||||
                         y_align: St.Align.END });
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
 | 
			
		||||
        this._onUserChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onUserChanged: function() {
 | 
			
		||||
        this._nameLabel.set_text(this.user.get_real_name());
 | 
			
		||||
        this._userAvatar.update();
 | 
			
		||||
        this._updateLoggedIn();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    syncStyleClasses: function() {
 | 
			
		||||
        this._updateLoggedIn();
 | 
			
		||||
 | 
			
		||||
        if (global.stage.get_key_focus() == this.actor)
 | 
			
		||||
            this.actor.add_style_pseudo_class('focus');
 | 
			
		||||
        else
 | 
			
		||||
            this.actor.remove_style_pseudo_class('focus');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateLoggedIn: function() {
 | 
			
		||||
        if (this.user.is_logged_in())
 | 
			
		||||
            this.actor.add_style_pseudo_class('logged-in');
 | 
			
		||||
        else
 | 
			
		||||
            this.actor.remove_style_pseudo_class('logged-in');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showTimedLoginIndicator: function(time) {
 | 
			
		||||
        let hold = new Batch.Hold();
 | 
			
		||||
 | 
			
		||||
        this.hideTimedLoginIndicator();
 | 
			
		||||
        Tweener.addTween(this._timedLoginIndicator,
 | 
			
		||||
                         { scale_x: 1.,
 | 
			
		||||
                           time: time,
 | 
			
		||||
                           transition: 'linear',
 | 
			
		||||
                           onComplete: function() {
 | 
			
		||||
                               hold.release();
 | 
			
		||||
                           },
 | 
			
		||||
                           onCompleteScope: this
 | 
			
		||||
                         });
 | 
			
		||||
        return hold;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideTimedLoginIndicator: function() {
 | 
			
		||||
        Tweener.removeTweens(this._timedLoginIndicator);
 | 
			
		||||
        this._timedLoginIndicator.scale_x = 0.;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(UserListItem.prototype);
 | 
			
		||||
 | 
			
		||||
const UserList = new Lang.Class({
 | 
			
		||||
    Name: 'UserList',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
 | 
			
		||||
        this.actor.set_policy(Gtk.PolicyType.NEVER,
 | 
			
		||||
                              Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                       style_class: 'login-dialog-user-list',
 | 
			
		||||
                                       pseudo_class: 'expanded' });
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(this._box);
 | 
			
		||||
        this._items = {};
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('key-focus-in', Lang.bind(this, this._moveFocusToItems));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _moveFocusToItems: function() {
 | 
			
		||||
        let hasItems = Object.keys(this._items).length > 0;
 | 
			
		||||
 | 
			
		||||
        if (!hasItems)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (global.stage.get_key_focus() != this.actor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
        if (!focusSet) {
 | 
			
		||||
            Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
 | 
			
		||||
                this._moveFocusToItems();
 | 
			
		||||
                return false;
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onItemActivated: function(activatedItem) {
 | 
			
		||||
        this.emit('activate', activatedItem);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateStyle: function(isExpanded) {
 | 
			
		||||
        let tasks = [];
 | 
			
		||||
 | 
			
		||||
        if (isExpanded)
 | 
			
		||||
            this._box.add_style_pseudo_class('expanded');
 | 
			
		||||
        else
 | 
			
		||||
            this._box.remove_style_pseudo_class('expanded');
 | 
			
		||||
 | 
			
		||||
        for (let userName in this._items) {
 | 
			
		||||
            let item = this._items[userName];
 | 
			
		||||
            item.actor.sync_hover();
 | 
			
		||||
            item.syncStyleClasses();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    scrollToItem: function(item) {
 | 
			
		||||
        let box = item.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
 | 
			
		||||
 | 
			
		||||
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
 | 
			
		||||
        Tweener.removeTweens(adjustment);
 | 
			
		||||
        Tweener.addTween (adjustment,
 | 
			
		||||
                          { value: value,
 | 
			
		||||
                            time: _SCROLL_ANIMATION_TIME,
 | 
			
		||||
                            transition: 'easeOutQuad' });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    jumpToItem: function(item) {
 | 
			
		||||
        let box = item.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
 | 
			
		||||
 | 
			
		||||
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
 | 
			
		||||
 | 
			
		||||
        adjustment.set_value(value);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getItemFromUserName: function(userName) {
 | 
			
		||||
        let item = this._items[userName];
 | 
			
		||||
 | 
			
		||||
        if (!item)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        return item;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addUser: function(user) {
 | 
			
		||||
        if (!user.is_loaded)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (user.is_system_account())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (user.locked)
 | 
			
		||||
           return;
 | 
			
		||||
 | 
			
		||||
        let userName = user.get_user_name();
 | 
			
		||||
 | 
			
		||||
        if (!userName)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.removeUser(user);
 | 
			
		||||
 | 
			
		||||
        let item = new UserListItem(user);
 | 
			
		||||
        this._box.add(item.actor, { x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._items[userName] = item;
 | 
			
		||||
 | 
			
		||||
        item.connect('activate',
 | 
			
		||||
                     Lang.bind(this, this._onItemActivated));
 | 
			
		||||
 | 
			
		||||
        // Try to keep the focused item front-and-center
 | 
			
		||||
        item.actor.connect('key-focus-in',
 | 
			
		||||
                           Lang.bind(this,
 | 
			
		||||
                                     function() {
 | 
			
		||||
                                         this.scrollToItem(item);
 | 
			
		||||
                                     }));
 | 
			
		||||
 | 
			
		||||
        this._moveFocusToItems();
 | 
			
		||||
 | 
			
		||||
        this.emit('item-added', item);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeUser: function(user) {
 | 
			
		||||
        if (!user.is_loaded)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let userName = user.get_user_name();
 | 
			
		||||
 | 
			
		||||
        if (!userName)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let item = this._items[userName];
 | 
			
		||||
 | 
			
		||||
        if (!item)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        item.actor.destroy();
 | 
			
		||||
        delete this._items[userName];
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(UserList.prototype);
 | 
			
		||||
@@ -7,8 +7,8 @@ const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Batch = imports.gdm.batch;
 | 
			
		||||
const Fprint = imports.gdm.fingerprint;
 | 
			
		||||
const Batch = imports.misc.batch;
 | 
			
		||||
const Fprint = imports.ui.auth.fingerprint;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
@@ -16,7 +16,7 @@ const PolkitAgent = imports.gi.PolkitAgent;
 | 
			
		||||
const Components = imports.ui.components;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const ShellEntry = imports.ui.shellEntry;
 | 
			
		||||
const UserMenu = imports.ui.userMenu;
 | 
			
		||||
const UserAvatar = imports.ui.userAvatar;
 | 
			
		||||
 | 
			
		||||
const DIALOG_ICON_SIZE = 48;
 | 
			
		||||
 | 
			
		||||
@@ -100,9 +100,9 @@ const AuthenticationDialog = new Lang.Class({
 | 
			
		||||
            let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
 | 
			
		||||
                                             vertical: false });
 | 
			
		||||
            messageBox.add(userBox);
 | 
			
		||||
            this._userAvatar = new UserMenu.UserAvatarWidget(this._user,
 | 
			
		||||
                                                             { iconSize: DIALOG_ICON_SIZE,
 | 
			
		||||
                                                               styleClass: 'polkit-dialog-user-icon' });
 | 
			
		||||
            this._userAvatar = new UserAvatar.UserAvatar(this._user,
 | 
			
		||||
                                                         { iconSize: DIALOG_ICON_SIZE,
 | 
			
		||||
                                                           styleClass: 'polkit-dialog-user-icon' });
 | 
			
		||||
            this._userAvatar.actor.hide();
 | 
			
		||||
            userBox.add(this._userAvatar.actor,
 | 
			
		||||
                        { x_fill:  true,
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ const GnomeSession = imports.misc.gnomeSession;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const UserMenu = imports.ui.userMenu;
 | 
			
		||||
const UserAvatar = imports.ui.userAvatar;
 | 
			
		||||
 | 
			
		||||
let _endSessionDialog = null;
 | 
			
		||||
 | 
			
		||||
@@ -360,9 +360,9 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
                                                icon_size: _DIALOG_ICON_SIZE,
 | 
			
		||||
                                                style_class: dialogContent.iconStyleClass });
 | 
			
		||||
        } else {
 | 
			
		||||
            let avatarWidget = new UserMenu.UserAvatarWidget(this._user,
 | 
			
		||||
                                                             { iconSize: _DIALOG_ICON_SIZE,
 | 
			
		||||
                                                               styleClass: dialogContent.iconStyleClass });
 | 
			
		||||
            let avatarWidget = new UserAvatar.UserAvatar(this._user,
 | 
			
		||||
                                                         { iconSize: _DIALOG_ICON_SIZE,
 | 
			
		||||
                                                           styleClass: dialogContent.iconStyleClass });
 | 
			
		||||
            this._iconBin.child = avatarWidget.actor;
 | 
			
		||||
            avatarWidget.update();
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ const Atk = imports.gi.Atk;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
const Animation = imports.ui.animation;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -187,10 +188,8 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    placeSpinner: function(layoutInfo) {
 | 
			
		||||
        /* This is here because of recursive imports */
 | 
			
		||||
        const Panel = imports.ui.panel;
 | 
			
		||||
        let spinnerIcon = global.datadir + '/theme/process-working.svg';
 | 
			
		||||
        this._workSpinner = new Panel.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
 | 
			
		||||
        this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
 | 
			
		||||
        this._workSpinner.actor.opacity = 0;
 | 
			
		||||
        this._workSpinner.actor.show();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ const Signals = imports.signals;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const Animation = imports.ui.animation;
 | 
			
		||||
const Config = imports.misc.config;
 | 
			
		||||
const CtrlAltTab = imports.ui.ctrlAltTab;
 | 
			
		||||
const DND = imports.ui.dnd;
 | 
			
		||||
@@ -29,7 +30,6 @@ const PANEL_ICON_SIZE = 24;
 | 
			
		||||
 | 
			
		||||
const BUTTON_DND_ACTIVATION_TIMEOUT = 250;
 | 
			
		||||
 | 
			
		||||
const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
 | 
			
		||||
const SPINNER_ANIMATION_TIME = 0.2;
 | 
			
		||||
 | 
			
		||||
// To make sure the panel corners blend nicely with the panel,
 | 
			
		||||
@@ -75,81 +75,6 @@ function _unpremultiply(color) {
 | 
			
		||||
                               blue: blue, alpha: color.alpha });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const Animation = new Lang.Class({
 | 
			
		||||
    Name: 'Animation',
 | 
			
		||||
 | 
			
		||||
    _init: function(filename, width, height, speed) {
 | 
			
		||||
        this.actor = new St.Bin();
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
        this._speed = speed;
 | 
			
		||||
 | 
			
		||||
        this._isLoaded = false;
 | 
			
		||||
        this._isPlaying = false;
 | 
			
		||||
        this._timeoutId = 0;
 | 
			
		||||
        this._frame = 0;
 | 
			
		||||
        this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height,
 | 
			
		||||
                                                                            Lang.bind(this, this._animationsLoaded));
 | 
			
		||||
        this.actor.set_child(this._animations);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    play: function() {
 | 
			
		||||
        if (this._isLoaded && this._timeoutId == 0) {
 | 
			
		||||
            if (this._frame == 0)
 | 
			
		||||
                this._showFrame(0);
 | 
			
		||||
 | 
			
		||||
            this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._isPlaying = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    stop: function() {
 | 
			
		||||
        if (this._timeoutId > 0) {
 | 
			
		||||
            Mainloop.source_remove(this._timeoutId);
 | 
			
		||||
            this._timeoutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._isPlaying = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showFrame: function(frame) {
 | 
			
		||||
        let oldFrameActor = this._animations.get_child_at_index(this._frame);
 | 
			
		||||
        if (oldFrameActor)
 | 
			
		||||
            oldFrameActor.hide();
 | 
			
		||||
 | 
			
		||||
        this._frame = (frame % this._animations.get_n_children());
 | 
			
		||||
 | 
			
		||||
        let newFrameActor = this._animations.get_child_at_index(this._frame);
 | 
			
		||||
        if (newFrameActor)
 | 
			
		||||
            newFrameActor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _update: function() {
 | 
			
		||||
        this._showFrame(this._frame + 1);
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _animationsLoaded: function() {
 | 
			
		||||
        this._isLoaded = true;
 | 
			
		||||
 | 
			
		||||
        if (this._isPlaying)
 | 
			
		||||
            this.play();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
        this.stop();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const AnimatedIcon = new Lang.Class({
 | 
			
		||||
    Name: 'AnimatedIcon',
 | 
			
		||||
    Extends: Animation,
 | 
			
		||||
 | 
			
		||||
    _init: function(filename, size) {
 | 
			
		||||
        this.parent(filename, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const TextShadower = new Lang.Class({
 | 
			
		||||
    Name: 'TextShadower',
 | 
			
		||||
 | 
			
		||||
@@ -360,7 +285,7 @@ const AppMenuButton = new Lang.Class({
 | 
			
		||||
        if (!success || this._spinnerIcon == icon)
 | 
			
		||||
            return;
 | 
			
		||||
        this._spinnerIcon = icon;
 | 
			
		||||
        this._spinner = new AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE);
 | 
			
		||||
        this._spinner = new Animation.AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE);
 | 
			
		||||
        this._container.add_actor(this._spinner.actor);
 | 
			
		||||
        this._spinner.actor.hide();
 | 
			
		||||
        this._spinner.actor.lower_bottom();
 | 
			
		||||
@@ -931,7 +856,7 @@ const PANEL_ITEM_IMPLEMENTATIONS = {
 | 
			
		||||
    'battery': imports.ui.status.power.Indicator,
 | 
			
		||||
    'lockScreen': imports.ui.status.lockScreenMenu.Indicator,
 | 
			
		||||
    'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
 | 
			
		||||
    'powerMenu': imports.gdm.powerMenu.PowerMenuButton,
 | 
			
		||||
    'powerMenu': imports.ui.auth.powerMenu.PowerMenuButton,
 | 
			
		||||
    'userMenu': imports.ui.userMenu.UserMenuButton
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ const _modes = {
 | 
			
		||||
        hasNotifications: true,
 | 
			
		||||
        isGreeter: true,
 | 
			
		||||
        isPrimary: true,
 | 
			
		||||
        unlockDialog: imports.gdm.loginDialog.LoginDialog,
 | 
			
		||||
        unlockDialog: imports.ui.auth.loginDialog.LoginDialog,
 | 
			
		||||
        components: ['polkitAgent'],
 | 
			
		||||
        panel: {
 | 
			
		||||
            left: [],
 | 
			
		||||
@@ -89,7 +89,7 @@ const _modes = {
 | 
			
		||||
        hasNotifications: true,
 | 
			
		||||
        isLocked: false,
 | 
			
		||||
        isPrimary: true,
 | 
			
		||||
        unlockDialog: imports.ui.unlockDialog.UnlockDialog,
 | 
			
		||||
        unlockDialog: imports.ui.auth.unlockDialog.UnlockDialog,
 | 
			
		||||
        components: ['networkAgent', 'polkitAgent', 'telepathyClient',
 | 
			
		||||
                     'keyring', 'recorder', 'autorunManager', 'automountManager'],
 | 
			
		||||
        panel: {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								js/ui/userAvatar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								js/ui/userAvatar.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
const DIALOG_ICON_SIZE = 64;
 | 
			
		||||
 | 
			
		||||
// Adapted from gdm/gui/user-switch-applet/applet.c
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
 | 
			
		||||
// Copyright (C) 2008,2009 Red Hat, Inc.
 | 
			
		||||
 | 
			
		||||
const UserAvatar = new Lang.Class({
 | 
			
		||||
    Name: 'UserAvatar',
 | 
			
		||||
 | 
			
		||||
    _init: function(user, params) {
 | 
			
		||||
        this._user = user;
 | 
			
		||||
        params = Params.parse(params, { reactive: false,
 | 
			
		||||
                                        iconSize: DIALOG_ICON_SIZE,
 | 
			
		||||
                                        styleClass: 'status-chooser-user-icon' });
 | 
			
		||||
        this._iconSize = params.iconSize;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Bin({ style_class: params.styleClass,
 | 
			
		||||
                                  track_hover: params.reactive,
 | 
			
		||||
                                  reactive: params.reactive });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setSensitive: function(sensitive) {
 | 
			
		||||
        this.actor.can_focus = sensitive;
 | 
			
		||||
        this.actor.reactive = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    update: function() {
 | 
			
		||||
        let iconFile = this._user.get_icon_file();
 | 
			
		||||
        if (iconFile && !GLib.file_test(iconFile, GLib.FileTest.EXISTS))
 | 
			
		||||
            iconFile = null;
 | 
			
		||||
 | 
			
		||||
        if (iconFile) {
 | 
			
		||||
            let file = Gio.File.new_for_path(iconFile);
 | 
			
		||||
            this.actor.child = null;
 | 
			
		||||
            this.actor.style = 'background-image: url("%s");'.format(iconFile);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.actor.style = null;
 | 
			
		||||
            this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic',
 | 
			
		||||
                                             icon_size: this._iconSize });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -21,6 +21,7 @@ const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const UserAvatar = imports.ui.userAvatar;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
 | 
			
		||||
@@ -57,48 +58,6 @@ const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session
 | 
			
		||||
 | 
			
		||||
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
 | 
			
		||||
 | 
			
		||||
// Adapted from gdm/gui/user-switch-applet/applet.c
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
 | 
			
		||||
// Copyright (C) 2008,2009 Red Hat, Inc.
 | 
			
		||||
 | 
			
		||||
const UserAvatarWidget = new Lang.Class({
 | 
			
		||||
    Name: 'UserAvatarWidget',
 | 
			
		||||
 | 
			
		||||
    _init: function(user, params) {
 | 
			
		||||
        this._user = user;
 | 
			
		||||
        params = Params.parse(params, { reactive: false,
 | 
			
		||||
                                        iconSize: DIALOG_ICON_SIZE,
 | 
			
		||||
                                        styleClass: 'status-chooser-user-icon' });
 | 
			
		||||
        this._iconSize = params.iconSize;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Bin({ style_class: params.styleClass,
 | 
			
		||||
                                  track_hover: params.reactive,
 | 
			
		||||
                                  reactive: params.reactive });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setSensitive: function(sensitive) {
 | 
			
		||||
        this.actor.can_focus = sensitive;
 | 
			
		||||
        this.actor.reactive = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    update: function() {
 | 
			
		||||
        let iconFile = this._user.get_icon_file();
 | 
			
		||||
        if (iconFile && !GLib.file_test(iconFile, GLib.FileTest.EXISTS))
 | 
			
		||||
            iconFile = null;
 | 
			
		||||
 | 
			
		||||
        if (iconFile) {
 | 
			
		||||
            let file = Gio.File.new_for_path(iconFile);
 | 
			
		||||
            this.actor.child = null;
 | 
			
		||||
            this.actor.style = 'background-image: url("%s");'.format(iconFile);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.actor.style = null;
 | 
			
		||||
            this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic',
 | 
			
		||||
                                             icon_size: this._iconSize });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const IMStatusItem = new Lang.Class({
 | 
			
		||||
    Name: 'IMStatusItem',
 | 
			
		||||
    Extends: PopupMenu.PopupBaseMenuItem,
 | 
			
		||||
@@ -170,7 +129,7 @@ const IMStatusChooserItem = new Lang.Class({
 | 
			
		||||
        this._userManager = AccountsService.UserManager.get_default();
 | 
			
		||||
        this._user = this._userManager.get_user(GLib.get_user_name());
 | 
			
		||||
 | 
			
		||||
        this._avatar = new UserAvatarWidget(this._user, { reactive: true });
 | 
			
		||||
        this._avatar = new UserAvatar.UserAvatar(this._user, { reactive: true });
 | 
			
		||||
        this._iconBin = new St.Button({ child: this._avatar.actor });
 | 
			
		||||
        this.addActor(this._iconBin);
 | 
			
		||||
 | 
			
		||||
@@ -908,7 +867,7 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
            let session = sessions[i];
 | 
			
		||||
            let userEntry = new St.BoxLayout({ style_class: 'login-dialog-user-list-item',
 | 
			
		||||
                                               vertical: false });
 | 
			
		||||
            let avatar = new UserAvatarWidget(session.user);
 | 
			
		||||
            let avatar = new UserAvatar.UserAvatar(session.user);
 | 
			
		||||
            avatar.update();
 | 
			
		||||
            userEntry.add(avatar.actor);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ const AccountsService = imports.gi.AccountsService;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const UserMenu = imports.ui.userMenu;
 | 
			
		||||
const UserAvatar = imports.ui.userAvatar;
 | 
			
		||||
 | 
			
		||||
const UserWidget = new Lang.Class({
 | 
			
		||||
    Name: 'UserWidget',
 | 
			
		||||
@@ -18,7 +18,7 @@ const UserWidget = new Lang.Class({
 | 
			
		||||
                                        vertical: false });
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
 | 
			
		||||
        this._avatar = new UserMenu.UserAvatarWidget(user);
 | 
			
		||||
        this._avatar = new UserAvatar.UserAvatar(user);
 | 
			
		||||
        this.actor.add(this._avatar.actor,
 | 
			
		||||
                       { x_fill: true, y_fill: true });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user