~brian-murray/lightdm/bug-967229

« back to all changes in this revision

Viewing changes to greeters/gtk/lightdm-gtk-greeter.c

  • Committer: Sebastien Bacher
  • Date: 2012-01-18 09:21:40 UTC
  • mfrom: (1007.1.355 lightdm)
  • mto: This revision was merged to the branch mainline in revision 1056.
  • Revision ID: seb128@ubuntu.com-20120118092140-fhyj1fmiouth227t
Tags: upstream-1.1.1
ImportĀ upstreamĀ versionĀ 1.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2010-2011 Robert Ancell.
3
 
 * Author: Robert Ancell <robert.ancell@canonical.com>
4
 
 * 
5
 
 * This program is free software: you can redistribute it and/or modify it under
6
 
 * the terms of the GNU General Public License as published by the Free Software
7
 
 * Foundation, either version 3 of the License, or (at your option) any later
8
 
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9
 
 * license.
10
 
 */
11
 
 
12
 
#include <stdlib.h>
13
 
#include <gtk/gtk.h>
14
 
#include <glib/gi18n.h>
15
 
#include <cairo-xlib.h>
16
 
#include <gdk-pixbuf/gdk-pixbuf.h>
17
 
#include <gdk/gdkx.h>
18
 
 
19
 
#include "lightdm.h"
20
 
 
21
 
static LightDMGreeter *greeter;
22
 
static GKeyFile *state;
23
 
static gchar *state_filename;
24
 
static GtkWindow *login_window, *panel_window;
25
 
static GtkLabel *message_label, *prompt_label;
26
 
static GtkTreeView *user_view;
27
 
static GtkWidget *login_box, *prompt_box;
28
 
static GtkEntry *prompt_entry;
29
 
static GtkComboBox *session_combo;
30
 
static GtkComboBox *language_combo;
31
 
static gchar *default_font_name, *default_theme_name;
32
 
static gboolean cancelling = FALSE, prompted = FALSE;
33
 
 
34
 
static gchar *
35
 
get_session ()
36
 
{
37
 
    GtkTreeIter iter;
38
 
    gchar *session;
39
 
 
40
 
    if (!gtk_combo_box_get_active_iter (session_combo, &iter))
41
 
        return g_strdup (lightdm_greeter_get_default_session_hint (greeter));
42
 
 
43
 
    gtk_tree_model_get (gtk_combo_box_get_model (session_combo), &iter, 1, &session, -1);
44
 
 
45
 
    return session;
46
 
}
47
 
 
48
 
static void
49
 
set_session (const gchar *session)
50
 
{
51
 
    GtkTreeModel *model = gtk_combo_box_get_model (session_combo);
52
 
    GtkTreeIter iter;
53
 
    const gchar *default_session;
54
 
 
55
 
    if (session && gtk_tree_model_get_iter_first (model, &iter))
56
 
    {
57
 
        do
58
 
        {
59
 
            gchar *s;
60
 
            gboolean matched;
61
 
            gtk_tree_model_get (model, &iter, 1, &s, -1);
62
 
            matched = strcmp (s, session) == 0;
63
 
            g_free (s);
64
 
            if (matched)
65
 
            {
66
 
                gtk_combo_box_set_active_iter (session_combo, &iter);
67
 
                return;
68
 
            }
69
 
        } while (gtk_tree_model_iter_next (model, &iter));
70
 
    }
71
 
 
72
 
    /* If failed to find this session, then try the default */
73
 
    default_session = lightdm_greeter_get_default_session_hint (greeter);
74
 
    if (default_session && g_strcmp0 (session, default_session) != 0)
75
 
    {
76
 
        set_session (lightdm_greeter_get_default_session_hint (greeter));
77
 
        return;
78
 
    }
79
 
 
80
 
    /* Otherwise just pick the first session */
81
 
    gtk_combo_box_set_active (session_combo, 0);
82
 
}
83
 
 
84
 
static gchar *
85
 
get_language ()
86
 
{
87
 
    GtkTreeIter iter;
88
 
    gchar *language;
89
 
 
90
 
    if (!gtk_combo_box_get_active_iter (language_combo, &iter))
91
 
        return NULL;
92
 
 
93
 
    gtk_tree_model_get (gtk_combo_box_get_model (language_combo), &iter, 1, &language, -1);
94
 
 
95
 
    return language;
96
 
}
97
 
 
98
 
static void
99
 
set_language (const gchar *language)
100
 
{
101
 
    GtkTreeModel *model = gtk_combo_box_get_model (language_combo);
102
 
    GtkTreeIter iter;
103
 
    const gchar *default_language = NULL;
104
 
 
105
 
    if (language && gtk_tree_model_get_iter_first (model, &iter))
106
 
    {
107
 
        do
108
 
        {
109
 
            gchar *s;
110
 
            gboolean matched;
111
 
            gtk_tree_model_get (model, &iter, 1, &s, -1);
112
 
            matched = strcmp (s, language) == 0;
113
 
            g_free (s);
114
 
            if (matched)
115
 
            {
116
 
                gtk_combo_box_set_active_iter (language_combo, &iter);
117
 
                return;
118
 
            }
119
 
        } while (gtk_tree_model_iter_next (model, &iter));
120
 
    }
121
 
 
122
 
    /* If failed to find this language, then try the default */
123
 
    if (lightdm_get_language ())
124
 
        default_language = lightdm_language_get_code (lightdm_get_language ());
125
 
    if (default_language && g_strcmp0 (default_language, language) != 0)
126
 
        set_language (default_language);
127
 
}
128
 
 
129
 
static void
130
 
set_message_label (const gchar *text)
131
 
{
132
 
    gtk_widget_set_visible (GTK_WIDGET (message_label), strcmp (text, "") != 0);
133
 
    gtk_label_set_text (message_label, text);
134
 
}
135
 
 
136
 
static void
137
 
start_authentication (const gchar *username)
138
 
{
139
 
    gchar *data;
140
 
    gsize data_length;
141
 
    GError *error = NULL;
142
 
 
143
 
    cancelling = FALSE;
144
 
    prompted = FALSE;
145
 
 
146
 
    g_key_file_set_value (state, "greeter", "last-user", username);
147
 
    data = g_key_file_to_data (state, &data_length, &error);
148
 
    if (error)
149
 
        g_warning ("Failed to save state file: %s", error->message);
150
 
    g_clear_error (&error);
151
 
    if (data)
152
 
    {
153
 
        g_file_set_contents (state_filename, data, data_length, &error);
154
 
        if (error)
155
 
            g_warning ("Failed to save state file: %s", error->message);
156
 
        g_clear_error (&error);
157
 
    }
158
 
    g_free (data);
159
 
 
160
 
    if (strcmp (username, "*other") == 0)
161
 
    {
162
 
        lightdm_greeter_authenticate (greeter, NULL);
163
 
    }
164
 
    else if (strcmp (username, "*guest") == 0)
165
 
    {
166
 
        lightdm_greeter_authenticate_as_guest (greeter);
167
 
    }
168
 
    else
169
 
    {
170
 
        LightDMUser *user;
171
 
 
172
 
        user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
173
 
        if (user)
174
 
        {
175
 
            set_session (lightdm_user_get_session (user));
176
 
            set_language (lightdm_user_get_language (user));
177
 
        }
178
 
        else
179
 
        {
180
 
            set_session (NULL);
181
 
            set_language (NULL);
182
 
        }
183
 
 
184
 
        lightdm_greeter_authenticate (greeter, username);
185
 
    }
186
 
}
187
 
 
188
 
static void
189
 
cancel_authentication (void)
190
 
{
191
 
    /* If in authentication then stop that first */
192
 
    cancelling = FALSE;
193
 
    if (lightdm_greeter_get_in_authentication (greeter))
194
 
    {
195
 
        cancelling = TRUE;
196
 
        lightdm_greeter_cancel_authentication (greeter);
197
 
        return;
198
 
    }
199
 
 
200
 
    /* Start a new login or return to the user list */
201
 
    if (lightdm_greeter_get_hide_users_hint (greeter))
202
 
        start_authentication ("*other");
203
 
    else
204
 
    {
205
 
        gtk_widget_hide (login_box);
206
 
        gtk_widget_grab_focus (GTK_WIDGET (user_view));
207
 
    }
208
 
}
209
 
 
210
 
static void
211
 
start_session (void)
212
 
{
213
 
    gchar *language;
214
 
    gchar *session;
215
 
 
216
 
    language = get_language ();
217
 
    if (language)
218
 
        lightdm_greeter_set_language (greeter, language);
219
 
    g_free (language);
220
 
 
221
 
    session = get_session ();
222
 
    if (!lightdm_greeter_start_session_sync (greeter, session, NULL))
223
 
    {
224
 
        set_message_label (_("Failed to start session"));
225
 
        start_authentication (lightdm_greeter_get_authentication_user (greeter));
226
 
    }
227
 
    g_free (session);
228
 
}
229
 
 
230
 
void user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column);
231
 
G_MODULE_EXPORT
232
 
void
233
 
user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column)
234
 
{
235
 
    GtkTreeModel *model = gtk_tree_view_get_model (user_view);  
236
 
    GtkTreeIter iter;
237
 
    gchar *user;
238
 
 
239
 
    gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
240
 
    gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
241
 
    start_authentication (user);
242
 
    g_free (user);
243
 
}
244
 
 
245
 
static gboolean
246
 
idle_select_cb ()
247
 
{
248
 
    GtkTreeModel *model = gtk_tree_view_get_model (user_view);
249
 
    GtkTreeIter iter;
250
 
    gchar *user;
251
 
 
252
 
    if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (user_view),
253
 
                                         NULL, &iter))
254
 
    {
255
 
        gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
256
 
        start_authentication (user);
257
 
        g_free (user);
258
 
    }
259
 
 
260
 
    return FALSE;
261
 
}
262
 
 
263
 
gboolean user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event);
264
 
G_MODULE_EXPORT
265
 
gboolean
266
 
user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event)
267
 
{
268
 
    /* Do it in the idle loop so the selection is done first */
269
 
    g_idle_add (idle_select_cb, NULL);
270
 
    return FALSE;
271
 
}
272
 
 
273
 
void login_cb (GtkWidget *widget);
274
 
G_MODULE_EXPORT
275
 
void
276
 
login_cb (GtkWidget *widget)
277
 
{
278
 
    gtk_widget_set_sensitive (GTK_WIDGET (prompt_entry), FALSE);
279
 
    set_message_label ("");
280
 
 
281
 
    if (lightdm_greeter_get_is_authenticated (greeter))
282
 
        start_session ();
283
 
    else if (lightdm_greeter_get_in_authentication (greeter))
284
 
        lightdm_greeter_respond (greeter, gtk_entry_get_text (prompt_entry));
285
 
    else
286
 
        start_authentication (lightdm_greeter_get_authentication_user (greeter));
287
 
}
288
 
 
289
 
void cancel_cb (GtkWidget *widget);
290
 
G_MODULE_EXPORT
291
 
void
292
 
cancel_cb (GtkWidget *widget)
293
 
{
294
 
    cancel_authentication ();
295
 
}
296
 
 
297
 
static void
298
 
show_prompt_cb (LightDMGreeter *greeter, const gchar *text, LightDMPromptType type)
299
 
{
300
 
    prompted = TRUE;
301
 
 
302
 
    gtk_widget_show (GTK_WIDGET (login_box));
303
 
    gtk_label_set_text (prompt_label, text);
304
 
    gtk_widget_set_sensitive (GTK_WIDGET (prompt_entry), TRUE);
305
 
    gtk_entry_set_text (prompt_entry, "");
306
 
    gtk_entry_set_visibility (prompt_entry, type != LIGHTDM_PROMPT_TYPE_SECRET);
307
 
    gtk_widget_show (GTK_WIDGET (prompt_box));
308
 
    gtk_widget_grab_focus (GTK_WIDGET (prompt_entry));
309
 
}
310
 
 
311
 
static void
312
 
show_message_cb (LightDMGreeter *greeter, const gchar *text, LightDMMessageType type)
313
 
{
314
 
    set_message_label (text);
315
 
}
316
 
 
317
 
static void
318
 
authentication_complete_cb (LightDMGreeter *greeter)
319
 
{
320
 
    gtk_entry_set_text (prompt_entry, "");
321
 
 
322
 
    if (cancelling)
323
 
    {
324
 
        cancel_authentication ();
325
 
        return;
326
 
    }
327
 
 
328
 
    gtk_widget_hide (prompt_box);
329
 
    gtk_widget_show (login_box);
330
 
 
331
 
    if (lightdm_greeter_get_is_authenticated (greeter))
332
 
    {
333
 
        if (prompted)
334
 
            start_session ();
335
 
    }
336
 
    else
337
 
    {
338
 
        if (prompted)
339
 
        {
340
 
            set_message_label (_("Incorrect password, please try again"));
341
 
            start_authentication (lightdm_greeter_get_authentication_user (greeter));
342
 
        }
343
 
        else
344
 
            set_message_label (_("Failed to authenticate"));
345
 
    }
346
 
}
347
 
 
348
 
static void
349
 
autologin_timer_expired_cb (LightDMGreeter *greeter)
350
 
{
351
 
    if (lightdm_greeter_get_autologin_guest_hint (greeter))
352
 
        start_authentication ("*guest");
353
 
    else if (lightdm_greeter_get_autologin_user_hint (greeter))
354
 
        start_authentication (lightdm_greeter_get_autologin_user_hint (greeter));
355
 
}
356
 
 
357
 
static void
358
 
center_window (GtkWindow *window)
359
 
{
360
 
    GdkScreen *screen;
361
 
    GtkAllocation allocation;
362
 
    GdkRectangle monitor_geometry;
363
 
 
364
 
    screen = gtk_window_get_screen (window);
365
 
    gdk_screen_get_monitor_geometry (screen, gdk_screen_get_primary_monitor (screen), &monitor_geometry);
366
 
    gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
367
 
    gtk_window_move (window,
368
 
                     monitor_geometry.x + (monitor_geometry.width - allocation.width) / 2,
369
 
                     monitor_geometry.y + (monitor_geometry.height - allocation.height) / 2);
370
 
}
371
 
 
372
 
void login_window_size_allocate_cb (GtkWidget *widget, GdkRectangle *allocation);
373
 
G_MODULE_EXPORT
374
 
void
375
 
login_window_size_allocate_cb (GtkWidget *widget, GdkRectangle *allocation)
376
 
{
377
 
    center_window (GTK_WINDOW (widget));
378
 
}
379
 
 
380
 
void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
381
 
G_MODULE_EXPORT
382
 
void
383
 
suspend_cb (GtkWidget *widget, LightDMGreeter *greeter)
384
 
{
385
 
    lightdm_suspend (NULL);
386
 
}
387
 
 
388
 
void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
389
 
G_MODULE_EXPORT
390
 
void
391
 
hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter)
392
 
{
393
 
    lightdm_hibernate (NULL);
394
 
}
395
 
 
396
 
void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
397
 
G_MODULE_EXPORT
398
 
void
399
 
restart_cb (GtkWidget *widget, LightDMGreeter *greeter)
400
 
{
401
 
    GtkWidget *dialog;
402
 
 
403
 
    gtk_widget_hide (GTK_WIDGET (login_window));
404
 
 
405
 
    dialog = gtk_message_dialog_new (NULL,
406
 
                                     GTK_DIALOG_MODAL,
407
 
                                     GTK_MESSAGE_OTHER,
408
 
                                     GTK_BUTTONS_NONE,
409
 
                                     "%s", _("Are you sure you want to close all programs and restart the computer?"));
410
 
    gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Return To Login"), FALSE, _("Restart"), TRUE, NULL);
411
 
    gtk_widget_show_all (dialog);
412
 
    center_window (GTK_WINDOW (dialog));
413
 
 
414
 
    if (gtk_dialog_run (GTK_DIALOG (dialog)))
415
 
        lightdm_restart (NULL);
416
 
 
417
 
    gtk_widget_destroy (dialog);
418
 
    gtk_widget_show (GTK_WIDGET (login_window));
419
 
}
420
 
 
421
 
void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
422
 
G_MODULE_EXPORT
423
 
void
424
 
shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter)
425
 
{
426
 
    GtkWidget *dialog;
427
 
 
428
 
    gtk_widget_hide (GTK_WIDGET (login_window));
429
 
 
430
 
    dialog = gtk_message_dialog_new (NULL,
431
 
                                     GTK_DIALOG_MODAL,
432
 
                                     GTK_MESSAGE_OTHER,
433
 
                                     GTK_BUTTONS_NONE,
434
 
                                     "%s", _("Are you sure you want to close all programs and shutdown the computer?"));
435
 
    gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Return To Login"), FALSE, _("Shutdown"), TRUE, NULL);
436
 
    gtk_widget_show_all (dialog);
437
 
    center_window (GTK_WINDOW (dialog));
438
 
 
439
 
    if (gtk_dialog_run (GTK_DIALOG (dialog)))
440
 
        lightdm_shutdown (NULL);
441
 
 
442
 
    gtk_widget_destroy (dialog);
443
 
    gtk_widget_show (GTK_WIDGET (login_window));
444
 
}
445
 
 
446
 
static void
447
 
user_added_cb (LightDMUserList *user_list, LightDMUser *user)
448
 
{
449
 
    GtkTreeModel *model;
450
 
    GtkTreeIter iter;
451
 
 
452
 
    model = gtk_tree_view_get_model (user_view);
453
 
 
454
 
    gtk_list_store_append (GTK_LIST_STORE (model), &iter);
455
 
    gtk_list_store_set (GTK_LIST_STORE (model), &iter,
456
 
                        0, lightdm_user_get_name (user),
457
 
                        1, lightdm_user_get_display_name (user),
458
 
                        2, lightdm_user_get_logged_in (user) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
459
 
                        /*3, pixbuf,*/
460
 
                        -1);
461
 
}
462
 
 
463
 
static gboolean
464
 
get_user_iter (const gchar *username, GtkTreeIter *iter)
465
 
{
466
 
    GtkTreeModel *model;
467
 
 
468
 
    model = gtk_tree_view_get_model (user_view);
469
 
  
470
 
    if (!gtk_tree_model_get_iter_first (model, iter))
471
 
        return FALSE;
472
 
    do
473
 
    {
474
 
        gchar *name;
475
 
        gboolean matched;
476
 
 
477
 
        gtk_tree_model_get (model, iter, 0, &name, -1);
478
 
        matched = g_strcmp0 (name, username) == 0;
479
 
        g_free (name);
480
 
        if (matched)
481
 
            return TRUE;
482
 
    } while (gtk_tree_model_iter_next (model, iter));
483
 
 
484
 
    return FALSE;
485
 
}
486
 
 
487
 
static void
488
 
user_changed_cb (LightDMUserList *user_list, LightDMUser *user)
489
 
{
490
 
    GtkTreeModel *model;
491
 
    GtkTreeIter iter;
492
 
 
493
 
    if (!get_user_iter (lightdm_user_get_name (user), &iter))
494
 
        return;
495
 
 
496
 
    model = gtk_tree_view_get_model (user_view);
497
 
    gtk_list_store_set (GTK_LIST_STORE (model), &iter,
498
 
                        0, lightdm_user_get_name (user),
499
 
                        1, lightdm_user_get_display_name (user),
500
 
                        2, lightdm_user_get_logged_in (user) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
501
 
                        /*3, pixbuf,*/
502
 
                        -1);
503
 
}
504
 
 
505
 
static void
506
 
user_removed_cb (LightDMUserList *user_list, LightDMUser *user)
507
 
{
508
 
    GtkTreeModel *model;
509
 
    GtkTreeIter iter;
510
 
 
511
 
    if (!get_user_iter (lightdm_user_get_name (user), &iter))
512
 
        return;
513
 
 
514
 
    model = gtk_tree_view_get_model (user_view);  
515
 
    gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
516
 
}
517
 
 
518
 
void a11y_font_cb (GtkWidget *widget);
519
 
G_MODULE_EXPORT
520
 
void
521
 
a11y_font_cb (GtkWidget *widget)
522
 
{
523
 
    if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
524
 
    {
525
 
        gchar *font_name, **tokens;
526
 
 
527
 
        g_object_get (gtk_settings_get_default (), "gtk-font-name", &font_name, NULL);
528
 
        tokens = g_strsplit (font_name, " ", 2);
529
 
        if (g_strv_length (tokens) == 2)
530
 
        {
531
 
            gint size = atoi (tokens[1]);
532
 
            if (size > 0)
533
 
            {
534
 
                g_free (font_name);
535
 
                font_name = g_strdup_printf ("%s %d", tokens[0], size + 10);
536
 
            }
537
 
        }
538
 
        g_strfreev (tokens);
539
 
 
540
 
        g_object_set (gtk_settings_get_default (), "gtk-font-name", font_name, NULL);
541
 
    }
542
 
    else
543
 
        g_object_set (gtk_settings_get_default (), "gtk-font-name", default_font_name, NULL);
544
 
}
545
 
 
546
 
void a11y_contrast_cb (GtkWidget *widget);
547
 
G_MODULE_EXPORT
548
 
void
549
 
a11y_contrast_cb (GtkWidget *widget)
550
 
{
551
 
    if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
552
 
        g_object_set (gtk_settings_get_default (), "gtk-theme-name", "HighContrastInverse", NULL);
553
 
    else
554
 
        g_object_set (gtk_settings_get_default (), "gtk-theme-name", default_theme_name, NULL);
555
 
}
556
 
 
557
 
static void
558
 
sigterm_cb (int signum)
559
 
{
560
 
    exit (0);
561
 
}
562
 
 
563
 
static void
564
 
load_user_list ()
565
 
{
566
 
    const GList *items, *item;
567
 
    GtkTreeModel *model;
568
 
    GtkTreeIter iter;
569
 
    gchar *last_user;
570
 
    const gchar *selected_user;
571
 
 
572
 
    g_signal_connect (lightdm_user_list_get_instance (), "user-added", G_CALLBACK (user_added_cb), NULL);
573
 
    g_signal_connect (lightdm_user_list_get_instance (), "user-changed", G_CALLBACK (user_changed_cb), NULL);
574
 
    g_signal_connect (lightdm_user_list_get_instance (), "user-removed", G_CALLBACK (user_removed_cb), NULL);
575
 
 
576
 
    model = gtk_tree_view_get_model (user_view);
577
 
    items = lightdm_user_list_get_users (lightdm_user_list_get_instance ());
578
 
    for (item = items; item; item = item->next)
579
 
    {
580
 
        LightDMUser *user = item->data;
581
 
        const gchar *image;
582
 
        GdkPixbuf *pixbuf = NULL;
583
 
 
584
 
        image = lightdm_user_get_image (user);
585
 
        if (image)
586
 
            pixbuf = gdk_pixbuf_new_from_file_at_scale (image, 64, 64, TRUE, NULL);
587
 
        if (!pixbuf)
588
 
            pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
589
 
                                               "stock_person",
590
 
                                               64,
591
 
                                               GTK_ICON_LOOKUP_USE_BUILTIN,
592
 
                                               NULL);
593
 
        /*if (!pixbuf)
594
 
        {
595
 
            pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 64, 64);
596
 
            memset (gdk_pixbuf_get_pixels (pixbuf), 0, gdk_pixbuf_get_height (pixbuf) * gdk_pixbuf_get_rowstride (pixbuf) * gdk_pixbuf_get_n_channels (pixbuf));
597
 
        }*/
598
 
 
599
 
        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
600
 
        gtk_list_store_set (GTK_LIST_STORE (model), &iter,
601
 
                            0, lightdm_user_get_name (user),
602
 
                            1, lightdm_user_get_display_name (user),
603
 
                            2, lightdm_user_get_logged_in (user) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
604
 
                            3, pixbuf,
605
 
                            -1);
606
 
    }
607
 
    if (lightdm_greeter_get_has_guest_account_hint (greeter))
608
 
    {
609
 
        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
610
 
        gtk_list_store_set (GTK_LIST_STORE (model), &iter,
611
 
                            0, "*guest",
612
 
                            1, _("Guest Account"),
613
 
                            2, PANGO_WEIGHT_NORMAL,
614
 
                            3, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
615
 
                            -1);
616
 
    }
617
 
 
618
 
    gtk_list_store_append (GTK_LIST_STORE (model), &iter);
619
 
    gtk_list_store_set (GTK_LIST_STORE (model), &iter,
620
 
                        0, "*other",
621
 
                        1, _("Other..."),
622
 
                        2, PANGO_WEIGHT_NORMAL,
623
 
                        3, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
624
 
                        -1);
625
 
 
626
 
    last_user = g_key_file_get_value (state, "greeter", "last-user", NULL);
627
 
 
628
 
    if (lightdm_greeter_get_select_user_hint (greeter))
629
 
        selected_user = lightdm_greeter_get_select_user_hint (greeter);
630
 
    else if (lightdm_greeter_get_select_guest_hint (greeter))
631
 
        selected_user = "*guest";
632
 
    else if (last_user)
633
 
        selected_user = last_user;
634
 
    else
635
 
        selected_user = NULL;
636
 
 
637
 
    if (selected_user && gtk_tree_model_get_iter_first (model, &iter))
638
 
    {
639
 
        do
640
 
        {
641
 
            gchar *name;
642
 
            gboolean matched;
643
 
            gtk_tree_model_get (model, &iter, 0, &name, -1);
644
 
            matched = strcmp (name, selected_user) == 0;
645
 
            g_free (name);
646
 
            if (matched)
647
 
            {
648
 
                gtk_tree_selection_select_iter (gtk_tree_view_get_selection (user_view), &iter);
649
 
                start_authentication (selected_user);
650
 
                break;
651
 
            }
652
 
        } while (gtk_tree_model_iter_next (model, &iter));
653
 
    }
654
 
 
655
 
    g_free (last_user);
656
 
}
657
 
 
658
 
static cairo_surface_t *
659
 
create_root_surface (GdkScreen *screen)
660
 
{
661
 
    gint number, width, height;
662
 
    Display *display;
663
 
    Pixmap pixmap;
664
 
    cairo_surface_t *surface;
665
 
 
666
 
    number = gdk_screen_get_number (screen);
667
 
    width = gdk_screen_get_width (screen);
668
 
    height = gdk_screen_get_height (screen);
669
 
 
670
 
    /* Open a new connection so with Retain Permanent so the pixmap remains when the greeter quits */
671
 
    gdk_flush ();
672
 
    display = XOpenDisplay (gdk_display_get_name (gdk_screen_get_display (screen)));
673
 
    if (!display)
674
 
    {
675
 
        g_warning ("Failed to create root pixmap");
676
 
        return NULL;
677
 
    }
678
 
    XSetCloseDownMode (display, RetainPermanent);
679
 
    pixmap = XCreatePixmap (display, RootWindow (display, number), width, height, DefaultDepth (display, number));
680
 
    XCloseDisplay (display);
681
 
 
682
 
    /* Convert into a Cairo surface */
683
 
    surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen),
684
 
                                         pixmap,
685
 
                                         GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen)),
686
 
                                         width, height);
687
 
 
688
 
    /* Use this pixmap for the background */
689
 
    XSetWindowBackgroundPixmap (GDK_SCREEN_XDISPLAY (screen),
690
 
                                RootWindow (GDK_SCREEN_XDISPLAY (screen), number),
691
 
                                cairo_xlib_surface_get_drawable (surface));
692
 
 
693
 
 
694
 
    return surface;  
695
 
}
696
 
 
697
 
int
698
 
main (int argc, char **argv)
699
 
{
700
 
    GKeyFile *config;
701
 
    GdkRectangle monitor_geometry;
702
 
    GtkBuilder *builder;
703
 
    GtkTreeModel *model;
704
 
    const GList *items, *item;
705
 
    GtkTreeIter iter;
706
 
    GtkCellRenderer *renderer;
707
 
    GtkWidget *menuitem, *hbox, *image;
708
 
    gchar *value, *state_dir;
709
 
    GdkPixbuf *background_pixbuf = NULL;
710
 
    GdkColor background_color;
711
 
    gint i;
712
 
    GError *error = NULL;
713
 
 
714
 
    /* Disable global menus */
715
 
    g_unsetenv ("UBUNTU_MENUPROXY");
716
 
 
717
 
    /* Initialize i18n */
718
 
    setlocale (LC_ALL, "");
719
 
    bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
720
 
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
721
 
    textdomain (GETTEXT_PACKAGE);
722
 
 
723
 
    signal (SIGTERM, sigterm_cb);
724
 
 
725
 
    gtk_init (&argc, &argv);
726
 
 
727
 
    config = g_key_file_new ();
728
 
    g_key_file_load_from_file (config, CONFIG_FILE, G_KEY_FILE_NONE, &error);
729
 
    if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
730
 
        g_warning ("Failed to load configuration from %s: %s\n", CONFIG_FILE, error->message);
731
 
    g_clear_error (&error);
732
 
 
733
 
    state_dir = g_build_filename (g_get_user_cache_dir (), "lightdm-gtk-greeter", NULL);
734
 
    g_mkdir_with_parents (state_dir, 0775);
735
 
    state_filename = g_build_filename (state_dir, "state", NULL);
736
 
    g_free (state_dir);
737
 
 
738
 
    state = g_key_file_new ();
739
 
    g_key_file_load_from_file (state, state_filename, G_KEY_FILE_NONE, &error);
740
 
    if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
741
 
        g_warning ("Failed to load state from %s: %s\n", state_filename, error->message);
742
 
    g_clear_error (&error);
743
 
 
744
 
    greeter = lightdm_greeter_new ();
745
 
    g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);  
746
 
    g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);
747
 
    g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
748
 
    g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (autologin_timer_expired_cb), NULL);
749
 
    if (!lightdm_greeter_connect_sync (greeter, NULL))
750
 
        return EXIT_FAILURE;
751
 
 
752
 
    /* Set default cursor */
753
 
    gdk_window_set_cursor (gdk_get_default_root_window (), gdk_cursor_new (GDK_LEFT_PTR));
754
 
 
755
 
    /* Load background */
756
 
    value = g_key_file_get_value (config, "greeter", "background", NULL);
757
 
    if (!value)
758
 
        value = g_strdup ("#000000");
759
 
    if (!gdk_color_parse (value, &background_color))
760
 
    {
761
 
        gchar *path;
762
 
        GError *error = NULL;
763
 
 
764
 
        if (g_path_is_absolute (value))
765
 
            path = g_strdup (value);
766
 
        else
767
 
            path = g_build_filename (GREETER_DATA_DIR, value, NULL);
768
 
 
769
 
        g_debug ("Loading background %s", path);
770
 
        background_pixbuf = gdk_pixbuf_new_from_file (path, &error);
771
 
        if (!background_pixbuf)
772
 
           g_warning ("Failed to load background: %s", error->message);
773
 
        g_clear_error (&error);
774
 
        g_free (path);
775
 
    }
776
 
    else
777
 
        g_debug ("Using background color %s", value);
778
 
    g_free (value);
779
 
 
780
 
    /* Set the background */
781
 
    for (i = 0; i < gdk_display_get_n_screens (gdk_display_get_default ()); i++)
782
 
    {
783
 
        GdkScreen *screen;
784
 
        cairo_surface_t *surface;
785
 
        cairo_t *c;
786
 
        int monitor;
787
 
 
788
 
        screen = gdk_display_get_screen (gdk_display_get_default (), i);
789
 
        surface = create_root_surface (screen);
790
 
        c = cairo_create (surface);
791
 
 
792
 
        for (monitor = 0; monitor < gdk_screen_get_n_monitors (screen); monitor++)
793
 
        {
794
 
            gdk_screen_get_monitor_geometry (screen, monitor, &monitor_geometry);
795
 
 
796
 
            if (background_pixbuf)
797
 
            {
798
 
                GdkPixbuf *pixbuf = gdk_pixbuf_scale_simple (background_pixbuf, monitor_geometry.width, monitor_geometry.height, GDK_INTERP_BILINEAR);
799
 
                gdk_cairo_set_source_pixbuf (c, pixbuf, monitor_geometry.x, monitor_geometry.y);
800
 
                g_object_unref (pixbuf);
801
 
            }
802
 
            else
803
 
                gdk_cairo_set_source_color (c, &background_color);
804
 
            cairo_paint (c);
805
 
        }
806
 
 
807
 
        cairo_destroy (c);
808
 
 
809
 
        /* Refresh background */
810
 
        gdk_flush ();
811
 
        XClearWindow (GDK_SCREEN_XDISPLAY (screen), RootWindow (GDK_SCREEN_XDISPLAY (screen), i));
812
 
    }
813
 
    if (background_pixbuf)
814
 
        g_object_unref (background_pixbuf);
815
 
 
816
 
    /* Set GTK+ settings */
817
 
    value = g_key_file_get_value (config, "greeter", "theme-name", NULL);
818
 
    if (value)
819
 
    {
820
 
        g_debug ("Using theme %s", value);
821
 
        g_object_set (gtk_settings_get_default (), "gtk-theme-name", value, NULL);
822
 
    }
823
 
    g_free (value);
824
 
    g_object_get (gtk_settings_get_default (), "gtk-theme-name", &default_theme_name, NULL);
825
 
    g_debug ("Default theme is '%s'", default_theme_name);
826
 
 
827
 
    value = g_key_file_get_value (config, "greeter", "font-name", NULL);
828
 
    if (value)
829
 
    {
830
 
        g_debug ("Using font %s", value);
831
 
        g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
832
 
    }
833
 
    g_object_get (gtk_settings_get_default (), "gtk-font-name", &default_font_name, NULL);  
834
 
    value = g_key_file_get_value (config, "greeter", "xft-dpi", NULL);
835
 
    if (value)
836
 
        g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", (int) (1024 * atof (value)), NULL);
837
 
    value = g_key_file_get_value (config, "greeter", "xft-antialias", NULL);
838
 
    if (value)
839
 
        g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", strcmp (value, "true") == 0, NULL);
840
 
    g_free (value);
841
 
    value = g_key_file_get_value (config, "greeter", "xft-hintstyle", NULL);
842
 
    if (value)
843
 
        g_object_set (gtk_settings_get_default (), "gtk-xft-hintstyle", value, NULL);
844
 
    g_free (value);
845
 
    value = g_key_file_get_value (config, "greeter", "xft-rgba", NULL);
846
 
    if (value)
847
 
        g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);
848
 
    g_free (value);
849
 
 
850
 
    /* Load out installed icons */
851
 
    gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), GREETER_DATA_DIR);
852
 
    gchar **path;
853
 
    gtk_icon_theme_get_search_path (gtk_icon_theme_get_default (), &path, NULL);
854
 
 
855
 
    builder = gtk_builder_new ();
856
 
    if (!gtk_builder_add_from_file (builder, GREETER_DATA_DIR "/greeter.ui", &error))
857
 
    {
858
 
        g_warning ("Error loading UI: %s", error->message);
859
 
        return EXIT_FAILURE;
860
 
    }
861
 
    g_clear_error (&error);
862
 
 
863
 
    login_window = GTK_WINDOW (gtk_builder_get_object (builder, "login_window"));
864
 
    login_box = GTK_WIDGET (gtk_builder_get_object (builder, "login_box"));
865
 
    prompt_box = GTK_WIDGET (gtk_builder_get_object (builder, "prompt_box"));
866
 
    prompt_label = GTK_LABEL (gtk_builder_get_object (builder, "prompt_label"));
867
 
    prompt_entry = GTK_ENTRY (gtk_builder_get_object (builder, "prompt_entry"));
868
 
    message_label = GTK_LABEL (gtk_builder_get_object (builder, "message_label"));
869
 
    session_combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, "session_combobox"));
870
 
    language_combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, "language_combobox"));  
871
 
    panel_window = GTK_WINDOW (gtk_builder_get_object (builder, "panel_window"));
872
 
 
873
 
    gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "hostname_label")), lightdm_get_hostname ());
874
 
 
875
 
    /* Glade can't handle custom menuitems, so set them up manually */
876
 
    menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "power_menuitem"));
877
 
    hbox = gtk_hbox_new (FALSE, 0);
878
 
    gtk_widget_show (hbox);
879
 
    gtk_container_add (GTK_CONTAINER (menuitem), hbox);
880
 
    image = gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_MENU);
881
 
    gtk_widget_show (image);
882
 
    gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0);
883
 
 
884
 
    menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "a11y_menuitem"));
885
 
    hbox = gtk_hbox_new (FALSE, 0);
886
 
    gtk_widget_show (hbox);
887
 
    gtk_container_add (GTK_CONTAINER (menuitem), hbox);
888
 
    image = gtk_image_new_from_icon_name ("accessibility", GTK_ICON_SIZE_MENU);
889
 
    gtk_widget_show (image);
890
 
    gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0);
891
 
 
892
 
    if (!lightdm_get_can_suspend ())
893
 
        gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "suspend_menuitem")));
894
 
    if (!lightdm_get_can_hibernate ())
895
 
        gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "hibernate_menuitem")));
896
 
    if (!lightdm_get_can_restart ())
897
 
        gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "restart_menuitem")));
898
 
    if (!lightdm_get_can_shutdown ())
899
 
        gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "shutdown_menuitem")));
900
 
 
901
 
    renderer = gtk_cell_renderer_text_new();
902
 
    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (session_combo), renderer, TRUE);
903
 
    gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (session_combo), renderer, "text", 0);
904
 
    model = gtk_combo_box_get_model (session_combo);
905
 
    items = lightdm_get_sessions ();
906
 
    for (item = items; item; item = item->next)
907
 
    {
908
 
        LightDMSession *session = item->data;
909
 
 
910
 
        gtk_widget_show (GTK_WIDGET (session_combo));
911
 
        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
912
 
        gtk_list_store_set (GTK_LIST_STORE (model), &iter,
913
 
                            0, lightdm_session_get_name (session),
914
 
                            1, lightdm_session_get_key (session),
915
 
                            -1);
916
 
    }
917
 
    set_session (NULL);
918
 
 
919
 
    if (g_key_file_get_boolean (config, "greeter", "show-language-selector", NULL))
920
 
    {
921
 
        gtk_widget_show (GTK_WIDGET (language_combo));
922
 
 
923
 
        renderer = gtk_cell_renderer_text_new();
924
 
        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (language_combo), renderer, TRUE);
925
 
        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (language_combo), renderer, "text", 0);
926
 
        model = gtk_combo_box_get_model (language_combo);
927
 
        items = lightdm_get_languages ();
928
 
        for (item = items; item; item = item->next)
929
 
        {
930
 
            LightDMLanguage *language = item->data;
931
 
            gchar *label;
932
 
 
933
 
            label = g_strdup_printf ("%s - %s", lightdm_language_get_name (language), lightdm_language_get_territory (language));
934
 
 
935
 
            gtk_widget_show (GTK_WIDGET (language_combo));
936
 
            gtk_list_store_append (GTK_LIST_STORE (model), &iter);
937
 
            gtk_list_store_set (GTK_LIST_STORE (model), &iter,
938
 
                                0, label,
939
 
                                1, lightdm_language_get_code (language),
940
 
                                -1);
941
 
            g_free (label);
942
 
        }
943
 
        set_language (NULL);
944
 
    }
945
 
 
946
 
    user_view = GTK_TREE_VIEW (gtk_builder_get_object (builder, "user_treeview"));
947
 
    gtk_tree_view_insert_column_with_attributes (user_view, 0, "Face", gtk_cell_renderer_pixbuf_new(), "pixbuf", 3, NULL);
948
 
    gtk_tree_view_insert_column_with_attributes (user_view, 1, "Name", gtk_cell_renderer_text_new(), "text", 1, "weight", 2, NULL);
949
 
 
950
 
    if (lightdm_greeter_get_hide_users_hint (greeter))
951
 
        start_authentication ("*other");
952
 
    else
953
 
    {
954
 
        load_user_list ();
955
 
        gtk_widget_show (GTK_WIDGET (user_view));
956
 
    } 
957
 
 
958
 
    gtk_builder_connect_signals(builder, greeter);
959
 
 
960
 
    gtk_widget_show (GTK_WIDGET (login_window));
961
 
    center_window (login_window);
962
 
 
963
 
    gtk_widget_show (GTK_WIDGET (panel_window));
964
 
    GtkAllocation allocation;
965
 
    gtk_widget_get_allocation (GTK_WIDGET (panel_window), &allocation);
966
 
    gdk_screen_get_monitor_geometry (gdk_screen_get_default (), gdk_screen_get_primary_monitor (gdk_screen_get_default ()), &monitor_geometry);
967
 
    gtk_window_resize (panel_window, monitor_geometry.width, allocation.height);
968
 
    gtk_window_move (panel_window, monitor_geometry.x, monitor_geometry.y);
969
 
 
970
 
    gtk_widget_show (GTK_WIDGET (login_window));
971
 
    gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
972
 
 
973
 
    gtk_main ();
974
 
 
975
 
    return EXIT_SUCCESS;
976
 
}