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

« back to all changes in this revision

Viewing changes to js/ui/userMenu.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:
4
4
const Gdm = imports.gi.Gdm;
5
5
const Gio = imports.gi.Gio;
6
6
const GLib = imports.gi.GLib;
 
7
const Gtk = imports.gi.Gtk;
7
8
const Lang = imports.lang;
8
9
const Pango = imports.gi.Pango;
9
10
const Shell = imports.gi.Shell;
10
11
const St = imports.gi.St;
11
12
const Tp = imports.gi.TelepathyGLib;
12
 
const UPowerGlib = imports.gi.UPowerGlib;
13
13
const Atk = imports.gi.Atk;
 
14
const Clutter = imports.gi.Clutter;
14
15
 
15
16
const BoxPointer = imports.ui.boxpointer;
16
17
const GnomeSession = imports.misc.gnomeSession;
 
18
const LoginManager = imports.misc.loginManager;
17
19
const Main = imports.ui.main;
 
20
const ModalDialog = imports.ui.modalDialog;
18
21
const PanelMenu = imports.ui.panelMenu;
19
22
const PopupMenu = imports.ui.popupMenu;
20
23
const Params = imports.misc.params;
21
 
const UnlockDialog = imports.ui.unlockDialog;
22
24
const Util = imports.misc.util;
23
25
 
24
26
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
25
27
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
 
28
const PRIVACY_SCHEMA = 'org.gnome.desktop.privacy'
26
29
const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
27
30
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
28
31
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
29
 
const LOCK_ENABLED_KEY = 'lock-enabled';
30
32
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
31
 
const SUSPEND_LOCK_ENABLED_KEY = 'ubuntu-lock-on-suspend';
 
33
const SHOW_FULL_NAME_IN_TOP_BAR_KEY = 'show-full-name-in-top-bar';
32
34
 
33
35
const DIALOG_ICON_SIZE = 64;
34
36
 
 
37
const MAX_USERS_IN_SESSION_DIALOG = 5;
 
38
 
35
39
const IMStatus = {
36
40
    AVAILABLE: 0,
37
41
    BUSY: 1,
42
46
    LAST: 6
43
47
};
44
48
 
 
49
 
 
50
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
 
51
    <property name="Id" type="s" access="read"/>
 
52
    <property name="Remote" type="b" access="read"/>
 
53
    <property name="Class" type="s" access="read"/>
 
54
    <property name="Type" type="s" access="read"/>
 
55
    <property name="State" type="s" access="read"/>
 
56
</interface>;
 
57
 
 
58
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
 
59
 
45
60
// Adapted from gdm/gui/user-switch-applet/applet.c
46
61
//
47
62
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
69
84
 
70
85
    update: function() {
71
86
        let iconFile = this._user.get_icon_file();
72
 
        if (!GLib.file_test(iconFile, GLib.FileTest.EXISTS))
 
87
        if (iconFile && !GLib.file_test(iconFile, GLib.FileTest.EXISTS))
73
88
            iconFile = null;
74
89
 
75
90
        if (iconFile) {
76
91
            let file = Gio.File.new_for_path(iconFile);
77
92
            this.actor.child = null;
78
93
            this.actor.style = 'background-image: url("%s");'.format(iconFile);
79
 
 
80
 
            // AccountsService uses a fixed location for avatar images, so
81
 
            // we need to clear out all cached data to pick up image changes,
82
 
            // see https://bugzilla.gnome.org/show_bug.cgi?id=679268
83
 
            this.actor.clear_background_image();
84
94
        } else {
85
95
            this.actor.style = null;
86
96
            this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic',
195
205
        item = new IMStatusItem(_("Idle"), 'user-idle-symbolic');
196
206
        this._combo.addMenuItem(item, IMStatus.IDLE);
197
207
 
198
 
        item = new IMStatusItem(_("Unavailable"), 'user-offline-symbolic');
 
208
        item = new IMStatusItem(_("Offline"), 'user-offline-symbolic');
199
209
        this._combo.addMenuItem(item, IMStatus.OFFLINE);
200
210
 
201
211
        this._combo.connect('active-item-changed',
483
493
 
484
494
        this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
485
495
        this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
 
496
        this._privacySettings = new Gio.Settings({ schema: PRIVACY_SCHEMA });
486
497
 
487
498
        this._userManager = AccountsService.UserManager.get_default();
488
499
 
490
501
        this._presence = new GnomeSession.Presence();
491
502
        this._session = new GnomeSession.SessionManager();
492
503
        this._haveShutdown = true;
 
504
        this._haveSuspend = true;
493
505
 
494
506
        this._accountMgr = Tp.AccountManager.dup();
495
507
 
496
 
        this._upClient = new UPowerGlib.Client();
 
508
        this._loginManager = LoginManager.getLoginManager();
497
509
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
498
510
 
499
511
        this._iconBox = new St.Bin();
556
568
                                       Lang.bind(this, this._updateSwitchUser));
557
569
        this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
558
570
                                       Lang.bind(this, this._updateLogout));
559
 
 
560
571
        this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
561
572
                                       Lang.bind(this, this._updateLockScreen));
 
573
        global.settings.connect('changed::' + ALWAYS_SHOW_LOG_OUT_KEY,
 
574
                                Lang.bind(this, this._updateLogout));
 
575
        this._screenSaverSettings.connect('changed::' + SHOW_FULL_NAME_IN_TOP_BAR_KEY,
 
576
                                           Lang.bind(this, this._updateUserName));
 
577
        this._privacySettings.connect('changed::' + SHOW_FULL_NAME_IN_TOP_BAR_KEY,
 
578
                                      Lang.bind(this, this._updateUserName));
562
579
        this._updateSwitchUser();
563
580
        this._updateLogout();
564
581
        this._updateLockScreen();
573
590
        // the lockdown setting changes, which should be close enough.
574
591
        this.menu.connect('open-state-changed', Lang.bind(this,
575
592
            function(menu, open) {
576
 
                if (open)
577
 
                    this._updateHaveShutdown();
 
593
                if (!open)
 
594
                    return;
 
595
 
 
596
                this._updateHaveShutdown();
 
597
                this._updateHaveSuspend();
578
598
            }));
579
599
        this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
580
600
                                       Lang.bind(this, this._updateHaveShutdown));
581
601
 
582
 
        this._upClient.connect('notify::can-suspend', Lang.bind(this, this._updateSuspendOrPowerOff));
583
 
 
584
602
        Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
 
603
        if (Main.screenShield)
 
604
            Main.screenShield.connect('locked-changed', Lang.bind(this, this._updatePresenceIcon));
585
605
        this._sessionUpdated();
586
606
    },
587
607
 
594
614
 
595
615
        this.setSensitive(!Main.sessionMode.isLocked);
596
616
        this._updatePresenceIcon();
 
617
        this._updateUserName();
597
618
    },
598
619
 
599
620
    _onDestroy: function() {
602
623
    },
603
624
 
604
625
    _updateUserName: function() {
605
 
        if (this._user.is_loaded)
 
626
        let settings = this._privacySettings;
 
627
        if (Main.sessionMode.isLocked)
 
628
            settings = this._screenSaverSettings;
 
629
        if (this._user.is_loaded && settings.get_boolean(SHOW_FULL_NAME_IN_TOP_BAR_KEY))
606
630
            this._name.set_text(this._user.get_real_name());
607
631
        else
608
632
            this._name.set_text("");
633
657
 
634
658
    _updateLockScreen: function() {
635
659
        let allowLockScreen = !this._lockdownSettings.get_boolean(DISABLE_LOCK_SCREEN_KEY);
636
 
        this._lockScreenItem.actor.visible = allowLockScreen;
 
660
        this._lockScreenItem.actor.visible = allowLockScreen && LoginManager.canLock();
637
661
    },
638
662
 
639
663
    _updateInstallUpdates: function() {
652
676
            }));
653
677
    },
654
678
 
 
679
    _updateHaveSuspend: function() {
 
680
        this._loginManager.canSuspend(Lang.bind(this,
 
681
            function(result) {
 
682
                this._haveSuspend = result;
 
683
                this._updateSuspendOrPowerOff();
 
684
        }));
 
685
    },
 
686
 
655
687
    _updateSuspendOrPowerOff: function() {
656
 
        this._haveSuspend = this._upClient.get_can_suspend();
657
 
 
658
688
        if (!this._suspendOrPowerOffItem)
659
689
            return;
660
690
 
691
721
            this._iconBox.child = this._idleIcon;
692
722
        else
693
723
            this._iconBox.child = this._offlineIcon;
 
724
 
 
725
        if (Main.sessionMode.isLocked)
 
726
            this._iconBox.visible = Main.screenShield.locked;
 
727
        else
 
728
            this._iconBox.visible = true;
694
729
    },
695
730
 
696
731
    _setupAccounts: function() {
751
786
        item = new PopupMenu.PopupSeparatorMenuItem();
752
787
        this.menu.addMenuItem(item);
753
788
 
754
 
        item = new PopupMenu.PopupMenuItem(_("System Settings"));
 
789
        item = new PopupMenu.PopupMenuItem(_("Settings"));
755
790
        item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
756
791
        this.menu.addMenuItem(item);
757
792
        this._systemSettings = item;
811
846
 
812
847
    _onMyAccountActivate: function() {
813
848
        Main.overview.hide();
814
 
        let app = Shell.AppSystem.get_default().lookup_setting('gnome-user-accounts-panel.desktop');
 
849
        let app = Shell.AppSystem.get_default().lookup_app('gnome-user-accounts-panel.desktop');
815
850
        app.activate();
816
851
    },
817
852
 
830
865
    _onLoginScreenActivate: function() {
831
866
        this.menu.close(BoxPointer.PopupAnimation.NONE);
832
867
        Main.overview.hide();
833
 
        Main.screenShield.lock(false);
834
 
        if (UnlockDialog.isSupported())
 
868
        if (Main.screenShield) {
 
869
            Main.screenShield.lock(false);
835
870
            Gdm.goto_login_session_sync(null);
836
 
        else
 
871
        } else
837
872
            this._lightdmLoginSession();
838
873
    },
839
874
 
849
884
        this._session.RebootRemote();
850
885
    },
851
886
 
 
887
    _openSessionWarnDialog: function(sessions) {
 
888
        let dialog = new ModalDialog.ModalDialog();
 
889
        let subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject',
 
890
                                          text: _("Other users are logged in.") });
 
891
        dialog.contentLayout.add(subjectLabel, { y_fill: true,
 
892
                                                 y_align: St.Align.START });
 
893
 
 
894
        let descriptionLabel = new St.Label({ style_class: 'end-session-dialog-description'});
 
895
        descriptionLabel.set_text(_("Shutting down might cause them to lose unsaved work."));
 
896
        descriptionLabel.clutter_text.line_wrap = true;
 
897
        dialog.contentLayout.add(descriptionLabel, { x_fill: true,
 
898
                                                     y_fill: true,
 
899
                                                     y_align: St.Align.START });
 
900
 
 
901
        let scrollView = new St.ScrollView({ style_class: 'end-session-dialog-app-list' });
 
902
        scrollView.add_style_class_name('vfade');
 
903
        scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
 
904
        dialog.contentLayout.add(scrollView, { x_fill: true, y_fill: true });
 
905
 
 
906
        let userList = new St.BoxLayout({ vertical: true });
 
907
        scrollView.add_actor(userList);
 
908
 
 
909
        for (let i = 0; i < sessions.length; i++) {
 
910
            let session = sessions[i];
 
911
            let userEntry = new St.BoxLayout({ style_class: 'login-dialog-user-list-item',
 
912
                                               vertical: false });
 
913
            let avatar = new UserAvatarWidget(session.user);
 
914
            avatar.update();
 
915
            userEntry.add(avatar.actor);
 
916
 
 
917
            let userLabelText = "";;
 
918
            let userName = session.user.get_real_name() ?
 
919
                           session.user.get_real_name() : session.username;
 
920
 
 
921
            if (session.info.remote)
 
922
                /* Translators: Remote here refers to a remote session, like a ssh login */
 
923
                userLabelText = _("%s (remote)").format(userName);
 
924
            else if (session.info.type == "tty")
 
925
                /* Translators: Console here refers to a tty like a VT console */
 
926
                userLabelText = _("%s (console)").format(userName);
 
927
            else
 
928
                userLabelText = userName;
 
929
 
 
930
            let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box',
 
931
                                                vertical: true });
 
932
            textLayout.add(new St.Label({ text: userLabelText }),
 
933
                           { y_fill: false,
 
934
                             y_align: St.Align.MIDDLE,
 
935
                             expand: true });
 
936
            userEntry.add(textLayout, { expand: true });
 
937
            userList.add(userEntry, { x_fill: true });
 
938
        }
 
939
 
 
940
        let cancelButton = { label: _("Cancel"),
 
941
                             action: function() { dialog.close(); },
 
942
                             key: Clutter.Escape };
 
943
 
 
944
        let powerOffButton = { label: _("Power Off"),  action: Lang.bind(this, function() {
 
945
            dialog.close();
 
946
            this._session.ShutdownRemote();
 
947
        }), default: true };
 
948
 
 
949
        dialog.setButtons([cancelButton, powerOffButton]);
 
950
 
 
951
        dialog.open();
 
952
    },
 
953
 
852
954
    _onSuspendOrPowerOffActivate: function() {
853
955
        Main.overview.hide();
854
956
 
855
957
        if (this._haveShutdown &&
856
958
            this._suspendOrPowerOffItem.state == PopupMenu.PopupAlternatingMenuItemState.DEFAULT) {
857
 
            this._session.ShutdownRemote();
 
959
            this._loginManager.listSessions(Lang.bind(this,
 
960
                function(result) {
 
961
                    let sessions = [];
 
962
                    let n = 0;
 
963
                    for (let i = 0; i < result.length; i++) {
 
964
                        let[id, uid, userName, seat, sessionPath] = result[i];
 
965
                        let proxy = new SystemdLoginSession(Gio.DBus.system,
 
966
                                                            'org.freedesktop.login1',
 
967
                                                            sessionPath);
 
968
 
 
969
                        if (proxy.Class != 'user')
 
970
                            continue;
 
971
 
 
972
                        if (proxy.State == 'closing')
 
973
                            continue;
 
974
 
 
975
                        if (proxy.Id == GLib.getenv('XDG_SESSION_ID'))
 
976
                            continue;
 
977
 
 
978
                        sessions.push({ user: this._userManager.get_user(userName),
 
979
                                        username: userName,
 
980
                                        info: { type: proxy.Type,
 
981
                                                remote: proxy.Remote }
 
982
                        });
 
983
 
 
984
                        // limit the number of entries
 
985
                        n++;
 
986
                        if (n == MAX_USERS_IN_SESSION_DIALOG)
 
987
                            break;
 
988
                    }
 
989
 
 
990
                    if (n != 0)
 
991
                        this._openSessionWarnDialog(sessions);
 
992
                    else
 
993
                        this._session.ShutdownRemote();
 
994
            }));
858
995
        } else {
859
 
            if (this._screenSaverSettings.get_boolean(SUSPEND_LOCK_ENABLED_KEY)) {
860
 
                let tmpId = Main.screenShield.connect('lock-screen-shown', Lang.bind(this, function() {
861
 
                    Main.screenShield.disconnect(tmpId);
862
 
 
863
 
                    this._upClient.suspend_sync(null);
864
 
                }));
865
 
 
866
 
                this.menu.close(BoxPointer.PopupAnimation.NONE);
867
 
                Main.screenShield.lock(true);
868
 
            } else {
869
 
                this._upClient.suspend_sync(null);
870
 
            }
 
996
            this.menu.close(BoxPointer.PopupAnimation.NONE);
 
997
            this._loginManager.suspend();
871
998
        }
872
999
    },
 
1000
 
873
1001
    _lightdmLoginSession: function() {
874
1002
        try {
875
1003
            let seat = GLib.getenv("XDG_SEAT_PATH");
879
1007
                                               'SwitchToGreeter', null, null,
880
1008
                                               Gio.DBusCallFlags.NONE,
881
1009
                                               -1, null);
 
1010
            return result;
882
1011
        } catch(e) {
883
 
            Main.screenShield.lock();
 
1012
            return false;
884
1013
        }
885
1014
    }
886
1015
});