2
* Copyright (C) 2010-2011 Robert Ancell.
3
* Author: Robert Ancell <robert.ancell@canonical.com>
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
22
#include <glib/gi18n.h>
23
#include <cairo-xlib.h>
26
#include <X11/Xatom.h>
27
#include <gdk-pixbuf/gdk-pixbuf.h>
30
#if GTK_CHECK_VERSION (3, 0, 0)
33
#include <gdk/gdkkeysyms.h>
35
#include <glib/gslist.h>
37
#ifdef HAVE_LIBINDICATOR
38
#include <libindicator/indicator-object.h>
39
#ifdef HAVE_LIBINDICATOR_NG
40
#include <libindicator/indicator-ng.h>
45
/* Some indicators need ido library */
46
#include "libido/libido.h"
51
#include <src/lightdm-gtk-greeter-ui.h>
53
static LightDMGreeter *greeter;
54
static GKeyFile *state;
55
static gchar *state_filename;
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;
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;
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;
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;
85
/* Pending Questions */
86
static GSList *pending_questions = NULL;
88
GSList *backgrounds = NULL;
91
static gchar *current_session;
92
static gchar *current_language;
94
/* Screensaver values */
95
int timeout, interval, prefer_blanking, allow_exposures;
97
#if GTK_CHECK_VERSION (3, 0, 0)
98
static GdkRGBA *default_background_color = NULL;
100
static GdkColor *default_background_color = NULL;
102
static gboolean cancelling = FALSE, prompted = FALSE;
103
static gboolean prompt_active = FALSE, password_prompted = FALSE;
104
#if GTK_CHECK_VERSION (3, 0, 0)
106
static GdkRegion *window_region = NULL;
113
LightDMMessageType message;
114
LightDMPromptType prompt;
117
} PAMConversationMessage;
124
/* interpret 'value' as percentage of screen width/height */
126
/* -1: left/top, 0: center, +1: right,bottom */
132
DimensionPosition x, y;
135
const WindowPosition CENTERED_WINDOW_POS = { .x = {50, +1, TRUE, 0}, .y = {50, +1, TRUE, 0} };
136
WindowPosition main_window_pos;
138
GdkPixbuf* default_user_pixbuf = NULL;
139
gchar* default_user_icon = "avatar-default";
142
pam_message_finalize (PAMConversationMessage *message)
144
g_free (message->text);
150
add_indicator_to_panel (GtkWidget *indicator_item, gint index)
153
GList* items = gtk_container_get_children (GTK_CONTAINER (menubar));
155
for (item = items; item; item = item->next)
157
if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item->data), "indicator-custom-index-data")) < index)
163
gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), GTK_WIDGET (indicator_item), insert_pos);
166
#ifdef HAVE_LIBINDICATOR
168
entry_scrolled (GtkWidget *menuitem, GdkEventScroll *event, gpointer data)
171
IndicatorObjectEntry *entry;
173
g_return_val_if_fail (GTK_IS_WIDGET (menuitem), FALSE);
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");
178
g_return_val_if_fail (INDICATOR_IS_OBJECT (io), FALSE);
180
g_signal_emit_by_name (io, "scroll", 1, event->direction);
181
g_signal_emit_by_name (io, "scroll-entry", entry, 1, event->direction);
187
entry_activated (GtkWidget *widget, gpointer user_data)
190
IndicatorObjectEntry *entry;
192
g_return_if_fail (GTK_IS_WIDGET (widget));
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");
197
g_return_if_fail (INDICATOR_IS_OBJECT (io));
199
return indicator_object_entry_activate (io, entry, gtk_get_current_event_time ());
203
create_menuitem (IndicatorObject *io, IndicatorObjectEntry *entry, GtkWidget *menubar)
205
GtkWidget *box, *menuitem;
206
gint index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (io), "indicator-custom-index-data"));
208
#if GTK_CHECK_VERSION (3, 0, 0)
209
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
211
box = gtk_hbox_new (FALSE, 0);
213
menuitem = gtk_menu_item_new ();
215
gtk_widget_add_events(GTK_WIDGET(menuitem), GDK_SCROLL_MASK);
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));
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);
226
gtk_box_pack_start (GTK_BOX(box), GTK_WIDGET(entry->image), FALSE, FALSE, 1);
229
gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(entry->label), FALSE, FALSE, 1);
232
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), GTK_WIDGET (entry->menu));
234
gtk_container_add (GTK_CONTAINER (menuitem), box);
235
gtk_widget_show (box);
236
add_indicator_to_panel (menuitem, index);
242
entry_added (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data)
244
GHashTable *menuitem_lookup;
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))
253
menuitem = create_menuitem (io, entry, GTK_WIDGET (user_data));
254
g_hash_table_insert (menuitem_lookup, entry, menuitem);
257
gtk_widget_show (menuitem);
261
entry_removed_cb (GtkWidget *widget, gpointer userdata)
264
GHashTable *menuitem_lookup;
268
io = g_object_get_data (G_OBJECT (widget), "indicator-custom-object-data");
269
if (!INDICATOR_IS_OBJECT (io))
272
entry = g_object_get_data (G_OBJECT (widget), "indicator-custom-entry-data");
273
if (entry != userdata)
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);
282
gtk_widget_destroy (widget);
286
entry_removed (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data)
288
gtk_container_foreach (GTK_CONTAINER (user_data), entry_removed_cb, entry);
292
menu_show (IndicatorObject *io, IndicatorObjectEntry *entry, guint32 timestamp, gpointer user_data)
294
IndicatorObjectEntry *entrydata;
298
menuitem = GTK_WIDGET (user_data);
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))
306
entrydata = lp->data;
307
gtk_menu_popdown (entrydata->menu);
309
g_list_free (entries);
311
/* And tell the menuitem to exit activation mode too */
312
gtk_menu_shell_cancel (GTK_MENU_SHELL (menuitem));
317
greeter_set_env (const gchar* key, const gchar* value)
319
g_setenv (key, value, TRUE);
321
GDBusProxy* proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
322
G_DBUS_PROXY_FLAGS_NONE,
324
"org.freedesktop.DBus",
325
"/org/freedesktop/DBus",
326
"org.freedesktop.DBus",
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);
340
menu_item_accel_closure_cb (GtkAccelGroup *accel_group,
341
GObject *acceleratable, guint keyval,
342
GdkModifierType modifier, gpointer data)
344
gtk_menu_item_activate (data);
348
/* Maybe unnecessary (in future) trick to enable accelerators for hidden/detached menu items */
350
reassign_menu_item_accel (GtkWidget *item)
353
const gchar *accel_path = gtk_menu_item_get_accel_path (GTK_MENU_ITEM (item));
355
if (accel_path && gtk_accel_map_lookup_entry (accel_path, &key))
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);
363
gtk_container_foreach (GTK_CONTAINER (gtk_menu_item_get_submenu (GTK_MENU_ITEM (item))),
364
(GtkCallback)reassign_menu_item_accel, NULL);
368
#ifdef START_INDICATOR_SERVICES
369
init_indicators (GKeyFile* config, GPid* indicator_pid, GPid* spi_pid)
371
init_indicators (GKeyFile* config)
374
gchar **names = NULL;
377
GHashTable *builtin_items = NULL;
380
gboolean inited = FALSE;
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};
388
if (g_key_file_has_key (config, "greeter", "show-indicators", NULL))
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);
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);
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);
403
for (i = 0; i < length; ++i)
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]);
413
#ifdef HAVE_LIBINDICATOR
415
IndicatorObject* io = NULL;
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");
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);
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);
437
if (g_path_is_absolute (names[i]))
438
{ /* library with absolute path */
439
io = indicator_object_new_from_file (names[i]);
441
else if (g_str_has_suffix (names[i], G_MODULE_SUFFIX))
443
path = g_build_filename (INDICATOR_DIR, names[i], NULL);
444
io = indicator_object_new_from_file (path);
446
#ifdef HAVE_LIBINDICATOR_NG
449
if (strchr (names[i], '.'))
450
path = g_strdup_printf ("%s/%s", UNITY_INDICATOR_DIR, names[i]);
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));
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));
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);
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);
481
g_warning ("Indicator \"%s\": failed to load", names[i]);
492
g_hash_table_iter_init (&iter, builtin_items);
493
while (g_hash_table_iter_next (&iter, NULL, &iter_value))
495
reassign_menu_item_accel (iter_value);
496
gtk_widget_hide (iter_value);
499
g_hash_table_unref (builtin_items);
506
GList *menu_items, *menu_iter;
508
/* if the user manually selected a session, use it */
510
return current_session;
512
menu_items = gtk_container_get_children(GTK_CONTAINER(session_menu));
514
for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
516
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_iter->data)))
518
return g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), "session-key"));
522
return g_strdup (lightdm_greeter_get_default_session_hint (greeter));
526
set_session (const gchar *session)
528
const gchar *default_session;
530
GList *menu_items, *menu_iter;
531
#if GTK_CHECK_VERSION (3, 0, 0)
532
GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
535
if (!gtk_widget_get_visible (session_menuitem))
537
current_session = g_strdup (session);
541
menu_items = gtk_container_get_children(GTK_CONTAINER(session_menu));
545
for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
549
s = g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), "session-key"));
550
matched = g_strcmp0 (s, session) == 0;
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);
561
gtk_image_set_from_icon_name (GTK_IMAGE(session_badge), "document-properties-symbolic", GTK_ICON_SIZE_MENU);
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)
572
set_session (last_session);
573
g_free (last_session);
576
g_free (last_session);
578
default_session = lightdm_greeter_get_default_session_hint (greeter);
579
if (default_session && g_strcmp0 (session, default_session) != 0)
581
set_session (lightdm_greeter_get_default_session_hint (greeter));
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);
593
GList *menu_items, *menu_iter;
595
/* if the user manually selected a language, use it */
596
if (current_language)
597
return current_language;
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))
602
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_iter->data)))
604
return g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), "language-code"));
612
set_language (const gchar *language)
614
const gchar *default_language = NULL;
615
GList *menu_items, *menu_iter;
617
if (!gtk_widget_get_visible (language_menuitem))
619
current_language = g_strdup (language);
623
menu_items = gtk_container_get_children(GTK_CONTAINER(language_menu));
627
for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
631
s = g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), "language-code"));
632
matched = g_strcmp0 (s, language) == 0;
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);
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);
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 */
653
for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
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")));
662
set_message_label (const gchar *text)
664
gtk_widget_set_visible (GTK_WIDGET (info_bar), g_strcmp0 (text, "") != 0);
665
gtk_label_set_text (message_label, text);
669
set_login_button_label (LightDMGreeter *greeter, const gchar *username)
672
gboolean logged_in = FALSE;
674
user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
676
logged_in = lightdm_user_get_logged_in (user);
678
gtk_button_set_label (login_button, _("Unlock"));
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);
688
static void set_background (GdkPixbuf *new_bg);
691
set_user_background (const gchar *username)
695
GdkPixbuf *bg = NULL;
696
GError *error = NULL;
698
user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
701
path = lightdm_user_get_background (user);
704
bg = gdk_pixbuf_new_from_file (path, &error);
707
g_warning ("Failed to load user background: %s", error->message);
708
g_clear_error (&error);
719
set_user_image (const gchar *username)
723
GdkPixbuf *image = NULL;
724
GError *error = NULL;
726
user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
729
path = lightdm_user_get_image (user);
732
image = gdk_pixbuf_new_from_file_at_scale (path, 80, 80, FALSE, &error);
735
gtk_image_set_from_pixbuf (GTK_IMAGE (user_image), image);
736
g_object_unref (image);
741
g_warning ("Failed to load user image: %s", error->message);
742
g_clear_error (&error);
747
if (default_user_pixbuf)
748
gtk_image_set_from_pixbuf (GTK_IMAGE (user_image), default_user_pixbuf);
750
gtk_image_set_from_icon_name (GTK_IMAGE (user_image), default_user_icon, GTK_ICON_SIZE_DIALOG);
753
/* Function translate user defined coordinates to absolute value */
755
get_absolute_position (const DimensionPosition *p, gint screen, gint window)
757
gint x = p->percentage ? (screen*p->value)/100 : p->value;
758
x = p->sign < 0 ? screen - x : x;
761
else if (p->anchor == 0)
764
if (x < 0) /* Offscreen: left/top */
766
else if (x + window > screen) /* Offscreen: right/bottom */
767
return screen - window;
773
center_window (GtkWindow *window, GtkAllocation *unused, const WindowPosition *pos)
775
GdkScreen *screen = gtk_window_get_screen (window);
776
GtkAllocation allocation;
777
GdkRectangle monitor_geometry;
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));
786
#if GTK_CHECK_VERSION (3, 0, 0)
787
/* Use the much simpler fake transparency by drawing the window background with Cairo for Gtk3 */
789
background_window_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data)
791
if (background_pixbuf)
792
gdk_cairo_set_source_pixbuf (cr, background_pixbuf, 0, 0);
794
gdk_cairo_set_source_rgba (cr, default_background_color);
800
login_window_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data)
802
GdkScreen *screen = gtk_window_get_screen (GTK_WINDOW(widget));
803
GtkAllocation *allocation = g_new0 (GtkAllocation, 1);
804
GdkRectangle monitor_geometry;
807
if (background_pixbuf)
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);
816
gdk_cairo_set_source_rgba (cr, default_background_color);
826
cairo_region_from_rectangle (gint width, gint height, gint radius)
830
gint x = radius, y = 0;
831
gint xChange = 1 - (radius << 1);
833
gint radiusError = 0;
839
rect.width = width - radius * 2;
840
rect.height = height - radius * 2;
842
region = gdk_region_rectangle (&rect);
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;
852
gdk_region_union_with_rect(region, &rect);
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;
859
gdk_region_union_with_rect(region, &rect);
862
radiusError += yChange;
864
if(((radiusError << 1) + xChange) > 0)
867
radiusError += xChange;
876
login_window_size_allocate (GtkWidget *widget, GdkRectangle *allocation, gpointer user_data)
880
GdkWindow *window = gtk_widget_get_window (widget);
882
gdk_region_destroy(window_region);
883
window_region = cairo_region_from_rectangle (allocation->width, allocation->height, radius);
885
gdk_window_shape_combine_region(window, window_region, 0, 0);
886
gdk_window_input_shape_combine_region(window, window_region, 0, 0);
893
background_window_expose (GtkWidget *widget,
894
GdkEventExpose *event,
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);
901
gdk_cairo_set_source_color (cr, default_background_color);
908
start_authentication (const gchar *username)
912
GError *error = NULL;
916
password_prompted = FALSE;
917
prompt_active = FALSE;
919
if (pending_questions)
921
g_slist_free_full (pending_questions, (GDestroyNotify) pam_message_finalize);
922
pending_questions = NULL;
925
g_key_file_set_value (state, "greeter", "last-user", username);
926
data = g_key_file_to_data (state, &data_length, &error);
928
g_warning ("Failed to save state file: %s", error->message);
929
g_clear_error (&error);
932
g_file_set_contents (state_filename, data, data_length, &error);
934
g_warning ("Failed to save state file: %s", error->message);
935
g_clear_error (&error);
939
if (g_strcmp0 (username, "*other") == 0)
941
gtk_widget_show (GTK_WIDGET (username_entry));
942
gtk_widget_show (GTK_WIDGET (cancel_button));
943
lightdm_greeter_authenticate (greeter, NULL);
945
else if (g_strcmp0 (username, "*guest") == 0)
947
lightdm_greeter_authenticate_as_guest (greeter);
953
user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
956
if (!current_session)
957
set_session (lightdm_user_get_session (user));
958
if (!current_language)
959
set_language (lightdm_user_get_language (user));
967
lightdm_greeter_authenticate (greeter, username);
972
cancel_authentication (void)
976
gboolean other = FALSE;
978
if (pending_questions)
980
g_slist_free_full (pending_questions, (GDestroyNotify) pam_message_finalize);
981
pending_questions = NULL;
984
/* If in authentication then stop that first */
986
if (lightdm_greeter_get_in_authentication (greeter))
989
lightdm_greeter_cancel_authentication (greeter);
990
set_message_label ("");
993
/* Make sure password entry is back to normal */
994
gtk_entry_set_visibility (password_entry, FALSE);
996
/* Force refreshing the prompt_box for "Other" */
997
model = gtk_combo_box_get_model (user_combo);
999
if (gtk_combo_box_get_active_iter (user_combo, &iter))
1003
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
1004
other = (g_strcmp0 (user, "*other") == 0);
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");
1012
gtk_widget_grab_focus (GTK_WIDGET (user_combo));
1016
start_session (void)
1022
GError *error = NULL;
1024
language = get_language ();
1026
lightdm_greeter_set_language (greeter, language);
1029
session = get_session ();
1031
/* Remember last choice */
1032
g_key_file_set_value (state, "greeter", "last-session", session);
1034
data = g_key_file_to_data (state, &data_length, &error);
1036
g_warning ("Failed to save state file: %s", error->message);
1037
g_clear_error (&error);
1040
g_file_set_contents (state_filename, data, data_length, &error);
1042
g_warning ("Failed to save state file: %s", error->message);
1043
g_clear_error (&error);
1047
if (!lightdm_greeter_start_session_sync (greeter, session, NULL))
1049
set_message_label (_("Failed to start session"));
1050
start_authentication (lightdm_greeter_get_authentication_user (greeter));
1056
session_selected_cb(GtkMenuItem *menuitem, gpointer user_data);
1059
session_selected_cb(GtkMenuItem *menuitem, gpointer user_data)
1061
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
1063
gchar *session = g_object_get_data (G_OBJECT (menuitem), "session-key");
1064
set_session(session);
1069
language_selected_cb(GtkMenuItem *menuitem, gpointer user_data);
1072
language_selected_cb(GtkMenuItem *menuitem, gpointer user_data)
1074
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
1076
gchar *language = g_object_get_data (G_OBJECT (menuitem), "language-code");
1077
set_language(language);
1082
power_menu_cb (GtkWidget *menuitem, gpointer userdata)
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());
1091
password_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
1094
password_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
1096
if ((event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down) &&
1097
gtk_widget_get_visible(GTK_WIDGET(user_combo)))
1101
GtkTreeModel *model = gtk_combo_box_get_model (user_combo);
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))
1107
gtk_widget_grab_focus (GTK_WIDGET (username_entry));
1111
if (!gtk_combo_box_get_active_iter (user_combo, &iter))
1114
if (event->keyval == GDK_KEY_Up)
1116
#if GTK_CHECK_VERSION (3, 0, 0)
1117
available = gtk_tree_model_iter_previous (model, &iter);
1119
GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
1120
available = gtk_tree_path_prev (path);
1122
available = gtk_tree_model_get_iter (model, &iter, path);
1123
gtk_tree_path_free (path);
1127
available = gtk_tree_model_iter_next (model, &iter);
1130
gtk_combo_box_set_active_iter (user_combo, &iter);
1138
username_focus_out_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data);
1141
username_focus_out_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
1143
if (!g_strcmp0(gtk_entry_get_text(username_entry), "") == 0)
1144
start_authentication(gtk_entry_get_text(username_entry));
1149
username_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
1152
username_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
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)
1160
gtk_widget_grab_focus(GTK_WIDGET(password_entry));
1168
menubar_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
1171
menubar_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
1173
switch (event->keyval)
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);
1188
login_window_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
1191
login_window_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
1193
GtkWidget *item = NULL;
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)
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);
1211
gtk_menu_shell_select_first (GTK_MENU_SHELL (menubar), TRUE);
1215
static void set_displayed_user (LightDMGreeter *greeter, gchar *username)
1217
gchar *user_tooltip;
1220
if (g_strcmp0 (username, "*other") == 0)
1222
gtk_widget_show (GTK_WIDGET (username_entry));
1223
gtk_widget_show (GTK_WIDGET (cancel_button));
1224
user_tooltip = g_strdup(_("Other"));
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);
1234
if (g_strcmp0 (username, "*guest") == 0)
1236
user_tooltip = g_strdup(_("Guest Account"));
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);
1244
if (lightdm_user_get_logged_in (user))
1246
set_language (lightdm_user_get_language (user));
1247
set_session (lightdm_user_get_session (user));
1249
gtk_widget_set_tooltip_text (GTK_WIDGET (user_combo), user_tooltip);
1250
start_authentication (username);
1251
g_free (user_tooltip);
1254
void user_combobox_active_changed_cb (GtkComboBox *widget, LightDMGreeter *greeter);
1257
user_combobox_active_changed_cb (GtkComboBox *widget, LightDMGreeter *greeter)
1259
GtkTreeModel *model;
1262
model = gtk_combo_box_get_model (user_combo);
1264
if (gtk_combo_box_get_active_iter (user_combo, &iter))
1268
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
1270
set_displayed_user(greeter, user);
1274
set_message_label ("");
1278
get_message_label (void)
1280
return gtk_label_get_text (message_label);
1284
process_prompts (LightDMGreeter *greeter)
1286
if (!pending_questions)
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);
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)
1302
prompt_active = TRUE;
1303
gtk_widget_grab_focus (GTK_WIDGET (username_entry));
1307
while (pending_questions)
1309
PAMConversationMessage *message = (PAMConversationMessage *) pending_questions->data;
1310
pending_questions = g_slist_remove (pending_questions, (gconstpointer) message);
1312
if (!message->is_prompt)
1314
/* FIXME: this doesn't show multiple messages, but that was
1315
* already the case before. */
1316
set_message_label (message->text);
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)
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)
1340
gtk_widget_grab_focus (GTK_WIDGET (password_entry));
1342
password_prompted = TRUE;
1343
prompt_active = TRUE;
1345
/* If we have more stuff after a prompt, assume that other prompts are pending,
1351
void login_cb (GtkWidget *widget);
1354
login_cb (GtkWidget *widget)
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);
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;
1365
if (lightdm_greeter_get_is_authenticated (greeter))
1367
else if (lightdm_greeter_get_in_authentication (greeter))
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
1373
if (pending_questions)
1374
process_prompts (greeter);
1377
start_authentication (lightdm_greeter_get_authentication_user (greeter));
1380
void cancel_cb (GtkWidget *widget);
1383
cancel_cb (GtkWidget *widget)
1385
cancel_authentication ();
1389
show_prompt_cb (LightDMGreeter *greeter, const gchar *text, LightDMPromptType type)
1391
PAMConversationMessage *message_obj = g_new (PAMConversationMessage, 1);
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);
1401
process_prompts (greeter);
1405
show_message_cb (LightDMGreeter *greeter, const gchar *text, LightDMMessageType type)
1407
PAMConversationMessage *message_obj = g_new (PAMConversationMessage, 1);
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);
1417
process_prompts (greeter);
1421
authentication_complete_cb (LightDMGreeter *greeter)
1423
prompt_active = FALSE;
1424
gtk_entry_set_text (password_entry, "");
1428
cancel_authentication ();
1432
if (pending_questions)
1434
g_slist_free_full (pending_questions, (GDestroyNotify) pam_message_finalize);
1435
pending_questions = NULL;
1438
if (lightdm_greeter_get_is_authenticated (greeter))
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));
1452
set_message_label (_("Failed to authenticate"));
1456
void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
1459
suspend_cb (GtkWidget *widget, LightDMGreeter *greeter)
1461
lightdm_suspend (NULL);
1464
void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
1467
hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter)
1469
lightdm_hibernate (NULL);
1473
show_power_prompt (const gchar* action, const gchar* message, const gchar* icon,
1474
const gchar* dialog_name, const gchar* button_name)
1480
const GList *items, *item;
1481
gint logged_in_users = 0;
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)
1488
LightDMUser *user = item->data;
1489
if (lightdm_user_get_logged_in (user))
1492
if (logged_in_users > 0)
1494
if (logged_in_users > 1)
1495
warning = g_strdup_printf (_("Warning: There are still %d users logged in."), logged_in_users);
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);
1502
/* Prepare the dialog */
1503
dialog = gtk_message_dialog_new (NULL,
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);
1515
image = gtk_image_new_from_icon_name(icon, GTK_ICON_SIZE_DIALOG);
1516
gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(dialog), image);
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");
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);
1526
g_signal_connect (G_OBJECT (dialog), "size-allocate", G_CALLBACK (login_window_size_allocate), NULL);
1528
gtk_container_set_border_width(GTK_CONTAINER (dialog), 18);
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);
1535
result = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK;
1537
gtk_widget_destroy (dialog);
1538
gtk_widget_show (GTK_WIDGET (login_window));
1543
void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
1546
restart_cb (GtkWidget *widget, LightDMGreeter *greeter)
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",
1554
"restart_dialog", "restart_button"))
1555
lightdm_restart (NULL);
1558
void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
1561
shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter)
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",
1569
"shutdown_dialog", "shutdown_button"))
1570
lightdm_shutdown (NULL);
1574
user_added_cb (LightDMUserList *user_list, LightDMUser *user, LightDMGreeter *greeter)
1576
GtkTreeModel *model;
1578
gboolean logged_in = FALSE;
1580
model = gtk_combo_box_get_model (user_combo);
1582
logged_in = lightdm_user_get_logged_in (user);
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,
1593
get_user_iter (const gchar *username, GtkTreeIter *iter)
1595
GtkTreeModel *model;
1597
model = gtk_combo_box_get_model (user_combo);
1599
if (!gtk_tree_model_get_iter_first (model, iter))
1606
gtk_tree_model_get (model, iter, 0, &name, -1);
1607
matched = g_strcmp0 (name, username) == 0;
1611
} while (gtk_tree_model_iter_next (model, iter));
1617
user_changed_cb (LightDMUserList *user_list, LightDMUser *user, LightDMGreeter *greeter)
1619
GtkTreeModel *model;
1621
gboolean logged_in = FALSE;
1623
if (!get_user_iter (lightdm_user_get_name (user), &iter))
1625
logged_in = lightdm_user_get_logged_in (user);
1627
model = gtk_combo_box_get_model (user_combo);
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,
1637
user_removed_cb (LightDMUserList *user_list, LightDMUser *user)
1639
GtkTreeModel *model;
1642
if (!get_user_iter (lightdm_user_get_name (user), &iter))
1645
model = gtk_combo_box_get_model (user_combo);
1646
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1649
void a11y_font_cb (GtkCheckMenuItem *item);
1652
a11y_font_cb (GtkCheckMenuItem *item)
1654
if (gtk_check_menu_item_get_active (item))
1656
gchar *font_name, **tokens;
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);
1664
gint size = atoi (tokens[length - 1]);
1667
g_free (tokens[length - 1]);
1668
tokens[length - 1] = g_strdup_printf ("%d", size + 10);
1670
font_name = g_strjoinv (" ", tokens);
1673
g_strfreev (tokens);
1675
g_object_set (gtk_settings_get_default (), "gtk-font-name", font_name, NULL);
1678
g_object_set (gtk_settings_get_default (), "gtk-font-name", default_font_name, NULL);
1681
void a11y_contrast_cb (GtkCheckMenuItem *item);
1684
a11y_contrast_cb (GtkCheckMenuItem *item)
1686
if (gtk_check_menu_item_get_active (item))
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);
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);
1699
keyboard_terminated_cb (GPid pid, gint status, gpointer user_data)
1701
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (keyboard_menuitem), FALSE);
1704
void a11y_keyboard_cb (GtkCheckMenuItem *item);
1707
a11y_keyboard_cb (GtkCheckMenuItem *item)
1709
if (gtk_check_menu_item_get_active (item))
1711
gboolean spawned = FALSE;
1714
GtkSocket* socket = NULL;
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))
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)
1725
gchar* end_ptr = NULL;
1727
text = g_strstrip (text);
1728
gint id = g_ascii_strtoll (text, &end_ptr, 0);
1730
if (id != 0 && end_ptr > text)
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));
1739
g_debug ("onboard keyboard command error : 'unrecognized output'");
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);
1751
g_child_watch_add (a11y_kbd_pid, keyboard_terminated_cb, NULL);
1756
if (a11y_keyboard_error)
1757
g_debug ("a11y keyboard command error : '%s'", a11y_keyboard_error->message);
1759
g_clear_error(&a11y_keyboard_error);
1760
gtk_check_menu_item_set_active (item, FALSE);
1765
if (a11y_kbd_pid != 0)
1767
kill (a11y_kbd_pid, SIGTERM);
1768
g_spawn_close_pid (a11y_kbd_pid);
1771
gtk_widget_hide (GTK_WIDGET(onboard_window));
1777
sigterm_cb (int signum)
1783
load_user_list (void)
1785
const GList *items, *item;
1786
GtkTreeModel *model;
1789
const gchar *selected_user;
1790
gboolean logged_in = FALSE;
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)
1799
LightDMUser *user = item->data;
1800
logged_in = lightdm_user_get_logged_in (user);
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,
1809
if (lightdm_greeter_get_has_guest_account_hint (greeter))
1811
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1812
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
1814
1, _("Guest Account"),
1815
2, PANGO_WEIGHT_NORMAL,
1819
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1820
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
1823
2, PANGO_WEIGHT_NORMAL,
1826
last_user = g_key_file_get_value (state, "greeter", "last-user", NULL);
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";
1833
selected_user = last_user;
1835
selected_user = NULL;
1837
if (gtk_tree_model_get_iter_first (model, &iter))
1840
gboolean matched = FALSE;
1846
gtk_tree_model_get (model, &iter, 0, &name, -1);
1847
matched = g_strcmp0 (name, selected_user) == 0;
1851
gtk_combo_box_set_active_iter (user_combo, &iter);
1852
name = g_strdup(selected_user);
1853
set_displayed_user(greeter, name);
1857
} while (gtk_tree_model_iter_next (model, &iter));
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);
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)
1879
gint number, width, height;
1882
cairo_surface_t *surface;
1884
number = gdk_screen_get_number (screen);
1885
width = gdk_screen_get_width (screen);
1886
height = gdk_screen_get_height (screen);
1888
/* Open a new connection so with Retain Permanent so the pixmap remains when the greeter quits */
1890
display = XOpenDisplay (gdk_display_get_name (gdk_screen_get_display (screen)));
1893
g_warning ("Failed to create root pixmap");
1897
XSetCloseDownMode (display, RetainPermanent);
1898
pixmap = XCreatePixmap (display, RootWindow (display, number), width, height, DefaultDepth (display, number));
1899
XCloseDisplay (display);
1901
/* Convert into a Cairo surface */
1902
surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen),
1904
GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen)),
1910
/* Sets the "ESETROOT_PMAP_ID" property to later be used to free the pixmap,
1913
set_root_pixmap_id (GdkScreen *screen,
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};
1923
unsigned long nitems, after;
1924
unsigned char *data_root, *data_esetroot;
1926
/* Get atoms for both properties in an array, only if they exist.
1927
* This method is to avoid multiple round-trips to Xserver
1929
if (XInternAtoms (display, atom_names, G_N_ELEMENTS(atom_names), True, atoms) &&
1930
atoms[0] != None && atoms[1] != None)
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)
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)
1941
Pixmap xrootpmap = *((Pixmap *) data_root);
1942
Pixmap esetrootpmap = *((Pixmap *) data_esetroot);
1944
XFree (data_esetroot);
1946
gdk_error_trap_push ();
1947
if (xrootpmap && xrootpmap == esetrootpmap) {
1948
XKillClient (display, xrootpmap);
1950
if (esetrootpmap && esetrootpmap != xrootpmap) {
1951
XKillClient (display, esetrootpmap);
1954
XSync (display, False);
1955
#if GTK_CHECK_VERSION (3, 0, 0)
1956
gdk_error_trap_pop_ignored ();
1958
gdk_error_trap_pop ();
1965
/* Get atoms for both properties in an array, create them if needed.
1966
* This method is to avoid multiple round-trips to Xserver
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");
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);
1978
XChangeProperty (display, xroot, atoms[1], XA_PIXMAP, 32,
1979
PropModeReplace, (unsigned char *) &xpixmap, 1);
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.
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().
1996
set_surface_as_root (GdkScreen *screen, cairo_surface_t *surface)
1998
g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB);
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
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));
2007
XGrabServer (display);
2009
XSetWindowBackgroundPixmap (display, xroot, pixmap_id);
2010
set_root_pixmap_id (screen, display, pixmap_id);
2011
XClearWindow (display, xroot);
2014
XUngrabServer (display);
2018
set_background (GdkPixbuf *new_bg)
2020
GdkRectangle monitor_geometry;
2021
GdkPixbuf *bg = NULL;
2023
gint i, p_height, p_width, height, width;
2025
gint numScreens = 1;
2030
bg = default_background_pixbuf;
2032
#if GDK_VERSION_CUR_STABLE < G_ENCODE_VERSION(3, 10)
2033
numScreens = gdk_display_get_n_screens (gdk_display_get_default());
2036
/* Set the background */
2037
for (i = 0; i < numScreens; i++)
2040
cairo_surface_t *surface;
2044
screen = gdk_display_get_screen (gdk_display_get_default (), i);
2045
surface = create_root_surface (screen);
2046
c = cairo_create (surface);
2048
for (monitor = 0; monitor < gdk_screen_get_n_monitors (screen); monitor++)
2050
gdk_screen_get_monitor_geometry (screen, monitor, &monitor_geometry);
2054
p_width = gdk_pixbuf_get_width(bg);
2055
p_height = gdk_pixbuf_get_height(bg);
2057
scale = (double)monitor_geometry.width/p_width;
2058
height = p_height * scale;
2059
width = monitor_geometry.width;
2061
if (height < monitor_geometry.height)
2063
scale = (double)monitor_geometry.height/p_height;
2064
height = monitor_geometry.height;
2065
width = p_width * scale;
2068
GdkPixbuf *p = gdk_pixbuf_scale_simple (bg, width,
2069
height, GDK_INTERP_BILINEAR);
2070
if (width > monitor_geometry.width)
2072
GdkPixbuf *tmp = gdk_pixbuf_new_subpixbuf(p, (width-monitor_geometry.width)/2, 0, monitor_geometry.width, monitor_geometry.height);
2076
if (!gdk_pixbuf_get_has_alpha (p))
2078
GdkPixbuf *tmp = gdk_pixbuf_add_alpha (p, FALSE, 255, 255, 255);
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;
2089
#if GTK_CHECK_VERSION (3, 0, 0)
2090
gdk_cairo_set_source_rgba (c, default_background_color);
2092
gdk_cairo_set_source_color (c, default_background_color);
2094
background_pixbuf = NULL;
2097
iter = g_slist_nth(backgrounds, monitor);
2098
gtk_widget_queue_draw(GTK_WIDGET(iter->data));
2103
/* Refresh background */
2105
set_surface_as_root(screen, surface);
2106
cairo_surface_destroy(surface);
2108
gtk_widget_queue_draw(GTK_WIDGET(login_window));
2109
gtk_widget_queue_draw(GTK_WIDGET(panel_window));
2113
clock_timeout_thread (void)
2116
struct tm * timeinfo;
2121
timeinfo = localtime ( &rawtime );
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 );
2132
read_position_from_str (const gchar *s, DimensionPosition *x)
2134
DimensionPosition p;
2136
gchar **parts = g_strsplit(s, ",", 2);
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;
2144
if (g_strcmp0(parts[1], "start") == 0)
2146
else if (g_strcmp0(parts[1], "center") == 0)
2148
else if (g_strcmp0(parts[1], "end") == 0)
2151
p.anchor = p.sign > 0 ? -1 : +1;
2160
static GdkFilterReturn
2161
focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
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)
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);
2172
/* Check to see if this window is our onboard window, since we don't want to focus it. */
2174
#if GTK_CHECK_VERSION (3, 0, 0)
2175
keyboard_xid = gdk_x11_window_get_xid (keyboard_win);
2177
keyboard_xid = gdk_x11_drawable_get_xid (keyboard_win);
2180
if (xwin != keyboard_xid && gdk_window_get_type_hint (win) != GDK_WINDOW_TYPE_HINT_NOTIFICATION)
2182
gdk_window_focus (win, GDK_CURRENT_TIME);
2183
/* Make sure to keep keyboard above */
2187
gdk_window_raise (keyboard_win);
2191
else if (xevent->type == UnmapNotify)
2195
XGetInputFocus (xevent->xunmap.display, &xwin, &revert_to);
2197
if (revert_to == RevertToNone)
2199
gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
2200
/* Make sure to keep keyboard above */
2204
gdk_window_raise (keyboard_win);
2208
return GDK_FILTER_CONTINUE;
2212
main (int argc, char **argv)
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;
2226
GdkColor background_color;
2228
GError *error = NULL;
2230
/* Background windows */
2232
gint numScreens = 1;
2238
#ifdef START_INDICATOR_SERVICES
2239
GPid indicator_pid = 0, spi_pid = 0;
2242
/* Disable global menus */
2243
g_unsetenv ("UBUNTU_MENUPROXY");
2245
/* Initialize i18n */
2246
setlocale (LC_ALL, "");
2247
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
2248
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2249
textdomain (GETTEXT_PACKAGE);
2251
signal (SIGTERM, sigterm_cb);
2253
#if GTK_CHECK_VERSION (3, 0, 0)
2260
gtk_init (&argc, &argv);
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);
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);
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);
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;
2291
/* Set default cursor */
2292
gdk_window_set_cursor (gdk_get_default_root_window (), gdk_cursor_new (GDK_LEFT_PTR));
2294
/* Load background */
2295
value = g_key_file_get_value (config, "greeter", "background", NULL);
2297
value = g_strdup ("#000000");
2298
#if GTK_CHECK_VERSION (3, 0, 0)
2299
if (!gdk_rgba_parse (&background_color, value))
2301
if (!gdk_color_parse (value, &background_color))
2305
GError *error = NULL;
2307
if (g_path_is_absolute (value))
2308
path = g_strdup (value);
2310
path = g_build_filename (GREETER_DATA_DIR, value, NULL);
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);
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);
2325
default_background_color = gdk_color_copy (&background_color);
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);
2335
screensaver_timeout = g_ascii_strtoll (value, &end_ptr, 0);
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);
2345
/* Set GTK+ settings */
2346
value = g_key_file_get_value (config, "greeter", "theme-name", NULL);
2349
g_debug ("Using Gtk+ theme %s", value);
2350
g_object_set (gtk_settings_get_default (), "gtk-theme-name", value, NULL);
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);
2356
value = g_key_file_get_value (config, "greeter", "icon-theme-name", NULL);
2359
g_debug ("Using icon theme %s", value);
2360
g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", value, NULL);
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);
2366
value = g_key_file_get_value (config, "greeter", "font-name", NULL);
2369
g_debug ("Using font %s", value);
2370
g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
2374
value = g_strdup("Sans 10");
2375
g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
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);
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);
2383
g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", g_strcmp0 (value, "true") == 0, NULL);
2385
value = g_key_file_get_value (config, "greeter", "xft-hintstyle", NULL);
2387
g_object_set (gtk_settings_get_default (), "gtk-xft-hintstyle", value, NULL);
2389
value = g_key_file_get_value (config, "greeter", "xft-rgba", NULL);
2391
g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);
2394
/* Get a11y on screen keyboard command*/
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);
2403
builder = gtk_builder_new ();
2404
if (!gtk_builder_add_from_string (builder, lightdm_gtk_greeter_ui,
2405
lightdm_gtk_greeter_ui_length, &error))
2407
g_warning ("Error loading UI: %s", error->message);
2408
return EXIT_FAILURE;
2410
g_clear_error (&error);
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);
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);
2431
keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
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"));
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);
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);
2453
gtk_container_add(GTK_CONTAINER(infobar_compat), GTK_WIDGET(info_bar));
2455
cancel_button = GTK_BUTTON (gtk_builder_get_object (builder, "cancel_button"));
2456
login_button = GTK_BUTTON (gtk_builder_get_object (builder, "login_button"));
2458
#if GTK_CHECK_VERSION (3, 0, 0)
2459
g_signal_connect (G_OBJECT (login_window), "draw", G_CALLBACK (login_window_draw), NULL);
2461
g_signal_connect (G_OBJECT (login_window), "size-allocate", G_CALLBACK (login_window_size_allocate), NULL);
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();
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"));
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"));
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);
2493
#ifdef START_INDICATOR_SERVICES
2494
init_indicators (config, &indicator_pid, &spi_pid);
2496
init_indicators (config);
2499
value = g_key_file_get_value (config, "greeter", "default-user-image", NULL);
2502
if (value[0] == '#')
2503
default_user_icon = g_strdup (value + 1);
2506
default_user_pixbuf = gdk_pixbuf_new_from_file (value, &error);
2507
if (!default_user_pixbuf)
2509
g_warning ("Failed to load default user image: %s", error->message);
2510
g_clear_error (&error);
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);
2521
clock_format = "%a, %H:%M";
2524
if (gtk_widget_get_visible (session_menuitem))
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);
2530
session_badge = gtk_image_new_from_icon_name ("document-properties", GTK_ICON_SIZE_MENU);
2532
session_badge = gtk_image_new_from_icon_name ("document-properties", GTK_ICON_SIZE_MENU);
2534
gtk_widget_show (session_badge);
2535
gtk_container_add (GTK_CONTAINER (session_menuitem), session_badge);
2537
items = lightdm_get_sessions ();
2538
GSList *sessions = NULL;
2539
for (item = items; item; item = item->next)
2541
LightDMSession *session = item->data;
2542
GtkWidget *radiomenuitem;
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));
2555
if (gtk_widget_get_visible (language_menuitem))
2557
items = lightdm_get_languages ();
2558
GSList *languages = NULL;
2559
for (item = items; item; item = item->next)
2561
LightDMLanguage *language = item->data;
2562
const gchar *country, *code;
2564
GtkWidget *radiomenuitem;
2566
country = lightdm_language_get_territory (language);
2568
label = g_strdup_printf ("%s - %s", lightdm_language_get_name (language), country);
2570
label = g_strdup (lightdm_language_get_name (language));
2572
code = lightdm_language_get_code (language);
2573
gchar *modifier = strchr (code, '@');
2574
if (modifier != NULL)
2576
gchar *label_new = g_strdup_printf ("%s [%s]", label, modifier+1);
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));
2588
set_language (NULL);
2592
if (gtk_widget_get_visible (a11y_menuitem))
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);
2598
image = gtk_image_new_from_icon_name ("preferences-desktop-accessibility", GTK_ICON_SIZE_MENU);
2600
image = gtk_image_new_from_icon_name ("preferences-desktop-accessibility", GTK_ICON_SIZE_MENU);
2602
gtk_widget_show (image);
2603
gtk_container_add (GTK_CONTAINER (a11y_menuitem), image);
2607
if (gtk_widget_get_visible (power_menuitem))
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);
2613
image = gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_MENU);
2615
image = gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_MENU);
2617
gtk_widget_show (image);
2618
gtk_container_add (GTK_CONTAINER (power_menuitem), image);
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")));
2625
g_signal_connect (G_OBJECT (power_menuitem),"activate", G_CALLBACK(power_menu_cb), NULL);
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);
2634
#if GDK_VERSION_CUR_STABLE < G_ENCODE_VERSION(3, 10)
2635
numScreens = gdk_display_get_n_screens (gdk_display_get_default());
2638
/* Set up the background images */
2639
for (scr = 0; scr < numScreens; scr++)
2641
screen = gdk_display_get_screen (gdk_display_get_default (), scr);
2642
for (monitor = 0; monitor < gdk_screen_get_n_monitors (screen); monitor++)
2644
gdk_screen_get_monitor_geometry (screen, monitor, &monitor_geometry);
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);
2651
gtk_widget_modify_bg(GTK_WIDGET(window), GTK_STATE_NORMAL, &background_color);
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);
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);
2665
g_signal_connect (G_OBJECT (window), "expose-event", G_CALLBACK (background_window_expose), NULL);
2667
gtk_widget_queue_draw (GTK_WIDGET(window));
2670
backgrounds = g_slist_reverse(backgrounds);
2672
if (lightdm_greeter_get_hide_users_hint (greeter))
2674
/* Set the background to default */
2675
set_background (NULL);
2676
start_authentication ("*other");
2680
/* This also sets the background to user's */
2682
gtk_widget_hide (GTK_WIDGET (cancel_button));
2683
gtk_widget_show (GTK_WIDGET (user_combo));
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);
2693
gchar *y = strchr(value, ' ');
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;
2705
gtk_builder_connect_signals(builder, greeter);
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);
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);
2718
gtk_widget_show (GTK_WIDGET (login_window));
2719
gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
2721
if (a11y_keyboard_command)
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)
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);
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);
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);
2744
#if GTK_CHECK_VERSION (3, 0, 0)
2746
gdk_threads_enter();
2749
#if GTK_CHECK_VERSION (3, 0, 0)
2751
gdk_threads_leave();
2754
#ifdef START_INDICATOR_SERVICES
2757
kill (indicator_pid, SIGTERM);
2758
waitpid (indicator_pid, NULL, 0);
2763
kill (spi_pid, SIGTERM);
2764
waitpid (spi_pid, NULL, 0);
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);
2776
gdk_color_free (default_background_color);
2779
return EXIT_SUCCESS;