~ubuntu-branches/ubuntu/utopic/lxdm/utopic

« back to all changes in this revision

Viewing changes to .pc/90_simple_expose.patch/src/greeter.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Lavergne
  • Date: 2011-03-20 00:31:24 UTC
  • Revision ID: james.westby@ubuntu.com-20110320003124-sbbwz38khs8l6gb0
Tags: 0.3.0-0ubuntu5
* debian/patches/90_simple_expose.patch
 - From upstream, rework the expose-event callback which have a high CPU
   usage (LP: #733912)
* debian/patches/20_disable_resize_grip.patch
 - Disable resize grip which break the background drawing (LP: #703658)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include <stdlib.h>
 
33
#include <sys/stat.h>
 
34
 
 
35
#include "lxcom.h"
 
36
 
 
37
enum {
 
38
    COL_SESSION_NAME,
 
39
    COL_SESSION_EXEC,
 
40
    COL_SESSION_DESKTOP_FILE,
 
41
    N_SESSION_COLS
 
42
};
 
43
 
 
44
enum {
 
45
    COL_LANG_DISPNAME,
 
46
    COL_LANG,
 
47
    N_LANG_COLS
 
48
};
 
49
 
 
50
#define VCONFIG_FILE "/var/lib/lxdm/lxdm.conf"
 
51
 
 
52
static GKeyFile *config;
 
53
static GKeyFile * var_config;
 
54
static GtkWidget* win;
 
55
static GtkWidget* prompt;
 
56
static GtkWidget* login_entry;
 
57
static GtkWidget* user_list;
 
58
 
 
59
static GtkWidget* sessions;
 
60
static GtkWidget* lang;
 
61
 
 
62
static GtkWidget* exit_btn;
 
63
 
 
64
static GtkWidget* exit_menu;
 
65
static GtkWidget *lang_menu;
 
66
 
 
67
static char* user = NULL;
 
68
static char* pass = NULL;
 
69
static char* session_exec = NULL;
 
70
static char* session_desktop_file = NULL;
 
71
 
 
72
static char* ui_file = NULL;
 
73
static char *ui_nobody = NULL;
 
74
 
 
75
static GdkPixbuf *bg_img = NULL;
 
76
static GdkColor bg_color = {0};
 
77
 
 
78
static GIOChannel *greeter_io;
 
79
 
 
80
static void do_reboot(void)
 
81
{
 
82
    printf("reboot\n");
 
83
}
 
84
 
 
85
static void do_shutdown(void)
 
86
{
 
87
    printf("shutdown\n");
 
88
}
 
89
 
 
90
static void on_screen_size_changed(GdkScreen* scr, GtkWindow* win)
 
91
{
 
92
    gtk_window_resize( win, gdk_screen_get_width(scr), gdk_screen_get_height(scr) );
 
93
}
 
94
 
 
95
static void on_entry_activate(GtkEntry* entry)
 
96
{
 
97
        char* tmp;
 
98
        if( !user )
 
99
        {
 
100
                user = g_strdup( gtk_entry_get_text( GTK_ENTRY(entry) ) );
 
101
                gtk_entry_set_text(GTK_ENTRY(entry), "");
 
102
                gtk_label_set_text( GTK_LABEL(prompt), _("Password:") );
 
103
                if(strchr(user, ' '))
 
104
                {
 
105
                        g_free(user);
 
106
                        user = NULL;
 
107
                        return;
 
108
                }
 
109
                gtk_entry_set_visibility(entry, FALSE);
 
110
        }
 
111
        else
 
112
        {
 
113
                GtkTreeIter it;
 
114
                char *session_lang = "";
 
115
 
 
116
                if( gtk_combo_box_get_active_iter(GTK_COMBO_BOX(sessions), &it) )
 
117
                {
 
118
                        GtkTreeModel* model = gtk_combo_box_get_model( GTK_COMBO_BOX(sessions) );
 
119
                        gtk_tree_model_get(model, &it, 1, &session_exec, 2, &session_desktop_file, -1);
 
120
                }
 
121
                else
 
122
                {
 
123
                        /* FIXME: fatal error */
 
124
                }
 
125
 
 
126
                tmp = g_strdup( gtk_entry_get_text(entry) );
 
127
                pass=g_base64_encode((guchar*)tmp,strlen(tmp)+1);
 
128
                g_free(tmp);
 
129
 
 
130
                if( lang && gtk_combo_box_get_active_iter(GTK_COMBO_BOX(lang), &it) )
 
131
                {
 
132
                        GtkTreeModel* model = gtk_combo_box_get_model( GTK_COMBO_BOX(lang) );
 
133
                        gtk_tree_model_get(model, &it, 1, &session_lang, -1);
 
134
                        //FIXME: is session leaked?
 
135
                }
 
136
 
 
137
                tmp = g_key_file_get_string(var_config, "base", "last_session", NULL);
 
138
                if( g_strcmp0(tmp, session_desktop_file) )
 
139
                {
 
140
                        g_key_file_set_string(var_config, "base", "last_session", session_desktop_file);
 
141
                }
 
142
                g_free(tmp);
 
143
 
 
144
                tmp = g_key_file_get_string(var_config, "base", "last_lang", NULL);
 
145
                if( g_strcmp0(tmp, session_lang) )
 
146
                {
 
147
                        g_key_file_set_string(var_config, "base", "last_lang", session_lang);
 
148
                }
 
149
                g_free(tmp);
 
150
 
 
151
                printf("login user=%s pass=%s session=%s lang=%s\n",
 
152
                        user, pass, session_exec, session_lang);
 
153
 
 
154
                /* password check failed */
 
155
                g_free(user);
 
156
                user = NULL;
 
157
                g_free(pass);
 
158
                pass = NULL;
 
159
 
 
160
                gtk_widget_hide(prompt);
 
161
                gtk_widget_hide( GTK_WIDGET(entry) );
 
162
 
 
163
                gtk_label_set_text( GTK_LABEL(prompt), _("User:") );
 
164
                gtk_entry_set_text(GTK_ENTRY(entry), "");
 
165
                gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE);
 
166
        }
 
167
}
 
168
 
 
169
static void load_sessions()
 
170
{
 
171
        GtkListStore* list;
 
172
        GtkTreeIter it, active_it = {0};
 
173
        char* last;
 
174
        char *path, *file_name, *name, *exec;
 
175
        GKeyFile* kf;
 
176
        GDir* dir = g_dir_open(XSESSIONS_DIR, 0, NULL);
 
177
        if( !dir )
 
178
                return;
 
179
 
 
180
        last = g_key_file_get_string(var_config, "base", "last_session", NULL);
 
181
 
 
182
        list = gtk_list_store_new(N_SESSION_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
 
183
        kf = g_key_file_new();
 
184
        while( ( file_name = (char*)g_dir_read_name(dir) ) != NULL )
 
185
        {
 
186
                path = g_build_filename(XSESSIONS_DIR, file_name, NULL);
 
187
                if( g_key_file_load_from_file(kf, path, 0, NULL) )
 
188
                {
 
189
                        name = g_key_file_get_locale_string(kf, "Desktop Entry", "Name", NULL, NULL);
 
190
                        if(!name || !name[0])
 
191
                        {
 
192
                                g_free(name);
 
193
                                g_free(path);
 
194
                                continue;
 
195
                        }
 
196
            exec = g_key_file_get_string(kf, "Desktop Entry", "Exec", NULL);
 
197
                        if(!exec || !exec[0])
 
198
                        {
 
199
                                /* bad session config file */
 
200
                                g_free(exec);
 
201
                                g_free(name);
 
202
                                g_free(path);
 
203
                                continue;
 
204
                        }
 
205
                        g_free(exec); /* we just test it, and not use it */
 
206
            exec=g_strdup(path);
 
207
 
 
208
            if( !strcmp(name, "LXDE") )
 
209
                gtk_list_store_prepend(list, &it);
 
210
            else
 
211
                gtk_list_store_append(list, &it);
 
212
            gtk_list_store_set(list, &it,
 
213
                               COL_SESSION_NAME, name,
 
214
                               COL_SESSION_EXEC, exec,
 
215
                               COL_SESSION_DESKTOP_FILE, file_name, -1);
 
216
            if( last && g_strcmp0(path, last) == 0 )
 
217
            {
 
218
                active_it = it;
 
219
                        }
 
220
 
 
221
            g_free(name);
 
222
            g_free(exec);
 
223
        }
 
224
        g_free(path);
 
225
    }
 
226
        g_dir_close(dir);
 
227
        g_key_file_free(kf);
 
228
 
 
229
        gtk_list_store_prepend(list, &it);
 
230
        gtk_list_store_set(list, &it,
 
231
                                           COL_SESSION_NAME, _("Default"),
 
232
                                           COL_SESSION_EXEC, "",
 
233
                                           COL_SESSION_DESKTOP_FILE, "__default__", -1);
 
234
        if( last && g_strcmp0("__default__", last) == 0 )
 
235
                active_it = it;
 
236
 
 
237
        g_free(last);
 
238
        gtk_combo_box_set_model( GTK_COMBO_BOX(sessions), GTK_TREE_MODEL(list) );
 
239
#if GTK_CHECK_VERSION(2,23,90)
 
240
        gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(sessions), 0);
 
241
#else
 
242
        gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(sessions), 0);
 
243
#endif
 
244
        if( active_it.stamp )
 
245
                gtk_combo_box_set_active_iter(GTK_COMBO_BOX(sessions), &active_it);
 
246
        else
 
247
                gtk_combo_box_set_active(GTK_COMBO_BOX(sessions), 0);
 
248
 
 
249
        g_object_unref(list);
 
250
}
 
251
 
 
252
static void load_lang_cb(void *arg, char *lang, char *desc)
 
253
{
 
254
    GtkListStore* list = (GtkListStore*)arg;
 
255
    GtkTreeIter it;
 
256
    gchar *temp,*p,*lang2;
 
257
 
 
258
    lang2=g_strdup(lang);
 
259
    p=strchr(lang2,'.');
 
260
    if(p) *p=0;
 
261
 
 
262
    if(lang2[0] && lang2[0]!='~')
 
263
        temp=g_strdup_printf("%s\t%s",lang2,desc?desc:"");
 
264
    else
 
265
        temp=g_strdup(desc);
 
266
    g_free(lang2);
 
267
    gtk_list_store_append(list, &it);
 
268
    gtk_list_store_set(list, &it,
 
269
                       COL_LANG_DISPNAME, temp,
 
270
                       COL_LANG, lang, -1);
 
271
    g_free(temp);
 
272
}
 
273
 
 
274
static gint lang_cmpr(GtkTreeModel *list,GtkTreeIter *a,GtkTreeIter *b,gpointer user_data)
 
275
{
 
276
        gint ret;
 
277
        gchar *as,*bs;
 
278
        gtk_tree_model_get(list,a,1,&as,-1);
 
279
        gtk_tree_model_get(list,b,1,&bs,-1);
 
280
        ret=strcmp(as,bs);
 
281
        g_free(as);g_free(bs);
 
282
        return ret;
 
283
}
 
284
 
 
285
static void on_menu_lang_select(GtkMenuItem *item,gpointer user_data)
 
286
{
 
287
        GtkTreeIter iter;
 
288
        char *sel=(char*)user_data;
 
289
        int i;
 
290
        gboolean res;
 
291
        GtkTreeModel *list;
 
292
        int active=-1;
 
293
        char *temp;
 
294
        if(!sel || !sel[0]) return;
 
295
        
 
296
        list=gtk_combo_box_get_model(GTK_COMBO_BOX(lang));
 
297
        res=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list),&iter);
 
298
        for(i=0;res==TRUE;i++)
 
299
        {
 
300
            gtk_tree_model_get(GTK_TREE_MODEL(list),&iter,1,&temp,-1);
 
301
            if(!strcmp(temp,sel))
 
302
            {
 
303
                 g_free(temp);
 
304
                 active=i;
 
305
                 break;
 
306
            }
 
307
            g_free(temp);
 
308
            res=gtk_tree_model_iter_next(GTK_TREE_MODEL(list),&iter);
 
309
        }
 
310
        if(active>=0)
 
311
        {
 
312
                gtk_combo_box_set_active(GTK_COMBO_BOX(lang),active);
 
313
                return;
 
314
        }
 
315
        gtk_list_store_append((GtkListStore*)list, &iter);
 
316
        temp=(char*)gtk_menu_item_get_label(item);
 
317
        gtk_list_store_set((GtkListStore*)list, &iter,
 
318
                       COL_LANG_DISPNAME, temp,
 
319
                       COL_LANG, sel, -1);
 
320
        gtk_combo_box_set_active_iter(GTK_COMBO_BOX(lang),&iter);
 
321
}
 
322
 
 
323
static void load_menu_lang_cb(void *arg, char *lang, char *desc)
 
324
{
 
325
        GtkWidget *menu=GTK_WIDGET(arg);
 
326
        GtkWidget* item;
 
327
 
 
328
        gchar *temp,*p,*lang2;
 
329
 
 
330
        lang2=g_strdup(lang);
 
331
        p=strchr(lang2,'.');
 
332
        if(p) *p=0;
 
333
 
 
334
        if(lang2[0] && lang2[0]!='~')
 
335
                temp=g_strdup_printf("%s\t%s",lang2,desc?desc:"");
 
336
        else
 
337
                temp=g_strdup(desc);
 
338
        g_free(lang2);
 
339
 
 
340
        item = gtk_menu_item_new_with_label(temp);
 
341
        g_signal_connect(item, "activate", G_CALLBACK(on_menu_lang_select), g_strdup(lang));
 
342
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
 
343
        g_free(temp);
 
344
}
 
345
 
 
346
static void show_all_languages(void)
 
347
{
 
348
        if(!lang_menu)
 
349
        {
 
350
                lang_menu=gtk_menu_new();
 
351
                lxdm_load_langs(var_config,TRUE,lang_menu,load_menu_lang_cb);
 
352
                gtk_widget_show_all(lang_menu);
 
353
        }
 
354
        gtk_menu_popup(GTK_MENU(lang_menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time());
 
355
}
 
356
 
 
357
static void on_lang_changed(GtkComboBox *widget)
 
358
{
 
359
        GtkTreeIter it;
 
360
        if( gtk_combo_box_get_active_iter(widget, &it) )
 
361
        {
 
362
                GtkListStore *list=(GtkListStore*)gtk_combo_box_get_model(GTK_COMBO_BOX(lang));
 
363
                char *lang=NULL;
 
364
                gtk_tree_model_get(GTK_TREE_MODEL(list), &it, 1, &lang, -1);
 
365
                if(lang[0]=='~')
 
366
                {
 
367
                        gtk_combo_box_set_active(widget,0);
 
368
                        show_all_languages();
 
369
                }
 
370
                g_free(lang);
 
371
        }
 
372
}
 
373
 
 
374
static void load_langs()
 
375
{
 
376
    GtkListStore* list;
 
377
    char* lang_str;
 
378
    int active = 0;
 
379
 
 
380
    list = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
 
381
    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(list),0,GTK_SORT_ASCENDING);
 
382
    gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list),0,lang_cmpr,NULL,NULL);
 
383
    lxdm_load_langs(var_config,FALSE,list, load_lang_cb);
 
384
    lang_str = g_key_file_get_string(var_config, "base", "last_lang", NULL);
 
385
    if(lang_str && lang_str[0])
 
386
    {
 
387
        gboolean res;
 
388
        GtkTreeIter iter;
 
389
        int i;
 
390
        res=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list),&iter);
 
391
        if(res) for(i=0;;i++)
 
392
        {
 
393
            gchar *lang;
 
394
            gtk_tree_model_get(GTK_TREE_MODEL(list),&iter,1,&lang,-1);
 
395
            if(!strcmp(lang,lang_str))
 
396
            {
 
397
                 g_free(lang);
 
398
                 active=i;
 
399
                 break;
 
400
            }
 
401
            g_free(lang);
 
402
            res=gtk_tree_model_iter_next(GTK_TREE_MODEL(list),&iter);
 
403
            if(!res) break;
 
404
        }
 
405
    }
 
406
    g_free(lang_str);
 
407
    gtk_combo_box_set_model( GTK_COMBO_BOX(lang), GTK_TREE_MODEL(list) );
 
408
#if GTK_CHECK_VERSION(2,23,90)
 
409
    gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(lang), 0);
 
410
#else
 
411
    gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(lang), 0);
 
412
#endif
 
413
    gtk_combo_box_set_active(GTK_COMBO_BOX(lang), active < 0 ? 0 : active);
 
414
    g_object_unref(list);
 
415
 
 
416
    g_signal_connect(G_OBJECT(lang),"changed",G_CALLBACK(on_lang_changed),NULL);
 
417
}
 
418
 
 
419
static void on_exit_clicked(GtkButton* exit_btn, gpointer user_data)
 
420
{
 
421
    gtk_menu_popup( GTK_MENU(exit_menu), NULL, NULL, NULL, NULL,
 
422
                   0, gtk_get_current_event_time() );
 
423
}
 
424
 
 
425
static void load_exit()
 
426
{
 
427
    GtkWidget* item;
 
428
    exit_menu = gtk_menu_new();
 
429
    item = gtk_image_menu_item_new_with_mnemonic( _("_Reboot") );
 
430
    g_signal_connect(item, "activate", G_CALLBACK(do_reboot), NULL);
 
431
    gtk_menu_shell_append(GTK_MENU_SHELL(exit_menu), item);
 
432
 
 
433
    item = gtk_image_menu_item_new_with_mnemonic( _("_Shutdown") );
 
434
    g_signal_connect(item, "activate", G_CALLBACK(do_shutdown), NULL);
 
435
    gtk_menu_shell_append(GTK_MENU_SHELL(exit_menu), item);
 
436
 
 
437
    gtk_widget_show_all(exit_menu);
 
438
    g_signal_connect(exit_btn, "clicked", G_CALLBACK(on_exit_clicked), NULL);
 
439
}
 
440
 
 
441
static gboolean on_expose(GtkWidget* widget, GdkEventExpose* evt, gpointer user_data)
 
442
{
 
443
    cairo_t *cr;
 
444
 
 
445
#if GTK_CHECK_VERSION(2,18,0)
 
446
    if(! gtk_widget_get_has_window(widget))
 
447
#else
 
448
    if( !GTK_WIDGET_REALIZED(widget) )
 
449
#endif
 
450
        return FALSE;
 
451
#if GTK_CHECK_VERSION(2,14,0)
 
452
    cr = gdk_cairo_create(gtk_widget_get_window(widget));
 
453
#else
 
454
    cr = gdk_cairo_create(widget->window);
 
455
#endif
 
456
    if( bg_img )
 
457
    {
 
458
        cairo_matrix_t matrix;
 
459
        double x = 0, y = 0, sx, sy;
 
460
        cairo_get_matrix(cr, &matrix);
 
461
        sx = (double)gdk_screen_width() / (double)gdk_pixbuf_get_width(bg_img);
 
462
        sy = (double)gdk_screen_height() / (double)gdk_pixbuf_get_height(bg_img);
 
463
        cairo_scale(cr, sx, sy);
 
464
        gdk_cairo_set_source_pixbuf(cr, bg_img, x, y);
 
465
        cairo_paint(cr);
 
466
        cairo_set_matrix(cr, &matrix);
 
467
    }
 
468
    else
 
469
    {
 
470
        gdk_cairo_set_source_color(cr, &bg_color);
 
471
        cairo_rectangle( cr, 0, 0, gdk_screen_width(), gdk_screen_height() );
 
472
        cairo_fill(cr);
 
473
    }
 
474
    cairo_destroy(cr);
 
475
    return FALSE;
 
476
}
 
477
 
 
478
static gboolean on_combobox_entry_button_release(GtkWidget* w, GdkEventButton* evt, GtkComboBox* combo)
 
479
{
 
480
    gboolean shown;
 
481
    g_object_get(combo, "popup-shown", &shown, NULL);
 
482
    if( shown )
 
483
        gtk_combo_box_popdown(combo);
 
484
    else
 
485
        gtk_combo_box_popup(combo);
 
486
    return FALSE;
 
487
}
 
488
 
 
489
static void fix_combobox_entry(GtkWidget* combo)
 
490
{
 
491
    GtkWidget* edit = gtk_bin_get_child(GTK_BIN(combo));
 
492
    gtk_editable_set_editable( (GtkEditable*)edit, FALSE );
 
493
#if GTK_CHECK_VERSION(2,18,0)
 
494
    gtk_widget_set_can_focus(edit, FALSE);
 
495
#else
 
496
    GTK_WIDGET_UNSET_FLAGS(edit, GTK_CAN_FOCUS);
 
497
#endif
 
498
    g_signal_connect(edit, "button-release-event", G_CALLBACK(on_combobox_entry_button_release), combo);
 
499
}
 
500
 
 
501
static void on_evt_box_expose(GtkWidget* widget, GdkEventExpose* evt, gpointer user_data)
 
502
{
 
503
#if GTK_CHECK_VERSION(2,18,0)
 
504
    if (gtk_widget_is_drawable(widget))
 
505
#else
 
506
    if (GTK_WIDGET_DRAWABLE (widget))
 
507
#endif
 
508
    {
 
509
        GtkWidgetClass* klass = (GtkWidgetClass*)G_OBJECT_GET_CLASS(widget);
 
510
        gtk_paint_flat_box (gtk_widget_get_style(widget),
 
511
#if GTK_CHECK_VERSION(2,14,0)
 
512
                            gtk_widget_get_window(widget),
 
513
#else
 
514
                            widget->window,
 
515
#endif
 
516
#if GTK_CHECK_VERSION(2,18,0)
 
517
                gtk_widget_get_state(widget), GTK_SHADOW_NONE,
 
518
#else
 
519
                widget->state, GTK_SHADOW_NONE,
 
520
#endif
 
521
                &evt->area, widget, "eventbox",
 
522
                0, 0, -1, -1);
 
523
        klass->expose_event (widget, evt);
 
524
    }
 
525
}
 
526
 
 
527
static gboolean on_timeout(GtkLabel* label)
 
528
{
 
529
    char buf[128];
 
530
    time_t t;
 
531
    struct tm* tmbuf;
 
532
    time(&t);
 
533
    tmbuf = localtime(&t);
 
534
    strftime(buf, 128, "%c", tmbuf);
 
535
    gtk_label_set_text(label, buf);
 
536
    return TRUE;
 
537
}
 
538
 
 
539
static void on_user_select(GtkIconView *iconview)
 
540
{
 
541
        GList *list=gtk_icon_view_get_selected_items(iconview);
 
542
        GtkTreeIter iter;
 
543
        GtkTreeModel *model=gtk_icon_view_get_model(iconview);
 
544
        char *name;
 
545
        if(!list) return;
 
546
        gtk_tree_model_get_iter(model,&iter,list->data);
 
547
        g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
 
548
        g_list_free (list);
 
549
        gtk_tree_model_get(model,&iter,2,&name,-1);
 
550
        gtk_widget_hide(user_list);
 
551
        if(name && name[0])
 
552
        {
 
553
                gtk_entry_set_text(GTK_ENTRY(login_entry),name);
 
554
                g_free(name);
 
555
                on_entry_activate(GTK_ENTRY(login_entry));
 
556
                gtk_widget_show(login_entry);
 
557
                gtk_widget_grab_focus(login_entry);
 
558
                
 
559
                gtk_label_set_text( GTK_LABEL(prompt), _("Password:") );
 
560
                gtk_widget_show(prompt);
 
561
        }
 
562
        else
 
563
        {
 
564
                g_free(name);
 
565
                if(user)
 
566
                {
 
567
                        g_free(user);
 
568
                        user=NULL;
 
569
                }
 
570
                gtk_entry_set_text(GTK_ENTRY(login_entry),"");
 
571
                gtk_widget_show(login_entry);
 
572
                gtk_widget_grab_focus(login_entry);
 
573
                gtk_label_set_text( GTK_LABEL(prompt), _("User:") );
 
574
                gtk_widget_show(prompt);
 
575
        }
 
576
}
 
577
 
 
578
static gboolean load_user_list(GtkWidget *widget)
 
579
{
 
580
        GtkListStore *model;
 
581
        GtkTreeIter iter;
 
582
        GKeyFile *kf;
 
583
        char *res=NULL;
 
584
        char **users;
 
585
        gsize count;
 
586
        int i;
 
587
        lxcom_send("/var/run/lxdm/lxdm.sock","USER_LIST",&res);
 
588
        if(!res)
 
589
        {
 
590
                printf("log USER_LIST fail\n");
 
591
                return FALSE;
 
592
        }
 
593
        kf=g_key_file_new();
 
594
        if(!g_key_file_load_from_data(kf,res,-1,0,NULL))
 
595
        {
 
596
                g_key_file_free(kf);
 
597
                g_free(res);
 
598
                printf("log USER_LIST data bad\n");
 
599
                return FALSE;
 
600
        }
 
601
        g_free(res);
 
602
        
 
603
        gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(widget),GTK_SELECTION_SINGLE);
 
604
        gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(widget),0);
 
605
        gtk_icon_view_set_markup_column(GTK_ICON_VIEW(widget),1);
 
606
        gtk_icon_view_set_orientation(GTK_ICON_VIEW(widget),GTK_ORIENTATION_HORIZONTAL);
 
607
        model=gtk_list_store_new(5,GDK_TYPE_PIXBUF,G_TYPE_STRING,
 
608
                        G_TYPE_STRING,G_TYPE_STRING,G_TYPE_BOOLEAN);
 
609
        gtk_icon_view_set_model(GTK_ICON_VIEW(widget),GTK_TREE_MODEL(model));
 
610
        g_signal_connect(G_OBJECT(widget),"item-activated",G_CALLBACK(on_user_select),NULL);
 
611
        g_signal_connect(G_OBJECT(widget),"selection-changed",G_CALLBACK(on_user_select),NULL);
 
612
        
 
613
        users=g_key_file_get_groups(kf,&count);
 
614
        if(!users || count<=0)
 
615
        {
 
616
                g_key_file_free(kf);
 
617
                printf("USER_LIST 0 user\n");
 
618
                return FALSE;
 
619
        }
 
620
        if(count>3)
 
621
        {
 
622
                // TODO: better ui needed
 
623
                count=3;
 
624
        }
 
625
        for(i=0;i<count;i++)
 
626
        {               
 
627
                char *gecos,*face_path,*display;
 
628
                gboolean login;
 
629
                GdkPixbuf *face=NULL;
 
630
                gtk_list_store_append(model,&iter);
 
631
                gecos=g_key_file_get_string(kf,users[i],"gecos",0);
 
632
                face_path=g_key_file_get_string(kf,users[i],"face",0);
 
633
                login=g_key_file_get_boolean(kf,users[i],"login",0);
 
634
                if(face_path)
 
635
                        face=gdk_pixbuf_new_from_file_at_scale(face_path,48,48,TRUE,NULL);
 
636
                if(!face)
 
637
                {
 
638
                        /* TODO: load some default face */
 
639
                        face=gdk_pixbuf_new_from_file_at_scale(ui_nobody,48,48,TRUE,NULL);
 
640
                }
 
641
                display=g_strdup_printf("<span font_size=\"x-large\">%s</span>%s%s%s%s",
 
642
                        gecos?gecos:users[i],
 
643
                        (gecos&&strcmp(gecos,users[i]))?"(":"",
 
644
                        (gecos&&strcmp(gecos,users[i]))?users[i]:"",
 
645
                        (gecos&&strcmp(gecos,users[i]))?")":"",
 
646
                        login?_("\n<i>logged in</i>"):"");
 
647
                // don't translate it now, not freeze
 
648
                gtk_list_store_set(model,&iter,0,face,1,display,2,users[i],3,gecos,4,login,-1);
 
649
                if(face) g_object_unref(G_OBJECT(face));
 
650
                g_free(display);
 
651
                g_free(gecos);
 
652
                g_free(face_path);
 
653
        }
 
654
        g_strfreev(users);
 
655
        g_key_file_free(kf);
 
656
        
 
657
        // add "More ..."
 
658
        gtk_list_store_append(model,&iter);
 
659
        gtk_list_store_set(model,&iter,1,_("More ..."),2,"",3,"",4,FALSE,-1);
 
660
        return TRUE;
 
661
}
 
662
 
 
663
static void create_win()
 
664
{
 
665
    GtkBuilder* builder;
 
666
    GdkScreen* scr;
 
667
    GSList* objs, *l;
 
668
    GtkWidget* w;
 
669
 
 
670
    builder = gtk_builder_new();
 
671
    gtk_builder_add_from_file(builder, ui_file ? ui_file : LXDM_DATA_DIR "/lxdm.glade", NULL);
 
672
    win = (GtkWidget*)gtk_builder_get_object(builder, "lxdm");
 
673
    /*
 
674
    Remove resize grip in Ubuntu 11.04 which break background painting
 
675
    see https://bugs.launchpad.net/ubuntu/+source/lxdm/+bug/703658
 
676
    */
 
677
    gtk_window_set_has_resize_grip(GTK_WINDOW(win), FALSE);
 
678
 
 
679
    /* set widget names according to their object id in GtkBuilder xml */
 
680
    objs = gtk_builder_get_objects(builder);
 
681
    for( l = objs; l; l = l->next )
 
682
    {
 
683
        GtkWidget* widget = (GtkWidget*)l->data;
 
684
        gtk_widget_set_name( widget, gtk_buildable_get_name( (GtkBuildable*)widget ) );
 
685
        char* path;
 
686
        gtk_widget_path(widget, NULL, &path, NULL);
 
687
    }
 
688
    g_slist_free(objs);
 
689
 
 
690
    if( bg_img ) /* only paint our own background if custom background image is set. */
 
691
    {
 
692
        gtk_widget_set_app_paintable(win, TRUE);
 
693
        g_signal_connect(win, "expose-event", G_CALLBACK(on_expose), NULL);
 
694
    } /* otherwise, let gtk theme paint it. */
 
695
 
 
696
    scr = gtk_widget_get_screen(win);
 
697
    g_signal_connect(scr, "size-changed", G_CALLBACK(on_screen_size_changed), win);
 
698
    
 
699
    user_list=(GtkWidget*)gtk_builder_get_object(builder,"user_list");
 
700
    if(user_list)
 
701
    {
 
702
                //TODO: load user list, connect select_changed,activate signal
 
703
                // Use GtkIconView may enough
 
704
        }
 
705
 
 
706
    prompt = (GtkWidget*)gtk_builder_get_object(builder, "prompt");
 
707
    login_entry = (GtkWidget*)gtk_builder_get_object(builder, "login_entry");
 
708
 
 
709
    g_signal_connect(login_entry, "activate", G_CALLBACK(on_entry_activate), NULL);
 
710
 
 
711
    sessions = (GtkWidget*)gtk_builder_get_object(builder, "sessions");
 
712
    gtk_widget_set_name(sessions, "sessions");
 
713
    fix_combobox_entry(sessions);
 
714
    load_sessions();
 
715
 
 
716
    w = (GtkWidget*)gtk_builder_get_object(builder, "bottom_pane");
 
717
    if( g_key_file_get_integer(config, "display", "bottom_pane", 0) )
 
718
    {
 
719
        /* hacks to let GtkEventBox paintable with gtk pixmap engine. */
 
720
#if GTK_CHECK_VERSION(2,18,0)
 
721
        if(gtk_widget_get_app_paintable(w))
 
722
#else
 
723
        if(GTK_WIDGET_APP_PAINTABLE(w))
 
724
#endif
 
725
            g_signal_connect(w, "expose-event", G_CALLBACK(on_evt_box_expose), NULL);
 
726
    }
 
727
    else
 
728
        gtk_event_box_set_visible_window(GTK_EVENT_BOX(w), FALSE);
 
729
 
 
730
    if( g_key_file_get_integer(config, "display", "lang", 0) == 0 )
 
731
    {
 
732
        GtkWidget *w;
 
733
        w = (GtkWidget*)gtk_builder_get_object(builder, "lang_box");
 
734
        if( w )
 
735
            gtk_widget_hide(w);
 
736
    }
 
737
    else
 
738
    {
 
739
        lang = (GtkWidget*)gtk_builder_get_object(builder, "lang");
 
740
        gtk_widget_set_name(lang, "lang");
 
741
        fix_combobox_entry(lang);
 
742
        load_langs();
 
743
    }
 
744
 
 
745
        if( (w = (GtkWidget*)gtk_builder_get_object(builder, "time"))!=NULL )
 
746
        {
 
747
                guint timeout = g_timeout_add(1000, (GSourceFunc)on_timeout, w);
 
748
                g_signal_connect_swapped(w, "destroy",
 
749
                        G_CALLBACK(g_source_remove), GUINT_TO_POINTER(timeout));
 
750
                on_timeout((GtkLabel*)w);
 
751
        }
 
752
 
 
753
        exit_btn = (GtkWidget*)gtk_builder_get_object(builder, "exit");
 
754
        load_exit();
 
755
 
 
756
        g_object_unref(builder);
 
757
 
 
758
        gtk_window_set_default_size( GTK_WINDOW(win), gdk_screen_get_width(scr), gdk_screen_get_height(scr) );
 
759
        gtk_window_present( GTK_WINDOW(win) );
 
760
        gtk_widget_realize(login_entry);
 
761
    
 
762
        if(user_list && !g_key_file_get_integer(config,"userlist","disable",NULL) && 
 
763
                        load_user_list(user_list))
 
764
        {
 
765
                gtk_widget_hide(login_entry);
 
766
        }
 
767
        else
 
768
        {
 
769
                if(user_list)
 
770
                {
 
771
                        gtk_widget_hide(user_list);
 
772
                        user_list=NULL;
 
773
                }
 
774
                gtk_widget_grab_focus(login_entry);
 
775
        }
 
776
}
 
777
 
 
778
int set_background(void)
 
779
{
 
780
    char *bg;
 
781
    char *style;
 
782
    GdkWindow* root = gdk_get_default_root_window();
 
783
    GdkCursor* cursor = gdk_cursor_new(GDK_LEFT_PTR);
 
784
 
 
785
    gdk_window_set_cursor(root, cursor);
 
786
 
 
787
    bg = g_key_file_get_string(config, "display", "bg", 0);
 
788
    if( !bg )
 
789
        bg = g_strdup("#222E45");
 
790
    style = g_key_file_get_string(config, "display", "bg_style", 0);
 
791
 
 
792
    if( bg )
 
793
    {
 
794
        if( bg[0] != '#' )
 
795
        {
 
796
            /* default the bg stretch */
 
797
            if(!style || strcmp(style, "stretch") == 0 )
 
798
            {
 
799
                GdkPixbuf *tmp=gdk_pixbuf_new_from_file(bg,0);
 
800
                if(tmp)
 
801
                {
 
802
                    bg_img=gdk_pixbuf_scale_simple(tmp,
 
803
                                                    gdk_screen_width(),
 
804
                                                    gdk_screen_height(),
 
805
                                                    GDK_INTERP_HYPER);
 
806
                    g_object_unref(tmp);
 
807
                }
 
808
            }
 
809
            else
 
810
            {
 
811
                bg_img = gdk_pixbuf_new_from_file(bg, 0);
 
812
            }
 
813
            if( !bg_img )
 
814
            {
 
815
                g_free(bg);
 
816
                bg = g_strdup("#222E45");
 
817
            }
 
818
        }
 
819
        if( bg[0] == '#' )
 
820
            gdk_color_parse(bg, &bg_color);
 
821
    }
 
822
    g_free(bg);
 
823
    g_free(style);
 
824
    return 0;
 
825
}
 
826
 
 
827
static gboolean on_lxdm_command(GIOChannel *source, GIOCondition condition, gpointer data)
 
828
{
 
829
        GIOStatus ret;
 
830
        char *str;
 
831
 
 
832
        if( !(G_IO_IN & condition) )
 
833
                return FALSE;
 
834
        ret = g_io_channel_read_line(source, &str, NULL, NULL, NULL);
 
835
        if( ret != G_IO_STATUS_NORMAL )
 
836
                return FALSE;
 
837
 
 
838
        if( !strncmp(str, "quit", 4) || !strncmp(str, "exit",4))
 
839
        gtk_main_quit();
 
840
        else if( !strncmp(str, "reset", 5) )
 
841
        {
 
842
                if(user)
 
843
                {
 
844
                        g_free(user);
 
845
                        user=NULL;
 
846
                }
 
847
                if(pass)
 
848
                {
 
849
                        g_free(pass);
 
850
                        pass=NULL;
 
851
                }
 
852
                gtk_label_set_text( GTK_LABEL(prompt), _("User:"));
 
853
                gtk_widget_show(prompt);
 
854
                if(user_list)
 
855
                {
 
856
                        gtk_widget_hide(login_entry);
 
857
                        gtk_icon_view_unselect_all(GTK_ICON_VIEW(user_list));
 
858
                        gtk_widget_show(user_list);
 
859
                }
 
860
                else
 
861
                {
 
862
                        gtk_widget_show(login_entry);
 
863
                        gtk_widget_grab_focus(login_entry);
 
864
                }
 
865
        }
 
866
        g_free(str);
 
867
        return TRUE;
 
868
}
 
869
 
 
870
void listen_stdin(void)
 
871
{
 
872
    greeter_io = g_io_channel_unix_new(0);
 
873
    g_io_add_watch(greeter_io, G_IO_IN, on_lxdm_command, NULL);
 
874
}
 
875
 
 
876
void set_root_background(void)
 
877
{
 
878
    GdkWindow *root = gdk_get_default_root_window();
 
879
 
 
880
    /* set background */
 
881
    if( !bg_img )
 
882
    {
 
883
        GdkColormap *map = (GdkColormap*)gdk_drawable_get_colormap(root);
 
884
        gdk_colormap_alloc_color(map, &bg_color, TRUE, TRUE);
 
885
        gdk_window_set_background(root, &bg_color);
 
886
    }
 
887
    else
 
888
    {
 
889
        GdkPixmap *pix = NULL;
 
890
        gdk_pixbuf_render_pixmap_and_mask(bg_img, &pix, NULL, 0);
 
891
        /* call x directly, because gdk will ref the pixmap */
 
892
        //gdk_window_set_back_pixmap(root,pix,FALSE);
 
893
        XSetWindowBackgroundPixmap( GDK_WINDOW_XDISPLAY(root),
 
894
                                   GDK_WINDOW_XID(root), GDK_PIXMAP_XID(pix) );
 
895
        g_object_unref(pix);
 
896
    }
 
897
    gdk_window_clear(root);
 
898
}
 
899
 
 
900
static void apply_theme(const char* theme_name)
 
901
{
 
902
    char* theme_dir = g_build_filename(LXDM_DATA_DIR "/themes", theme_name, NULL);
 
903
    char* rc = g_build_filename(theme_dir, "gtkrc", NULL);
 
904
 
 
905
    ui_file = g_build_filename(theme_dir, "greeter.ui", NULL);
 
906
 
 
907
    if( g_file_test(rc, G_FILE_TEST_EXISTS) )
 
908
    {
 
909
        gtk_rc_parse(rc);
 
910
    }
 
911
    g_free(rc);
 
912
 
 
913
    if( !g_file_test(ui_file, G_FILE_TEST_EXISTS) )
 
914
    {
 
915
        g_free(ui_file);
 
916
        ui_file = NULL;
 
917
    }
 
918
    
 
919
    ui_nobody = g_build_filename(theme_dir, "nobody.png", NULL);
 
920
    if( !g_file_test(ui_nobody, G_FILE_TEST_EXISTS) )
 
921
    {
 
922
        g_free(ui_nobody);
 
923
        ui_nobody = NULL;
 
924
    }
 
925
    
 
926
    g_free(theme_dir);
 
927
    
 
928
    
 
929
}
 
930
 
 
931
int main(int arc, char *arg[])
 
932
{
 
933
    char* theme_name;
 
934
    GtkSettings*p;
 
935
 
 
936
    config = g_key_file_new();
 
937
    g_key_file_load_from_file(config, CONFIG_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL);
 
938
 
 
939
    var_config = g_key_file_new();
 
940
    g_key_file_set_list_separator(var_config, ' ');
 
941
    g_key_file_load_from_file(var_config,VCONFIG_FILE,G_KEY_FILE_KEEP_COMMENTS, NULL);
 
942
 
 
943
    gtk_init(&arc, &arg);
 
944
 
 
945
    /* this will override LC_MESSAGES */
 
946
    unsetenv("LANGUAGE");
 
947
 
 
948
    bindtextdomain("lxdm", "/usr/share/locale");
 
949
    textdomain("lxdm");
 
950
 
 
951
    p=gtk_settings_get_default();
 
952
    if(p)
 
953
    {
 
954
        setenv("GTK_IM_MODULE","gtk-im-context-simple",1);
 
955
        gtk_settings_set_string_property(p,"gtk-im-module","gtk-im-context-simple",0);
 
956
        gtk_settings_set_long_property(p,"gtk-show-input-method-menu",0,0);
 
957
    }
 
958
 
 
959
    set_background();
 
960
    set_root_background();
 
961
 
 
962
    /* set gtk+ theme */
 
963
    theme_name = g_key_file_get_string(config, "display", "gtk_theme", NULL);
 
964
    if( theme_name )
 
965
    {
 
966
        GtkSettings* settings = gtk_settings_get_default();
 
967
        g_object_set(settings, "gtk-theme-name", theme_name, NULL);
 
968
        g_free(theme_name);
 
969
    }
 
970
 
 
971
    /* load gtkrc-based themes */
 
972
    theme_name = g_key_file_get_string(config, "display", "theme", NULL);
 
973
    if( theme_name ) /* theme is specified */
 
974
    {
 
975
        apply_theme(theme_name);
 
976
        g_free(theme_name);
 
977
    }
 
978
 
 
979
    /* create the login window */
 
980
    create_win();
 
981
    listen_stdin();
 
982
    /* use line buffered stdout for inter-process-communcation of
 
983
     * single-line-commands */
 
984
    setvbuf(stdout, NULL, _IOLBF, 0 );
 
985
 
 
986
    gtk_main();
 
987
 
 
988
    g_key_file_free(config);
 
989
    g_key_file_free(var_config);
 
990
 
 
991
    return 0;
 
992
}