Merging upstream version 0.5.1.
[debian/lxdm.git] / src / greeter.c
CommitLineData
9931e273
DB
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>
d6ba7c28
AG
28#include <gdk/gdkkeysyms.h>
29#ifdef ENABLE_GTK3
30#include <gdk/gdkkeysyms-compat.h>
31#endif
9931e273
DB
32#include <glib/gi18n.h>
33#include <X11/XKBlib.h>
34
35#include "lang.h"
36#include <time.h>
37#include <stdlib.h>
38#include <sys/stat.h>
39#include <sys/wait.h>
40
41#include "lxcom.h"
42#include "greeter-utils.h"
d6ba7c28 43#include "lxcommon.h"
9931e273
DB
44
45enum {
46 COL_SESSION_NAME,
47 COL_SESSION_EXEC,
48 COL_SESSION_DESKTOP_FILE,
49 N_SESSION_COLS
50};
51
52enum {
53 COL_LANG_DISPNAME,
54 COL_LANG,
55 N_LANG_COLS
56};
57
9931e273
DB
58#define XKB_SYMBOL_DIR "/usr/share/X11/xkb/symbols.dir"
59
60static GtkBuilder* builder;
61static GKeyFile *config;
62static GKeyFile * var_config;
63static GtkWidget* win;
d6ba7c28 64static GtkWidget* alignment2;
9931e273
DB
65static GtkWidget* prompt;
66static GtkWidget* login_entry;
d6ba7c28 67static GtkWidget* user_list_scrolled;
9931e273
DB
68static GtkWidget* user_list;
69
70static GtkWidget* sessions;
71static GtkWidget* lang;
72
73static GtkWidget* exit_btn;
74
75static GtkWidget* exit_menu;
76static GtkWidget *lang_menu;
77
78static char* user = NULL;
79static char* pass = NULL;
80
81static char* ui_file = NULL;
82static char *ui_nobody = NULL;
83
84static GIOChannel *greeter_io;
85
86static int auto_login;
87static char datetime_fmt[8]="%c";
88
89static void do_reboot(void)
90{
91 printf("reboot\n");
92}
93
94static void do_shutdown(void)
95{
96 printf("shutdown\n");
97}
98
99static char *get_session_lang(void)
100{
101 GtkTreeModel* model;
102 GtkTreeIter it;
103 gchar *res;
104 if(!lang)
105 return g_strdup("");
106
107 if(!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(lang), &it))
108 return g_strdup("");
109 model = gtk_combo_box_get_model(GTK_COMBO_BOX(lang));
110 gtk_tree_model_get(model, &it, 1, &res, -1);
111 return res;
112}
113
114static char *get_session_exec(void)
115{
116 GtkTreeModel* model;
117 GtkTreeIter it;
118 gchar *res;
d6ba7c28 119 if(!sessions)
9931e273
DB
120 return g_strdup("");
121
122 if(!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(sessions), &it))
123 return g_strdup("");
124 model = gtk_combo_box_get_model(GTK_COMBO_BOX(sessions));
125 gtk_tree_model_get(model, &it, 1, &res, -1);
126 return res;
127}
128
d6ba7c28
AG
129static void switch_to_input_user(void)
130{
131 if(user)
132 {
133 g_free(user);
134 user=NULL;
135 }
136 if(pass)
137 {
138 g_free(pass);
139 pass=NULL;
140 }
141 gtk_label_set_text( GTK_LABEL(prompt), _("User:"));
142 gtk_widget_show(prompt);
143 if(user_list)
144 {
145 gtk_widget_hide(login_entry);
146 if(user_list_scrolled)
147 gtk_widget_show(user_list_scrolled);
148 else
149 gtk_widget_hide(user_list);
150 gtk_widget_grab_focus(user_list);
151 }
152 else
153 {
154 gtk_widget_show(login_entry);
155 gtk_widget_grab_focus(login_entry);
156 }
157}
158
159static void switch_to_input_passwd(void)
160{
161 if(user_list!=NULL)
162 {
163 if(user_list_scrolled)
164 gtk_widget_hide(user_list_scrolled);
165 else
166 gtk_widget_hide(user_list);
167 }
168 gtk_label_set_text( GTK_LABEL(prompt), _("Password:") );
169 gtk_entry_set_text(GTK_ENTRY(login_entry), "");
170 gtk_entry_set_visibility(GTK_ENTRY(login_entry), FALSE);
171 gtk_widget_show(login_entry);
172 gtk_widget_grab_focus(login_entry);
173}
174
175static void try_login_user(const char *user)
176{
177 char *session_exec=get_session_exec();
178 char *session_lang=get_session_lang();
179
180 printf("login user=%s session=%s lang=%s\n",
181 user, session_exec, session_lang);
182
183 g_free(session_lang);
184 g_free(session_exec);
185
186}
187
9931e273
DB
188static void on_entry_activate(GtkEntry* entry)
189{
190 char* tmp;
191 if( !user )
192 {
193 user = g_strdup( gtk_entry_get_text( GTK_ENTRY(entry) ) );
c8e553a1
AG
194 if(strlen(user)==0)
195 {
196 g_free(user);
197 user=NULL;
198 return;
199 }
9931e273
DB
200 if(strchr(user, ' '))
201 {
c8e553a1 202 gtk_entry_set_text(GTK_ENTRY(entry), "");
9931e273
DB
203 g_free(user);
204 user = NULL;
205 return;
206 }
d6ba7c28
AG
207 if(g_key_file_get_integer(config,"base","skip_password",NULL)!=0)
208 {
209 gtk_label_set_text( GTK_LABEL(prompt), "");
210 try_login_user(user);
211 }
212 else
213 {
214 switch_to_input_passwd();
215 }
9931e273
DB
216 }
217 else
218 {
219 char *session_exec=get_session_exec();
220 char *session_lang=get_session_lang();
221
222 tmp = g_strdup( gtk_entry_get_text(entry) );
223 pass=g_base64_encode((guchar*)tmp,strlen(tmp)+1);
224 g_free(tmp);
225
226 printf("login user=%s pass=%s session=%s lang=%s\n",
227 user, pass, session_exec, session_lang);
228
229 /* password check failed */
230 g_free(user);
231 user = NULL;
232 g_free(pass);
233 pass = NULL;
234 g_free(session_lang);
235 g_free(session_exec);
236
237 gtk_widget_hide(prompt);
238 gtk_widget_hide( GTK_WIDGET(entry) );
239
240 gtk_label_set_text( GTK_LABEL(prompt), _("User:") );
241 gtk_entry_set_text(GTK_ENTRY(entry), "");
242 gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE);
243 }
244}
245
246static void load_sessions()
247{
248 GtkListStore* list;
249 GtkTreeIter it, active_it = {0};
250 char* last;
251 char *path, *file_name, *name, *exec;
252 GKeyFile* kf;
253 GDir* dir = g_dir_open(XSESSIONS_DIR, 0, NULL);
254 if( !dir )
255 return;
256
257 last = g_key_file_get_string(var_config, "base", "last_session", NULL);
258
259 list = gtk_list_store_new(N_SESSION_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
260 kf = g_key_file_new();
261 while( ( file_name = (char*)g_dir_read_name(dir) ) != NULL )
262 {
263 path = g_build_filename(XSESSIONS_DIR, file_name, NULL);
264 if( g_key_file_load_from_file(kf, path, 0, NULL) )
265 {
266 name = g_key_file_get_locale_string(kf, "Desktop Entry", "Name", NULL, NULL);
267 if(!name || !name[0])
268 {
269 g_free(name);
270 g_free(path);
271 continue;
272 }
273 exec = g_key_file_get_string(kf, "Desktop Entry", "Exec", NULL);
274 if(!exec || !exec[0])
275 {
276 /* bad session config file */
277 g_free(exec);
278 g_free(name);
279 g_free(path);
280 continue;
281 }
282 g_free(exec); /* we just test it, and not use it */
283 exec=g_strdup(path);
284
285 if( !strcmp(name, "LXDE") )
286 gtk_list_store_prepend(list, &it);
287 else
288 gtk_list_store_append(list, &it);
289 gtk_list_store_set(list, &it,
290 COL_SESSION_NAME, name,
291 COL_SESSION_EXEC, exec,
292 COL_SESSION_DESKTOP_FILE, file_name, -1);
293 if( last && g_strcmp0(path, last) == 0 )
294 {
295 active_it = it;
296 }
297
298 g_free(name);
299 g_free(exec);
300 }
301 g_free(path);
302 }
303 g_dir_close(dir);
304 g_key_file_free(kf);
305
306 gtk_list_store_prepend(list, &it);
307 gtk_list_store_set(list, &it,
308 COL_SESSION_NAME, _("Default"),
309 COL_SESSION_EXEC, "",
310 COL_SESSION_DESKTOP_FILE, "__default__", -1);
311 if( last && g_strcmp0("__default__", last) == 0 )
312 active_it = it;
313
314 g_free(last);
315 gtk_combo_box_set_model( GTK_COMBO_BOX(sessions), GTK_TREE_MODEL(list) );
316#if GTK_CHECK_VERSION(2,24,0)
317 gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(sessions), 0);
318#else
319 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(sessions), 0);
320#endif
321 if( active_it.stamp )
322 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(sessions), &active_it);
323 else
324 gtk_combo_box_set_active(GTK_COMBO_BOX(sessions), 0);
325
326 g_object_unref(list);
327}
328
329static void load_lang_cb(void *arg, char *lang, char *desc)
330{
331 GtkListStore* list = (GtkListStore*)arg;
332 GtkTreeIter it;
333 gchar *temp,*p,*lang2;
334
335 lang2=g_strdup(lang);
336 p=strchr(lang2,'.');
337 if(p) *p=0;
338
339 if(lang2[0] && lang2[0]!='~')
340 temp=g_strdup_printf("%s\t%s",lang2,desc?desc:"");
341 else
342 temp=g_strdup(desc);
343 g_free(lang2);
344 gtk_list_store_append(list, &it);
345 gtk_list_store_set(list, &it,
346 COL_LANG_DISPNAME, temp,
347 COL_LANG, lang, -1);
348 g_free(temp);
349}
350
351static gint lang_cmpr(GtkTreeModel *list,GtkTreeIter *a,GtkTreeIter *b,gpointer user_data)
352{
353 gint ret;
354 gchar *as,*bs;
355 gtk_tree_model_get(list,a,1,&as,-1);
356 gtk_tree_model_get(list,b,1,&bs,-1);
357 ret=strcmp(as,bs);
358 g_free(as);g_free(bs);
359 return ret;
360}
361
362static gint keyboard_cmpr(GtkTreeModel *list,GtkTreeIter *a,GtkTreeIter *b,gpointer user_data)
363{
364 gint ret;
365 gchar *as,*bs;
366 gtk_tree_model_get(list,a,0,&as,-1);
367 gtk_tree_model_get(list,b,0,&bs,-1);
368 ret=strcmp(as,bs);
369 g_free(as);g_free(bs);
370 return ret;
371}
372
373static void on_menu_lang_select(GtkMenuItem *item,gpointer user_data)
374{
375 GtkTreeIter iter;
376 char *sel=(char*)user_data;
377 int i;
378 gboolean res;
379 GtkTreeModel *list;
380 int active=-1;
381 char *temp;
382 if(!sel || !sel[0]) return;
383
384 list=gtk_combo_box_get_model(GTK_COMBO_BOX(lang));
385 res=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list),&iter);
386 for(i=0;res==TRUE;i++)
387 {
388 gtk_tree_model_get(GTK_TREE_MODEL(list),&iter,1,&temp,-1);
389 if(!strcmp(temp,sel))
390 {
391 g_free(temp);
392 active=i;
393 break;
394 }
395 g_free(temp);
396 res=gtk_tree_model_iter_next(GTK_TREE_MODEL(list),&iter);
397 }
398 if(active>=0)
399 {
400 gtk_combo_box_set_active(GTK_COMBO_BOX(lang),active);
401 return;
402 }
403 gtk_list_store_append((GtkListStore*)list, &iter);
404 temp=(char*)gtk_menu_item_get_label(item);
405 gtk_list_store_set((GtkListStore*)list, &iter,
406 COL_LANG_DISPNAME, temp,
407 COL_LANG, sel, -1);
408 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(lang),&iter);
409}
410
411static void load_menu_lang_cb(void *arg, char *lang, char *desc)
412{
413 GtkWidget *menu=GTK_WIDGET(arg);
414 GtkWidget* item;
415
416 gchar *temp,*p,*lang2;
417
418 lang2=g_strdup(lang);
419 p=strchr(lang2,'.');
420 if(p) *p=0;
421
422 if(lang2[0] && lang2[0]!='~')
423 temp=g_strdup_printf("%s\t%s",lang2,desc?desc:"");
424 else
425 temp=g_strdup(desc);
426 g_free(lang2);
427
428 item = gtk_menu_item_new_with_label(temp);
429 g_signal_connect(item, "activate", G_CALLBACK(on_menu_lang_select), g_strdup(lang));
430 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
431 g_free(temp);
432}
433
434static void show_all_languages(void)
435{
436 if(!lang_menu)
437 {
438 lang_menu=gtk_menu_new();
439 lxdm_load_langs(var_config,TRUE,lang_menu,load_menu_lang_cb);
440 gtk_widget_show_all(lang_menu);
441 }
442 gtk_menu_popup(GTK_MENU(lang_menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time());
443}
444
445static void on_lang_changed(GtkComboBox *widget)
446{
447 GtkTreeIter it;
448 if( gtk_combo_box_get_active_iter(widget, &it) )
449 {
450 GtkListStore *list=(GtkListStore*)gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
451 char *lang=NULL;
452 gtk_tree_model_get(GTK_TREE_MODEL(list), &it, 1, &lang, -1);
453 if(lang[0]=='~')
454 {
455 gtk_combo_box_set_active(widget,0);
456 show_all_languages();
457 }
458 g_free(lang);
459 }
460}
461
462static void load_langs()
463{
464 GtkListStore* list;
465 char* lang_str;
466 int active = 0;
467
468 list = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
469 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(list),0,GTK_SORT_ASCENDING);
470 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list),0,lang_cmpr,NULL,NULL);
471 lxdm_load_langs(var_config,FALSE,list, load_lang_cb);
472 lang_str = g_key_file_get_string(var_config, "base", "last_lang", NULL);
473 if(lang_str && lang_str[0])
474 {
475 gboolean res;
476 GtkTreeIter iter;
477 int i;
478 res=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list),&iter);
479 if(res) for(i=0;;i++)
480 {
481 gchar *lang;
482 gtk_tree_model_get(GTK_TREE_MODEL(list),&iter,1,&lang,-1);
483 if(!strcmp(lang,lang_str))
484 {
485 g_free(lang);
486 active=i;
487 break;
488 }
489 g_free(lang);
490 res=gtk_tree_model_iter_next(GTK_TREE_MODEL(list),&iter);
491 if(!res) break;
492 }
493 }
494 g_free(lang_str);
495 gtk_combo_box_set_model( GTK_COMBO_BOX(lang), GTK_TREE_MODEL(list) );
496#if GTK_CHECK_VERSION(2,24,0)
497 gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(lang), 0);
498#else
499 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(lang), 0);
500#endif
501 gtk_combo_box_set_active(GTK_COMBO_BOX(lang), active < 0 ? 0 : active);
502 g_object_unref(list);
503
504 g_signal_connect(G_OBJECT(lang),"changed",G_CALLBACK(on_lang_changed),NULL);
505}
506
507static void on_keyboard_changed(GtkComboBox *widget)
508{
509 GtkTreeIter it;
510 if( gtk_combo_box_get_active_iter(widget, &it) )
511 {
512 GtkListStore *list=(GtkListStore*)gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
513 char *keyboard=NULL;
514 char *cmd;
515 int status;
516 gboolean res;
517 gtk_tree_model_get(GTK_TREE_MODEL(list), &it, 0, &keyboard, -1);
518 /* set the current xkb */
519 cmd=g_strdup_printf("setxkbmap %s",keyboard);
520 res=g_spawn_command_line_sync(cmd,NULL,NULL,&status,NULL);
521 printf("%s %d %d\n",cmd,res,WEXITSTATUS (status));
522 g_free(cmd);
523 g_free(keyboard);
524 }
525}
526
527static gchar *xkb_name_norm(gchar *s)
528{
529 if(!strcmp(s,"pc")) return NULL;
530 if(!strncmp(s,"pc(",3)) return NULL;
531 if(!strncmp(s,"inet(",5)) return NULL;
532 if(!strncmp(s,"group(",6)) return NULL;
533 if(!strncmp(s,"srvr_ctrl(",10)) return NULL;
534 if(g_str_has_suffix(s,"(basic)"))
535 {
536 *strstr(s,"(basic)")=0;
537 }
538 else if(!strcmp(s,"jp(106)")) //TODO: is default jp jp(106)
539 {
540 s[2]=0;
541 }
542 return s;
543}
544
545static char *xkb_get_current(void)
546{
547 Display *dpy=gdk_x11_display_get_xdisplay(gdk_display_get_default());
548 XkbDescRec * xkb_desc;
549 char *symbol_string=NULL;
550 gchar **list;
551 int i;
552
553 if(!dpy) return NULL;
554 xkb_desc=XkbAllocKeyboard();
555 if (xkb_desc == NULL)
556 return NULL;
557 XkbGetControls(dpy, XkbAllControlsMask, xkb_desc);
558 XkbGetNames(dpy, XkbSymbolsNameMask | XkbGroupNamesMask, xkb_desc);
559 if ((xkb_desc->names == NULL) || (xkb_desc->ctrls == NULL) || (xkb_desc->names->groups == NULL))
560 {
561 }
562 else
563 {
564 if (xkb_desc->names->symbols != None)
565 {
566 symbol_string=XGetAtomName(dpy, xkb_desc->names->symbols);
567 }
568 }
569 XkbFreeKeyboard(xkb_desc, 0, True);
570
571 if(!symbol_string)
572 return FALSE;
573 list=g_strsplit(symbol_string,"+",-1);
574 XFree(symbol_string);
575 if(!list) return NULL;
576 for(i=0;list[i]!=NULL;i++)
577 {
578 if(!xkb_name_norm(list[i])) continue;
579 symbol_string=g_strdup(list[i]);
580 break;
581 }
582 g_strfreev(list);
583
584 return symbol_string;
585}
586
587#if 0
588
589static gboolean load_keyboards(GtkWidget *w)
590{
591 GtkListStore* list;
592 char p1[16],p2[16],p3[64];
593 FILE *fp;
594 char *cur;
595 int ret;
596 int count,active;
597 GtkTreeIter active_iter;
598 GdkScreen *scr;
599
600 scr=gdk_screen_get_default();
601 if(gdk_screen_get_width(scr)<1024)
602 return FALSE;
603
604 if(!w) return FALSE;
605
606 cur=xkb_get_current();
607 if(!cur) return FALSE;
608 fp=fopen(XKB_SYMBOL_DIR,"r");
609 if(!fp)
610 {
611 g_print("open xkb symbol dir fail\n");
612 g_free(cur);
613 return FALSE;
614 }
615 list = gtk_list_store_new(1, G_TYPE_STRING);
616 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(list),0,GTK_SORT_ASCENDING);
617 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list),0,keyboard_cmpr,NULL,NULL);
618 for(count=0,active=-1;(ret=fscanf(fp,"%16s %16s %64s\n",p1,p2,p3))==3;)
619 {
620 GtkTreeIter iter;
621 if(strchr(p2,'m') && !strchr(p2,'a')) continue;
622 if(!xkb_name_norm(p3)) continue;
623 gtk_list_store_append(list,&iter);
624 gtk_list_store_set(list,&iter,0,p3,-1);
625 if(!strcmp(cur,p3))
626 {
627 active=count;
628 active_iter=iter;
629 }
630 count++;
631 }
632 fclose(fp);
633 g_free(cur);
634
635 if(count==0 || active==-1)
636 {
637 g_object_unref(list);
638 return FALSE;
639 }
640
641 gtk_combo_box_set_model(GTK_COMBO_BOX(w), GTK_TREE_MODEL(list) );
642 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(w), 0);
643 g_object_unref(G_OBJECT(list));
644 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(w), &active_iter);
645
646 g_signal_connect(G_OBJECT(w),"changed",G_CALLBACK(on_keyboard_changed),NULL);
647
648 return TRUE;
649}
650#else
651static gboolean load_keyboards(GtkWidget *w)
652{
653 GtkListStore* list;
654 char *cur;
655 int count,active;
656 GtkTreeIter active_iter;
657 GdkScreen *scr;
658 GDir *dir;
659 const gchar *filename;
660
661 scr=gdk_screen_get_default();
662 if(gdk_screen_get_width(scr)<1024)
663 return FALSE;
664
665 if(!w) return FALSE;
666
667 cur=xkb_get_current();
668 if(!cur) return FALSE;
669 dir=g_dir_open("/usr/share/X11/xkb/symbols",0,FALSE);
670 if(!dir)
671 {
672 g_print("open xkb symbol dir fail\n");
673 g_free(cur);
674 return FALSE;
675 }
676 list = gtk_list_store_new(1, G_TYPE_STRING);
677 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(list),0,GTK_SORT_ASCENDING);
678 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list),0,keyboard_cmpr,NULL,NULL);
679 for(count=0,active=-1;(filename=g_dir_read_name(dir))!=NULL;)
680 {
681 GtkTreeIter iter;
682 if(strlen(filename)!=2)
683 continue;
684 gtk_list_store_append(list,&iter);
685 gtk_list_store_set(list,&iter,0,filename,-1);
686 if(!strcmp(cur,filename))
687 {
688 active=count;
689 active_iter=iter;
690 }
691 count++;
692 }
693 g_dir_close(dir);
694 g_free(cur);
695
696 if(count==0 || active==-1)
697 {
698 g_object_unref(list);
699 return FALSE;
700 }
701
702 gtk_combo_box_set_model(GTK_COMBO_BOX(w), GTK_TREE_MODEL(list) );
703#if GTK_CHECK_VERSION(2,24,0)
704 gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(w), 0);
705#else
706 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(w), 0);
707#endif
708 g_object_unref(G_OBJECT(list));
709 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(w), &active_iter);
710
711 g_signal_connect(G_OBJECT(w),"changed",G_CALLBACK(on_keyboard_changed),NULL);
712
713 return TRUE;
714}
715#endif
716
717static void on_exit_clicked(GtkButton* exit_btn, gpointer user_data)
718{
719 gtk_menu_popup( GTK_MENU(exit_menu), NULL, NULL, NULL, NULL,
720 0, gtk_get_current_event_time() );
721}
722
723static void load_exit()
724{
725 GtkWidget* item;
726 exit_menu = gtk_menu_new();
727 item = gtk_image_menu_item_new_with_mnemonic( _("_Reboot") );
728 g_signal_connect(item, "activate", G_CALLBACK(do_reboot), NULL);
729 gtk_menu_shell_append(GTK_MENU_SHELL(exit_menu), item);
730
731 item = gtk_image_menu_item_new_with_mnemonic( _("_Shutdown") );
732 g_signal_connect(item, "activate", G_CALLBACK(do_shutdown), NULL);
733 gtk_menu_shell_append(GTK_MENU_SHELL(exit_menu), item);
734
735 gtk_widget_show_all(exit_menu);
736 g_signal_connect(exit_btn, "clicked", G_CALLBACK(on_exit_clicked), NULL);
737}
738
739#if 0
740static gboolean on_expose(GtkWidget* widget, GdkEventExpose* evt, gpointer user_data)
741{
742 cairo_t *cr;
743 GdkRectangle *r=&evt->area;
744
745#if GTK_CHECK_VERSION(2,18,0)
746 if(! gtk_widget_get_has_window(widget))
747#else
748 if( !GTK_WIDGET_REALIZED(widget) )
749#endif
750 return FALSE;
751#if GTK_CHECK_VERSION(2,14,0)
752 cr = gdk_cairo_create(gtk_widget_get_window(widget));
753#else
754 cr = gdk_cairo_create(widget->window);
755#endif
756 if(bg_img )
757 {
758 gdk_cairo_set_source_pixbuf(cr, bg_img, 0, 0);
759 gdk_cairo_rectangle (cr,r);
760 cairo_paint(cr);
761 }
762 else
763 {
764 gdk_cairo_set_source_color(cr, &bg_color);
765 gdk_cairo_rectangle (cr,r);
766 cairo_fill(cr);
767 }
768 cairo_destroy(cr);
769 return FALSE;
770}
771#endif
772
773static gboolean on_combobox_entry_button_release(GtkWidget* w, GdkEventButton* evt, GtkComboBox* combo)
774{
775 gboolean shown;
776 g_object_get(combo, "popup-shown", &shown, NULL);
777 if( shown )
778 gtk_combo_box_popdown(combo);
779 else
780 gtk_combo_box_popup(combo);
781 return FALSE;
782}
783
784static void fix_combobox_entry(GtkWidget* combo)
785{
786 GtkWidget* edit = gtk_bin_get_child(GTK_BIN(combo));
787 gtk_editable_set_editable( (GtkEditable*)edit, FALSE );
788#if GTK_CHECK_VERSION(2,18,0)
789 gtk_widget_set_can_focus(edit, FALSE);
790#else
791 GTK_WIDGET_UNSET_FLAGS(edit, GTK_CAN_FOCUS);
792#endif
793 g_signal_connect(edit, "button-release-event", G_CALLBACK(on_combobox_entry_button_release), combo);
794}
795
796#if GTK_CHECK_VERSION(3,0,0)
797static gboolean on_evt_box_draw(GtkWidget *widget,cairo_t *cr,gpointer user_data)
798{
799 GtkStyleContext *style=gtk_widget_get_style_context(widget);
800 gtk_render_background(style,cr,0,0,
801 gtk_widget_get_allocated_width(widget),
802 gtk_widget_get_allocated_height(widget));
803 return FALSE;
804}
805#else
806static gboolean on_evt_box_expose(GtkWidget *widget, GdkEventExpose* evt, gpointer user_data)
807{
808#if GTK_CHECK_VERSION(2,18,0)
809 if (gtk_widget_is_drawable(widget))
810#else
811 if (GTK_WIDGET_DRAWABLE (widget))
812#endif
813 {
814 GtkWidgetClass* klass = (GtkWidgetClass*)G_OBJECT_GET_CLASS(widget);
815 gtk_paint_flat_box (gtk_widget_get_style(widget),
816#if GTK_CHECK_VERSION(2,14,0)
817 gtk_widget_get_window(widget),
818#else
819 widget->window,
820#endif
821#if GTK_CHECK_VERSION(2,18,0)
822 gtk_widget_get_state(widget), GTK_SHADOW_NONE,
823#else
824 widget->state, GTK_SHADOW_NONE,
825#endif
826 &evt->area, widget, "eventbox",
827 0, 0, -1, -1);
828 klass->expose_event (widget, evt);
829 }
830 return FALSE;
831}
832#endif
833
834static gboolean on_timeout(GtkLabel* label)
835{
836 char buf[128];
837 time_t t;
838 struct tm* tmbuf;
839 time(&t);
840 tmbuf = localtime(&t);
841 strftime(buf, 128, datetime_fmt, tmbuf);
842 gtk_label_set_text(label, buf);
843 return TRUE;
844}
845
846static gboolean autologin_timeout(gpointer data)
847{
848 char *user=g_key_file_get_string(config,"base","autologin",NULL);
849 if(auto_login && user && user[0])
850 {
851 char *session_exec=get_session_exec();
852 char *session_lang=get_session_lang();
853
854 printf("autologin session=%s lang=%s\n",
855 session_exec, session_lang);
856
857 g_free(session_lang);
858 g_free(session_exec);
859
860 gtk_widget_hide(prompt);
861 gtk_widget_hide( GTK_WIDGET(login_entry) );
862 }
863 g_free(user);
864 return FALSE;
865}
866
867static gboolean is_autologin_user(const char *name)
868{
869 char *autologin=g_key_file_get_string(config,"base","autologin",NULL);
870 if(!autologin)
871 return FALSE;
872 return strcmp(name,autologin)?FALSE:TRUE;
873}
874
875static void on_user_select(GtkIconView *iconview)
876{
877 GList *list=gtk_icon_view_get_selected_items(iconview);
878 GtkTreeIter iter;
879 GtkTreeModel *model=gtk_icon_view_get_model(iconview);
880 char *name;
881 if(!list) return;
882 gtk_tree_model_get_iter(model,&iter,list->data);
883 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
884 g_list_free (list);
885 gtk_tree_model_get(model,&iter,2,&name,-1);
d6ba7c28
AG
886 if(user_list_scrolled)
887 gtk_widget_hide(user_list_scrolled);
888 else
889 gtk_widget_hide(user_list);
9931e273
DB
890 if(name && name[0])
891 {
892 if(auto_login && is_autologin_user(name))
893 {
894 g_free(name);
895
896 char *session_exec=get_session_exec();
897 char *session_lang=get_session_lang();
898
899 printf("autologin session=%s lang=%s\n",
900 session_exec, session_lang);
901
902 g_free(session_lang);
903 g_free(session_exec);
904
905 gtk_widget_hide(prompt);
906 gtk_widget_hide( GTK_WIDGET(login_entry) );
907 return;
908 }
d6ba7c28
AG
909 if(g_key_file_get_integer(config,"base","skip_password",NULL)!=0)
910 {
911 gtk_label_set_text( GTK_LABEL(prompt), "");
912 user=name;
913 try_login_user(user);
914 return;
915 }
9931e273
DB
916 gtk_entry_set_text(GTK_ENTRY(login_entry),name);
917 g_free(name);
918 on_entry_activate(GTK_ENTRY(login_entry));
919 gtk_widget_show(login_entry);
920 gtk_widget_grab_focus(login_entry);
921
922 gtk_label_set_text( GTK_LABEL(prompt), _("Password:") );
923 gtk_widget_show(prompt);
924 }
925 else
926 {
927 g_free(name);
928 if(user)
929 {
930 g_free(user);
931 user=NULL;
932 }
933 gtk_entry_set_text(GTK_ENTRY(login_entry),"");
934 gtk_widget_show(login_entry);
935 gtk_widget_grab_focus(login_entry);
936 gtk_label_set_text( GTK_LABEL(prompt), _("User:") );
937 gtk_widget_show(prompt);
938 }
939 auto_login=0;
940}
941
942static void on_user_click(GtkIconView *iconview)
943{
944 on_user_select(iconview);
945}
946
947static gboolean load_user_list(GtkWidget *widget)
948{
949 GtkListStore *model;
950 GtkTreeIter iter;
951 GKeyFile *kf;
952 GtkTreePath *path;
953 char *res=NULL;
954 char **users;
955 gsize count;
956 int i;
957 lxcom_send("/var/run/lxdm/lxdm.sock","USER_LIST",&res);
958 if(!res)
959 {
960 printf("log USER_LIST fail\n");
961 return FALSE;
962 }
963 kf=g_key_file_new();
964 if(!g_key_file_load_from_data(kf,res,-1,0,NULL))
965 {
966 g_key_file_free(kf);
967 g_free(res);
968 printf("log USER_LIST data bad\n");
969 return FALSE;
970 }
971 g_free(res);
972
973 gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(widget),GTK_SELECTION_SINGLE);
974 gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(widget),0);
975 gtk_icon_view_set_markup_column(GTK_ICON_VIEW(widget),1);
976#if GTK_CHECK_VERSION(2,22,0)
977 gtk_icon_view_set_item_orientation(GTK_ICON_VIEW(widget),GTK_ORIENTATION_HORIZONTAL);
978#else
979 gtk_icon_view_set_orientation(GTK_ICON_VIEW(widget),GTK_ORIENTATION_HORIZONTAL);
980#endif
d6ba7c28
AG
981 // FIXME: this should be done at greeter-gtk3.ui
982 // but set there will cause "Floating point exception"
983 gtk_icon_view_set_columns(GTK_ICON_VIEW(widget),1);
984
9931e273
DB
985 model=gtk_list_store_new(5,GDK_TYPE_PIXBUF,G_TYPE_STRING,
986 G_TYPE_STRING,G_TYPE_STRING,G_TYPE_BOOLEAN);
987 gtk_icon_view_set_model(GTK_ICON_VIEW(widget),GTK_TREE_MODEL(model));
988 g_signal_connect(G_OBJECT(widget),"item-activated",G_CALLBACK(on_user_select),NULL);
989 //g_signal_connect(G_OBJECT(widget),"selection-changed",G_CALLBACK(on_user_select),NULL);
990 g_signal_connect(G_OBJECT(widget),"button-release-event",G_CALLBACK(on_user_click),NULL);
991
992 users=g_key_file_get_groups(kf,&count);
993 if(!users || count<=0)
994 {
995 g_key_file_free(kf);
996 printf("USER_LIST 0 user\n");
997 return FALSE;
998 }
999 if(count>3)
1000 {
d6ba7c28
AG
1001 if(user_list_scrolled)
1002 {
1003 gtk_alignment_set(GTK_ALIGNMENT(alignment2), 0.5, 0.1, 0, 0.3);
1004 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(user_list_scrolled), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
1005 }
1006 else
1007 count=3;
9931e273
DB
1008 }
1009 for(i=0;i<count;i++)
1010 {
1011 char *gecos,*face_path,*display;
d6ba7c28 1012 gchar *gecos_escape;
9931e273
DB
1013 gboolean login;
1014 GdkPixbuf *face=NULL;
1015 gtk_list_store_append(model,&iter);
1016 gecos=g_key_file_get_string(kf,users[i],"gecos",0);
1017 face_path=g_key_file_get_string(kf,users[i],"face",0);
1018 login=g_key_file_get_boolean(kf,users[i],"login",0);
d6ba7c28
AG
1019 if(gecos!=NULL)
1020 {
1021 char *comma=gecos?strchr(gecos,','):NULL;
1022 if (comma)
1023 *comma='\0';
1024 }
9931e273
DB
1025 if(face_path)
1026 face=gdk_pixbuf_new_from_file_at_scale(face_path,48,48,TRUE,NULL);
1027 if(!face)
1028 {
1029 /* TODO: load some default face */
1030 if(ui_nobody)
1031 face=gdk_pixbuf_new_from_file_at_scale(ui_nobody,48,48,TRUE,NULL);
1032 if(!face)
1033 face=gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
1034 "avatar-default", 48,GTK_ICON_LOOKUP_FORCE_SIZE,NULL);
1035 }
d6ba7c28 1036 gecos_escape=g_markup_escape_text(gecos?gecos:users[i],-1);
9931e273 1037 display=g_strdup_printf("<span font_size=\"x-large\">%s</span>%s%s%s%s",
d6ba7c28
AG
1038 gecos_escape,
1039 (gecos&&strcmp(gecos,users[i]))?" (":"",
9931e273
DB
1040 (gecos&&strcmp(gecos,users[i]))?users[i]:"",
1041 (gecos&&strcmp(gecos,users[i]))?")":"",
1042 login?_("\n<i>logged in</i>"):"");
1043 // don't translate it now, not freeze
d6ba7c28 1044 g_free(gecos_escape);
9931e273
DB
1045 gtk_list_store_set(model,&iter,0,face,1,display,2,users[i],3,gecos,4,login,-1);
1046 if(face) g_object_unref(G_OBJECT(face));
1047 g_free(display);
1048 g_free(gecos);
1049 g_free(face_path);
1050 }
1051 g_strfreev(users);
1052 g_key_file_free(kf);
d6ba7c28 1053
9931e273
DB
1054 // add "More ..."
1055 gtk_list_store_append(model,&iter);
1056 gtk_list_store_set(model,&iter,1,_("More ..."),2,"",3,"",4,FALSE,-1);
d6ba7c28 1057
9931e273
DB
1058 path=gtk_tree_path_new_from_string("0");
1059 gtk_icon_view_select_path(GTK_ICON_VIEW(widget),path);
1060 gtk_widget_grab_focus(widget);
1061 gtk_icon_view_set_cursor(GTK_ICON_VIEW(widget),path,NULL,FALSE);
1062 gtk_tree_path_free(path);
d6ba7c28 1063
9931e273
DB
1064 return TRUE;
1065}
1066
1067static void on_screen_size_changed(GdkScreen *screen,GtkWidget *win)
1068{
1069 GdkRectangle rc;
1070 GdkWindow *window;
1071#if GTK_CHECK_VERSION(3,0,0)
1072 window=gtk_widget_get_window(win);
1073#else
1074 window=win->window;
1075#endif
1076 ui_get_geometry(window,&rc);
1077 if(rc.width<1024 && g_key_file_get_integer(config, "display", "keyboard", 0)==1)
1078 {
1079 GtkWidget *w;
1080 w=(GtkWidget*)gtk_builder_get_object(builder, "keyboard");
1081 gtk_widget_hide(w);
1082 w=(GtkWidget*)gtk_builder_get_object(builder, "label_keyboard");
1083 gtk_widget_hide(w);
1084 }
1085
1086 gtk_window_move(GTK_WINDOW(win),rc.x,rc.y);
1087 gtk_window_resize(GTK_WINDOW(win),rc.width,rc.height);
1088 ui_set_bg(window,config);
1089}
1090
d6ba7c28
AG
1091static gint login_entry_on_key_press (GtkWidget *widget,GdkEventKey *event)
1092{
1093 if(event->keyval == GDK_Escape)
1094 switch_to_input_user();
1095 return FALSE;
1096}
1097
9931e273
DB
1098static void create_win()
1099{
1100 GSList* objs, *l;
1101 GtkWidget* w;
1102 GdkWindow *window;
1103 gchar *temp;
1104 GdkRectangle rc;
1105 GdkScreen *scr;
1106
1107 temp=g_key_file_get_string(config,"display","datetime",NULL);
1108 if(temp && temp[0]=='%' && strlen(temp)<=3)
1109 strcpy(datetime_fmt,temp);
1110 g_free(temp);
1111
1112 builder = gtk_builder_new();
1113 gtk_builder_add_from_file(builder, ui_file ? ui_file : LXDM_DATA_DIR "/lxdm.glade", NULL);
1114 win = (GtkWidget*)gtk_builder_get_object(builder, "lxdm");
1115#if GTK_CHECK_VERSION(3,0,0)
1116 gtk_window_set_has_resize_grip(GTK_WINDOW(win),FALSE);
1117#endif
1118 gtk_widget_realize(win);
1119#if GTK_CHECK_VERSION(3,0,0)
1120 window=gtk_widget_get_window(win);
1121#else
1122 window=win->window;
1123#endif
1124
1125 /* set widget names according to their object id in GtkBuilder xml */
1126 objs = gtk_builder_get_objects(builder);
1127 for( l = objs; l; l = l->next )
1128 {
1129 char* path;
1130 GtkWidget* widget = (GtkWidget*)l->data;
1131 gtk_widget_set_name( widget, gtk_buildable_get_name( (GtkBuildable*)widget ) );
1132 gtk_widget_path(widget, NULL, &path, NULL);
1133 }
1134 g_slist_free(objs);
1135
1136 if(g_key_file_has_key(config,"display","bg",NULL ))
1137 {
1138#if GTK_CHECK_VERSION(3,0,0)
1139 GtkStyleContext *style=gtk_widget_get_style_context(win);
1140 gtk_style_context_remove_class(style,GTK_STYLE_PROPERTY_BACKGROUND_IMAGE);
1141#endif
1142 gtk_widget_set_app_paintable(win, TRUE);
1143
1144 } /* otherwise, let gtk theme paint it. */
1145
d6ba7c28
AG
1146 alignment2=(GtkWidget*)gtk_builder_get_object(builder,"alignment2");
1147 user_list_scrolled=(GtkWidget*)gtk_builder_get_object(builder,"user_list_scrolled");
9931e273
DB
1148 user_list=(GtkWidget*)gtk_builder_get_object(builder,"user_list");
1149
1150 prompt = (GtkWidget*)gtk_builder_get_object(builder, "prompt");
1151 login_entry = (GtkWidget*)gtk_builder_get_object(builder, "login_entry");
d6ba7c28
AG
1152 if(login_entry!=NULL)
1153 {
1154 g_signal_connect_after(login_entry,"key-press-event",G_CALLBACK(login_entry_on_key_press),NULL);
1155 }
9931e273
DB
1156
1157 g_signal_connect(login_entry, "activate", G_CALLBACK(on_entry_activate), NULL);
1158
d6ba7c28 1159 if( g_key_file_get_integer(config, "display", "bottom_pane", 0)==1)
9931e273
DB
1160 {
1161 /* hacks to let GtkEventBox paintable with gtk pixmap engine. */
d6ba7c28
AG
1162 w = (GtkWidget*)gtk_builder_get_object(builder, "bottom_pane");
1163 if(g_key_file_get_integer(config, "display", "transparent_pane", 0)==1)
1164 {
1165 }
1166 else
1167 {
9931e273 1168#if GTK_CHECK_VERSION(2,18,0)
d6ba7c28 1169 if(gtk_widget_get_app_paintable(w))
9931e273 1170#else
d6ba7c28 1171 if(GTK_WIDGET_APP_PAINTABLE(w))
9931e273
DB
1172#endif
1173
1174#if GTK_CHECK_VERSION(3,0,0)
d6ba7c28 1175 g_signal_connect(w,"draw",G_CALLBACK(on_evt_box_draw),NULL);
9931e273 1176#else
d6ba7c28 1177 g_signal_connect(w, "expose-event", G_CALLBACK(on_evt_box_expose), NULL);
9931e273 1178#endif
d6ba7c28
AG
1179 }
1180 if( g_key_file_get_integer(config, "display", "hide_sessions", 0)==1)
1181 {
1182 w = (GtkWidget*)gtk_builder_get_object(builder, "sessions_box");
1183 if(w) gtk_widget_hide(w);
1184 }
1185 else
1186 {
1187 sessions = (GtkWidget*)gtk_builder_get_object(builder, "sessions");
1188 gtk_widget_set_name(sessions, "sessions");
1189 fix_combobox_entry(sessions);
1190 load_sessions();
1191 }
1192
1193 if( g_key_file_get_integer(config, "display", "lang", 0) == 0 )
1194 {
1195 w = (GtkWidget*)gtk_builder_get_object(builder, "lang_box");
1196 if(w) gtk_widget_hide(w);
1197 }
1198 else
1199 {
1200 lang = (GtkWidget*)gtk_builder_get_object(builder, "lang");
1201 gtk_widget_set_name(lang, "lang");
1202 fix_combobox_entry(lang);
1203 load_langs();
1204 }
1205
1206 if(g_key_file_get_integer(config, "display", "keyboard", 0)==1)
1207 {
1208 w=(GtkWidget*)gtk_builder_get_object(builder, "keyboard");
1209 if((load_keyboards(w))!=FALSE)
1210 {
1211 fix_combobox_entry(w);
1212 gtk_widget_show(w);
1213 w=(GtkWidget*)gtk_builder_get_object(builder, "label_keyboard");
1214 if(w) gtk_widget_show(w);
1215 }
1216 }
9931e273
DB
1217 }
1218 else
9931e273 1219 {
d6ba7c28
AG
1220 w = (GtkWidget*)gtk_builder_get_object(builder, "bottom_pane");
1221 gtk_widget_hide(w);
9931e273 1222 }
d6ba7c28
AG
1223
1224 if(g_key_file_get_integer(config, "display", "hide_time", 0)==1)
9931e273 1225 {
d6ba7c28
AG
1226 w = (GtkWidget*)gtk_builder_get_object(builder, "time");
1227 gtk_widget_hide(w);
9931e273 1228 }
d6ba7c28 1229 else
9931e273 1230 {
9931e273
DB
1231 if( (w = (GtkWidget*)gtk_builder_get_object(builder, "time"))!=NULL )
1232 {
1233 guint timeout = g_timeout_add(1000, (GSourceFunc)on_timeout, w);
1234 g_signal_connect_swapped(w, "destroy",
1235 G_CALLBACK(g_source_remove), GUINT_TO_POINTER(timeout));
1236 on_timeout((GtkLabel*)w);
1237 }
d6ba7c28 1238 }
9931e273 1239
d6ba7c28
AG
1240 if(g_key_file_get_integer(config, "display", "hide_exit", 0)==1)
1241 {
1242 w=(GtkWidget*)gtk_builder_get_object(builder, "exit");
1243 gtk_widget_hide(w);
1244 }
1245 else
1246 {
1247 exit_btn = (GtkWidget*)gtk_builder_get_object(builder, "exit");
1248 load_exit();
1249 }
9931e273
DB
1250
1251 ui_get_geometry(window,&rc);
1252 gtk_window_move(GTK_WINDOW(win),rc.x,rc.y);
1253 gtk_window_set_default_size(GTK_WINDOW(win),rc.width,rc.height);
9931e273
DB
1254
1255 if(user_list && !g_key_file_get_integer(config,"userlist","disable",NULL) &&
1256 load_user_list(user_list))
1257 {
1258 gtk_widget_hide(login_entry);
1259 }
1260 else
1261 {
1262 if(user_list)
1263 {
d6ba7c28
AG
1264 if(user_list_scrolled)
1265 gtk_widget_hide(user_list_scrolled);
1266 else
1267 gtk_widget_hide(user_list);
9931e273
DB
1268 user_list=NULL;
1269 }
1270 }
1271
1272 ui_add_cursor();
1273 ui_set_cursor(gtk_widget_get_window(win),GDK_LEFT_PTR);
1274 gtk_widget_show(win);
d6ba7c28
AG
1275 ui_set_bg(window,config);
1276
9931e273
DB
1277 ui_set_focus(window);
1278 if(!user_list)
1279 gtk_widget_grab_focus(login_entry);
1280
1281 scr = gtk_widget_get_screen(win);
1282 g_signal_connect(scr, "size-changed", G_CALLBACK(on_screen_size_changed), win);
1283}
1284
1285static gboolean on_lxdm_command(GIOChannel *source, GIOCondition condition, gpointer data)
1286{
1287 GIOStatus ret;
1288 char *str;
1289
1290 if( !(G_IO_IN & condition) )
1291 return FALSE;
1292 ret = g_io_channel_read_line(source, &str, NULL, NULL, NULL);
1293 if( ret != G_IO_STATUS_NORMAL )
1294 return FALSE;
1295
1296 if( !strncmp(str, "quit", 4) || !strncmp(str, "exit",4))
1297 gtk_main_quit();
1298 else if( !strncmp(str, "reset", 5) )
1299 {
d6ba7c28
AG
1300 switch_to_input_user();
1301 }
1302 else if( !strncmp(str, "password", 8))
1303 {
1304 switch_to_input_passwd();
9931e273
DB
1305 }
1306 g_free(str);
1307 return TRUE;
1308}
1309
1310void listen_stdin(void)
1311{
1312 greeter_io = g_io_channel_unix_new(0);
1313 g_io_add_watch(greeter_io, G_IO_IN, on_lxdm_command, NULL);
1314}
1315
1316static void apply_theme(const char* theme_name)
1317{
1318 char* theme_dir = g_build_filename(LXDM_DATA_DIR "/themes", theme_name, NULL);
1319 char *rc;
1320
1321#if GTK_CHECK_VERSION(3,0,0)
1322 ui_file = g_build_filename(theme_dir, "greeter-gtk3.ui", NULL);
1323 rc=g_build_filename(theme_dir, "gtk.css", NULL);
1324 GtkCssProvider *css=gtk_css_provider_new();
1325 gtk_css_provider_load_from_path(css,rc,NULL);
1326 g_free(rc);
1327 gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
1328 GTK_STYLE_PROVIDER(css),
1329 GTK_STYLE_PROVIDER_PRIORITY_USER);
1330#else
1331 ui_file = g_build_filename(theme_dir, "greeter.ui", NULL);
1332 rc = g_build_filename(theme_dir, "gtkrc", NULL);
1333 if( g_file_test(rc, G_FILE_TEST_EXISTS) )
1334 {
1335 gtk_rc_parse(rc);
1336 }
1337 g_free(rc);
1338#endif
1339
1340 if( !g_file_test(ui_file, G_FILE_TEST_EXISTS) )
1341 {
1342 g_free(ui_file);
1343 ui_file = NULL;
1344 }
1345
1346#if GTK_CHECK_VERSION(3,0,0)
1347
1348#endif
1349
1350 ui_nobody = g_build_filename(theme_dir, "nobody.png", NULL);
1351 if( !g_file_test(ui_nobody, G_FILE_TEST_EXISTS) )
1352 {
1353 g_free(ui_nobody);
1354 ui_nobody = NULL;
1355 }
1356
1357 g_free(theme_dir);
1358}
1359
1360int main(int arc, char *arg[])
1361{
1362 char* theme_name;
1363 GtkSettings *settings;
1364 int i;
1365
1366 /* this will override LC_MESSAGES */
1367 unsetenv("LANGUAGE");
1368
1369#if !GTK_CHECK_VERSION(3,0,0)
1370 gtk_set_locale();
1371#endif
1372 bindtextdomain("lxdm", "/usr/share/locale");
1373 textdomain("lxdm");
1374
1375 config = g_key_file_new();
1376 g_key_file_load_from_file(config, CONFIG_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL);
1377 var_config = g_key_file_new();
1378 g_key_file_set_list_separator(var_config, ' ');
1379 g_key_file_load_from_file(var_config,VCONFIG_FILE,G_KEY_FILE_KEEP_COMMENTS, NULL);
1380
1381 gtk_init(&arc, &arg);
1382 for(i=1;i<arc;i++)
1383 {
1384 if(!strcmp(arg[i],"--auto-login"))
1385 {
1386 auto_login=g_key_file_get_integer(config,"base","timeout",NULL);
1387 }
1388 }
1389
1390 settings=gtk_settings_get_default();
1391 if(settings)
1392 {
1393 setenv("GTK_IM_MODULE","gtk-im-context-simple",1);
1394 gtk_settings_set_string_property(settings,"gtk-im-module","gtk-im-context-simple",0);
1395 gtk_settings_set_long_property(settings,"gtk-show-input-method-menu",0,0);
1396 }
1397
1398 /* set gtk+ theme */
1399 theme_name = g_key_file_get_string(config, "display", "gtk_theme", NULL);
1400 if(theme_name)
1401 {
1402 if(settings)
1403 g_object_set(settings, "gtk-theme-name", theme_name, NULL);
1404 g_free(theme_name);
1405 }
1406
1407 /* load gtkrc-based themes */
1408 theme_name = g_key_file_get_string(config, "display", "theme", NULL);
1409 if( theme_name ) /* theme is specified */
1410 {
1411 apply_theme(theme_name);
1412 g_free(theme_name);
1413 }
1414
1415 /* create the login window */
1416 create_win();
1417 listen_stdin();
1418 /* use line buffered stdout for inter-process-communcation of
1419 * single-line-commands */
1420 setvbuf(stdout, NULL, _IOLBF, 0 );
1421
1422 if(auto_login)
1423 {
1424 g_timeout_add_seconds(auto_login,autologin_timeout,NULL);
1425 }
1426 gtk_main();
1427
1428 g_key_file_free(config);
1429 g_key_file_free(var_config);
1430
1431 return 0;
1432}