~noskcaj/ubuntu/wily/lightdm-gtk-greeter/merge

« back to all changes in this revision

Viewing changes to src/lightdm-gtk-greeter.c

  • Committer: Package Import Robot
  • Author(s): Sean Davis, Sean Davis
  • Date: 2015-06-16 20:20:00 UTC
  • mfrom: (1.2.20 sid)
  • Revision ID: package-import@ubuntu.com-20150616202000-whdodnwujc6gfv2i
Tags: 2.0.1-1ubuntu1
[ Sean Davis ]
* Merge from Debian unstable.  Remaining changes:
  - debian/01_ubuntu.conf
    + Renamed from lightdm-gtk-greeter-ubuntu.conf
    + Removed unneeded comments
  - debian/control, debian/rules:
    + Add Indicators support.
  - debian/control:
    + Build-Depends on liblightdm-gobject-1-dev instead on
      liblightdm-gobject-dev as it's non-existing in archive.
  - debian/copyright:
    + Update copyright for lightdm-gtk-greeter, it's been a long time
      since lightdm housed all of the greeters
  - debian/01_ubuntu.conf,
    debian/lightdm-gtk-greeter.{post,pre}{inst,rm},
    debian/60-lightdm-gtk-greeter.conf:
    + Install and remove Ubuntu conf files.
  - debian/lightdm-gtk-greeter.{preinst,prerm,postinstpostrm}
    + Migrate post-1.0.0 configuration to conf.d/01_ubuntu.conf
    + Do not use update-alternatives for lightdm-gtk-greeter config
  - debian/rules
    + Install lightdm and lightdm-gtk-greeter configuration

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
 
48
48
#include <lightdm.h>
49
49
 
 
50
#include "src/greeterconfiguration.h"
50
51
#include "src/greetermenubar.h"
51
52
#include "src/greeterbackground.h"
52
53
#include "src/lightdm-gtk-greeter-ui.h"
53
54
#include "src/lightdm-gtk-greeter-css-fallback.h"
54
55
#include "src/lightdm-gtk-greeter-css-application.h"
55
56
 
 
57
 
56
58
static LightDMGreeter *greeter;
57
59
 
58
 
/* State file */
59
 
static GKeyFile *state;
60
 
static gchar *state_filename;
61
 
static void save_state_file (void);
62
 
 
63
60
/* List of spawned processes */
64
61
static GSList *pids_to_close = NULL;
65
62
static GPid spawn_argv_pid (gchar **argv, GSpawnFlags flags, gint *pfd, GError **perror);
70
67
static void sigterm_cb (gpointer user_data);
71
68
 
72
69
/* Screen window */
73
 
static GtkOverlay *screen_overlay;
 
70
static GtkOverlay   *screen_overlay;
 
71
static GtkWidget    *screen_overlay_child;
74
72
 
75
73
/* Login window */
76
74
static GtkWidget    *login_window;
123
121
    DimensionPosition width, height;
124
122
} WindowPosition;
125
123
 
126
 
static WindowPosition* key_file_get_position (GKeyFile *key_file, const gchar *group_name, const gchar *key, const WindowPosition *default_value);
 
124
static WindowPosition* str_to_position (const gchar *str, const WindowPosition *default_value);
127
125
/* Function translate user defined coordinates to absolute value */
128
126
static gint get_absolute_position (const DimensionPosition *p, gint screen, gint window);
129
127
gboolean screen_overlay_get_child_position_cb (GtkWidget *overlay, GtkWidget *widget, GdkRectangle *allocation, gpointer user_data);
263
261
/* Maybe unnecessary (in future) trick to enable accelerators for hidden/detached menu items */
264
262
static void reassign_menu_item_accel (GtkWidget *item);
265
263
 
266
 
static void init_indicators (GKeyFile* config);
 
264
static void init_indicators (void);
267
265
 
268
266
static void layout_selected_cb (GtkCheckMenuItem *menuitem, gpointer user_data);
269
267
static void update_layouts_menu (void);
283
281
void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data);
284
282
void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data);
285
283
 
286
 
/* Power indciator */
 
284
/* Power indicator */
287
285
static void power_menu_cb (GtkWidget *menuitem, gpointer userdata);
288
286
void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
289
287
void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
290
288
void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
291
289
void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
292
290
 
 
291
static void read_monitor_configuration (const gchar *group, const gchar *name);
 
292
 
 
293
struct SavedFocusData
 
294
{
 
295
    GtkWidget *widget;
 
296
    gint editable_pos;
 
297
};
 
298
 
293
299
gpointer greeter_save_focus(GtkWidget* widget);
294
300
void greeter_restore_focus(const gpointer saved_data);
295
301
 
296
 
struct SavedFocusData
 
302
 
 
303
static void
 
304
read_monitor_configuration (const gchar *group, const gchar *name)
297
305
{
298
 
    GtkWidget *widget;
299
 
    gint editable_pos;
300
 
};
 
306
    g_debug ("[Configuration] Monitor configuration found: '%s'", name);
 
307
 
 
308
    gchar *background = config_get_string (group, CONFIG_KEY_BACKGROUND, NULL);
 
309
    greeter_background_set_monitor_config (greeter_background, name, background,
 
310
                                           config_get_bool (group, CONFIG_KEY_USER_BACKGROUND, -1),
 
311
                                           config_get_bool (group, CONFIG_KEY_LAPTOP, -1),
 
312
                                           config_get_int (group, CONFIG_KEY_T_DURATION, -1),
 
313
                                           config_get_enum (group, CONFIG_KEY_T_TYPE,
 
314
                                                TRANSITION_TYPE_FALLBACK,
 
315
                                                "none",         TRANSITION_TYPE_NONE,
 
316
                                                "linear",       TRANSITION_TYPE_LINEAR,
 
317
                                                "ease-in-out",  TRANSITION_TYPE_EASE_IN_OUT, NULL));
 
318
    g_free (background);
 
319
}
301
320
 
302
321
gpointer
303
322
greeter_save_focus(GtkWidget* widget)
316
335
void
317
336
greeter_restore_focus(const gpointer saved_data)
318
337
{
319
 
    if (!saved_data)
320
 
        return;
321
 
 
322
338
    struct SavedFocusData *data = saved_data;
323
 
    if (GTK_IS_WIDGET (data->widget))
324
 
        gtk_widget_grab_focus (data->widget);
 
339
 
 
340
    if (!saved_data || !GTK_IS_WIDGET (data->widget))
 
341
        return;
 
342
 
 
343
    gtk_widget_grab_focus (data->widget);
325
344
    if (GTK_IS_EDITABLE(data->widget) && data->editable_pos > -1)
326
345
        gtk_editable_set_position(GTK_EDITABLE(data->widget), data->editable_pos);
327
346
}
328
347
 
329
 
/* State file */
330
 
 
331
348
static void
332
 
save_state_file (void)
 
349
infobar_revealed_cb_710888 (GObject *gobject, GParamSpec *pspec, gpointer user_data)
333
350
{
334
 
    GError *error = NULL;
335
 
    gsize data_length = 0;
336
 
    gchar *data = g_key_file_to_data (state, &data_length, &error);
337
 
 
338
 
    if (error)
339
 
    {
340
 
        g_warning ("Failed to save state file: %s", error->message);
341
 
        g_clear_error (&error);
342
 
    }
343
 
 
344
 
    if (data)
345
 
    {
346
 
        g_file_set_contents (state_filename, data, data_length, &error);
347
 
        if (error)
348
 
        {
349
 
            g_warning ("Failed to save state file: %s", error->message);
350
 
            g_clear_error (&error);
351
 
        }
352
 
        g_free (data);
353
 
    }
 
351
    gtk_widget_set_visible (GTK_WIDGET (info_bar), !message_label_is_empty ());
354
352
}
355
353
 
356
354
/* Terminating */
431
429
static void
432
430
sigterm_cb (gpointer user_data)
433
431
{
434
 
    g_slist_foreach (pids_to_close, (GFunc)close_pid, GINT_TO_POINTER (FALSE));
435
 
    g_slist_free (pids_to_close);
436
 
    pids_to_close = NULL;
437
 
    gtk_main_quit ();
 
432
    gboolean is_callback = GPOINTER_TO_INT (user_data);
 
433
 
 
434
    if (is_callback)
 
435
        g_debug ("SIGTERM received");
 
436
 
 
437
    if (pids_to_close)
 
438
    {
 
439
        g_slist_foreach (pids_to_close, (GFunc)close_pid, GINT_TO_POINTER (FALSE));
 
440
        g_slist_free (pids_to_close);
 
441
        pids_to_close = NULL;
 
442
    }
 
443
 
 
444
    if (is_callback)
 
445
    {
 
446
        gtk_main_quit ();
 
447
        #ifdef KILL_ON_SIGTERM
 
448
        /* LP: #1445461 */
 
449
        g_debug ("Killing greeter with exit()...");
 
450
        exit (EXIT_SUCCESS);
 
451
        #endif
 
452
    }
438
453
}
439
454
 
440
455
/* Power window */
564
579
}
565
580
 
566
581
static WindowPosition*
567
 
key_file_get_position (GKeyFile *key_file, const gchar *group_name, const gchar *key, const WindowPosition *default_value)
 
582
str_to_position (const gchar *str, const WindowPosition *default_value)
568
583
{
569
584
    WindowPosition* pos = g_new0 (WindowPosition, 1);
570
 
    gchar *value = g_key_file_get_value (key_file, group_name, key, NULL);
571
 
 
572
585
    *pos = *default_value;
573
586
 
574
 
    if (value)
 
587
    if (str)
575
588
    {
 
589
        gchar *value = g_strdup (str);
576
590
        gchar *x = value;
577
591
        gchar *y = strchr (value, ' ');
578
592
        if (y)
732
746
            }
733
747
            else
734
748
            {
735
 
                g_warning ("Failed to load user image: %s", error->message);
 
749
                g_debug ("Failed to load user image: %s", error->message);
736
750
                g_clear_error (&error);
737
751
            }
738
752
        }
849
863
                if (id != 0 && end_ptr > text)
850
864
                {
851
865
                    socket = GTK_SOCKET (gtk_socket_new ());
 
866
                    gtk_container_foreach (GTK_CONTAINER (command->widget), (GtkCallback)gtk_widget_destroy, NULL);
852
867
                    gtk_container_add (GTK_CONTAINER (command->widget), GTK_WIDGET (socket));
853
868
                    gtk_socket_add_id (socket, id);
854
869
                    gtk_widget_show_all (GTK_WIDGET (command->widget));
879
894
            g_warning ("[Command/%s] Failed to run: %s", command->name, error->message);
880
895
        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE);
881
896
    }
 
897
 
882
898
    g_clear_error (&error);
883
899
 
884
900
    return command->pid;
911
927
static void
912
928
a11y_menuitem_toggled_cb (GtkCheckMenuItem *item, const gchar* name)
913
929
{
914
 
    g_key_file_set_boolean (state, "a11y-states", name, gtk_check_menu_item_get_active (item));
915
 
    save_state_file ();
 
930
    config_set_bool (STATE_SECTION_A11Y, name, gtk_check_menu_item_get_active (item));
916
931
}
917
932
 
918
933
/* Session */
942
957
    if (!session || !is_valid_session (sessions, session))
943
958
    {
944
959
        /* previous session */
945
 
        last_session = g_key_file_get_value (state, "greeter", "last-session", NULL);
 
960
        last_session = config_get_string (STATE_SECTION_GREETER, STATE_KEY_LAST_SESSION, NULL);
946
961
        if (last_session && g_strcmp0 (session, last_session) != 0 &&
947
962
            is_valid_session (sessions, last_session))
948
963
            session = last_session;
1410
1425
}
1411
1426
 
1412
1427
static void
1413
 
init_indicators (GKeyFile* config)
 
1428
init_indicators (void)
1414
1429
{
1415
 
    gchar **names = NULL;
1416
1430
    gsize length = 0;
1417
1431
    guint i;
1418
1432
    GHashTable *builtin_items = NULL;
1421
1435
    #ifdef HAVE_LIBINDICATOR
1422
1436
    gboolean inited = FALSE;
1423
1437
    #endif
1424
 
    gboolean fallback = FALSE;
1425
1438
 
1426
1439
    const gchar *DEFAULT_LAYOUT[] = {"~host", "~spacer", "~clock", "~spacer",
1427
1440
                                     "~session", "~language", "~a11y", "~power", NULL};
1428
1441
 
1429
 
    if (g_key_file_has_key (config, "greeter", "indicators", NULL))
1430
 
    {   /* no option = default list, empty value = empty list */
1431
 
        names = g_key_file_get_string_list (config, "greeter", "indicators", &length, NULL);
1432
 
    }
1433
 
    else if (g_key_file_has_key (config, "greeter", "show-indicators", NULL))
1434
 
    {   /* fallback mode: no option = empty value = default list */
1435
 
        names = g_key_file_get_string_list (config, "greeter", "show-indicators", &length, NULL);
1436
 
        if (length == 0)
1437
 
            fallback = TRUE;
1438
 
    }
1439
 
 
1440
 
    if (!names || fallback)
1441
 
    {
 
1442
    gchar **names = config_get_string_list (NULL, CONFIG_KEY_INDICATORS, NULL);
 
1443
    if (!names)
1442
1444
        names = (gchar**)DEFAULT_LAYOUT;
1443
 
        length = g_strv_length (names);
1444
 
    }
 
1445
    length = g_strv_length (names);
1445
1446
 
1446
1447
    builtin_items = g_hash_table_new (g_str_hash, g_str_equal);
1447
1448
 
1925
1926
        pending_questions = NULL;
1926
1927
    }
1927
1928
 
1928
 
    g_key_file_set_value (state, "greeter", "last-user", username);
1929
 
    save_state_file ();
 
1929
    config_set_string (STATE_SECTION_GREETER, STATE_KEY_LAST_USER, username);
1930
1930
 
1931
1931
    if (g_strcmp0 (username, "*other") == 0)
1932
1932
    {
2018
2018
    session = get_session ();
2019
2019
 
2020
2020
    /* Remember last choice */
2021
 
    g_key_file_set_value (state, "greeter", "last-session", session);
2022
 
    save_state_file ();
 
2021
    config_set_string (STATE_SECTION_GREETER, STATE_KEY_LAST_SESSION, session);
2023
2022
 
2024
2023
    greeter_background_save_xroot (greeter_background);
2025
2024
 
2305
2304
}
2306
2305
 
2307
2306
static void
 
2307
timed_autologin_cb (LightDMGreeter *greeter)
 
2308
{
 
2309
    /* Don't trigger autologin if user locks screen with light-locker (thanks to Andrew P.). */
 
2310
    if (!lightdm_greeter_get_lock_hint (greeter))
 
2311
    {
 
2312
        if (lightdm_greeter_get_is_authenticated (greeter))
 
2313
        {
 
2314
            /* Configured autologin user may be already selected in user list. */
 
2315
            if (lightdm_greeter_get_authentication_user (greeter))
 
2316
                /* Selected user matches configured autologin-user option. */
 
2317
                start_session ();
 
2318
            else if (lightdm_greeter_get_autologin_guest_hint (greeter))
 
2319
                /* "Guest session" is selected and autologin-guest is enabled. */
 
2320
                start_session ();
 
2321
            else if (lightdm_greeter_get_autologin_user_hint (greeter))
 
2322
            {
 
2323
                /* "Guest session" is selected, but autologin-user is configured. */
 
2324
                start_authentication (lightdm_greeter_get_autologin_user_hint (greeter));
 
2325
                prompted = TRUE;
 
2326
            }
 
2327
        }
 
2328
        else
 
2329
            lightdm_greeter_authenticate_autologin (greeter);
 
2330
    }
 
2331
}
 
2332
 
 
2333
static void
2308
2334
authentication_complete_cb (LightDMGreeter *greeter)
2309
2335
{
2310
2336
    prompt_active = FALSE;
2436
2462
    const GList *items, *item;
2437
2463
    GtkTreeModel *model;
2438
2464
    GtkTreeIter iter;
2439
 
    gchar *last_user;
2440
2465
    const gchar *selected_user;
2441
2466
    gboolean logged_in = FALSE;
2442
2467
 
2474
2499
                        2, PANGO_WEIGHT_NORMAL,
2475
2500
                        -1);
2476
2501
 
2477
 
    last_user = g_key_file_get_value (state, "greeter", "last-user", NULL);
 
2502
    gchar *last_user = config_get_string (STATE_SECTION_GREETER, STATE_KEY_LAST_USER, NULL);
2478
2503
 
2479
2504
    if (lightdm_greeter_get_select_user_hint (greeter))
2480
2505
        selected_user = lightdm_greeter_get_select_user_hint (greeter);
2513
2538
            set_displayed_user (greeter, name);
2514
2539
            g_free (name);
2515
2540
        }
2516
 
 
2517
2541
    }
2518
2542
 
2519
2543
    g_free (last_user);
2520
2544
}
2521
2545
 
2522
2546
static GdkFilterReturn
2523
 
focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer  data)
 
2547
wm_window_filter (GdkXEvent *gxevent, GdkEvent *event, gpointer  data)
2524
2548
{
2525
 
    XEvent* xevent = (XEvent*)gxevent;
2526
 
    GdkWindow* keyboard_win = a11y_keyboard_command && a11y_keyboard_command->widget ?
2527
 
                                    gtk_widget_get_window (GTK_WIDGET (a11y_keyboard_command->widget)) : NULL;
 
2549
    XEvent *xevent = (XEvent*)gxevent;
2528
2550
    if (xevent->type == MapNotify)
2529
2551
    {
2530
 
        Window xwin = xevent->xmap.window;
2531
 
        Window keyboard_xid = 0;
2532
 
        GdkDisplay* display = gdk_x11_lookup_xdisplay (xevent->xmap.display);
2533
 
        GdkWindow* win = gdk_x11_window_foreign_new_for_display (display, xwin);
 
2552
        GdkDisplay *display = gdk_x11_lookup_xdisplay (xevent->xmap.display);
 
2553
        GdkWindow *win = gdk_x11_window_foreign_new_for_display (display, xevent->xmap.window);
2534
2554
        GdkWindowTypeHint win_type = gdk_window_get_type_hint (win);
2535
2555
 
2536
 
        /* Check to see if this window is our onboard window, since we don't want to focus it. */
2537
 
        if (keyboard_win)
2538
 
            keyboard_xid = gdk_x11_window_get_xid (keyboard_win);
2539
 
 
2540
 
        if (xwin != keyboard_xid
2541
 
            && win_type != GDK_WINDOW_TYPE_HINT_TOOLTIP
2542
 
            && win_type != GDK_WINDOW_TYPE_HINT_NOTIFICATION)
2543
 
        {
 
2556
        if (win_type != GDK_WINDOW_TYPE_HINT_COMBO &&
 
2557
            win_type != GDK_WINDOW_TYPE_HINT_TOOLTIP &&
 
2558
            win_type != GDK_WINDOW_TYPE_HINT_NOTIFICATION)
 
2559
        /*
 
2560
        if (win_type == GDK_WINDOW_TYPE_HINT_DESKTOP ||
 
2561
            win_type == GDK_WINDOW_TYPE_HINT_DIALOG)
 
2562
        */
2544
2563
            gdk_window_focus (win, GDK_CURRENT_TIME);
2545
 
            /* Make sure to keep keyboard above */
2546
 
            if (keyboard_win)
2547
 
                gdk_window_raise (keyboard_win);
2548
 
        }
2549
2564
    }
2550
2565
    else if (xevent->type == UnmapNotify)
2551
2566
    {
2552
2567
        Window xwin;
2553
 
        int revert_to;
 
2568
        int revert_to = RevertToNone;
 
2569
 
2554
2570
        XGetInputFocus (xevent->xunmap.display, &xwin, &revert_to);
2555
 
 
2556
2571
        if (revert_to == RevertToNone)
2557
 
        {
2558
 
            gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
2559
 
            /* Make sure to keep keyboard above */
2560
 
            if (keyboard_win)
2561
 
                gdk_window_raise (keyboard_win);
2562
 
        }
 
2572
            gdk_window_lower (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (screen_overlay))));
2563
2573
    }
 
2574
 
2564
2575
    return GDK_FILTER_CONTINUE;
2565
2576
}
2566
2577
 
2583
2594
int
2584
2595
main (int argc, char **argv)
2585
2596
{
2586
 
    GKeyFile *config;
2587
2597
    GtkBuilder *builder;
2588
2598
    const GList *items, *item;
2589
2599
    GtkWidget *image;
2590
 
    gchar *value, **values, *state_dir;
 
2600
    gchar *value;
2591
2601
    GtkIconTheme *icon_theme;
2592
2602
    GtkCssProvider *css_provider;
2593
2603
    GError *error = NULL;
2594
 
    Display *display;
2595
2604
 
2596
2605
    /* Prevent memory from being swapped out, as we are dealing with passwords */
2597
2606
    mlockall (MCL_CURRENT | MCL_FUTURE);
2598
2607
 
 
2608
    g_message ("Starting %s (%s, %s)", PACKAGE_STRING, __DATE__, __TIME__);
 
2609
 
2599
2610
    /* Disable global menus */
2600
2611
    g_unsetenv ("UBUNTU_MENUPROXY");
2601
2612
 
2611
2622
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2612
2623
    textdomain (GETTEXT_PACKAGE);
2613
2624
 
2614
 
    g_unix_signal_add (SIGTERM, (GSourceFunc)sigterm_cb, NULL);
2615
 
 
2616
 
    config = g_key_file_new ();
2617
 
    g_key_file_load_from_file (config, CONFIG_FILE, G_KEY_FILE_NONE, &error);
2618
 
    if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
2619
 
        g_warning ("Failed to load configuration from %s: %s\n", CONFIG_FILE, error->message);
2620
 
    g_clear_error (&error);
2621
 
 
2622
 
    if (g_key_file_get_boolean (config, "greeter", "allow-debugging", NULL))
 
2625
    g_unix_signal_add (SIGTERM, (GSourceFunc)sigterm_cb, /* is_callback */ GINT_TO_POINTER (TRUE));
 
2626
 
 
2627
    config_init ();
 
2628
 
 
2629
    if (config_get_bool (NULL, CONFIG_KEY_DEBUGGING, FALSE))
2623
2630
        g_log_set_default_handler (debug_log_handler, NULL);
2624
2631
 
2625
2632
    /* init gtk */
2628
2635
    /* Disabling GtkInspector shortcuts.
2629
2636
       It is still possible to run GtkInspector with GTK_DEBUG=interactive.
2630
2637
       Assume that user knows what he's doing. */
2631
 
    if (!g_key_file_get_boolean (config, "greeter", "allow-debugging", NULL))
 
2638
    if (!config_get_bool (NULL, CONFIG_KEY_DEBUGGING, FALSE))
2632
2639
    {
2633
2640
        GtkWidget *fake_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2634
2641
        GtkBindingSet *set = gtk_binding_set_by_class (G_OBJECT_GET_CLASS (fake_window));
2660
2667
    }
2661
2668
 
2662
2669
#ifdef HAVE_LIBIDO
 
2670
    g_debug ("Initializing IDO library");
2663
2671
    ido_init ();
2664
2672
#endif
2665
2673
 
2666
 
    state_dir = g_build_filename (g_get_user_cache_dir (), "lightdm-gtk-greeter", NULL);
2667
 
    g_mkdir_with_parents (state_dir, 0775);
2668
 
    state_filename = g_build_filename (state_dir, "state", NULL);
2669
 
    g_free (state_dir);
2670
 
 
2671
 
    state = g_key_file_new ();
2672
 
    g_key_file_load_from_file (state, state_filename, G_KEY_FILE_NONE, &error);
2673
 
    if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
2674
 
        g_warning ("Failed to load state from %s: %s\n", state_filename, error->message);
2675
 
    g_clear_error (&error);
2676
 
 
2677
2674
    greeter = lightdm_greeter_new ();
2678
2675
    g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);
2679
2676
    g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);
2680
2677
    g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
2681
 
    g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (lightdm_greeter_authenticate_autologin), NULL);
 
2678
    g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (timed_autologin_cb), NULL);
2682
2679
    if (!lightdm_greeter_connect_sync (greeter, NULL))
2683
2680
        return EXIT_FAILURE;
2684
2681
 
2686
2683
    gdk_window_set_cursor (gdk_get_default_root_window (), gdk_cursor_new (GDK_LEFT_PTR));
2687
2684
 
2688
2685
    /* Make the greeter behave a bit more like a screensaver if used as un/lock-screen by blanking the screen */
2689
 
    gchar* end_ptr = NULL;
2690
 
    int screensaver_timeout = 60;
2691
 
    value = g_key_file_get_value (config, "greeter", "screensaver-timeout", NULL);
2692
 
    if (value)
2693
 
        screensaver_timeout = g_ascii_strtoll (value, &end_ptr, 0);
2694
 
    g_free (value);
2695
 
 
2696
 
    display = gdk_x11_display_get_xdisplay (gdk_display_get_default ());
2697
2686
    if (lightdm_greeter_get_lock_hint (greeter))
2698
2687
    {
 
2688
        Display *display = gdk_x11_display_get_xdisplay (gdk_display_get_default ());
2699
2689
        XGetScreenSaver (display, &timeout, &interval, &prefer_blanking, &allow_exposures);
2700
2690
        XForceScreenSaver (display, ScreenSaverActive);
2701
 
        XSetScreenSaver (display, screensaver_timeout, 0, ScreenSaverActive, DefaultExposures);
 
2691
        XSetScreenSaver (display, config_get_int (NULL, CONFIG_KEY_SCREENSAVER_TIMEOUT, 60), 0,
 
2692
                         ScreenSaverActive, DefaultExposures);
2702
2693
    }
2703
2694
 
2704
2695
    /* Set GTK+ settings */
2705
 
    value = g_key_file_get_value (config, "greeter", "theme-name", NULL);
 
2696
    value = config_get_string (NULL, CONFIG_KEY_THEME, NULL);
2706
2697
    if (value)
2707
2698
    {
2708
 
        g_debug ("Using Gtk+ theme %s", value);
 
2699
        g_debug ("[Configuration] Changing GTK+ theme to '%s'", value);
2709
2700
        g_object_set (gtk_settings_get_default (), "gtk-theme-name", value, NULL);
 
2701
        g_free (value);
2710
2702
    }
2711
 
    g_free (value);
2712
2703
    g_object_get (gtk_settings_get_default (), "gtk-theme-name", &default_theme_name, NULL);
2713
 
    g_debug ("Default Gtk+ theme is '%s'", default_theme_name);
 
2704
    g_debug ("[Configuration] GTK+ theme: '%s'", default_theme_name);
2714
2705
 
2715
 
    value = g_key_file_get_value (config, "greeter", "icon-theme-name", NULL);
 
2706
    value = config_get_string (NULL, CONFIG_KEY_ICON_THEME, NULL);
2716
2707
    if (value)
2717
2708
    {
2718
 
        g_debug ("Using icon theme %s", value);
 
2709
        g_debug ("[Configuration] Changing icons theme to '%s'", value);
2719
2710
        g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", value, NULL);
 
2711
        g_free (value);
2720
2712
    }
2721
 
    g_free (value);
2722
2713
    g_object_get (gtk_settings_get_default (), "gtk-icon-theme-name", &default_icon_theme_name, NULL);
2723
 
    g_debug ("Default theme is '%s'", default_icon_theme_name);
 
2714
    g_debug ("[Configuration] Icons theme: '%s'", default_icon_theme_name);
2724
2715
 
2725
 
    value = g_key_file_get_value (config, "greeter", "font-name", NULL);
 
2716
    value = config_get_string (NULL, CONFIG_KEY_FONT, "Sans 10");
2726
2717
    if (value)
2727
2718
    {
2728
 
        g_debug ("Using font %s", value);
2729
 
        g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
2730
 
    }
2731
 
    else
2732
 
    {
2733
 
        value = g_strdup ("Sans 10");
2734
 
        g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
 
2719
        g_debug ("[Configuration] Changing font to '%s'", value);
 
2720
        g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
 
2721
        g_free (value);
2735
2722
    }
2736
2723
    g_object_get (gtk_settings_get_default (), "gtk-font-name", &default_font_name, NULL);
2737
 
    value = g_key_file_get_value (config, "greeter", "xft-dpi", NULL);
2738
 
    if (value)
2739
 
        g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", (int) (1024 * atof (value)), NULL);
2740
 
    value = g_key_file_get_value (config, "greeter", "xft-antialias", NULL);
2741
 
    if (value)
2742
 
        g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", g_strcmp0 (value, "true") == 0, NULL);
2743
 
    g_free (value);
2744
 
    value = g_key_file_get_value (config, "greeter", "xft-hintstyle", NULL);
2745
 
    if (value)
 
2724
    g_debug ("[Configuration] Font: '%s'", default_font_name);
 
2725
 
 
2726
    if (config_has_key (NULL, CONFIG_KEY_DPI))
 
2727
        g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", 1024*config_get_int (NULL, CONFIG_KEY_DPI, 96), NULL);
 
2728
 
 
2729
    if (config_has_key (NULL, CONFIG_KEY_ANTIALIAS))
 
2730
        g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", config_get_bool (NULL, CONFIG_KEY_ANTIALIAS, FALSE), NULL);
 
2731
 
 
2732
    value = config_get_string (NULL, CONFIG_KEY_HINT_STYLE, NULL);
 
2733
    if (value)
 
2734
    {
2746
2735
        g_object_set (gtk_settings_get_default (), "gtk-xft-hintstyle", value, NULL);
2747
 
    g_free (value);
2748
 
    value = g_key_file_get_value (config, "greeter", "xft-rgba", NULL);
 
2736
        g_free (value);
 
2737
    }
 
2738
 
 
2739
    value = config_get_string (NULL, CONFIG_KEY_RGBA, NULL);
2749
2740
    if (value)
 
2741
    {
2750
2742
        g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);
2751
 
    g_free (value);
 
2743
        g_free (value);
 
2744
    }
2752
2745
 
2753
2746
    #ifdef AT_SPI_COMMAND
2754
2747
    spawn_line_pid (AT_SPI_COMMAND, G_SPAWN_SEARCH_PATH, NULL);
2769
2762
 
2770
2763
    /* Screen window */
2771
2764
    screen_overlay = GTK_OVERLAY (gtk_builder_get_object (builder, "screen_overlay"));
 
2765
    screen_overlay_child = GTK_WIDGET (gtk_builder_get_object (builder, "screen_overlay_child"));
2772
2766
 
2773
2767
    /* Login window */
2774
2768
    login_window = GTK_WIDGET (gtk_builder_get_object (builder, "login_window"));
2817
2811
    gtk_accel_map_add_entry ("<Login>/a11y/reader", GDK_KEY_F4, 0);
2818
2812
    gtk_accel_map_add_entry ("<Login>/power/shutdown", GDK_KEY_F4, GDK_MOD1_MASK);
2819
2813
 
2820
 
    init_indicators (config);
 
2814
    init_indicators ();
 
2815
 
 
2816
    /* https://bugzilla.gnome.org/show_bug.cgi?id=710888
 
2817
       > GtkInfoBar not shown after calling gtk_widget_show
 
2818
       Assume they will fix it someday. */
 
2819
    if (gtk_get_major_version () == 3 && gtk_get_minor_version () < 18)
 
2820
    {
 
2821
        GList *children = gtk_container_get_children (GTK_CONTAINER (info_bar));
 
2822
        if (g_list_length (children) == 1 && GTK_IS_REVEALER (children->data))
 
2823
            g_signal_connect_after(children->data, "notify::child-revealed", (GCallback)infobar_revealed_cb_710888, NULL);
 
2824
        g_list_free (children);
 
2825
    }
2821
2826
 
2822
2827
    /* Hide empty panel */
2823
2828
    GList *menubar_items = gtk_container_get_children (GTK_CONTAINER (menubar));
2826
2831
    else
2827
2832
        g_list_free (menubar_items);
2828
2833
 
2829
 
    if (g_key_file_get_boolean (config, "greeter", "hide-user-image", NULL))
 
2834
    if (config_get_bool (NULL, CONFIG_KEY_HIDE_USER_IMAGE, FALSE))
2830
2835
    {
2831
2836
        gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "user_image_border")));
2832
2837
        gtk_widget_hide (GTK_WIDGET (user_image));  /* Hide to mark image is disabled */
2834
2839
    }
2835
2840
    else
2836
2841
    {
2837
 
        value = g_key_file_get_value (config, "greeter", "default-user-image", NULL);
 
2842
        value = config_get_string (NULL, CONFIG_KEY_DEFAULT_USER_IMAGE, NULL);
2838
2843
        if (value)
2839
2844
        {
2840
2845
            if (value[0] == '#')
2929
2934
        gtk_container_add (GTK_CONTAINER (a11y_menuitem), image);
2930
2935
    }
2931
2936
 
2932
 
    value = g_key_file_get_value (config, "greeter", "keyboard", NULL);
2933
 
    a11y_keyboard_command = menu_command_parse_extended ("keyboard", value, keyboard_menuitem, "onboard", "--xid");
2934
 
    g_free (value);
2935
 
 
 
2937
    value = config_get_string (NULL, CONFIG_KEY_KEYBOARD, NULL);
 
2938
    if (value)
 
2939
    {
 
2940
        a11y_keyboard_command = menu_command_parse_extended ("keyboard", value, keyboard_menuitem, "onboard", "--xid");
 
2941
        g_free (value);
 
2942
    }
2936
2943
    gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);
2937
2944
 
2938
 
    value = g_key_file_get_value (config, "greeter", "reader", NULL);
2939
 
    a11y_reader_command = menu_command_parse ("reader", value, reader_menuitem);
 
2945
 
 
2946
 
 
2947
    value = config_get_string (NULL, CONFIG_KEY_READER, NULL);
 
2948
    if (value)
 
2949
    {
 
2950
        a11y_reader_command = menu_command_parse ("reader", value, reader_menuitem);
 
2951
        g_free (value);
 
2952
    }
2940
2953
    gtk_widget_set_visible (reader_menuitem, a11y_reader_command != NULL);
2941
 
    g_free (value);
2942
2954
 
2943
2955
    /* Power menu */
2944
2956
    if (gtk_widget_get_visible (power_menuitem))
2997
3009
    {
2998
3010
        gtk_menu_item_set_label (GTK_MENU_ITEM (clock_menuitem), "");
2999
3011
        clock_label = gtk_bin_get_child (GTK_BIN (clock_menuitem));
3000
 
        clock_format = g_key_file_get_value (config, "greeter", "clock-format", NULL);
3001
 
        if (!clock_format)
3002
 
            clock_format = "%a, %H:%M";
 
3012
        clock_format = config_get_string (NULL, CONFIG_KEY_CLOCK_FORMAT, "%a, %H:%M");
3003
3013
        clock_timeout_thread ();
3004
3014
        gdk_threads_add_timeout (1000, (GSourceFunc) clock_timeout_thread, NULL);
3005
3015
    }
3023
3033
    /* Background */
3024
3034
    greeter_background = greeter_background_new (GTK_WIDGET (screen_overlay));
3025
3035
 
3026
 
    value = g_key_file_get_value (config, "greeter", "active-monitor", NULL);
 
3036
    value = config_get_string (NULL, CONFIG_KEY_ACTIVE_MONITOR, NULL);
3027
3037
    greeter_background_set_active_monitor_config (greeter_background, value ? value : "#cursor");
3028
3038
    g_free (value);
3029
3039
 
3030
 
    const gchar *CONFIG_MONITOR_PREFIX = "monitor:";
 
3040
    read_monitor_configuration (CONFIG_GROUP_DEFAULT, GREETER_BACKGROUND_DEFAULT);
 
3041
 
3031
3042
    gchar **config_group;
3032
 
    gchar **config_groups = g_key_file_get_groups (config, NULL);
 
3043
    gchar **config_groups = config_get_groups (CONFIG_GROUP_MONITOR);
3033
3044
    for (config_group = config_groups; *config_group; ++config_group)
3034
3045
    {
3035
 
        gchar *name_to_free = NULL;
3036
 
        const gchar *name = *config_group;
3037
 
 
3038
 
        if (g_strcmp0 (*config_group, "greeter") != 0)
3039
 
        {
3040
 
            if (!g_str_has_prefix (name, CONFIG_MONITOR_PREFIX))
3041
 
                continue;
3042
 
            name = *config_group + sizeof (CONFIG_MONITOR_PREFIX);
3043
 
            while (*name && g_ascii_isspace (*name))
3044
 
                ++name;
3045
 
        }
3046
 
        else
3047
 
            name = name_to_free = g_strdup (GREETER_BACKGROUND_DEFAULT);
3048
 
 
3049
 
        g_debug ("Monitor configuration found: '%s'", name);
3050
 
 
3051
 
        GError *user_bg_error = NULL, *laptop_error = NULL, *duration_error = NULL;
3052
 
        gboolean user_bg = g_key_file_get_boolean (config, *config_group, "user-background", &user_bg_error);
3053
 
        gboolean laptop = g_key_file_get_boolean (config, *config_group, "laptop", &laptop_error);
3054
 
        gchar *background = g_key_file_get_value (config, *config_group, "background", NULL);
3055
 
        gchar *tr_type = g_key_file_get_string (config, *config_group, "transition-type", NULL);
3056
 
        gint tr_duration = g_key_file_get_integer (config, *config_group, "transition-duration", &duration_error);
3057
 
 
3058
 
        greeter_background_set_monitor_config (greeter_background, name, background,
3059
 
                                               user_bg, user_bg_error == NULL,
3060
 
                                               laptop, laptop_error == NULL,
3061
 
                                               duration_error == NULL ? tr_duration : -1,
3062
 
                                               tr_type);
3063
 
 
3064
 
        g_free (tr_type);
3065
 
        g_free (background);
3066
 
        g_free (name_to_free);
3067
 
        g_clear_error (&user_bg_error);
3068
 
        g_clear_error (&laptop_error);
 
3046
        const gchar *name = *config_group + sizeof (CONFIG_GROUP_MONITOR);
 
3047
        while (*name && g_ascii_isspace (*name))
 
3048
            ++name;
 
3049
 
 
3050
        read_monitor_configuration (*config_group, name);
3069
3051
    }
3070
3052
    g_strfreev (config_groups);
3071
3053
 
3087
3069
    }
3088
3070
 
3089
3071
    /* Windows positions */
3090
 
    g_object_set_data_full (G_OBJECT (login_window), WINDOW_DATA_POSITION,
3091
 
                            key_file_get_position (config, "greeter", "position", &WINDOW_POS_CENTER), g_free);
3092
 
 
3093
 
    value = g_key_file_get_value (config, "greeter", "panel-position", NULL);
3094
 
    if (g_strcmp0 (value, "bottom") == 0)
3095
 
        gtk_widget_set_valign (panel_window, GTK_ALIGN_END);
 
3072
    value = config_get_string (NULL, CONFIG_KEY_POSITION, NULL);
 
3073
    g_object_set_data_full (G_OBJECT (login_window), WINDOW_DATA_POSITION, str_to_position (value, &WINDOW_POS_CENTER), g_free);
3096
3074
    g_free (value);
3097
3075
 
 
3076
 
 
3077
    gtk_widget_set_valign (panel_window, config_get_enum (NULL, CONFIG_KEY_PANEL_POSITION, GTK_ALIGN_START,
 
3078
                                                          "bottom", GTK_ALIGN_END,
 
3079
                                                          "top", GTK_ALIGN_START, NULL));
 
3080
 
3098
3081
    if (a11y_keyboard_command)
3099
 
        g_object_set_data_full (G_OBJECT (a11y_keyboard_command->widget), WINDOW_DATA_POSITION,
3100
 
                                key_file_get_position (config, "greeter", "keyboard-position", &KEYBOARD_POSITION), g_free);
 
3082
    {
 
3083
        value = config_get_string (NULL, CONFIG_KEY_KEYBOARD_POSITION, NULL);
 
3084
        g_object_set_data_full (G_OBJECT (a11y_keyboard_command->widget), WINDOW_DATA_POSITION, str_to_position (value, &KEYBOARD_POSITION), g_free);
 
3085
        g_free (value);
 
3086
    }
3101
3087
 
3102
3088
    gtk_builder_connect_signals (builder, greeter);
3103
3089
 
3104
 
    values = g_key_file_get_string_list (config, "greeter", "a11y-states", NULL, NULL);
3105
 
    if (values && *values)
 
3090
    gchar **a11y_states = config_get_string_list (NULL, CONFIG_KEY_A11Y_STATES, NULL);
 
3091
    if (a11y_states && *a11y_states)
3106
3092
    {
3107
3093
        GHashTable *items = g_hash_table_new (g_str_hash, g_str_equal);
3108
3094
        g_hash_table_insert (items, "contrast", contrast_menuitem);
3112
3098
 
3113
3099
        gpointer item;
3114
3100
        gchar **values_iter;
3115
 
        for (values_iter = values; *values_iter; ++values_iter)
 
3101
        for (values_iter = a11y_states; *values_iter; ++values_iter)
3116
3102
        {
3117
3103
            value = *values_iter;
3118
3104
            switch (value[0])
3131
3117
                    gtk_widget_get_visible (GTK_WIDGET (item)))
3132
3118
                {
3133
3119
                    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
3134
 
                                                    g_key_file_get_boolean (state, "a11y-states", value, NULL));
 
3120
                                                    config_get_bool (STATE_SECTION_A11Y, value, FALSE));
3135
3121
                    g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (a11y_menuitem_toggled_cb), g_strdup (value));
3136
3122
                }
3137
3123
            }
3138
3124
        }
3139
3125
        g_hash_table_unref (items);
3140
3126
    }
3141
 
    g_strfreev (values);
 
3127
    g_strfreev (a11y_states);
3142
3128
 
3143
 
    /* focus fix (source: unity-greeter) */
 
3129
    /* There is no window manager, so we need to implement some of its functionality */
3144
3130
    GdkWindow* root_window = gdk_get_default_root_window ();
3145
3131
    gdk_window_set_events (root_window, gdk_window_get_events (root_window) | GDK_SUBSTRUCTURE_MASK);
3146
 
    gdk_window_add_filter (root_window, focus_upon_map, NULL);
 
3132
    gdk_window_add_filter (root_window, wm_window_filter, NULL);
3147
3133
 
3148
3134
    gtk_widget_show (GTK_WIDGET (screen_overlay));
3149
3135
 
 
3136
    g_debug ("Run Gtk loop...");
3150
3137
    gtk_main ();
 
3138
    g_debug ("Gtk loop exits");
3151
3139
 
3152
 
    g_slist_foreach (pids_to_close, (GFunc)close_pid, NULL);
 
3140
    sigterm_cb (/* is_callback */ GINT_TO_POINTER (FALSE));
3153
3141
 
3154
3142
    return EXIT_SUCCESS;
3155
3143
}