2
* Copyright (C) 2010 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>
15
#include <gdk-pixbuf/gdk-pixbuf.h>
16
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
20
static LdmGreeter *greeter;
21
static GtkTreeModel *user_model;
22
static GtkWidget *user_window, *vbox, *message_label, *user_view;
23
static GtkWidget *username_entry, *password_entry;
24
static GtkWidget *panel_window;
25
static gchar *session = NULL, *theme_name;
28
start_authentication (const gchar *username)
32
if (user_model && gtk_tree_model_get_iter_first (GTK_TREE_MODEL (user_model), &iter))
37
gtk_tree_model_get (GTK_TREE_MODEL (user_model), &iter, 0, &user, -1);
38
gtk_list_store_set (GTK_LIST_STORE (user_model), &iter, 3, strcmp (user, username) == 0, -1);
40
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (user_model), &iter));
43
gtk_widget_set_sensitive (username_entry, FALSE);
45
ldm_greeter_start_authentication (greeter, username);
49
user_view_activate_cb (GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column)
54
gtk_tree_model_get_iter (GTK_TREE_MODEL (user_model), &iter, path);
55
gtk_tree_model_get (GTK_TREE_MODEL (user_model), &iter, 0, &user, -1);
56
start_authentication (user);
66
if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (user_view)),
69
gtk_tree_model_get (GTK_TREE_MODEL (user_model), &iter, 0, &user, -1);
70
start_authentication (user);
78
user_view_click_cb (GtkWidget *widget, GdkEventButton *event)
80
/* Do it in the idle loop so the selection is done first */
81
g_idle_add (idle_select_cb, NULL);
86
username_activate_cb (GtkWidget *widget)
88
start_authentication (gtk_entry_get_text (GTK_ENTRY (username_entry)));
92
password_activate_cb (GtkWidget *widget)
94
gtk_widget_set_sensitive (widget, FALSE);
95
ldm_greeter_provide_secret (greeter, gtk_entry_get_text (GTK_ENTRY (widget)));
99
show_prompt_cb (LdmGreeter *greeter, const gchar *text)
101
gtk_widget_show (password_entry);
102
gtk_widget_set_sensitive (password_entry, TRUE);
103
gtk_widget_grab_focus (password_entry);
107
show_message_cb (LdmGreeter *greeter, const gchar *text)
109
gtk_widget_show (message_label);
110
gtk_label_set_text (GTK_LABEL (message_label), text);
114
authentication_complete_cb (LdmGreeter *greeter)
118
gtk_widget_hide (password_entry);
119
gtk_entry_set_text (GTK_ENTRY (password_entry), "");
121
/* Clear row shading */
122
if (user_model && gtk_tree_model_get_iter_first (GTK_TREE_MODEL (user_model), &iter))
126
gtk_list_store_set (GTK_LIST_STORE (user_model), &iter, 3, TRUE, -1);
127
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (user_model), &iter));
131
gtk_entry_set_text (GTK_ENTRY (username_entry), "");
132
gtk_widget_set_sensitive (username_entry, TRUE);
136
gtk_widget_grab_focus (user_view);
138
gtk_widget_grab_focus (username_entry);
140
if (ldm_greeter_get_is_authenticated (greeter))
142
ldm_greeter_login (greeter, ldm_greeter_get_authentication_user (greeter), session);
146
gtk_widget_show (message_label);
147
gtk_label_set_text (GTK_LABEL (message_label), "Failed to authenticate");
152
timed_login_cb (LdmGreeter *greeter, const gchar *username)
154
ldm_greeter_login (greeter, ldm_greeter_get_timed_login_user (greeter), ldm_greeter_get_default_session (greeter));
158
suspend_cb (GtkWidget *widget, LdmGreeter *greeter)
160
ldm_greeter_suspend (greeter);
164
hibernate_cb (GtkWidget *widget, LdmGreeter *greeter)
166
ldm_greeter_hibernate (greeter);
170
center_window (GtkWindow *window)
172
GtkAllocation allocation;
175
gint screen_width, screen_height;
177
gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
178
display = gdk_display_get_default ();
179
screen = gdk_display_get_default_screen (display);
180
screen_width = gdk_screen_get_width (screen);
181
screen_height = gdk_screen_get_height (screen);
182
gtk_window_move (GTK_WINDOW (window),
183
(screen_width - allocation.width) / 2,
184
(screen_height - allocation.height) / 2);
188
restart_cb (GtkWidget *widget, LdmGreeter *greeter)
192
dialog = gtk_message_dialog_new (NULL,
193
GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
196
"%s", _("Are you sure you want to close all programs and restart the computer?"));
197
gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), gtk_image_new_from_icon_name ("system-restart", GTK_ICON_SIZE_DIALOG));
198
gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), FALSE, _("Restart"), TRUE, NULL);
199
gtk_widget_show_all (dialog);
200
center_window (GTK_WINDOW (dialog));
202
if (gtk_dialog_run (GTK_DIALOG (dialog)))
203
ldm_greeter_restart (greeter);
204
gtk_widget_destroy (dialog);
208
shutdown_cb (GtkWidget *widget, LdmGreeter *greeter)
212
dialog = gtk_message_dialog_new (NULL,
213
GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
216
"%s", _("Are you sure you want to close all programs and shutdown the computer?"));
217
gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_DIALOG));
218
gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), FALSE, _("Shutdown"), TRUE, NULL);
219
gtk_widget_show_all (dialog);
220
center_window (GTK_WINDOW (dialog));
222
if (gtk_dialog_run (GTK_DIALOG (dialog)))
223
ldm_greeter_shutdown (greeter);
224
gtk_widget_destroy (dialog);
228
quit_cb (LdmGreeter *greeter, const gchar *username)
234
layout_changed_cb (GtkWidget *widget)
236
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
237
ldm_greeter_set_layout (greeter, g_object_get_data (G_OBJECT (widget), "layout"));
241
session_changed_cb (GtkWidget *widget)
243
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
246
session = g_strdup (g_object_get_data (G_OBJECT (widget), "key"));
251
a11y_font_cb (GtkWidget *widget)
253
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
254
g_object_set (gtk_settings_get_default (), "gtk-font-name", "UbuntuBeta 20", NULL);
256
g_object_set (gtk_settings_get_default (), "gtk-font-name", "UbuntuBeta 10", NULL);
260
a11y_contrast_cb (GtkWidget *widget)
262
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
263
g_object_set (gtk_settings_get_default (), "gtk-theme-name", "HighContrastInverse", NULL);
265
g_object_set (gtk_settings_get_default (), "gtk-theme-name", theme_name, NULL);
269
sigterm_cb (int signum)
275
make_user_view (void)
279
GtkCellRenderer *renderer;
280
const GList *items, *item;
283
items = ldm_greeter_get_users (greeter);
287
model = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN);
288
for (item = items; item; item = item->next)
290
LdmUser *user = item->data;
292
GdkPixbuf *pixbuf = NULL;
294
image = ldm_user_get_image (user);
295
if (image[0] != '\0')
299
path = g_filename_from_uri (image, NULL, NULL);
301
pixbuf = gdk_pixbuf_new_from_file_at_scale (path, 64, 64, TRUE, NULL);
305
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
311
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
312
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
313
0, ldm_user_get_name (user),
314
1, ldm_user_get_display_name (user),
320
view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
321
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
322
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_NONE);
324
renderer = gtk_cell_renderer_pixbuf_new();
325
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), 0, "Face", renderer, "pixbuf", 2, "sensitive", 3, NULL);
327
renderer = gtk_cell_renderer_text_new();
328
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), 1, "Name", renderer, "text", 1, NULL);
330
g_signal_connect (view, "row-activated", G_CALLBACK (user_view_activate_cb), NULL);
331
g_signal_connect (view, "button-press-event", G_CALLBACK (user_view_click_cb), NULL);
333
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
334
gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), &iter);
340
main(int argc, char **argv)
342
gchar *theme_dir, *rc_file, *background_image;
344
const GList *items, *item;
345
GSList *session_radio_list = NULL, *language_radio_list = NULL, *layout_radio_list = NULL;
348
gint screen_width, screen_height;
349
GtkAllocation allocation;
350
GtkWidget *logo_image;
351
GtkWidget *option_menu, *power_menu;
352
GtkWidget *menu_bar, *menu, *menu_item;
353
GdkColor background_color;
354
gint n_power_items = 0;
356
signal (SIGTERM, sigterm_cb);
360
greeter = ldm_greeter_new ();
362
g_signal_connect (G_OBJECT (greeter), "show-prompt", G_CALLBACK (show_prompt_cb), NULL);
363
g_signal_connect (G_OBJECT (greeter), "show-message", G_CALLBACK (show_message_cb), NULL);
364
g_signal_connect (G_OBJECT (greeter), "show-error", G_CALLBACK (show_message_cb), NULL);
365
g_signal_connect (G_OBJECT (greeter), "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
366
g_signal_connect (G_OBJECT (greeter), "timed-login", G_CALLBACK (timed_login_cb), NULL);
367
g_signal_connect (G_OBJECT (greeter), "quit", G_CALLBACK (quit_cb), NULL);
369
ldm_greeter_connect (greeter);
370
session = g_strdup (ldm_greeter_get_default_session (greeter));
372
theme_dir = g_path_get_dirname (ldm_greeter_get_theme (greeter));
373
rc_file = ldm_greeter_get_string_property (greeter, "gtkrc");
376
gchar *path = g_build_filename (theme_dir, rc_file, NULL);
378
gtk_rc_add_default_file (path);
382
gtk_init (&argc, &argv);
384
g_object_get (gtk_settings_get_default (), "gtk-theme-name", &theme_name, NULL);
386
display = gdk_display_get_default ();
387
screen = gdk_display_get_default_screen (display);
388
screen_width = gdk_screen_get_width (screen);
389
screen_height = gdk_screen_get_height (screen);
391
root = gdk_get_default_root_window ();
392
gdk_window_set_cursor (root, gdk_cursor_new (GDK_LEFT_PTR));
393
//FIXME: background_color = ldm_greeter_get_string_property (greeter, "background-color");
394
gdk_color_parse ("#000000", &background_color);
395
gdk_color_alloc (gdk_window_get_colormap (root), &background_color);
396
gdk_window_set_background (root, &background_color);
398
background_image = ldm_greeter_get_string_property (greeter, "background-image");
399
if (background_image)
403
GError *error = NULL;
405
path = g_build_filename (theme_dir, background_image, NULL);
406
g_free (background_image);
407
pixbuf = gdk_pixbuf_new_from_file (path, &error);
409
g_warning ("Failed to load background: %s", error->message);
410
g_clear_error (&error);
418
scaled = gdk_pixbuf_scale_simple (pixbuf, screen_width, screen_height, GDK_INTERP_BILINEAR);
419
g_object_unref (pixbuf);
421
gdk_pixbuf_render_pixmap_and_mask_for_colormap (scaled, gdk_window_get_colormap (root), &pixmap, NULL, 0);
422
g_object_unref (scaled);
424
gdk_window_set_back_pixmap (root, pixmap, FALSE);
427
background_image = NULL;
429
gdk_window_clear (root);
431
user_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
432
gtk_window_set_decorated (GTK_WINDOW (user_window), FALSE);
433
gtk_window_set_resizable (GTK_WINDOW (user_window), FALSE);
434
gtk_container_set_border_width (GTK_CONTAINER (user_window), 12);
435
g_signal_connect (user_window, "delete-event", gtk_main_quit, NULL);
437
vbox = gtk_vbox_new (FALSE, 6);
438
gtk_container_add (GTK_CONTAINER (user_window), vbox);
440
logo_image = gtk_image_new_from_icon_name ("computer", GTK_ICON_SIZE_DIALOG);
441
gtk_image_set_pixel_size (GTK_IMAGE (logo_image), 64);
442
gtk_box_pack_start (GTK_BOX (vbox), logo_image, FALSE, FALSE, 0);
443
gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (ldm_greeter_get_hostname (greeter)), FALSE, FALSE, 0);
445
message_label = gtk_label_new ("");
446
gtk_box_pack_start (GTK_BOX (vbox), message_label, FALSE, FALSE, 0);
447
gtk_widget_set_no_show_all (message_label, TRUE);
449
user_view = make_user_view ();
452
username_entry = NULL;
453
user_model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_view));
454
gtk_box_pack_start (GTK_BOX (vbox), user_view, FALSE, FALSE, 0);
458
username_entry = gtk_entry_new ();
459
gtk_box_pack_start (GTK_BOX (vbox), username_entry, FALSE, FALSE, 0);
460
g_signal_connect (username_entry, "activate", G_CALLBACK (username_activate_cb), NULL);
464
password_entry = gtk_entry_new ();
465
gtk_entry_set_visibility (GTK_ENTRY (password_entry), FALSE);
466
gtk_widget_set_sensitive (password_entry, FALSE);
467
gtk_box_pack_start (GTK_BOX (vbox), password_entry, FALSE, FALSE, 0);
468
g_signal_connect (password_entry, "activate", G_CALLBACK (password_activate_cb), NULL);
469
gtk_widget_set_no_show_all (password_entry, TRUE);
471
gtk_widget_show_all (user_window);
473
/* Center the window */
474
center_window (GTK_WINDOW (user_window));
476
panel_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
477
gtk_window_set_decorated (GTK_WINDOW (panel_window), FALSE);
478
gtk_window_set_resizable (GTK_WINDOW (panel_window), FALSE);
479
gtk_window_set_default_size (GTK_WINDOW (panel_window), screen_width, 10);
481
menu_bar = gtk_menu_bar_new ();
482
gtk_container_add (GTK_CONTAINER (panel_window), menu_bar);
484
menu_item = gtk_image_menu_item_new ();
485
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));
486
gtk_menu_item_set_label (GTK_MENU_ITEM (menu_item), ""); // NOTE: Needed to make the icon show as selected
487
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menu_item), TRUE);
488
gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
489
menu = gtk_menu_new ();
490
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
492
menu_item = gtk_check_menu_item_new_with_label (_("Large Font"));
493
g_signal_connect (menu_item, "toggled", G_CALLBACK (a11y_font_cb), NULL);
494
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
496
menu_item = gtk_check_menu_item_new_with_label (_("High Constrast"));
497
g_signal_connect (menu_item, "toggled", G_CALLBACK (a11y_contrast_cb), NULL);
498
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
500
menu_item = gtk_menu_item_new_with_label (_("Options"));
501
gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
502
option_menu = gtk_menu_new ();
503
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), option_menu);
505
menu_item = gtk_menu_item_new_with_label (_("Language"));
506
gtk_menu_shell_append (GTK_MENU_SHELL (option_menu), menu_item);
507
menu = gtk_menu_new ();
508
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
509
items = ldm_greeter_get_languages (greeter);
510
for (item = items; item; item = item->next)
512
LdmLanguage *language = item->data;
515
if (ldm_language_get_name (language)[0] == '\0')
516
label = g_strdup (ldm_language_get_code (language));
518
label = g_strdup_printf ("%s - %s", ldm_language_get_name (language), ldm_language_get_territory (language));
520
menu_item = gtk_radio_menu_item_new_with_label (language_radio_list, label);
521
language_radio_list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
522
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
524
if (g_str_equal (ldm_language_get_code (language), ldm_greeter_get_language (greeter)))
525
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
527
//g_object_set_data (G_OBJECT (menu_item), "language", g_strdup (ldm_language_get_code (language)));
528
//g_signal_connect (menu_item, "toggled", G_CALLBACK (language_changed_cb), NULL);
531
menu_item = gtk_menu_item_new_with_label (_("Keyboard Layout"));
532
gtk_menu_shell_append (GTK_MENU_SHELL (option_menu), menu_item);
533
menu = gtk_menu_new ();
534
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
535
items = ldm_greeter_get_layouts (greeter);
536
for (item = items; item; item = item->next)
538
LdmLayout *layout = item->data;
540
menu_item = gtk_radio_menu_item_new_with_label (layout_radio_list, ldm_layout_get_description (layout));
541
layout_radio_list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
542
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
544
if (g_str_equal (ldm_layout_get_name (layout), ldm_greeter_get_layout (greeter)))
545
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
547
g_object_set_data (G_OBJECT (menu_item), "layout", g_strdup (ldm_layout_get_name (layout)));
548
g_signal_connect (menu_item, "toggled", G_CALLBACK (layout_changed_cb), NULL);
551
menu_item = gtk_menu_item_new_with_label (_("Session"));
552
gtk_menu_shell_append (GTK_MENU_SHELL (option_menu), menu_item);
553
menu = gtk_menu_new ();
554
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
555
items = ldm_greeter_get_sessions (greeter);
556
for (item = items; item; item = item->next)
558
LdmSession *session = item->data;
560
menu_item = gtk_radio_menu_item_new_with_label (session_radio_list, ldm_session_get_name (session));
561
session_radio_list = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
562
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
564
if (g_str_equal (ldm_session_get_key (session), ldm_greeter_get_default_session (greeter)))
565
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
567
g_object_set_data (G_OBJECT (menu_item), "key", g_strdup (ldm_session_get_key (session)));
568
g_signal_connect (menu_item, "toggled", G_CALLBACK (session_changed_cb), NULL);
571
power_menu = gtk_menu_new ();
572
if (ldm_greeter_get_can_suspend (greeter))
574
menu_item = gtk_menu_item_new_with_label (_("Suspend"));
575
gtk_menu_shell_append (GTK_MENU_SHELL (power_menu), menu_item);
576
g_signal_connect (menu_item, "activate", G_CALLBACK (suspend_cb), greeter);
579
if (ldm_greeter_get_can_hibernate (greeter))
581
menu_item = gtk_menu_item_new_with_label (_("Hibernate"));
582
gtk_menu_shell_append (GTK_MENU_SHELL (power_menu), menu_item);
583
g_signal_connect (menu_item, "activate", G_CALLBACK (hibernate_cb), greeter);
586
if (ldm_greeter_get_can_restart (greeter))
588
menu_item = gtk_menu_item_new_with_label (_("Restart..."));
589
gtk_menu_shell_append (GTK_MENU_SHELL (power_menu), menu_item);
590
g_signal_connect (menu_item, "activate", G_CALLBACK (restart_cb), greeter);
593
if (ldm_greeter_get_can_shutdown (greeter))
595
menu_item = gtk_menu_item_new_with_label (_("Shutdown..."));
596
gtk_menu_shell_append (GTK_MENU_SHELL (power_menu), menu_item);
597
g_signal_connect (menu_item, "activate", G_CALLBACK (shutdown_cb), greeter);
600
if (n_power_items > 0)
602
menu_item = gtk_image_menu_item_new ();
603
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menu_item), TRUE);
604
gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menu_item), TRUE);
605
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));
606
gtk_menu_item_set_label (GTK_MENU_ITEM (menu_item), ""); // NOTE: Needed to make the icon show as selected
607
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), power_menu);
608
gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item);
611
gtk_widget_show_all (panel_window);
613
gtk_widget_get_allocation (panel_window, &allocation);
614
gtk_widget_set_size_request (GTK_WIDGET (panel_window), screen_width, allocation.height);
615
gtk_window_move (GTK_WINDOW (panel_window), 0, screen_height - allocation.height);
617
gtk_widget_grab_focus (user_view);