~ubuntu-branches/ubuntu/trusty/lightdm-gtk-greeter/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/update-session-language.patch/src/lightdm-gtk-greeter.c

  • Committer: Package Import Robot
  • Author(s): Gunnar Hjalmarsson, Thaddäus Tintenfisch
  • Date: 2014-03-02 18:05:00 UTC
  • Revision ID: package-import@ubuntu.com-20140302180500-qga92kisqi02yi5m
Tags: 1.8.1-1ubuntu2
[ Thaddäus Tintenfisch ]
* debian/patches/update-session-language.patch:
  - Always update preselected session and language when another
    user is selected (LP: #1282139).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010-2011 Robert Ancell.
 
3
 * Author: Robert Ancell <robert.ancell@canonical.com>
 
4
 * 
 
5
 * This program is free software: you can redistribute it and/or modify it under
 
6
 * the terms of the GNU General Public License as published by the Free Software
 
7
 * Foundation, either version 3 of the License, or (at your option) any later
 
8
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
 
9
 * license.
 
10
 */
 
11
 
 
12
#ifdef HAVE_CONFIG_H
 
13
#include <config.h>
 
14
#endif
 
15
 
 
16
#ifdef HAVE_STDLIB_H
 
17
#include <stdlib.h>
 
18
#endif
 
19
 
 
20
#include <locale.h>
 
21
#include <gtk/gtk.h>
 
22
#include <glib/gi18n.h>
 
23
#include <cairo-xlib.h>
 
24
#include <sys/wait.h>
 
25
#include <X11/Xlib.h>
 
26
#include <X11/Xatom.h>
 
27
#include <gdk-pixbuf/gdk-pixbuf.h>
 
28
#include <gdk/gdkx.h>
 
29
#include <glib.h>
 
30
#if GTK_CHECK_VERSION (3, 0, 0)
 
31
#include <gtk/gtkx.h>
 
32
#else
 
33
#include <gdk/gdkkeysyms.h>
 
34
#endif
 
35
#include <glib/gslist.h>
 
36
 
 
37
#ifdef HAVE_LIBINDICATOR
 
38
#include <libindicator/indicator-object.h>
 
39
#ifdef HAVE_LIBINDICATOR_NG
 
40
#include <libindicator/indicator-ng.h>
 
41
#endif
 
42
#endif
 
43
 
 
44
#ifdef HAVE_LIBIDO
 
45
/* Some indicators need ido library */
 
46
#include "libido/libido.h"
 
47
#endif
 
48
 
 
49
#include <lightdm.h>
 
50
 
 
51
#include <src/lightdm-gtk-greeter-ui.h>
 
52
 
 
53
static LightDMGreeter *greeter;
 
54
static GKeyFile *state;
 
55
static gchar *state_filename;
 
56
 
 
57
/* Defaults */
 
58
static gchar *default_font_name, *default_theme_name, *default_icon_theme_name;
 
59
static GdkPixbuf *default_background_pixbuf = NULL;
 
60
static GdkPixbuf *background_pixbuf = NULL;
 
61
 
 
62
/* Panel Widgets */
 
63
static GtkWindow *panel_window;
 
64
static GtkWidget *clock_label;
 
65
static GtkWidget *menubar, *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem, *session_badge;
 
66
static GtkWidget *suspend_menuitem, *hibernate_menuitem, *restart_menuitem, *shutdown_menuitem;
 
67
static GtkWidget *keyboard_menuitem;
 
68
static GtkMenu *session_menu, *language_menu;
 
69
 
 
70
/* Login Window Widgets */
 
71
static GtkWindow *login_window;
 
72
static GtkImage *user_image;
 
73
static GtkComboBox *user_combo;
 
74
static GtkEntry *username_entry, *password_entry;
 
75
static GtkLabel *message_label;
 
76
static GtkInfoBar *info_bar;
 
77
static GtkButton *cancel_button, *login_button;
 
78
 
 
79
static gchar *clock_format;
 
80
static gchar **a11y_keyboard_command;
 
81
static GPid a11y_kbd_pid = 0;
 
82
static GError *a11y_keyboard_error;
 
83
static GtkWindow *onboard_window;
 
84
 
 
85
/* Pending Questions */
 
86
static GSList *pending_questions = NULL;
 
87
 
 
88
GSList *backgrounds = NULL;
 
89
 
 
90
/* Current choices */
 
91
static gchar *current_session;
 
92
static gchar *current_language;
 
93
 
 
94
/* Screensaver values */
 
95
int timeout, interval, prefer_blanking, allow_exposures;
 
96
 
 
97
#if GTK_CHECK_VERSION (3, 0, 0)
 
98
static GdkRGBA *default_background_color = NULL;
 
99
#else
 
100
static GdkColor *default_background_color = NULL;
 
101
#endif
 
102
static gboolean cancelling = FALSE, prompted = FALSE;
 
103
static gboolean prompt_active = FALSE, password_prompted = FALSE;
 
104
#if GTK_CHECK_VERSION (3, 0, 0)
 
105
#else
 
106
static GdkRegion *window_region = NULL;
 
107
#endif
 
108
 
 
109
typedef struct
 
110
{
 
111
  gboolean is_prompt;
 
112
  union {
 
113
    LightDMMessageType message;
 
114
    LightDMPromptType prompt;
 
115
  } type;
 
116
  gchar *text;
 
117
} PAMConversationMessage;
 
118
 
 
119
typedef struct
 
120
{
 
121
    gint value;
 
122
    /* +0 and -0 */
 
123
    gint sign;
 
124
    /* interpret 'value' as percentage of screen width/height */
 
125
    gboolean percentage;
 
126
    /* -1: left/top, 0: center, +1: right,bottom */
 
127
    gint anchor;
 
128
} DimensionPosition;
 
129
 
 
130
typedef struct
 
131
{
 
132
    DimensionPosition x, y;
 
133
} WindowPosition;
 
134
 
 
135
const WindowPosition CENTERED_WINDOW_POS = { .x = {50, +1, TRUE, 0}, .y = {50, +1, TRUE, 0} };
 
136
WindowPosition main_window_pos;
 
137
 
 
138
GdkPixbuf* default_user_pixbuf = NULL;
 
139
gchar* default_user_icon = "avatar-default";
 
140
 
 
141
static void
 
142
pam_message_finalize (PAMConversationMessage *message)
 
143
{
 
144
    g_free (message->text);
 
145
    g_free (message);
 
146
}
 
147
 
 
148
 
 
149
static void
 
150
add_indicator_to_panel (GtkWidget *indicator_item, gint index)
 
151
{
 
152
    gint insert_pos = 0;
 
153
    GList* items = gtk_container_get_children (GTK_CONTAINER (menubar));
 
154
    GList* item;
 
155
    for (item = items; item; item = item->next)
 
156
    {
 
157
        if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item->data), "indicator-custom-index-data")) < index)
 
158
            break;
 
159
        insert_pos++;
 
160
    }
 
161
    g_list_free (items);
 
162
 
 
163
    gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), GTK_WIDGET (indicator_item), insert_pos);
 
164
}
 
165
 
 
166
#ifdef HAVE_LIBINDICATOR
 
167
static gboolean
 
168
entry_scrolled (GtkWidget *menuitem, GdkEventScroll *event, gpointer data)
 
169
{
 
170
    IndicatorObject      *io;
 
171
    IndicatorObjectEntry *entry;
 
172
 
 
173
    g_return_val_if_fail (GTK_IS_WIDGET (menuitem), FALSE);
 
174
 
 
175
    io = g_object_get_data (G_OBJECT (menuitem), "indicator-custom-object-data");
 
176
    entry = g_object_get_data (G_OBJECT (menuitem), "indicator-custom-entry-data");
 
177
 
 
178
    g_return_val_if_fail (INDICATOR_IS_OBJECT (io), FALSE);
 
179
 
 
180
    g_signal_emit_by_name (io, "scroll", 1, event->direction);
 
181
    g_signal_emit_by_name (io, "scroll-entry", entry, 1, event->direction);
 
182
 
 
183
    return FALSE;
 
184
}
 
185
 
 
186
static void
 
187
entry_activated (GtkWidget *widget, gpointer user_data)
 
188
{
 
189
    IndicatorObject      *io;
 
190
    IndicatorObjectEntry *entry;
 
191
 
 
192
    g_return_if_fail (GTK_IS_WIDGET (widget));
 
193
 
 
194
    io = g_object_get_data (G_OBJECT (widget), "indicator-custom-object-data");
 
195
    entry = g_object_get_data (G_OBJECT (widget), "indicator-custom-entry-data");
 
196
 
 
197
    g_return_if_fail (INDICATOR_IS_OBJECT (io));
 
198
 
 
199
    return indicator_object_entry_activate (io, entry, gtk_get_current_event_time ());
 
200
}
 
201
 
 
202
static GtkWidget*
 
203
create_menuitem (IndicatorObject *io, IndicatorObjectEntry *entry, GtkWidget *menubar)
 
204
{
 
205
    GtkWidget *box, *menuitem;
 
206
    gint index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (io), "indicator-custom-index-data"));
 
207
 
 
208
#if GTK_CHECK_VERSION (3, 0, 0)
 
209
    box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
 
210
#else
 
211
    box = gtk_hbox_new (FALSE, 0);
 
212
#endif
 
213
    menuitem = gtk_menu_item_new ();
 
214
 
 
215
    gtk_widget_add_events(GTK_WIDGET(menuitem), GDK_SCROLL_MASK);
 
216
 
 
217
    g_object_set_data (G_OBJECT (menuitem), "indicator-custom-box-data", box);
 
218
    g_object_set_data (G_OBJECT (menuitem), "indicator-custom-object-data", io);
 
219
    g_object_set_data (G_OBJECT (menuitem), "indicator-custom-entry-data", entry);
 
220
    g_object_set_data (G_OBJECT (menuitem), "indicator-custom-index-data", GINT_TO_POINTER (index));
 
221
 
 
222
    g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (entry_activated), NULL);
 
223
    g_signal_connect (G_OBJECT (menuitem), "scroll-event", G_CALLBACK (entry_scrolled), NULL);
 
224
 
 
225
    if (entry->image)
 
226
        gtk_box_pack_start (GTK_BOX(box), GTK_WIDGET(entry->image), FALSE, FALSE, 1);
 
227
 
 
228
    if (entry->label)
 
229
        gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(entry->label), FALSE, FALSE, 1);
 
230
 
 
231
    if (entry->menu)
 
232
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), GTK_WIDGET (entry->menu));
 
233
 
 
234
    gtk_container_add (GTK_CONTAINER (menuitem), box);
 
235
    gtk_widget_show (box);
 
236
    add_indicator_to_panel (menuitem, index);
 
237
 
 
238
    return menuitem;
 
239
}
 
240
 
 
241
static void
 
242
entry_added (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data)
 
243
{
 
244
    GHashTable *menuitem_lookup;
 
245
    GtkWidget  *menuitem;
 
246
 
 
247
    /* if the menuitem doesn't already exist, create it now */
 
248
    menuitem_lookup = g_object_get_data (G_OBJECT (io), "indicator-custom-menuitems-data");
 
249
    g_return_if_fail (menuitem_lookup);
 
250
    menuitem = g_hash_table_lookup (menuitem_lookup, entry);
 
251
    if (!GTK_IS_WIDGET (menuitem))
 
252
    {
 
253
        menuitem = create_menuitem (io, entry, GTK_WIDGET (user_data));
 
254
        g_hash_table_insert (menuitem_lookup, entry, menuitem);
 
255
    }
 
256
 
 
257
    gtk_widget_show (menuitem);
 
258
}
 
259
 
 
260
static void
 
261
entry_removed_cb (GtkWidget *widget, gpointer userdata)
 
262
{
 
263
    IndicatorObject *io;
 
264
    GHashTable      *menuitem_lookup;
 
265
    GtkWidget       *menuitem;
 
266
    gpointer         entry;
 
267
 
 
268
    io = g_object_get_data (G_OBJECT (widget), "indicator-custom-object-data");
 
269
    if (!INDICATOR_IS_OBJECT (io))
 
270
        return;
 
271
 
 
272
    entry = g_object_get_data (G_OBJECT (widget), "indicator-custom-entry-data");
 
273
    if (entry != userdata)
 
274
        return;
 
275
 
 
276
    menuitem_lookup = g_object_get_data (G_OBJECT (io), "indicator-custom-menuitems-data");
 
277
    g_return_if_fail (menuitem_lookup);
 
278
    menuitem = g_hash_table_lookup (menuitem_lookup, entry);
 
279
    if (GTK_IS_WIDGET (menuitem))
 
280
        gtk_widget_hide (menuitem);
 
281
 
 
282
    gtk_widget_destroy (widget);
 
283
}
 
284
 
 
285
static void
 
286
entry_removed (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data)
 
287
{
 
288
    gtk_container_foreach (GTK_CONTAINER (user_data), entry_removed_cb, entry);
 
289
}
 
290
 
 
291
static void
 
292
menu_show (IndicatorObject *io, IndicatorObjectEntry *entry, guint32 timestamp, gpointer user_data)
 
293
{
 
294
    IndicatorObjectEntry *entrydata;
 
295
    GtkWidget            *menuitem;
 
296
    GList                *entries, *lp;
 
297
 
 
298
    menuitem = GTK_WIDGET (user_data);
 
299
 
 
300
    if (!entry)
 
301
    {
 
302
        /* Close any open menus instead of opening one */
 
303
        entries = indicator_object_get_entries (io);
 
304
        for (lp = entries; lp; lp = g_list_next (entry))
 
305
        {
 
306
            entrydata = lp->data;
 
307
            gtk_menu_popdown (entrydata->menu);
 
308
        }
 
309
        g_list_free (entries);
 
310
 
 
311
        /* And tell the menuitem to exit activation mode too */
 
312
        gtk_menu_shell_cancel (GTK_MENU_SHELL (menuitem));
 
313
    }
 
314
}
 
315
 
 
316
static void
 
317
greeter_set_env (const gchar* key, const gchar* value)
 
318
{
 
319
    g_setenv (key, value, TRUE);
 
320
 
 
321
    GDBusProxy* proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
 
322
                                                       G_DBUS_PROXY_FLAGS_NONE,
 
323
                                                       NULL,
 
324
                                                       "org.freedesktop.DBus",
 
325
                                                       "/org/freedesktop/DBus",
 
326
                                                       "org.freedesktop.DBus",
 
327
                                                       NULL, NULL);
 
328
    GVariant *result;
 
329
    GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
 
330
    g_variant_builder_add (builder, "{ss}", key, value);
 
331
    result = g_dbus_proxy_call_sync (proxy, "UpdateActivationEnvironment", g_variant_new ("(a{ss})", builder),
 
332
                                     G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL);
 
333
    g_variant_unref (result);
 
334
    g_variant_builder_unref (builder);
 
335
    g_object_unref (proxy);
 
336
}
 
337
#endif
 
338
 
 
339
static gboolean
 
340
menu_item_accel_closure_cb (GtkAccelGroup *accel_group,
 
341
                            GObject *acceleratable, guint keyval,
 
342
                            GdkModifierType modifier, gpointer data)
 
343
{
 
344
    gtk_menu_item_activate (data);
 
345
    return FALSE;
 
346
}
 
347
 
 
348
/* Maybe unnecessary (in future) trick to enable accelerators for hidden/detached menu items */
 
349
static void
 
350
reassign_menu_item_accel (GtkWidget *item)
 
351
{
 
352
    GtkAccelKey key;
 
353
    const gchar *accel_path = gtk_menu_item_get_accel_path (GTK_MENU_ITEM (item));
 
354
 
 
355
    if (accel_path && gtk_accel_map_lookup_entry (accel_path, &key))
 
356
    {
 
357
        GClosure *closure = g_cclosure_new (G_CALLBACK (menu_item_accel_closure_cb), item, NULL);
 
358
        gtk_accel_group_connect (gtk_menu_get_accel_group (GTK_MENU (gtk_widget_get_parent (item))),
 
359
                                 key.accel_key, key.accel_mods, key.accel_flags, closure);
 
360
        g_closure_unref (closure);
 
361
    }
 
362
 
 
363
    gtk_container_foreach (GTK_CONTAINER (gtk_menu_item_get_submenu (GTK_MENU_ITEM (item))),
 
364
                           (GtkCallback)reassign_menu_item_accel, NULL);
 
365
}
 
366
 
 
367
static void
 
368
#ifdef START_INDICATOR_SERVICES
 
369
init_indicators (GKeyFile* config, GPid* indicator_pid, GPid* spi_pid)
 
370
#else
 
371
init_indicators (GKeyFile* config)
 
372
#endif
 
373
{
 
374
    gchar **names = NULL;
 
375
    gsize length = 0;
 
376
    guint i;
 
377
    GHashTable *builtin_items = NULL;
 
378
    GHashTableIter iter;
 
379
    gpointer iter_value;
 
380
    gboolean inited = FALSE;
 
381
 
 
382
#ifdef START_INDICATOR_SERVICES
 
383
    GError *error = NULL;
 
384
    gchar *AT_SPI_CMD[] = {"/usr/lib/at-spi2-core/at-spi-bus-launcher", "--launch-immediately", NULL};
 
385
    gchar *INDICATORS_CMD[] = {"init", "--user", "--startup-event", "indicator-services-start", NULL};
 
386
#endif
 
387
 
 
388
    if (g_key_file_has_key (config, "greeter", "show-indicators", NULL))
 
389
    {
 
390
        names = g_key_file_get_string_list (config, "greeter", "show-indicators", &length, NULL);
 
391
        builtin_items = g_hash_table_new (g_str_hash, g_str_equal);
 
392
 
 
393
        g_hash_table_insert (builtin_items, "~power", power_menuitem);
 
394
        g_hash_table_insert (builtin_items, "~session", session_menuitem);
 
395
        g_hash_table_insert (builtin_items, "~language", language_menuitem);
 
396
        g_hash_table_insert (builtin_items, "~a11y", a11y_menuitem);
 
397
 
 
398
        g_hash_table_iter_init (&iter, builtin_items);
 
399
        while (g_hash_table_iter_next (&iter, NULL, &iter_value))
 
400
            gtk_container_remove (GTK_CONTAINER (menubar), iter_value);
 
401
    }
 
402
 
 
403
    for (i = 0; i < length; ++i)
 
404
    {
 
405
        if (names[i][0] == '~' && g_hash_table_lookup_extended (builtin_items, names[i], NULL, &iter_value))
 
406
        {   /* Built-in indicators */
 
407
            g_object_set_data (G_OBJECT (iter_value), "indicator-custom-index-data", GINT_TO_POINTER (i));
 
408
            add_indicator_to_panel (iter_value, i);
 
409
            g_hash_table_remove (builtin_items, (gconstpointer)names[i]);
 
410
            continue;
 
411
        }
 
412
 
 
413
        #ifdef HAVE_LIBINDICATOR
 
414
        gchar* path = NULL;
 
415
        IndicatorObject* io = NULL;
 
416
 
 
417
        if (!inited)
 
418
        {
 
419
            /* Set indicators to run with reduced functionality */
 
420
            greeter_set_env ("INDICATOR_GREETER_MODE", "1");
 
421
            /* Don't allow virtual file systems? */
 
422
            greeter_set_env ("GIO_USE_VFS", "local");
 
423
            greeter_set_env ("GVFS_DISABLE_FUSE", "1");
 
424
 
 
425
            #ifdef START_INDICATOR_SERVICES
 
426
            if (!g_spawn_async (NULL, AT_SPI_CMD, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, spi_pid, &error))
 
427
                g_warning ("Failed to run \"at-spi-bus-launcher\": %s", error->message);
 
428
            g_clear_error (&error);
 
429
 
 
430
            if (!g_spawn_async (NULL, INDICATORS_CMD, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, indicator_pid, &error))
 
431
                g_warning ("Failed to run \"indicator-services\": %s", error->message);
 
432
            g_clear_error (&error);
 
433
            #endif
 
434
            inited = TRUE;
 
435
        }
 
436
 
 
437
        if (g_path_is_absolute (names[i]))
 
438
        {   /* library with absolute path */
 
439
            io = indicator_object_new_from_file (names[i]);
 
440
        }
 
441
        else if (g_str_has_suffix (names[i], G_MODULE_SUFFIX))
 
442
        {   /* library */
 
443
            path = g_build_filename (INDICATOR_DIR, names[i], NULL);
 
444
            io = indicator_object_new_from_file (path);
 
445
        }
 
446
        #ifdef HAVE_LIBINDICATOR_NG
 
447
        else
 
448
        {   /* service file */
 
449
            if (strchr (names[i], '.'))
 
450
                path = g_strdup_printf ("%s/%s", UNITY_INDICATOR_DIR, names[i]);
 
451
            else
 
452
                path = g_strdup_printf ("%s/com.canonical.indicator.%s", UNITY_INDICATOR_DIR, names[i]);
 
453
            io = INDICATOR_OBJECT (indicator_ng_new_for_profile (path, "desktop_greeter", NULL));
 
454
        }
 
455
        #endif
 
456
 
 
457
        if (io)
 
458
        {
 
459
            GList *entries, *lp;
 
460
 
 
461
            /* used to store/fetch menu entries */
 
462
            g_object_set_data_full (G_OBJECT (io), "indicator-custom-menuitems-data",
 
463
                                    g_hash_table_new (g_direct_hash, g_direct_equal),
 
464
                                    (GDestroyNotify) g_hash_table_destroy);
 
465
            g_object_set_data (G_OBJECT (io), "indicator-custom-index-data", GINT_TO_POINTER (i));
 
466
 
 
467
            g_signal_connect (G_OBJECT (io), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED,
 
468
                              G_CALLBACK (entry_added), menubar);
 
469
            g_signal_connect (G_OBJECT (io), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED,
 
470
                              G_CALLBACK (entry_removed), menubar);
 
471
            g_signal_connect (G_OBJECT (io), INDICATOR_OBJECT_SIGNAL_MENU_SHOW,
 
472
                              G_CALLBACK (menu_show), menubar);
 
473
 
 
474
            entries = indicator_object_get_entries (io);
 
475
            for (lp = entries; lp; lp = g_list_next (lp))
 
476
                entry_added (io, lp->data, menubar);
 
477
            g_list_free (entries);
 
478
        }
 
479
        else
 
480
        {
 
481
            g_warning ("Indicator \"%s\": failed to load", names[i]);
 
482
        }
 
483
 
 
484
        g_free (path);
 
485
        #endif
 
486
    }
 
487
    if (names)
 
488
        g_strfreev (names);
 
489
 
 
490
    if (builtin_items)
 
491
    {
 
492
        g_hash_table_iter_init (&iter, builtin_items);
 
493
        while (g_hash_table_iter_next (&iter, NULL, &iter_value))
 
494
        {
 
495
            reassign_menu_item_accel (iter_value);
 
496
            gtk_widget_hide (iter_value);
 
497
        }
 
498
 
 
499
        g_hash_table_unref (builtin_items);
 
500
    }
 
501
}
 
502
 
 
503
static gchar *
 
504
get_session (void)
 
505
{
 
506
    GList *menu_items, *menu_iter;
 
507
 
 
508
    /* if the user manually selected a session, use it */
 
509
    if (current_session)
 
510
        return current_session;
 
511
 
 
512
    menu_items = gtk_container_get_children(GTK_CONTAINER(session_menu));
 
513
    
 
514
    for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
 
515
    {
 
516
        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_iter->data)))
 
517
        {
 
518
            return g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), "session-key"));
 
519
        }
 
520
    }
 
521
 
 
522
    return g_strdup (lightdm_greeter_get_default_session_hint (greeter));
 
523
}
 
524
 
 
525
static void
 
526
set_session (const gchar *session)
 
527
{
 
528
    const gchar *default_session;
 
529
    gchar *last_session;
 
530
    GList *menu_items, *menu_iter;
 
531
#if GTK_CHECK_VERSION (3, 0, 0)
 
532
    GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
 
533
#endif
 
534
 
 
535
    if (!gtk_widget_get_visible (session_menuitem))
 
536
    {
 
537
        current_session = g_strdup (session);
 
538
        return;
 
539
    }
 
540
 
 
541
    menu_items = gtk_container_get_children(GTK_CONTAINER(session_menu));
 
542
 
 
543
    if (session)
 
544
    {
 
545
        for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
 
546
        {
 
547
            gchar *s;
 
548
            gboolean matched;
 
549
            s = g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), "session-key"));
 
550
            matched = g_strcmp0 (s, session) == 0;
 
551
            g_free (s);
 
552
            if (matched)
 
553
            {
 
554
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_iter->data), TRUE);
 
555
                current_session = g_strdup(session);
 
556
                /* Set menuitem-image to session-badge */
 
557
#if GTK_CHECK_VERSION (3, 0, 0)
 
558
                if (gtk_icon_theme_has_icon(icon_theme, g_strdup_printf ("%s_badge-symbolic", g_ascii_strdown (session, strlen (session)))))
 
559
                    gtk_image_set_from_icon_name (GTK_IMAGE(session_badge), g_strdup_printf ("%s_badge-symbolic", g_ascii_strdown (session, strlen (session))), GTK_ICON_SIZE_MENU);
 
560
                else
 
561
                    gtk_image_set_from_icon_name (GTK_IMAGE(session_badge), "document-properties-symbolic", GTK_ICON_SIZE_MENU);
 
562
#endif
 
563
                return;
 
564
            }
 
565
        }
 
566
    }
 
567
    
 
568
    /* If failed to find this session, then try the previous, then the default */
 
569
    last_session = g_key_file_get_value (state, "greeter", "last-session", NULL);
 
570
    if (last_session && g_strcmp0 (session, last_session) != 0)
 
571
    {
 
572
        set_session (last_session);
 
573
        g_free (last_session);
 
574
        return;
 
575
    }
 
576
    g_free (last_session);
 
577
    
 
578
    default_session = lightdm_greeter_get_default_session_hint (greeter);
 
579
    if (default_session && g_strcmp0 (session, default_session) != 0)
 
580
    {
 
581
        set_session (lightdm_greeter_get_default_session_hint (greeter));
 
582
        return;
 
583
    }
 
584
    /* Otherwise just pick the first session */
 
585
    menu_iter = g_list_first(menu_items);
 
586
    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_iter->data), TRUE);
 
587
    return;
 
588
}
 
589
 
 
590
static gchar *
 
591
get_language (void)
 
592
{
 
593
    GList *menu_items, *menu_iter;
 
594
 
 
595
    /* if the user manually selected a language, use it */
 
596
    if (current_language)
 
597
        return current_language;
 
598
 
 
599
    menu_items = gtk_container_get_children(GTK_CONTAINER(language_menu));    
 
600
    for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
 
601
    {
 
602
        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_iter->data)))
 
603
        {
 
604
            return g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), "language-code"));
 
605
        }
 
606
    }
 
607
 
 
608
    return NULL;
 
609
}
 
610
 
 
611
static void
 
612
set_language (const gchar *language)
 
613
{
 
614
    const gchar *default_language = NULL;    
 
615
    GList *menu_items, *menu_iter;
 
616
 
 
617
    if (!gtk_widget_get_visible (language_menuitem))
 
618
    {
 
619
        current_language = g_strdup (language);
 
620
        return;
 
621
    }
 
622
 
 
623
    menu_items = gtk_container_get_children(GTK_CONTAINER(language_menu));
 
624
 
 
625
    if (language)
 
626
    {
 
627
        for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
 
628
        {
 
629
            gchar *s;
 
630
            gboolean matched;
 
631
            s = g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), "language-code"));
 
632
            matched = g_strcmp0 (s, language) == 0;
 
633
            g_free (s);
 
634
            if (matched)
 
635
            {
 
636
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_iter->data), TRUE);
 
637
                current_language = g_strdup(language);
 
638
                gtk_menu_item_set_label(GTK_MENU_ITEM(language_menuitem),language);
 
639
                return;
 
640
            }
 
641
        }
 
642
    }
 
643
 
 
644
    /* If failed to find this language, then try the default */
 
645
    if (lightdm_get_language ()) {
 
646
        default_language = lightdm_language_get_code (lightdm_get_language ());
 
647
        gtk_menu_item_set_label(GTK_MENU_ITEM (language_menuitem), default_language);
 
648
    }
 
649
    if (default_language && g_strcmp0 (default_language, language) != 0)
 
650
        set_language (default_language);
 
651
    /* If all else fails, just use the first language from the menu */
 
652
    else {
 
653
        for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
 
654
        {
 
655
            if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_iter->data)))
 
656
                gtk_menu_item_set_label(GTK_MENU_ITEM(language_menuitem), g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), "language-code")));
 
657
        }
 
658
    }
 
659
}
 
660
 
 
661
static void
 
662
set_message_label (const gchar *text)
 
663
{
 
664
    gtk_widget_set_visible (GTK_WIDGET (info_bar), g_strcmp0 (text, "") != 0);
 
665
    gtk_label_set_text (message_label, text);
 
666
}
 
667
 
 
668
static void
 
669
set_login_button_label (LightDMGreeter *greeter, const gchar *username)
 
670
{
 
671
    LightDMUser *user;
 
672
    gboolean logged_in = FALSE;
 
673
 
 
674
    user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
 
675
    if (user)
 
676
        logged_in = lightdm_user_get_logged_in (user);
 
677
    if (logged_in)
 
678
        gtk_button_set_label (login_button, _("Unlock"));
 
679
    else
 
680
        gtk_button_set_label (login_button, _("Log In"));
 
681
    gtk_widget_set_can_default (GTK_WIDGET (login_button), TRUE);
 
682
    gtk_widget_grab_default (GTK_WIDGET (login_button));
 
683
    /* and disable the session and language widgets */
 
684
    gtk_widget_set_sensitive (GTK_WIDGET (session_menuitem), !logged_in);
 
685
    gtk_widget_set_sensitive (GTK_WIDGET (language_menuitem), !logged_in);
 
686
}
 
687
 
 
688
static void set_background (GdkPixbuf *new_bg);
 
689
 
 
690
static void
 
691
set_user_background (const gchar *username)
 
692
{
 
693
    LightDMUser *user;
 
694
    const gchar *path;
 
695
    GdkPixbuf *bg = NULL;
 
696
    GError *error = NULL;
 
697
 
 
698
    user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
 
699
    if (user)
 
700
    {
 
701
        path = lightdm_user_get_background (user);
 
702
        if (path)
 
703
        {
 
704
            bg = gdk_pixbuf_new_from_file (path, &error);
 
705
            if (!bg)
 
706
            {
 
707
                g_warning ("Failed to load user background: %s", error->message);
 
708
                g_clear_error (&error);
 
709
            }
 
710
        }
 
711
    }
 
712
 
 
713
    set_background (bg);
 
714
    if (bg)
 
715
        g_object_unref (bg);
 
716
}
 
717
 
 
718
static void
 
719
set_user_image (const gchar *username)
 
720
{
 
721
    const gchar *path;
 
722
    LightDMUser *user;
 
723
    GdkPixbuf *image = NULL;
 
724
    GError *error = NULL;
 
725
 
 
726
    user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
 
727
    if (user)
 
728
    {
 
729
        path = lightdm_user_get_image (user);
 
730
        if (path)
 
731
        {
 
732
            image = gdk_pixbuf_new_from_file_at_scale (path, 80, 80, FALSE, &error);
 
733
            if (image)
 
734
            {
 
735
                gtk_image_set_from_pixbuf (GTK_IMAGE (user_image), image);
 
736
                g_object_unref (image);
 
737
                return;
 
738
            }
 
739
            else
 
740
            {
 
741
                g_warning ("Failed to load user image: %s", error->message);
 
742
                g_clear_error (&error);
 
743
            }
 
744
        }
 
745
    }
 
746
    
 
747
    if (default_user_pixbuf)
 
748
        gtk_image_set_from_pixbuf (GTK_IMAGE (user_image), default_user_pixbuf);
 
749
    else
 
750
        gtk_image_set_from_icon_name (GTK_IMAGE (user_image), default_user_icon, GTK_ICON_SIZE_DIALOG);
 
751
}
 
752
 
 
753
/* Function translate user defined coordinates to absolute value */
 
754
static gint
 
755
get_absolute_position (const DimensionPosition *p, gint screen, gint window)
 
756
{
 
757
    gint x = p->percentage ? (screen*p->value)/100 : p->value;
 
758
    x = p->sign < 0 ? screen - x : x;
 
759
    if (p->anchor > 0)
 
760
        x -= window;
 
761
    else if (p->anchor == 0)
 
762
        x -= window/2;
 
763
 
 
764
    if (x < 0)                     /* Offscreen: left/top */
 
765
        return 0;
 
766
    else if (x + window > screen)  /* Offscreen: right/bottom */
 
767
        return screen - window;
 
768
    else
 
769
        return x;
 
770
}
 
771
 
 
772
static void
 
773
center_window (GtkWindow *window, GtkAllocation *unused, const WindowPosition *pos)
 
774
{   
 
775
    GdkScreen *screen = gtk_window_get_screen (window);
 
776
    GtkAllocation allocation;
 
777
    GdkRectangle monitor_geometry;
 
778
 
 
779
    gdk_screen_get_monitor_geometry (screen, gdk_screen_get_primary_monitor (screen), &monitor_geometry);
 
780
    gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
 
781
    gtk_window_move (window,
 
782
                     monitor_geometry.x + get_absolute_position (&pos->x, monitor_geometry.width, allocation.width),
 
783
                     monitor_geometry.y + get_absolute_position (&pos->y, monitor_geometry.height, allocation.height));
 
784
}
 
785
 
 
786
#if GTK_CHECK_VERSION (3, 0, 0)
 
787
/* Use the much simpler fake transparency by drawing the window background with Cairo for Gtk3 */
 
788
static gboolean
 
789
background_window_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data)
 
790
{
 
791
    if (background_pixbuf)
 
792
        gdk_cairo_set_source_pixbuf (cr, background_pixbuf, 0, 0);
 
793
    else
 
794
        gdk_cairo_set_source_rgba (cr, default_background_color);
 
795
    cairo_paint (cr);
 
796
    return FALSE;
 
797
}
 
798
 
 
799
static gboolean
 
800
login_window_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data)
 
801
{
 
802
    GdkScreen *screen = gtk_window_get_screen (GTK_WINDOW(widget));
 
803
    GtkAllocation *allocation = g_new0 (GtkAllocation, 1);
 
804
    GdkRectangle monitor_geometry;
 
805
    gint x,y;
 
806
 
 
807
    if (background_pixbuf)
 
808
    {
 
809
        gdk_screen_get_monitor_geometry (screen, gdk_screen_get_primary_monitor (screen), &monitor_geometry);
 
810
        gtk_widget_get_allocation (widget, allocation);
 
811
        x = get_absolute_position (&main_window_pos.x, monitor_geometry.width, allocation->width);
 
812
        y = get_absolute_position (&main_window_pos.y, monitor_geometry.height, allocation->height);
 
813
        gdk_cairo_set_source_pixbuf (cr, background_pixbuf, monitor_geometry.x - x, monitor_geometry.y - y);
 
814
    }
 
815
    else
 
816
        gdk_cairo_set_source_rgba (cr, default_background_color);
 
817
 
 
818
    cairo_paint (cr);
 
819
 
 
820
    g_free (allocation);
 
821
    return FALSE;
 
822
}
 
823
 
 
824
#else
 
825
static GdkRegion *
 
826
cairo_region_from_rectangle (gint width, gint height, gint radius)
 
827
{
 
828
    GdkRegion *region;
 
829
 
 
830
    gint x = radius, y = 0;
 
831
    gint xChange = 1 - (radius << 1);
 
832
    gint yChange = 0;
 
833
    gint radiusError = 0;
 
834
 
 
835
    GdkRectangle rect;
 
836
 
 
837
    rect.x = radius;
 
838
    rect.y = radius;
 
839
    rect.width = width - radius * 2;
 
840
    rect.height = height - radius * 2;
 
841
 
 
842
    region = gdk_region_rectangle (&rect);
 
843
 
 
844
    while(x >= y)
 
845
    {
 
846
 
 
847
        rect.x = -x + radius;
 
848
        rect.y = -y + radius;
 
849
        rect.width = x - radius + width - rect.x;
 
850
        rect.height =  y - radius + height - rect.y;
 
851
 
 
852
        gdk_region_union_with_rect(region, &rect);
 
853
 
 
854
        rect.x = -y + radius;
 
855
        rect.y = -x + radius;
 
856
        rect.width = y - radius + width - rect.x;
 
857
        rect.height =  x - radius + height - rect.y;
 
858
 
 
859
        gdk_region_union_with_rect(region, &rect);
 
860
 
 
861
        y++;
 
862
        radiusError += yChange;
 
863
        yChange += 2;
 
864
        if(((radiusError << 1) + xChange) > 0)
 
865
        {
 
866
            x--;
 
867
            radiusError += xChange;
 
868
            xChange += 2;
 
869
        }
 
870
   }
 
871
 
 
872
   return region;
 
873
}
 
874
 
 
875
static gboolean
 
876
login_window_size_allocate (GtkWidget *widget, GdkRectangle *allocation, gpointer user_data)
 
877
{
 
878
    gint    radius = 10;
 
879
 
 
880
    GdkWindow *window = gtk_widget_get_window (widget);
 
881
    if (window_region)
 
882
        gdk_region_destroy(window_region);
 
883
    window_region = cairo_region_from_rectangle (allocation->width, allocation->height, radius);
 
884
    if (window) {
 
885
        gdk_window_shape_combine_region(window, window_region, 0, 0);
 
886
        gdk_window_input_shape_combine_region(window, window_region, 0, 0);
 
887
    }
 
888
 
 
889
    return TRUE;
 
890
}
 
891
 
 
892
static gboolean
 
893
background_window_expose (GtkWidget    *widget,
 
894
                                       GdkEventExpose *event,
 
895
                                       gpointer user_data)
 
896
{
 
897
    cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (widget));
 
898
    if (background_pixbuf)
 
899
        gdk_cairo_set_source_pixbuf (cr, background_pixbuf, 0, 0);
 
900
    else
 
901
        gdk_cairo_set_source_color (cr, default_background_color);
 
902
    cairo_paint (cr);
 
903
    return FALSE;
 
904
}
 
905
#endif
 
906
 
 
907
static void
 
908
start_authentication (const gchar *username)
 
909
{
 
910
    gchar *data;
 
911
    gsize data_length;
 
912
    GError *error = NULL;
 
913
 
 
914
    cancelling = FALSE;
 
915
    prompted = FALSE;
 
916
    password_prompted = FALSE;
 
917
    prompt_active = FALSE;
 
918
 
 
919
    if (pending_questions)
 
920
    {
 
921
        g_slist_free_full (pending_questions, (GDestroyNotify) pam_message_finalize);
 
922
        pending_questions = NULL;
 
923
    }
 
924
 
 
925
    g_key_file_set_value (state, "greeter", "last-user", username);
 
926
    data = g_key_file_to_data (state, &data_length, &error);
 
927
    if (error)
 
928
        g_warning ("Failed to save state file: %s", error->message);
 
929
    g_clear_error (&error);
 
930
    if (data)
 
931
    {
 
932
        g_file_set_contents (state_filename, data, data_length, &error);
 
933
        if (error)
 
934
            g_warning ("Failed to save state file: %s", error->message);
 
935
        g_clear_error (&error);
 
936
    }
 
937
    g_free (data);
 
938
 
 
939
    if (g_strcmp0 (username, "*other") == 0)
 
940
    {
 
941
        gtk_widget_show (GTK_WIDGET (username_entry));
 
942
        gtk_widget_show (GTK_WIDGET (cancel_button));
 
943
        lightdm_greeter_authenticate (greeter, NULL);
 
944
    }
 
945
    else if (g_strcmp0 (username, "*guest") == 0)
 
946
    {
 
947
        lightdm_greeter_authenticate_as_guest (greeter);
 
948
    }
 
949
    else
 
950
    {
 
951
        LightDMUser *user;
 
952
 
 
953
        user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
 
954
        if (user)
 
955
        {
 
956
            if (!current_session)
 
957
                set_session (lightdm_user_get_session (user));
 
958
            if (!current_language)
 
959
                set_language (lightdm_user_get_language (user));
 
960
        }
 
961
        else
 
962
        {
 
963
            set_session (NULL);
 
964
            set_language (NULL);
 
965
        }
 
966
 
 
967
        lightdm_greeter_authenticate (greeter, username);
 
968
    }
 
969
}
 
970
 
 
971
static void
 
972
cancel_authentication (void)
 
973
{
 
974
    GtkTreeModel *model;
 
975
    GtkTreeIter iter;
 
976
    gboolean other = FALSE;
 
977
 
 
978
    if (pending_questions)
 
979
    {
 
980
        g_slist_free_full (pending_questions, (GDestroyNotify) pam_message_finalize);
 
981
        pending_questions = NULL;
 
982
    }
 
983
 
 
984
    /* If in authentication then stop that first */
 
985
    cancelling = FALSE;
 
986
    if (lightdm_greeter_get_in_authentication (greeter))
 
987
    {
 
988
        cancelling = TRUE;
 
989
        lightdm_greeter_cancel_authentication (greeter);
 
990
        set_message_label ("");
 
991
    }
 
992
 
 
993
    /* Make sure password entry is back to normal */
 
994
    gtk_entry_set_visibility (password_entry, FALSE);
 
995
 
 
996
    /* Force refreshing the prompt_box for "Other" */
 
997
    model = gtk_combo_box_get_model (user_combo);
 
998
 
 
999
    if (gtk_combo_box_get_active_iter (user_combo, &iter))
 
1000
    {
 
1001
        gchar *user;
 
1002
 
 
1003
        gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
 
1004
        other = (g_strcmp0 (user, "*other") == 0);
 
1005
        g_free (user);
 
1006
    }
 
1007
 
 
1008
    /* Start a new login or return to the user list */
 
1009
    if (other || lightdm_greeter_get_hide_users_hint (greeter))
 
1010
        start_authentication ("*other");
 
1011
    else
 
1012
        gtk_widget_grab_focus (GTK_WIDGET (user_combo));
 
1013
}
 
1014
 
 
1015
static void
 
1016
start_session (void)
 
1017
{
 
1018
    gchar *language;
 
1019
    gchar *session;
 
1020
    gchar *data;
 
1021
    gsize data_length;
 
1022
    GError *error = NULL;
 
1023
 
 
1024
    language = get_language ();
 
1025
    if (language)
 
1026
        lightdm_greeter_set_language (greeter, language);
 
1027
    g_free (language);
 
1028
 
 
1029
    session = get_session ();
 
1030
 
 
1031
    /* Remember last choice */
 
1032
    g_key_file_set_value (state, "greeter", "last-session", session);
 
1033
 
 
1034
    data = g_key_file_to_data (state, &data_length, &error);
 
1035
    if (error)
 
1036
        g_warning ("Failed to save state file: %s", error->message);
 
1037
    g_clear_error (&error);
 
1038
    if (data)
 
1039
    {
 
1040
        g_file_set_contents (state_filename, data, data_length, &error);
 
1041
        if (error)
 
1042
            g_warning ("Failed to save state file: %s", error->message);
 
1043
        g_clear_error (&error);
 
1044
    }
 
1045
    g_free (data);
 
1046
 
 
1047
    if (!lightdm_greeter_start_session_sync (greeter, session, NULL))
 
1048
    {
 
1049
        set_message_label (_("Failed to start session"));
 
1050
        start_authentication (lightdm_greeter_get_authentication_user (greeter));
 
1051
    }
 
1052
    g_free (session);
 
1053
}
 
1054
 
 
1055
void
 
1056
session_selected_cb(GtkMenuItem *menuitem, gpointer user_data);
 
1057
G_MODULE_EXPORT
 
1058
void
 
1059
session_selected_cb(GtkMenuItem *menuitem, gpointer user_data)
 
1060
{
 
1061
    if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
 
1062
    {
 
1063
       gchar *session = g_object_get_data (G_OBJECT (menuitem), "session-key");
 
1064
       set_session(session);
 
1065
    }
 
1066
}
 
1067
 
 
1068
void
 
1069
language_selected_cb(GtkMenuItem *menuitem, gpointer user_data);
 
1070
G_MODULE_EXPORT
 
1071
void
 
1072
language_selected_cb(GtkMenuItem *menuitem, gpointer user_data)
 
1073
{
 
1074
    if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
 
1075
    {
 
1076
       gchar *language = g_object_get_data (G_OBJECT (menuitem), "language-code");
 
1077
       set_language(language);
 
1078
    }
 
1079
}
 
1080
 
 
1081
static void
 
1082
power_menu_cb (GtkWidget *menuitem, gpointer userdata)
 
1083
{
 
1084
    gtk_widget_set_sensitive (suspend_menuitem, lightdm_get_can_suspend());
 
1085
    gtk_widget_set_sensitive (hibernate_menuitem, lightdm_get_can_hibernate());
 
1086
    gtk_widget_set_sensitive (restart_menuitem, lightdm_get_can_restart());
 
1087
    gtk_widget_set_sensitive (shutdown_menuitem, lightdm_get_can_shutdown());
 
1088
}
 
1089
 
 
1090
gboolean
 
1091
password_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
 
1092
G_MODULE_EXPORT
 
1093
gboolean
 
1094
password_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 
1095
{
 
1096
    if ((event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down) &&
 
1097
        gtk_widget_get_visible(GTK_WIDGET(user_combo)))
 
1098
    {
 
1099
        gboolean available;
 
1100
        GtkTreeIter iter;
 
1101
        GtkTreeModel *model = gtk_combo_box_get_model (user_combo);
 
1102
 
 
1103
        /* Back to username_entry if it is available */
 
1104
        if (event->keyval == GDK_KEY_Up &&
 
1105
            gtk_widget_get_visible (GTK_WIDGET (username_entry)) && widget == GTK_WIDGET (password_entry))
 
1106
        {
 
1107
            gtk_widget_grab_focus (GTK_WIDGET (username_entry));
 
1108
            return TRUE;
 
1109
        }
 
1110
 
 
1111
        if (!gtk_combo_box_get_active_iter (user_combo, &iter))
 
1112
            return FALSE;
 
1113
 
 
1114
        if (event->keyval == GDK_KEY_Up)
 
1115
        {
 
1116
            #if GTK_CHECK_VERSION (3, 0, 0)
 
1117
            available = gtk_tree_model_iter_previous (model, &iter);
 
1118
            #else
 
1119
            GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
 
1120
            available = gtk_tree_path_prev (path);
 
1121
            if (available)
 
1122
                available = gtk_tree_model_get_iter (model, &iter, path);
 
1123
            gtk_tree_path_free (path);
 
1124
            #endif
 
1125
        }
 
1126
        else
 
1127
            available = gtk_tree_model_iter_next (model, &iter);
 
1128
 
 
1129
        if (available)
 
1130
            gtk_combo_box_set_active_iter (user_combo, &iter);
 
1131
 
 
1132
        return TRUE;
 
1133
    }
 
1134
    return FALSE;
 
1135
}
 
1136
 
 
1137
gboolean
 
1138
username_focus_out_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data);
 
1139
G_MODULE_EXPORT
 
1140
gboolean
 
1141
username_focus_out_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
 
1142
{
 
1143
    if (!g_strcmp0(gtk_entry_get_text(username_entry), "") == 0)
 
1144
        start_authentication(gtk_entry_get_text(username_entry));
 
1145
    return FALSE;
 
1146
}
 
1147
 
 
1148
gboolean
 
1149
username_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
 
1150
G_MODULE_EXPORT
 
1151
gboolean
 
1152
username_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 
1153
{
 
1154
    /* Acts as password_entry */
 
1155
    if (event->keyval == GDK_KEY_Up)
 
1156
        return password_key_press_cb (widget, event, user_data);
 
1157
    /* Enter activates the password entry */
 
1158
    else if (event->keyval == GDK_KEY_Return)
 
1159
    {
 
1160
        gtk_widget_grab_focus(GTK_WIDGET(password_entry));
 
1161
        return TRUE;
 
1162
    }
 
1163
    else
 
1164
        return FALSE;
 
1165
}
 
1166
 
 
1167
gboolean
 
1168
menubar_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
 
1169
G_MODULE_EXPORT
 
1170
gboolean
 
1171
menubar_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 
1172
{
 
1173
    switch (event->keyval)
 
1174
    {
 
1175
    case GDK_KEY_Tab: case GDK_KEY_Escape:
 
1176
    case GDK_KEY_Super_L: case GDK_KEY_Super_R:
 
1177
    case GDK_KEY_F9: case GDK_KEY_F10:
 
1178
    case GDK_KEY_F11: case GDK_KEY_F12:
 
1179
        gtk_menu_shell_cancel (GTK_MENU_SHELL (menubar));
 
1180
        gtk_window_present (login_window);
 
1181
        return TRUE;
 
1182
    default:
 
1183
        return FALSE;
 
1184
    };
 
1185
}
 
1186
 
 
1187
gboolean
 
1188
login_window_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
 
1189
G_MODULE_EXPORT
 
1190
gboolean
 
1191
login_window_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 
1192
{
 
1193
    GtkWidget *item = NULL;
 
1194
 
 
1195
    if (event->keyval == GDK_KEY_F9)
 
1196
        item = session_menuitem;
 
1197
    else if (event->keyval == GDK_KEY_F10)
 
1198
        item = language_menuitem;
 
1199
    else if (event->keyval == GDK_KEY_F11)
 
1200
        item = a11y_menuitem;
 
1201
    else if (event->keyval == GDK_KEY_F12)
 
1202
        item = power_menuitem;
 
1203
    else if (event->keyval != GDK_KEY_Escape &&
 
1204
             event->keyval != GDK_KEY_Super_L &&
 
1205
             event->keyval != GDK_KEY_Super_R)
 
1206
        return FALSE;
 
1207
 
 
1208
    if (GTK_IS_MENU_ITEM (item) && gtk_widget_is_sensitive (item) && gtk_widget_get_visible (item))
 
1209
        gtk_menu_shell_select_item (GTK_MENU_SHELL (menubar), item);
 
1210
    else
 
1211
        gtk_menu_shell_select_first (GTK_MENU_SHELL (menubar), TRUE);
 
1212
    return TRUE;
 
1213
}
 
1214
 
 
1215
static void set_displayed_user (LightDMGreeter *greeter, gchar *username)
 
1216
{
 
1217
    gchar *user_tooltip;
 
1218
    LightDMUser *user;
 
1219
 
 
1220
    if (g_strcmp0 (username, "*other") == 0)
 
1221
    {
 
1222
        gtk_widget_show (GTK_WIDGET (username_entry));
 
1223
        gtk_widget_show (GTK_WIDGET (cancel_button));
 
1224
        user_tooltip = g_strdup(_("Other"));
 
1225
    }
 
1226
    else
 
1227
    {
 
1228
        gtk_widget_hide (GTK_WIDGET (username_entry));
 
1229
        gtk_widget_hide (GTK_WIDGET (cancel_button));
 
1230
        gtk_widget_grab_focus (GTK_WIDGET (password_entry));
 
1231
        user_tooltip = g_strdup(username);
 
1232
    }
 
1233
 
 
1234
    if (g_strcmp0 (username, "*guest") == 0)
 
1235
    {
 
1236
        user_tooltip = g_strdup(_("Guest Account"));
 
1237
    }
 
1238
 
 
1239
    set_login_button_label (greeter, username);
 
1240
    set_user_background (username);
 
1241
    set_user_image (username);
 
1242
    user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
 
1243
    if (user)
 
1244
        if (lightdm_user_get_logged_in (user))
 
1245
        {
 
1246
            set_language (lightdm_user_get_language (user));
 
1247
            set_session (lightdm_user_get_session (user));
 
1248
        }
 
1249
    gtk_widget_set_tooltip_text (GTK_WIDGET (user_combo), user_tooltip);
 
1250
    start_authentication (username);
 
1251
    g_free (user_tooltip);
 
1252
}
 
1253
 
 
1254
void user_combobox_active_changed_cb (GtkComboBox *widget, LightDMGreeter *greeter);
 
1255
G_MODULE_EXPORT
 
1256
void
 
1257
user_combobox_active_changed_cb (GtkComboBox *widget, LightDMGreeter *greeter)
 
1258
{
 
1259
    GtkTreeModel *model;
 
1260
    GtkTreeIter iter;
 
1261
 
 
1262
    model = gtk_combo_box_get_model (user_combo);
 
1263
 
 
1264
    if (gtk_combo_box_get_active_iter (user_combo, &iter))
 
1265
    {
 
1266
        gchar *user;
 
1267
 
 
1268
        gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
 
1269
 
 
1270
        set_displayed_user(greeter, user);
 
1271
 
 
1272
        g_free (user);
 
1273
    }
 
1274
    set_message_label ("");
 
1275
}
 
1276
 
 
1277
static const gchar*
 
1278
get_message_label (void)
 
1279
{
 
1280
    return gtk_label_get_text (message_label);
 
1281
}
 
1282
 
 
1283
static void
 
1284
process_prompts (LightDMGreeter *greeter)
 
1285
{
 
1286
    if (!pending_questions)
 
1287
        return;
 
1288
 
 
1289
    /* always allow the user to change username again */
 
1290
    gtk_widget_set_sensitive (GTK_WIDGET (username_entry), TRUE);
 
1291
    gtk_widget_set_sensitive (GTK_WIDGET (password_entry), TRUE);
 
1292
 
 
1293
    /* Special case: no user selected from list, so PAM asks us for the user
 
1294
     * via a prompt. For that case, use the username field */
 
1295
    if (!prompted && pending_questions && !pending_questions->next &&
 
1296
        ((PAMConversationMessage *) pending_questions->data)->is_prompt &&
 
1297
        ((PAMConversationMessage *) pending_questions->data)->type.prompt != LIGHTDM_PROMPT_TYPE_SECRET &&
 
1298
        gtk_widget_get_visible ((GTK_WIDGET (username_entry))) &&
 
1299
        lightdm_greeter_get_authentication_user (greeter) == NULL)
 
1300
    {
 
1301
        prompted = TRUE;
 
1302
        prompt_active = TRUE;
 
1303
        gtk_widget_grab_focus (GTK_WIDGET (username_entry));
 
1304
        return;
 
1305
    }
 
1306
 
 
1307
    while (pending_questions)
 
1308
    {
 
1309
        PAMConversationMessage *message = (PAMConversationMessage *) pending_questions->data;
 
1310
        pending_questions = g_slist_remove (pending_questions, (gconstpointer) message);
 
1311
 
 
1312
        if (!message->is_prompt)
 
1313
        {
 
1314
            /* FIXME: this doesn't show multiple messages, but that was
 
1315
             * already the case before. */
 
1316
            set_message_label (message->text);
 
1317
            continue;
 
1318
        }
 
1319
 
 
1320
        gtk_entry_set_text (password_entry, "");
 
1321
        gtk_entry_set_visibility (password_entry, message->type.prompt != LIGHTDM_PROMPT_TYPE_SECRET);
 
1322
        if (get_message_label()[0] == 0 && password_prompted)
 
1323
        {
 
1324
            /* No message was provided beforehand and this is not the
 
1325
             * first password prompt, so use the prompt as label,
 
1326
             * otherwise the user will be completely unclear of what
 
1327
             * is going on. Actually, the fact that prompt messages are
 
1328
             * not shown is problematic in general, especially if
 
1329
             * somebody uses a custom PAM module that wants to ask
 
1330
             * something different. */
 
1331
            gchar *str = message->text;
 
1332
            if (g_str_has_suffix (str, ": "))
 
1333
                str = g_strndup (str, strlen (str) - 2);
 
1334
            else if (g_str_has_suffix (str, ":"))
 
1335
                str = g_strndup (str, strlen (str) - 1);
 
1336
            set_message_label (str);
 
1337
            if (str != message->text)
 
1338
                g_free (str);
 
1339
        }
 
1340
        gtk_widget_grab_focus (GTK_WIDGET (password_entry));
 
1341
        prompted = TRUE;
 
1342
        password_prompted = TRUE;
 
1343
        prompt_active = TRUE;
 
1344
 
 
1345
        /* If we have more stuff after a prompt, assume that other prompts are pending,
 
1346
         * so stop here. */
 
1347
        break;
 
1348
    }
 
1349
}
 
1350
 
 
1351
void login_cb (GtkWidget *widget);
 
1352
G_MODULE_EXPORT
 
1353
void
 
1354
login_cb (GtkWidget *widget)
 
1355
{
 
1356
    /* Reset to default screensaver values */
 
1357
    if (lightdm_greeter_get_lock_hint (greeter))
 
1358
        XSetScreenSaver(gdk_x11_display_get_xdisplay(gdk_display_get_default ()), timeout, interval, prefer_blanking, allow_exposures);        
 
1359
 
 
1360
    gtk_widget_set_sensitive (GTK_WIDGET (username_entry), FALSE);
 
1361
    gtk_widget_set_sensitive (GTK_WIDGET (password_entry), FALSE);
 
1362
    set_message_label ("");
 
1363
    prompt_active = FALSE;
 
1364
 
 
1365
    if (lightdm_greeter_get_is_authenticated (greeter))
 
1366
        start_session ();
 
1367
    else if (lightdm_greeter_get_in_authentication (greeter))
 
1368
    {
 
1369
        lightdm_greeter_respond (greeter, gtk_entry_get_text (password_entry));
 
1370
        /* If we have questions pending, then we continue processing
 
1371
         * those, until we are done. (Otherwise, authentication will
 
1372
         * not complete.) */
 
1373
        if (pending_questions)
 
1374
            process_prompts (greeter);
 
1375
    }
 
1376
    else
 
1377
        start_authentication (lightdm_greeter_get_authentication_user (greeter));
 
1378
}
 
1379
 
 
1380
void cancel_cb (GtkWidget *widget);
 
1381
G_MODULE_EXPORT
 
1382
void
 
1383
cancel_cb (GtkWidget *widget)
 
1384
{
 
1385
    cancel_authentication ();
 
1386
}
 
1387
 
 
1388
static void
 
1389
show_prompt_cb (LightDMGreeter *greeter, const gchar *text, LightDMPromptType type)
 
1390
{
 
1391
    PAMConversationMessage *message_obj = g_new (PAMConversationMessage, 1);
 
1392
    if (message_obj)
 
1393
    {
 
1394
        message_obj->is_prompt = TRUE;
 
1395
        message_obj->type.prompt = type;
 
1396
        message_obj->text = g_strdup (text);
 
1397
        pending_questions = g_slist_append (pending_questions, message_obj);
 
1398
    }
 
1399
 
 
1400
    if (!prompt_active)
 
1401
        process_prompts (greeter);
 
1402
}
 
1403
 
 
1404
static void
 
1405
show_message_cb (LightDMGreeter *greeter, const gchar *text, LightDMMessageType type)
 
1406
{
 
1407
    PAMConversationMessage *message_obj = g_new (PAMConversationMessage, 1);
 
1408
    if (message_obj)
 
1409
    {
 
1410
        message_obj->is_prompt = FALSE;
 
1411
        message_obj->type.message = type;
 
1412
        message_obj->text = g_strdup (text);
 
1413
        pending_questions = g_slist_append (pending_questions, message_obj);
 
1414
    }
 
1415
 
 
1416
    if (!prompt_active)
 
1417
        process_prompts (greeter);
 
1418
}
 
1419
 
 
1420
static void
 
1421
authentication_complete_cb (LightDMGreeter *greeter)
 
1422
{
 
1423
    prompt_active = FALSE;
 
1424
    gtk_entry_set_text (password_entry, "");
 
1425
 
 
1426
    if (cancelling)
 
1427
    {
 
1428
        cancel_authentication ();
 
1429
        return;
 
1430
    }
 
1431
 
 
1432
    if (pending_questions)
 
1433
    {
 
1434
        g_slist_free_full (pending_questions, (GDestroyNotify) pam_message_finalize);
 
1435
        pending_questions = NULL;
 
1436
    }
 
1437
 
 
1438
    if (lightdm_greeter_get_is_authenticated (greeter))
 
1439
    {
 
1440
        if (prompted)
 
1441
            start_session ();
 
1442
    }
 
1443
    else
 
1444
    {
 
1445
        if (prompted)
 
1446
        {
 
1447
            if (get_message_label()[0] == 0)
 
1448
                set_message_label (_("Incorrect password, please try again"));
 
1449
            start_authentication (lightdm_greeter_get_authentication_user (greeter));
 
1450
        }
 
1451
        else
 
1452
            set_message_label (_("Failed to authenticate"));
 
1453
    }
 
1454
}
 
1455
 
 
1456
void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
 
1457
G_MODULE_EXPORT
 
1458
void
 
1459
suspend_cb (GtkWidget *widget, LightDMGreeter *greeter)
 
1460
{
 
1461
    lightdm_suspend (NULL);
 
1462
}
 
1463
 
 
1464
void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
 
1465
G_MODULE_EXPORT
 
1466
void
 
1467
hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter)
 
1468
{
 
1469
    lightdm_hibernate (NULL);
 
1470
}
 
1471
 
 
1472
static gboolean
 
1473
show_power_prompt (const gchar* action, const gchar* message, const gchar* icon,
 
1474
                   const gchar* dialog_name, const gchar* button_name)
 
1475
{
 
1476
    GtkWidget *dialog;
 
1477
    GtkWidget *image;
 
1478
    GtkWidget *button;
 
1479
    gboolean   result;
 
1480
    const GList *items, *item;
 
1481
    gint logged_in_users = 0;
 
1482
    gchar *warning;
 
1483
    
 
1484
    /* Check if there are still users logged in, count them and if so, display a warning */
 
1485
    items = lightdm_user_list_get_users (lightdm_user_list_get_instance ());
 
1486
    for (item = items; item; item = item->next)
 
1487
    {
 
1488
        LightDMUser *user = item->data;
 
1489
        if (lightdm_user_get_logged_in (user))
 
1490
            logged_in_users++;
 
1491
    }
 
1492
    if (logged_in_users > 0)
 
1493
    {
 
1494
        if (logged_in_users > 1)
 
1495
            warning = g_strdup_printf (_("Warning: There are still %d users logged in."), logged_in_users);
 
1496
        else
 
1497
            warning = g_strdup_printf (_("Warning: There is still %d user logged in."), logged_in_users);
 
1498
        message = g_markup_printf_escaped ("<b>%s</b>\n%s", warning, message);
 
1499
        g_free (warning);
 
1500
    }
 
1501
 
 
1502
    /* Prepare the dialog */
 
1503
    dialog = gtk_message_dialog_new (NULL,
 
1504
                                     GTK_DIALOG_MODAL,
 
1505
                                     GTK_MESSAGE_OTHER,
 
1506
                                     GTK_BUTTONS_NONE,
 
1507
                                     "%s", action);
 
1508
    gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog), "%s", message);        
 
1509
    button = gtk_dialog_add_button(GTK_DIALOG (dialog), _("Cancel"), GTK_RESPONSE_CANCEL);
 
1510
    gtk_widget_set_name(button, "cancel_button");
 
1511
    button = gtk_dialog_add_button(GTK_DIALOG (dialog), action, GTK_RESPONSE_OK);
 
1512
    gtk_widget_set_name(button, button_name);
 
1513
 
 
1514
    /* Add the icon */
 
1515
    image = gtk_image_new_from_icon_name(icon, GTK_ICON_SIZE_DIALOG);
 
1516
    gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(dialog), image);
 
1517
 
 
1518
    /* Make the dialog themeable and attractive */
 
1519
#if GTK_CHECK_VERSION (3, 0, 0)
 
1520
    gtk_style_context_add_class(GTK_STYLE_CONTEXT(gtk_widget_get_style_context(GTK_WIDGET(dialog))), "lightdm-gtk-greeter");
 
1521
#endif
 
1522
    gtk_widget_set_name(dialog, dialog_name);
 
1523
#if GTK_CHECK_VERSION (3, 0, 0)
 
1524
    g_signal_connect (G_OBJECT (dialog), "draw", G_CALLBACK (login_window_draw), NULL);
 
1525
#else
 
1526
    g_signal_connect (G_OBJECT (dialog), "size-allocate", G_CALLBACK (login_window_size_allocate), NULL);
 
1527
#endif
 
1528
    gtk_container_set_border_width(GTK_CONTAINER (dialog), 18);
 
1529
 
 
1530
    /* Hide the login window and show the dialog */
 
1531
    gtk_widget_hide (GTK_WIDGET (login_window));
 
1532
    gtk_widget_show_all (dialog);
 
1533
    center_window (GTK_WINDOW (dialog), NULL, &CENTERED_WINDOW_POS);
 
1534
 
 
1535
    result = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK;
 
1536
 
 
1537
    gtk_widget_destroy (dialog);
 
1538
    gtk_widget_show (GTK_WIDGET (login_window));
 
1539
 
 
1540
    return result;
 
1541
}
 
1542
 
 
1543
void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
 
1544
G_MODULE_EXPORT
 
1545
void
 
1546
restart_cb (GtkWidget *widget, LightDMGreeter *greeter)
 
1547
{
 
1548
    if (show_power_prompt(_("Restart"), _("Are you sure you want to close all programs and restart the computer?"),
 
1549
                          #if GTK_CHECK_VERSION (3, 0, 0)
 
1550
                          "view-refresh-symbolic",
 
1551
                          #else
 
1552
                          "view-refresh",
 
1553
                          #endif
 
1554
                          "restart_dialog", "restart_button"))
 
1555
        lightdm_restart (NULL);
 
1556
}
 
1557
 
 
1558
void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
 
1559
G_MODULE_EXPORT
 
1560
void
 
1561
shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter)
 
1562
{
 
1563
    if (show_power_prompt(_("Shut Down"), _("Are you sure you want to close all programs and shut down the computer?"),
 
1564
                          #if GTK_CHECK_VERSION (3, 0, 0)
 
1565
                          "system-shutdown-symbolic",
 
1566
                          #else
 
1567
                          "system-shutdown",
 
1568
                          #endif
 
1569
                          "shutdown_dialog", "shutdown_button"))
 
1570
        lightdm_shutdown (NULL);
 
1571
}
 
1572
 
 
1573
static void
 
1574
user_added_cb (LightDMUserList *user_list, LightDMUser *user, LightDMGreeter *greeter)
 
1575
{
 
1576
    GtkTreeModel *model;
 
1577
    GtkTreeIter iter;
 
1578
    gboolean logged_in = FALSE;
 
1579
 
 
1580
    model = gtk_combo_box_get_model (user_combo);
 
1581
 
 
1582
    logged_in = lightdm_user_get_logged_in (user);
 
1583
 
 
1584
    gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
1585
    gtk_list_store_set (GTK_LIST_STORE (model), &iter,
 
1586
                        0, lightdm_user_get_name (user),
 
1587
                        1, lightdm_user_get_display_name (user),
 
1588
                        2, logged_in ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
 
1589
                        -1);
 
1590
}
 
1591
 
 
1592
static gboolean
 
1593
get_user_iter (const gchar *username, GtkTreeIter *iter)
 
1594
{
 
1595
    GtkTreeModel *model;
 
1596
 
 
1597
    model = gtk_combo_box_get_model (user_combo);
 
1598
 
 
1599
    if (!gtk_tree_model_get_iter_first (model, iter))
 
1600
        return FALSE;
 
1601
    do
 
1602
    {
 
1603
        gchar *name;
 
1604
        gboolean matched;
 
1605
 
 
1606
        gtk_tree_model_get (model, iter, 0, &name, -1);
 
1607
        matched = g_strcmp0 (name, username) == 0;
 
1608
        g_free (name);
 
1609
        if (matched)
 
1610
            return TRUE;
 
1611
    } while (gtk_tree_model_iter_next (model, iter));
 
1612
 
 
1613
    return FALSE;
 
1614
}
 
1615
 
 
1616
static void
 
1617
user_changed_cb (LightDMUserList *user_list, LightDMUser *user, LightDMGreeter *greeter)
 
1618
{
 
1619
    GtkTreeModel *model;
 
1620
    GtkTreeIter iter;
 
1621
    gboolean logged_in = FALSE;
 
1622
 
 
1623
    if (!get_user_iter (lightdm_user_get_name (user), &iter))
 
1624
        return;
 
1625
    logged_in = lightdm_user_get_logged_in (user);
 
1626
 
 
1627
    model = gtk_combo_box_get_model (user_combo);
 
1628
 
 
1629
    gtk_list_store_set (GTK_LIST_STORE (model), &iter,
 
1630
                        0, lightdm_user_get_name (user),
 
1631
                        1, lightdm_user_get_display_name (user),
 
1632
                        2, logged_in ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
 
1633
                        -1);
 
1634
}
 
1635
 
 
1636
static void
 
1637
user_removed_cb (LightDMUserList *user_list, LightDMUser *user)
 
1638
{
 
1639
    GtkTreeModel *model;
 
1640
    GtkTreeIter iter;
 
1641
 
 
1642
    if (!get_user_iter (lightdm_user_get_name (user), &iter))
 
1643
        return;
 
1644
 
 
1645
    model = gtk_combo_box_get_model (user_combo);
 
1646
    gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
 
1647
}
 
1648
 
 
1649
void a11y_font_cb (GtkCheckMenuItem *item);
 
1650
G_MODULE_EXPORT
 
1651
void
 
1652
a11y_font_cb (GtkCheckMenuItem *item)
 
1653
{
 
1654
    if (gtk_check_menu_item_get_active (item))
 
1655
    {
 
1656
        gchar *font_name, **tokens;
 
1657
        guint length;
 
1658
 
 
1659
        g_object_get (gtk_settings_get_default (), "gtk-font-name", &font_name, NULL);
 
1660
        tokens = g_strsplit (font_name, " ", -1);
 
1661
        length = g_strv_length (tokens);
 
1662
        if (length > 1)
 
1663
        {
 
1664
            gint size = atoi (tokens[length - 1]);
 
1665
            if (size > 0)
 
1666
            {
 
1667
                g_free (tokens[length - 1]);
 
1668
                tokens[length - 1] = g_strdup_printf ("%d", size + 10);
 
1669
                g_free (font_name);
 
1670
                font_name = g_strjoinv (" ", tokens);
 
1671
            }
 
1672
        }
 
1673
        g_strfreev (tokens);
 
1674
 
 
1675
        g_object_set (gtk_settings_get_default (), "gtk-font-name", font_name, NULL);
 
1676
    }
 
1677
    else
 
1678
        g_object_set (gtk_settings_get_default (), "gtk-font-name", default_font_name, NULL);
 
1679
}
 
1680
 
 
1681
void a11y_contrast_cb (GtkCheckMenuItem *item);
 
1682
G_MODULE_EXPORT
 
1683
void
 
1684
a11y_contrast_cb (GtkCheckMenuItem *item)
 
1685
{
 
1686
    if (gtk_check_menu_item_get_active (item))
 
1687
    {
 
1688
        g_object_set (gtk_settings_get_default (), "gtk-theme-name", "HighContrast", NULL);
 
1689
        g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", "HighContrast", NULL);
 
1690
    }
 
1691
    else
 
1692
    {
 
1693
        g_object_set (gtk_settings_get_default (), "gtk-theme-name", default_theme_name, NULL);
 
1694
        g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", default_icon_theme_name, NULL);
 
1695
    }
 
1696
}
 
1697
 
 
1698
static void
 
1699
keyboard_terminated_cb (GPid pid, gint status, gpointer user_data)
 
1700
{
 
1701
    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (keyboard_menuitem), FALSE);
 
1702
}
 
1703
 
 
1704
void a11y_keyboard_cb (GtkCheckMenuItem *item);
 
1705
G_MODULE_EXPORT
 
1706
void
 
1707
a11y_keyboard_cb (GtkCheckMenuItem *item)
 
1708
{
 
1709
    if (gtk_check_menu_item_get_active (item))
 
1710
    {
 
1711
        gboolean spawned = FALSE;
 
1712
        if (onboard_window)
 
1713
        {
 
1714
            GtkSocket* socket = NULL;
 
1715
            gint out_fd = 0;
 
1716
 
 
1717
            if (g_spawn_async_with_pipes (NULL, a11y_keyboard_command, NULL, G_SPAWN_SEARCH_PATH,
 
1718
                                          NULL, NULL, &a11y_kbd_pid, NULL, &out_fd, NULL,
 
1719
                                          &a11y_keyboard_error))
 
1720
            {
 
1721
                gchar* text = NULL;
 
1722
                GIOChannel* out_channel = g_io_channel_unix_new (out_fd);
 
1723
                if (g_io_channel_read_line(out_channel, &text, NULL, NULL, &a11y_keyboard_error) == G_IO_STATUS_NORMAL)
 
1724
                {
 
1725
                    gchar* end_ptr = NULL;
 
1726
 
 
1727
                    text = g_strstrip (text);
 
1728
                    gint id = g_ascii_strtoll (text, &end_ptr, 0);
 
1729
 
 
1730
                    if (id != 0 && end_ptr > text)
 
1731
                    {
 
1732
                        socket = GTK_SOCKET (gtk_socket_new ());
 
1733
                        gtk_container_add (GTK_CONTAINER (onboard_window), GTK_WIDGET (socket));
 
1734
                        gtk_socket_add_id (socket, id);
 
1735
                        gtk_widget_show_all (GTK_WIDGET (onboard_window));
 
1736
                        spawned = TRUE;
 
1737
                    }
 
1738
                    else
 
1739
                        g_debug ("onboard keyboard command error : 'unrecognized output'");
 
1740
 
 
1741
                    g_free(text);
 
1742
                }
 
1743
            }
 
1744
        }
 
1745
        else
 
1746
        {
 
1747
            spawned = g_spawn_async (NULL, a11y_keyboard_command, NULL,
 
1748
                                     G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
 
1749
                                     NULL, NULL, &a11y_kbd_pid, &a11y_keyboard_error);
 
1750
            if (spawned)
 
1751
                g_child_watch_add (a11y_kbd_pid, keyboard_terminated_cb, NULL);
 
1752
        }
 
1753
 
 
1754
        if(!spawned)
 
1755
        {
 
1756
            if (a11y_keyboard_error)
 
1757
                g_debug ("a11y keyboard command error : '%s'", a11y_keyboard_error->message);
 
1758
            a11y_kbd_pid = 0;
 
1759
            g_clear_error(&a11y_keyboard_error);
 
1760
            gtk_check_menu_item_set_active (item, FALSE);
 
1761
        }
 
1762
    }
 
1763
    else
 
1764
    {
 
1765
        if (a11y_kbd_pid != 0)
 
1766
        {
 
1767
            kill (a11y_kbd_pid, SIGTERM);
 
1768
            g_spawn_close_pid (a11y_kbd_pid);
 
1769
            a11y_kbd_pid = 0;
 
1770
            if (onboard_window)
 
1771
                gtk_widget_hide (GTK_WIDGET(onboard_window));
 
1772
        }
 
1773
    }
 
1774
}
 
1775
 
 
1776
static void
 
1777
sigterm_cb (int signum)
 
1778
{
 
1779
    exit (0);
 
1780
}
 
1781
 
 
1782
static void
 
1783
load_user_list (void)
 
1784
{
 
1785
    const GList *items, *item;
 
1786
    GtkTreeModel *model;
 
1787
    GtkTreeIter iter;
 
1788
    gchar *last_user;
 
1789
    const gchar *selected_user;
 
1790
    gboolean logged_in = FALSE;
 
1791
 
 
1792
    g_signal_connect (lightdm_user_list_get_instance (), "user-added", G_CALLBACK (user_added_cb), greeter);
 
1793
    g_signal_connect (lightdm_user_list_get_instance (), "user-changed", G_CALLBACK (user_changed_cb), greeter);
 
1794
    g_signal_connect (lightdm_user_list_get_instance (), "user-removed", G_CALLBACK (user_removed_cb), NULL);
 
1795
    model = gtk_combo_box_get_model (user_combo);
 
1796
    items = lightdm_user_list_get_users (lightdm_user_list_get_instance ());
 
1797
    for (item = items; item; item = item->next)
 
1798
    {
 
1799
        LightDMUser *user = item->data;
 
1800
        logged_in = lightdm_user_get_logged_in (user);
 
1801
 
 
1802
        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
1803
        gtk_list_store_set (GTK_LIST_STORE (model), &iter,
 
1804
                            0, lightdm_user_get_name (user),
 
1805
                            1, lightdm_user_get_display_name (user),
 
1806
                            2, logged_in ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
 
1807
                            -1);
 
1808
    }
 
1809
    if (lightdm_greeter_get_has_guest_account_hint (greeter))
 
1810
    {
 
1811
        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
1812
        gtk_list_store_set (GTK_LIST_STORE (model), &iter,
 
1813
                            0, "*guest",
 
1814
                            1, _("Guest Account"),
 
1815
                            2, PANGO_WEIGHT_NORMAL,
 
1816
                            -1);
 
1817
    }
 
1818
 
 
1819
    gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
1820
    gtk_list_store_set (GTK_LIST_STORE (model), &iter,
 
1821
                        0, "*other",
 
1822
                        1, _("Other..."),
 
1823
                        2, PANGO_WEIGHT_NORMAL,
 
1824
                        -1);
 
1825
 
 
1826
    last_user = g_key_file_get_value (state, "greeter", "last-user", NULL);
 
1827
 
 
1828
    if (lightdm_greeter_get_select_user_hint (greeter))
 
1829
        selected_user = lightdm_greeter_get_select_user_hint (greeter);
 
1830
    else if (lightdm_greeter_get_select_guest_hint (greeter))
 
1831
        selected_user = "*guest";
 
1832
    else if (last_user)
 
1833
        selected_user = last_user;
 
1834
    else
 
1835
        selected_user = NULL;
 
1836
 
 
1837
    if (gtk_tree_model_get_iter_first (model, &iter))
 
1838
    {
 
1839
        gchar *name;
 
1840
        gboolean matched = FALSE;
 
1841
        
 
1842
        if (selected_user)
 
1843
        {
 
1844
            do
 
1845
            {
 
1846
                gtk_tree_model_get (model, &iter, 0, &name, -1);
 
1847
                matched = g_strcmp0 (name, selected_user) == 0;
 
1848
                g_free (name);
 
1849
                if (matched)
 
1850
                {
 
1851
                    gtk_combo_box_set_active_iter (user_combo, &iter);
 
1852
                    name = g_strdup(selected_user);
 
1853
                    set_displayed_user(greeter, name);
 
1854
                    g_free(name);
 
1855
                    break;
 
1856
                }
 
1857
            } while (gtk_tree_model_iter_next (model, &iter));
 
1858
        }
 
1859
        if (!matched)
 
1860
        {
 
1861
            gtk_tree_model_get_iter_first (model, &iter);
 
1862
            gtk_tree_model_get (model, &iter, 0, &name, -1);
 
1863
            gtk_combo_box_set_active_iter (user_combo, &iter);
 
1864
            set_displayed_user(greeter, name);
 
1865
            g_free(name);
 
1866
        }
 
1867
        
 
1868
    }
 
1869
 
 
1870
    g_free (last_user);
 
1871
}
 
1872
 
 
1873
/* The following code for setting a RetainPermanent background pixmap was taken
 
1874
   originally from Gnome, with some fixes from MATE. see:
 
1875
   https://github.com/mate-desktop/mate-desktop/blob/master/libmate-desktop/mate-bg.c */
 
1876
static cairo_surface_t *
 
1877
create_root_surface (GdkScreen *screen)
 
1878
{
 
1879
    gint number, width, height;
 
1880
    Display *display;
 
1881
    Pixmap pixmap;
 
1882
    cairo_surface_t *surface;
 
1883
 
 
1884
    number = gdk_screen_get_number (screen);
 
1885
    width = gdk_screen_get_width (screen);
 
1886
    height = gdk_screen_get_height (screen);
 
1887
 
 
1888
    /* Open a new connection so with Retain Permanent so the pixmap remains when the greeter quits */
 
1889
    gdk_flush ();
 
1890
    display = XOpenDisplay (gdk_display_get_name (gdk_screen_get_display (screen)));
 
1891
    if (!display)
 
1892
    {
 
1893
        g_warning ("Failed to create root pixmap");
 
1894
        return NULL;
 
1895
    }
 
1896
 
 
1897
    XSetCloseDownMode (display, RetainPermanent);
 
1898
    pixmap = XCreatePixmap (display, RootWindow (display, number), width, height, DefaultDepth (display, number));
 
1899
    XCloseDisplay (display);
 
1900
 
 
1901
    /* Convert into a Cairo surface */
 
1902
    surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen),
 
1903
                                         pixmap,
 
1904
                                         GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen)),
 
1905
                                         width, height);
 
1906
 
 
1907
    return surface;
 
1908
}
 
1909
 
 
1910
/* Sets the "ESETROOT_PMAP_ID" property to later be used to free the pixmap,
 
1911
*/
 
1912
static void
 
1913
set_root_pixmap_id (GdkScreen *screen,
 
1914
                         Display *display,
 
1915
                         Pixmap xpixmap)
 
1916
{
 
1917
    Window xroot = RootWindow (display, gdk_screen_get_number (screen));
 
1918
    char *atom_names[] = {"_XROOTPMAP_ID", "ESETROOT_PMAP_ID"};
 
1919
    Atom atoms[G_N_ELEMENTS(atom_names)] = {0};
 
1920
 
 
1921
    Atom type;
 
1922
    int format;
 
1923
    unsigned long nitems, after;
 
1924
    unsigned char *data_root, *data_esetroot;
 
1925
 
 
1926
    /* Get atoms for both properties in an array, only if they exist.
 
1927
     * This method is to avoid multiple round-trips to Xserver
 
1928
     */
 
1929
    if (XInternAtoms (display, atom_names, G_N_ELEMENTS(atom_names), True, atoms) &&
 
1930
        atoms[0] != None && atoms[1] != None)
 
1931
    {
 
1932
 
 
1933
        XGetWindowProperty (display, xroot, atoms[0], 0L, 1L, False, AnyPropertyType,
 
1934
                            &type, &format, &nitems, &after, &data_root);
 
1935
        if (data_root && type == XA_PIXMAP && format == 32 && nitems == 1)
 
1936
        {
 
1937
            XGetWindowProperty (display, xroot, atoms[1], 0L, 1L, False, AnyPropertyType,
 
1938
                                &type, &format, &nitems, &after, &data_esetroot);
 
1939
            if (data_esetroot && type == XA_PIXMAP && format == 32 && nitems == 1)
 
1940
            {
 
1941
                Pixmap xrootpmap = *((Pixmap *) data_root);
 
1942
                Pixmap esetrootpmap = *((Pixmap *) data_esetroot);
 
1943
                XFree (data_root);
 
1944
                XFree (data_esetroot);
 
1945
 
 
1946
                gdk_error_trap_push ();
 
1947
                if (xrootpmap && xrootpmap == esetrootpmap) {
 
1948
                    XKillClient (display, xrootpmap);
 
1949
                }
 
1950
                if (esetrootpmap && esetrootpmap != xrootpmap) {
 
1951
                    XKillClient (display, esetrootpmap);
 
1952
                }
 
1953
 
 
1954
                XSync (display, False);
 
1955
#if GTK_CHECK_VERSION (3, 0, 0)
 
1956
                gdk_error_trap_pop_ignored ();
 
1957
#else
 
1958
                gdk_error_trap_pop ();
 
1959
#endif
 
1960
 
 
1961
            }
 
1962
        }
 
1963
    }
 
1964
 
 
1965
    /* Get atoms for both properties in an array, create them if needed.
 
1966
     * This method is to avoid multiple round-trips to Xserver
 
1967
     */
 
1968
    if (!XInternAtoms (display, atom_names, G_N_ELEMENTS(atom_names), False, atoms) ||
 
1969
        atoms[0] == None || atoms[1] == None) {
 
1970
        g_warning("Could not create atoms needed to set root pixmap id/properties.\n");
 
1971
        return;
 
1972
    }
 
1973
 
 
1974
    /* Set new _XROOTMAP_ID and ESETROOT_PMAP_ID properties */
 
1975
    XChangeProperty (display, xroot, atoms[0], XA_PIXMAP, 32,
 
1976
                     PropModeReplace, (unsigned char *) &xpixmap, 1);
 
1977
 
 
1978
    XChangeProperty (display, xroot, atoms[1], XA_PIXMAP, 32,
 
1979
                     PropModeReplace, (unsigned char *) &xpixmap, 1);
 
1980
}
 
1981
 
 
1982
/**
 
1983
* set_surface_as_root:
 
1984
* @screen: the #GdkScreen to change root background on
 
1985
* @surface: the #cairo_surface_t to set root background from.
 
1986
* Must be an xlib surface backing a pixmap.
 
1987
*
 
1988
* Set the root pixmap, and properties pointing to it. We
 
1989
* do this atomically with a server grab to make sure that
 
1990
* we won't leak the pixmap if somebody else it setting
 
1991
* it at the same time. (This assumes that they follow the
 
1992
* same conventions we do). @surface should come from a call
 
1993
* to create_root_surface().
 
1994
**/
 
1995
static void
 
1996
set_surface_as_root (GdkScreen *screen, cairo_surface_t *surface)
 
1997
{
 
1998
    g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB);
 
1999
 
 
2000
    /* Desktop background pixmap should be created from dummy X client since most
 
2001
     * applications will try to kill it with XKillClient later when changing pixmap
 
2002
     */
 
2003
    Display *display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
 
2004
    Pixmap pixmap_id = cairo_xlib_surface_get_drawable (surface);
 
2005
    Window xroot = RootWindow (display, gdk_screen_get_number (screen));
 
2006
 
 
2007
    XGrabServer (display);
 
2008
 
 
2009
    XSetWindowBackgroundPixmap (display, xroot, pixmap_id);
 
2010
    set_root_pixmap_id (screen, display, pixmap_id);
 
2011
    XClearWindow (display, xroot);
 
2012
 
 
2013
    XFlush (display);
 
2014
    XUngrabServer (display);
 
2015
}
 
2016
 
 
2017
static void
 
2018
set_background (GdkPixbuf *new_bg)
 
2019
{
 
2020
    GdkRectangle monitor_geometry;
 
2021
    GdkPixbuf *bg = NULL;
 
2022
    GSList *iter;
 
2023
    gint i, p_height, p_width, height, width;
 
2024
    gdouble scale;
 
2025
    gint numScreens = 1;
 
2026
 
 
2027
    if (new_bg)
 
2028
        bg = new_bg;
 
2029
    else
 
2030
        bg = default_background_pixbuf;
 
2031
 
 
2032
    #if GDK_VERSION_CUR_STABLE < G_ENCODE_VERSION(3, 10)
 
2033
        numScreens = gdk_display_get_n_screens (gdk_display_get_default());
 
2034
    #endif
 
2035
 
 
2036
    /* Set the background */
 
2037
    for (i = 0; i < numScreens; i++)
 
2038
    {
 
2039
        GdkScreen *screen;
 
2040
        cairo_surface_t *surface;
 
2041
        cairo_t *c;
 
2042
        int monitor;
 
2043
 
 
2044
        screen = gdk_display_get_screen (gdk_display_get_default (), i);
 
2045
        surface = create_root_surface (screen);
 
2046
        c = cairo_create (surface);
 
2047
 
 
2048
        for (monitor = 0; monitor < gdk_screen_get_n_monitors (screen); monitor++)
 
2049
        {
 
2050
            gdk_screen_get_monitor_geometry (screen, monitor, &monitor_geometry);
 
2051
 
 
2052
            if (bg)
 
2053
            {
 
2054
                p_width = gdk_pixbuf_get_width(bg);
 
2055
                p_height = gdk_pixbuf_get_height(bg);
 
2056
 
 
2057
                scale = (double)monitor_geometry.width/p_width;
 
2058
                height = p_height * scale;
 
2059
                width = monitor_geometry.width;
 
2060
 
 
2061
                if (height < monitor_geometry.height)
 
2062
                {
 
2063
                    scale = (double)monitor_geometry.height/p_height;
 
2064
                    height = monitor_geometry.height;
 
2065
                    width = p_width * scale;
 
2066
                }
 
2067
 
 
2068
                GdkPixbuf *p = gdk_pixbuf_scale_simple (bg, width,
 
2069
                                                        height, GDK_INTERP_BILINEAR);
 
2070
                if (width > monitor_geometry.width)
 
2071
                {
 
2072
                    GdkPixbuf *tmp = gdk_pixbuf_new_subpixbuf(p, (width-monitor_geometry.width)/2, 0, monitor_geometry.width, monitor_geometry.height);
 
2073
                    g_object_unref (p);
 
2074
                    p = tmp;
 
2075
                }
 
2076
                if (!gdk_pixbuf_get_has_alpha (p))
 
2077
                {
 
2078
                    GdkPixbuf *tmp = gdk_pixbuf_add_alpha (p, FALSE, 255, 255, 255);
 
2079
                    g_object_unref (p);
 
2080
                    p = tmp;
 
2081
                }
 
2082
                gdk_cairo_set_source_pixbuf (c, p, monitor_geometry.x, monitor_geometry.y);
 
2083
                /* Make the background pixbuf globally accessible so it can be reused for fake transparency */
 
2084
                if (background_pixbuf)
 
2085
                    g_object_unref(background_pixbuf);                
 
2086
                background_pixbuf = p;
 
2087
            }
 
2088
            else {
 
2089
#if GTK_CHECK_VERSION (3, 0, 0)
 
2090
                gdk_cairo_set_source_rgba (c, default_background_color);
 
2091
#else
 
2092
                gdk_cairo_set_source_color (c, default_background_color);
 
2093
#endif
 
2094
                background_pixbuf = NULL;
 
2095
            }
 
2096
            cairo_paint (c);
 
2097
            iter = g_slist_nth(backgrounds, monitor);
 
2098
            gtk_widget_queue_draw(GTK_WIDGET(iter->data));
 
2099
        }
 
2100
 
 
2101
        cairo_destroy (c);
 
2102
 
 
2103
        /* Refresh background */
 
2104
        gdk_flush ();
 
2105
        set_surface_as_root(screen, surface);
 
2106
        cairo_surface_destroy(surface);
 
2107
    }
 
2108
    gtk_widget_queue_draw(GTK_WIDGET(login_window));
 
2109
    gtk_widget_queue_draw(GTK_WIDGET(panel_window));
 
2110
}
 
2111
 
 
2112
static gboolean
 
2113
clock_timeout_thread (void)
 
2114
{
 
2115
    time_t rawtime;
 
2116
    struct tm * timeinfo;
 
2117
    gchar time_str[50];
 
2118
    gchar *markup;
 
2119
    
 
2120
    time ( &rawtime );
 
2121
    timeinfo = localtime ( &rawtime );
 
2122
    
 
2123
    strftime(time_str, 50, clock_format, timeinfo);
 
2124
    markup = g_markup_printf_escaped("<b>%s</b>", time_str);
 
2125
    gtk_label_set_markup( GTK_LABEL(clock_label), markup );
 
2126
    g_free(markup);
 
2127
    
 
2128
    return TRUE;
 
2129
}
 
2130
 
 
2131
static gboolean
 
2132
read_position_from_str (const gchar *s, DimensionPosition *x)
 
2133
{
 
2134
    DimensionPosition p;
 
2135
    gchar *end = NULL;
 
2136
    gchar **parts = g_strsplit(s, ",", 2);
 
2137
    if (parts[0])
 
2138
    {
 
2139
        p.value = g_ascii_strtoll(parts[0], &end, 10);
 
2140
        p.percentage = end && end[0] == '%';
 
2141
        p.sign = (p.value < 0 || (p.value == 0 && parts[0][0] == '-')) ? -1 : +1;
 
2142
        if (p.value < 0)
 
2143
            p.value *= -1;
 
2144
        if (g_strcmp0(parts[1], "start") == 0)
 
2145
            p.anchor = -1;
 
2146
        else if (g_strcmp0(parts[1], "center") == 0)
 
2147
            p.anchor = 0;
 
2148
        else if (g_strcmp0(parts[1], "end") == 0)
 
2149
            p.anchor = +1;
 
2150
        else
 
2151
            p.anchor = p.sign > 0 ? -1 : +1;
 
2152
        *x = p;
 
2153
    }
 
2154
    else
 
2155
        x = NULL;
 
2156
    g_strfreev (parts);
 
2157
    return x != NULL;
 
2158
}
 
2159
 
 
2160
static GdkFilterReturn
 
2161
focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer  data)
 
2162
{
 
2163
    XEvent* xevent = (XEvent*)gxevent;
 
2164
    GdkWindow* keyboard_win = onboard_window ? gtk_widget_get_window (GTK_WIDGET (onboard_window)) : NULL;
 
2165
    if (xevent->type == MapNotify)
 
2166
    {
 
2167
        Window xwin = xevent->xmap.window;
 
2168
        Window keyboard_xid = 0;
 
2169
        GdkDisplay* display = gdk_x11_lookup_xdisplay (xevent->xmap.display);
 
2170
        GdkWindow* win = gdk_x11_window_foreign_new_for_display (display, xwin);
 
2171
 
 
2172
        /* Check to see if this window is our onboard window, since we don't want to focus it. */
 
2173
        if (keyboard_win)
 
2174
#if GTK_CHECK_VERSION (3, 0, 0)
 
2175
                keyboard_xid = gdk_x11_window_get_xid (keyboard_win);
 
2176
#else
 
2177
                keyboard_xid = gdk_x11_drawable_get_xid (keyboard_win);
 
2178
#endif
 
2179
            
 
2180
        if (xwin != keyboard_xid && gdk_window_get_type_hint (win) != GDK_WINDOW_TYPE_HINT_NOTIFICATION)
 
2181
        {
 
2182
            gdk_window_focus (win, GDK_CURRENT_TIME);
 
2183
            /* Make sure to keep keyboard above */
 
2184
            if (onboard_window)
 
2185
            {
 
2186
                if (keyboard_win)
 
2187
                    gdk_window_raise (keyboard_win);
 
2188
            }
 
2189
        }
 
2190
    }
 
2191
    else if (xevent->type == UnmapNotify)
 
2192
    {
 
2193
        Window xwin;
 
2194
        int revert_to;
 
2195
        XGetInputFocus (xevent->xunmap.display, &xwin, &revert_to);
 
2196
 
 
2197
        if (revert_to == RevertToNone)
 
2198
        {
 
2199
            gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
 
2200
            /* Make sure to keep keyboard above */
 
2201
            if (onboard_window)
 
2202
            {
 
2203
                if (keyboard_win)
 
2204
                    gdk_window_raise (keyboard_win);
 
2205
            }
 
2206
        }
 
2207
    }
 
2208
    return GDK_FILTER_CONTINUE;
 
2209
}
 
2210
 
 
2211
int
 
2212
main (int argc, char **argv)
 
2213
{
 
2214
    GKeyFile *config;
 
2215
    GdkRectangle monitor_geometry;
 
2216
    GtkBuilder *builder;
 
2217
    const GList *items, *item;
 
2218
    GtkCellRenderer *renderer;
 
2219
    GtkWidget *image, *infobar_compat, *content_area;
 
2220
    gchar *value, *state_dir;
 
2221
#if GTK_CHECK_VERSION (3, 0, 0)
 
2222
    GdkRGBA background_color;
 
2223
    GtkIconTheme *icon_theme;
 
2224
    GtkCssProvider *css_provider;
 
2225
#else
 
2226
    GdkColor background_color;
 
2227
#endif
 
2228
    GError *error = NULL;
 
2229
 
 
2230
    /* Background windows */
 
2231
    gint monitor, scr;
 
2232
    gint numScreens = 1;
 
2233
    GdkScreen *screen;
 
2234
    GtkWidget *window;
 
2235
 
 
2236
    Display* display;
 
2237
 
 
2238
    #ifdef START_INDICATOR_SERVICES
 
2239
    GPid indicator_pid = 0, spi_pid = 0;
 
2240
    #endif
 
2241
 
 
2242
    /* Disable global menus */
 
2243
    g_unsetenv ("UBUNTU_MENUPROXY");
 
2244
 
 
2245
    /* Initialize i18n */
 
2246
    setlocale (LC_ALL, "");
 
2247
    bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
 
2248
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
2249
    textdomain (GETTEXT_PACKAGE);
 
2250
 
 
2251
    signal (SIGTERM, sigterm_cb);
 
2252
 
 
2253
#if GTK_CHECK_VERSION (3, 0, 0)
 
2254
#else
 
2255
    /* init threads */
 
2256
    gdk_threads_init();
 
2257
#endif
 
2258
 
 
2259
    /* init gtk */
 
2260
    gtk_init (&argc, &argv);
 
2261
    
 
2262
#ifdef HAVE_LIBIDO
 
2263
    ido_init ();
 
2264
#endif
 
2265
 
 
2266
    config = g_key_file_new ();
 
2267
    g_key_file_load_from_file (config, CONFIG_FILE, G_KEY_FILE_NONE, &error);
 
2268
    if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
 
2269
        g_warning ("Failed to load configuration from %s: %s\n", CONFIG_FILE, error->message);
 
2270
    g_clear_error (&error);
 
2271
 
 
2272
    state_dir = g_build_filename (g_get_user_cache_dir (), "lightdm-gtk-greeter", NULL);
 
2273
    g_mkdir_with_parents (state_dir, 0775);
 
2274
    state_filename = g_build_filename (state_dir, "state", NULL);
 
2275
    g_free (state_dir);
 
2276
 
 
2277
    state = g_key_file_new ();
 
2278
    g_key_file_load_from_file (state, state_filename, G_KEY_FILE_NONE, &error);
 
2279
    if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
 
2280
        g_warning ("Failed to load state from %s: %s\n", state_filename, error->message);
 
2281
    g_clear_error (&error);
 
2282
 
 
2283
    greeter = lightdm_greeter_new ();
 
2284
    g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);  
 
2285
    g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);
 
2286
    g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
 
2287
    g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (lightdm_greeter_authenticate_autologin), NULL);
 
2288
    if (!lightdm_greeter_connect_sync (greeter, NULL))
 
2289
        return EXIT_FAILURE;
 
2290
 
 
2291
    /* Set default cursor */
 
2292
    gdk_window_set_cursor (gdk_get_default_root_window (), gdk_cursor_new (GDK_LEFT_PTR));
 
2293
 
 
2294
    /* Load background */
 
2295
    value = g_key_file_get_value (config, "greeter", "background", NULL);
 
2296
    if (!value)
 
2297
        value = g_strdup ("#000000");
 
2298
#if GTK_CHECK_VERSION (3, 0, 0)
 
2299
    if (!gdk_rgba_parse (&background_color, value))
 
2300
#else
 
2301
    if (!gdk_color_parse (value, &background_color))
 
2302
#endif
 
2303
    {
 
2304
        gchar *path;
 
2305
        GError *error = NULL;
 
2306
 
 
2307
        if (g_path_is_absolute (value))
 
2308
            path = g_strdup (value);
 
2309
        else
 
2310
            path = g_build_filename (GREETER_DATA_DIR, value, NULL);
 
2311
 
 
2312
        g_debug ("Loading background %s", path);
 
2313
        default_background_pixbuf = gdk_pixbuf_new_from_file (path, &error);
 
2314
        if (!default_background_pixbuf)
 
2315
            g_warning ("Failed to load background: %s", error->message);
 
2316
        g_clear_error (&error);
 
2317
        g_free (path);
 
2318
    }
 
2319
    else
 
2320
    {
 
2321
        g_debug ("Using background color %s", value);
 
2322
#if GTK_CHECK_VERSION (3, 0, 0)
 
2323
        default_background_color = gdk_rgba_copy (&background_color);
 
2324
#else
 
2325
        default_background_color = gdk_color_copy (&background_color);
 
2326
#endif
 
2327
    }
 
2328
    g_free (value);
 
2329
 
 
2330
    /* Make the greeter behave a bit more like a screensaver if used as un/lock-screen by blanking the screen */
 
2331
    gchar* end_ptr = NULL;
 
2332
    int screensaver_timeout = 60;
 
2333
    value = g_key_file_get_value (config, "greeter", "screensaver-timeout", NULL);
 
2334
    if (value)
 
2335
        screensaver_timeout = g_ascii_strtoll (value, &end_ptr, 0);
 
2336
    g_free (value);
 
2337
    
 
2338
    display = gdk_x11_display_get_xdisplay(gdk_display_get_default ());
 
2339
    if (lightdm_greeter_get_lock_hint (greeter)) {
 
2340
        XGetScreenSaver(display, &timeout, &interval, &prefer_blanking, &allow_exposures);
 
2341
        XForceScreenSaver(display, ScreenSaverActive);
 
2342
        XSetScreenSaver(display, screensaver_timeout, 0, ScreenSaverActive, DefaultExposures);
 
2343
    }
 
2344
 
 
2345
    /* Set GTK+ settings */
 
2346
    value = g_key_file_get_value (config, "greeter", "theme-name", NULL);
 
2347
    if (value)
 
2348
    {
 
2349
        g_debug ("Using Gtk+ theme %s", value);
 
2350
        g_object_set (gtk_settings_get_default (), "gtk-theme-name", value, NULL);
 
2351
    }
 
2352
    g_free (value);
 
2353
    g_object_get (gtk_settings_get_default (), "gtk-theme-name", &default_theme_name, NULL);
 
2354
    g_debug ("Default Gtk+ theme is '%s'", default_theme_name);
 
2355
 
 
2356
    value = g_key_file_get_value (config, "greeter", "icon-theme-name", NULL);
 
2357
    if (value)
 
2358
    {
 
2359
        g_debug ("Using icon theme %s", value);
 
2360
        g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", value, NULL);
 
2361
    }
 
2362
    g_free (value);
 
2363
    g_object_get (gtk_settings_get_default (), "gtk-icon-theme-name", &default_icon_theme_name, NULL);
 
2364
    g_debug ("Default theme is '%s'", default_icon_theme_name);
 
2365
 
 
2366
    value = g_key_file_get_value (config, "greeter", "font-name", NULL);
 
2367
    if (value)
 
2368
    {
 
2369
        g_debug ("Using font %s", value);
 
2370
        g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
 
2371
    }
 
2372
    else
 
2373
    {
 
2374
        value = g_strdup("Sans 10");
 
2375
        g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
 
2376
    }
 
2377
    g_object_get (gtk_settings_get_default (), "gtk-font-name", &default_font_name, NULL);  
 
2378
    value = g_key_file_get_value (config, "greeter", "xft-dpi", NULL);
 
2379
    if (value)
 
2380
        g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", (int) (1024 * atof (value)), NULL);
 
2381
    value = g_key_file_get_value (config, "greeter", "xft-antialias", NULL);
 
2382
    if (value)
 
2383
        g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", g_strcmp0 (value, "true") == 0, NULL);
 
2384
    g_free (value);
 
2385
    value = g_key_file_get_value (config, "greeter", "xft-hintstyle", NULL);
 
2386
    if (value)
 
2387
        g_object_set (gtk_settings_get_default (), "gtk-xft-hintstyle", value, NULL);
 
2388
    g_free (value);
 
2389
    value = g_key_file_get_value (config, "greeter", "xft-rgba", NULL);
 
2390
    if (value)
 
2391
        g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);
 
2392
    g_free (value);
 
2393
    
 
2394
    /* Get a11y on screen keyboard command*/
 
2395
    gint argp;
 
2396
    value = g_key_file_get_value (config, "greeter", "keyboard", NULL);
 
2397
    g_debug ("a11y keyboard command is '%s'", value);
 
2398
    /* Set NULL to blank to avoid warnings */
 
2399
    if (!value) { value = g_strdup(""); }
 
2400
    g_shell_parse_argv (value, &argp, &a11y_keyboard_command, NULL);
 
2401
    g_free (value);
 
2402
 
 
2403
    builder = gtk_builder_new ();
 
2404
    if (!gtk_builder_add_from_string (builder, lightdm_gtk_greeter_ui,
 
2405
                                      lightdm_gtk_greeter_ui_length, &error))
 
2406
    {
 
2407
        g_warning ("Error loading UI: %s", error->message);
 
2408
        return EXIT_FAILURE;
 
2409
    }
 
2410
    g_clear_error (&error);
 
2411
    
 
2412
    /* Panel */
 
2413
    panel_window = GTK_WINDOW (gtk_builder_get_object (builder, "panel_window"));
 
2414
#if GTK_CHECK_VERSION (3, 0, 0)
 
2415
    gtk_style_context_add_class(GTK_STYLE_CONTEXT(gtk_widget_get_style_context(GTK_WIDGET(panel_window))), "lightdm-gtk-greeter");
 
2416
    gtk_style_context_add_class(GTK_STYLE_CONTEXT(gtk_widget_get_style_context(GTK_WIDGET(panel_window))), GTK_STYLE_CLASS_MENUBAR);
 
2417
    g_signal_connect (G_OBJECT (panel_window), "draw", G_CALLBACK (background_window_draw), NULL);
 
2418
#endif
 
2419
    gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "hostname_label")), lightdm_get_hostname ());
 
2420
    session_menu = GTK_MENU(gtk_builder_get_object (builder, "session_menu"));
 
2421
    language_menu = GTK_MENU(gtk_builder_get_object (builder, "language_menu"));
 
2422
    clock_label = GTK_WIDGET(gtk_builder_get_object (builder, "clock_label"));
 
2423
    menubar = GTK_WIDGET (gtk_builder_get_object (builder, "menubar"));
 
2424
    /* Never allow the panel-window to be moved via the menubar */
 
2425
#if GTK_CHECK_VERSION (3, 0, 0) 
 
2426
    css_provider = gtk_css_provider_new ();
 
2427
    gtk_css_provider_load_from_data (css_provider, "* { -GtkWidget-window-dragging: false; }", -1, NULL);
 
2428
    gtk_style_context_add_provider (GTK_STYLE_CONTEXT(gtk_widget_get_style_context(GTK_WIDGET(menubar))), GTK_STYLE_PROVIDER (css_provider), 800);
 
2429
#endif
 
2430
    
 
2431
    keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
 
2432
 
 
2433
    /* Login window */
 
2434
    login_window = GTK_WINDOW (gtk_builder_get_object (builder, "login_window"));
 
2435
    user_image = GTK_IMAGE (gtk_builder_get_object (builder, "user_image"));
 
2436
    user_combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, "user_combobox"));
 
2437
    username_entry = GTK_ENTRY (gtk_builder_get_object (builder, "username_entry"));
 
2438
    password_entry = GTK_ENTRY (gtk_builder_get_object (builder, "password_entry"));
 
2439
 
 
2440
    /* Add InfoBar via code for GTK+2 compatability */
 
2441
    infobar_compat = GTK_WIDGET(gtk_builder_get_object(builder, "infobar_compat"));
 
2442
    info_bar = GTK_INFO_BAR (gtk_info_bar_new());
 
2443
    gtk_info_bar_set_message_type(info_bar, GTK_MESSAGE_ERROR);
 
2444
    gtk_widget_set_name(GTK_WIDGET(info_bar), "greeter_infobar");
 
2445
    content_area = gtk_info_bar_get_content_area(info_bar);
 
2446
 
 
2447
    message_label = GTK_LABEL (gtk_builder_get_object (builder, "message_label"));
 
2448
    g_object_ref(message_label);
 
2449
    gtk_container_remove(GTK_CONTAINER(infobar_compat), GTK_WIDGET(message_label));
 
2450
    gtk_container_add(GTK_CONTAINER(content_area), GTK_WIDGET(message_label));
 
2451
    g_object_unref(message_label);
 
2452
 
 
2453
    gtk_container_add(GTK_CONTAINER(infobar_compat), GTK_WIDGET(info_bar));
 
2454
 
 
2455
    cancel_button = GTK_BUTTON (gtk_builder_get_object (builder, "cancel_button"));
 
2456
    login_button = GTK_BUTTON (gtk_builder_get_object (builder, "login_button"));
 
2457
 
 
2458
#if GTK_CHECK_VERSION (3, 0, 0)
 
2459
    g_signal_connect (G_OBJECT (login_window), "draw", G_CALLBACK (login_window_draw), NULL);
 
2460
#else
 
2461
    g_signal_connect (G_OBJECT (login_window), "size-allocate", G_CALLBACK (login_window_size_allocate), NULL);
 
2462
#endif
 
2463
 
 
2464
    /* To maintain compatability with GTK+2, set special properties here */
 
2465
#if GTK_CHECK_VERSION (3, 0, 0)
 
2466
    gtk_style_context_add_class(GTK_STYLE_CONTEXT(gtk_widget_get_style_context(GTK_WIDGET(login_window))), "lightdm-gtk-greeter");
 
2467
    gtk_box_set_child_packing(GTK_BOX(content_area), GTK_WIDGET(message_label), TRUE, TRUE, 0, GTK_PACK_START);
 
2468
    gtk_window_set_has_resize_grip(GTK_WINDOW(panel_window), FALSE);
 
2469
    gtk_widget_set_margin_top(GTK_WIDGET(user_combo), 12);
 
2470
    gtk_widget_set_margin_bottom(GTK_WIDGET(password_entry), 12);
 
2471
    gtk_entry_set_placeholder_text(password_entry, _("Enter your password"));
 
2472
    gtk_entry_set_placeholder_text(username_entry, _("Enter your username"));
 
2473
    icon_theme = gtk_icon_theme_get_default();
 
2474
#else
 
2475
    gtk_container_set_border_width (GTK_CONTAINER(gtk_builder_get_object (builder, "vbox2")), 18);
 
2476
    gtk_container_set_border_width (GTK_CONTAINER(gtk_builder_get_object (builder, "content_frame")), 14);
 
2477
    gtk_container_set_border_width (GTK_CONTAINER(gtk_builder_get_object (builder, "buttonbox_frame")), 8);
 
2478
    gtk_widget_set_tooltip_text(GTK_WIDGET(password_entry), _("Enter your password"));
 
2479
    gtk_widget_set_tooltip_text(GTK_WIDGET(username_entry), _("Enter your username"));
 
2480
#endif
 
2481
 
 
2482
    /* Indicators */
 
2483
    session_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "session_menuitem"));
 
2484
    language_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "language_menuitem"));
 
2485
    a11y_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "a11y_menuitem"));
 
2486
    power_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "power_menuitem"));
 
2487
 
 
2488
    gtk_accel_map_add_entry ("<Login>/a11y/font", GDK_KEY_F1, 0);
 
2489
    gtk_accel_map_add_entry ("<Login>/a11y/contrast", GDK_KEY_F2, 0);
 
2490
    gtk_accel_map_add_entry ("<Login>/a11y/keyboard", GDK_KEY_F3, 0);
 
2491
    gtk_accel_map_add_entry ("<Login>/power/shutdown", GDK_KEY_F4, GDK_MOD1_MASK);
 
2492
 
 
2493
#ifdef START_INDICATOR_SERVICES
 
2494
    init_indicators (config, &indicator_pid, &spi_pid);
 
2495
#else
 
2496
    init_indicators (config);
 
2497
#endif
 
2498
 
 
2499
    value = g_key_file_get_value (config, "greeter", "default-user-image", NULL);
 
2500
    if (value)
 
2501
    {
 
2502
        if (value[0] == '#')
 
2503
            default_user_icon = g_strdup (value + 1);
 
2504
        else
 
2505
        {
 
2506
            default_user_pixbuf = gdk_pixbuf_new_from_file (value, &error);
 
2507
            if (!default_user_pixbuf)
 
2508
            {
 
2509
                g_warning ("Failed to load default user image: %s", error->message);
 
2510
                g_clear_error (&error);
 
2511
            }
 
2512
        }
 
2513
        g_free (value);
 
2514
    }
 
2515
 
 
2516
    /* Clock */
 
2517
    gtk_widget_set_visible(GTK_WIDGET(clock_label),
 
2518
                           g_key_file_get_boolean (config, "greeter", "show-clock", NULL));
 
2519
    clock_format = g_key_file_get_value (config, "greeter", "clock-format", NULL);
 
2520
    if (!clock_format)
 
2521
        clock_format = "%a, %H:%M";
 
2522
 
 
2523
    /* Session menu */
 
2524
    if (gtk_widget_get_visible (session_menuitem))
 
2525
    {
 
2526
#if GTK_CHECK_VERSION (3, 0, 0)
 
2527
        if (gtk_icon_theme_has_icon(icon_theme, "document-properties-symbolic"))
 
2528
            session_badge = gtk_image_new_from_icon_name ("document-properties-symbolic", GTK_ICON_SIZE_MENU);
 
2529
        else
 
2530
            session_badge = gtk_image_new_from_icon_name ("document-properties", GTK_ICON_SIZE_MENU);
 
2531
#else
 
2532
        session_badge = gtk_image_new_from_icon_name ("document-properties", GTK_ICON_SIZE_MENU);
 
2533
#endif
 
2534
        gtk_widget_show (session_badge);
 
2535
        gtk_container_add (GTK_CONTAINER (session_menuitem), session_badge);
 
2536
 
 
2537
        items = lightdm_get_sessions ();
 
2538
        GSList *sessions = NULL;
 
2539
        for (item = items; item; item = item->next)
 
2540
        {
 
2541
            LightDMSession *session = item->data;
 
2542
            GtkWidget *radiomenuitem;
 
2543
            
 
2544
            radiomenuitem = gtk_radio_menu_item_new_with_label (sessions, lightdm_session_get_name (session));
 
2545
            g_object_set_data (G_OBJECT (radiomenuitem), "session-key", (gpointer) lightdm_session_get_key (session));
 
2546
            sessions = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (radiomenuitem));
 
2547
            g_signal_connect(G_OBJECT(radiomenuitem), "activate", G_CALLBACK(session_selected_cb), NULL);
 
2548
            gtk_menu_shell_append (GTK_MENU_SHELL(session_menu), radiomenuitem);
 
2549
            gtk_widget_show (GTK_WIDGET (radiomenuitem));
 
2550
        }
 
2551
        set_session (NULL);
 
2552
    }
 
2553
 
 
2554
    /* Language menu */
 
2555
    if (gtk_widget_get_visible (language_menuitem))
 
2556
    {
 
2557
        items = lightdm_get_languages ();
 
2558
        GSList *languages = NULL;
 
2559
        for (item = items; item; item = item->next)
 
2560
        {
 
2561
            LightDMLanguage *language = item->data;
 
2562
            const gchar *country, *code;
 
2563
            gchar *label;
 
2564
            GtkWidget *radiomenuitem;
 
2565
 
 
2566
            country = lightdm_language_get_territory (language);
 
2567
            if (country)
 
2568
                label = g_strdup_printf ("%s - %s", lightdm_language_get_name (language), country);
 
2569
            else
 
2570
                label = g_strdup (lightdm_language_get_name (language));
 
2571
                
 
2572
            code = lightdm_language_get_code (language);
 
2573
            gchar *modifier = strchr (code, '@');
 
2574
            if (modifier != NULL)
 
2575
            {
 
2576
                gchar *label_new = g_strdup_printf ("%s [%s]", label, modifier+1);
 
2577
                g_free (label);
 
2578
                label = label_new;
 
2579
            }
 
2580
 
 
2581
            radiomenuitem = gtk_radio_menu_item_new_with_label (languages, label);
 
2582
            g_object_set_data (G_OBJECT (radiomenuitem), "language-code", (gpointer) code);
 
2583
            languages = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (radiomenuitem));
 
2584
            g_signal_connect(G_OBJECT(radiomenuitem), "activate", G_CALLBACK(language_selected_cb), NULL);
 
2585
            gtk_menu_shell_append (GTK_MENU_SHELL(language_menu), radiomenuitem);
 
2586
            gtk_widget_show (GTK_WIDGET (radiomenuitem));
 
2587
        }
 
2588
        set_language (NULL);
 
2589
    }
 
2590
    
 
2591
    /* a11y menu */
 
2592
    if (gtk_widget_get_visible (a11y_menuitem))
 
2593
    {
 
2594
    #if GTK_CHECK_VERSION (3, 0, 0)
 
2595
        if (gtk_icon_theme_has_icon(icon_theme, "preferences-desktop-accessibility-symbolic"))
 
2596
            image = gtk_image_new_from_icon_name ("preferences-desktop-accessibility-symbolic", GTK_ICON_SIZE_MENU);
 
2597
        else
 
2598
            image = gtk_image_new_from_icon_name ("preferences-desktop-accessibility", GTK_ICON_SIZE_MENU);
 
2599
    #else
 
2600
        image = gtk_image_new_from_icon_name ("preferences-desktop-accessibility", GTK_ICON_SIZE_MENU);
 
2601
    #endif
 
2602
        gtk_widget_show (image);
 
2603
        gtk_container_add (GTK_CONTAINER (a11y_menuitem), image);
 
2604
    }
 
2605
 
 
2606
    /* Power menu */
 
2607
    if (gtk_widget_get_visible (power_menuitem))
 
2608
    {
 
2609
#if GTK_CHECK_VERSION (3, 0, 0)
 
2610
        if (gtk_icon_theme_has_icon(icon_theme, "system-shutdown-symbolic"))
 
2611
            image = gtk_image_new_from_icon_name ("system-shutdown-symbolic", GTK_ICON_SIZE_MENU);
 
2612
        else
 
2613
            image = gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_MENU);
 
2614
#else
 
2615
        image = gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_MENU);
 
2616
#endif
 
2617
        gtk_widget_show (image);
 
2618
        gtk_container_add (GTK_CONTAINER (power_menuitem), image);
 
2619
 
 
2620
        suspend_menuitem = (GTK_WIDGET (gtk_builder_get_object (builder, "suspend_menuitem")));
 
2621
        hibernate_menuitem = (GTK_WIDGET (gtk_builder_get_object (builder, "hibernate_menuitem")));
 
2622
        restart_menuitem = (GTK_WIDGET (gtk_builder_get_object (builder, "restart_menuitem")));
 
2623
        shutdown_menuitem = (GTK_WIDGET (gtk_builder_get_object (builder, "shutdown_menuitem")));
 
2624
 
 
2625
        g_signal_connect (G_OBJECT (power_menuitem),"activate", G_CALLBACK(power_menu_cb), NULL);
 
2626
    }
 
2627
 
 
2628
    /* Users combobox */
 
2629
    renderer = gtk_cell_renderer_text_new();
 
2630
    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (user_combo), renderer, TRUE);
 
2631
    gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (user_combo), renderer, "text", 1);
 
2632
    gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (user_combo), renderer, "weight", 2);
 
2633
 
 
2634
    #if GDK_VERSION_CUR_STABLE < G_ENCODE_VERSION(3, 10)
 
2635
        numScreens = gdk_display_get_n_screens (gdk_display_get_default());
 
2636
    #endif
 
2637
 
 
2638
    /* Set up the background images */  
 
2639
    for (scr = 0; scr < numScreens; scr++)
 
2640
    {
 
2641
        screen = gdk_display_get_screen (gdk_display_get_default (), scr);
 
2642
        for (monitor = 0; monitor < gdk_screen_get_n_monitors (screen); monitor++)
 
2643
        {
 
2644
            gdk_screen_get_monitor_geometry (screen, monitor, &monitor_geometry);
 
2645
        
 
2646
            window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
2647
            gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DESKTOP);
 
2648
#if GTK_CHECK_VERSION (3, 0, 0)
 
2649
            gtk_widget_override_background_color(GTK_WIDGET(window), GTK_STATE_FLAG_NORMAL, &background_color);
 
2650
#else
 
2651
            gtk_widget_modify_bg(GTK_WIDGET(window), GTK_STATE_NORMAL, &background_color);
 
2652
#endif
 
2653
            gtk_window_set_screen(GTK_WINDOW(window), screen);
 
2654
            gtk_window_set_keep_below(GTK_WINDOW(window), TRUE);
 
2655
            gtk_widget_set_size_request(window, monitor_geometry.width, monitor_geometry.height);
 
2656
            gtk_window_set_resizable (GTK_WINDOW(window), FALSE);
 
2657
            gtk_widget_set_app_paintable (GTK_WIDGET(window), TRUE);
 
2658
            gtk_window_move (GTK_WINDOW(window), monitor_geometry.x, monitor_geometry.y);
 
2659
 
 
2660
            backgrounds = g_slist_prepend(backgrounds, window);
 
2661
            gtk_widget_show (window);
 
2662
#if GTK_CHECK_VERSION (3, 0, 0)
 
2663
            g_signal_connect (G_OBJECT (window), "draw", G_CALLBACK (background_window_draw), NULL);
 
2664
#else
 
2665
            g_signal_connect (G_OBJECT (window), "expose-event", G_CALLBACK (background_window_expose), NULL);
 
2666
#endif
 
2667
            gtk_widget_queue_draw (GTK_WIDGET(window));
 
2668
        }
 
2669
    }
 
2670
    backgrounds = g_slist_reverse(backgrounds);
 
2671
 
 
2672
    if (lightdm_greeter_get_hide_users_hint (greeter))
 
2673
    {
 
2674
        /* Set the background to default */
 
2675
        set_background (NULL);
 
2676
        start_authentication ("*other");
 
2677
    }
 
2678
    else
 
2679
    {
 
2680
        /* This also sets the background to user's */
 
2681
        load_user_list ();
 
2682
        gtk_widget_hide (GTK_WIDGET (cancel_button));
 
2683
        gtk_widget_show (GTK_WIDGET (user_combo));
 
2684
    }
 
2685
 
 
2686
    /* Window position */
 
2687
    /* Default: x-center, y-center */
 
2688
    main_window_pos = CENTERED_WINDOW_POS;
 
2689
    value = g_key_file_get_value (config, "greeter", "position", NULL);
 
2690
    if (value)
 
2691
    {
 
2692
        gchar *x = value;
 
2693
        gchar *y = strchr(value, ' ');
 
2694
        if (y)
 
2695
            (y++)[0] = '\0';
 
2696
        
 
2697
        if (read_position_from_str (x, &main_window_pos.x))
 
2698
            /* If there is no y-part then y = x */
 
2699
            if (!y || !read_position_from_str (y, &main_window_pos.y))
 
2700
                main_window_pos.y = main_window_pos.x;
 
2701
 
 
2702
        g_free (value);
 
2703
    }
 
2704
 
 
2705
    gtk_builder_connect_signals(builder, greeter);
 
2706
 
 
2707
    gtk_widget_show (GTK_WIDGET (login_window));
 
2708
    center_window (login_window,  NULL, &main_window_pos);
 
2709
    g_signal_connect (GTK_WIDGET (login_window), "size-allocate", G_CALLBACK (center_window), &main_window_pos);
 
2710
 
 
2711
    gtk_widget_show (GTK_WIDGET (panel_window));
 
2712
    GtkAllocation allocation;
 
2713
    gtk_widget_get_allocation (GTK_WIDGET (panel_window), &allocation);
 
2714
    gdk_screen_get_monitor_geometry (gdk_screen_get_default (), gdk_screen_get_primary_monitor (gdk_screen_get_default ()), &monitor_geometry);
 
2715
    gtk_window_resize (panel_window, monitor_geometry.width, allocation.height);
 
2716
    gtk_window_move (panel_window, monitor_geometry.x, monitor_geometry.y);
 
2717
 
 
2718
    gtk_widget_show (GTK_WIDGET (login_window));
 
2719
    gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
 
2720
 
 
2721
    if (a11y_keyboard_command)
 
2722
    {
 
2723
        /* If command is onboard, position the application at the bottom-center of the screen */
 
2724
        if (g_strcmp0(a11y_keyboard_command[0], "onboard") == 0)
 
2725
        {
 
2726
            gint argp;
 
2727
            value = "onboard --xid";
 
2728
            g_debug ("a11y keyboard command is now '%s'", value);
 
2729
            g_shell_parse_argv (value, &argp, &a11y_keyboard_command, NULL);
 
2730
            onboard_window = GTK_WINDOW (gtk_window_new(GTK_WINDOW_TOPLEVEL));
 
2731
            gtk_widget_set_size_request (GTK_WIDGET (onboard_window), 605, 205);
 
2732
            gtk_window_move (onboard_window, (monitor_geometry.width - 605)/2, monitor_geometry.height - 205);
 
2733
        }
 
2734
    }
 
2735
    gtk_widget_set_sensitive (keyboard_menuitem, a11y_keyboard_command != NULL);
 
2736
    gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);
 
2737
    gdk_threads_add_timeout (100, (GSourceFunc) clock_timeout_thread, NULL);
 
2738
 
 
2739
    /* focus fix (source: unity-greeter) */
 
2740
    GdkWindow* root_window = gdk_get_default_root_window ();
 
2741
    gdk_window_set_events (root_window, gdk_window_get_events (root_window) | GDK_SUBSTRUCTURE_MASK);
 
2742
    gdk_window_add_filter (root_window, focus_upon_map, NULL);
 
2743
 
 
2744
#if GTK_CHECK_VERSION (3, 0, 0)
 
2745
#else
 
2746
    gdk_threads_enter();
 
2747
#endif
 
2748
    gtk_main ();
 
2749
#if GTK_CHECK_VERSION (3, 0, 0)
 
2750
#else
 
2751
    gdk_threads_leave();
 
2752
#endif
 
2753
 
 
2754
#ifdef START_INDICATOR_SERVICES
 
2755
    if (indicator_pid)
 
2756
    {
 
2757
                kill (indicator_pid, SIGTERM);
 
2758
                waitpid (indicator_pid, NULL, 0);
 
2759
    }
 
2760
 
 
2761
    if (spi_pid)
 
2762
    {
 
2763
                kill (spi_pid, SIGTERM);
 
2764
                waitpid (spi_pid, NULL, 0);
 
2765
    }
 
2766
#endif
 
2767
 
 
2768
    if (background_pixbuf)
 
2769
        g_object_unref (background_pixbuf);
 
2770
    if (default_background_pixbuf)
 
2771
        g_object_unref (default_background_pixbuf);
 
2772
    if (default_background_color)
 
2773
#if GTK_CHECK_VERSION (3, 0, 0)
 
2774
        gdk_rgba_free (default_background_color);
 
2775
#else
 
2776
        gdk_color_free (default_background_color);
 
2777
#endif
 
2778
 
 
2779
    return EXIT_SUCCESS;
 
2780
}