]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - greeters/gtk/lightdm-example-gtk-greeter.c
e11e6f2cf8e81072f845b4a0901b0b333e58ad0f
[sojka/lightdm.git] / greeters / gtk / lightdm-example-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.h>
16 #include <gdk-pixbuf/gdk-pixbuf.h>
17 #include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
18
19 #include "lightdm/greeter.h"
20
21 static LdmGreeter *greeter;
22 static GtkWidget *window, *message_label, *user_view;
23 static GdkPixbuf *background_pixbuf;
24 static GtkWidget *prompt_box, *prompt_label, *prompt_entry, *session_combo;
25 static gchar *theme_name;
26
27 static gchar *
28 get_session ()
29 {
30     GtkTreeIter iter;
31     gchar *session;
32
33     if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (session_combo), &iter))
34         return g_strdup (ldm_greeter_get_default_session (greeter));
35
36     gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (session_combo)), &iter, 1, &session, -1);
37
38     return session;
39 }
40
41 static void
42 set_session (const gchar *session)
43 {
44     GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (session_combo));
45     GtkTreeIter iter;
46
47     if (!gtk_tree_model_get_iter_first (model, &iter))
48         return;
49   
50     do
51     {
52         gchar *s;
53         gboolean matched;
54         gtk_tree_model_get (model, &iter, 1, &s, -1);
55         matched = strcmp (s, session) == 0;
56         g_free (s);
57         if (matched)
58         {
59             gtk_combo_box_set_active_iter (GTK_COMBO_BOX (session_combo), &iter);
60             return;
61         }
62     } while (gtk_tree_model_iter_next (model, &iter));
63 }
64
65 static void
66 start_authentication (const gchar *username)
67 {
68     gchar *language, *layout, *session;
69
70     gtk_widget_hide (message_label);
71     gtk_label_set_text (GTK_LABEL (message_label), "");
72
73     if (strcmp (username, "*other") == 0)
74     {
75         ldm_greeter_login (greeter, NULL);
76     }
77     else if (strcmp (username, "*guest") == 0)
78     {
79         ldm_greeter_login_as_guest (greeter);
80     }
81     else
82     {
83         if (ldm_greeter_get_user_defaults (greeter, username, &language, &layout, &session))
84         {
85             set_session (session);
86             g_free (language);
87             g_free (layout);
88             g_free (session);
89         }
90
91         ldm_greeter_login (greeter, username);
92     }
93 }
94
95 void user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column);
96 G_MODULE_EXPORT
97 void
98 user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column)
99 {
100     GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));  
101     GtkTreeIter iter;
102     gchar *user;
103
104     gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
105     gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
106     start_authentication (user);
107     g_free (user);
108 }
109
110 static gboolean
111 idle_select_cb ()
112 {
113     GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
114     GtkTreeIter iter;
115     gchar *user;
116
117     if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (user_view)),
118                                          NULL, &iter))
119     {
120         gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
121         start_authentication (user);
122         g_free (user);
123     }
124
125     return FALSE;
126 }
127
128 gboolean user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event);
129 G_MODULE_EXPORT
130 gboolean
131 user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event)
132 {
133     /* Do it in the idle loop so the selection is done first */
134     g_idle_add (idle_select_cb, NULL);
135     return FALSE;
136 }
137
138 void login_cb (GtkWidget *widget);
139 G_MODULE_EXPORT
140 void
141 login_cb (GtkWidget *widget)
142 {
143     gtk_widget_set_sensitive (prompt_entry, FALSE);
144     if (!ldm_greeter_get_in_authentication (greeter))
145         start_authentication (gtk_entry_get_text (GTK_ENTRY (prompt_entry)));
146     else
147         ldm_greeter_provide_secret (greeter, gtk_entry_get_text (GTK_ENTRY (prompt_entry)));
148     gtk_entry_set_text (GTK_ENTRY (prompt_entry), "");
149 }
150
151 void cancel_cb (GtkWidget *widget);
152 G_MODULE_EXPORT
153 void
154 cancel_cb (GtkWidget *widget)
155 {
156     ldm_greeter_cancel_authentication (greeter);
157 }
158
159 static void
160 show_prompt_cb (LdmGreeter *greeter, const gchar *text)
161 {
162     gtk_label_set_text (GTK_LABEL (prompt_label), text);
163     gtk_widget_set_sensitive (prompt_entry, TRUE);
164     gtk_entry_set_text (GTK_ENTRY (prompt_entry), "");
165     gtk_entry_set_visibility (GTK_ENTRY (prompt_entry), FALSE);
166     gtk_widget_show (prompt_box);
167     gtk_widget_grab_focus (prompt_entry);
168 }
169
170 static void
171 show_message_cb (LdmGreeter *greeter, const gchar *text)
172 {
173     gtk_label_set_text (GTK_LABEL (message_label), text);
174     gtk_widget_show (message_label);
175 }
176
177 static void
178 authentication_complete_cb (LdmGreeter *greeter)
179 {
180     gtk_widget_hide (prompt_box);
181     gtk_label_set_text (GTK_LABEL (prompt_label), "");
182     gtk_entry_set_text (GTK_ENTRY (prompt_entry), "");
183
184     gtk_widget_grab_focus (user_view);
185
186     if (ldm_greeter_get_is_authenticated (greeter))
187     {
188         gchar *session = get_session ();
189         ldm_greeter_start_session (greeter, session);
190         g_free (session);
191     }
192     else
193     {
194         gtk_label_set_text (GTK_LABEL (message_label), "Failed to authenticate");
195         gtk_widget_show (message_label);
196     }
197 }
198
199 static void
200 timed_login_cb (LdmGreeter *greeter, const gchar *username)
201 {
202     set_session (ldm_greeter_get_default_session (greeter));
203     ldm_greeter_login (greeter, ldm_greeter_get_timed_login_user (greeter));
204 }
205
206 void suspend_cb (GtkWidget *widget, LdmGreeter *greeter);
207 G_MODULE_EXPORT
208 void
209 suspend_cb (GtkWidget *widget, LdmGreeter *greeter)
210 {
211     ldm_greeter_suspend (greeter);
212 }
213
214 void hibernate_cb (GtkWidget *widget, LdmGreeter *greeter);
215 G_MODULE_EXPORT
216 void
217 hibernate_cb (GtkWidget *widget, LdmGreeter *greeter)
218 {
219     ldm_greeter_hibernate (greeter);
220 }
221
222 static void
223 center_window (GtkWindow *window)
224 {
225     GtkAllocation allocation;
226     GdkDisplay *display;
227     GdkScreen *screen;
228     gint screen_width, screen_height;
229
230     gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
231     display = gdk_display_get_default ();
232     screen = gdk_display_get_default_screen (display);
233     screen_width = gdk_screen_get_width (screen);
234     screen_height = gdk_screen_get_height (screen);
235     gtk_window_move (GTK_WINDOW (window),
236                      (screen_width - allocation.width) / 2,
237                      (screen_height - allocation.height) / 2);
238 }
239
240 void restart_cb (GtkWidget *widget, LdmGreeter *greeter);
241 G_MODULE_EXPORT
242 void
243 restart_cb (GtkWidget *widget, LdmGreeter *greeter)
244 {
245     GtkWidget *dialog;
246
247     dialog = gtk_message_dialog_new (NULL,
248                                      GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
249                                      GTK_MESSAGE_OTHER,
250                                      GTK_BUTTONS_NONE,
251                                      "%s", _("Are you sure you want to close all programs and restart the computer?"));
252     gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), gtk_image_new_from_icon_name ("system-restart", GTK_ICON_SIZE_DIALOG));
253     gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), FALSE, _("Restart"), TRUE, NULL);
254     gtk_widget_show_all (dialog);
255     center_window (GTK_WINDOW (dialog));
256
257     if (gtk_dialog_run (GTK_DIALOG (dialog)))
258         ldm_greeter_restart (greeter);
259     gtk_widget_destroy (dialog);
260 }
261
262 void shutdown_cb (GtkWidget *widget, LdmGreeter *greeter);
263 G_MODULE_EXPORT
264 void
265 shutdown_cb (GtkWidget *widget, LdmGreeter *greeter)
266 {
267     GtkWidget *dialog;
268
269     dialog = gtk_message_dialog_new (NULL,
270                                      GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
271                                      GTK_MESSAGE_OTHER,
272                                      GTK_BUTTONS_NONE,
273                                      "%s", _("Are you sure you want to close all programs and shutdown the computer?"));
274     gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_DIALOG));
275     gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), FALSE, _("Shutdown"), TRUE, NULL);
276     gtk_widget_show_all (dialog);
277     center_window (GTK_WINDOW (dialog));
278
279     if (gtk_dialog_run (GTK_DIALOG (dialog)))
280         ldm_greeter_shutdown (greeter);
281     gtk_widget_destroy (dialog);
282 }
283
284 static gboolean
285 fade_timer_cb (gpointer data)
286 {
287     gdouble opacity;
288
289     opacity = gtk_window_get_opacity (GTK_WINDOW (window));
290     opacity -= 0.1;
291     if (opacity <= 0)
292     {
293         gtk_main_quit ();
294         return FALSE;
295     }
296     gtk_window_set_opacity (GTK_WINDOW (window), opacity);
297
298     return TRUE;
299 }
300
301 static void
302 user_added_cb (LdmGreeter *greeter, LdmUser *user)
303 {
304     GtkTreeModel *model;
305     GtkTreeIter iter;
306
307     model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
308
309     gtk_list_store_append (GTK_LIST_STORE (model), &iter);
310     gtk_list_store_set (GTK_LIST_STORE (model), &iter,
311                         0, ldm_user_get_name (user),
312                         1, ldm_user_get_display_name (user),
313                         /*2, pixbuf,*/
314                         -1);
315 }
316
317 static gboolean
318 get_user_iter (const gchar *username, GtkTreeIter *iter)
319 {
320     GtkTreeModel *model;
321
322     model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
323   
324     if (!gtk_tree_model_get_iter_first (model, iter))
325         return FALSE;
326     do
327     {
328         gchar *name;
329         gboolean matched;
330
331         gtk_tree_model_get (model, iter, 0, &name, -1);
332         matched = strcmp (name, username) == 0;
333         g_free (name);
334         if (matched)
335             return TRUE;
336     } while (gtk_tree_model_iter_next (model, iter));
337
338     return FALSE;
339 }
340
341 static void
342 user_changed_cb (LdmGreeter *greeter, LdmUser *user)
343 {
344     GtkTreeModel *model;
345     GtkTreeIter iter;
346
347     if (!get_user_iter (ldm_user_get_name (user), &iter))
348         return;
349
350     model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
351     gtk_list_store_set (GTK_LIST_STORE (model), &iter,
352                         0, ldm_user_get_name (user),
353                         1, ldm_user_get_display_name (user),
354                         /*2, pixbuf,*/
355                         -1);
356 }
357
358 static void
359 user_removed_cb (LdmGreeter *greeter, LdmUser *user)
360 {
361     GtkTreeModel *model;
362     GtkTreeIter iter;
363
364     if (!get_user_iter (ldm_user_get_name (user), &iter))
365         return;
366
367     model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));  
368     gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
369 }
370
371 static void
372 quit_cb (LdmGreeter *greeter, const gchar *username)
373 {
374     /* Fade out the greeter */
375     g_timeout_add (40, (GSourceFunc) fade_timer_cb, NULL);
376 }
377
378 void a11y_font_cb (GtkWidget *widget);
379 G_MODULE_EXPORT
380 void
381 a11y_font_cb (GtkWidget *widget)
382 {
383     if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
384         g_object_set (gtk_settings_get_default (), "gtk-font-name", "Ubuntu 20", NULL);
385     else
386         g_object_set (gtk_settings_get_default (), "gtk-font-name", "Ubuntu 10", NULL);
387 }
388
389 void a11y_contrast_cb (GtkWidget *widget);
390 G_MODULE_EXPORT
391 void
392 a11y_contrast_cb (GtkWidget *widget)
393 {
394     if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
395         g_object_set (gtk_settings_get_default (), "gtk-theme-name", "HighContrastInverse", NULL);
396     else
397         g_object_set (gtk_settings_get_default (), "gtk-theme-name", theme_name, NULL);
398 }
399
400 static void
401 sigterm_cb (int signum)
402 {
403     exit (0);
404 }
405
406 gboolean draw_background_cb (GtkWidget *widget, GdkEventExpose *event);
407 G_MODULE_EXPORT
408 gboolean
409 draw_background_cb (GtkWidget *widget, GdkEventExpose *event)
410 {
411     cairo_t *context;
412     GtkAllocation allocation;
413
414     context = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
415
416     gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
417     gdk_cairo_set_source_pixbuf (context, background_pixbuf, 0.0, 0.0);
418     gdk_cairo_region (context, event->region);
419     cairo_fill (context);
420
421     cairo_destroy (context);
422
423     return FALSE;
424 }
425
426 static void
427 connect_cb (LdmGreeter *greeter)
428 {
429     GdkWindow *root;
430     GdkDisplay *display;
431     GdkScreen *screen;
432     gint screen_width, screen_height;
433     GtkBuilder *builder;
434     const GList *items, *item;
435     GtkTreeModel *model;
436     GtkTreeIter iter;
437     GtkCellRenderer *renderer;
438     gchar *theme_dir, *rc_file, *background_image;
439     GError *error = NULL;
440
441     display = gdk_display_get_default ();
442     screen = gdk_display_get_default_screen (display);
443     screen_width = gdk_screen_get_width (screen);
444     screen_height = gdk_screen_get_height (screen);
445
446     g_object_get (gtk_settings_get_default (), "gtk-theme-name", &theme_name, NULL);
447     theme_dir = g_path_get_dirname (ldm_greeter_get_theme (greeter));
448     rc_file = ldm_greeter_get_string_property (greeter, "gtkrc");
449     if (rc_file)
450     {
451         gchar *path = g_build_filename (theme_dir, rc_file, NULL);
452         g_free (rc_file);
453         gtk_rc_add_default_file (path);
454         g_free (path);
455     }
456
457     builder = gtk_builder_new ();
458     if (!gtk_builder_add_from_file (builder, UI_DIR "/greeter.ui", &error))
459     {
460         g_warning ("Error loading UI: %s", error->message);
461         return;
462     }
463     g_clear_error (&error);
464     window = GTK_WIDGET (gtk_builder_get_object (builder, "greeter_window"));
465     prompt_box = GTK_WIDGET (gtk_builder_get_object (builder, "prompt_box"));
466     prompt_label = GTK_WIDGET (gtk_builder_get_object (builder, "prompt_label"));
467     prompt_entry = GTK_WIDGET (gtk_builder_get_object (builder, "prompt_entry"));
468     message_label = GTK_WIDGET (gtk_builder_get_object (builder, "message_label"));
469     session_combo = GTK_WIDGET (gtk_builder_get_object (builder, "session_combobox"));
470   
471     gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "hostname_label")), ldm_greeter_get_hostname (greeter));
472
473     background_image = ldm_greeter_get_string_property (greeter, "background-image");
474     if (background_image)
475     {
476         gchar *path;
477         GdkPixbuf *pixbuf;
478         GError *error = NULL;
479
480         path = g_build_filename (theme_dir, background_image, NULL);
481         g_free (background_image);
482         pixbuf = gdk_pixbuf_new_from_file (path, &error);
483         if (!pixbuf)
484            g_warning ("Failed to load background: %s", error->message);
485         g_clear_error (&error);
486         g_free (path);
487
488         if (pixbuf)
489         {
490             background_pixbuf = gdk_pixbuf_scale_simple (pixbuf, screen_width, screen_height, GDK_INTERP_BILINEAR);
491             g_object_unref (pixbuf);
492         }
493     }
494
495     /* Set the background */
496     root = gdk_get_default_root_window ();
497     gdk_window_set_cursor (root, gdk_cursor_new (GDK_LEFT_PTR));
498     if (background_pixbuf)
499     {
500         GdkPixmap *pixmap;
501
502         gdk_pixbuf_render_pixmap_and_mask_for_colormap (background_pixbuf, gdk_window_get_colormap (root), &pixmap, NULL, 0);
503         gdk_window_set_back_pixmap (root, pixmap, FALSE);
504     }
505
506     if (!ldm_greeter_get_can_suspend (greeter))
507         gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "suspend_menuitem")));
508     if (!ldm_greeter_get_can_hibernate (greeter))
509         gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "hibernate_menuitem")));
510     if (!ldm_greeter_get_can_restart (greeter))
511         gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "restart_menuitem")));
512     if (!ldm_greeter_get_can_shutdown (greeter))
513         gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "shutdown_menuitem")));
514
515     user_view = GTK_WIDGET (gtk_builder_get_object (builder, "user_treeview"));
516     gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (user_view), 0, "Face", gtk_cell_renderer_pixbuf_new(), "pixbuf", 2, NULL);
517     gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (user_view), 1, "Name", gtk_cell_renderer_text_new(), "text", 1, NULL);
518
519     model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
520     items = ldm_greeter_get_users (greeter);
521     for (item = items; item; item = item->next)
522     {
523         LdmUser *user = item->data;
524         const gchar *image;
525         GdkPixbuf *pixbuf = NULL;
526
527         image = ldm_user_get_image (user);
528         if (image)
529         {
530             gchar *path;
531
532             path = g_filename_from_uri (image, NULL, NULL);
533             if (path)
534                 pixbuf = gdk_pixbuf_new_from_file_at_scale (path, 64, 64, TRUE, NULL);
535             g_free (path);
536         }
537         if (!pixbuf)
538             pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
539                                                "stock_person",
540                                                64,
541                                                GTK_ICON_LOOKUP_USE_BUILTIN,
542                                                NULL);
543         /*if (!pixbuf)
544         {
545             pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 64, 64);
546             memset (gdk_pixbuf_get_pixels (pixbuf), 0, gdk_pixbuf_get_height (pixbuf) * gdk_pixbuf_get_rowstride (pixbuf) * gdk_pixbuf_get_n_channels (pixbuf));
547         }*/
548
549         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
550         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
551                             0, ldm_user_get_name (user),
552                             1, ldm_user_get_display_name (user),
553                             2, pixbuf,
554                             -1);
555     }
556     if (ldm_greeter_get_has_guest_session (greeter))
557     {
558         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
559         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
560                             0, "*guest",
561                             1, "Guest Account",
562                             2, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
563                             -1);
564     }
565
566     gtk_list_store_append (GTK_LIST_STORE (model), &iter);
567     gtk_list_store_set (GTK_LIST_STORE (model), &iter,
568                         0, "*other",
569                         1, "Other...",
570                         2, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
571                         -1);
572
573     renderer = gtk_cell_renderer_text_new();
574     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (session_combo), renderer, TRUE);
575     gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (session_combo), renderer, "text", 0);
576     model = gtk_combo_box_get_model (GTK_COMBO_BOX (session_combo));
577     items = ldm_greeter_get_sessions (greeter);
578     for (item = items; item; item = item->next)
579     {
580         LdmSession *session = item->data;
581
582         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
583         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
584                             0, ldm_session_get_name (session),
585                             1, ldm_session_get_key (session),
586                             -1);
587     }
588     set_session (ldm_greeter_get_default_session (greeter));
589
590     gtk_window_set_default_size (GTK_WINDOW (window), screen_width, screen_height);
591     gtk_builder_connect_signals(builder, greeter);
592     gtk_widget_show (window);
593
594     gtk_widget_grab_focus (user_view);
595 }
596
597 int
598 main(int argc, char **argv)
599 {
600     /* Disable global menus */
601     unsetenv ("UBUNTU_MENUPROXY");
602
603     signal (SIGTERM, sigterm_cb);
604   
605     g_type_init ();
606
607     greeter = ldm_greeter_new ();
608     g_signal_connect (G_OBJECT (greeter), "connected", G_CALLBACK (connect_cb), NULL);    
609     g_signal_connect (G_OBJECT (greeter), "show-prompt", G_CALLBACK (show_prompt_cb), NULL);  
610     g_signal_connect (G_OBJECT (greeter), "show-message", G_CALLBACK (show_message_cb), NULL);
611     g_signal_connect (G_OBJECT (greeter), "show-error", G_CALLBACK (show_message_cb), NULL);
612     g_signal_connect (G_OBJECT (greeter), "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
613     g_signal_connect (G_OBJECT (greeter), "timed-login", G_CALLBACK (timed_login_cb), NULL);
614     g_signal_connect (G_OBJECT (greeter), "user-added", G_CALLBACK (user_added_cb), NULL);
615     g_signal_connect (G_OBJECT (greeter), "user-changed", G_CALLBACK (user_changed_cb), NULL);
616     g_signal_connect (G_OBJECT (greeter), "user-removed", G_CALLBACK (user_removed_cb), NULL);
617     g_signal_connect (G_OBJECT (greeter), "quit", G_CALLBACK (quit_cb), NULL);
618     ldm_greeter_connect_to_server (greeter);
619
620     gtk_init (&argc, &argv);
621
622     gtk_main ();
623
624     return 0;
625 }