2 * Copyright (C) 2010-2011 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
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
14 #include <glib/gi18n.h>
16 #include <gdk-pixbuf/gdk-pixbuf.h>
17 #include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
19 #include "lightdm/greeter.h"
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;
33 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (session_combo), &iter))
34 return g_strdup (ldm_greeter_get_default_session (greeter));
36 gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (session_combo)), &iter, 1, &session, -1);
42 set_session (const gchar *session)
44 GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (session_combo));
47 if (!gtk_tree_model_get_iter_first (model, &iter))
54 gtk_tree_model_get (model, &iter, 1, &s, -1);
55 matched = strcmp (s, session) == 0;
59 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (session_combo), &iter);
62 } while (gtk_tree_model_iter_next (model, &iter));
66 start_authentication (const gchar *username)
68 gchar *language, *layout, *session;
70 gtk_widget_hide (message_label);
71 gtk_label_set_text (GTK_LABEL (message_label), "");
73 if (strcmp (username, "*other") == 0)
75 ldm_greeter_login (greeter, NULL);
77 else if (strcmp (username, "*guest") == 0)
79 ldm_greeter_login_as_guest (greeter);
83 if (ldm_greeter_get_user_defaults (greeter, username, &language, &layout, &session))
85 set_session (session);
91 ldm_greeter_login (greeter, username);
95 void user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column);
98 user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column)
100 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
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);
113 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
117 if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (user_view)),
120 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
121 start_authentication (user);
128 gboolean user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event);
131 user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event)
133 /* Do it in the idle loop so the selection is done first */
134 g_idle_add (idle_select_cb, NULL);
138 void login_cb (GtkWidget *widget);
141 login_cb (GtkWidget *widget)
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)));
147 ldm_greeter_provide_secret (greeter, gtk_entry_get_text (GTK_ENTRY (prompt_entry)));
148 gtk_entry_set_text (GTK_ENTRY (prompt_entry), "");
151 void cancel_cb (GtkWidget *widget);
154 cancel_cb (GtkWidget *widget)
156 ldm_greeter_cancel_authentication (greeter);
160 show_prompt_cb (LdmGreeter *greeter, const gchar *text)
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);
171 show_message_cb (LdmGreeter *greeter, const gchar *text)
173 gtk_label_set_text (GTK_LABEL (message_label), text);
174 gtk_widget_show (message_label);
178 authentication_complete_cb (LdmGreeter *greeter)
180 gtk_widget_hide (prompt_box);
181 gtk_label_set_text (GTK_LABEL (prompt_label), "");
182 gtk_entry_set_text (GTK_ENTRY (prompt_entry), "");
184 gtk_widget_grab_focus (user_view);
186 if (ldm_greeter_get_is_authenticated (greeter))
188 gchar *session = get_session ();
189 ldm_greeter_start_session (greeter, session);
194 gtk_label_set_text (GTK_LABEL (message_label), "Failed to authenticate");
195 gtk_widget_show (message_label);
200 timed_login_cb (LdmGreeter *greeter, const gchar *username)
202 set_session (ldm_greeter_get_default_session (greeter));
203 ldm_greeter_login (greeter, ldm_greeter_get_timed_login_user (greeter));
206 void suspend_cb (GtkWidget *widget, LdmGreeter *greeter);
209 suspend_cb (GtkWidget *widget, LdmGreeter *greeter)
211 ldm_greeter_suspend (greeter);
214 void hibernate_cb (GtkWidget *widget, LdmGreeter *greeter);
217 hibernate_cb (GtkWidget *widget, LdmGreeter *greeter)
219 ldm_greeter_hibernate (greeter);
223 center_window (GtkWindow *window)
225 GtkAllocation allocation;
228 gint screen_width, screen_height;
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);
240 void restart_cb (GtkWidget *widget, LdmGreeter *greeter);
243 restart_cb (GtkWidget *widget, LdmGreeter *greeter)
247 dialog = gtk_message_dialog_new (NULL,
248 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
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));
257 if (gtk_dialog_run (GTK_DIALOG (dialog)))
258 ldm_greeter_restart (greeter);
259 gtk_widget_destroy (dialog);
262 void shutdown_cb (GtkWidget *widget, LdmGreeter *greeter);
265 shutdown_cb (GtkWidget *widget, LdmGreeter *greeter)
269 dialog = gtk_message_dialog_new (NULL,
270 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
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));
279 if (gtk_dialog_run (GTK_DIALOG (dialog)))
280 ldm_greeter_shutdown (greeter);
281 gtk_widget_destroy (dialog);
285 fade_timer_cb (gpointer data)
289 opacity = gtk_window_get_opacity (GTK_WINDOW (window));
296 gtk_window_set_opacity (GTK_WINDOW (window), opacity);
302 user_added_cb (LdmGreeter *greeter, LdmUser *user)
307 model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
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),
318 get_user_iter (const gchar *username, GtkTreeIter *iter)
322 model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
324 if (!gtk_tree_model_get_iter_first (model, iter))
331 gtk_tree_model_get (model, iter, 0, &name, -1);
332 matched = strcmp (name, username) == 0;
336 } while (gtk_tree_model_iter_next (model, iter));
342 user_changed_cb (LdmGreeter *greeter, LdmUser *user)
347 if (!get_user_iter (ldm_user_get_name (user), &iter))
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),
359 user_removed_cb (LdmGreeter *greeter, LdmUser *user)
364 if (!get_user_iter (ldm_user_get_name (user), &iter))
367 model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
368 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
372 quit_cb (LdmGreeter *greeter, const gchar *username)
374 /* Fade out the greeter */
375 g_timeout_add (40, (GSourceFunc) fade_timer_cb, NULL);
378 void a11y_font_cb (GtkWidget *widget);
381 a11y_font_cb (GtkWidget *widget)
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);
386 g_object_set (gtk_settings_get_default (), "gtk-font-name", "Ubuntu 10", NULL);
389 void a11y_contrast_cb (GtkWidget *widget);
392 a11y_contrast_cb (GtkWidget *widget)
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);
397 g_object_set (gtk_settings_get_default (), "gtk-theme-name", theme_name, NULL);
401 sigterm_cb (int signum)
406 gboolean draw_background_cb (GtkWidget *widget, GdkEventExpose *event);
409 draw_background_cb (GtkWidget *widget, GdkEventExpose *event)
412 GtkAllocation allocation;
414 context = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
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);
421 cairo_destroy (context);
427 connect_cb (LdmGreeter *greeter)
432 gint screen_width, screen_height;
434 const GList *items, *item;
437 GtkCellRenderer *renderer;
438 gchar *theme_dir, *rc_file, *background_image;
439 GError *error = NULL;
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);
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");
451 gchar *path = g_build_filename (theme_dir, rc_file, NULL);
453 gtk_rc_add_default_file (path);
457 builder = gtk_builder_new ();
458 if (!gtk_builder_add_from_file (builder, UI_DIR "/greeter.ui", &error))
460 g_warning ("Error loading UI: %s", error->message);
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"));
471 gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "hostname_label")), ldm_greeter_get_hostname (greeter));
473 background_image = ldm_greeter_get_string_property (greeter, "background-image");
474 if (background_image)
478 GError *error = NULL;
480 path = g_build_filename (theme_dir, background_image, NULL);
481 g_free (background_image);
482 pixbuf = gdk_pixbuf_new_from_file (path, &error);
484 g_warning ("Failed to load background: %s", error->message);
485 g_clear_error (&error);
490 background_pixbuf = gdk_pixbuf_scale_simple (pixbuf, screen_width, screen_height, GDK_INTERP_BILINEAR);
491 g_object_unref (pixbuf);
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)
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);
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")));
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);
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)
523 LdmUser *user = item->data;
525 GdkPixbuf *pixbuf = NULL;
527 image = ldm_user_get_image (user);
532 path = g_filename_from_uri (image, NULL, NULL);
534 pixbuf = gdk_pixbuf_new_from_file_at_scale (path, 64, 64, TRUE, NULL);
538 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
541 GTK_ICON_LOOKUP_USE_BUILTIN,
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));
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),
556 if (ldm_greeter_get_has_guest_session (greeter))
558 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
559 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
562 2, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
566 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
567 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
570 2, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
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)
580 LdmSession *session = item->data;
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),
588 set_session (ldm_greeter_get_default_session (greeter));
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);
594 gtk_widget_grab_focus (user_view);
598 main(int argc, char **argv)
600 /* Disable global menus */
601 unsetenv ("UBUNTU_MENUPROXY");
603 signal (SIGTERM, sigterm_cb);
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);
620 gtk_init (&argc, &argv);