Imported Upstream version 0.2.0
[debian/lxdm.git] / src / greeter.c
1 /*
2 * lxdm-ui.c
3 *
4 * Copyright 2009 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 <gtk/gtk.h>
27 #include <gdk/gdkx.h>
28 #include <glib/gi18n.h>
29
30 #include "lang.h"
31 #include <time.h>
32
33 enum {
34 COL_SESSION_NAME,
35 COL_SESSION_EXEC,
36 COL_SESSION_DESKTOP_FILE,
37 N_SESSION_COLS
38 };
39
40 enum {
41 COL_LANG_DISPNAME,
42 COL_LANG,
43 N_LANG_COLS
44 };
45
46 #ifndef VCONFIG_FILE
47 #define VCONFIG_FILE "/etc/lxdm/lxdm.conf"
48 #endif
49
50 static gboolean config_changed = FALSE;
51 static GKeyFile *config;
52 static GKeyFile * var_config;
53 static GtkWidget* win;
54 static GtkWidget* prompt;
55 static GtkWidget* login_entry;
56 static GtkWidget* prompt;
57
58 static GtkWidget* sessions;
59 static GtkWidget* lang;
60
61 static GtkWidget* exit;
62
63 static GtkWidget* exit_menu;
64 static GtkWidget *lang_menu;
65
66 static char* user = NULL;
67 static char* pass = NULL;
68 static char* session_exec = NULL;
69 static char* session_desktop_file = NULL;
70
71 static char* ui_file = NULL;
72
73 static GdkPixbuf *bg_img = NULL;
74 static GdkColor bg_color = {0};
75
76 static GIOChannel *greeter_io;
77
78 static void do_reboot(void)
79 {
80 printf("reboot\n");
81 }
82
83 static void do_shutdown(void)
84 {
85 printf("shutdown\n");
86 }
87
88 static void on_screen_size_changed(GdkScreen* scr, GtkWindow* win)
89 {
90 gtk_window_resize( win, gdk_screen_get_width(scr), gdk_screen_get_height(scr) );
91 }
92
93 static void on_entry_activate(GtkEntry* entry, gpointer user_data)
94 {
95 char* tmp;
96 if( !user )
97 {
98 user = g_strdup( gtk_entry_get_text( GTK_ENTRY(entry) ) );
99 gtk_entry_set_text(GTK_ENTRY(entry), "");
100 gtk_label_set_text( GTK_LABEL(prompt), _("Password:") );
101 if( strchr(user, ' ') )
102 {
103 g_free(user);
104 user = NULL;
105 return;
106 }
107 gtk_entry_set_visibility(entry, FALSE);
108 }
109 else
110 {
111 GtkTreeIter it;
112 char *session_lang = "";
113
114 if( gtk_combo_box_get_active_iter(GTK_COMBO_BOX(sessions), &it) )
115 {
116 GtkTreeModel* model = gtk_combo_box_get_model( GTK_COMBO_BOX(sessions) );
117 gtk_tree_model_get(model, &it, 1, &session_exec, 2, &session_desktop_file, -1);
118 }
119 else
120 {
121 /* FIXME: fatal error */
122 }
123
124 pass = g_strdup( gtk_entry_get_text(entry) );
125 if( strchr(pass, ' ') )
126 {
127 g_free(user); user = NULL;
128 g_free(pass); pass = NULL;
129 gtk_label_set_text( GTK_LABEL(prompt), _("User:") );
130 gtk_entry_set_text(GTK_ENTRY(entry), "");
131 gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE);
132 return;
133 }
134
135 if( lang && gtk_combo_box_get_active_iter(GTK_COMBO_BOX(lang), &it) )
136 {
137 GtkTreeModel* model = gtk_combo_box_get_model( GTK_COMBO_BOX(lang) );
138 gtk_tree_model_get(model, &it, 1, &session_lang, -1);
139 //FIXME: is session leaked?
140 }
141
142 tmp = g_key_file_get_string(var_config, "base", "last_session", NULL);
143 if( g_strcmp0(tmp, session_desktop_file) )
144 {
145 g_key_file_set_string(var_config, "base", "last_session", session_desktop_file);
146 config_changed = TRUE;
147 }
148 g_free(tmp);
149
150 tmp = g_key_file_get_string(var_config, "base", "last_lang", NULL);
151 if( g_strcmp0(tmp, session_lang) )
152 {
153 g_key_file_set_string(var_config, "base", "last_lang", session_lang);
154 config_changed = TRUE;
155 }
156 g_free(tmp);
157
158 printf("login user=%s pass=%s session=%s lang=%s\n",
159 user, pass, session_exec, session_lang);
160
161 /* password check failed */
162 g_free(user);
163 user = NULL;
164 g_free(pass);
165 pass = NULL;
166
167 gtk_widget_hide(prompt);
168 gtk_widget_hide( GTK_WIDGET(entry) );
169
170 gtk_label_set_text( GTK_LABEL(prompt), _("User:") );
171 gtk_entry_set_text(GTK_ENTRY(entry), "");
172 gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE);
173 }
174 }
175
176 static void load_sessions()
177 {
178 GtkListStore* list;
179 GtkTreeIter it, active_it = {0};
180 char* last;
181 char *path, *file_name, *name, *exec;
182 GKeyFile* kf;
183 GDir* dir = g_dir_open(XSESSIONS_DIR, 0, NULL);
184 if( !dir )
185 return;
186
187 last = g_key_file_get_string(var_config, "base", "last_session", NULL);
188
189 list = gtk_list_store_new(N_SESSION_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
190 kf = g_key_file_new();
191 while( ( file_name = (char*)g_dir_read_name(dir) ) != NULL )
192 {
193 path = g_build_filename(XSESSIONS_DIR, file_name, NULL);
194 if( g_key_file_load_from_file(kf, path, 0, NULL) )
195 {
196 name = g_key_file_get_locale_string(kf, "Desktop Entry", "Name", NULL, NULL);
197 //exec = g_key_file_get_string(kf, "Desktop Entry", "Exec", NULL);
198 exec=g_strdup(path);
199
200 if( !strcmp(name, "LXDE") )
201 gtk_list_store_prepend(list, &it);
202 else
203 gtk_list_store_append(list, &it);
204 gtk_list_store_set(list, &it,
205 COL_SESSION_NAME, name,
206 COL_SESSION_EXEC, exec,
207 COL_SESSION_DESKTOP_FILE, file_name, -1);
208
209 if( last && g_strcmp0(file_name, last) == 0 )
210 active_it = it;
211
212 g_free(name);
213 g_free(exec);
214 }
215 g_free(path);
216 }
217 g_dir_close(dir);
218 g_key_file_free(kf);
219
220 gtk_list_store_prepend(list, &it);
221 gtk_list_store_set(list, &it,
222 COL_SESSION_NAME, _("Default"),
223 COL_SESSION_EXEC, "",
224 COL_SESSION_DESKTOP_FILE, "__default__", -1);
225 if( last && g_strcmp0(file_name, last) == 0 )
226 active_it = it;
227
228 g_free(last);
229 gtk_combo_box_set_model( GTK_COMBO_BOX(sessions), GTK_TREE_MODEL(list) );
230 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(sessions), 0);
231 if( active_it.stamp )
232 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(sessions), &active_it);
233 else
234 gtk_combo_box_set_active(GTK_COMBO_BOX(sessions), 0);
235
236 g_object_unref(list);
237 }
238
239 static void load_lang_cb(void *arg, char *lang, char *desc)
240 {
241 GtkListStore* list = (GtkListStore*)arg;
242 GtkTreeIter it;
243 gchar *temp,*p,*lang2;
244
245 lang2=g_strdup(lang);
246 p=strchr(lang2,'.');
247 if(p) *p=0;
248
249 //temp=g_strdup_printf("\xe2\x80\x8e%s\t\t\xe2\x80\xab%s",lang,desc);
250 if(lang2[0] && lang2[0]!='~')
251 temp=g_strdup_printf("%s\t%s",lang2,desc?desc:"");
252 else
253 temp=g_strdup(desc);
254 g_free(lang2);
255 gtk_list_store_append(list, &it);
256 gtk_list_store_set(list, &it,
257 COL_LANG_DISPNAME, temp,
258 COL_LANG, lang, -1);
259 g_free(temp);
260 }
261
262 static gint lang_cmpr(GtkTreeModel *list,GtkTreeIter *a,GtkTreeIter *b,gpointer user_data)
263 {
264 gint ret;
265 gchar *as,*bs;
266 gtk_tree_model_get(list,a,1,&as,-1);
267 gtk_tree_model_get(list,b,1,&bs,-1);
268 ret=strcmp(as,bs);
269 g_free(as);g_free(bs);
270 return ret;
271 }
272
273 static void on_menu_lang_select(GtkMenuItem *item,gpointer user_data)
274 {
275 GtkTreeIter iter;
276 char *sel=(char*)user_data;
277 int i;
278 gboolean res;
279 GtkTreeModel *list;
280 int active=-1;
281 char *temp;
282 GPtrArray *array;
283 if(!sel || !sel[0]) return;
284
285 list=gtk_combo_box_get_model(GTK_COMBO_BOX(lang));
286 res=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list),&iter);
287 for(i=0;res==TRUE;i++)
288 {
289 gtk_tree_model_get(GTK_TREE_MODEL(list),&iter,1,&temp,-1);
290 if(!strcmp(temp,sel))
291 {
292 g_free(temp);
293 active=i;
294 break;
295 }
296 g_free(temp);
297 res=gtk_tree_model_iter_next(GTK_TREE_MODEL(list),&iter);
298 }
299 if(active>=0)
300 {
301 gtk_combo_box_set_active(GTK_COMBO_BOX(lang),active);
302 return;
303 }
304 gtk_list_store_append((GtkListStore*)list, &iter);
305 temp=(char*)gtk_menu_item_get_label(item);
306 gtk_list_store_set((GtkListStore*)list, &iter,
307 COL_LANG_DISPNAME, temp,
308 COL_LANG, sel, -1);
309 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(lang),&iter);
310
311 array=g_ptr_array_new();
312 res=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list),&iter);
313 while(res==TRUE)
314 {
315 gtk_tree_model_get(GTK_TREE_MODEL(list),&iter,1,&temp,-1);
316 if(!temp || !temp[0] || temp[0]=='~')
317 {
318 g_free(temp);
319 }
320 else
321 {
322 g_ptr_array_add(array,temp);
323 }
324 res=gtk_tree_model_iter_next(GTK_TREE_MODEL(list),&iter);
325 }
326 g_key_file_set_string_list(var_config,"base","last_langs",(void*)array->pdata,array->len);
327 config_changed=TRUE;
328 g_ptr_array_foreach(array,(GFunc)g_free,0);
329 g_ptr_array_free(array,TRUE);
330 }
331
332 static void load_menu_lang_cb(void *arg, char *lang, char *desc)
333 {
334 GtkWidget *menu=GTK_WIDGET(arg);
335 GtkWidget* item;
336
337 gchar *temp,*p,*lang2;
338
339 lang2=g_strdup(lang);
340 p=strchr(lang2,'.');
341 if(p) *p=0;
342
343 if(lang2[0] && lang2[0]!='~')
344 temp=g_strdup_printf("%s\t%s",lang2,desc?desc:"");
345 else
346 temp=g_strdup(desc);
347 g_free(lang2);
348
349 item = gtk_menu_item_new_with_label(temp);
350 g_signal_connect(item, "activate", G_CALLBACK(on_menu_lang_select), g_strdup(lang));
351 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
352 g_free(temp);
353 }
354
355 static void show_all_languages(void)
356 {
357 if(!lang_menu)
358 {
359 lang_menu=gtk_menu_new();
360 lxdm_load_langs(var_config,TRUE,lang_menu,load_menu_lang_cb);
361 gtk_widget_show_all(lang_menu);
362 }
363 gtk_menu_popup(GTK_MENU(lang_menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time());
364 }
365
366 static void on_lang_changed(GtkComboBox *widget)
367 {
368 GtkTreeIter it;
369 if( gtk_combo_box_get_active_iter(widget, &it) )
370 {
371 GtkListStore *list=(GtkListStore*)gtk_combo_box_get_model(GTK_COMBO_BOX(lang));
372 char *lang=NULL;
373 gtk_tree_model_get(GTK_TREE_MODEL(list), &it, 1, &lang, -1);
374 if(lang[0]=='~')
375 {
376 gtk_combo_box_set_active(widget,0);
377 show_all_languages();
378 }
379 g_free(lang);
380 }
381 else
382 {
383 return;
384 }
385
386 }
387
388 static void load_langs()
389 {
390 GtkListStore* list;
391 char* lang_str;
392 int active = 0;
393
394 list = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
395 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(list),0,GTK_SORT_ASCENDING);
396 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list),0,lang_cmpr,NULL,NULL);
397 lxdm_load_langs(var_config,FALSE,list, load_lang_cb);
398 lang_str = g_key_file_get_string(var_config, "base", "last_lang", NULL);
399 if(lang_str && lang_str[0])
400 {
401 gboolean res;
402 GtkTreeIter iter;
403 int i;
404 res=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list),&iter);
405 if(res) for(i=0;;i++)
406 {
407 gchar *lang;
408 gtk_tree_model_get(GTK_TREE_MODEL(list),&iter,1,&lang,-1);
409 if(!strcmp(lang,lang_str))
410 {
411 g_free(lang);
412 active=i;
413 break;
414 }
415 g_free(lang);
416 res=gtk_tree_model_iter_next(GTK_TREE_MODEL(list),&iter);
417 if(!res) break;
418 }
419 }
420 g_free(lang_str);
421 gtk_combo_box_set_model( GTK_COMBO_BOX(lang), GTK_TREE_MODEL(list) );
422 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(lang), 0);
423 gtk_combo_box_set_active(GTK_COMBO_BOX(lang), active < 0 ? 0 : active);
424 g_object_unref(list);
425
426 g_signal_connect(G_OBJECT(lang),"changed",G_CALLBACK(on_lang_changed),NULL);
427 }
428
429 static void on_exit_clicked(GtkButton* exit_btn, gpointer user_data)
430 {
431 gtk_menu_popup( GTK_MENU(exit_menu), NULL, NULL, NULL, NULL,
432 0, gtk_get_current_event_time() );
433 }
434
435 static void load_exit()
436 {
437 GtkWidget* item;
438 exit_menu = gtk_menu_new();
439 item = gtk_image_menu_item_new_with_mnemonic( _("_Reboot") );
440 g_signal_connect(item, "activate", G_CALLBACK(do_reboot), NULL);
441 gtk_menu_shell_append(GTK_MENU_SHELL(exit_menu), item);
442
443 item = gtk_image_menu_item_new_with_mnemonic( _("_Shutdown") );
444 g_signal_connect(item, "activate", G_CALLBACK(do_shutdown), NULL);
445 gtk_menu_shell_append(GTK_MENU_SHELL(exit_menu), item);
446
447 gtk_widget_show_all(exit_menu);
448 g_signal_connect(exit, "clicked", G_CALLBACK(on_exit_clicked), NULL);
449 }
450
451 static gboolean on_expose(GtkWidget* widget, GdkEventExpose* evt, gpointer user_data)
452 {
453 cairo_t *cr;
454
455 if( !GTK_WIDGET_REALIZED(widget) )
456 return FALSE;
457 cr = gdk_cairo_create(widget->window);
458 if( bg_img )
459 {
460 cairo_matrix_t matrix;
461 double x = -0.5, y = -0.5, sx, sy;
462 cairo_get_matrix(cr, &matrix);
463 sx = (double)gdk_screen_width() / (double)gdk_pixbuf_get_width(bg_img);
464 sy = (double)gdk_screen_height() / (double)gdk_pixbuf_get_height(bg_img);
465 cairo_scale(cr, sx, sy);
466 gdk_cairo_set_source_pixbuf(cr, bg_img, x, y);
467 cairo_paint(cr);
468 cairo_set_matrix(cr, &matrix);
469 }
470 else
471 {
472 gdk_cairo_set_source_color(cr, &bg_color);
473 cairo_rectangle( cr, 0, 0, gdk_screen_width(), gdk_screen_height() );
474 cairo_fill(cr);
475 }
476 cairo_destroy(cr);
477 return FALSE;
478 }
479
480 static gboolean on_combobox_entry_button_release(GtkWidget* w, GdkEventButton* evt, GtkComboBox* combo)
481 {
482 gboolean shown;
483 g_object_get(combo, "popup-shown", &shown, NULL);
484 if( shown )
485 gtk_combo_box_popdown(combo);
486 else
487 gtk_combo_box_popup(combo);
488 return FALSE;
489 }
490
491 static void fix_combobox_entry(GtkWidget* combo)
492 {
493 GtkWidget* edit = gtk_bin_get_child(GTK_BIN(combo));
494 gtk_editable_set_editable( (GtkEditable*)edit, FALSE );
495 GTK_WIDGET_UNSET_FLAGS(edit, GTK_CAN_FOCUS);
496 g_signal_connect(edit, "button-release-event", G_CALLBACK(on_combobox_entry_button_release), combo);
497 }
498
499 static void on_evt_box_expose(GtkWidget* widget, GdkEventExpose* evt, gpointer user_data)
500 {
501 if (GTK_WIDGET_DRAWABLE (widget))
502 {
503 GtkWidgetClass* klass = (GtkWidgetClass*)G_OBJECT_GET_CLASS(widget);
504 gtk_paint_flat_box (widget->style, widget->window,
505 widget->state, GTK_SHADOW_NONE,
506 &evt->area, widget, "eventbox",
507 0, 0, -1, -1);
508 klass->expose_event (widget, evt);
509 }
510 }
511
512 static gboolean on_timeout(GtkLabel* label)
513 {
514 char buf[128];
515 time_t t;
516 struct tm* tmbuf;
517 time(&t);
518 tmbuf = localtime(&t);
519 strftime(buf, 128, "%c", tmbuf);
520 gtk_label_set_text(label, buf);
521 return TRUE;
522 }
523
524 static void create_win()
525 {
526 GtkBuilder* builder;
527 GdkScreen* scr;
528 GSList* objs, *l;
529 GtkWidget* w;
530
531 builder = gtk_builder_new();
532 gtk_builder_add_from_file(builder, ui_file ? ui_file : LXDM_DATA_DIR "/lxdm.glade", NULL);
533 win = (GtkWidget*)gtk_builder_get_object(builder, "lxdm");
534
535 /* set widget names according to their object id in GtkBuilder xml */
536 objs = gtk_builder_get_objects(builder);
537 for( l = objs; l; l = l->next )
538 {
539 GtkWidget* widget = (GtkWidget*)l->data;
540 gtk_widget_set_name( widget, gtk_buildable_get_name( (GtkBuildable*)widget ) );
541 char* path;
542 gtk_widget_path(widget, NULL, &path, NULL);
543 }
544 g_slist_free(objs);
545
546 if( bg_img ) /* only paint our own background if custom background image is set. */
547 {
548 GTK_WIDGET_SET_FLAGS(win, GTK_APP_PAINTABLE);
549 g_signal_connect(win, "expose-event", G_CALLBACK(on_expose), NULL);
550 } /* otherwise, let gtk theme paint it. */
551
552 scr = gtk_widget_get_screen(win);
553 g_signal_connect(scr, "size-changed", G_CALLBACK(on_screen_size_changed), win);
554
555 prompt = (GtkWidget*)gtk_builder_get_object(builder, "prompt");
556 login_entry = (GtkWidget*)gtk_builder_get_object(builder, "login_entry");
557
558 g_signal_connect(login_entry, "activate", G_CALLBACK(on_entry_activate), NULL);
559
560 sessions = (GtkWidget*)gtk_builder_get_object(builder, "sessions");
561 gtk_widget_set_name(sessions, "sessions");
562 fix_combobox_entry(sessions);
563 load_sessions();
564
565 w = (GtkWidget*)gtk_builder_get_object(builder, "bottom_pane");
566 if( g_key_file_get_integer(config, "display", "bottom_pane", 0) )
567 {
568 /* hacks to let GtkEventBox paintable with gtk pixmap engine. */
569 if(GTK_WIDGET_APP_PAINTABLE(w))
570 g_signal_connect(w, "expose-event", G_CALLBACK(on_evt_box_expose), NULL);
571 }
572 else
573 gtk_event_box_set_visible_window(GTK_EVENT_BOX(w), FALSE);
574
575 if( g_key_file_get_integer(config, "display", "lang", 0) == 0 )
576 {
577 GtkWidget *w;
578 w = (GtkWidget*)gtk_builder_get_object(builder, "lang_box");
579 if( w )
580 gtk_widget_hide(w);
581 }
582 else
583 {
584 lang = (GtkWidget*)gtk_builder_get_object(builder, "lang");
585 gtk_widget_set_name(lang, "lang");
586 fix_combobox_entry(lang);
587 load_langs();
588 }
589
590 if( (w = (GtkWidget*)gtk_builder_get_object(builder, "time"))!=NULL )
591 {
592 guint timeout = g_timeout_add(1000, (GSourceFunc)on_timeout, w);
593 g_signal_connect_swapped(w, "destroy",
594 G_CALLBACK(g_source_remove), GUINT_TO_POINTER(timeout));
595 on_timeout((GtkLabel*)w);
596 }
597
598 exit = (GtkWidget*)gtk_builder_get_object(builder, "exit");
599 load_exit();
600
601 g_object_unref(builder);
602
603 gtk_window_set_default_size( GTK_WINDOW(win), gdk_screen_get_width(scr), gdk_screen_get_height(scr) );
604 gtk_window_present( GTK_WINDOW(win) );
605 gtk_widget_realize(login_entry);
606 //gdk_keyboard_grab(login_entry->window,FALSE,GDK_CURRENT_TIME);
607 gtk_widget_grab_focus(login_entry);
608 }
609
610 int set_background(void)
611 {
612 char *bg;
613 char *style;
614 GdkWindow* root = gdk_get_default_root_window();
615 GdkCursor* cursor = gdk_cursor_new(GDK_LEFT_PTR);
616
617 gdk_window_set_cursor(root, cursor);
618
619 bg = g_key_file_get_string(config, "display", "bg", 0);
620 if( !bg )
621 bg = g_strdup("#222E45");
622 style = g_key_file_get_string(config, "display", "bg_style", 0);
623
624 if( bg )
625 {
626 if( bg[0] != '#' )
627 {
628 /* default the bg stretch */
629 if(!style || strcmp(style, "stretch") == 0 )
630 {
631 GdkPixbuf *tmp=gdk_pixbuf_new_from_file(bg,0);
632 if(tmp)
633 {
634 bg_img=gdk_pixbuf_scale_simple(tmp,
635 gdk_screen_width(),
636 gdk_screen_height(),
637 GDK_INTERP_HYPER);
638 g_object_unref(tmp);
639 }
640 }
641 else
642 {
643 bg_img = gdk_pixbuf_new_from_file(bg, 0);
644 }
645 if( !bg_img )
646 {
647 g_free(bg);
648 bg = g_strdup("#222E45");
649 }
650 }
651 if( bg[0] == '#' )
652 gdk_color_parse(bg, &bg_color);
653 }
654 //gdk_window_set_background(win,&screen);
655 g_free(bg);
656 g_free(style);
657 return 0;
658 }
659
660 static gboolean on_lxdm_command(GIOChannel *source, GIOCondition condition, gpointer data)
661 {
662 GIOStatus ret;
663 char *str;
664
665 if( !(G_IO_IN & condition) )
666 return FALSE;
667 ret = g_io_channel_read_line(source, &str, NULL, NULL, NULL);
668 if( ret != G_IO_STATUS_NORMAL )
669 return FALSE;
670
671 if( !strncmp(str, "quit", 4) || !strncmp(str, "exit",4))
672 gtk_main_quit();
673 else if( !strncmp(str, "reset", 5) )
674 {
675 gtk_widget_show(prompt);
676 gtk_widget_show(login_entry);
677 gtk_widget_grab_focus(login_entry);
678 }
679 g_free(str);
680 return TRUE;
681 }
682
683 void listen_stdin(void)
684 {
685 greeter_io = g_io_channel_unix_new(0);
686 g_io_add_watch(greeter_io, G_IO_IN, on_lxdm_command, NULL);
687 }
688
689 void set_root_background(void)
690 {
691 GdkWindow *root = gdk_get_default_root_window();
692
693 /* set background */
694 if( !bg_img )
695 {
696 GdkColormap *map = (GdkColormap*)gdk_window_get_colormap(root);
697 gdk_color_alloc(map, &bg_color);
698 gdk_window_set_background(root, &bg_color);
699 }
700 else
701 {
702 GdkPixmap *pix = NULL;
703 gdk_pixbuf_render_pixmap_and_mask(bg_img, &pix, NULL, 0);
704 /* call x directly, because gdk will ref the pixmap */
705 //gdk_window_set_back_pixmap(root,pix,FALSE);
706 XSetWindowBackgroundPixmap( GDK_WINDOW_XDISPLAY(root),
707 GDK_WINDOW_XID(root), GDK_PIXMAP_XID(pix) );
708 g_object_unref(pix);
709 }
710 gdk_window_clear(root);
711 }
712
713 static void apply_theme(const char* theme_name)
714 {
715 char* theme_dir = g_build_filename(LXDM_DATA_DIR "/themes", theme_name, NULL);
716 char* rc = g_build_filename(theme_dir, "gtkrc", NULL);
717
718 ui_file = g_build_filename(theme_dir, "greeter.ui", NULL);
719
720 if( g_file_test(rc, G_FILE_TEST_EXISTS) )
721 {
722 g_debug("%s", rc);
723 gtk_rc_parse(rc);
724 }
725 g_free(rc);
726
727 if( !g_file_test(ui_file, G_FILE_TEST_EXISTS) )
728 {
729 g_free(ui_file);
730 ui_file = NULL;
731 }
732 g_free(theme_dir);
733 }
734
735 int main(int arc, char *arg[])
736 {
737 char* theme_name;
738
739 gtk_set_locale();
740 bindtextdomain("lxdm", "/usr/share/locale");
741 textdomain("lxdm");
742
743 config = g_key_file_new();
744 g_key_file_load_from_file(config, CONFIG_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL);
745
746 var_config = g_key_file_new();
747 g_key_file_set_list_separator(var_config, ' ');
748 g_key_file_load_from_file(var_config,VCONFIG_FILE,G_KEY_FILE_KEEP_COMMENTS, NULL);
749
750 gtk_init(&arc, &arg);
751
752 set_background();
753 set_root_background();
754
755 /* set gtk+ theme */
756 theme_name = g_key_file_get_string(config, "display", "gtk_theme", NULL);
757 if( theme_name )
758 {
759 GtkSettings* settings = gtk_settings_get_default();
760 g_object_set(settings, "gtk-theme-name", theme_name, NULL);
761 g_free(theme_name);
762 }
763
764 /* load gtkrc-based themes */
765 theme_name = g_key_file_get_string(config, "display", "theme", NULL);
766 if( theme_name ) /* theme is specified */
767 {
768 apply_theme(theme_name);
769 g_free(theme_name);
770 }
771
772 /* create the login window */
773 create_win();
774 listen_stdin();
775 /* use line buffered stdout for inter-process-communcation of
776 * single-line-commands */
777 setvbuf(stdout, NULL, _IOLBF, 0 );
778
779 gtk_main();
780
781 if( config_changed )
782 {
783 gsize len;
784 char* data = g_key_file_to_data(var_config, &len, NULL);
785 g_file_set_contents(VCONFIG_FILE, data, len, NULL);
786 g_free(data);
787 }
788 g_key_file_free(config);
789 g_key_file_free(var_config);
790
791 return 0;
792 }