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 LightDMGreeter *greeter;
22 static LightDMUserList *user_list;
23 static GtkWidget *window, *message_label, *user_view;
24 static GdkPixbuf *background_pixbuf = NULL;
25 static GtkWidget *prompt_box, *prompt_label, *prompt_entry, *session_combo;
26 static gchar *theme_name;
34 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (session_combo), &iter))
35 return g_strdup (lightdm_greeter_get_default_session_hint (greeter));
37 gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (session_combo)), &iter, 1, &session, -1);
43 set_session (const gchar *session)
45 GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (session_combo));
48 if (!gtk_tree_model_get_iter_first (model, &iter))
55 gtk_tree_model_get (model, &iter, 1, &s, -1);
56 matched = strcmp (s, session) == 0;
60 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (session_combo), &iter);
63 } while (gtk_tree_model_iter_next (model, &iter));
67 start_authentication (const gchar *username)
69 gtk_widget_hide (message_label);
70 gtk_label_set_text (GTK_LABEL (message_label), "");
72 if (strcmp (username, "*other") == 0)
74 lightdm_greeter_login_with_user_prompt (greeter);
76 else if (strcmp (username, "*guest") == 0)
78 lightdm_greeter_login_as_guest (greeter);
83 user = lightdm_user_list_get_user_by_name (user_list, username);
85 set_session (lightdm_user_get_session (user));
87 set_session (lightdm_greeter_get_default_session_hint (greeter));
89 lightdm_greeter_login (greeter, username);
93 void user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column);
96 user_treeview_row_activated_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column)
98 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
102 gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
103 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
104 start_authentication (user);
111 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
115 if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (user_view)),
118 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
119 start_authentication (user);
126 gboolean user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event);
129 user_treeview_button_press_event_cb (GtkWidget *widget, GdkEventButton *event)
131 /* Do it in the idle loop so the selection is done first */
132 g_idle_add (idle_select_cb, NULL);
136 void login_cb (GtkWidget *widget);
139 login_cb (GtkWidget *widget)
141 gtk_widget_set_sensitive (prompt_entry, FALSE);
142 if (!lightdm_greeter_get_in_authentication (greeter))
143 start_authentication (gtk_entry_get_text (GTK_ENTRY (prompt_entry)));
145 lightdm_greeter_respond (greeter, gtk_entry_get_text (GTK_ENTRY (prompt_entry)));
146 gtk_entry_set_text (GTK_ENTRY (prompt_entry), "");
149 void cancel_cb (GtkWidget *widget);
152 cancel_cb (GtkWidget *widget)
154 lightdm_greeter_cancel_authentication (greeter);
158 show_prompt_cb (LightDMGreeter *greeter, const gchar *text, LightDMPromptType type)
160 gtk_label_set_text (GTK_LABEL (prompt_label), text);
161 gtk_widget_set_sensitive (prompt_entry, TRUE);
162 gtk_entry_set_text (GTK_ENTRY (prompt_entry), "");
163 gtk_entry_set_visibility (GTK_ENTRY (prompt_entry), type != LIGHTDM_PROMPT_TYPE_SECRET);
164 gtk_widget_show (prompt_box);
165 gtk_widget_grab_focus (prompt_entry);
169 show_message_cb (LightDMGreeter *greeter, const gchar *text, LightDMMessageType type)
171 gtk_label_set_text (GTK_LABEL (message_label), text);
172 gtk_widget_show (message_label);
176 authentication_complete_cb (LightDMGreeter *greeter)
178 gtk_widget_hide (prompt_box);
179 gtk_label_set_text (GTK_LABEL (prompt_label), "");
180 gtk_entry_set_text (GTK_ENTRY (prompt_entry), "");
182 gtk_widget_grab_focus (user_view);
184 if (lightdm_greeter_get_is_authenticated (greeter))
186 gchar *session = get_session ();
187 lightdm_greeter_start_session (greeter, session);
192 gtk_label_set_text (GTK_LABEL (message_label), "Failed to authenticate");
193 gtk_widget_show (message_label);
194 if (lightdm_greeter_get_hide_users_hint (greeter))
195 lightdm_greeter_login_with_user_prompt (greeter);
200 autologin_timer_expired_cb (LightDMGreeter *greeter)
202 set_session (lightdm_greeter_get_default_session_hint (greeter));
203 if (lightdm_greeter_get_autologin_guest_hint (greeter))
204 lightdm_greeter_login_as_guest (greeter);
205 else if (lightdm_greeter_get_autologin_user_hint (greeter))
206 lightdm_greeter_login (greeter, lightdm_greeter_get_autologin_user_hint (greeter));
209 void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
212 suspend_cb (GtkWidget *widget, LightDMGreeter *greeter)
214 lightdm_greeter_suspend (greeter);
217 void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
220 hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter)
222 lightdm_greeter_hibernate (greeter);
226 center_window (GtkWindow *window)
228 GtkAllocation allocation;
231 gint screen_width, screen_height;
233 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
234 display = gdk_display_get_default ();
235 screen = gdk_display_get_default_screen (display);
236 screen_width = gdk_screen_get_width (screen);
237 screen_height = gdk_screen_get_height (screen);
238 gtk_window_move (GTK_WINDOW (window),
239 (screen_width - allocation.width) / 2,
240 (screen_height - allocation.height) / 2);
243 void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
246 restart_cb (GtkWidget *widget, LightDMGreeter *greeter)
250 dialog = gtk_message_dialog_new (NULL,
251 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
254 "%s", _("Are you sure you want to close all programs and restart the computer?"));
255 gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), gtk_image_new_from_icon_name ("system-restart", GTK_ICON_SIZE_DIALOG));
256 gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), FALSE, _("Restart"), TRUE, NULL);
257 gtk_widget_show_all (dialog);
258 center_window (GTK_WINDOW (dialog));
260 if (gtk_dialog_run (GTK_DIALOG (dialog)))
261 lightdm_greeter_restart (greeter);
262 gtk_widget_destroy (dialog);
265 void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
268 shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter)
272 dialog = gtk_message_dialog_new (NULL,
273 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
276 "%s", _("Are you sure you want to close all programs and shutdown the computer?"));
277 gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_DIALOG));
278 gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), FALSE, _("Shutdown"), TRUE, NULL);
279 gtk_widget_show_all (dialog);
280 center_window (GTK_WINDOW (dialog));
282 if (gtk_dialog_run (GTK_DIALOG (dialog)))
283 lightdm_greeter_shutdown (greeter);
284 gtk_widget_destroy (dialog);
288 fade_timer_cb (gpointer data)
292 opacity = gtk_window_get_opacity (GTK_WINDOW (window));
299 gtk_window_set_opacity (GTK_WINDOW (window), opacity);
305 user_added_cb (LightDMUserList *user_list, LightDMUser *user)
310 model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
312 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
313 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
314 0, lightdm_user_get_name (user),
315 1, lightdm_user_get_display_name (user),
321 get_user_iter (const gchar *username, GtkTreeIter *iter)
325 model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
327 if (!gtk_tree_model_get_iter_first (model, iter))
334 gtk_tree_model_get (model, iter, 0, &name, -1);
335 matched = strcmp (name, username) == 0;
339 } while (gtk_tree_model_iter_next (model, iter));
345 user_changed_cb (LightDMUserList *user_list, LightDMUser *user)
350 if (!get_user_iter (lightdm_user_get_name (user), &iter))
353 model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
354 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
355 0, lightdm_user_get_name (user),
356 1, lightdm_user_get_display_name (user),
362 user_removed_cb (LightDMUserList *user_list, LightDMUser *user)
367 if (!get_user_iter (lightdm_user_get_name (user), &iter))
370 model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
371 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
375 quit_cb (LightDMGreeter *greeter, const gchar *username)
377 /* Fade out the greeter */
378 g_timeout_add (40, (GSourceFunc) fade_timer_cb, NULL);
381 void a11y_font_cb (GtkWidget *widget);
384 a11y_font_cb (GtkWidget *widget)
386 if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
387 g_object_set (gtk_settings_get_default (), "gtk-font-name", "Ubuntu 20", NULL);
389 g_object_set (gtk_settings_get_default (), "gtk-font-name", "Ubuntu 10", NULL);
392 void a11y_contrast_cb (GtkWidget *widget);
395 a11y_contrast_cb (GtkWidget *widget)
397 if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
398 g_object_set (gtk_settings_get_default (), "gtk-theme-name", "HighContrastInverse", NULL);
400 g_object_set (gtk_settings_get_default (), "gtk-theme-name", theme_name, NULL);
404 sigterm_cb (int signum)
409 gboolean draw_background_cb (GtkWidget *widget, GdkEventExpose *event);
412 draw_background_cb (GtkWidget *widget, GdkEventExpose *event)
415 GtkAllocation allocation;
417 context = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
419 gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
420 if (background_pixbuf)
421 gdk_cairo_set_source_pixbuf (context, background_pixbuf, 0.0, 0.0);
423 cairo_set_source_rgb (context, 0, 0, 0);
424 cairo_fill (context);
426 cairo_destroy (context);
434 const GList *items, *item;
438 user_list = lightdm_user_list_new ();
439 g_signal_connect (user_list, "user-added", G_CALLBACK (user_added_cb), NULL);
440 g_signal_connect (user_list, "user-changed", G_CALLBACK (user_changed_cb), NULL);
441 g_signal_connect (user_list, "user-removed", G_CALLBACK (user_removed_cb), NULL);
443 items = lightdm_user_list_get_users (user_list);
445 model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
446 for (item = items; item; item = item->next)
448 LightDMUser *user = item->data;
450 GdkPixbuf *pixbuf = NULL;
452 image = lightdm_user_get_image (user);
454 pixbuf = gdk_pixbuf_new_from_file_at_scale (image, 64, 64, TRUE, NULL);
456 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
459 GTK_ICON_LOOKUP_USE_BUILTIN,
463 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 64, 64);
464 memset (gdk_pixbuf_get_pixels (pixbuf), 0, gdk_pixbuf_get_height (pixbuf) * gdk_pixbuf_get_rowstride (pixbuf) * gdk_pixbuf_get_n_channels (pixbuf));
467 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
468 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
469 0, lightdm_user_get_name (user),
470 1, lightdm_user_get_display_name (user),
474 if (lightdm_greeter_get_has_guest_account_hint (greeter))
476 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
477 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
480 2, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
484 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
485 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
488 2, gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock_person", 64, 0, NULL),
493 connected_cb (LightDMGreeter *greeter)
498 gint screen_width, screen_height;
501 const GList *items, *item;
503 GtkCellRenderer *renderer;
504 gchar *rc_file, *background_image;
505 GError *error = NULL;
507 display = gdk_display_get_default ();
508 screen = gdk_display_get_default_screen (display);
509 screen_width = gdk_screen_get_width (screen);
510 screen_height = gdk_screen_get_height (screen);
512 g_object_get (gtk_settings_get_default (), "gtk-theme-name", &theme_name, NULL);
513 rc_file = NULL; // FIXME
516 gchar *path = g_build_filename (GREETER_DATA_DIR, rc_file, NULL);
518 gtk_rc_add_default_file (path);
522 builder = gtk_builder_new ();
523 if (!gtk_builder_add_from_file (builder, GREETER_DATA_DIR "/greeter.ui", &error))
525 g_warning ("Error loading UI: %s", error->message);
528 g_clear_error (&error);
529 window = GTK_WIDGET (gtk_builder_get_object (builder, "greeter_window"));
530 prompt_box = GTK_WIDGET (gtk_builder_get_object (builder, "prompt_box"));
531 prompt_label = GTK_WIDGET (gtk_builder_get_object (builder, "prompt_label"));
532 prompt_entry = GTK_WIDGET (gtk_builder_get_object (builder, "prompt_entry"));
533 message_label = GTK_WIDGET (gtk_builder_get_object (builder, "message_label"));
534 session_combo = GTK_WIDGET (gtk_builder_get_object (builder, "session_combobox"));
536 gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "hostname_label")), lightdm_greeter_get_hostname (greeter));
538 background_image = NULL; // FIXME
539 if (background_image)
543 GError *error = NULL;
545 path = g_build_filename (GREETER_DATA_DIR, background_image, NULL);
546 g_free (background_image);
547 pixbuf = gdk_pixbuf_new_from_file (path, &error);
549 g_warning ("Failed to load background: %s", error->message);
550 g_clear_error (&error);
555 background_pixbuf = gdk_pixbuf_scale_simple (pixbuf, screen_width, screen_height, GDK_INTERP_BILINEAR);
556 g_object_unref (pixbuf);
560 /* Set the background */
561 root = gdk_get_default_root_window ();
562 gdk_window_set_cursor (root, gdk_cursor_new (GDK_LEFT_PTR));
563 if (background_pixbuf)
567 gdk_pixbuf_render_pixmap_and_mask_for_colormap (background_pixbuf, gdk_window_get_colormap (root), &pixmap, NULL, 0);
568 gdk_window_set_back_pixmap (root, pixmap, FALSE);
571 if (!lightdm_greeter_get_can_suspend (greeter))
572 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "suspend_menuitem")));
573 if (!lightdm_greeter_get_can_hibernate (greeter))
574 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "hibernate_menuitem")));
575 if (!lightdm_greeter_get_can_restart (greeter))
576 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "restart_menuitem")));
577 if (!lightdm_greeter_get_can_shutdown (greeter))
578 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "shutdown_menuitem")));
580 user_view = GTK_WIDGET (gtk_builder_get_object (builder, "user_treeview"));
581 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (user_view), 0, "Face", gtk_cell_renderer_pixbuf_new(), "pixbuf", 2, NULL);
582 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (user_view), 1, "Name", gtk_cell_renderer_text_new(), "text", 1, NULL);
584 if (lightdm_greeter_get_hide_users_hint (greeter))
585 lightdm_greeter_login_with_user_prompt (greeter);
589 gtk_widget_show (user_view);
592 // FIXME: Select the requested user if lightdm_greeter_get_timed_login_user () && lightdm_greeter_get_timed_login_delay () == 0
594 renderer = gtk_cell_renderer_text_new();
595 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (session_combo), renderer, TRUE);
596 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (session_combo), renderer, "text", 0);
597 model = gtk_combo_box_get_model (GTK_COMBO_BOX (session_combo));
598 items = lightdm_greeter_get_sessions (greeter);
599 for (item = items; item; item = item->next)
601 LightDMSession *session = item->data;
603 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
604 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
605 0, lightdm_session_get_name (session),
606 1, lightdm_session_get_key (session),
609 set_session (lightdm_greeter_get_default_session_hint (greeter));
611 gtk_window_set_default_size (GTK_WINDOW (window), screen_width, screen_height);
612 gtk_builder_connect_signals(builder, greeter);
613 gtk_widget_show (window);
615 gtk_widget_grab_focus (user_view);
619 main(int argc, char **argv)
621 /* Disable global menus */
622 unsetenv ("UBUNTU_MENUPROXY");
624 signal (SIGTERM, sigterm_cb);
626 gtk_init (&argc, &argv);
628 greeter = lightdm_greeter_new ();
629 g_signal_connect (greeter, "connected", G_CALLBACK (connected_cb), NULL);
630 g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);
631 g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);
632 g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
633 g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (autologin_timer_expired_cb), NULL);
634 g_signal_connect (greeter, "quit", G_CALLBACK (quit_cb), NULL);
635 lightdm_greeter_connect_to_server (greeter);