Trivial fixes.
[lxde/ldm-gtk-builder-greeter.git] / src / lightdm-gtk-builder-greeter.c
1 /*
2 * ldm-gtk-builder-greeter.c
3 *
4 * Copyright 2010 - 2012 PCMan <pcman.tw@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <lightdm-gobject-1/lightdm.h>
27 #include <gtk/gtk.h>
28 #include <glib/gi18n.h>
29 #include <glib/gstdio.h>
30 #include <time.h>
31 #include <signal.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34
35 #if GTK_CHECK_VERSION(3, 0, 0)
36 #define GREETER_UI_FILE "greeter-gtk3.ui"
37 #define GTK_CSS_FILE "gtk3.css"
38 #elif GTK_CHECK_VERSION(2, 0, 0)
39 #define GREETER_UI_FILE "greeter-gtk2.ui"
40 #define GTK_RC_FILE "gtk2.rc"
41 #endif
42
43 static char* test_dir = NULL;
44 static LightDMGreeter *greeter = NULL;
45 static char* theme_dir = NULL;
46
47 static GtkWidget* win = NULL;
48 static GtkWidget* prompt = NULL;
49 static GtkWidget* login_entry = NULL;
50
51 /* in the future, we'll support user list. */
52 static GtkWidget* user_list = NULL;
53
54 /* the user can use either a combobox or a button to select a session */
55 static GtkListStore* sessions_model = NULL;
56 static GtkWidget* sessions_combo = NULL;
57 static GtkWidget* sessions_btn = NULL;
58 GtkTreeIter selected_session_it = {0};
59
60 /* the user can use either a combobox or a button to select a language */
61 static GtkListStore* languages_model = NULL;
62 static GtkWidget* lang_combo = NULL;
63 static GtkWidget* lang_btn = NULL;
64 GtkTreeIter selected_language_it = {0};
65
66 /* exit button popups a menu with suspend, restart, shutdown options inside. */
67 static GtkWidget* exit_btn = NULL;
68 static GtkWidget* exit_menu = NULL;
69
70 /* or the theme authors can use the buttons directly */
71 static GtkWidget* suspend_btn = NULL;
72 static GtkWidget* hibernate_btn = NULL;
73 static GtkWidget* shutdown_btn = NULL;
74 static GtkWidget* restart_btn = NULL;
75
76 static GOptionEntry option_entries[] =
77 {
78 {"test-dir", 't', G_OPTION_FLAG_FILENAME, G_OPTION_ARG_FILENAME, &test_dir, "Test theme dir", "<dir>"},
79 {0}
80 };
81
82 static void select_language(const char *lang);
83 static void select_session(const char *session);
84
85 static void select_session(const char *session)
86 {
87 GtkTreeModel *model = GTK_TREE_MODEL(sessions_model);
88 GtkTreeIter iter;
89
90 if(!session)
91 session = lightdm_greeter_get_default_session_hint(greeter);
92
93 if(session && gtk_tree_model_get_iter_first(model, &iter))
94 {
95 do
96 {
97 char* key;
98 gtk_tree_model_get(model, &iter, 1, &key, -1);
99 if(g_strcmp0(key, session) == 0)
100 {
101 if(sessions_combo)
102 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(sessions_combo), &iter);
103 selected_session_it = iter;
104 g_free(key);
105 break;
106 }
107 g_free(key);
108 }
109 while (gtk_tree_model_iter_next(model, &iter));
110 }
111 g_debug("FIXME: select_session failed to find session named: %s", session);
112 }
113
114
115 static void on_show_message(LightDMGreeter *greeter, gchar* text,
116 LightDMMessageType type, gpointer user_data)
117 {
118 g_debug("message: %d: %s", type, text);
119 }
120
121 static void on_show_prompt(LightDMGreeter *greeter, gchar* text,
122 LightDMPromptType type, gpointer user_data)
123 {
124 const char* user_name;
125
126 gtk_label_set_text(GTK_LABEL(prompt), text);
127 gtk_entry_set_text(GTK_ENTRY(login_entry), "");
128 gtk_widget_set_sensitive(login_entry, TRUE);
129 gtk_widget_grab_focus(login_entry);
130
131 gtk_entry_set_visibility(GTK_ENTRY(login_entry),
132 type != LIGHTDM_PROMPT_TYPE_SECRET);
133
134 user_name = lightdm_greeter_get_authentication_user(greeter);
135 if(user_name) /* update UI for the user */
136 {
137 LightDMUser* user = lightdm_user_list_get_user_by_name(lightdm_user_list_get_instance(),
138 user_name);
139 select_session(user ? lightdm_user_get_session(user) : NULL);
140 select_language(user ? lightdm_user_get_language(user) : NULL);
141 }
142 }
143
144 static const char* get_selected_language()
145 {
146 if(selected_language_it.stamp != 0) /* valid */
147 {
148 LightDMLanguage* lang;
149 gtk_tree_model_get(languages_model, &selected_language_it, 1, &lang, -1);
150 if(lang)
151 g_object_unref(lang);
152 return lightdm_language_get_code(lang);
153 }
154 return NULL;
155 }
156
157 static void select_language(const char *lang)
158 {
159 GtkTreeModel* model = GTK_TREE_MODEL(languages_model);
160 GtkTreeIter iter;
161 if(lang && gtk_tree_model_get_iter_first(model, &iter))
162 {
163 do
164 {
165 LightDMLanguage *language;
166 gtk_tree_model_get(model, &iter, 1, &language, -1);
167 if(g_strcmp0(lightdm_language_get_code(language), lang) == 0)
168 {
169 if(lang_combo)
170 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(lang_combo), &iter);
171 selected_language_it = iter;
172 break;
173 }
174 }
175 while (gtk_tree_model_iter_next(model, &iter));
176 }
177 }
178
179 static void authenticate_user(const gchar *username)
180 {
181 LightDMUser *user;
182 user = lightdm_user_list_get_user_by_name(lightdm_user_list_get_instance(), username);
183 if(user)
184 select_session(lightdm_user_get_session(user));
185 else
186 select_session(NULL);
187 lightdm_greeter_authenticate(greeter, username);
188 }
189
190 static gchar *get_selected_session()
191 {
192 char* session = NULL;
193 if(selected_session_it.stamp != 0) /* valid iter */
194 gtk_tree_model_get(sessions_model, &selected_session_it, 1, &session, -1);
195 return session;
196 }
197
198 static void start_session(void)
199 {
200 gchar *session = get_selected_session();
201 const char* user_name = lightdm_greeter_get_authentication_user(greeter);
202 LightDMUser* user;
203 GError* err = NULL;
204 char* dmrc_path;
205 GKeyFile* dmrc;
206
207 #if 0
208 /* Older LightDM has no API for setting default session/language for users.
209 * However, its settings are loaded from ~/.dmrc.
210 * So let's write our values to ~/.dmrc.
211 * For details about .dmrc, see:
212 * http://library.gnome.org/admin/gdm/stable/configuration.html.en
213 * If LightDM supports this, we don't have to do the hack here. */
214
215 /* UPDATE: New LightDM seems to store the language settings via AccountService. */
216
217 user = lightdm_user_list_get_user_by_name(lightdm_user_list_get_instance(),
218 user_name);
219 dmrc = g_key_file_new();
220 dmrc_path = g_build_filename(lightdm_user_get_home_directory(user), ".dmrc", NULL);
221 g_key_file_load_from_file(dmrc, dmrc_path,
222 G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS,
223 NULL);
224 g_key_file_set_string(dmrc, "Desktop", "Language", language);
225 g_key_file_free(dmrc);
226 #endif
227
228 const char* language = get_selected_language();
229 lightdm_greeter_set_language(greeter, language); /* It's great that lightdm finally supports this. */
230
231 if(!lightdm_greeter_start_session_sync(greeter, session, &err))
232 {
233 // set_message_label (_("Failed to start session"));
234 g_error_free(err);
235 authenticate_user(lightdm_greeter_get_authentication_user(greeter));
236 }
237 g_free(session);
238 }
239
240 static void on_authentication_complete(LightDMGreeter *greeter, gpointer user_data)
241 {
242 gtk_entry_set_text(GTK_ENTRY(login_entry), "");
243
244 if(lightdm_greeter_get_is_authenticated(greeter))
245 {
246 start_session();
247 }
248 else /* login failed, ask for username again */
249 {
250 lightdm_greeter_authenticate(greeter, NULL);
251 }
252 }
253
254 static void on_autologin_timer_expired(LightDMGreeter *greeter, gpointer user_data)
255 {
256 if(lightdm_greeter_get_autologin_guest_hint(greeter))
257 lightdm_greeter_authenticate_as_guest(greeter);
258 else if (lightdm_greeter_get_autologin_user_hint(greeter))
259 authenticate_user(lightdm_greeter_get_autologin_user_hint(greeter));
260 }
261
262 static void on_screen_size_changed(GdkScreen* scr, GtkWindow* win)
263 {
264 gtk_window_resize( win, gdk_screen_get_width(scr), gdk_screen_get_height(scr) );
265 }
266
267 static gboolean on_combobox_entry_button_release(GtkWidget* w, GdkEventButton* evt, GtkComboBox* combo)
268 {
269 gboolean shown;
270 g_object_get(combo, "popup-shown", &shown, NULL);
271 if( shown )
272 gtk_combo_box_popdown(combo);
273 else
274 gtk_combo_box_popup(combo);
275 return FALSE;
276 }
277
278 static void init_combobox_entry(GtkWidget* combo)
279 {
280 GtkWidget* edit = gtk_bin_get_child(GTK_BIN(combo));
281 gtk_editable_set_editable( (GtkEditable*)edit, FALSE );
282 GTK_WIDGET_UNSET_FLAGS(edit, GTK_CAN_FOCUS);
283 g_signal_connect(edit, "button-release-event", G_CALLBACK(on_combobox_entry_button_release), combo);
284 }
285
286 static gboolean on_timeout(GtkLabel* label)
287 {
288 char buf[128];
289 time_t t;
290 struct tm* tmbuf;
291 time(&t);
292 tmbuf = localtime(&t);
293 /* TODO: make format of time configurable. */
294 strftime(buf, 128, "%c", tmbuf);
295 gtk_label_set_text(label, buf);
296 return TRUE;
297 }
298
299 static gboolean select_from_model(const char* title, const char* prompt_msg, GtkTreeModel* model, GtkTreeIter* selected_it)
300 {
301 gboolean ret = FALSE;
302 GtkBuilder* builder = gtk_builder_new();
303 if(gtk_builder_add_from_file(builder, PACKAGE_UI_DIR "/chooser.ui", NULL))
304 {
305 GtkDialog* dlg = GTK_DIALOG(gtk_builder_get_object(builder, "dlg"));
306 GtkLabel* message = GTK_LABEL(gtk_builder_get_object(builder, "message"));
307 GtkTreeView* view = GTK_TREE_VIEW(gtk_builder_get_object(builder, "view"));
308 GtkTreeSelection* tree_sel = gtk_tree_view_get_selection(view);
309
310 gtk_window_set_title(GTK_WINDOW(dlg), title);
311 gtk_label_set_text(message, prompt_msg);
312
313 gtk_tree_view_set_model(view, model);
314 gtk_tree_selection_set_mode(tree_sel, GTK_SELECTION_BROWSE);
315 gtk_tree_selection_select_iter(tree_sel, selected_it);
316
317 if(gtk_dialog_run(dlg) == GTK_RESPONSE_OK)
318 {
319 gtk_tree_selection_get_selected(tree_sel, NULL, selected_it);
320 ret = TRUE;
321 }
322 gtk_widget_destroy(GTK_WIDGET(dlg));
323 }
324 g_object_unref(builder);
325
326 /* focus the entry again */
327 if(login_entry)
328 gtk_widget_grab_focus(login_entry);
329 return ret;
330 }
331
332 static void on_sessions_btn_clicked(GtkButton* btn, gpointer user_data)
333 {
334 /* ask the user to select a desktop session */
335 if(select_from_model(_("Desktop Sessions"),
336 _("Select a desktop session:"),
337 GTK_TREE_MODEL(sessions_model), &selected_session_it))
338 {
339 gtk_combo_box_set_active_iter(sessions_combo, &selected_session_it);
340 }
341 }
342
343 static void on_languages_btn_clicked(GtkButton* btn, gpointer user_data)
344 {
345 /* ask the user to select a language */
346 if(select_from_model(_("Languages"),
347 _("Select a language:"),
348 GTK_TREE_MODEL(languages_model), &selected_language_it))
349 {
350 gtk_combo_box_set_active_iter(lang_combo, &selected_language_it);
351 }
352 }
353
354 static void on_sessions_combo_changed(GtkComboBox* combo, gpointer user_data)
355 {
356 gtk_combo_box_get_active_iter(combo, &selected_session_it);
357 }
358
359 static void on_languages_combo_changed(GtkComboBox* combo, gpointer user_data)
360 {
361 gtk_combo_box_get_active_iter(combo, &selected_language_it);
362 }
363
364 static void init_sessions(GtkBuilder* builder)
365 {
366 GtkTreeIter it;
367 const char* default_session = lightdm_greeter_get_default_session_hint(greeter);
368 const GList* sessions = lightdm_get_sessions();
369 const GList* l;
370 GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
371
372 for(l = sessions; l; l=l->next)
373 {
374 LightDMSession* session = LIGHTDM_SESSION(l->data);
375 const char* name = lightdm_session_get_name(session);
376 const char* key = lightdm_session_get_key(session);
377 gtk_list_store_insert_with_values(store, &it, -1,
378 0, name,
379 1, key, -1);
380 if(g_strcmp0(key, default_session) == 0)
381 selected_session_it = it;
382 }
383 sessions_model = store;
384
385 /* session selection combo box is used */
386 sessions_combo = (GtkWidget*)gtk_builder_get_object(builder, "sessions");
387 if(sessions_combo)
388 {
389 init_combobox_entry(sessions_combo);
390 g_signal_connect(sessions_combo, "changed", G_CALLBACK(on_sessions_combo_changed), NULL);
391
392 gtk_combo_box_set_model(GTK_COMBO_BOX(sessions_combo), GTK_TREE_MODEL(store));
393 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(sessions_combo), 0);
394 if(selected_session_it.stamp == 0) /* invalid */
395 gtk_tree_model_get_iter_first(sessions_model, &selected_session_it);
396 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(sessions_combo), &selected_session_it);
397 }
398
399 /* session selection button */
400 sessions_btn = (GtkWidget*)gtk_builder_get_object(builder, "sessions_btn");
401 if(sessions_btn)
402 g_signal_connect(sessions_btn, "clicked", G_CALLBACK(on_sessions_btn_clicked), NULL);
403 }
404
405 static void init_languages(GtkBuilder* builder)
406 {
407 GtkTreeIter it;
408 const LightDMLanguage* default_lang = lightdm_get_language();
409 const GList* langs = lightdm_get_languages();
410 const GList* l;
411 GtkListStore* list = gtk_list_store_new(2, G_TYPE_STRING, LIGHTDM_TYPE_LANGUAGE);
412 for(l = langs; l; l=l->next)
413 {
414 LightDMLanguage* lang = LIGHTDM_LANGUAGE(l->data);
415 const char* name = lightdm_language_get_name(lang);
416 const char* territory = lightdm_language_get_territory(lang);
417 const char* code = lightdm_language_get_code(lang);
418 char* title = g_strdup_printf("%s (%s)\t%s", name, territory, code);
419 gtk_list_store_insert_with_values(list, &it, -1, 0, title, 1, lang, -1);
420 g_free(title);
421 if(default_lang == lang)
422 selected_language_it = it;
423 }
424 languages_model = list;
425
426 lang_combo = (GtkWidget*)gtk_builder_get_object(builder, "lang");
427 if(lang_combo)
428 {
429 init_combobox_entry(lang_combo);
430 g_signal_connect(sessions_combo, "changed", G_CALLBACK(on_languages_combo_changed), NULL);
431
432 gtk_combo_box_set_model( GTK_COMBO_BOX(lang_combo), GTK_TREE_MODEL(list) );
433 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(lang_combo), 0);
434 if(selected_language_it.stamp == 0) /* invalid iter */
435 gtk_tree_model_get_iter_first(languages_model, &selected_language_it);
436 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(lang_combo), &selected_language_it);
437 }
438
439 lang_btn = (GtkWidget*)gtk_builder_get_object(builder, "lang_btn");
440 if(lang_btn)
441 g_signal_connect(lang_btn, "clicked", G_CALLBACK(on_languages_btn_clicked), NULL);
442 }
443
444 static void on_exit_btn_clicked(GtkButton* btn, GtkMenu* menu)
445 {
446 gtk_menu_popup(menu, NULL, NULL, NULL, btn, 1, gtk_get_current_event_time());
447 }
448
449 static void show_error(const char* title, const char* message)
450 {
451 GtkWidget* dlg = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, message);
452 gtk_window_set_title(GTK_WINDOW(dlg), title ? title:_("Error"));
453 gtk_dialog_run(GTK_DIALOG(dlg));
454 gtk_widget_destroy(dlg);
455 }
456
457 /* item can be a GtkButton or a GtkMenuItem */
458 static void on_suspend(GtkWidget* item, gpointer user_data)
459 {
460 GError* error = NULL;
461 if(!lightdm_suspend(&error))
462 {
463 show_error(NULL, error->message);
464 g_error_free(error);
465 }
466 }
467
468 /* item can be a GtkButton or a GtkMenuItem */
469 static void on_hibernate(GtkWidget* item, gpointer user_data)
470 {
471 GError* error = NULL;
472 if(!lightdm_hibernate(&error))
473 {
474 show_error(NULL, error->message);
475 g_error_free(error);
476 }
477 }
478
479 /* item can be a GtkButton or a GtkMenuItem */
480 static void on_restart(GtkWidget* item, gpointer user_data)
481 {
482 GError* error = NULL;
483 if(!lightdm_restart(&error))
484 {
485 show_error(NULL, error->message);
486 g_error_free(error);
487 }
488 }
489
490 /* item can be a GtkButton or a GtkMenuItem */
491 static void on_shutdown(GtkWidget* item, gpointer user_data)
492 {
493 GError* error = NULL;
494 if(!lightdm_shutdown(&error))
495 {
496 show_error(NULL, error->message);
497 g_error_free(error);
498 }
499 }
500
501 static void load_exit_buttons(GtkBuilder* builder)
502 {
503 exit_btn = GTK_WIDGET(gtk_builder_get_object(builder, "exit_btn"));
504
505 suspend_btn = GTK_WIDGET(gtk_builder_get_object(builder, "suspend_btn"));
506 hibernate_btn = GTK_WIDGET(gtk_builder_get_object(builder, "hibernate_btn"));
507 shutdown_btn = GTK_WIDGET(gtk_builder_get_object(builder, "shutdown_btn"));
508 restart_btn = GTK_WIDGET(gtk_builder_get_object(builder, "restart_btn"));
509
510 if(exit_btn)
511 {
512 GtkWidget* menu = gtk_menu_new();
513 GtkWidget* item;
514 if(lightdm_get_can_suspend())
515 {
516 item = gtk_menu_item_new_with_label(_("Suspend"));
517 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
518 g_signal_connect(item, "activate", G_CALLBACK(on_suspend), NULL);
519 }
520 if(lightdm_get_can_hibernate())
521 {
522 item = gtk_menu_item_new_with_label(_("Hibernate"));
523 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
524 g_signal_connect(item, "activate", G_CALLBACK(on_hibernate), NULL);
525 }
526 if(lightdm_get_can_restart())
527 {
528 item = gtk_menu_item_new_with_label(_("Restart"));
529 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
530 g_signal_connect(item, "activate", G_CALLBACK(on_restart), NULL);
531 }
532 if(lightdm_get_can_shutdown())
533 {
534 item = gtk_menu_item_new_with_label(_("Shutdown"));
535 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
536 g_signal_connect(item, "activate", G_CALLBACK(on_shutdown), NULL);
537 }
538 gtk_widget_show_all(menu);
539 g_signal_connect_swapped(exit_btn, "destroy", G_CALLBACK(gtk_widget_destroy), menu);
540 g_signal_connect(exit_btn, "clicked", G_CALLBACK(on_exit_btn_clicked), menu);
541 }
542
543 if(suspend_btn)
544 g_signal_connect(suspend_btn, "clicked", G_CALLBACK(on_suspend), NULL);
545 if(hibernate_btn)
546 g_signal_connect(hibernate_btn, "clicked", G_CALLBACK(on_hibernate), NULL);
547 if(shutdown_btn)
548 g_signal_connect(shutdown_btn, "clicked", G_CALLBACK(on_shutdown), NULL);
549 if(restart_btn)
550 g_signal_connect(restart_btn, "clicked", G_CALLBACK(on_restart), NULL);
551 }
552
553 static void on_login_entry_activate(GtkEntry* entry, gpointer user_data)
554 {
555 gtk_widget_set_sensitive(GTK_WIDGET(entry), FALSE);
556 // set_message_label ("");
557
558 if(G_LIKELY(lightdm_greeter_get_in_authentication(greeter)))
559 lightdm_greeter_respond(greeter, gtk_entry_get_text(entry));
560 }
561
562 static gboolean show_ui()
563 {
564 GError* err = NULL;
565 GdkScreen* scr;
566 GtkWidget* w;
567 GdkCursor* cursor;
568 GSList* objects, *l;
569
570 /* we don't want to use the theme mechanism provided by lightdm. */
571 GtkBuilder* builder = gtk_builder_new();
572 char* file = g_build_filename(theme_dir, GREETER_UI_FILE, NULL);
573
574 if(!gtk_builder_add_from_file(builder, file, &err))
575 {
576 g_debug("%s", err->message);
577 return FALSE;
578 }
579
580 /* set widget names for theming */
581 objects = gtk_builder_get_objects(builder);
582 for(l = objects; l; l=l->next)
583 {
584 if(GTK_IS_WIDGET(l->data))
585 {
586 GtkWidget* widget = (GtkWidget*)l->data;
587 gtk_widget_set_name(widget,
588 gtk_buildable_get_name(GTK_BUILDABLE(widget)));
589 }
590 }
591 g_slist_free(objects);
592
593 win = GTK_WIDGET (gtk_builder_get_object(builder, "win"));
594 scr = gtk_widget_get_screen(win);
595 g_signal_connect(scr, "size-changed", G_CALLBACK(on_screen_size_changed), win);
596
597 prompt = (GtkWidget*)gtk_builder_get_object(builder, "prompt");
598 login_entry = (GtkWidget*)gtk_builder_get_object(builder, "login_entry");
599 g_signal_connect(login_entry, "activate", G_CALLBACK(on_login_entry_activate), NULL);
600 #if 0
601 user_list = (GtkWidget*)gtk_builder_get_object(builder, "user_list");
602
603 if(user_list)
604 {
605 /* the user select a username from the list */
606 if(GTK_IS_VBOX(user_list))
607 load_user_list();
608 else
609 g_error("Bug: user_list should be a GtkVBox object");
610
611 }
612 else if(login_entry)
613 {
614 /* the user type username and password manually */
615 g_signal_connect(login_entry, "activate", G_CALLBACK(on_entry_activate), NULL);
616 }
617 #endif
618
619 init_sessions(builder);
620 init_languages(builder);
621
622 if( w = (GtkWidget*)gtk_builder_get_object(builder, "time") )
623 {
624 guint timeout = g_timeout_add(1000, (GSourceFunc)on_timeout, w);
625 g_signal_connect_swapped(w, "destroy",
626 G_CALLBACK(g_source_remove), GUINT_TO_POINTER(timeout));
627 on_timeout((GtkLabel*)w);
628 }
629
630 /* load "Exit", "Shutdown", "Reboot",...etc. */
631 load_exit_buttons(builder);
632
633 g_object_unref(builder);
634
635 gtk_window_set_decorated(GTK_WINDOW(win), FALSE);
636 gtk_window_set_default_size(GTK_WINDOW(win),
637 gdk_screen_get_width(scr),
638 gdk_screen_get_height(scr) );
639 #if GTK_CHECK_VERSION(3, 0, 0)
640 gtk_window_set_has_resize_grip(GTK_WINDOW(win), FALSE);
641 #endif
642 gtk_window_fullscreen(GTK_WINDOW(win));
643
644 gtk_window_present( GTK_WINDOW(win) );
645
646 cursor = gdk_cursor_new(GDK_LEFT_PTR);
647 gdk_window_set_cursor(gdk_screen_get_root_window(scr), cursor);
648 gdk_cursor_unref(cursor);
649
650 return TRUE;
651 }
652
653 static void on_sigterm(int sig)
654 {
655 exit(0);
656 }
657
658 int main(int argc, char** argv)
659 {
660 GError* err = NULL;
661 GKeyFile* kf;
662 char* greeter_theme_name;
663 char* widget_theme_name;
664
665 /* gettext support */
666 #ifdef ENABLE_NLS
667 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
668 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
669 textdomain ( GETTEXT_PACKAGE );
670 #endif
671
672 /* initialize GTK+ and parse the command line arguments */
673 if(G_UNLIKELY(!gtk_init_with_args(&argc, &argv, "", option_entries, GETTEXT_PACKAGE, &err)))
674 {
675 g_print( "Error: %s\n", err->message );
676 return 1;
677 }
678
679 signal(SIGTERM, on_sigterm);
680
681 greeter = lightdm_greeter_new();
682 g_signal_connect(greeter, "show-prompt", G_CALLBACK(on_show_prompt), NULL);
683 g_signal_connect(greeter, "show-message", G_CALLBACK(on_show_message), NULL);
684 g_signal_connect(greeter, "authentication-complete", G_CALLBACK(on_authentication_complete), NULL);
685 g_signal_connect(greeter, "autologin-timer-expired", G_CALLBACK(on_autologin_timer_expired), NULL);
686
687 if(!test_dir && !lightdm_greeter_connect_sync(greeter, NULL))
688 {
689 g_print("Error: unable to connect to lightdm deamon.\n");
690 return 1;
691 }
692
693 /* load global greeter config */
694 kf = g_key_file_new();
695 if(g_key_file_load_from_file(kf, CONFIG_DIR "/lightdm-gtk-builder-greeter.conf",
696 0, NULL))
697 {
698 greeter_theme_name = g_key_file_get_string(kf, "greeter", "theme", NULL);
699 widget_theme_name = g_key_file_get_string(kf, "greeter", "gtk_theme", NULL);
700 if(widget_theme_name)
701 {
702 /* FIXME: shouldn't this be set in gtkrc instead? */
703 g_object_set(gtk_settings_get_default(), "gtk-theme-name",
704 widget_theme_name, NULL);
705 g_free(widget_theme_name);
706 }
707 }
708 else
709 greeter_theme_name = g_strdup("default");
710
711 g_key_file_free(kf);
712
713 /* Set default cursor */
714 gdk_window_set_cursor (gdk_get_default_root_window(), gdk_cursor_new(GDK_LEFT_PTR));
715
716 if(test_dir)
717 {
718 g_free(theme_dir);
719 theme_dir = test_dir;
720 }
721 else
722 {
723 theme_dir = g_build_filename(PACKAGE_DATA_DIR "/themes",
724 greeter_theme_name, NULL);
725 }
726
727 #if GTK_CHECK_VERSION(3, 0, 0)
728 /* NOTE: this piece of code is not yet tested */
729 char* gtkcss = g_build_filename(theme_dir, GTK_CSS_FILE, NULL);
730 GtkCssProvider *css = gtk_css_provider_new();
731 gtk_css_provider_load_from_path(css, gtkcss, NULL);
732 g_free(gtkcss);
733 gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
734 GTK_STYLE_PROVIDER(css),
735 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
736 g_object_unref(css);
737 #else
738 /* GTK+ 2.x */
739 char* gtkrc = g_build_filename(theme_dir, GTK_RC_FILE, NULL);
740 gtk_rc_parse(gtkrc);
741 g_free(gtkrc);
742 #endif
743
744 /* create GUI */
745 if(!show_ui())
746 return 1;
747
748 /* FIXME: should we honor this config value and show a user list if it's FALSE?
749 * IMO, whether to show user list or not is theme specific.
750 * For now, we do not support user list. */
751 /* if (lightdm_greeter_get_hide_users_hint (greeter)) */
752 if(!test_dir)
753 lightdm_greeter_authenticate(greeter, NULL);
754
755 gtk_main();
756
757 g_object_unref(greeter);
758
759 return 0;
760 }