~darkxst/ubuntu/saucy/gnome-shell/upstart_log

« back to all changes in this revision

Viewing changes to .pc/git_fix_dialog_activate_signals.patch/js/gdm/loginDialog.js

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-05-31 12:01:12 UTC
  • mfrom: (1.1.49) (19.1.36 experimental)
  • Revision ID: package-import@ubuntu.com-20130531120112-ew91khxf051x9i2r
Tags: 3.8.2-1ubuntu1
* Merge with Debian (LP: #1185869, #1185721). Remaining changes:
  - debian/control.in:
    + Build-depend on libsystemd-login-dev & libsystemd-daemon-dev
    + Depend on gdm instead of gdm3
    + Don't recommend gnome-session-fallback
  - debian/patches/40_change-pam-name-to-match-gdm.patch:
  - debian/patches/revert-suspend-break.patch:
    + Disabled, not needed on Ubuntu
  - debian/patches/ubuntu-lightdm-user-switching.patch:
    + Allow user switching when using LightDM. Thanks Gerhard Stein
      for rebasing against gnome-shell 3.8!
  - debian/patches/ubuntu_lock_on_suspend.patch
    + Respect Ubuntu's lock-on-suspend setting.
      Disabled until it can be rewritten.
  - debian/patches/git_relock_screen_after_crash.patch:
    + Add Upstream fix for unlocked session after crash (LP: #1064584)
* Note that the new GNOME Classic mode (which requires installing
  gnome-shell-extensions) won't work until gnome-session 3.8 is
  available in Ubuntu

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
2
 
/*
3
 
 * Copyright 2011 Red Hat, Inc
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2, or (at your option)
8
 
 * any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18
 
 * 02111-1307, USA.
19
 
 */
20
 
 
21
 
const AccountsService = imports.gi.AccountsService;
22
 
const Clutter = imports.gi.Clutter;
23
 
const CtrlAltTab = imports.ui.ctrlAltTab;
24
 
const Gio = imports.gi.Gio;
25
 
const GLib = imports.gi.GLib;
26
 
const Gtk = imports.gi.Gtk;
27
 
const Mainloop = imports.mainloop;
28
 
const Meta = imports.gi.Meta;
29
 
const Lang = imports.lang;
30
 
const Pango = imports.gi.Pango;
31
 
const Signals = imports.signals;
32
 
const Shell = imports.gi.Shell;
33
 
const St = imports.gi.St;
34
 
const Gdm = imports.gi.Gdm;
35
 
 
36
 
const Batch = imports.gdm.batch;
37
 
const Fprint = imports.gdm.fingerprint;
38
 
const GdmUtil = imports.gdm.util;
39
 
const Lightbox = imports.ui.lightbox;
40
 
const Main = imports.ui.main;
41
 
const ModalDialog = imports.ui.modalDialog;
42
 
const Tweener = imports.ui.tweener;
43
 
const UserMenu = imports.ui.userMenu;
44
 
 
45
 
const _RESIZE_ANIMATION_TIME = 0.25;
46
 
const _SCROLL_ANIMATION_TIME = 0.5;
47
 
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
48
 
const _LOGO_ICON_NAME_SIZE = 48;
49
 
 
50
 
let _loginDialog = null;
51
 
 
52
 
function _smoothlyResizeActor(actor, width, height) {
53
 
    let finalWidth;
54
 
    let finalHeight;
55
 
 
56
 
    if (width < 0)
57
 
        finalWidth = actor.width;
58
 
    else
59
 
        finalWidth = width;
60
 
 
61
 
    if (height < 0)
62
 
        finalHeight = actor.height;
63
 
    else
64
 
        finalHeight = height;
65
 
 
66
 
    actor.set_size(actor.width, actor.height);
67
 
 
68
 
    if (actor.width == finalWidth && actor.height == finalHeight)
69
 
        return null;
70
 
 
71
 
    let hold = new Batch.Hold();
72
 
 
73
 
    Tweener.addTween(actor,
74
 
                     { width: finalWidth,
75
 
                       height: finalHeight,
76
 
                       time: _RESIZE_ANIMATION_TIME,
77
 
                       transition: 'easeOutQuad',
78
 
                       onComplete: Lang.bind(this, function() {
79
 
                                       hold.release();
80
 
                                   })
81
 
                     });
82
 
    return hold;
83
 
}
84
 
 
85
 
const UserListItem = new Lang.Class({
86
 
    Name: 'UserListItem',
87
 
 
88
 
    _init: function(user) {
89
 
        this.user = user;
90
 
        this._userChangedId = this.user.connect('changed',
91
 
                                                 Lang.bind(this, this._onUserChanged));
92
 
 
93
 
        let layout = new St.BoxLayout({ vertical: false });
94
 
        this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
95
 
                                     can_focus: true,
96
 
                                     child: layout,
97
 
                                     reactive: true,
98
 
                                     x_align: St.Align.START,
99
 
                                     x_fill: true });
100
 
 
101
 
        this._userAvatar = new UserMenu.UserAvatarWidget(this.user,
102
 
                                                         { styleClass: 'login-dialog-user-list-item-icon' });
103
 
        layout.add(this._userAvatar.actor);
104
 
        let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box',
105
 
                                            vertical:    true });
106
 
        layout.add(textLayout, { expand: true });
107
 
 
108
 
        this._nameLabel = new St.Label({ style_class: 'login-dialog-user-list-item-name' });
109
 
        this.actor.label_actor = this._nameLabel;
110
 
        textLayout.add(this._nameLabel,
111
 
                       { y_fill: false,
112
 
                         y_align: St.Align.MIDDLE,
113
 
                         expand: true });
114
 
 
115
 
        this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
116
 
                                                 scale_x: 0 });
117
 
        textLayout.add(this._timedLoginIndicator,
118
 
                       { x_fill: true,
119
 
                         x_align: St.Align.MIDDLE,
120
 
                         y_fill: false,
121
 
                         y_align: St.Align.END });
122
 
 
123
 
        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
124
 
        this._onUserChanged();
125
 
    },
126
 
 
127
 
    _onUserChanged: function() {
128
 
        this._nameLabel.set_text(this.user.get_real_name());
129
 
        this._userAvatar.update();
130
 
        this._updateLoggedIn();
131
 
    },
132
 
 
133
 
    syncStyleClasses: function() {
134
 
        this._updateLoggedIn();
135
 
 
136
 
        if (global.stage.get_key_focus() == this.actor)
137
 
            this.actor.add_style_pseudo_class('focus');
138
 
        else
139
 
            this.actor.remove_style_pseudo_class('focus');
140
 
    },
141
 
 
142
 
    _updateLoggedIn: function() {
143
 
        if (this.user.is_logged_in())
144
 
            this.actor.add_style_pseudo_class('logged-in');
145
 
        else
146
 
            this.actor.remove_style_pseudo_class('logged-in');
147
 
    },
148
 
 
149
 
    _onClicked: function() {
150
 
        this.emit('activate');
151
 
    },
152
 
 
153
 
    showTimedLoginIndicator: function(time) {
154
 
        let hold = new Batch.Hold();
155
 
 
156
 
        this.hideTimedLoginIndicator();
157
 
        Tweener.addTween(this._timedLoginIndicator,
158
 
                         { scale_x: 1.,
159
 
                           time: time,
160
 
                           transition: 'linear',
161
 
                           onComplete: function() {
162
 
                               hold.release();
163
 
                           },
164
 
                           onCompleteScope: this
165
 
                         });
166
 
        return hold;
167
 
    },
168
 
 
169
 
    hideTimedLoginIndicator: function() {
170
 
        Tweener.removeTweens(this._timedLoginIndicator);
171
 
        this._timedLoginIndicator.scale_x = 0.;
172
 
    }
173
 
});
174
 
Signals.addSignalMethods(UserListItem.prototype);
175
 
 
176
 
const UserList = new Lang.Class({
177
 
    Name: 'UserList',
178
 
 
179
 
    _init: function() {
180
 
        this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
181
 
        this.actor.set_policy(Gtk.PolicyType.NEVER,
182
 
                              Gtk.PolicyType.AUTOMATIC);
183
 
 
184
 
        this._box = new St.BoxLayout({ vertical: true,
185
 
                                       style_class: 'login-dialog-user-list',
186
 
                                       pseudo_class: 'expanded' });
187
 
 
188
 
        this.actor.add_actor(this._box);
189
 
        this._items = {};
190
 
 
191
 
        this.actor.connect('key-focus-in', Lang.bind(this, this._moveFocusToItems));
192
 
    },
193
 
 
194
 
    _moveFocusToItems: function() {
195
 
        let hasItems = Object.keys(this._items).length > 0;
196
 
 
197
 
        if (!hasItems)
198
 
            return;
199
 
 
200
 
        if (global.stage.get_key_focus() != this.actor)
201
 
            return;
202
 
 
203
 
        let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
204
 
        if (!focusSet) {
205
 
            Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
206
 
                this._moveFocusToItems();
207
 
                return false;
208
 
            }));
209
 
        }
210
 
    },
211
 
 
212
 
    _showItem: function(item) {
213
 
        let tasks = [function() {
214
 
                         return GdmUtil.fadeInActor(item.actor);
215
 
                     }];
216
 
 
217
 
        let batch = new Batch.ConsecutiveBatch(this, tasks);
218
 
        return batch.run();
219
 
    },
220
 
 
221
 
    _onItemActivated: function(activatedItem) {
222
 
        this.emit('activate', activatedItem);
223
 
    },
224
 
 
225
 
    giveUpWhitespace: function() {
226
 
        let container = this.actor.get_parent();
227
 
 
228
 
        container.child_set(this.actor, { expand: false });
229
 
    },
230
 
 
231
 
    takeOverWhitespace: function() {
232
 
        let container = this.actor.get_parent();
233
 
 
234
 
        container.child_set(this.actor, { expand: true });
235
 
    },
236
 
 
237
 
    pinInPlace: function() {
238
 
        this._box.set_size(this._box.width, this._box.height);
239
 
    },
240
 
 
241
 
    shrinkToNaturalHeight: function() {
242
 
        let oldWidth = this._box.width;
243
 
        let oldHeight = this._box.height;
244
 
        this._box.set_size(-1, -1);
245
 
        let [minHeight, naturalHeight] = this._box.get_preferred_height(-1);
246
 
        this._box.set_size(oldWidth, oldHeight);
247
 
 
248
 
        let batch = new Batch.ConsecutiveBatch(this,
249
 
                                               [function() {
250
 
                                                    return _smoothlyResizeActor(this._box, -1, naturalHeight);
251
 
                                                },
252
 
 
253
 
                                                function() {
254
 
                                                    this._box.set_size(-1, -1);
255
 
                                                }
256
 
                                               ]);
257
 
 
258
 
        return batch.run();
259
 
    },
260
 
 
261
 
    hideItemsExcept: function(exception) {
262
 
        let tasks = [];
263
 
 
264
 
        for (let userName in this._items) {
265
 
            let item = this._items[userName];
266
 
 
267
 
            item.actor.set_hover(false);
268
 
            item.actor.reactive = false;
269
 
            item.actor.can_focus = false;
270
 
            item.syncStyleClasses();
271
 
            item._timedLoginIndicator.scale_x = 0.;
272
 
            if (item != exception)
273
 
                tasks.push(function() {
274
 
                    return GdmUtil.fadeOutActor(item.actor);
275
 
                });
276
 
        }
277
 
 
278
 
        let batch = new Batch.ConsecutiveBatch(this,
279
 
                                               [function() {
280
 
                                                    return GdmUtil.fadeOutActor(this.actor.vscroll);
281
 
                                                },
282
 
 
283
 
                                                new Batch.ConcurrentBatch(this, tasks),
284
 
 
285
 
                                                function() {
286
 
                                                    this._box.remove_style_pseudo_class('expanded');
287
 
                                                }
288
 
                                               ]);
289
 
 
290
 
        return batch.run();
291
 
    },
292
 
 
293
 
    hideItems: function() {
294
 
        return this.hideItemsExcept(null);
295
 
    },
296
 
 
297
 
    _getExpandedHeight: function() {
298
 
        let hiddenActors = [];
299
 
        for (let userName in this._items) {
300
 
            let item = this._items[userName];
301
 
            if (!item.actor.visible) {
302
 
                item.actor.show();
303
 
                hiddenActors.push(item.actor);
304
 
            }
305
 
        }
306
 
 
307
 
        if (!this._box.visible) {
308
 
            this._box.show();
309
 
            hiddenActors.push(this._box);
310
 
        }
311
 
 
312
 
        this._box.set_size(-1, -1);
313
 
        let [minHeight, naturalHeight] = this._box.get_preferred_height(-1);
314
 
 
315
 
        for (let i = 0; i < hiddenActors.length; i++) {
316
 
            let actor = hiddenActors[i];
317
 
            actor.hide();
318
 
        }
319
 
 
320
 
        return naturalHeight;
321
 
    },
322
 
 
323
 
    showItems: function() {
324
 
        let tasks = [];
325
 
 
326
 
        for (let userName in this._items) {
327
 
            let item = this._items[userName];
328
 
            item.actor.sync_hover();
329
 
            item.actor.reactive = true;
330
 
            item.actor.can_focus = true;
331
 
            item.syncStyleClasses();
332
 
            tasks.push(function() {
333
 
                return this._showItem(item);
334
 
            });
335
 
        }
336
 
 
337
 
        let batch = new Batch.ConsecutiveBatch(this,
338
 
                                               [function() {
339
 
                                                    this.takeOverWhitespace();
340
 
                                                },
341
 
 
342
 
                                                function() {
343
 
                                                    let fullHeight = this._getExpandedHeight();
344
 
                                                    return _smoothlyResizeActor(this._box, -1, fullHeight);
345
 
                                                },
346
 
 
347
 
                                                function() {
348
 
                                                    this._box.add_style_pseudo_class('expanded');
349
 
                                                },
350
 
 
351
 
                                                new Batch.ConcurrentBatch(this, tasks),
352
 
 
353
 
                                                function() {
354
 
                                                    this.actor.set_size(-1, -1);
355
 
                                                },
356
 
 
357
 
                                                function() {
358
 
                                                    return GdmUtil.fadeInActor(this.actor.vscroll);
359
 
                                                }]);
360
 
        return batch.run();
361
 
    },
362
 
 
363
 
    scrollToItem: function(item) {
364
 
        let box = item.actor.get_allocation_box();
365
 
 
366
 
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
367
 
 
368
 
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
369
 
        Tweener.removeTweens(adjustment);
370
 
        Tweener.addTween (adjustment,
371
 
                          { value: value,
372
 
                            time: _SCROLL_ANIMATION_TIME,
373
 
                            transition: 'easeOutQuad' });
374
 
    },
375
 
 
376
 
    jumpToItem: function(item) {
377
 
        let box = item.actor.get_allocation_box();
378
 
 
379
 
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
380
 
 
381
 
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
382
 
 
383
 
        adjustment.set_value(value);
384
 
    },
385
 
 
386
 
    getItemFromUserName: function(userName) {
387
 
        let item = this._items[userName];
388
 
 
389
 
        if (!item)
390
 
            return null;
391
 
 
392
 
        return item;
393
 
    },
394
 
 
395
 
    addUser: function(user) {
396
 
        if (!user.is_loaded)
397
 
            return;
398
 
 
399
 
        if (user.is_system_account())
400
 
            return;
401
 
 
402
 
        if (user.locked)
403
 
           return;
404
 
 
405
 
        let userName = user.get_user_name();
406
 
 
407
 
        if (!userName)
408
 
            return;
409
 
 
410
 
        this.removeUser(user);
411
 
 
412
 
        let item = new UserListItem(user);
413
 
        this._box.add(item.actor, { x_fill: true });
414
 
 
415
 
        this._items[userName] = item;
416
 
 
417
 
        item.connect('activate',
418
 
                     Lang.bind(this, this._onItemActivated));
419
 
 
420
 
        // Try to keep the focused item front-and-center
421
 
        item.actor.connect('key-focus-in',
422
 
                           Lang.bind(this,
423
 
                                     function() {
424
 
                                         this.scrollToItem(item);
425
 
                                     }));
426
 
 
427
 
        this._moveFocusToItems();
428
 
 
429
 
        this.emit('item-added', item);
430
 
    },
431
 
 
432
 
    removeUser: function(user) {
433
 
        if (!user.is_loaded)
434
 
            return;
435
 
 
436
 
        let userName = user.get_user_name();
437
 
 
438
 
        if (!userName)
439
 
            return;
440
 
 
441
 
        let item = this._items[userName];
442
 
 
443
 
        if (!item)
444
 
            return;
445
 
 
446
 
        item.actor.destroy();
447
 
        delete this._items[userName];
448
 
    }
449
 
});
450
 
Signals.addSignalMethods(UserList.prototype);
451
 
 
452
 
const SessionListItem = new Lang.Class({
453
 
    Name: 'SessionListItem',
454
 
 
455
 
    _init: function(id, name) {
456
 
        this.id = id;
457
 
 
458
 
        this.actor = new St.Button({ style_class: 'login-dialog-session-list-item',
459
 
                                     can_focus: true,
460
 
                                     reactive: true,
461
 
                                     x_fill: true,
462
 
                                     x_align: St.Align.START });
463
 
 
464
 
        this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list-item-box' });
465
 
 
466
 
        this.actor.add_actor(this._box);
467
 
        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
468
 
 
469
 
        this._dot = new St.DrawingArea({ style_class: 'login-dialog-session-list-item-dot' });
470
 
        this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot));
471
 
        this._box.add_actor(this._dot);
472
 
        this.setShowDot(false);
473
 
 
474
 
        let label = new St.Label({ style_class: 'login-dialog-session-list-item-label',
475
 
                                   text: name });
476
 
        this.actor.label_actor = label;
477
 
 
478
 
        this._box.add_actor(label);
479
 
    },
480
 
 
481
 
    setShowDot: function(show) {
482
 
        if (show)
483
 
            this._dot.opacity = 255;
484
 
        else
485
 
            this._dot.opacity = 0;
486
 
    },
487
 
 
488
 
    _onRepaintDot: function(area) {
489
 
        let cr = area.get_context();
490
 
        let [width, height] = area.get_surface_size();
491
 
        let color = area.get_theme_node().get_foreground_color();
492
 
 
493
 
        cr.setSourceRGBA (color.red / 255,
494
 
                          color.green / 255,
495
 
                          color.blue / 255,
496
 
                          color.alpha / 255);
497
 
        cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
498
 
        cr.fill();
499
 
    },
500
 
 
501
 
    _onClicked: function() {
502
 
        this.emit('activate');
503
 
    }
504
 
});
505
 
Signals.addSignalMethods(SessionListItem.prototype);
506
 
 
507
 
const SessionList = new Lang.Class({
508
 
    Name: 'SessionList',
509
 
 
510
 
    _init: function() {
511
 
        this.actor = new St.Bin();
512
 
 
513
 
        this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list',
514
 
                                       vertical: true});
515
 
        this.actor.child = this._box;
516
 
 
517
 
        this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
518
 
                                       can_focus: true,
519
 
                                       x_fill: true,
520
 
                                       y_fill: true });
521
 
        let box = new St.BoxLayout();
522
 
        this._button.add_actor(box);
523
 
 
524
 
        this._triangle = new St.Label({ style_class: 'login-dialog-session-list-triangle',
525
 
                                        text: '\u25B8' });
526
 
        box.add_actor(this._triangle);
527
 
 
528
 
        let label = new St.Label({ style_class: 'login-dialog-session-list-label',
529
 
                                   text: _("Session...") });
530
 
        box.add_actor(label);
531
 
 
532
 
        this._button.connect('clicked',
533
 
                             Lang.bind(this, this._onClicked));
534
 
        this._box.add_actor(this._button);
535
 
        this._scrollView = new St.ScrollView({ style_class: 'login-dialog-session-list-scroll-view'});
536
 
        this._scrollView.set_policy(Gtk.PolicyType.NEVER,
537
 
                                    Gtk.PolicyType.AUTOMATIC);
538
 
        this._box.add_actor(this._scrollView);
539
 
        this._itemList = new St.BoxLayout({ style_class: 'login-dialog-session-item-list',
540
 
                                            vertical: true });
541
 
        this._scrollView.add_actor(this._itemList);
542
 
        this._scrollView.hide();
543
 
        this.isOpen = false;
544
 
        this._populate();
545
 
    },
546
 
 
547
 
    open: function() {
548
 
        if (this.isOpen)
549
 
            return;
550
 
 
551
 
        this._button.add_style_pseudo_class('open');
552
 
        this._scrollView.show();
553
 
        this._triangle.set_text('\u25BE');
554
 
 
555
 
        this.isOpen = true;
556
 
    },
557
 
 
558
 
    close: function() {
559
 
        if (!this.isOpen)
560
 
            return;
561
 
 
562
 
        this._button.remove_style_pseudo_class('open');
563
 
        this._scrollView.hide();
564
 
        this._triangle.set_text('\u25B8');
565
 
 
566
 
        this.isOpen = false;
567
 
    },
568
 
 
569
 
    _onClicked: function() {
570
 
        if (!this.isOpen)
571
 
            this.open();
572
 
        else
573
 
            this.close();
574
 
    },
575
 
 
576
 
    setActiveSession: function(sessionId) {
577
 
         if (sessionId == this._activeSessionId)
578
 
             return;
579
 
 
580
 
         if (this._activeSessionId)
581
 
             this._items[this._activeSessionId].setShowDot(false);
582
 
 
583
 
         this._items[sessionId].setShowDot(true);
584
 
         this._activeSessionId = sessionId;
585
 
 
586
 
         this.emit('session-activated', this._activeSessionId);
587
 
    },
588
 
 
589
 
    _populate: function() {
590
 
        this._itemList.destroy_all_children();
591
 
        this._activeSessionId = null;
592
 
        this._items = {};
593
 
 
594
 
        let ids = Gdm.get_session_ids();
595
 
        ids.sort();
596
 
 
597
 
        if (ids.length <= 1) {
598
 
            this._box.hide();
599
 
            this._button.hide();
600
 
        } else {
601
 
            this._button.show();
602
 
            this._box.show();
603
 
        }
604
 
 
605
 
        for (let i = 0; i < ids.length; i++) {
606
 
            let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
607
 
 
608
 
            let item = new SessionListItem(ids[i], sessionName);
609
 
            this._itemList.add_actor(item.actor);
610
 
            this._items[ids[i]] = item;
611
 
 
612
 
            if (!this._activeSessionId)
613
 
                this.setActiveSession(ids[i]);
614
 
 
615
 
            item.connect('activate',
616
 
                         Lang.bind(this, function() {
617
 
                             this.setActiveSession(item.id);
618
 
                         }));
619
 
        }
620
 
    }
621
 
});
622
 
Signals.addSignalMethods(SessionList.prototype);
623
 
 
624
 
const LoginDialog = new Lang.Class({
625
 
    Name: 'LoginDialog',
626
 
    Extends: ModalDialog.ModalDialog,
627
 
 
628
 
    _init: function(parentActor) {
629
 
        this.parent({ shellReactive: true,
630
 
                      styleClass: 'login-dialog',
631
 
                      parentActor: parentActor,
632
 
                      shouldFadeIn: false });
633
 
        this.connect('destroy',
634
 
                     Lang.bind(this, this._onDestroy));
635
 
        this.connect('opened',
636
 
                     Lang.bind(this, this._onOpened));
637
 
 
638
 
        this._userManager = AccountsService.UserManager.get_default()
639
 
        this._greeterClient = new Gdm.Client();
640
 
 
641
 
        this._greeter = this._greeterClient.get_greeter_sync(null);
642
 
 
643
 
        this._greeter.connect('default-session-name-changed',
644
 
                              Lang.bind(this, this._onDefaultSessionChanged));
645
 
 
646
 
        this._greeter.connect('session-opened',
647
 
                              Lang.bind(this, this._onSessionOpened));
648
 
        this._greeter.connect('timed-login-requested',
649
 
                              Lang.bind(this, this._onTimedLoginRequested));
650
 
 
651
 
        this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient);
652
 
        this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
653
 
        this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
654
 
        this._userVerifier.connect('reset', Lang.bind(this, this._reset));
655
 
        this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
656
 
        this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
657
 
        this._verifyingUser = false;
658
 
 
659
 
        this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
660
 
 
661
 
        this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
662
 
                               Lang.bind(this, this._updateLogo));
663
 
        this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
664
 
                               Lang.bind(this, this._updateBanner));
665
 
        this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
666
 
                               Lang.bind(this, this._updateBanner));
667
 
        this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
668
 
                               Lang.bind(this, this._updateDisableUserList));
669
 
 
670
 
        this._logoBox = new St.Bin({ style_class: 'login-dialog-logo-box' });
671
 
        this.contentLayout.add(this._logoBox);
672
 
        this._updateLogo();
673
 
 
674
 
        this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
675
 
                                           text: '' });
676
 
        this.contentLayout.add(this._bannerLabel);
677
 
        this._updateBanner();
678
 
 
679
 
        this._titleLabel = new St.Label({ style_class: 'login-dialog-title',
680
 
                                          text: C_("title", "Sign In"),
681
 
                                          visible: false });
682
 
 
683
 
        this.contentLayout.add(this._titleLabel,
684
 
                              { y_fill: false,
685
 
                                y_align: St.Align.START });
686
 
 
687
 
        this._userList = new UserList();
688
 
        this.contentLayout.add(this._userList.actor,
689
 
                               { expand: true,
690
 
                                 x_fill: true,
691
 
                                 y_fill: true });
692
 
 
693
 
        this.setInitialKeyFocus(this._userList.actor);
694
 
 
695
 
        this._promptBox = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
696
 
                                             vertical: true });
697
 
        this.contentLayout.add(this._promptBox,
698
 
                               { expand: true,
699
 
                                 x_fill: true,
700
 
                                 y_fill: true,
701
 
                                 x_align: St.Align.START });
702
 
        this._promptLabel = new St.Label({ style_class: 'login-dialog-prompt-label' });
703
 
 
704
 
        this._promptBox.add(this._promptLabel,
705
 
                            { expand: true,
706
 
                              x_fill: true,
707
 
                              y_fill: true,
708
 
                              x_align: St.Align.START });
709
 
        this._promptEntry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
710
 
                                           can_focus: true });
711
 
        this._promptBox.add(this._promptEntry,
712
 
                            { expand: true,
713
 
                              x_fill: true,
714
 
                              y_fill: false,
715
 
                              x_align: St.Align.START });
716
 
 
717
 
        this._promptMessage = new St.Label({ visible: false });
718
 
        this._promptBox.add(this._promptMessage, { x_fill: true });
719
 
 
720
 
        this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint-message' });
721
 
        this._promptLoginHint.hide();
722
 
        this._promptBox.add(this._promptLoginHint);
723
 
 
724
 
        this._sessionList = new SessionList();
725
 
        this._sessionList.connect('session-activated',
726
 
                                  Lang.bind(this, function(list, sessionId) {
727
 
                                                this._greeter.call_select_session_sync (sessionId, null);
728
 
                                            }));
729
 
 
730
 
        this._promptBox.add(this._sessionList.actor,
731
 
                            { expand: true,
732
 
                              x_fill: false,
733
 
                              y_fill: true,
734
 
                              x_align: St.Align.START });
735
 
        this._promptBox.hide();
736
 
 
737
 
        // translators: this message is shown below the user list on the
738
 
        // login screen. It can be activated to reveal an entry for
739
 
        // manually entering the username.
740
 
        let notListedLabel = new St.Label({ text: _("Not listed?"),
741
 
                                            style_class: 'login-dialog-not-listed-label' });
742
 
        this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
743
 
                                                can_focus: true,
744
 
                                                child: notListedLabel,
745
 
                                                reactive: true,
746
 
                                                x_align: St.Align.START,
747
 
                                                x_fill: true });
748
 
 
749
 
        this._notListedButton.connect('clicked', Lang.bind(this, this._hideUserListAndLogIn));
750
 
 
751
 
        this.contentLayout.add(this._notListedButton,
752
 
                               { expand: false,
753
 
                                 x_align: St.Align.START,
754
 
                                 x_fill: true });
755
 
 
756
 
        if (!this._userManager.is_loaded)
757
 
            this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
758
 
                                                                  Lang.bind(this, function() {
759
 
                                                                      if (this._userManager.is_loaded) {
760
 
                                                                          this._loadUserList();
761
 
                                                                          this._userManager.disconnect(this._userManagerLoadedId);
762
 
                                                                          this._userManagerLoadedId = 0;
763
 
                                                                      }
764
 
                                                                  }));
765
 
        else
766
 
            this._loadUserList();
767
 
 
768
 
        this._userList.connect('activate',
769
 
                               Lang.bind(this, function(userList, item) {
770
 
                                   this._onUserListActivated(item);
771
 
                               }));
772
 
 
773
 
   },
774
 
 
775
 
    _updateDisableUserList: function() {
776
 
        let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
777
 
 
778
 
        // If this is the first time around, set initial focus
779
 
        if (this._disableUserList == undefined && disableUserList)
780
 
            this.setInitialKeyFocus(this._promptEntry);
781
 
 
782
 
        if (disableUserList != this._disableUserList) {
783
 
            this._disableUserList = disableUserList;
784
 
 
785
 
            if (!this._verifyingUser)
786
 
               this._reset();
787
 
        }
788
 
   },
789
 
 
790
 
    _updateLogo: function() {
791
 
        this._logoBox.child = null;
792
 
        let path = this._settings.get_string(GdmUtil.LOGO_KEY);
793
 
 
794
 
        if (path) {
795
 
            let file = Gio.file_new_for_path(path);
796
 
            let uri = file.get_uri();
797
 
 
798
 
            let textureCache = St.TextureCache.get_default();
799
 
            this._logoBox.child = textureCache.load_uri_async(uri, -1, _LOGO_ICON_NAME_SIZE);
800
 
        }
801
 
 
802
 
    },
803
 
 
804
 
    _updateBanner: function() {
805
 
        let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
806
 
        let text = this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY);
807
 
 
808
 
        if (enabled && text) {
809
 
            this._bannerLabel.set_text(text);
810
 
            this._fadeInBanner();
811
 
        } else {
812
 
            this._fadeOutBanner();
813
 
        }
814
 
    },
815
 
 
816
 
    _reset: function() {
817
 
        this._promptMessage.hide();
818
 
        this._user = null;
819
 
        this._verifyingUser = false;
820
 
 
821
 
        if (this._disableUserList)
822
 
            this._hideUserListAndLogIn();
823
 
        else
824
 
            this._showUserList();
825
 
    },
826
 
 
827
 
    _onDefaultSessionChanged: function(client, sessionId) {
828
 
        this._sessionList.setActiveSession(sessionId);
829
 
    },
830
 
 
831
 
    _showMessage: function(userVerifier, message, styleClass) {
832
 
        if (message) {
833
 
            this._promptMessage.text = message;
834
 
            this._promptMessage.styleClass = styleClass;
835
 
            GdmUtil.fadeInActor(this._promptMessage);
836
 
        } else {
837
 
            GdmUtil.fadeOutActor(this._promptMessage);
838
 
        }
839
 
    },
840
 
 
841
 
    _showLoginHint: function(verifier, message) {
842
 
        this._promptLoginHint.set_text(message)
843
 
        GdmUtil.fadeInActor(this._promptLoginHint);
844
 
    },
845
 
 
846
 
    _hideLoginHint: function() {
847
 
        GdmUtil.fadeOutActor(this._promptLoginHint);
848
 
        this._promptLoginHint.set_text('');
849
 
    },
850
 
 
851
 
    cancel: function() {
852
 
        this._userVerifier.cancel();
853
 
    },
854
 
 
855
 
    _fadeInPrompt: function() {
856
 
        let tasks = [function() {
857
 
                         return GdmUtil.fadeInActor(this._promptLabel);
858
 
                     },
859
 
 
860
 
                     function() {
861
 
                         return GdmUtil.fadeInActor(this._promptEntry);
862
 
                     },
863
 
 
864
 
                     function() {
865
 
                         // Show it with 0 opacity so we preallocate space for it
866
 
                         // in the event we need to fade in the message
867
 
                         this._promptLoginHint.opacity = 0;
868
 
                         this._promptLoginHint.show();
869
 
                     },
870
 
 
871
 
                     function() {
872
 
                         return GdmUtil.fadeInActor(this._promptBox);
873
 
                     },
874
 
 
875
 
                     function() {
876
 
                         if (this._user && this._user.is_logged_in())
877
 
                             return null;
878
 
 
879
 
                         if (!this._verifyingUser)
880
 
                             return null;
881
 
 
882
 
                         return GdmUtil.fadeInActor(this._sessionList.actor);
883
 
                     },
884
 
 
885
 
                     function() {
886
 
                         this._promptEntry.grab_key_focus();
887
 
                     }];
888
 
 
889
 
        this._sessionList.actor.hide();
890
 
        let batch = new Batch.ConcurrentBatch(this, tasks);
891
 
        return batch.run();
892
 
    },
893
 
 
894
 
    _showPrompt: function() {
895
 
        let hold = new Batch.Hold();
896
 
 
897
 
        let cancelButtonInfo = { action: Lang.bind(this, this.cancel),
898
 
                                 label: _("Cancel"),
899
 
                                 key: Clutter.Escape };
900
 
        let okButtonInfo = { action: Lang.bind(this, function() {
901
 
                                         hold.release();
902
 
                                     }),
903
 
                             label: C_("button", "Sign In"),
904
 
                             default: true };
905
 
        let buttons = [];
906
 
        if (!this._disableUserList || this._verifyingUser)
907
 
            buttons.push(cancelButtonInfo);
908
 
        buttons.push(okButtonInfo);
909
 
 
910
 
        let tasks = [function() {
911
 
                         return this._fadeInPrompt();
912
 
                     },
913
 
 
914
 
                     function() {
915
 
                         this.setButtons(buttons);
916
 
                     },
917
 
 
918
 
                     hold];
919
 
 
920
 
        let batch = new Batch.ConcurrentBatch(this, tasks);
921
 
 
922
 
        return batch.run();
923
 
    },
924
 
 
925
 
    _hidePrompt: function() {
926
 
        this.setButtons([]);
927
 
 
928
 
        let tasks = [function() {
929
 
                         return GdmUtil.fadeOutActor(this._promptBox);
930
 
                     },
931
 
 
932
 
                     function() {
933
 
                         this._promptLoginHint.hide();
934
 
                         this._promptEntry.reactive = true;
935
 
                         this._promptEntry.set_text('');
936
 
                     }];
937
 
 
938
 
        let batch = new Batch.ConsecutiveBatch(this, tasks);
939
 
 
940
 
        return batch.run();
941
 
    },
942
 
 
943
 
    _askQuestion: function(verifier, serviceName, question, passwordChar) {
944
 
        this._promptLabel.set_text(question);
945
 
 
946
 
        this._promptEntry.set_text('');
947
 
        this._promptEntry.clutter_text.set_password_char(passwordChar);
948
 
 
949
 
        let tasks = [this._showPrompt,
950
 
 
951
 
                     function() {
952
 
                         let _text = this._promptEntry.get_text();
953
 
                         this._promptEntry.reactive = false;
954
 
                         this._userVerifier.answerQuery(serviceName, _text);
955
 
                     }];
956
 
 
957
 
        let batch = new Batch.ConsecutiveBatch(this, tasks);
958
 
        return batch.run();
959
 
    },
960
 
 
961
 
    _askForUsernameAndLogIn: function() {
962
 
        this._promptLabel.set_text(_("Username: "));
963
 
        this._promptEntry.set_text('');
964
 
        this._promptEntry.clutter_text.set_password_char('');
965
 
 
966
 
        let tasks = [this._showPrompt,
967
 
 
968
 
                     function() {
969
 
                         let userName = this._promptEntry.get_text();
970
 
                         this._promptEntry.reactive = false;
971
 
                         return this._beginVerificationForUser(userName);
972
 
                     }];
973
 
 
974
 
        let batch = new Batch.ConsecutiveBatch(this, tasks);
975
 
        return batch.run();
976
 
    },
977
 
 
978
 
    _onSessionOpened: function(client, serviceName) {
979
 
        this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
980
 
    },
981
 
 
982
 
    _waitForItemForUser: function(userName) {
983
 
        let item = this._userList.getItemFromUserName(userName);
984
 
 
985
 
        if (item)
986
 
          return null;
987
 
 
988
 
        let hold = new Batch.Hold();
989
 
        let signalId = this._userList.connect('item-added',
990
 
                                              Lang.bind(this, function() {
991
 
                                                  let item = this._userList.getItemFromUserName(userName);
992
 
 
993
 
                                                  if (item)
994
 
                                                      hold.release();
995
 
                                              }));
996
 
 
997
 
        hold.connect('release', Lang.bind(this, function() {
998
 
                         this._userList.disconnect(signalId);
999
 
                     }));
1000
 
 
1001
 
        return hold;
1002
 
    },
1003
 
 
1004
 
    _showTimedLoginAnimation: function() {
1005
 
        this._timedLoginItem.actor.grab_key_focus();
1006
 
        return this._timedLoginItem.showTimedLoginIndicator(this._timedLoginAnimationTime);
1007
 
    },
1008
 
 
1009
 
    _blockTimedLoginUntilIdle: function() {
1010
 
        // This blocks timed login from starting until a few
1011
 
        // seconds after the user stops interacting with the
1012
 
        // login screen.
1013
 
        //
1014
 
        // We skip this step if the timed login delay is very
1015
 
        // short.
1016
 
        if ((this._timedLoginDelay - _TIMED_LOGIN_IDLE_THRESHOLD) <= 0)
1017
 
          return null;
1018
 
 
1019
 
        let hold = new Batch.Hold();
1020
 
 
1021
 
        this._timedLoginIdleTimeOutId = Mainloop.timeout_add_seconds(_TIMED_LOGIN_IDLE_THRESHOLD,
1022
 
                                                                     function() {
1023
 
                                                                         this._timedLoginAnimationTime -= _TIMED_LOGIN_IDLE_THRESHOLD;
1024
 
                                                                         hold.release();
1025
 
                                                                     });
1026
 
        return hold;
1027
 
    },
1028
 
 
1029
 
    _startTimedLogin: function(userName, delay) {
1030
 
        this._timedLoginItem = null;
1031
 
        this._timedLoginDelay = delay;
1032
 
        this._timedLoginAnimationTime = delay;
1033
 
 
1034
 
        let tasks = [function() {
1035
 
                         return this._waitForItemForUser(userName);
1036
 
                     },
1037
 
 
1038
 
                     function() {
1039
 
                         this._timedLoginItem = this._userList.getItemFromUserName(userName);
1040
 
                     },
1041
 
 
1042
 
                     function() {
1043
 
                         // If we're just starting out, start on the right
1044
 
                         // item.
1045
 
                         if (!this.is_loaded) {
1046
 
                             this._userList.jumpToItem(this._timedLoginItem);
1047
 
                         }
1048
 
                     },
1049
 
 
1050
 
                     this._blockTimedLoginUntilIdle,
1051
 
 
1052
 
                     function() {
1053
 
                         this._userList.scrollToItem(this._timedLoginItem);
1054
 
                     },
1055
 
 
1056
 
                     this._showTimedLoginAnimation,
1057
 
 
1058
 
                     function() {
1059
 
                         this._timedLoginBatch = null;
1060
 
                         this._greeter.call_begin_auto_login_sync(userName, null);
1061
 
                     }];
1062
 
 
1063
 
        this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks);
1064
 
 
1065
 
        return this._timedLoginBatch.run();
1066
 
    },
1067
 
 
1068
 
    _resetTimedLogin: function() {
1069
 
        if (this._timedLoginBatch) {
1070
 
            this._timedLoginBatch.cancel();
1071
 
            this._timedLoginBatch = null;
1072
 
        }
1073
 
 
1074
 
        if (this._timedLoginItem)
1075
 
            this._timedLoginItem.hideTimedLoginIndicator();
1076
 
 
1077
 
        let userName = this._timedLoginItem.user.get_user_name();
1078
 
 
1079
 
        if (userName)
1080
 
            this._startTimedLogin(userName, this._timedLoginDelay);
1081
 
    },
1082
 
 
1083
 
    _onTimedLoginRequested: function(client, userName, seconds) {
1084
 
        this._startTimedLogin(userName, seconds);
1085
 
 
1086
 
        global.stage.connect('captured-event',
1087
 
                             Lang.bind(this, function(actor, event) {
1088
 
                                if (this._timedLoginDelay == undefined)
1089
 
                                    return false;
1090
 
 
1091
 
                                if (event.type() == Clutter.EventType.KEY_PRESS ||
1092
 
                                    event.type() == Clutter.EventType.BUTTON_PRESS) {
1093
 
                                    if (this._timedLoginBatch) {
1094
 
                                        this._timedLoginBatch.cancel();
1095
 
                                        this._timedLoginBatch = null;
1096
 
                                    }
1097
 
                                } else if (event.type() == Clutter.EventType.KEY_RELEASE ||
1098
 
                                           event.type() == Clutter.EventType.BUTTON_RELEASE) {
1099
 
                                    this._resetTimedLogin();
1100
 
                                }
1101
 
 
1102
 
                                return false;
1103
 
                             }));
1104
 
    },
1105
 
 
1106
 
    _hideUserListAndLogIn: function() {
1107
 
        let tasks = [function() {
1108
 
                         return this._userList.hideItems();
1109
 
                     },
1110
 
 
1111
 
                     function() {
1112
 
                         return this._userList.giveUpWhitespace();
1113
 
                     },
1114
 
 
1115
 
                     function() {
1116
 
                         this._userList.actor.hide();
1117
 
                     },
1118
 
 
1119
 
                     new Batch.ConcurrentBatch(this, [this._fadeOutTitleLabel,
1120
 
                                                      this._fadeOutNotListedButton,
1121
 
                                                      this._fadeOutLogo]),
1122
 
 
1123
 
                     function() {
1124
 
                         return this._askForUsernameAndLogIn();
1125
 
                     }];
1126
 
 
1127
 
        let batch = new Batch.ConsecutiveBatch(this, tasks);
1128
 
        batch.run();
1129
 
    },
1130
 
 
1131
 
    _fadeInLogo: function() {
1132
 
        return GdmUtil.fadeInActor(this._logoBox);
1133
 
    },
1134
 
 
1135
 
    _fadeOutLogo: function() {
1136
 
        return GdmUtil.fadeOutActor(this._logoBox);
1137
 
    },
1138
 
 
1139
 
    _showUserList: function() {
1140
 
        let tasks = [this._hidePrompt,
1141
 
 
1142
 
                     new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel,
1143
 
                                                      this._fadeInNotListedButton,
1144
 
                                                      this._fadeInLogo]),
1145
 
 
1146
 
                     function() {
1147
 
                         this._sessionList.close();
1148
 
                         this._promptLoginHint.hide();
1149
 
                         this._userList.actor.show();
1150
 
                         this._userList.actor.opacity = 255;
1151
 
                         return this._userList.showItems();
1152
 
                     },
1153
 
 
1154
 
                     function() {
1155
 
                         this._userList.actor.reactive = true;
1156
 
                         this._userList.actor.grab_key_focus();
1157
 
                     }];
1158
 
 
1159
 
        let batch = new Batch.ConsecutiveBatch(this, tasks);
1160
 
        batch.run();
1161
 
    },
1162
 
 
1163
 
    _fadeInBanner: function() {
1164
 
        return GdmUtil.fadeInActor(this._bannerLabel);
1165
 
    },
1166
 
 
1167
 
    _fadeOutBanner: function() {
1168
 
        return GdmUtil.fadeOutActor(this._bannerLabel);
1169
 
    },
1170
 
 
1171
 
    _fadeInTitleLabel: function() {
1172
 
        return GdmUtil.fadeInActor(this._titleLabel);
1173
 
    },
1174
 
 
1175
 
    _fadeOutTitleLabel: function() {
1176
 
        return GdmUtil.fadeOutActor(this._titleLabel);
1177
 
    },
1178
 
 
1179
 
    _fadeInNotListedButton: function() {
1180
 
        return GdmUtil.fadeInActor(this._notListedButton);
1181
 
    },
1182
 
 
1183
 
    _fadeOutNotListedButton: function() {
1184
 
        return GdmUtil.fadeOutActor(this._notListedButton);
1185
 
    },
1186
 
 
1187
 
    _beginVerificationForUser: function(userName) {
1188
 
        let hold = new Batch.Hold();
1189
 
 
1190
 
        this._userVerifier.begin(userName, hold);
1191
 
        this._verifyingUser = true;
1192
 
        return hold;
1193
 
    },
1194
 
 
1195
 
    _onUserListActivated: function(activatedItem) {
1196
 
        let userName;
1197
 
 
1198
 
        let tasks = [function() {
1199
 
                         this._userList.actor.reactive = false;
1200
 
                         return this._userList.pinInPlace();
1201
 
                     },
1202
 
 
1203
 
                     function() {
1204
 
                         return this._userList.hideItemsExcept(activatedItem);
1205
 
                     },
1206
 
 
1207
 
                     function() {
1208
 
                         return this._userList.giveUpWhitespace();
1209
 
                     },
1210
 
 
1211
 
                     new Batch.ConcurrentBatch(this, [this._fadeOutTitleLabel,
1212
 
                                                      this._fadeOutNotListedButton,
1213
 
                                                      this._fadeOutLogo]),
1214
 
 
1215
 
                     function() {
1216
 
                         return this._userList.shrinkToNaturalHeight();
1217
 
                     },
1218
 
 
1219
 
                     function() {
1220
 
                         userName = activatedItem.user.get_user_name();
1221
 
 
1222
 
                         return this._beginVerificationForUser(userName);
1223
 
                     }];
1224
 
 
1225
 
        this._user = activatedItem.user;
1226
 
 
1227
 
        let batch = new Batch.ConsecutiveBatch(this, tasks);
1228
 
        batch.run();
1229
 
    },
1230
 
 
1231
 
    _onDestroy: function() {
1232
 
        if (this._userManagerLoadedId) {
1233
 
            this._userManager.disconnect(this._userManagerLoadedId);
1234
 
            this._userManagerLoadedId = 0;
1235
 
        }
1236
 
    },
1237
 
 
1238
 
    _loadUserList: function() {
1239
 
        let users = this._userManager.list_users();
1240
 
 
1241
 
        for (let i = 0; i < users.length; i++) {
1242
 
            this._userList.addUser(users[i]);
1243
 
        }
1244
 
 
1245
 
        this._updateDisableUserList();
1246
 
 
1247
 
        this._userManager.connect('user-added',
1248
 
                                  Lang.bind(this, function(userManager, user) {
1249
 
                                      this._userList.addUser(user);
1250
 
                                  }));
1251
 
 
1252
 
        this._userManager.connect('user-removed',
1253
 
                                  Lang.bind(this, function(userManager, user) {
1254
 
                                      this._userList.removeUser(user);
1255
 
                                  }));
1256
 
 
1257
 
        // emitted in idle so caller doesn't have to explicitly check if
1258
 
        // it's loaded immediately after construction
1259
 
        // (since there's no way the caller could be listening for
1260
 
        // 'loaded' yet)
1261
 
        Mainloop.idle_add(Lang.bind(this, function() {
1262
 
            this.emit('loaded');
1263
 
            this.is_loaded = true;
1264
 
        }));
1265
 
    },
1266
 
 
1267
 
    _onOpened: function() {
1268
 
        Main.ctrlAltTabManager.addGroup(this.dialogLayout,
1269
 
                                        _("Login Window"),
1270
 
                                        'dialog-password-symbolic',
1271
 
                                        { sortGroup: CtrlAltTab.SortGroup.MIDDLE });
1272
 
 
1273
 
    },
1274
 
 
1275
 
    close: function() {
1276
 
        this.parent();
1277
 
 
1278
 
        Main.ctrlAltTabManager.removeGroup(this.dialogLayout);
1279
 
    }
1280
 
});