Merge lp:~kalgasnik/lightdm-gtk-greeter/post-2.0.0 into lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/trunk

Proposed by Andrew P.
Status: Merged
Merged at revision: 326
Proposed branch: lp:~kalgasnik/lightdm-gtk-greeter/post-2.0.0
Merge into: lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/trunk
Diff against target: 1539 lines (+685/-278)
8 files modified
src/Makefile.am (+2/-0)
src/greeterbackground.c (+75/-39)
src/greeterbackground.h (+16/-3)
src/greeterconfiguration.c (+371/-0)
src/greeterconfiguration.h (+57/-0)
src/lightdm-gtk-greeter-fallback.css (+5/-5)
src/lightdm-gtk-greeter.c (+154/-229)
src/lightdm-gtk-greeter.glade (+5/-2)
To merge this branch: bzr merge lp:~kalgasnik/lightdm-gtk-greeter/post-2.0.0
Reviewer Review Type Date Requested Status
Sean Davis Approve
Andrew P. Pending
Review via email: mp+251694@code.launchpad.net

Description of the change

1. Greeter can go to infinite loop at launch when used with two monitors in mirrored mode and active-monitor=#cursor

http://ubuntuforums.org/showthread.php?t=2268061
http://forum.ubuntuusers.de/topic/loginbildschirm-weis-erst-nach-rechtsklick-sic/
http://ubuntuforums.org/showthread.php?t=2267474
https://bugs.archlinux.org/task/43999

2. gtk_widget_reparent marked as deprecated in 3.14 but gtk_container_remove/add is not equal replacement if widget contains GtkPlug.
gtk_widget_reparent used in greeter to move screen_overlay from on monitor window to another.
Looks like remove/add leaves GtkPlug in invalid state.

http://i.imgur.com/E7BtTRx.png
http://i.imgur.com/dlvjay5.png

3. Sending "WM_TAKE_FOCUS" to active monitor window, "onboard" just doesn't work in xembed mode without it.

4. Greeter doesn't lose focus when monitors configuration changed.

5. Multiple configuration files. Order:
g_get_system_data_dirs():
.../lightdm/lightdm-gtk-greeter.conf.d/*.conf
.../lightdm/lightdm-gtk-greeter.conf
g_get_system_config_dirs():
.../lightdm/lightdm-gtk-greeter.conf.d/*.conf
.../lightdm/lightdm-gtk-greeter.conf
/etc/lightdm/lightdm-gtk-greeter.conf.d/*.conf
/etc/lightdm/lightdm-gtk-greeter.conf

Sample:
/usr/share/lightdm/lightdm-gtk-greeter.conf.d/a.conf
/etc/xdg/lightdm/lightdm-gtk-greeter.conf.d/1.conf
/etc/xdg/lightdm/lightdm-gtk-greeter.conf.d/2.conf
/etc/xdg/lightdm/lightdm-gtk-greeter.conf
/etc/lightdm/lightdm-gtk-greeter.conf.d/arch.conf
/etc/lightdm/lightdm-gtk-greeter.conf

To post a comment you must log in.
325. By Andrew P.

conf.d support (LP: #1421587)

Revision history for this message
Simon Steinbeiß (ochosi) wrote :

Hey Andrew!
This is a huge amount of changes so I guess the branch-name is accurate :)
I wonder whether we could rip out some parts of it as bugfix for 2.0 and then do a bugfix release for it which we could then still upload to 15.04. Would that be possible?

Revision history for this message
Sean Davis (bluesabre) wrote :

Simon,

Actually, other than the configuration location (not really a "feature"), I'd say these are all bug fixes.

#1 is a critical bug that can leave the greeter completely non-functional.
#2 and #3 break accessibility by making the on-screen keyboard unusable.
#4 means that keyboard input would be lost without using a mouse.

I haven't tested the branch yet, but these all sound reasonable to me. I'll test it out this weekend.

326. By Andrew P.

Fallback if no .conf files found

Revision history for this message
Sean Davis (bluesabre) wrote :

I just tested this branch with a second monitor. It seems the white screen bug is still present.

Revision history for this message
Andrew P. (kalgasnik) wrote :

Log with allow-debugging=true?
Is it white "need to click or use active-monitor=0" screen?

Revision history for this message
Sean Davis (bluesabre) wrote :

I think I had some other components interfering. This time I built a proper package and installed it over a clean system, and everything seems to be okay. Going to merge this one in.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2014-11-04 11:38:36 +0000
+++ src/Makefile.am 2015-03-29 05:44:39 +0000
@@ -10,6 +10,8 @@
10 lightdm-gtk-greeter.c \10 lightdm-gtk-greeter.c \
11 greeterbackground.c \11 greeterbackground.c \
12 greeterbackground.h \12 greeterbackground.h \
13 greeterconfiguration.c \
14 greeterconfiguration.h \
13 greetermenubar.c \15 greetermenubar.c \
14 greetermenubar.h16 greetermenubar.h
1517
1618
=== modified file 'src/greeterbackground.c'
--- src/greeterbackground.c 2014-12-10 07:59:02 +0000
+++ src/greeterbackground.c 2015-03-29 05:44:39 +0000
@@ -58,7 +58,7 @@
58} BackgroundConfig;58} BackgroundConfig;
5959
60/* Transition configuration60/* Transition configuration
61 Used to as part of <MonitorConfig> and <Monitor> */61 Used as part of <MonitorConfig> and <Monitor> */
62typedef struct62typedef struct
63{63{
64 /* Transition duration, in ms */64 /* Transition duration, in ms */
@@ -177,9 +177,6 @@
177 gboolean follow_cursor;177 gboolean follow_cursor;
178 /* Use cursor position to determinate initial active monitor */178 /* Use cursor position to determinate initial active monitor */
179 gboolean follow_cursor_to_init;179 gboolean follow_cursor_to_init;
180
181 /* Name => transition function, inited in set_monitor_config() */
182 GHashTable* transition_types;
183};180};
184181
185enum182enum
@@ -205,10 +202,10 @@
205void greeter_background_set_monitor_config (GreeterBackground* background,202void greeter_background_set_monitor_config (GreeterBackground* background,
206 const gchar* name,203 const gchar* name,
207 const gchar* bg, /* NULL to use fallback value */204 const gchar* bg, /* NULL to use fallback value */
208 gboolean user_bg, gboolean user_bg_used,205 gint user_bg, /* -1 to use fallback value */
209 gboolean laptop, gboolean laptop_used,206 gint laptop, /* -1 to use fallback value */
210 gint transition_duration, /* -1 to use fallback value */207 gint transition_duration, /* -1 to use fallback value */
211 const gchar* transition_type); /* NULL to use fallback value */208 TransitionType transition_type); /* NULL to use fallback value */
212void greeter_background_remove_monitor_config (GreeterBackground* background,209void greeter_background_remove_monitor_config (GreeterBackground* background,
213 const gchar* name);210 const gchar* name);
214gchar** greeter_background_get_configured_monitors (GreeterBackground* background);211gchar** greeter_background_get_configured_monitors (GreeterBackground* background);
@@ -296,7 +293,7 @@
296static void set_surface_as_root (GdkScreen* screen,293static void set_surface_as_root (GdkScreen* screen,
297 cairo_surface_t* surface);294 cairo_surface_t* surface);
298static gdouble transition_func_linear (gdouble x);295static gdouble transition_func_linear (gdouble x);
299static gdouble transition_func_easy_in_out (gdouble x);296static gdouble transition_func_ease_in_out (gdouble x);
300297
301/* Implemented in lightdm-gtk-greeter.c */298/* Implemented in lightdm-gtk-greeter.c */
302gpointer greeter_save_focus(GtkWidget* widget);299gpointer greeter_save_focus(GtkWidget* widget);
@@ -317,7 +314,7 @@
317 .transition =314 .transition =
318 {315 {
319 .duration = 500,316 .duration = 500,
320 .func = transition_func_easy_in_out,317 .func = transition_func_ease_in_out,
321 .draw = (TransitionDraw)monitor_transition_draw_alpha318 .draw = (TransitionDraw)monitor_transition_draw_alpha
322 }319 }
323};320};
@@ -413,10 +410,10 @@
413greeter_background_set_monitor_config(GreeterBackground* background,410greeter_background_set_monitor_config(GreeterBackground* background,
414 const gchar* name,411 const gchar* name,
415 const gchar* bg,412 const gchar* bg,
416 gboolean user_bg, gboolean user_bg_used,413 gint user_bg,
417 gboolean laptop, gboolean laptop_used,414 gint laptop,
418 gint transition_duration,415 gint transition_duration,
419 const gchar* transition_type)416 TransitionType transition_type)
420{417{
421 g_return_if_fail(GREETER_IS_BACKGROUND(background));418 g_return_if_fail(GREETER_IS_BACKGROUND(background));
422 GreeterBackgroundPrivate* priv = background->priv;419 GreeterBackgroundPrivate* priv = background->priv;
@@ -427,29 +424,22 @@
427424
428 if(!background_config_initialize(&config->bg, bg))425 if(!background_config_initialize(&config->bg, bg))
429 background_config_copy(&FALLBACK->bg, &config->bg);426 background_config_copy(&FALLBACK->bg, &config->bg);
430 config->user_bg = user_bg_used ? user_bg : FALLBACK->user_bg;427 config->user_bg = user_bg >= 0 ? user_bg : FALLBACK->user_bg;
431 config->laptop = laptop_used ? laptop : FALLBACK->laptop;428 config->laptop = laptop >= 0 ? laptop : FALLBACK->laptop;
432 config->transition.duration = transition_duration >= 0 ? transition_duration : FALLBACK->transition.duration;429 config->transition.duration = transition_duration >= 0 ? transition_duration : FALLBACK->transition.duration;
433 config->transition.draw = FALLBACK->transition.draw;430 config->transition.draw = FALLBACK->transition.draw;
434431
435 if(transition_type)432 switch(transition_type)
436 {433 {
437 if(!priv->transition_types)434 case TRANSITION_TYPE_NONE:
438 {435 config->transition.func = NULL; break;
439 priv->transition_types = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);436 case TRANSITION_TYPE_LINEAR:
440 g_hash_table_insert(priv->transition_types, g_strdup("none"), NULL);437 config->transition.func = transition_func_linear; break;
441 g_hash_table_insert(priv->transition_types, g_strdup("linear"), transition_func_linear);438 case TRANSITION_TYPE_EASE_IN_OUT:
442 g_hash_table_insert(priv->transition_types, g_strdup("easy-in-out"), transition_func_easy_in_out);439 config->transition.func = transition_func_ease_in_out; break;
443 }440 default:
444 if(!g_hash_table_lookup_extended(priv->transition_types, transition_type, NULL, (gpointer*)&config->transition.func))
445 {
446 g_warning("[Background] Invalid transition type for '%s' monitor: '%s'. Using fallback value.",
447 name, transition_type);
448 config->transition.func = FALLBACK->transition.func;441 config->transition.func = FALLBACK->transition.func;
449 }
450 }442 }
451 else
452 config->transition.func = FALLBACK->transition.func;
453443
454 if(FALLBACK == priv->default_config)444 if(FALLBACK == priv->default_config)
455 g_hash_table_insert(priv->configs, g_strdup(name), config);445 g_hash_table_insert(priv->configs, g_strdup(name), config);
@@ -495,12 +485,18 @@
495 g_return_if_fail(GREETER_IS_BACKGROUND(background));485 g_return_if_fail(GREETER_IS_BACKGROUND(background));
496 g_return_if_fail(GDK_IS_SCREEN(screen));486 g_return_if_fail(GDK_IS_SCREEN(screen));
497487
498 g_debug("[Background] Connecting to screen: %p", screen);488 g_debug("[Background] Connecting to screen: %p (%dx%dpx, %dx%dmm)", screen,
489 gdk_screen_get_width(screen), gdk_screen_get_height(screen),
490 gdk_screen_get_width_mm(screen), gdk_screen_get_height_mm(screen));
499491
500 GreeterBackgroundPrivate* priv = background->priv;492 GreeterBackgroundPrivate* priv = background->priv;
501493 gpointer saved_focus = NULL;
502 if(priv->screen)494 if(priv->screen)
495 {
496 if (priv->active_monitor)
497 saved_focus = greeter_save_focus(priv->child);
503 greeter_background_disconnect(background);498 greeter_background_disconnect(background);
499 }
504500
505 priv->screen = screen;501 priv->screen = screen;
506 priv->monitors_size = gdk_screen_get_n_monitors(screen);502 priv->monitors_size = gdk_screen_get_n_monitors(screen);
@@ -513,7 +509,9 @@
513 Monitor* first_not_skipped_monitor = NULL;509 Monitor* first_not_skipped_monitor = NULL;
514510
515 GHashTable* images_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);511 GHashTable* images_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
512 cairo_region_t *screen_region = cairo_region_create();
516 gint i;513 gint i;
514
517 for(i = 0; i < priv->monitors_size; ++i)515 for(i = 0; i < priv->monitors_size; ++i)
518 {516 {
519 const MonitorConfig* config;517 const MonitorConfig* config;
@@ -553,6 +551,15 @@
553 config = &DEFAULT_MONITOR_CONFIG;551 config = &DEFAULT_MONITOR_CONFIG;
554 }552 }
555553
554 /* Simple check to skip fully overlapped monitors.
555 Actually, it's can track only monitors in "mirrors" mode. Nothing more. */
556 if(cairo_region_contains_rectangle(screen_region, &monitor->geometry) == CAIRO_REGION_OVERLAP_IN)
557 {
558 g_debug("[Background] Skipping monitor %s #%d, its area is already used by other monitors", printable_name, i);
559 continue;
560 }
561 cairo_region_union_rectangle(screen_region, &monitor->geometry);
562
556 if(!first_not_skipped_monitor)563 if(!first_not_skipped_monitor)
557 first_not_skipped_monitor = monitor;564 first_not_skipped_monitor = monitor;
558565
@@ -578,9 +585,8 @@
578 for(item = priv->accel_groups; item != NULL; item = g_slist_next(item))585 for(item = priv->accel_groups; item != NULL; item = g_slist_next(item))
579 gtk_window_add_accel_group(monitor->window, item->data);586 gtk_window_add_accel_group(monitor->window, item->data);
580587
581 if(priv->follow_cursor)588 g_signal_connect(G_OBJECT(monitor->window), "enter-notify-event",
582 g_signal_connect(G_OBJECT(monitor->window), "enter-notify-event",589 G_CALLBACK(monitor_window_enter_notify_cb), monitor);
583 G_CALLBACK(monitor_window_enter_notify_cb), monitor);
584590
585 if(config->user_bg)591 if(config->user_bg)
586 priv->customized_monitors = g_slist_prepend(priv->customized_monitors, monitor);592 priv->customized_monitors = g_slist_prepend(priv->customized_monitors, monitor);
@@ -624,9 +630,16 @@
624 }630 }
625 }631 }
626 }632 }
633
627 if(!priv->active_monitor)634 if(!priv->active_monitor)
628 greeter_background_set_active_monitor(background, NULL);635 greeter_background_set_active_monitor(background, NULL);
629636
637 if(saved_focus)
638 {
639 greeter_restore_focus(saved_focus);
640 g_free(saved_focus);
641 }
642
630 priv->screen_monitors_changed_handler_id = g_signal_connect(G_OBJECT(screen), "monitors-changed",643 priv->screen_monitors_changed_handler_id = g_signal_connect(G_OBJECT(screen), "monitors-changed",
631 G_CALLBACK(greeter_background_monitors_changed_cb),644 G_CALLBACK(greeter_background_monitors_changed_cb),
632 background);645 background);
@@ -768,8 +781,9 @@
768 gpointer focus = greeter_save_focus(priv->child);781 gpointer focus = greeter_save_focus(priv->child);
769782
770 if(old_parent)783 if(old_parent)
771 gtk_container_remove(GTK_CONTAINER(old_parent), priv->child);784 gtk_widget_reparent(priv->child, GTK_WIDGET(active->window));
772 gtk_container_add(GTK_CONTAINER(active->window), priv->child);785 else
786 gtk_container_add(GTK_CONTAINER(active->window), priv->child);
773787
774 gtk_window_present(active->window);788 gtk_window_present(active->window);
775 greeter_restore_focus(focus);789 greeter_restore_focus(focus);
@@ -1393,8 +1407,30 @@
1393 GdkEventCrossing* event,1407 GdkEventCrossing* event,
1394 const Monitor* monitor)1408 const Monitor* monitor)
1395{1409{
1396 if(monitor->object->priv->active_monitor != monitor &&1410 if(monitor->object->priv->active_monitor == monitor)
1397 greeter_background_monitor_enabled(monitor->object, monitor))1411 {
1412 GdkWindow *gdkwindow = gtk_widget_get_window (widget);
1413 Window window = GDK_WINDOW_XID (gdkwindow);
1414 Display *display = GDK_WINDOW_XDISPLAY (gdkwindow);
1415
1416 static Atom wm_protocols = None;
1417 static Atom wm_take_focus = None;
1418
1419 if (!wm_protocols)
1420 wm_protocols = XInternAtom(display, "WM_PROTOCOLS", False);
1421 if (!wm_take_focus)
1422 wm_take_focus = XInternAtom(display, "WM_TAKE_FOCUS", False);
1423
1424 XEvent ev = {0};
1425 ev.xclient.type = ClientMessage;
1426 ev.xclient.window = window;
1427 ev.xclient.message_type = wm_protocols;
1428 ev.xclient.format = 32;
1429 ev.xclient.data.l[0] = wm_take_focus;
1430 ev.xclient.data.l[1] = CurrentTime;
1431 XSendEvent(display, window, False, 0L, &ev);
1432 }
1433 else if(monitor->object->priv->follow_cursor && greeter_background_monitor_enabled(monitor->object, monitor))
1398 greeter_background_set_active_monitor(monitor->object, monitor);1434 greeter_background_set_active_monitor(monitor->object, monitor);
1399 return FALSE;1435 return FALSE;
1400}1436}
@@ -1633,7 +1669,7 @@
1633}1669}
16341670
1635static gdouble1671static gdouble
1636transition_func_easy_in_out(gdouble x)1672transition_func_ease_in_out(gdouble x)
1637{1673{
1638 return (1 - cos(M_PI*x))/2;1674 return (1 - cos(M_PI*x))/2;
1639}1675}
16401676
=== modified file 'src/greeterbackground.h'
--- src/greeterbackground.h 2014-11-03 10:39:58 +0000
+++ src/greeterbackground.h 2015-03-29 05:44:39 +0000
@@ -14,6 +14,19 @@
1414
15#define GREETER_BACKGROUND_DEFAULT "*"15#define GREETER_BACKGROUND_DEFAULT "*"
1616
17typedef enum
18{
19 TRANSITION_TYPE_NONE,
20 TRANSITION_TYPE_EASE_IN_OUT,
21 TRANSITION_TYPE_LINEAR,
22 TRANSITION_TYPE_FALLBACK
23} TransitionType;
24
25typedef enum
26{
27 TRANSITION_EFFECT_NONE,
28} TransitionEffect;
29
17typedef struct _GreeterBackground GreeterBackground;30typedef struct _GreeterBackground GreeterBackground;
18typedef struct _GreeterBackgroundClass GreeterBackgroundClass;31typedef struct _GreeterBackgroundClass GreeterBackgroundClass;
1932
@@ -25,10 +38,10 @@
25void greeter_background_set_monitor_config (GreeterBackground* background,38void greeter_background_set_monitor_config (GreeterBackground* background,
26 const gchar* name,39 const gchar* name,
27 const gchar* bg,40 const gchar* bg,
28 gboolean user_bg, gboolean user_bg_used,41 gint user_bg,
29 gboolean laptop, gboolean laptop_used,42 gint laptop,
30 gint transition_duration,43 gint transition_duration,
31 const gchar* transition_func);44 TransitionType transition_type);
32void greeter_background_remove_monitor_config (GreeterBackground* background,45void greeter_background_remove_monitor_config (GreeterBackground* background,
33 const gchar* name);46 const gchar* name);
34gchar** greeter_background_get_configured_monitors (GreeterBackground* background);47gchar** greeter_background_get_configured_monitors (GreeterBackground* background);
3548
=== added file 'src/greeterconfiguration.c'
--- src/greeterconfiguration.c 1970-01-01 00:00:00 +0000
+++ src/greeterconfiguration.c 2015-03-29 05:44:39 +0000
@@ -0,0 +1,371 @@
1
2#include <glib.h>
3
4#include "greeterconfiguration.h"
5
6
7static GKeyFile* greeter_config = NULL;
8static GKeyFile* state_config = NULL;
9static gchar* state_filename = NULL;
10
11static GKeyFile* get_file_for_group (const gchar** group);
12static void save_key_file (GKeyFile* config, const gchar* path);
13static gboolean get_int (GKeyFile* config, const gchar* group, const gchar* key, gint* out);
14static gboolean get_bool (GKeyFile* config, const gchar* group, const gchar* key, gboolean* out);
15
16/* Implementation */
17
18static GList*
19append_directory_content(GList* files, const gchar* path)
20{
21 GError* error = NULL;
22 gchar* full_path = g_build_filename(path, "lightdm", "lightdm-gtk-greeter.conf.d", NULL);
23 GDir* dir = g_dir_open(full_path, 0, &error);
24 if(error && !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
25 g_warning("[Configuration] Failed to read configuration directory '%s': %s", full_path, error->message);
26 g_clear_error(&error);
27
28 GList* content = NULL;
29 if(dir)
30 {
31 const gchar *name;
32 while((name = g_dir_read_name(dir)))
33 {
34 if(!g_str_has_suffix(name, ".conf"))
35 continue;
36 content = g_list_prepend(content, g_build_filename(full_path, name, NULL));
37 }
38 g_dir_close(dir);
39
40 if(content)
41 content = g_list_sort(content, (GCompareFunc)g_strcmp0);
42 }
43
44 content = g_list_append(content, g_build_filename(path, "lightdm", "lightdm-gtk-greeter.conf", NULL));
45
46 GList* list_iter;
47 for(list_iter = content; list_iter; list_iter = g_list_next(list_iter))
48 {
49 if(g_file_test(list_iter->data, G_FILE_TEST_IS_REGULAR))
50 files = g_list_prepend(files, list_iter->data);
51 else
52 g_free(list_iter->data);
53 }
54
55 g_list_free(content);
56 g_free(full_path);
57 return files;
58}
59
60void
61config_init(void)
62{
63 GError* error = NULL;
64
65 gchar* state_config_dir = g_build_filename(g_get_user_cache_dir(), "lightdm-gtk-greeter", NULL);
66 state_filename = g_build_filename(state_config_dir, "state", NULL);
67 g_mkdir_with_parents(state_config_dir, 0775);
68 g_free(state_config_dir);
69
70 state_config = g_key_file_new();
71 g_key_file_load_from_file(state_config, state_filename, G_KEY_FILE_NONE, &error);
72 if (error && !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
73 g_warning("[Configuration] Failed to load state from %s: %s", state_filename, error->message);
74 g_clear_error(&error);
75
76
77 gint i;
78 GList* files = NULL;
79
80 const gchar* const* dirs = g_get_system_data_dirs();
81 for(i = 0; dirs[i]; ++i)
82 files = append_directory_content(files, dirs[i]);
83
84 dirs = g_get_system_config_dirs();
85 for(i = 0; dirs[i]; ++i)
86 files = append_directory_content(files, dirs[i]);
87
88 gchar* config_path_tmp = g_path_get_dirname(CONFIG_FILE);
89 gchar* config_path = g_path_get_dirname(config_path_tmp);
90 files = append_directory_content(files, config_path);
91 g_free(config_path_tmp);
92 g_free(config_path);
93
94 files = g_list_reverse(files);
95
96 GKeyFile* tmp_config = NULL;
97 GList* file_iter = NULL;
98 for(file_iter = files; file_iter; file_iter = g_list_next(file_iter))
99 {
100 const gchar* path = file_iter->data;
101
102 if(!tmp_config)
103 tmp_config = g_key_file_new();
104
105 if(!g_key_file_load_from_file(tmp_config, path, G_KEY_FILE_NONE, &error))
106 {
107 if(error)
108 {
109 g_warning("[Configuration] Failed to read file '%s': %s", path, error->message);
110 g_clear_error(&error);
111 }
112 else
113 g_warning("[Configuration] Failed to read file '%s'", path);
114 continue;
115 }
116 g_message("[Configuration] Reading file: %s", path);
117
118 if(!greeter_config)
119 {
120 greeter_config = tmp_config;
121 tmp_config = NULL;
122 continue;
123 }
124
125 gchar** group_iter = NULL;
126 gchar** groups = g_key_file_get_groups(tmp_config, NULL);
127 for(group_iter = groups; *group_iter; ++group_iter)
128 {
129 if(**group_iter == '-')
130 {
131 g_key_file_remove_group(greeter_config, *group_iter + 1, NULL);
132 continue;
133 }
134
135 gchar** key_iter = NULL;
136 gchar** keys = g_key_file_get_keys(tmp_config, *group_iter, NULL, NULL);
137 for(key_iter = keys; *key_iter; ++key_iter)
138 {
139 if(**key_iter == '-')
140 {
141 g_key_file_remove_key(greeter_config, *group_iter, *key_iter + 1, NULL);
142 continue;
143 }
144
145 gchar* value = g_key_file_get_value(tmp_config, *group_iter, *key_iter, NULL);
146 if(value)
147 {
148 g_key_file_set_value(greeter_config, *group_iter, *key_iter, value);
149 g_free(value);
150 }
151 }
152 g_strfreev(keys);
153 }
154 g_strfreev(groups);
155 }
156 if (tmp_config)
157 g_key_file_unref(tmp_config);
158 g_list_free_full(files, g_free);
159
160 if(!greeter_config)
161 greeter_config = g_key_file_new();
162}
163
164static GKeyFile*
165get_file_for_group(const gchar** group)
166{
167 if(!*group)
168 *group = CONFIG_GROUP_DEFAULT;
169
170 if(*group[0] == '/')
171 {
172 (*group)++;
173 return state_config;
174 }
175
176 return greeter_config;
177}
178
179static void
180save_key_file(GKeyFile* config, const gchar* path)
181{
182 GError* error = NULL;
183 gsize data_length = 0;
184 gchar* data = g_key_file_to_data(config, &data_length, &error);
185
186 if(error)
187 {
188 g_warning("[Configuration] Failed to save file: %s", error->message);
189 g_clear_error(&error);
190 }
191
192 if(data)
193 {
194 g_file_set_contents(path, data, data_length, &error);
195 if(error)
196 {
197 g_warning("[Configuration] Failed to save file: %s", error->message);
198 g_clear_error(&error);
199 }
200 g_free(data);
201 }
202}
203
204static gboolean
205get_int(GKeyFile* config, const gchar* group, const gchar* key, gint* out)
206{
207 GError* error = NULL;
208 *out = g_key_file_get_integer(config, group, key, &error);
209 if(!error)
210 return TRUE;
211 if(g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE))
212 g_warning("[Configuration] Failed to parse integer value [%s] %s: %s", group, key, error->message);
213 g_clear_error(&error);
214 return FALSE;
215}
216
217static gboolean
218get_bool(GKeyFile* config, const gchar* group, const gchar* key, gboolean* out)
219{
220 GError* error = NULL;
221 *out = g_key_file_get_boolean(config, group, key, &error);
222 if(!error)
223 return TRUE;
224 if(g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE))
225 g_warning("[Configuration] Failed to parse boolean value [%s] %s: %s", group, key, error->message);
226 g_clear_error(&error);
227 return FALSE;
228}
229
230gchar**
231config_get_groups(const gchar* prefix)
232{
233 gsize groups_size = 0, i, next;
234 gchar** groups = g_key_file_get_groups(greeter_config, &groups_size);
235
236 for(i = next = 0; i < groups_size; ++i)
237 if(groups[i] && g_str_has_prefix(groups[i], prefix))
238 {
239 if(i != next)
240 {
241 g_free (groups[next]);
242 groups[next] = groups[i];
243 groups[i] = NULL;
244 }
245 ++next;
246 }
247
248 if(groups)
249 groups[next] = NULL;
250
251 return groups;
252}
253
254gboolean
255config_has_key(const gchar* group, const gchar* key)
256{
257 GKeyFile* file = get_file_for_group(&group);
258 return g_key_file_has_key(file, group, key, NULL);
259}
260
261gchar*
262config_get_string(const gchar* group, const gchar* key, const gchar* fallback)
263{
264 GKeyFile* file = get_file_for_group(&group);
265 gchar* value = g_key_file_get_value(file, group, key, NULL);
266 return value || !fallback ? value : g_strdup(fallback);
267}
268
269void
270config_set_string(const gchar* group, const gchar* key, const gchar* value)
271{
272 if(get_file_for_group(&group) != state_config)
273 {
274 g_warning("[Configuration] %s(%s, %s, '%s')", __func__, group, key, value);
275 return;
276 }
277
278 g_key_file_set_value(state_config, group, key, value);
279 save_key_file(state_config, state_filename);
280}
281
282gchar**
283config_get_string_list(const gchar* group, const gchar* key, gchar** fallback)
284{
285 GKeyFile* file = get_file_for_group(&group);
286 gchar** value = g_key_file_get_string_list(file, group, key, NULL, NULL);
287 return value || !fallback ? value : g_strdupv(fallback);
288}
289
290gint
291config_get_int(const gchar* group, const gchar* key, gint fallback)
292{
293 GKeyFile* file = get_file_for_group(&group);
294 gint value;
295 if(!get_int(file, group, key, &value))
296 return fallback;
297 return value;
298}
299
300void
301config_set_int(const gchar* group, const gchar* key, gint value)
302{
303 if(get_file_for_group(&group) != state_config)
304 {
305 g_warning("[Configuration] %s(%s, %s, %d)", __func__, group, key, value);
306 return;
307 }
308
309 g_key_file_set_integer(state_config, group, key, value);
310 save_key_file(state_config, state_filename);
311}
312
313gboolean
314config_get_bool(const gchar* group, const gchar* key, gboolean fallback)
315{
316 GKeyFile* file = get_file_for_group(&group);
317 gboolean value;
318 if(!get_bool(file, group, key, &value))
319 return fallback;
320 return value;
321}
322
323void
324config_set_bool(const gchar* group, const gchar* key, gboolean value)
325{
326 if(get_file_for_group(&group) != state_config)
327 {
328 g_warning("[Configuration] %s(%s, %s, %d)", __func__, group, key, value);
329 return;
330 }
331
332 g_key_file_set_boolean(state_config, group, key, value);
333 save_key_file(state_config, state_filename);
334}
335
336gint
337config_get_enum(const gchar* group, const gchar* key, gint fallback, const gchar* first_item, ...)
338{
339 if(!first_item)
340 return fallback;
341
342 GKeyFile* file = get_file_for_group(&group);
343 gchar* value = g_key_file_get_value(file, group, key, NULL);
344
345 if(!value)
346 return fallback;
347
348 va_list var_args;
349 va_start(var_args, first_item);
350
351 gboolean found = FALSE;
352 const gchar* item_name = first_item;
353 while(item_name)
354 {
355 gint item_value = va_arg(var_args, gint);
356 if(g_strcmp0(value, item_name) == 0)
357 {
358 found = TRUE;
359 fallback = item_value;
360 break;
361 }
362 item_name = va_arg(var_args, gchar*);
363 }
364 va_end(var_args);
365
366 if(!found)
367 g_warning("[Configuration] Failed to parse enum value [%s] %s: %s", group, key, value);
368
369 return fallback;
370}
371
0372
=== added file 'src/greeterconfiguration.h'
--- src/greeterconfiguration.h 1970-01-01 00:00:00 +0000
+++ src/greeterconfiguration.h 2015-03-29 05:44:39 +0000
@@ -0,0 +1,57 @@
1
2#ifndef GREETER_CONFIGURATION_H
3#define GREETER_CONFIGURATION_H
4
5#include <glib.h>
6
7
8#define CONFIG_GROUP_DEFAULT "greeter"
9#define CONFIG_KEY_INDICATORS "indicators"
10#define CONFIG_KEY_DEBUGGING "allow-debugging"
11#define CONFIG_KEY_SCREENSAVER_TIMEOUT "screensaver-timeout"
12#define CONFIG_KEY_THEME "theme-name"
13#define CONFIG_KEY_ICON_THEME "icon-theme-name"
14#define CONFIG_KEY_FONT "font-name"
15#define CONFIG_KEY_DPI "xft-dpi"
16#define CONFIG_KEY_ANTIALIAS "xft-antialias"
17#define CONFIG_KEY_HINT_STYLE "xft-hintstyle"
18#define CONFIG_KEY_RGBA "xft-rgba"
19#define CONFIG_KEY_HIDE_USER_IMAGE "hide-user-image"
20#define CONFIG_KEY_DEFAULT_USER_IMAGE "default-user-image"
21#define CONFIG_KEY_KEYBOARD "keyboard"
22#define CONFIG_KEY_READER "reader"
23#define CONFIG_KEY_CLOCK_FORMAT "clock-format"
24#define CONFIG_KEY_ACTIVE_MONITOR "active-monitor"
25#define CONFIG_KEY_POSITION "position"
26#define CONFIG_KEY_PANEL_POSITION "panel-position"
27#define CONFIG_KEY_KEYBOARD_POSITION "keyboard-position"
28#define CONFIG_KEY_A11Y_STATES "a11y-states"
29
30#define CONFIG_GROUP_MONITOR "monitor:"
31#define CONFIG_KEY_BACKGROUND "background"
32#define CONFIG_KEY_USER_BACKGROUND "user-background"
33#define CONFIG_KEY_LAPTOP "laptop"
34#define CONFIG_KEY_T_TYPE "transition-type"
35#define CONFIG_KEY_T_DURATION "transition-duration"
36
37#define STATE_SECTION_GREETER "/greeter"
38#define STATE_SECTION_A11Y "/a11y-states"
39#define STATE_KEY_LAST_USER "last-user"
40#define STATE_KEY_LAST_SESSION "last-session"
41
42
43void config_init (void);
44
45gchar** config_get_groups (const gchar* prefix);
46gboolean config_has_key (const gchar* group, const gchar* key);
47
48gchar* config_get_string (const gchar* group, const gchar* key, const gchar* fallback);
49void config_set_string (const gchar* group, const gchar* key, const gchar* value);
50gchar** config_get_string_list (const gchar* group, const gchar* key, gchar** fallback);
51gint config_get_int (const gchar* group, const gchar* key, gint fallback);
52void config_set_int (const gchar* group, const gchar* key, gint value);
53gboolean config_get_bool (const gchar* group, const gchar* key, gboolean fallback);
54void config_set_bool (const gchar* group, const gchar* key, gboolean value);
55gint config_get_enum (const gchar* group, const gchar* key, gint fallback, const gchar* first_name, ...) G_GNUC_NULL_TERMINATED;
56
57#endif //GREETER_CONFIGURATION_H
058
=== modified file 'src/lightdm-gtk-greeter-fallback.css'
--- src/lightdm-gtk-greeter-fallback.css 2014-05-22 19:52:34 +0000
+++ src/lightdm-gtk-greeter-fallback.css 2015-03-29 05:44:39 +0000
@@ -1,12 +1,12 @@
1#layout_menuitem>GtkLabel1#layout_menuitem>GtkLabel
2{2{
3 border: 1px solid alpha(@menu_fg_color, 0.8);3 border: 1px solid alpha(@menu_fg_color, 0.8);
4 border-radius: 0.5em;4 border-radius: 0.5em;
5 padding: 0px 0.25em;5 padding: 0px 0.25em;
6 background: alpha(@menu_fg_color, 0.2);6 background: alpha(@menu_fg_color, 0.2);
7}7}
88
9#layout_menuitem9#layout_menuitem
10{10{
11 padding: 1px;11 padding: 1px;
12}12}
1313
=== modified file 'src/lightdm-gtk-greeter.c'
--- src/lightdm-gtk-greeter.c 2015-01-26 14:41:10 +0000
+++ src/lightdm-gtk-greeter.c 2015-03-29 05:44:39 +0000
@@ -47,19 +47,16 @@
4747
48#include <lightdm.h>48#include <lightdm.h>
4949
50#include "src/greeterconfiguration.h"
50#include "src/greetermenubar.h"51#include "src/greetermenubar.h"
51#include "src/greeterbackground.h"52#include "src/greeterbackground.h"
52#include "src/lightdm-gtk-greeter-ui.h"53#include "src/lightdm-gtk-greeter-ui.h"
53#include "src/lightdm-gtk-greeter-css-fallback.h"54#include "src/lightdm-gtk-greeter-css-fallback.h"
54#include "src/lightdm-gtk-greeter-css-application.h"55#include "src/lightdm-gtk-greeter-css-application.h"
5556
57
56static LightDMGreeter *greeter;58static LightDMGreeter *greeter;
5759
58/* State file */
59static GKeyFile *state;
60static gchar *state_filename;
61static void save_state_file (void);
62
63/* List of spawned processes */60/* List of spawned processes */
64static GSList *pids_to_close = NULL;61static GSList *pids_to_close = NULL;
65static GPid spawn_argv_pid (gchar **argv, GSpawnFlags flags, gint *pfd, GError **perror);62static GPid spawn_argv_pid (gchar **argv, GSpawnFlags flags, gint *pfd, GError **perror);
@@ -70,7 +67,8 @@
70static void sigterm_cb (gpointer user_data);67static void sigterm_cb (gpointer user_data);
7168
72/* Screen window */69/* Screen window */
73static GtkOverlay *screen_overlay;70static GtkOverlay *screen_overlay;
71static GtkWidget *screen_overlay_child;
7472
75/* Login window */73/* Login window */
76static GtkWidget *login_window;74static GtkWidget *login_window;
@@ -123,7 +121,7 @@
123 DimensionPosition width, height;121 DimensionPosition width, height;
124} WindowPosition;122} WindowPosition;
125123
126static WindowPosition* key_file_get_position (GKeyFile *key_file, const gchar *group_name, const gchar *key, const WindowPosition *default_value);124static WindowPosition* str_to_position (const gchar *str, const WindowPosition *default_value);
127/* Function translate user defined coordinates to absolute value */125/* Function translate user defined coordinates to absolute value */
128static gint get_absolute_position (const DimensionPosition *p, gint screen, gint window);126static gint get_absolute_position (const DimensionPosition *p, gint screen, gint window);
129gboolean screen_overlay_get_child_position_cb (GtkWidget *overlay, GtkWidget *widget, GdkRectangle *allocation, gpointer user_data);127gboolean screen_overlay_get_child_position_cb (GtkWidget *overlay, GtkWidget *widget, GdkRectangle *allocation, gpointer user_data);
@@ -263,7 +261,7 @@
263/* Maybe unnecessary (in future) trick to enable accelerators for hidden/detached menu items */261/* Maybe unnecessary (in future) trick to enable accelerators for hidden/detached menu items */
264static void reassign_menu_item_accel (GtkWidget *item);262static void reassign_menu_item_accel (GtkWidget *item);
265263
266static void init_indicators (GKeyFile* config);264static void init_indicators (void);
267265
268static void layout_selected_cb (GtkCheckMenuItem *menuitem, gpointer user_data);266static void layout_selected_cb (GtkCheckMenuItem *menuitem, gpointer user_data);
269static void update_layouts_menu (void);267static void update_layouts_menu (void);
@@ -283,21 +281,42 @@
283void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data);281void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data);
284void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data);282void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data);
285283
286/* Power indciator */284/* Power indicator */
287static void power_menu_cb (GtkWidget *menuitem, gpointer userdata);285static void power_menu_cb (GtkWidget *menuitem, gpointer userdata);
288void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);286void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
289void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);287void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
290void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);288void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
291void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);289void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
292290
291static void read_monitor_configuration (const gchar *group, const gchar *name);
292
293struct SavedFocusData
294{
295 GtkWidget *widget;
296 gint editable_pos;
297};
298
293gpointer greeter_save_focus(GtkWidget* widget);299gpointer greeter_save_focus(GtkWidget* widget);
294void greeter_restore_focus(const gpointer saved_data);300void greeter_restore_focus(const gpointer saved_data);
295301
296struct SavedFocusData302
303static void
304read_monitor_configuration (const gchar *group, const gchar *name)
297{305{
298 GtkWidget *widget;306 g_debug ("[Configuration] Monitor configuration found: '%s'", name);
299 gint editable_pos;307
300};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}
301320
302gpointer321gpointer
303greeter_save_focus(GtkWidget* widget)322greeter_save_focus(GtkWidget* widget)
@@ -316,43 +335,16 @@
316void335void
317greeter_restore_focus(const gpointer saved_data)336greeter_restore_focus(const gpointer saved_data)
318{337{
319 if (!saved_data)
320 return;
321
322 struct SavedFocusData *data = saved_data;338 struct SavedFocusData *data = saved_data;
323 if (GTK_IS_WIDGET (data->widget))339
324 gtk_widget_grab_focus (data->widget);340 if (!saved_data || !GTK_IS_WIDGET (data->widget))
341 return;
342
343 gtk_widget_grab_focus (data->widget);
325 if (GTK_IS_EDITABLE(data->widget) && data->editable_pos > -1)344 if (GTK_IS_EDITABLE(data->widget) && data->editable_pos > -1)
326 gtk_editable_set_position(GTK_EDITABLE(data->widget), data->editable_pos);345 gtk_editable_set_position(GTK_EDITABLE(data->widget), data->editable_pos);
327}346}
328347
329/* State file */
330
331static void
332save_state_file (void)
333{
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 }
354}
355
356/* Terminating */348/* Terminating */
357349
358static GPid350static GPid
@@ -564,15 +556,14 @@
564}556}
565557
566static WindowPosition*558static WindowPosition*
567key_file_get_position (GKeyFile *key_file, const gchar *group_name, const gchar *key, const WindowPosition *default_value)559str_to_position (const gchar *str, const WindowPosition *default_value)
568{560{
569 WindowPosition* pos = g_new0 (WindowPosition, 1);561 WindowPosition* pos = g_new0 (WindowPosition, 1);
570 gchar *value = g_key_file_get_value (key_file, group_name, key, NULL);
571
572 *pos = *default_value;562 *pos = *default_value;
573563
574 if (value)564 if (str)
575 {565 {
566 gchar *value = g_strdup (str);
576 gchar *x = value;567 gchar *x = value;
577 gchar *y = strchr (value, ' ');568 gchar *y = strchr (value, ' ');
578 if (y)569 if (y)
@@ -732,7 +723,7 @@
732 }723 }
733 else724 else
734 {725 {
735 g_warning ("Failed to load user image: %s", error->message);726 g_debug ("Failed to load user image: %s", error->message);
736 g_clear_error (&error);727 g_clear_error (&error);
737 }728 }
738 }729 }
@@ -849,6 +840,7 @@
849 if (id != 0 && end_ptr > text)840 if (id != 0 && end_ptr > text)
850 {841 {
851 socket = GTK_SOCKET (gtk_socket_new ());842 socket = GTK_SOCKET (gtk_socket_new ());
843 gtk_container_foreach (GTK_CONTAINER (command->widget), (GtkCallback)gtk_widget_destroy, NULL);
852 gtk_container_add (GTK_CONTAINER (command->widget), GTK_WIDGET (socket));844 gtk_container_add (GTK_CONTAINER (command->widget), GTK_WIDGET (socket));
853 gtk_socket_add_id (socket, id);845 gtk_socket_add_id (socket, id);
854 gtk_widget_show_all (GTK_WIDGET (command->widget));846 gtk_widget_show_all (GTK_WIDGET (command->widget));
@@ -879,6 +871,7 @@
879 g_warning ("[Command/%s] Failed to run: %s", command->name, error->message);871 g_warning ("[Command/%s] Failed to run: %s", command->name, error->message);
880 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE);872 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE);
881 }873 }
874
882 g_clear_error (&error);875 g_clear_error (&error);
883876
884 return command->pid;877 return command->pid;
@@ -911,8 +904,7 @@
911static void904static void
912a11y_menuitem_toggled_cb (GtkCheckMenuItem *item, const gchar* name)905a11y_menuitem_toggled_cb (GtkCheckMenuItem *item, const gchar* name)
913{906{
914 g_key_file_set_boolean (state, "a11y-states", name, gtk_check_menu_item_get_active (item));907 config_set_bool (STATE_SECTION_A11Y, name, gtk_check_menu_item_get_active (item));
915 save_state_file ();
916}908}
917909
918/* Session */910/* Session */
@@ -942,7 +934,7 @@
942 if (!session || !is_valid_session (sessions, session))934 if (!session || !is_valid_session (sessions, session))
943 {935 {
944 /* previous session */936 /* previous session */
945 last_session = g_key_file_get_value (state, "greeter", "last-session", NULL);937 last_session = config_get_string (STATE_SECTION_GREETER, STATE_KEY_LAST_SESSION, NULL);
946 if (last_session && g_strcmp0 (session, last_session) != 0 &&938 if (last_session && g_strcmp0 (session, last_session) != 0 &&
947 is_valid_session (sessions, last_session))939 is_valid_session (sessions, last_session))
948 session = last_session;940 session = last_session;
@@ -1410,9 +1402,8 @@
1410}1402}
14111403
1412static void1404static void
1413init_indicators (GKeyFile* config)1405init_indicators (void)
1414{1406{
1415 gchar **names = NULL;
1416 gsize length = 0;1407 gsize length = 0;
1417 guint i;1408 guint i;
1418 GHashTable *builtin_items = NULL;1409 GHashTable *builtin_items = NULL;
@@ -1421,27 +1412,14 @@
1421 #ifdef HAVE_LIBINDICATOR1412 #ifdef HAVE_LIBINDICATOR
1422 gboolean inited = FALSE;1413 gboolean inited = FALSE;
1423 #endif1414 #endif
1424 gboolean fallback = FALSE;
14251415
1426 const gchar *DEFAULT_LAYOUT[] = {"~host", "~spacer", "~clock", "~spacer",1416 const gchar *DEFAULT_LAYOUT[] = {"~host", "~spacer", "~clock", "~spacer",
1427 "~session", "~language", "~a11y", "~power", NULL};1417 "~session", "~language", "~a11y", "~power", NULL};
14281418
1429 if (g_key_file_has_key (config, "greeter", "indicators", NULL))1419 gchar **names = config_get_string_list (NULL, CONFIG_KEY_INDICATORS, NULL);
1430 { /* no option = default list, empty value = empty list */1420 if (!names)
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 names = (gchar**)DEFAULT_LAYOUT;1421 names = (gchar**)DEFAULT_LAYOUT;
1443 length = g_strv_length (names);1422 length = g_strv_length (names);
1444 }
14451423
1446 builtin_items = g_hash_table_new (g_str_hash, g_str_equal);1424 builtin_items = g_hash_table_new (g_str_hash, g_str_equal);
14471425
@@ -1925,8 +1903,7 @@
1925 pending_questions = NULL;1903 pending_questions = NULL;
1926 }1904 }
19271905
1928 g_key_file_set_value (state, "greeter", "last-user", username);1906 config_set_string (STATE_SECTION_GREETER, STATE_KEY_LAST_USER, username);
1929 save_state_file ();
19301907
1931 if (g_strcmp0 (username, "*other") == 0)1908 if (g_strcmp0 (username, "*other") == 0)
1932 {1909 {
@@ -2018,8 +1995,7 @@
2018 session = get_session ();1995 session = get_session ();
20191996
2020 /* Remember last choice */1997 /* Remember last choice */
2021 g_key_file_set_value (state, "greeter", "last-session", session);1998 config_set_string (STATE_SECTION_GREETER, STATE_KEY_LAST_SESSION, session);
2022 save_state_file ();
20231999
2024 greeter_background_save_xroot (greeter_background);2000 greeter_background_save_xroot (greeter_background);
20252001
@@ -2436,7 +2412,6 @@
2436 const GList *items, *item;2412 const GList *items, *item;
2437 GtkTreeModel *model;2413 GtkTreeModel *model;
2438 GtkTreeIter iter;2414 GtkTreeIter iter;
2439 gchar *last_user;
2440 const gchar *selected_user;2415 const gchar *selected_user;
2441 gboolean logged_in = FALSE;2416 gboolean logged_in = FALSE;
24422417
@@ -2474,7 +2449,7 @@
2474 2, PANGO_WEIGHT_NORMAL,2449 2, PANGO_WEIGHT_NORMAL,
2475 -1);2450 -1);
24762451
2477 last_user = g_key_file_get_value (state, "greeter", "last-user", NULL);2452 gchar *last_user = config_get_string (STATE_SECTION_GREETER, STATE_KEY_LAST_USER, NULL);
24782453
2479 if (lightdm_greeter_get_select_user_hint (greeter))2454 if (lightdm_greeter_get_select_user_hint (greeter))
2480 selected_user = lightdm_greeter_get_select_user_hint (greeter);2455 selected_user = lightdm_greeter_get_select_user_hint (greeter);
@@ -2513,54 +2488,40 @@
2513 set_displayed_user (greeter, name);2488 set_displayed_user (greeter, name);
2514 g_free (name);2489 g_free (name);
2515 }2490 }
2516
2517 }2491 }
25182492
2519 g_free (last_user);2493 g_free (last_user);
2520}2494}
25212495
2522static GdkFilterReturn2496static GdkFilterReturn
2523focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer data)2497wm_window_filter (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
2524{2498{
2525 XEvent* xevent = (XEvent*)gxevent;2499 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;
2528 if (xevent->type == MapNotify)2500 if (xevent->type == MapNotify)
2529 {2501 {
2530 Window xwin = xevent->xmap.window;2502 GdkDisplay *display = gdk_x11_lookup_xdisplay (xevent->xmap.display);
2531 Window keyboard_xid = 0;2503 GdkWindow *win = gdk_x11_window_foreign_new_for_display (display, xevent->xmap.window);
2532 GdkDisplay* display = gdk_x11_lookup_xdisplay (xevent->xmap.display);
2533 GdkWindow* win = gdk_x11_window_foreign_new_for_display (display, xwin);
2534 GdkWindowTypeHint win_type = gdk_window_get_type_hint (win);2504 GdkWindowTypeHint win_type = gdk_window_get_type_hint (win);
25352505
2536 /* Check to see if this window is our onboard window, since we don't want to focus it. */2506 if (win_type != GDK_WINDOW_TYPE_HINT_COMBO &&
2537 if (keyboard_win)2507 win_type != GDK_WINDOW_TYPE_HINT_TOOLTIP &&
2538 keyboard_xid = gdk_x11_window_get_xid (keyboard_win);2508 win_type != GDK_WINDOW_TYPE_HINT_NOTIFICATION)
25392509 /*
2540 if (xwin != keyboard_xid2510 if (win_type == GDK_WINDOW_TYPE_HINT_DESKTOP ||
2541 && win_type != GDK_WINDOW_TYPE_HINT_TOOLTIP2511 win_type == GDK_WINDOW_TYPE_HINT_DIALOG)
2542 && win_type != GDK_WINDOW_TYPE_HINT_NOTIFICATION)2512 */
2543 {
2544 gdk_window_focus (win, GDK_CURRENT_TIME);2513 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 }2514 }
2550 else if (xevent->type == UnmapNotify)2515 else if (xevent->type == UnmapNotify)
2551 {2516 {
2552 Window xwin;2517 Window xwin;
2553 int revert_to;2518 int revert_to = RevertToNone;
2519
2554 XGetInputFocus (xevent->xunmap.display, &xwin, &revert_to);2520 XGetInputFocus (xevent->xunmap.display, &xwin, &revert_to);
2555
2556 if (revert_to == RevertToNone)2521 if (revert_to == RevertToNone)
2557 {2522 gdk_window_lower (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (screen_overlay))));
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 }
2563 }2523 }
2524
2564 return GDK_FILTER_CONTINUE;2525 return GDK_FILTER_CONTINUE;
2565}2526}
25662527
@@ -2583,19 +2544,19 @@
2583int2544int
2584main (int argc, char **argv)2545main (int argc, char **argv)
2585{2546{
2586 GKeyFile *config;
2587 GtkBuilder *builder;2547 GtkBuilder *builder;
2588 const GList *items, *item;2548 const GList *items, *item;
2589 GtkWidget *image;2549 GtkWidget *image;
2590 gchar *value, **values, *state_dir;2550 gchar *value;
2591 GtkIconTheme *icon_theme;2551 GtkIconTheme *icon_theme;
2592 GtkCssProvider *css_provider;2552 GtkCssProvider *css_provider;
2593 GError *error = NULL;2553 GError *error = NULL;
2594 Display *display;
25952554
2596 /* Prevent memory from being swapped out, as we are dealing with passwords */2555 /* Prevent memory from being swapped out, as we are dealing with passwords */
2597 mlockall (MCL_CURRENT | MCL_FUTURE);2556 mlockall (MCL_CURRENT | MCL_FUTURE);
25982557
2558 g_message ("Starting %s (%s, %s)", PACKAGE_STRING, __DATE__, __TIME__);
2559
2599 /* Disable global menus */2560 /* Disable global menus */
2600 g_unsetenv ("UBUNTU_MENUPROXY");2561 g_unsetenv ("UBUNTU_MENUPROXY");
26012562
@@ -2613,13 +2574,9 @@
26132574
2614 g_unix_signal_add (SIGTERM, (GSourceFunc)sigterm_cb, NULL);2575 g_unix_signal_add (SIGTERM, (GSourceFunc)sigterm_cb, NULL);
26152576
2616 config = g_key_file_new ();2577 config_init ();
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);
26212578
2622 if (g_key_file_get_boolean (config, "greeter", "allow-debugging", NULL))2579 if (config_get_bool (NULL, CONFIG_KEY_DEBUGGING, FALSE))
2623 g_log_set_default_handler (debug_log_handler, NULL);2580 g_log_set_default_handler (debug_log_handler, NULL);
26242581
2625 /* init gtk */2582 /* init gtk */
@@ -2628,7 +2585,7 @@
2628 /* Disabling GtkInspector shortcuts.2585 /* Disabling GtkInspector shortcuts.
2629 It is still possible to run GtkInspector with GTK_DEBUG=interactive.2586 It is still possible to run GtkInspector with GTK_DEBUG=interactive.
2630 Assume that user knows what he's doing. */2587 Assume that user knows what he's doing. */
2631 if (!g_key_file_get_boolean (config, "greeter", "allow-debugging", NULL))2588 if (!config_get_bool (NULL, CONFIG_KEY_DEBUGGING, FALSE))
2632 {2589 {
2633 GtkWidget *fake_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);2590 GtkWidget *fake_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2634 GtkBindingSet *set = gtk_binding_set_by_class (G_OBJECT_GET_CLASS (fake_window));2591 GtkBindingSet *set = gtk_binding_set_by_class (G_OBJECT_GET_CLASS (fake_window));
@@ -2660,20 +2617,10 @@
2660 }2617 }
26612618
2662#ifdef HAVE_LIBIDO2619#ifdef HAVE_LIBIDO
2620 g_debug ("Initializing IDO library");
2663 ido_init ();2621 ido_init ();
2664#endif2622#endif
26652623
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 greeter = lightdm_greeter_new ();2624 greeter = lightdm_greeter_new ();
2678 g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);2625 g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);
2679 g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);2626 g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);
@@ -2686,69 +2633,65 @@
2686 gdk_window_set_cursor (gdk_get_default_root_window (), gdk_cursor_new (GDK_LEFT_PTR));2633 gdk_window_set_cursor (gdk_get_default_root_window (), gdk_cursor_new (GDK_LEFT_PTR));
26872634
2688 /* Make the greeter behave a bit more like a screensaver if used as un/lock-screen by blanking the screen */2635 /* 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 if (lightdm_greeter_get_lock_hint (greeter))2636 if (lightdm_greeter_get_lock_hint (greeter))
2698 {2637 {
2638 Display *display = gdk_x11_display_get_xdisplay (gdk_display_get_default ());
2699 XGetScreenSaver (display, &timeout, &interval, &prefer_blanking, &allow_exposures);2639 XGetScreenSaver (display, &timeout, &interval, &prefer_blanking, &allow_exposures);
2700 XForceScreenSaver (display, ScreenSaverActive);2640 XForceScreenSaver (display, ScreenSaverActive);
2701 XSetScreenSaver (display, screensaver_timeout, 0, ScreenSaverActive, DefaultExposures);2641 XSetScreenSaver (display, config_get_int (NULL, CONFIG_KEY_SCREENSAVER_TIMEOUT, 60), 0,
2642 ScreenSaverActive, DefaultExposures);
2702 }2643 }
27032644
2704 /* Set GTK+ settings */2645 /* Set GTK+ settings */
2705 value = g_key_file_get_value (config, "greeter", "theme-name", NULL);2646 value = config_get_string (NULL, CONFIG_KEY_THEME, NULL);
2706 if (value)2647 if (value)
2707 {2648 {
2708 g_debug ("Using Gtk+ theme %s", value);2649 g_debug ("[Configuration] Changing GTK+ theme to '%s'", value);
2709 g_object_set (gtk_settings_get_default (), "gtk-theme-name", value, NULL);2650 g_object_set (gtk_settings_get_default (), "gtk-theme-name", value, NULL);
2651 g_free (value);
2710 }2652 }
2711 g_free (value);
2712 g_object_get (gtk_settings_get_default (), "gtk-theme-name", &default_theme_name, NULL);2653 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);2654 g_debug ("[Configuration] GTK+ theme: '%s'", default_theme_name);
27142655
2715 value = g_key_file_get_value (config, "greeter", "icon-theme-name", NULL);2656 value = config_get_string (NULL, CONFIG_KEY_ICON_THEME, NULL);
2716 if (value)2657 if (value)
2717 {2658 {
2718 g_debug ("Using icon theme %s", value);2659 g_debug ("[Configuration] Changing icons theme to '%s'", value);
2719 g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", value, NULL);2660 g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", value, NULL);
2661 g_free (value);
2720 }2662 }
2721 g_free (value);
2722 g_object_get (gtk_settings_get_default (), "gtk-icon-theme-name", &default_icon_theme_name, NULL);2663 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);2664 g_debug ("[Configuration] Icons theme: '%s'", default_icon_theme_name);
27242665
2725 value = g_key_file_get_value (config, "greeter", "font-name", NULL);2666 value = config_get_string (NULL, CONFIG_KEY_FONT, "Sans 10");
2726 if (value)2667 if (value)
2727 {2668 {
2728 g_debug ("Using font %s", value);2669 g_debug ("[Configuration] Changing font to '%s'", value);
2729 g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);2670 g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
2730 }2671 g_free (value);
2731 else
2732 {
2733 value = g_strdup ("Sans 10");
2734 g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
2735 }2672 }
2736 g_object_get (gtk_settings_get_default (), "gtk-font-name", &default_font_name, NULL);2673 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);2674 g_debug ("[Configuration] Font: '%s'", default_font_name);
2738 if (value)2675
2739 g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", (int) (1024 * atof (value)), NULL);2676 if (config_has_key (NULL, CONFIG_KEY_DPI))
2740 value = g_key_file_get_value (config, "greeter", "xft-antialias", NULL);2677 g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", 1024*config_get_int (NULL, CONFIG_KEY_DPI, 96), NULL);
2741 if (value)2678
2742 g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", g_strcmp0 (value, "true") == 0, NULL);2679 if (config_has_key (NULL, CONFIG_KEY_ANTIALIAS))
2743 g_free (value);2680 g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", config_get_bool (NULL, CONFIG_KEY_ANTIALIAS, FALSE), NULL);
2744 value = g_key_file_get_value (config, "greeter", "xft-hintstyle", NULL);2681
2745 if (value)2682 value = config_get_string (NULL, CONFIG_KEY_HINT_STYLE, NULL);
2683 if (value)
2684 {
2746 g_object_set (gtk_settings_get_default (), "gtk-xft-hintstyle", value, NULL);2685 g_object_set (gtk_settings_get_default (), "gtk-xft-hintstyle", value, NULL);
2747 g_free (value);2686 g_free (value);
2748 value = g_key_file_get_value (config, "greeter", "xft-rgba", NULL);2687 }
2688
2689 value = config_get_string (NULL, CONFIG_KEY_RGBA, NULL);
2749 if (value)2690 if (value)
2691 {
2750 g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);2692 g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);
2751 g_free (value);2693 g_free (value);
2694 }
27522695
2753 #ifdef AT_SPI_COMMAND2696 #ifdef AT_SPI_COMMAND
2754 spawn_line_pid (AT_SPI_COMMAND, G_SPAWN_SEARCH_PATH, NULL);2697 spawn_line_pid (AT_SPI_COMMAND, G_SPAWN_SEARCH_PATH, NULL);
@@ -2769,6 +2712,7 @@
27692712
2770 /* Screen window */2713 /* Screen window */
2771 screen_overlay = GTK_OVERLAY (gtk_builder_get_object (builder, "screen_overlay"));2714 screen_overlay = GTK_OVERLAY (gtk_builder_get_object (builder, "screen_overlay"));
2715 screen_overlay_child = GTK_WIDGET (gtk_builder_get_object (builder, "screen_overlay_child"));
27722716
2773 /* Login window */2717 /* Login window */
2774 login_window = GTK_WIDGET (gtk_builder_get_object (builder, "login_window"));2718 login_window = GTK_WIDGET (gtk_builder_get_object (builder, "login_window"));
@@ -2817,7 +2761,7 @@
2817 gtk_accel_map_add_entry ("<Login>/a11y/reader", GDK_KEY_F4, 0);2761 gtk_accel_map_add_entry ("<Login>/a11y/reader", GDK_KEY_F4, 0);
2818 gtk_accel_map_add_entry ("<Login>/power/shutdown", GDK_KEY_F4, GDK_MOD1_MASK);2762 gtk_accel_map_add_entry ("<Login>/power/shutdown", GDK_KEY_F4, GDK_MOD1_MASK);
28192763
2820 init_indicators (config);2764 init_indicators ();
28212765
2822 /* Hide empty panel */2766 /* Hide empty panel */
2823 GList *menubar_items = gtk_container_get_children (GTK_CONTAINER (menubar));2767 GList *menubar_items = gtk_container_get_children (GTK_CONTAINER (menubar));
@@ -2826,7 +2770,7 @@
2826 else2770 else
2827 g_list_free (menubar_items);2771 g_list_free (menubar_items);
28282772
2829 if (g_key_file_get_boolean (config, "greeter", "hide-user-image", NULL))2773 if (config_get_bool (NULL, CONFIG_KEY_HIDE_USER_IMAGE, FALSE))
2830 {2774 {
2831 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "user_image_border")));2775 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "user_image_border")));
2832 gtk_widget_hide (GTK_WIDGET (user_image)); /* Hide to mark image is disabled */2776 gtk_widget_hide (GTK_WIDGET (user_image)); /* Hide to mark image is disabled */
@@ -2834,7 +2778,7 @@
2834 }2778 }
2835 else2779 else
2836 {2780 {
2837 value = g_key_file_get_value (config, "greeter", "default-user-image", NULL);2781 value = config_get_string (NULL, CONFIG_KEY_DEFAULT_USER_IMAGE, NULL);
2838 if (value)2782 if (value)
2839 {2783 {
2840 if (value[0] == '#')2784 if (value[0] == '#')
@@ -2929,16 +2873,23 @@
2929 gtk_container_add (GTK_CONTAINER (a11y_menuitem), image);2873 gtk_container_add (GTK_CONTAINER (a11y_menuitem), image);
2930 }2874 }
29312875
2932 value = g_key_file_get_value (config, "greeter", "keyboard", NULL);2876 value = config_get_string (NULL, CONFIG_KEY_KEYBOARD, NULL);
2933 a11y_keyboard_command = menu_command_parse_extended ("keyboard", value, keyboard_menuitem, "onboard", "--xid");2877 if (value)
2934 g_free (value);2878 {
29352879 a11y_keyboard_command = menu_command_parse_extended ("keyboard", value, keyboard_menuitem, "onboard", "--xid");
2880 g_free (value);
2881 }
2936 gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);2882 gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);
29372883
2938 value = g_key_file_get_value (config, "greeter", "reader", NULL);2884
2939 a11y_reader_command = menu_command_parse ("reader", value, reader_menuitem);2885
2886 value = config_get_string (NULL, CONFIG_KEY_READER, NULL);
2887 if (value)
2888 {
2889 a11y_reader_command = menu_command_parse ("reader", value, reader_menuitem);
2890 g_free (value);
2891 }
2940 gtk_widget_set_visible (reader_menuitem, a11y_reader_command != NULL);2892 gtk_widget_set_visible (reader_menuitem, a11y_reader_command != NULL);
2941 g_free (value);
29422893
2943 /* Power menu */2894 /* Power menu */
2944 if (gtk_widget_get_visible (power_menuitem))2895 if (gtk_widget_get_visible (power_menuitem))
@@ -2997,9 +2948,7 @@
2997 {2948 {
2998 gtk_menu_item_set_label (GTK_MENU_ITEM (clock_menuitem), "");2949 gtk_menu_item_set_label (GTK_MENU_ITEM (clock_menuitem), "");
2999 clock_label = gtk_bin_get_child (GTK_BIN (clock_menuitem));2950 clock_label = gtk_bin_get_child (GTK_BIN (clock_menuitem));
3000 clock_format = g_key_file_get_value (config, "greeter", "clock-format", NULL);2951 clock_format = config_get_string (NULL, CONFIG_KEY_CLOCK_FORMAT, "%a, %H:%M");
3001 if (!clock_format)
3002 clock_format = "%a, %H:%M";
3003 clock_timeout_thread ();2952 clock_timeout_thread ();
3004 gdk_threads_add_timeout (1000, (GSourceFunc) clock_timeout_thread, NULL);2953 gdk_threads_add_timeout (1000, (GSourceFunc) clock_timeout_thread, NULL);
3005 }2954 }
@@ -3023,49 +2972,21 @@
3023 /* Background */2972 /* Background */
3024 greeter_background = greeter_background_new (GTK_WIDGET (screen_overlay));2973 greeter_background = greeter_background_new (GTK_WIDGET (screen_overlay));
30252974
3026 value = g_key_file_get_value (config, "greeter", "active-monitor", NULL);2975 value = config_get_string (NULL, CONFIG_KEY_ACTIVE_MONITOR, NULL);
3027 greeter_background_set_active_monitor_config (greeter_background, value ? value : "#cursor");2976 greeter_background_set_active_monitor_config (greeter_background, value ? value : "#cursor");
3028 g_free (value);2977 g_free (value);
30292978
3030 const gchar *CONFIG_MONITOR_PREFIX = "monitor:";2979 read_monitor_configuration (CONFIG_GROUP_DEFAULT, GREETER_BACKGROUND_DEFAULT);
2980
3031 gchar **config_group;2981 gchar **config_group;
3032 gchar **config_groups = g_key_file_get_groups (config, NULL);2982 gchar **config_groups = config_get_groups (CONFIG_GROUP_MONITOR);
3033 for (config_group = config_groups; *config_group; ++config_group)2983 for (config_group = config_groups; *config_group; ++config_group)
3034 {2984 {
3035 gchar *name_to_free = NULL;2985 const gchar *name = *config_group + sizeof (CONFIG_GROUP_MONITOR);
3036 const gchar *name = *config_group;2986 while (*name && g_ascii_isspace (*name))
30372987 ++name;
3038 if (g_strcmp0 (*config_group, "greeter") != 0)2988
3039 {2989 read_monitor_configuration (*config_group, name);
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);
3069 }2990 }
3070 g_strfreev (config_groups);2991 g_strfreev (config_groups);
30712992
@@ -3087,22 +3008,26 @@
3087 }3008 }
30883009
3089 /* Windows positions */3010 /* Windows positions */
3090 g_object_set_data_full (G_OBJECT (login_window), WINDOW_DATA_POSITION,3011 value = config_get_string (NULL, CONFIG_KEY_POSITION, NULL);
3091 key_file_get_position (config, "greeter", "position", &WINDOW_POS_CENTER), g_free);3012 g_object_set_data_full (G_OBJECT (login_window), WINDOW_DATA_POSITION, str_to_position (value, &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);
3096 g_free (value);3013 g_free (value);
30973014
3015
3016 gtk_widget_set_valign (panel_window, config_get_enum (NULL, CONFIG_KEY_PANEL_POSITION, GTK_ALIGN_START,
3017 "bottom", GTK_ALIGN_END,
3018 "top", GTK_ALIGN_START, NULL));
3019
3098 if (a11y_keyboard_command)3020 if (a11y_keyboard_command)
3099 g_object_set_data_full (G_OBJECT (a11y_keyboard_command->widget), WINDOW_DATA_POSITION,3021 {
3100 key_file_get_position (config, "greeter", "keyboard-position", &KEYBOARD_POSITION), g_free);3022 value = config_get_string (NULL, CONFIG_KEY_KEYBOARD_POSITION, NULL);
3023 g_object_set_data_full (G_OBJECT (a11y_keyboard_command->widget), WINDOW_DATA_POSITION, str_to_position (value, &KEYBOARD_POSITION), g_free);
3024 g_free (value);
3025 }
31013026
3102 gtk_builder_connect_signals (builder, greeter);3027 gtk_builder_connect_signals (builder, greeter);
31033028
3104 values = g_key_file_get_string_list (config, "greeter", "a11y-states", NULL, NULL);3029 gchar **a11y_states = config_get_string_list (NULL, CONFIG_KEY_A11Y_STATES, NULL);
3105 if (values && *values)3030 if (a11y_states && *a11y_states)
3106 {3031 {
3107 GHashTable *items = g_hash_table_new (g_str_hash, g_str_equal);3032 GHashTable *items = g_hash_table_new (g_str_hash, g_str_equal);
3108 g_hash_table_insert (items, "contrast", contrast_menuitem);3033 g_hash_table_insert (items, "contrast", contrast_menuitem);
@@ -3112,7 +3037,7 @@
31123037
3113 gpointer item;3038 gpointer item;
3114 gchar **values_iter;3039 gchar **values_iter;
3115 for (values_iter = values; *values_iter; ++values_iter)3040 for (values_iter = a11y_states; *values_iter; ++values_iter)
3116 {3041 {
3117 value = *values_iter;3042 value = *values_iter;
3118 switch (value[0])3043 switch (value[0])
@@ -3131,19 +3056,19 @@
3131 gtk_widget_get_visible (GTK_WIDGET (item)))3056 gtk_widget_get_visible (GTK_WIDGET (item)))
3132 {3057 {
3133 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),3058 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
3134 g_key_file_get_boolean (state, "a11y-states", value, NULL));3059 config_get_bool (STATE_SECTION_A11Y, value, FALSE));
3135 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (a11y_menuitem_toggled_cb), g_strdup (value));3060 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (a11y_menuitem_toggled_cb), g_strdup (value));
3136 }3061 }
3137 }3062 }
3138 }3063 }
3139 g_hash_table_unref (items);3064 g_hash_table_unref (items);
3140 }3065 }
3141 g_strfreev (values);3066 g_strfreev (a11y_states);
31423067
3143 /* focus fix (source: unity-greeter) */3068 /* There is no window manager, so we need to implement some of its functionality */
3144 GdkWindow* root_window = gdk_get_default_root_window ();3069 GdkWindow* root_window = gdk_get_default_root_window ();
3145 gdk_window_set_events (root_window, gdk_window_get_events (root_window) | GDK_SUBSTRUCTURE_MASK);3070 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);3071 gdk_window_add_filter (root_window, wm_window_filter, NULL);
31473072
3148 gtk_widget_show (GTK_WIDGET (screen_overlay));3073 gtk_widget_show (GTK_WIDGET (screen_overlay));
31493074
31503075
=== modified file 'src/lightdm-gtk-greeter.glade'
--- src/lightdm-gtk-greeter.glade 2014-12-10 07:59:02 +0000
+++ src/lightdm-gtk-greeter.glade 2015-03-29 05:44:39 +0000
@@ -282,6 +282,7 @@
282 <property name="name">cancel_button</property>282 <property name="name">cancel_button</property>
283 <property name="visible">True</property>283 <property name="visible">True</property>
284 <property name="can_focus">True</property>284 <property name="can_focus">True</property>
285 <property name="receives_default">False</property>
285 <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/>286 <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/>
286 </object>287 </object>
287 <packing>288 <packing>
@@ -296,6 +297,7 @@
296 <property name="name">power_ok_button</property>297 <property name="name">power_ok_button</property>
297 <property name="visible">True</property>298 <property name="visible">True</property>
298 <property name="can_focus">True</property>299 <property name="can_focus">True</property>
300 <property name="receives_default">False</property>
299 <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/>301 <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/>
300 </object>302 </object>
301 <packing>303 <packing>
@@ -326,10 +328,9 @@
326 <property name="vexpand">True</property>328 <property name="vexpand">True</property>
327 <signal name="get-child-position" handler="screen_overlay_get_child_position_cb" swapped="no"/>329 <signal name="get-child-position" handler="screen_overlay_get_child_position_cb" swapped="no"/>
328 <child>330 <child>
329 <object class="GtkBox" id="screen-child">331 <object class="GtkEventBox" id="screen_overlay_child">
330 <property name="visible">True</property>332 <property name="visible">True</property>
331 <property name="can_focus">False</property>333 <property name="can_focus">False</property>
332 <property name="orientation">vertical</property>
333 <child>334 <child>
334 <placeholder/>335 <placeholder/>
335 </child>336 </child>
@@ -541,6 +542,7 @@
541 <property name="name">cancel_button</property>542 <property name="name">cancel_button</property>
542 <property name="visible">True</property>543 <property name="visible">True</property>
543 <property name="can_focus">True</property>544 <property name="can_focus">True</property>
545 <property name="receives_default">False</property>
544 <signal name="clicked" handler="cancel_cb" swapped="no"/>546 <signal name="clicked" handler="cancel_cb" swapped="no"/>
545 </object>547 </object>
546 <packing>548 <packing>
@@ -555,6 +557,7 @@
555 <property name="name">login_button</property>557 <property name="name">login_button</property>
556 <property name="visible">True</property>558 <property name="visible">True</property>
557 <property name="can_focus">True</property>559 <property name="can_focus">True</property>
560 <property name="receives_default">False</property>
558 <signal name="clicked" handler="login_cb" swapped="no"/>561 <signal name="clicked" handler="login_cb" swapped="no"/>
559 </object>562 </object>
560 <packing>563 <packing>

Subscribers

People subscribed via source and target branches