]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - greeters/gtk/lightdm-gtk-greeter.c
ed9cb4d5311e99f23e1a9a6b86258110d7007dcf
[sojka/lightdm.git] / greeters / gtk / lightdm-gtk-greeter.c
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 GtkWindow *login_window, *panel_window;
23 static GtkLabel *message_label, *prompt_label;
24 static GtkTreeView *user_view;
25 static GtkWidget *login_box, *prompt_box;
26 static GtkEntry *prompt_entry;
27 static GtkComboBox *session_combo;
28 static gchar *default_font_name, *default_theme_name;
29 static gboolean cancelling = FALSE, prompted = FALSE;
30
31 static gchar *
32 get_session ()
33 {
34     GtkTreeIter iter;
35     gchar *session;
36
37     if (!gtk_combo_box_get_active_iter (session_combo, &iter))
38         return g_strdup (lightdm_greeter_get_default_session_hint (greeter));
39
40     gtk_tree_model_get (gtk_combo_box_get_model (session_combo), &iter, 1, &session, -1);
41
42     return session;
43 }
44
45 static void
46 set_session (const gchar *session)
47 {
48     GtkTreeModel *model = gtk_combo_box_get_model (session_combo);
49     GtkTreeIter iter;
50     const gchar *default_session;
51
52     if (session && gtk_tree_model_get_iter_first (model, &iter))
53     {
54         do
55         {
56             gchar *s;
57             gboolean matched;
58             gtk_tree_model_get (model, &iter, 1, &s, -1);
59             matched = strcmp (s, session) == 0;
60             g_free (s);
61             if (matched)
62             {
63                 gtk_combo_box_set_active_iter (session_combo, &iter);
64                 return;
65             }
66         } while (gtk_tree_model_iter_next (model, &iter));
67     }
68
69     /* If failed to find this session, then try the default */
70     default_session = lightdm_greeter_get_default_session_hint (greeter);
71     if (default_session && g_strcmp0 (session, default_session) != 0)
72         set_session (lightdm_greeter_get_default_session_hint (greeter));
73 }
74
75 static void
76 set_message_label (const gchar *text)
77 {
78     gtk_widget_set_visible (GTK_WIDGET (message_label), strcmp (text, "") != 0);
79     gtk_label_set_text (message_label, text);
80 }
81
82 static void
83 start_authentication (const gchar *username)
84 {
85     cancelling = FALSE;
86     prompted = FALSE;
87
88     if (!username)
89     {
90         lightdm_greeter_authenticate (greeter, NULL);
91     }
92     else if (strcmp (username, "*guest") == 0)
93     {
94         lightdm_greeter_authenticate_as_guest (greeter);
95     }
96     else
97     {
98         LightDMUser *user;
99
100         user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
101         if (user)
102             set_session (lightdm_user_get_session (user));
103         else
104             set_session (NULL);
105
106         lightdm_greeter_authenticate (greeter, username);
107     }
108 }
109
110 static void
111 cancel_authentication (void)
112 {
113     /* If in authentication then stop that first */
114     cancelling = FALSE;
115     if (lightdm_greeter_get_in_authentication (greeter))
116     {
117         cancelling = TRUE;
118         lightdm_greeter_cancel_authentication (greeter);
119         return;
120     }
121
122     /* Start a new login or return to the user list */
123     if (lightdm_greeter_get_hide_users_hint (greeter))
124         start_authentication (NULL);
125     else
126     {
127         gtk_widget_hide (login_box);
128         gtk_widget_grab_focus (GTK_WIDGET (user_view));
129     }
130 }
131
132 static void
133 start_session (void)
134 {
135     gchar *session;
136
137     session = get_session ();
138     if (!lightdm_greeter_start_session_sync (greeter, session, NULL))
139     {
140         set_message_label (_("Failed to start session"));
141         start_authentication (lightdm_greeter_get_authentication_user (greeter));
142     }
143     g_free (session);
144 }
145
146 void user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column);
147 G_MODULE_EXPORT
148 void
149 user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column)
150 {
151     GtkTreeModel *model = gtk_tree_view_get_model (user_view);  
152     GtkTreeIter iter;
153     gchar *user;
154
155     gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
156     gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
157     start_authentication (user);
158     g_free (user);
159 }
160
161 static gboolean
162 idle_select_cb ()
163 {
164     GtkTreeModel *model = gtk_tree_view_get_model (user_view);
165     GtkTreeIter iter;
166     gchar *user;
167
168     if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (user_view),
169                                          NULL, &iter))
170     {
171         gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
172         start_authentication (user);
173         g_free (user);
174     }
175
176     return FALSE;
177 }
178
179 gboolean user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event);
180 G_MODULE_EXPORT
181 gboolean
182 user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event)
183 {
184     /* Do it in the idle loop so the selection is done first */
185     g_idle_add (idle_select_cb, NULL);
186     return FALSE;
187 }
188
189 void login_cb (GtkWidget *widget);
190 G_MODULE_EXPORT
191 void
192 login_cb (GtkWidget *widget)
193 {
194     gtk_widget_set_sensitive (GTK_WIDGET (prompt_entry), FALSE);
195     set_message_label ("");
196
197     if (lightdm_greeter_get_is_authenticated (greeter))
198         start_session ();
199     else if (lightdm_greeter_get_in_authentication (greeter))
200         lightdm_greeter_respond (greeter, gtk_entry_get_text (prompt_entry));
201     else
202         start_authentication (lightdm_greeter_get_authentication_user (greeter));
203 }
204
205 void cancel_cb (GtkWidget *widget);
206 G_MODULE_EXPORT
207 void
208 cancel_cb (GtkWidget *widget)
209 {
210     cancel_authentication ();
211 }
212
213 static void
214 show_prompt_cb (LightDMGreeter *greeter, const gchar *text, LightDMPromptType type)
215 {
216     prompted = TRUE;
217
218     gtk_widget_show (GTK_WIDGET (login_box));
219     gtk_label_set_text (prompt_label, text);
220     gtk_widget_set_sensitive (GTK_WIDGET (prompt_entry), TRUE);
221     gtk_entry_set_text (prompt_entry, "");
222     gtk_entry_set_visibility (prompt_entry, type != LIGHTDM_PROMPT_TYPE_SECRET);
223     gtk_widget_show (GTK_WIDGET (prompt_box));
224     gtk_widget_grab_focus (GTK_WIDGET (prompt_entry));
225 }
226
227 static void
228 show_message_cb (LightDMGreeter *greeter, const gchar *text, LightDMMessageType type)
229 {
230     set_message_label (text);
231 }
232
233 static void
234 authentication_complete_cb (LightDMGreeter *greeter)
235 {
236     gtk_entry_set_text (prompt_entry, "");
237
238     if (cancelling)
239     {
240         cancel_authentication ();
241         return;
242     }
243
244     gtk_widget_hide (prompt_box);
245     gtk_widget_show (login_box);
246
247     if (lightdm_greeter_get_is_authenticated (greeter))
248     {
249         if (prompted)
250             start_session ();
251     }
252     else
253     {
254         if (prompted)
255         {
256             set_message_label (_("Incorrect password, please try again"));
257             start_authentication (lightdm_greeter_get_authentication_user (greeter));
258         }
259         else
260             set_message_label (_("Failed to authenticate"));
261     }
262 }
263
264 static void
265 autologin_timer_expired_cb (LightDMGreeter *greeter)
266 {
267     if (lightdm_greeter_get_autologin_guest_hint (greeter))
268         start_authentication ("*guest");
269     else if (lightdm_greeter_get_autologin_user_hint (greeter))
270         start_authentication (lightdm_greeter_get_autologin_user_hint (greeter));
271 }
272
273 static void
274 center_window (GtkWindow *window)
275 {
276     GdkScreen *screen;
277     GtkAllocation allocation;
278     GdkRectangle monitor_geometry;
279
280     screen = gtk_window_get_screen (window);
281     gdk_screen_get_monitor_geometry (screen, gdk_screen_get_primary_monitor (screen), &monitor_geometry);
282     gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
283     gtk_window_move (window,
284                      monitor_geometry.x + (monitor_geometry.width - allocation.width) / 2,
285                      monitor_geometry.y + (monitor_geometry.height - allocation.height) / 2);
286 }
287
288 void login_window_size_allocate_cb (GtkWidget *widget, GdkRectangle *allocation);
289 G_MODULE_EXPORT
290 void
291 login_window_size_allocate_cb (GtkWidget *widget, GdkRectangle *allocation)
292 {
293     center_window (GTK_WINDOW (widget));
294 }
295
296 void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
297 G_MODULE_EXPORT
298 void
299 suspend_cb (GtkWidget *widget, LightDMGreeter *greeter)
300 {
301     lightdm_suspend (NULL);
302 }
303
304 void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
305 G_MODULE_EXPORT
306 void
307 hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter)
308 {
309     lightdm_hibernate (NULL);
310 }
311
312 void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
313 G_MODULE_EXPORT
314 void
315 restart_cb (GtkWidget *widget, LightDMGreeter *greeter)
316 {
317     GtkWidget *dialog;
318
319     gtk_widget_hide (GTK_WIDGET (login_window));
320
321     dialog = gtk_message_dialog_new (NULL,
322                                      GTK_DIALOG_MODAL,
323                                      GTK_MESSAGE_OTHER,
324                                      GTK_BUTTONS_NONE,
325                                      "%s", _("Are you sure you want to close all programs and restart the computer?"));
326     gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Return To Login"), FALSE, _("Restart"), TRUE, NULL);
327     gtk_widget_show_all (dialog);
328     center_window (GTK_WINDOW (dialog));
329
330     if (gtk_dialog_run (GTK_DIALOG (dialog)))
331         lightdm_restart (NULL);
332
333     gtk_widget_destroy (dialog);
334     gtk_widget_show (GTK_WIDGET (login_window));
335 }
336
337 void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
338 G_MODULE_EXPORT
339 void
340 shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter)
341 {
342     GtkWidget *dialog;
343
344     gtk_widget_hide (GTK_WIDGET (login_window));
345
346     dialog = gtk_message_dialog_new (NULL,
347                                      GTK_DIALOG_MODAL,
348                                      GTK_MESSAGE_OTHER,
349                                      GTK_BUTTONS_NONE,
350                                      "%s", _("Are you sure you want to close all programs and shutdown the computer?"));
351     gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Return To Login"), FALSE, _("Shutdown"), TRUE, NULL);
352     gtk_widget_show_all (dialog);
353     center_window (GTK_WINDOW (dialog));
354
355     if (gtk_dialog_run (GTK_DIALOG (dialog)))
356         lightdm_shutdown (NULL);
357
358     gtk_widget_destroy (dialog);
359     gtk_widget_show (GTK_WIDGET (login_window));
360 }
361
362 static void
363 user_added_cb (LightDMUserList *user_list, LightDMUser *user)
364 {
365     GtkTreeModel *model;
366     GtkTreeIter iter;
367
368     model = gtk_tree_view_get_model (user_view);
369
370     gtk_list_store_append (GTK_LIST_STORE (model), &iter);
371     gtk_list_store_set (GTK_LIST_STORE (model), &iter,
372                         0, lightdm_user_get_name (user),
373                         1, lightdm_user_get_display_name (user),
374                         2, lightdm_user_get_logged_in (user) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
375                         /*3, pixbuf,*/
376                         -1);
377 }
378
379 static gboolean
380 get_user_iter (const gchar *username, GtkTreeIter *iter)
381 {
382     GtkTreeModel *model;
383
384     model = gtk_tree_view_get_model (user_view);
385   
386     if (!gtk_tree_model_get_iter_first (model, iter))
387         return FALSE;
388     do
389     {
390         gchar *name;
391         gboolean matched;
392
393         gtk_tree_model_get (model, iter, 0, &name, -1);
394         matched = g_strcmp0 (name, username) == 0;
395         g_free (name);
396         if (matched)
397             return TRUE;
398     } while (gtk_tree_model_iter_next (model, iter));
399
400     return FALSE;
401 }
402
403 static void
404 user_changed_cb (LightDMUserList *user_list, LightDMUser *user)
405 {
406     GtkTreeModel *model;
407     GtkTreeIter iter;
408
409     if (!get_user_iter (lightdm_user_get_name (user), &iter))
410         return;
411
412     model = gtk_tree_view_get_model (user_view);
413     gtk_list_store_set (GTK_LIST_STORE (model), &iter,
414                         0, lightdm_user_get_name (user),
415                         1, lightdm_user_get_display_name (user),
416                         2, lightdm_user_get_logged_in (user) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
417                         /*3, pixbuf,*/
418                         -1);
419 }
420
421 static void
422 user_removed_cb (LightDMUserList *user_list, LightDMUser *user)
423 {
424     GtkTreeModel *model;
425     GtkTreeIter iter;
426
427     if (!get_user_iter (lightdm_user_get_name (user), &iter))
428         return;
429
430     model = gtk_tree_view_get_model (user_view);  
431     gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
432 }
433
434 void a11y_font_cb (GtkWidget *widget);
435 G_MODULE_EXPORT
436 void
437 a11y_font_cb (GtkWidget *widget)
438 {
439     if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
440     {
441         gchar *font_name, **tokens;
442
443         g_object_get (gtk_settings_get_default (), "gtk-font-name", &font_name, NULL);
444         tokens = g_strsplit (font_name, " ", 2);
445         if (g_strv_length (tokens) == 2)
446         {
447             gint size = atoi (tokens[1]);
448             if (size > 0)
449             {
450                 g_free (font_name);
451                 font_name = g_strdup_printf ("%s %d", tokens[0], size + 10);
452             }
453         }
454         g_strfreev (tokens);
455
456         g_object_set (gtk_settings_get_default (), "gtk-font-name", font_name, NULL);
457     }
458     else
459         g_object_set (gtk_settings_get_default (), "gtk-font-name", default_font_name, NULL);
460 }
461
462 void a11y_contrast_cb (GtkWidget *widget);
463 G_MODULE_EXPORT
464 void
465 a11y_contrast_cb (GtkWidget *widget)
466 {
467     if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
468         g_object_set (gtk_settings_get_default (), "gtk-theme-name", "HighContrastInverse", NULL);
469     else
470         g_object_set (gtk_settings_get_default (), "gtk-theme-name", default_theme_name, NULL);
471 }
472
473 static void
474 sigterm_cb (int signum)
475 {
476     exit (0);
477 }
478
479 static void
480 load_user_list ()
481 {
482     const GList *items, *item;
483     GtkTreeModel *model;
484     GtkTreeIter iter;
485
486     g_signal_connect (lightdm_user_list_get_instance (), "user-added", G_CALLBACK (user_added_cb), NULL);
487     g_signal_connect (lightdm_user_list_get_instance (), "user-changed", G_CALLBACK (user_changed_cb), NULL);
488     g_signal_connect (lightdm_user_list_get_instance (), "user-removed", G_CALLBACK (user_removed_cb), NULL);
489
490     model = gtk_tree_view_get_model (user_view);
491     items = lightdm_user_list_get_users (lightdm_user_list_get_instance ());
492     for (item = items; item; item = item->next)
493     {
494         LightDMUser *user = item->data;
495         const gchar *image;
496         GdkPixbuf *pixbuf = NULL;
497
498         image = lightdm_user_get_image (user);
499         if (image)
500             pixbuf = gdk_pixbuf_new_from_file_at_scale (image, 64, 64, TRUE, NULL);
501         if (!pixbuf)
502             pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
503                                                "stock_person",
504                                                64,
505                                                GTK_ICON_LOOKUP_USE_BUILTIN,
506                                                NULL);
507         /*if (!pixbuf)
508         {
509             pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 64, 64);
510             memset (gdk_pixbuf_get_pixels (pixbuf), 0, gdk_pixbuf_get_height (pixbuf) * gdk_pixbuf_get_rowstride (pixbuf) * gdk_pixbuf_get_n_channels (pixbuf));
511         }*/
512
513         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
514         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
515                             0, lightdm_user_get_name (user),
516                             1, lightdm_user_get_display_name (user),
517                             2, lightdm_user_get_logged_in (user) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
518                             3, pixbuf,
519                             -1);
520
521         if (lightdm_greeter_get_select_user_hint (greeter) &&
522             strcmp (lightdm_greeter_get_select_user_hint (greeter), lightdm_user_get_name (user)) == 0)
523             gtk_tree_selection_select_iter (gtk_tree_view_get_selection (user_view), &iter);
524     }
525     if (lightdm_greeter_get_has_guest_account_hint (greeter))
526     {
527         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
528         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
529                             0, "*guest",
530                             1, "Guest Account",
531                             2, PANGO_WEIGHT_NORMAL,
532                             3, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
533                             -1);
534         if (lightdm_greeter_get_select_guest_hint (greeter))
535             gtk_tree_selection_select_iter (gtk_tree_view_get_selection (user_view), &iter);
536     }
537
538     gtk_list_store_append (GTK_LIST_STORE (model), &iter);
539     gtk_list_store_set (GTK_LIST_STORE (model), &iter,
540                         0, NULL,
541                         1, "Other...",
542                         2, PANGO_WEIGHT_NORMAL,
543                         3, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
544                         -1);
545 }
546
547 static cairo_surface_t *
548 create_root_surface (GdkScreen *screen)
549 {
550     gint number, width, height;
551     Display *display;
552     Pixmap pixmap;
553     cairo_surface_t *surface;
554
555     number = gdk_screen_get_number (screen);
556     width = gdk_screen_get_width (screen);
557     height = gdk_screen_get_height (screen);
558
559     /* Open a new connection so with Retain Permanent so the pixmap remains when the greeter quits */
560     gdk_flush ();
561     display = XOpenDisplay (gdk_display_get_name (gdk_screen_get_display (screen)));
562     if (!display)
563     {
564         g_warning ("Failed to create root pixmap");
565         return NULL;
566     }
567     XSetCloseDownMode (display, RetainPermanent);
568     pixmap = XCreatePixmap (display, RootWindow (display, number), width, height, DefaultDepth (display, number));
569     XCloseDisplay (display);
570
571     /* Convert into a Cairo surface */
572     surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen),
573                                          pixmap,
574                                          GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen)),
575                                          width, height);
576
577     /* Use this pixmap for the background */
578     XSetWindowBackgroundPixmap (GDK_SCREEN_XDISPLAY (screen),
579                                 RootWindow (GDK_SCREEN_XDISPLAY (screen), number),
580                                 cairo_xlib_surface_get_drawable (surface));
581
582
583     return surface;  
584 }
585
586 int
587 main(int argc, char **argv)
588 {
589     GKeyFile *config;
590     GdkRectangle monitor_geometry;
591     GtkBuilder *builder;
592     GtkTreeModel *model;
593     const GList *items, *item;
594     GtkTreeIter iter;
595     GtkCellRenderer *renderer;
596     gchar *value;
597     GdkPixbuf *background_pixbuf = NULL;
598     GdkColor background_color;
599     gint i;
600     GError *error = NULL;
601
602     /* Disable global menus */
603     g_unsetenv ("UBUNTU_MENUPROXY");
604
605     signal (SIGTERM, sigterm_cb);
606
607     config = g_key_file_new ();
608     if (!g_key_file_load_from_file (config, CONFIG_FILE, G_KEY_FILE_NONE, &error) &&
609         !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
610         g_warning ("Failed to load configuration from %s: %s\n", CONFIG_FILE, error->message);
611     g_clear_error (&error);
612
613     gtk_init (&argc, &argv);
614
615     greeter = lightdm_greeter_new ();
616     g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);  
617     g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);
618     g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
619     g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (autologin_timer_expired_cb), NULL);
620     if (!lightdm_greeter_connect_sync (greeter, NULL))
621         return EXIT_FAILURE;
622
623     /* Set default cursor */
624     gdk_window_set_cursor (gdk_get_default_root_window (), gdk_cursor_new (GDK_LEFT_PTR));
625
626     /* Load background */
627     value = g_key_file_get_value (config, "greeter", "background", NULL);
628     if (!value)
629         value = g_strdup ("#000000");
630     if (!gdk_color_parse (value, &background_color))
631     {
632         gchar *path;
633         GError *error = NULL;
634
635         if (g_path_is_absolute (value))
636             path = g_strdup (value);
637         else
638             path = g_build_filename (GREETER_DATA_DIR, value, NULL);
639
640         g_debug ("Loading background %s", path);
641         background_pixbuf = gdk_pixbuf_new_from_file (path, &error);
642         if (!background_pixbuf)
643            g_warning ("Failed to load background: %s", error->message);
644         g_clear_error (&error);
645         g_free (path);
646     }
647     else
648         g_debug ("Using background color %s", value);
649     g_free (value);
650
651     /* Set the background */
652     for (i = 0; i < gdk_display_get_n_screens (gdk_display_get_default ()); i++)
653     {
654         GdkScreen *screen;
655         cairo_surface_t *surface;
656         cairo_t *c;
657         int monitor;
658
659         screen = gdk_display_get_screen (gdk_display_get_default (), i);
660         surface = create_root_surface (screen);
661         c = cairo_create (surface);
662
663         for (monitor = 0; monitor < gdk_screen_get_n_monitors (screen); monitor++)
664         {
665             gdk_screen_get_monitor_geometry (screen, monitor, &monitor_geometry);
666
667             if (background_pixbuf)
668             {
669                 GdkPixbuf *pixbuf = gdk_pixbuf_scale_simple (background_pixbuf, monitor_geometry.width, monitor_geometry.height, GDK_INTERP_BILINEAR);
670                 gdk_cairo_set_source_pixbuf (c, pixbuf, monitor_geometry.x, monitor_geometry.y);
671                 g_object_unref (pixbuf);
672             }
673             else
674                 gdk_cairo_set_source_color (c, &background_color);
675             cairo_paint (c);
676         }
677
678         cairo_destroy (c);
679
680         /* Refresh background */
681         gdk_flush ();
682         XClearWindow (GDK_SCREEN_XDISPLAY (screen), RootWindow (GDK_SCREEN_XDISPLAY (screen), i));
683     }
684     if (background_pixbuf)
685         g_object_unref (background_pixbuf);
686
687     /* Set GTK+ settings */
688     value = g_key_file_get_value (config, "greeter", "theme-name", NULL);
689     if (value)
690     {
691         g_debug ("Using theme %s", value);
692         g_object_set (gtk_settings_get_default (), "gtk-theme-name", value, NULL);
693     }
694     g_free (value);
695     g_object_get (gtk_settings_get_default (), "gtk-theme-name", &default_theme_name, NULL);
696     g_debug ("Default theme is '%s'", default_theme_name);
697
698     value = g_key_file_get_value (config, "greeter", "font-name", NULL);
699     if (value)
700     {
701         g_debug ("Using font %s", value);
702         g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
703     }
704     g_object_get (gtk_settings_get_default (), "gtk-font-name", &default_font_name, NULL);  
705     value = g_key_file_get_value (config, "greeter", "xft-dpi", NULL);
706     if (value)
707         g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", (int) (1024 * atof (value)), NULL);
708     value = g_key_file_get_value (config, "greeter", "xft-antialias", NULL);
709     if (value)
710         g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", strcmp (value, "true") == 0, NULL);
711     g_free (value);
712     value = g_key_file_get_value (config, "greeter", "xft-hintstyle", NULL);
713     if (value)
714         g_object_set (gtk_settings_get_default (), "gtk-xft-hintstyle", value, NULL);
715     g_free (value);
716     value = g_key_file_get_value (config, "greeter", "xft-rgba", NULL);
717     if (value)
718         g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);
719     g_free (value);
720
721     /* Load out installed icons */
722     gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), GREETER_DATA_DIR);
723     gchar **path;
724     gtk_icon_theme_get_search_path (gtk_icon_theme_get_default (), &path, NULL);
725
726     builder = gtk_builder_new ();
727     if (!gtk_builder_add_from_file (builder, GREETER_DATA_DIR "/greeter.ui", &error))
728     {
729         g_warning ("Error loading UI: %s", error->message);
730         return EXIT_FAILURE;
731     }
732     g_clear_error (&error);
733
734     login_window = GTK_WINDOW (gtk_builder_get_object (builder, "login_window"));
735     login_box = GTK_WIDGET (gtk_builder_get_object (builder, "login_box"));
736     prompt_box = GTK_WIDGET (gtk_builder_get_object (builder, "prompt_box"));
737     prompt_label = GTK_LABEL (gtk_builder_get_object (builder, "prompt_label"));
738     prompt_entry = GTK_ENTRY (gtk_builder_get_object (builder, "prompt_entry"));
739     message_label = GTK_LABEL (gtk_builder_get_object (builder, "message_label"));
740     session_combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, "session_combobox"));
741     panel_window = GTK_WINDOW (gtk_builder_get_object (builder, "panel_window"));
742
743     gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "hostname_label")), lightdm_get_hostname ());
744
745     if (!lightdm_get_can_suspend ())
746         gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "suspend_menuitem")));
747     if (!lightdm_get_can_hibernate ())
748         gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "hibernate_menuitem")));
749     if (!lightdm_get_can_restart ())
750         gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "restart_menuitem")));
751     if (!lightdm_get_can_shutdown ())
752         gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "shutdown_menuitem")));
753
754     user_view = GTK_TREE_VIEW (gtk_builder_get_object (builder, "user_treeview"));
755     gtk_tree_view_insert_column_with_attributes (user_view, 0, "Face", gtk_cell_renderer_pixbuf_new(), "pixbuf", 3, NULL);
756     gtk_tree_view_insert_column_with_attributes (user_view, 1, "Name", gtk_cell_renderer_text_new(), "text", 1, "weight", 2, NULL);
757
758     if (lightdm_greeter_get_hide_users_hint (greeter))
759         start_authentication (NULL);
760     else
761     {
762         load_user_list ();
763         gtk_widget_show (GTK_WIDGET (user_view));
764     }
765
766     renderer = gtk_cell_renderer_text_new();
767     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (session_combo), renderer, TRUE);
768     gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (session_combo), renderer, "text", 0);
769     model = gtk_combo_box_get_model (session_combo);
770     items = lightdm_get_sessions ();
771     for (item = items; item; item = item->next)
772     {
773         LightDMSession *session = item->data;
774
775         gtk_widget_show (GTK_WIDGET (session_combo));
776         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
777         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
778                             0, lightdm_session_get_name (session),
779                             1, lightdm_session_get_key (session),
780                             -1);
781     }
782     set_session (NULL);
783
784     gtk_builder_connect_signals(builder, greeter);
785
786     gtk_widget_show (GTK_WIDGET (login_window));
787     center_window (login_window);
788
789     gtk_widget_show (GTK_WIDGET (panel_window));
790     GtkAllocation allocation;
791     gtk_widget_get_allocation (GTK_WIDGET (panel_window), &allocation);
792     gdk_screen_get_monitor_geometry (gdk_screen_get_default (), gdk_screen_get_primary_monitor (gdk_screen_get_default ()), &monitor_geometry);
793     gtk_window_resize (panel_window, monitor_geometry.width, allocation.height);
794     gtk_window_move (panel_window, monitor_geometry.x, monitor_geometry.y);
795
796     gtk_window_present (login_window);
797
798     gtk_main ();
799
800     return EXIT_SUCCESS;
801 }