~ubuntu-branches/ubuntu/trusty/unity-greeter/trusty

« back to all changes in this revision

Viewing changes to .pc/move-nm-applet.patch/src/unity-greeter.vala

  • Committer: Package Import Robot
  • Author(s): Michael Terry
  • Date: 2013-03-15 14:04:08 UTC
  • mfrom: (1.1.22)
  • Revision ID: package-import@ubuntu.com-20130315140408-m2kwmrmxtyn0j9hk
Tags: 13.04.2-0ubuntu1
* New upstream release.
  - Fix duplicate entries showing for multiple users on the same remote
    login service.
  - Add custom indicator support for system administrators (LP: #1155157)
* debian/control:
  - Switch Vcs-Bzr to point at Unity Greeter trunk, since we are inlining
    the packaging
  - Use debhelper 9
* debian/rules:
  - Use upstream ./autogen.sh for autoreconf
* debian/patches/do-not-read-password.patch,
  debian/patches/move-nm-applet.patch,
  debian/patches/spawn-gsd-directly.patch:
  - Drop, included upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*-
2
 
 *
3
 
 * Copyright (C) 2011 Canonical Ltd
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 version 3 as
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 
 *
17
 
 * Authored by: Robert Ancell <robert.ancell@canonical.com>
18
 
 */
19
 
 
20
 
public const int grid_size = 40;
21
 
 
22
 
public class UnityGreeter
23
 
{
24
 
    public static UnityGreeter singleton;
25
 
 
26
 
    public signal void show_message (string text, LightDM.MessageType type);
27
 
    public signal void show_prompt (string text, LightDM.PromptType type);
28
 
    public signal void authentication_complete ();
29
 
    public signal void starting_session ();
30
 
 
31
 
    public bool test_mode = false;
32
 
 
33
 
    private string state_file;
34
 
    private KeyFile state;
35
 
 
36
 
    private Cairo.XlibSurface background_surface;
37
 
 
38
 
    private SettingsDaemon settings_daemon;
39
 
 
40
 
    private MainWindow main_window;
41
 
 
42
 
    private LightDM.Greeter greeter;
43
 
 
44
 
    private Canberra.Context canberra_context;
45
 
 
46
 
    private static Timer log_timer;
47
 
 
48
 
    private UnityGreeter (bool test_mode_)
49
 
    {
50
 
        singleton = this;
51
 
        test_mode = test_mode_;
52
 
 
53
 
        /* Prepare to set the background */
54
 
        debug ("Creating background surface");
55
 
        background_surface = create_root_surface (Gdk.Screen.get_default ());
56
 
 
57
 
        greeter = new LightDM.Greeter ();
58
 
        greeter.show_message.connect ((text, type) => { show_message (text, type); });
59
 
        greeter.show_prompt.connect ((text, type) => { show_prompt (text, type); });
60
 
        greeter.autologin_timer_expired.connect (() => { greeter.authenticate_autologin (); });
61
 
        greeter.authentication_complete.connect (() => { authentication_complete (); });
62
 
        var connected = false;
63
 
        try
64
 
        {
65
 
            connected = greeter.connect_sync ();
66
 
        }
67
 
        catch (Error e)
68
 
        {
69
 
            warning ("Failed to connect to LightDM daemon");
70
 
        }
71
 
        if (!connected && !test_mode)
72
 
            Posix.exit (Posix.EXIT_FAILURE);
73
 
 
74
 
        if (!test_mode)
75
 
        {
76
 
            settings_daemon = new SettingsDaemon ();
77
 
            settings_daemon.start.begin ();
78
 
        }
79
 
 
80
 
        var state_dir = Path.build_filename (Environment.get_user_cache_dir (), "unity-greeter");
81
 
        DirUtils.create_with_parents (state_dir, 0775);
82
 
 
83
 
        state_file = Path.build_filename (state_dir, "state");
84
 
        state = new KeyFile ();
85
 
        try
86
 
        {
87
 
            state.load_from_file (state_file, KeyFileFlags.NONE);
88
 
        }
89
 
        catch (Error e)
90
 
        {
91
 
            if (!(e is FileError.NOENT))
92
 
                warning ("Failed to load state from %s: %s\n", state_file, e.message);
93
 
        }
94
 
 
95
 
        main_window = new MainWindow ();
96
 
 
97
 
        start_fake_wm ();
98
 
        Gdk.threads_add_idle (ready_cb);
99
 
    }
100
 
 
101
 
    public string? get_state (string key)
102
 
    {
103
 
        try
104
 
        {
105
 
            return state.get_value ("greeter", key);
106
 
        }
107
 
        catch (Error e)
108
 
        {
109
 
            return null;
110
 
        }
111
 
    }
112
 
 
113
 
    public void set_state (string key, string value)
114
 
    {
115
 
        state.set_value ("greeter", key, value);
116
 
        var data = state.to_data ();
117
 
        try
118
 
        {
119
 
            FileUtils.set_contents (state_file, data);
120
 
        }
121
 
        catch (Error e)
122
 
        {
123
 
            debug ("Failed to write state: %s", e.message);
124
 
        }
125
 
    }
126
 
 
127
 
    public void push_list (GreeterList widget)
128
 
    {
129
 
        main_window.push_list (widget);
130
 
    }
131
 
 
132
 
    public void pop_list ()
133
 
    {
134
 
        main_window.pop_list ();
135
 
    }
136
 
 
137
 
    public static void add_style_class (Gtk.Widget widget)
138
 
    {
139
 
        /* Add style context class lightdm-user-list */
140
 
        var ctx = widget.get_style_context ();
141
 
        ctx.add_class ("lightdm");
142
 
    }
143
 
 
144
 
    public static LightDM.Layout? get_layout_by_name (string name)
145
 
    {
146
 
        foreach (var layout in LightDM.get_layouts ())
147
 
        {
148
 
            if (layout.name == name)
149
 
                return layout;
150
 
        }
151
 
        return null;
152
 
    }
153
 
 
154
 
    public void start_session (string? session, Background bg)
155
 
    {
156
 
        /* Paint our background onto the root window before we close our own window */
157
 
        var c = new Cairo.Context (background_surface);
158
 
        bg.draw_full (c, Background.DrawFlags.NONE);
159
 
        c = null;
160
 
        refresh_background (Gdk.Screen.get_default (), background_surface);
161
 
 
162
 
        if (test_mode)
163
 
        {
164
 
                debug ("Successfully logged in!  Quitting...");
165
 
                Gtk.main_quit ();
166
 
        }
167
 
        else
168
 
        {
169
 
            starting_session ();
170
 
            try
171
 
            {
172
 
                greeter.start_session_sync (session);
173
 
            }
174
 
            catch (Error e)
175
 
            {
176
 
                warning ("Failed to start session: %s", e.message);
177
 
            }
178
 
        }
179
 
    }
180
 
 
181
 
    private bool ready_cb ()
182
 
    {
183
 
        debug ("starting system-ready sound");
184
 
 
185
 
        /* Launch canberra */
186
 
        Canberra.Context.create (out canberra_context);
187
 
 
188
 
        if (UGSettings.get_boolean (UGSettings.KEY_PLAY_READY_SOUND))
189
 
            canberra_context.play (0,
190
 
                                   Canberra.PROP_CANBERRA_XDG_THEME_NAME,
191
 
                                   "ubuntu",
192
 
                                   Canberra.PROP_EVENT_ID,
193
 
                                   "system-ready");
194
 
 
195
 
        return false;
196
 
    }
197
 
 
198
 
    public void show ()
199
 
    {
200
 
        debug ("Showing main window");
201
 
        main_window.show ();
202
 
        main_window.get_window ().focus (Gdk.CURRENT_TIME);
203
 
        main_window.set_keyboard_state ();
204
 
    }
205
 
 
206
 
    public bool is_authenticated ()
207
 
    {
208
 
        return greeter.is_authenticated;
209
 
    }
210
 
 
211
 
    public void authenticate (string? userid = null)
212
 
    {
213
 
        greeter.authenticate (userid);
214
 
    }
215
 
 
216
 
    public void authenticate_as_guest ()
217
 
    {
218
 
        greeter.authenticate_as_guest ();
219
 
    }
220
 
 
221
 
    public void authenticate_remote (string? session, string? userid)
222
 
    {
223
 
        UnityGreeter.singleton.greeter.authenticate_remote (session, userid);
224
 
    }
225
 
 
226
 
    public void cancel_authentication ()
227
 
    {
228
 
        greeter.cancel_authentication ();
229
 
    }
230
 
 
231
 
    public void respond (string response)
232
 
    {
233
 
        greeter.respond (response);
234
 
    }
235
 
 
236
 
    public string authentication_user ()
237
 
    {
238
 
        return greeter.authentication_user;
239
 
    }
240
 
 
241
 
    public string default_session_hint ()
242
 
    {
243
 
        return greeter.default_session_hint;
244
 
    }
245
 
 
246
 
    public string select_user_hint ()
247
 
    {
248
 
        return greeter.select_user_hint;
249
 
    }
250
 
 
251
 
    public bool show_manual_login_hint ()
252
 
    {
253
 
        return greeter.show_manual_login_hint;
254
 
    }
255
 
 
256
 
    public bool show_remote_login_hint ()
257
 
    {
258
 
        return greeter.show_remote_login_hint;
259
 
    }
260
 
 
261
 
    public bool hide_users_hint ()
262
 
    {
263
 
        return greeter.hide_users_hint;
264
 
    }
265
 
 
266
 
    public bool has_guest_account_hint ()
267
 
    {
268
 
        return greeter.has_guest_account_hint;
269
 
    }
270
 
 
271
 
    private Gdk.FilterReturn focus_upon_map (Gdk.XEvent gxevent, Gdk.Event event)
272
 
    {
273
 
        var xevent = (X.Event*)gxevent;
274
 
        if (xevent.type == X.EventType.MapNotify)
275
 
        {
276
 
            var display = Gdk.x11_lookup_xdisplay (xevent.xmap.display);
277
 
            var xwin = xevent.xmap.window;
278
 
            var win = Gdk.X11Window.foreign_new_for_display (display, xwin);
279
 
 
280
 
            /* Check to see if this window is our onboard window, since we don't want to focus it. */
281
 
            X.Window keyboard_xid = 0;
282
 
            if (main_window.menubar.keyboard_window != null)
283
 
                keyboard_xid = Gdk.X11Window.get_xid (main_window.menubar.keyboard_window.get_window ());
284
 
 
285
 
            if (xwin != keyboard_xid && win.get_type_hint() != Gdk.WindowTypeHint.NOTIFICATION)
286
 
            {
287
 
                win.focus (Gdk.CURRENT_TIME);
288
 
 
289
 
                /* Make sure to keep keyboard above */
290
 
                if (main_window.menubar.keyboard_window != null)
291
 
                    main_window.menubar.keyboard_window.get_window ().raise ();
292
 
            }
293
 
        }
294
 
        else if (xevent.type == X.EventType.UnmapNotify)
295
 
        {
296
 
            // Since we aren't keeping track of focus (for example, we don't
297
 
            // track the Z stack of windows) like a normal WM would, when we
298
 
            // decide here where to return focus after another window unmaps,
299
 
            // we don't have much to go on.  X will tell us if we should take
300
 
            // focus back.  (I could not find an obvious way to determine this,
301
 
            // but checking if the X input focus is RevertTo.None seems
302
 
            // reliable.)
303
 
 
304
 
            X.Window xwin;
305
 
            int revert_to;
306
 
            xevent.xunmap.display.get_input_focus (out xwin, out revert_to);
307
 
 
308
 
            if (revert_to == X.RevertTo.None)
309
 
            {
310
 
                main_window.get_window ().focus (Gdk.CURRENT_TIME);
311
 
 
312
 
                /* Make sure to keep keyboard above */
313
 
                if (main_window.menubar.keyboard_window != null)
314
 
                    main_window.menubar.keyboard_window.get_window ().raise ();
315
 
            }
316
 
        }
317
 
        return Gdk.FilterReturn.CONTINUE;
318
 
    }
319
 
 
320
 
    private void start_fake_wm ()
321
 
    {
322
 
        /* We want new windows (e.g. the shutdown dialog) to gain focus.
323
 
           We don't really need anything more than that (don't need alt-tab
324
 
           since any dialog should be "modal" or at least dealt with before
325
 
           continuing even if not actually marked as modal) */
326
 
        var root = Gdk.get_default_root_window ();
327
 
        root.set_events (root.get_events () | Gdk.EventMask.SUBSTRUCTURE_MASK);
328
 
        root.add_filter (focus_upon_map);
329
 
    }
330
 
 
331
 
    private static Cairo.XlibSurface? create_root_surface (Gdk.Screen screen)
332
 
    {
333
 
        var visual = screen.get_system_visual ();
334
 
 
335
 
        unowned X.Display display = Gdk.X11Display.get_xdisplay (screen.get_display ());
336
 
 
337
 
        var pixmap = X.CreatePixmap (display,
338
 
                                     Gdk.X11Window.get_xid (screen.get_root_window ()),
339
 
                                     screen.get_width (),
340
 
                                     screen.get_height (),
341
 
                                     visual.get_depth ());
342
 
 
343
 
        /* Convert into a Cairo surface */
344
 
        var surface = new Cairo.XlibSurface (display,
345
 
                                             pixmap,
346
 
                                             Gdk.X11Visual.get_xvisual (visual),
347
 
                                             screen.get_width (), screen.get_height ());
348
 
 
349
 
        return surface;
350
 
    }
351
 
 
352
 
    private static void refresh_background (Gdk.Screen screen, Cairo.XlibSurface surface)
353
 
    {
354
 
        Gdk.flush ();
355
 
 
356
 
        unowned X.Display display = Gdk.X11Display.get_xdisplay (screen.get_display ());
357
 
 
358
 
        /* Ensure Cairo has actually finished its drawing */
359
 
        surface.flush ();
360
 
        /* Use this pixmap for the background */
361
 
        X.SetWindowBackgroundPixmap (display,
362
 
                                     Gdk.X11Window.get_xid (screen.get_root_window ()),
363
 
                                     surface.get_drawable ());
364
 
 
365
 
        X.ClearWindow (display, Gdk.X11Window.get_xid (screen.get_root_window ()));
366
 
    }
367
 
 
368
 
    private static void log_cb (string? log_domain, LogLevelFlags log_level, string message)
369
 
    {
370
 
        string prefix;
371
 
        switch (log_level & LogLevelFlags.LEVEL_MASK)
372
 
        {
373
 
        case LogLevelFlags.LEVEL_ERROR:
374
 
            prefix = "ERROR:";
375
 
            break;
376
 
        case LogLevelFlags.LEVEL_CRITICAL:
377
 
            prefix = "CRITICAL:";
378
 
            break;
379
 
        case LogLevelFlags.LEVEL_WARNING:
380
 
            prefix = "WARNING:";
381
 
            break;
382
 
        case LogLevelFlags.LEVEL_MESSAGE:
383
 
            prefix = "MESSAGE:";
384
 
            break;
385
 
        case LogLevelFlags.LEVEL_INFO:
386
 
            prefix = "INFO:";
387
 
            break;
388
 
        case LogLevelFlags.LEVEL_DEBUG:
389
 
            prefix = "DEBUG:";
390
 
            break;
391
 
        default:
392
 
            prefix = "LOG:";
393
 
            break;
394
 
        }
395
 
 
396
 
        stderr.printf ("[%+.2fs] %s %s\n", log_timer.elapsed (), prefix, message);
397
 
    }
398
 
 
399
 
    public static int main (string[] args)
400
 
    {
401
 
        /* Protect memory from being paged to disk, as we deal with passwords */
402
 
        Posix.mlockall (Posix.MCL_CURRENT | Posix.MCL_FUTURE);
403
 
 
404
 
        /* Disable the stupid global menubar */
405
 
        Environment.unset_variable ("UBUNTU_MENUPROXY");
406
 
 
407
 
        /* Initialize i18n */
408
 
        Intl.setlocale (LocaleCategory.ALL, "");
409
 
        Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
410
 
        Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8");
411
 
        Intl.textdomain (Config.GETTEXT_PACKAGE);
412
 
 
413
 
        /* Set up the accessibility stack, in case the user needs it for screen reading etc. */
414
 
        Environment.set_variable ("GTK_MODULES", "atk-bridge", false);
415
 
 
416
 
        Pid atspi_pid = 0;
417
 
 
418
 
        try
419
 
        {
420
 
            string[] argv;
421
 
 
422
 
            Shell.parse_argv ("/usr/lib/at-spi2-core/at-spi-bus-launcher --launch-immediately", out argv);
423
 
            Process.spawn_async (null,
424
 
                                 argv,
425
 
                                 null,
426
 
                                 SpawnFlags.SEARCH_PATH,
427
 
                                 null,
428
 
                                 out atspi_pid);
429
 
        }
430
 
        catch (Error e)
431
 
        {
432
 
            warning ("Error starting the at-spi registry: %s", e.message);
433
 
        }
434
 
 
435
 
        Gtk.init (ref args);
436
 
 
437
 
        log_timer = new Timer ();
438
 
        Log.set_default_handler (log_cb);
439
 
 
440
 
        debug ("Starting unity-greeter %s UID=%d LANG=%s", Config.VERSION, (int) Posix.getuid (), Environment.get_variable ("LANG"));
441
 
 
442
 
        /* Set the cursor to not be the crap default */
443
 
        debug ("Setting cursor");
444
 
        Gdk.get_default_root_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.LEFT_PTR));
445
 
 
446
 
        bool do_show_version = false;
447
 
        bool do_test_mode = false;
448
 
        OptionEntry versionOption = { "version", 'v', 0, OptionArg.NONE, ref do_show_version,
449
 
                /* Help string for command line --version flag */
450
 
                N_("Show release version"), null };
451
 
        OptionEntry testOption =  { "test-mode", 0, 0, OptionArg.NONE, ref do_test_mode,
452
 
                /* Help string for command line --test-mode flag */
453
 
                N_("Run in test mode"), null };
454
 
        OptionEntry nullOption = { null };
455
 
        OptionEntry[] options = { versionOption, testOption, nullOption };
456
 
 
457
 
        debug ("Loading command line options");
458
 
        var c = new OptionContext (/* Arguments and description for --help text */
459
 
                                   _("- Unity Greeter"));
460
 
        c.add_main_entries (options, Config.GETTEXT_PACKAGE);
461
 
        c.add_group (Gtk.get_option_group (true));
462
 
        try
463
 
        {
464
 
            c.parse (ref args);
465
 
        }
466
 
        catch (Error e)
467
 
        {
468
 
            stderr.printf ("%s\n", e.message);
469
 
            stderr.printf (/* Text printed out when an unknown command-line argument provided */
470
 
                           _("Run '%s --help' to see a full list of available command line options."), args[0]);
471
 
            stderr.printf ("\n");
472
 
            return Posix.EXIT_FAILURE;
473
 
        }
474
 
        if (do_show_version)
475
 
        {
476
 
            /* Note, not translated so can be easily parsed */
477
 
            stderr.printf ("unity-greeter %s\n", Config.VERSION);
478
 
            return Posix.EXIT_SUCCESS;
479
 
        }
480
 
 
481
 
        if (do_test_mode)
482
 
            debug ("Running in test mode");
483
 
 
484
 
        if (!do_test_mode)
485
 
        {
486
 
            /* Make nm-applet hide items the user does not have permissions to interact with */
487
 
            Environment.set_variable ("NM_APPLET_HIDE_POLICY_ITEMS", "1", true);
488
 
 
489
 
            try
490
 
            {
491
 
                Process.spawn_command_line_async ("nm-applet");
492
 
            }
493
 
            catch (Error e)
494
 
            {
495
 
                warning ("Error starting nm-applet: %s", e.message);
496
 
            }
497
 
        }
498
 
 
499
 
        /* Set GTK+ settings */
500
 
        debug ("Setting GTK+ settings");
501
 
        var settings = Gtk.Settings.get_default ();
502
 
        var value = UGSettings.get_string (UGSettings.KEY_THEME_NAME);
503
 
        if (value != "")
504
 
            settings.set ("gtk-theme-name", value, null);
505
 
        value = UGSettings.get_string (UGSettings.KEY_ICON_THEME_NAME);
506
 
        if (value != "")
507
 
            settings.set ("gtk-icon-theme-name", value, null);
508
 
        value = UGSettings.get_string (UGSettings.KEY_FONT_NAME);
509
 
        if (value != "")
510
 
            settings.set ("gtk-font-name", value, null);
511
 
        var double_value = UGSettings.get_double (UGSettings.KEY_XFT_DPI);
512
 
        if (double_value != 0.0)
513
 
            settings.set ("gtk-xft-dpi", (int) (1024 * double_value), null);
514
 
        var boolean_value = UGSettings.get_boolean (UGSettings.KEY_XFT_ANTIALIAS);
515
 
        settings.set ("gtk-xft-antialias", boolean_value, null);
516
 
        value = UGSettings.get_string (UGSettings.KEY_XFT_HINTSTYLE);
517
 
        if (value != "")
518
 
            settings.set ("gtk-xft-hintstyle", value, null);
519
 
        value = UGSettings.get_string (UGSettings.KEY_XFT_RGBA);
520
 
        if (value != "")
521
 
            settings.set ("gtk-xft-rgba", value, null);
522
 
 
523
 
        debug ("Creating Unity Greeter");
524
 
        var greeter = new UnityGreeter (do_test_mode);
525
 
 
526
 
        debug ("Showing greeter");
527
 
        greeter.show ();
528
 
 
529
 
        debug ("Starting main loop");
530
 
        Gtk.main ();
531
 
 
532
 
        if (atspi_pid != 0)
533
 
        {
534
 
            Posix.kill (atspi_pid, Posix.SIGKILL);
535
 
            int status;
536
 
            Posix.waitpid (atspi_pid, out status, 0);
537
 
            atspi_pid = 0;
538
 
        }
539
 
 
540
 
        return Posix.EXIT_SUCCESS;
541
 
    }
542
 
}