]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - greeters/gtk/lightdm-gtk-greeter.c
Fix bugs with new login_with_defaults
[sojka/lightdm.git] / greeters / gtk / lightdm-gtk-greeter.c
1 /*
2  * Copyright (C) 2010 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 "greeter.h"
20
21 static LdmGreeter *greeter;
22 static GtkTreeModel *user_model;
23 static GtkWidget *window, *vbox, *login_vbox, *message_label, *user_view;
24 static GdkPixmap *background_pixmap;
25 static GtkWidget *username_entry, *password_entry;
26 static gchar *theme_name;
27 static GSList *session_radio_list = NULL, *language_radio_list = NULL, *layout_radio_list = NULL;
28
29 static gchar *
30 get_language ()
31 {
32     GSList *iter;
33
34     for (iter = language_radio_list; iter; iter = iter->next)
35     {
36         GtkCheckMenuItem *item = iter->data;
37         if (gtk_check_menu_item_get_active (item))
38             return g_object_get_data (G_OBJECT (item), "language");
39     }
40
41     return NULL;
42 }
43
44 static void
45 set_language (const gchar *language)
46 {
47     GSList *iter;
48
49     for (iter = language_radio_list; iter; iter = iter->next)
50     {
51         GtkCheckMenuItem *item = iter->data;
52         if (strcmp (language, g_object_get_data (G_OBJECT (item), "language")) == 0)
53             gtk_check_menu_item_set_active (item, TRUE);
54     }
55 }
56
57 #if 0
58 static gchar *
59 get_layout ()
60 {
61     GSList *iter;
62
63     for (iter = layout_radio_list; iter; iter = iter->next)
64     {
65         GtkCheckMenuItem *item = iter->data;
66         if (gtk_check_menu_item_get_active (item))
67             return g_object_get_data (G_OBJECT (item), "layout");
68     }
69
70     return NULL;
71 }
72 #endif
73
74 static void
75 set_layout (const gchar *layout)
76 {
77     GSList *iter;
78
79     for (iter = layout_radio_list; iter; iter = iter->next)
80     {
81         GtkCheckMenuItem *item = iter->data;
82         if (strcmp (layout, g_object_get_data (G_OBJECT (item), "layout")) == 0)
83             gtk_check_menu_item_set_active (item, TRUE);
84     }
85 }
86
87 static gchar *
88 get_session ()
89 {
90     GSList *iter;
91
92     for (iter = session_radio_list; iter; iter = iter->next)
93     {
94         GtkCheckMenuItem *item = iter->data;
95         if (gtk_check_menu_item_get_active (item))
96             return g_object_get_data (G_OBJECT (item), "key");
97     }
98
99     return NULL;
100 }
101
102 static void
103 set_session (const gchar *session)
104 {
105     GSList *iter;
106
107     for (iter = session_radio_list; iter; iter = iter->next)
108     {
109         GtkCheckMenuItem *item = iter->data;
110         if (strcmp (session, g_object_get_data (G_OBJECT (item), "key")) == 0)
111             gtk_check_menu_item_set_active (item, TRUE);
112     }
113 }
114
115 static void
116 start_authentication (const gchar *username)
117 {
118     GtkTreeIter iter;
119     gchar *language, *layout, *session;
120   
121     if (ldm_greeter_get_user_defaults (greeter, username, &language, &layout, &session))
122     {
123         set_language (language);
124         set_session (session);
125         set_layout (layout);
126         g_free (language);
127         g_free (layout);
128         g_free (session);
129     }
130
131     if (user_model && gtk_tree_model_get_iter_first (GTK_TREE_MODEL (user_model), &iter))
132     {
133         do
134         {
135             gchar *user;
136             gtk_tree_model_get (GTK_TREE_MODEL (user_model), &iter, 0, &user, -1);
137             gtk_list_store_set (GTK_LIST_STORE (user_model), &iter, 3, strcmp (user, username) == 0, -1);
138             g_free (user);
139         } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (user_model), &iter));
140     }
141     if (username_entry)
142         gtk_widget_set_sensitive (username_entry, FALSE);
143
144     ldm_greeter_start_authentication (greeter, username);
145 }
146
147 static void
148 user_view_activate_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column)
149 {
150     GtkTreeIter iter;
151     gchar *user;
152
153     gtk_tree_model_get_iter (GTK_TREE_MODEL (user_model), &iter, path);
154     gtk_tree_model_get (GTK_TREE_MODEL (user_model), &iter, 0, &user, -1);
155     start_authentication (user);
156     g_free (user);
157 }
158
159 static gboolean
160 idle_select_cb ()
161 {
162     GtkTreeIter iter;
163     gchar *user;
164
165     if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (user_view)),
166                                          NULL, &iter))
167     {
168         gtk_tree_model_get (GTK_TREE_MODEL (user_model), &iter, 0, &user, -1);
169         start_authentication (user);
170         g_free (user);
171     }
172
173     return FALSE;
174 }
175
176 static gboolean
177 user_view_click_cb (GtkWidget *widget, GdkEventButton *event)
178 {
179     /* Do it in the idle loop so the selection is done first */
180     g_idle_add (idle_select_cb, NULL);
181     return FALSE;
182 }
183
184 static void
185 username_activate_cb (GtkWidget *widget)
186 {
187     start_authentication (gtk_entry_get_text (GTK_ENTRY (username_entry)));
188 }
189
190 static void
191 password_activate_cb (GtkWidget *widget)
192 {
193     gtk_widget_set_sensitive (widget, FALSE);
194     ldm_greeter_provide_secret (greeter, gtk_entry_get_text (GTK_ENTRY (widget)));
195 }
196
197 static void
198 show_prompt_cb (LdmGreeter *greeter, const gchar *text)
199 {
200     gtk_widget_show (password_entry);
201     gtk_widget_set_sensitive (password_entry, TRUE);
202     gtk_widget_grab_focus (password_entry);
203 }
204
205 static void
206 show_message_cb (LdmGreeter *greeter, const gchar *text)
207 {
208     gtk_label_set_text (GTK_LABEL (message_label), text);
209     gtk_widget_show (message_label);
210 }
211
212 static void
213 authentication_complete_cb (LdmGreeter *greeter)
214 {
215     GtkTreeIter iter;
216
217     gtk_widget_hide (password_entry);
218     gtk_entry_set_text (GTK_ENTRY (password_entry), "");
219
220     /* Clear row shading */
221     if (user_model && gtk_tree_model_get_iter_first (GTK_TREE_MODEL (user_model), &iter))
222     {
223         do
224         {
225             gtk_list_store_set (GTK_LIST_STORE (user_model), &iter, 3, TRUE, -1);
226         } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (user_model), &iter));
227     }
228     if (username_entry)
229     {
230         gtk_entry_set_text (GTK_ENTRY (username_entry), "");
231         gtk_widget_set_sensitive (username_entry, TRUE);
232     }
233
234     if (user_view)
235         gtk_widget_grab_focus (user_view);
236     else
237         gtk_widget_grab_focus (username_entry);
238   
239     if (ldm_greeter_get_is_authenticated (greeter))
240     {
241         ldm_greeter_login (greeter, ldm_greeter_get_authentication_user (greeter), get_session (), get_language ());
242     }
243     else
244     {
245         gtk_label_set_text (GTK_LABEL (message_label), "Failed to authenticate");
246         gtk_widget_show (message_label);
247     }
248 }
249
250 static void
251 timed_login_cb (LdmGreeter *greeter, const gchar *username)
252 {
253     ldm_greeter_login (greeter, ldm_greeter_get_timed_login_user (greeter), NULL, NULL);
254 }
255
256 static void
257 suspend_cb (GtkWidget *widget, LdmGreeter *greeter)
258 {
259     ldm_greeter_suspend (greeter);
260 }
261
262 static void
263 hibernate_cb (GtkWidget *widget, LdmGreeter *greeter)
264 {
265     ldm_greeter_hibernate (greeter);
266 }
267
268 static void
269 center_window (GtkWindow *window)
270 {
271     GtkAllocation allocation;
272     GdkDisplay *display;
273     GdkScreen *screen;
274     gint screen_width, screen_height;
275
276     gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
277     display = gdk_display_get_default ();
278     screen = gdk_display_get_default_screen (display);
279     screen_width = gdk_screen_get_width (screen);
280     screen_height = gdk_screen_get_height (screen);
281     gtk_window_move (GTK_WINDOW (window),
282                      (screen_width - allocation.width) / 2,
283                      (screen_height - allocation.height) / 2);
284 }
285
286 static void
287 restart_cb (GtkWidget *widget, LdmGreeter *greeter)
288 {
289     GtkWidget *dialog;
290
291     dialog = gtk_message_dialog_new (NULL,
292                                      GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
293                                      GTK_MESSAGE_OTHER,
294                                      GTK_BUTTONS_NONE,
295                                      "%s", _("Are you sure you want to close all programs and restart the computer?"));
296     gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), gtk_image_new_from_icon_name ("system-restart", GTK_ICON_SIZE_DIALOG));
297     gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), FALSE, _("Restart"), TRUE, NULL);
298     gtk_widget_show_all (dialog);
299     center_window (GTK_WINDOW (dialog));
300
301     if (gtk_dialog_run (GTK_DIALOG (dialog)))
302         ldm_greeter_restart (greeter);
303     gtk_widget_destroy (dialog);
304 }
305
306 static void
307 shutdown_cb (GtkWidget *widget, LdmGreeter *greeter)
308 {
309     GtkWidget *dialog;
310
311     dialog = gtk_message_dialog_new (NULL,
312                                      GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
313                                      GTK_MESSAGE_OTHER,
314                                      GTK_BUTTONS_NONE,
315                                      "%s", _("Are you sure you want to close all programs and shutdown the computer?"));
316     gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_DIALOG));
317     gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), FALSE, _("Shutdown"), TRUE, NULL);
318     gtk_widget_show_all (dialog);
319     center_window (GTK_WINDOW (dialog));
320
321     if (gtk_dialog_run (GTK_DIALOG (dialog)))
322         ldm_greeter_shutdown (greeter);
323     gtk_widget_destroy (dialog);
324 }
325
326 static gboolean
327 fade_timer_cb (gpointer data)
328 {
329     gdouble opacity;
330
331     opacity = gtk_window_get_opacity (GTK_WINDOW (window));
332     opacity -= 0.1;
333     if (opacity <= 0)
334     {
335         gtk_main_quit ();
336         return FALSE;
337     }
338     gtk_window_set_opacity (GTK_WINDOW (window), opacity);
339
340     return TRUE;
341 }
342
343 static void
344 quit_cb (LdmGreeter *greeter, const gchar *username)
345 {
346     /* Fade out the greeter */
347     g_timeout_add (40, (GSourceFunc) fade_timer_cb, NULL);
348 }
349
350 static void
351 layout_changed_cb (GtkWidget *widget)
352 {
353     if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
354         ldm_greeter_set_layout (greeter, g_object_get_data (G_OBJECT (widget), "layout"));
355 }
356
357 static void
358 a11y_font_cb (GtkWidget *widget)
359 {
360     if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
361         g_object_set (gtk_settings_get_default (), "gtk-font-name", "UbuntuBeta 20", NULL);
362     else
363         g_object_set (gtk_settings_get_default (), "gtk-font-name", "UbuntuBeta 10", NULL);
364 }
365
366 static void
367 a11y_contrast_cb (GtkWidget *widget)
368 {
369     if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
370         g_object_set (gtk_settings_get_default (), "gtk-theme-name", "HighContrastInverse", NULL);
371     else
372         g_object_set (gtk_settings_get_default (), "gtk-theme-name", theme_name, NULL);
373 }
374
375 static void
376 sigterm_cb (int signum)
377 {
378     exit (0);
379 }
380
381 static GtkWidget *
382 make_user_view (void)
383 {
384     GtkListStore *model;
385     GtkWidget *view;
386     GtkCellRenderer *renderer;
387     const GList *items, *item;
388     GtkTreeIter iter;
389
390     items = ldm_greeter_get_users (greeter);
391     if (!items)
392         return NULL;
393   
394     model = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN);
395     for (item = items; item; item = item->next)
396     {
397         LdmUser *user = item->data;
398         const gchar *image;
399         GdkPixbuf *pixbuf = NULL;
400
401         image = ldm_user_get_image (user);
402         if (image[0] != '\0')
403         {
404             gchar *path;
405
406             path = g_filename_from_uri (image, NULL, NULL);
407             if (path)
408                 pixbuf = gdk_pixbuf_new_from_file_at_scale (path, 64, 64, TRUE, NULL);
409             g_free (path);
410         }
411         if (!pixbuf)
412             pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
413                                                "stock_person",
414                                                64,
415                                                0,
416                                                NULL);
417
418         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
419         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
420                             0, ldm_user_get_name (user),
421                             1, ldm_user_get_display_name (user),
422                             2, pixbuf,
423                             3, TRUE,
424                             -1);
425     }
426
427     view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
428     gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
429     gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_NONE);
430
431     renderer = gtk_cell_renderer_pixbuf_new();
432     gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), 0, "Face", renderer, "pixbuf", 2, "sensitive", 3, NULL);
433
434     renderer = gtk_cell_renderer_text_new();
435     gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), 1, "Name", renderer, "text", 1, NULL);
436
437     g_signal_connect (view, "row-activated", G_CALLBACK (user_view_activate_cb), NULL);
438     g_signal_connect (view, "button-press-event", G_CALLBACK (user_view_click_cb), NULL);
439
440     if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
441         gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), &iter);
442
443     return view;
444 }
445
446 static gboolean
447 draw_background_cb (GtkWidget *widget, GdkEventExpose *event)
448 {
449     cairo_t *context;
450     GtkAllocation allocation;
451
452     context = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
453
454     gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
455     gdk_cairo_set_source_pixmap (context, background_pixmap, 0.0, 0.0);
456     cairo_rectangle (context, 0, 0, allocation.width, allocation.height);
457     cairo_fill (context);
458
459     cairo_destroy (context);
460
461     return FALSE;
462 }
463
464 static void
465 connect_cb (LdmGreeter *greeter)
466 {
467     gchar *theme_dir, *rc_file, *background_image;
468     GdkWindow *root;
469     const GList *items, *item;
470     GdkDisplay *display;
471     GdkScreen *screen;
472     gint screen_width, screen_height;
473     GtkWidget *login_align, *logo_image;
474     GtkWidget *option_menu, *power_menu;
475     GtkWidget *menu_bar, *menu, *menu_item;
476     gint n_power_items = 0;
477
478     theme_dir = g_path_get_dirname (ldm_greeter_get_theme (greeter));
479     rc_file = ldm_greeter_get_string_property (greeter, "gtkrc");
480     if (rc_file)
481     {
482         gchar *path = g_build_filename (theme_dir, rc_file, NULL);
483         g_free (rc_file);
484         gtk_rc_add_default_file (path);
485         g_free (path);
486     }
487
488     g_object_get (gtk_settings_get_default (), "gtk-theme-name", &theme_name, NULL);
489
490     display = gdk_display_get_default ();
491     screen = gdk_display_get_default_screen (display);
492     screen_width = gdk_screen_get_width (screen);
493     screen_height = gdk_screen_get_height (screen);
494
495     root = gdk_get_default_root_window ();
496     gdk_window_set_cursor (root, gdk_cursor_new (GDK_LEFT_PTR));
497
498     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
499     gtk_widget_set_app_paintable (window, TRUE);
500     g_signal_connect (G_OBJECT (window), "expose-event", G_CALLBACK (draw_background_cb), NULL);
501     gtk_window_set_default_size (GTK_WINDOW (window), screen_width, screen_height);
502     gtk_window_fullscreen (GTK_WINDOW (window));
503     gtk_widget_realize (window);
504
505     background_image = ldm_greeter_get_string_property (greeter, "background-image");
506     if (background_image)
507     {
508         gchar *path;
509         GdkPixbuf *pixbuf;
510         GError *error = NULL;
511
512         path = g_build_filename (theme_dir, background_image, NULL);
513         g_free (background_image);
514         pixbuf = gdk_pixbuf_new_from_file (path, &error);
515         if (!pixbuf)
516            g_warning ("Failed to load background: %s", error->message);
517         g_clear_error (&error);
518         g_free (path);
519
520         if (pixbuf)
521         {
522             GdkPixbuf *scaled;
523             GdkWindow *w;
524
525             scaled = gdk_pixbuf_scale_simple (pixbuf, screen_width, screen_height, GDK_INTERP_BILINEAR);
526             g_object_unref (pixbuf);
527
528             w = gtk_widget_get_window (GTK_WIDGET (window));
529
530             gdk_pixbuf_render_pixmap_and_mask_for_colormap (scaled, gdk_window_get_colormap (w), &background_pixmap, NULL, 0);
531             g_object_unref (scaled);
532         }
533     }
534
535     vbox = gtk_vbox_new (FALSE, 0);
536     gtk_container_add (GTK_CONTAINER (window), vbox);
537
538     login_align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
539     gtk_box_pack_start (GTK_BOX (vbox), login_align, TRUE, TRUE, 0);
540
541     GtkWidget *notebook;
542     notebook = gtk_notebook_new ();
543     gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
544     gtk_container_add (GTK_CONTAINER (login_align), notebook);
545
546     login_vbox = gtk_vbox_new (FALSE, 6);
547     gtk_container_set_border_width (GTK_CONTAINER (login_vbox), 12);
548     gtk_container_add (GTK_CONTAINER (notebook), login_vbox);
549
550     logo_image = gtk_image_new_from_icon_name ("computer", GTK_ICON_SIZE_DIALOG);
551     gtk_image_set_pixel_size (GTK_IMAGE (logo_image), 64);
552     gtk_box_pack_start (GTK_BOX (login_vbox), logo_image, FALSE, FALSE, 0);
553     gtk_box_pack_start (GTK_BOX (login_vbox), gtk_label_new (ldm_greeter_get_hostname (greeter)), FALSE, FALSE, 0);
554
555     message_label = gtk_label_new ("");
556     gtk_box_pack_start (GTK_BOX (login_vbox), message_label, FALSE, FALSE, 0);
557     gtk_widget_set_no_show_all (message_label, TRUE);
558
559     user_view = make_user_view ();
560     if (user_view)
561     {
562         username_entry = NULL;
563         user_model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
564         gtk_box_pack_start (GTK_BOX (login_vbox), user_view, FALSE, FALSE, 0);
565     }
566     else
567     {
568         username_entry = gtk_entry_new ();
569         gtk_box_pack_start (GTK_BOX (login_vbox), username_entry, FALSE, FALSE, 0);
570         g_signal_connect (username_entry, "activate", G_CALLBACK (username_activate_cb), NULL);
571         user_model = NULL;
572     }
573
574     password_entry = gtk_entry_new ();
575     gtk_entry_set_visibility (GTK_ENTRY (password_entry), FALSE);
576     gtk_widget_set_sensitive (password_entry, FALSE);
577     gtk_box_pack_start (GTK_BOX (login_vbox), password_entry, FALSE, FALSE, 0);
578     g_signal_connect (password_entry, "activate", G_CALLBACK (password_activate_cb), NULL);
579     gtk_widget_set_no_show_all (password_entry, TRUE);
580
581     menu_bar = gtk_menu_bar_new ();
582     gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, TRUE, 0);
583
584     menu_item = gtk_image_menu_item_new ();
585     gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), gtk_image_new_from_icon_name ("preferences-desktop-accessibility", GTK_ICON_SIZE_LARGE_TOOLBAR));
586     gtk_menu_item_set_label (GTK_MENU_ITEM (menu_item), ""); // NOTE: Needed to make the icon show as selected
587     gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menu_item), TRUE);
588     gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
589     menu = gtk_menu_new ();
590     gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
591
592     menu_item = gtk_check_menu_item_new_with_label (_("Large Font"));
593     g_signal_connect (menu_item, "toggled", G_CALLBACK (a11y_font_cb), NULL);
594     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
595
596     menu_item = gtk_check_menu_item_new_with_label (_("High Constrast"));
597     g_signal_connect (menu_item, "toggled", G_CALLBACK (a11y_contrast_cb), NULL);
598     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
599
600     menu_item = gtk_menu_item_new_with_label (_("Options"));
601     gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
602     option_menu = gtk_menu_new ();
603     gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), option_menu);
604
605     menu_item = gtk_menu_item_new_with_label (_("Language"));
606     gtk_menu_shell_append (GTK_MENU_SHELL (option_menu), menu_item);
607     menu = gtk_menu_new ();
608     gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
609
610     items = ldm_greeter_get_languages (greeter);
611     for (item = items; item; item = item->next)
612     {
613         LdmLanguage *language = item->data;
614         gchar *label;
615       
616         if (ldm_language_get_name (language)[0] == '\0')
617             label = g_strdup (ldm_language_get_code (language));
618         else
619             label = g_strdup_printf ("%s - %s", ldm_language_get_name (language), ldm_language_get_territory (language));
620
621         menu_item = gtk_radio_menu_item_new_with_label (language_radio_list, label);
622         language_radio_list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
623         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
624
625         if (ldm_language_matches (language, ldm_greeter_get_default_language (greeter)))
626             gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
627
628         g_object_set_data (G_OBJECT (menu_item), "language", g_strdup (ldm_language_get_code (language)));
629     }
630
631     menu_item = gtk_menu_item_new_with_label (_("Keyboard Layout"));
632     gtk_menu_shell_append (GTK_MENU_SHELL (option_menu), menu_item);
633     menu = gtk_menu_new ();
634     gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
635     items = ldm_greeter_get_layouts (greeter);
636     for (item = items; item; item = item->next)
637     {
638         LdmLayout *layout = item->data;
639
640         menu_item = gtk_radio_menu_item_new_with_label (layout_radio_list, ldm_layout_get_description (layout));
641         layout_radio_list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
642         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
643
644         if (g_str_equal (ldm_layout_get_name (layout), ldm_greeter_get_default_layout (greeter)))
645             gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
646
647         g_object_set_data (G_OBJECT (menu_item), "layout", g_strdup (ldm_layout_get_name (layout)));
648         g_signal_connect (menu_item, "toggled", G_CALLBACK (layout_changed_cb), NULL);
649     }
650
651     ldm_greeter_set_layout (greeter, ldm_greeter_get_default_layout (greeter));
652
653     menu_item = gtk_menu_item_new_with_label (_("Session"));
654     gtk_menu_shell_append (GTK_MENU_SHELL (option_menu), menu_item);
655     menu = gtk_menu_new ();
656     gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
657     items = ldm_greeter_get_sessions (greeter);
658     for (item = items; item; item = item->next)
659     {
660         LdmSession *session = item->data;
661
662         menu_item = gtk_radio_menu_item_new_with_label (session_radio_list, ldm_session_get_name (session));
663         session_radio_list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
664         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
665
666         if (g_str_equal (ldm_session_get_key (session), ldm_greeter_get_default_session (greeter)))
667             gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
668
669         g_object_set_data (G_OBJECT (menu_item), "key", g_strdup (ldm_session_get_key (session)));
670     }
671
672     power_menu = gtk_menu_new ();
673     if (ldm_greeter_get_can_suspend (greeter))
674     {
675         menu_item = gtk_menu_item_new_with_label (_("Suspend"));
676         gtk_menu_shell_append (GTK_MENU_SHELL (power_menu), menu_item);
677         g_signal_connect (menu_item, "activate", G_CALLBACK (suspend_cb), greeter);
678         n_power_items++;
679     }
680     if (ldm_greeter_get_can_hibernate (greeter))
681     {
682         menu_item = gtk_menu_item_new_with_label (_("Hibernate"));
683         gtk_menu_shell_append (GTK_MENU_SHELL (power_menu), menu_item);
684         g_signal_connect (menu_item, "activate", G_CALLBACK (hibernate_cb), greeter);
685         n_power_items++;
686     }
687     if (ldm_greeter_get_can_restart (greeter))
688     {
689         menu_item = gtk_menu_item_new_with_label (_("Restart..."));
690         gtk_menu_shell_append (GTK_MENU_SHELL (power_menu), menu_item);
691         g_signal_connect (menu_item, "activate", G_CALLBACK (restart_cb), greeter);
692         n_power_items++;
693     }
694     if (ldm_greeter_get_can_shutdown (greeter))
695     {
696         menu_item = gtk_menu_item_new_with_label (_("Shutdown..."));
697         gtk_menu_shell_append (GTK_MENU_SHELL (power_menu), menu_item);
698         g_signal_connect (menu_item, "activate", G_CALLBACK (shutdown_cb), greeter);
699         n_power_items++;
700     }
701     if (n_power_items > 0)
702     {
703         menu_item = gtk_image_menu_item_new ();
704         gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menu_item), TRUE);
705         gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menu_item), TRUE);
706         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_LARGE_TOOLBAR));
707         gtk_menu_item_set_label (GTK_MENU_ITEM (menu_item), ""); // NOTE: Needed to make the icon show as selected
708         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), power_menu);
709         gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
710     }
711
712     gtk_widget_show_all (window);
713
714     if (user_view)
715         gtk_widget_grab_focus (user_view);
716     else
717         gtk_widget_grab_focus (username_entry);    
718 }
719
720 int
721 main(int argc, char **argv)
722 {
723     signal (SIGTERM, sigterm_cb);
724
725     g_type_init ();
726
727     greeter = ldm_greeter_new ();
728     g_signal_connect (G_OBJECT (greeter), "connected", G_CALLBACK (connect_cb), NULL);    
729     g_signal_connect (G_OBJECT (greeter), "show-prompt", G_CALLBACK (show_prompt_cb), NULL);  
730     g_signal_connect (G_OBJECT (greeter), "show-message", G_CALLBACK (show_message_cb), NULL);
731     g_signal_connect (G_OBJECT (greeter), "show-error", G_CALLBACK (show_message_cb), NULL);
732     g_signal_connect (G_OBJECT (greeter), "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
733     g_signal_connect (G_OBJECT (greeter), "timed-login", G_CALLBACK (timed_login_cb), NULL);
734     g_signal_connect (G_OBJECT (greeter), "quit", G_CALLBACK (quit_cb), NULL);
735     ldm_greeter_connect_to_server (greeter);
736
737     gtk_init (&argc, &argv);
738
739     gtk_main ();
740
741     return 0;
742 }