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

Proposed by Andrew P. on 2015-03-04
Status: Merged
Merged at revision: 326
Proposed branch: lp:~kalgasnik/lightdm-gtk-greeter/post-2.0.0
Merge into: lp:lightdm-gtk-greeter
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 on 2015-04-26
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. on 2015-03-27

conf.d support (LP: #1421587)

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?

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. on 2015-03-29

Fallback if no .conf files found

Sean Davis (bluesabre) wrote :

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

Andrew P. (kalgasnik) wrote :

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

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
1=== modified file 'src/Makefile.am'
2--- src/Makefile.am 2014-11-04 11:38:36 +0000
3+++ src/Makefile.am 2015-03-29 05:44:39 +0000
4@@ -10,6 +10,8 @@
5 lightdm-gtk-greeter.c \
6 greeterbackground.c \
7 greeterbackground.h \
8+ greeterconfiguration.c \
9+ greeterconfiguration.h \
10 greetermenubar.c \
11 greetermenubar.h
12
13
14=== modified file 'src/greeterbackground.c'
15--- src/greeterbackground.c 2014-12-10 07:59:02 +0000
16+++ src/greeterbackground.c 2015-03-29 05:44:39 +0000
17@@ -58,7 +58,7 @@
18 } BackgroundConfig;
19
20 /* Transition configuration
21- Used to as part of <MonitorConfig> and <Monitor> */
22+ Used as part of <MonitorConfig> and <Monitor> */
23 typedef struct
24 {
25 /* Transition duration, in ms */
26@@ -177,9 +177,6 @@
27 gboolean follow_cursor;
28 /* Use cursor position to determinate initial active monitor */
29 gboolean follow_cursor_to_init;
30-
31- /* Name => transition function, inited in set_monitor_config() */
32- GHashTable* transition_types;
33 };
34
35 enum
36@@ -205,10 +202,10 @@
37 void greeter_background_set_monitor_config (GreeterBackground* background,
38 const gchar* name,
39 const gchar* bg, /* NULL to use fallback value */
40- gboolean user_bg, gboolean user_bg_used,
41- gboolean laptop, gboolean laptop_used,
42+ gint user_bg, /* -1 to use fallback value */
43+ gint laptop, /* -1 to use fallback value */
44 gint transition_duration, /* -1 to use fallback value */
45- const gchar* transition_type); /* NULL to use fallback value */
46+ TransitionType transition_type); /* NULL to use fallback value */
47 void greeter_background_remove_monitor_config (GreeterBackground* background,
48 const gchar* name);
49 gchar** greeter_background_get_configured_monitors (GreeterBackground* background);
50@@ -296,7 +293,7 @@
51 static void set_surface_as_root (GdkScreen* screen,
52 cairo_surface_t* surface);
53 static gdouble transition_func_linear (gdouble x);
54-static gdouble transition_func_easy_in_out (gdouble x);
55+static gdouble transition_func_ease_in_out (gdouble x);
56
57 /* Implemented in lightdm-gtk-greeter.c */
58 gpointer greeter_save_focus(GtkWidget* widget);
59@@ -317,7 +314,7 @@
60 .transition =
61 {
62 .duration = 500,
63- .func = transition_func_easy_in_out,
64+ .func = transition_func_ease_in_out,
65 .draw = (TransitionDraw)monitor_transition_draw_alpha
66 }
67 };
68@@ -413,10 +410,10 @@
69 greeter_background_set_monitor_config(GreeterBackground* background,
70 const gchar* name,
71 const gchar* bg,
72- gboolean user_bg, gboolean user_bg_used,
73- gboolean laptop, gboolean laptop_used,
74+ gint user_bg,
75+ gint laptop,
76 gint transition_duration,
77- const gchar* transition_type)
78+ TransitionType transition_type)
79 {
80 g_return_if_fail(GREETER_IS_BACKGROUND(background));
81 GreeterBackgroundPrivate* priv = background->priv;
82@@ -427,29 +424,22 @@
83
84 if(!background_config_initialize(&config->bg, bg))
85 background_config_copy(&FALLBACK->bg, &config->bg);
86- config->user_bg = user_bg_used ? user_bg : FALLBACK->user_bg;
87- config->laptop = laptop_used ? laptop : FALLBACK->laptop;
88+ config->user_bg = user_bg >= 0 ? user_bg : FALLBACK->user_bg;
89+ config->laptop = laptop >= 0 ? laptop : FALLBACK->laptop;
90 config->transition.duration = transition_duration >= 0 ? transition_duration : FALLBACK->transition.duration;
91 config->transition.draw = FALLBACK->transition.draw;
92
93- if(transition_type)
94+ switch(transition_type)
95 {
96- if(!priv->transition_types)
97- {
98- priv->transition_types = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
99- g_hash_table_insert(priv->transition_types, g_strdup("none"), NULL);
100- g_hash_table_insert(priv->transition_types, g_strdup("linear"), transition_func_linear);
101- g_hash_table_insert(priv->transition_types, g_strdup("easy-in-out"), transition_func_easy_in_out);
102- }
103- if(!g_hash_table_lookup_extended(priv->transition_types, transition_type, NULL, (gpointer*)&config->transition.func))
104- {
105- g_warning("[Background] Invalid transition type for '%s' monitor: '%s'. Using fallback value.",
106- name, transition_type);
107+ case TRANSITION_TYPE_NONE:
108+ config->transition.func = NULL; break;
109+ case TRANSITION_TYPE_LINEAR:
110+ config->transition.func = transition_func_linear; break;
111+ case TRANSITION_TYPE_EASE_IN_OUT:
112+ config->transition.func = transition_func_ease_in_out; break;
113+ default:
114 config->transition.func = FALLBACK->transition.func;
115- }
116 }
117- else
118- config->transition.func = FALLBACK->transition.func;
119
120 if(FALLBACK == priv->default_config)
121 g_hash_table_insert(priv->configs, g_strdup(name), config);
122@@ -495,12 +485,18 @@
123 g_return_if_fail(GREETER_IS_BACKGROUND(background));
124 g_return_if_fail(GDK_IS_SCREEN(screen));
125
126- g_debug("[Background] Connecting to screen: %p", screen);
127+ g_debug("[Background] Connecting to screen: %p (%dx%dpx, %dx%dmm)", screen,
128+ gdk_screen_get_width(screen), gdk_screen_get_height(screen),
129+ gdk_screen_get_width_mm(screen), gdk_screen_get_height_mm(screen));
130
131 GreeterBackgroundPrivate* priv = background->priv;
132-
133+ gpointer saved_focus = NULL;
134 if(priv->screen)
135+ {
136+ if (priv->active_monitor)
137+ saved_focus = greeter_save_focus(priv->child);
138 greeter_background_disconnect(background);
139+ }
140
141 priv->screen = screen;
142 priv->monitors_size = gdk_screen_get_n_monitors(screen);
143@@ -513,7 +509,9 @@
144 Monitor* first_not_skipped_monitor = NULL;
145
146 GHashTable* images_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
147+ cairo_region_t *screen_region = cairo_region_create();
148 gint i;
149+
150 for(i = 0; i < priv->monitors_size; ++i)
151 {
152 const MonitorConfig* config;
153@@ -553,6 +551,15 @@
154 config = &DEFAULT_MONITOR_CONFIG;
155 }
156
157+ /* Simple check to skip fully overlapped monitors.
158+ Actually, it's can track only monitors in "mirrors" mode. Nothing more. */
159+ if(cairo_region_contains_rectangle(screen_region, &monitor->geometry) == CAIRO_REGION_OVERLAP_IN)
160+ {
161+ g_debug("[Background] Skipping monitor %s #%d, its area is already used by other monitors", printable_name, i);
162+ continue;
163+ }
164+ cairo_region_union_rectangle(screen_region, &monitor->geometry);
165+
166 if(!first_not_skipped_monitor)
167 first_not_skipped_monitor = monitor;
168
169@@ -578,9 +585,8 @@
170 for(item = priv->accel_groups; item != NULL; item = g_slist_next(item))
171 gtk_window_add_accel_group(monitor->window, item->data);
172
173- if(priv->follow_cursor)
174- g_signal_connect(G_OBJECT(monitor->window), "enter-notify-event",
175- G_CALLBACK(monitor_window_enter_notify_cb), monitor);
176+ g_signal_connect(G_OBJECT(monitor->window), "enter-notify-event",
177+ G_CALLBACK(monitor_window_enter_notify_cb), monitor);
178
179 if(config->user_bg)
180 priv->customized_monitors = g_slist_prepend(priv->customized_monitors, monitor);
181@@ -624,9 +630,16 @@
182 }
183 }
184 }
185+
186 if(!priv->active_monitor)
187 greeter_background_set_active_monitor(background, NULL);
188
189+ if(saved_focus)
190+ {
191+ greeter_restore_focus(saved_focus);
192+ g_free(saved_focus);
193+ }
194+
195 priv->screen_monitors_changed_handler_id = g_signal_connect(G_OBJECT(screen), "monitors-changed",
196 G_CALLBACK(greeter_background_monitors_changed_cb),
197 background);
198@@ -768,8 +781,9 @@
199 gpointer focus = greeter_save_focus(priv->child);
200
201 if(old_parent)
202- gtk_container_remove(GTK_CONTAINER(old_parent), priv->child);
203- gtk_container_add(GTK_CONTAINER(active->window), priv->child);
204+ gtk_widget_reparent(priv->child, GTK_WIDGET(active->window));
205+ else
206+ gtk_container_add(GTK_CONTAINER(active->window), priv->child);
207
208 gtk_window_present(active->window);
209 greeter_restore_focus(focus);
210@@ -1393,8 +1407,30 @@
211 GdkEventCrossing* event,
212 const Monitor* monitor)
213 {
214- if(monitor->object->priv->active_monitor != monitor &&
215- greeter_background_monitor_enabled(monitor->object, monitor))
216+ if(monitor->object->priv->active_monitor == monitor)
217+ {
218+ GdkWindow *gdkwindow = gtk_widget_get_window (widget);
219+ Window window = GDK_WINDOW_XID (gdkwindow);
220+ Display *display = GDK_WINDOW_XDISPLAY (gdkwindow);
221+
222+ static Atom wm_protocols = None;
223+ static Atom wm_take_focus = None;
224+
225+ if (!wm_protocols)
226+ wm_protocols = XInternAtom(display, "WM_PROTOCOLS", False);
227+ if (!wm_take_focus)
228+ wm_take_focus = XInternAtom(display, "WM_TAKE_FOCUS", False);
229+
230+ XEvent ev = {0};
231+ ev.xclient.type = ClientMessage;
232+ ev.xclient.window = window;
233+ ev.xclient.message_type = wm_protocols;
234+ ev.xclient.format = 32;
235+ ev.xclient.data.l[0] = wm_take_focus;
236+ ev.xclient.data.l[1] = CurrentTime;
237+ XSendEvent(display, window, False, 0L, &ev);
238+ }
239+ else if(monitor->object->priv->follow_cursor && greeter_background_monitor_enabled(monitor->object, monitor))
240 greeter_background_set_active_monitor(monitor->object, monitor);
241 return FALSE;
242 }
243@@ -1633,7 +1669,7 @@
244 }
245
246 static gdouble
247-transition_func_easy_in_out(gdouble x)
248+transition_func_ease_in_out(gdouble x)
249 {
250 return (1 - cos(M_PI*x))/2;
251 }
252
253=== modified file 'src/greeterbackground.h'
254--- src/greeterbackground.h 2014-11-03 10:39:58 +0000
255+++ src/greeterbackground.h 2015-03-29 05:44:39 +0000
256@@ -14,6 +14,19 @@
257
258 #define GREETER_BACKGROUND_DEFAULT "*"
259
260+typedef enum
261+{
262+ TRANSITION_TYPE_NONE,
263+ TRANSITION_TYPE_EASE_IN_OUT,
264+ TRANSITION_TYPE_LINEAR,
265+ TRANSITION_TYPE_FALLBACK
266+} TransitionType;
267+
268+typedef enum
269+{
270+ TRANSITION_EFFECT_NONE,
271+} TransitionEffect;
272+
273 typedef struct _GreeterBackground GreeterBackground;
274 typedef struct _GreeterBackgroundClass GreeterBackgroundClass;
275
276@@ -25,10 +38,10 @@
277 void greeter_background_set_monitor_config (GreeterBackground* background,
278 const gchar* name,
279 const gchar* bg,
280- gboolean user_bg, gboolean user_bg_used,
281- gboolean laptop, gboolean laptop_used,
282+ gint user_bg,
283+ gint laptop,
284 gint transition_duration,
285- const gchar* transition_func);
286+ TransitionType transition_type);
287 void greeter_background_remove_monitor_config (GreeterBackground* background,
288 const gchar* name);
289 gchar** greeter_background_get_configured_monitors (GreeterBackground* background);
290
291=== added file 'src/greeterconfiguration.c'
292--- src/greeterconfiguration.c 1970-01-01 00:00:00 +0000
293+++ src/greeterconfiguration.c 2015-03-29 05:44:39 +0000
294@@ -0,0 +1,371 @@
295+
296+#include <glib.h>
297+
298+#include "greeterconfiguration.h"
299+
300+
301+static GKeyFile* greeter_config = NULL;
302+static GKeyFile* state_config = NULL;
303+static gchar* state_filename = NULL;
304+
305+static GKeyFile* get_file_for_group (const gchar** group);
306+static void save_key_file (GKeyFile* config, const gchar* path);
307+static gboolean get_int (GKeyFile* config, const gchar* group, const gchar* key, gint* out);
308+static gboolean get_bool (GKeyFile* config, const gchar* group, const gchar* key, gboolean* out);
309+
310+/* Implementation */
311+
312+static GList*
313+append_directory_content(GList* files, const gchar* path)
314+{
315+ GError* error = NULL;
316+ gchar* full_path = g_build_filename(path, "lightdm", "lightdm-gtk-greeter.conf.d", NULL);
317+ GDir* dir = g_dir_open(full_path, 0, &error);
318+ if(error && !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
319+ g_warning("[Configuration] Failed to read configuration directory '%s': %s", full_path, error->message);
320+ g_clear_error(&error);
321+
322+ GList* content = NULL;
323+ if(dir)
324+ {
325+ const gchar *name;
326+ while((name = g_dir_read_name(dir)))
327+ {
328+ if(!g_str_has_suffix(name, ".conf"))
329+ continue;
330+ content = g_list_prepend(content, g_build_filename(full_path, name, NULL));
331+ }
332+ g_dir_close(dir);
333+
334+ if(content)
335+ content = g_list_sort(content, (GCompareFunc)g_strcmp0);
336+ }
337+
338+ content = g_list_append(content, g_build_filename(path, "lightdm", "lightdm-gtk-greeter.conf", NULL));
339+
340+ GList* list_iter;
341+ for(list_iter = content; list_iter; list_iter = g_list_next(list_iter))
342+ {
343+ if(g_file_test(list_iter->data, G_FILE_TEST_IS_REGULAR))
344+ files = g_list_prepend(files, list_iter->data);
345+ else
346+ g_free(list_iter->data);
347+ }
348+
349+ g_list_free(content);
350+ g_free(full_path);
351+ return files;
352+}
353+
354+void
355+config_init(void)
356+{
357+ GError* error = NULL;
358+
359+ gchar* state_config_dir = g_build_filename(g_get_user_cache_dir(), "lightdm-gtk-greeter", NULL);
360+ state_filename = g_build_filename(state_config_dir, "state", NULL);
361+ g_mkdir_with_parents(state_config_dir, 0775);
362+ g_free(state_config_dir);
363+
364+ state_config = g_key_file_new();
365+ g_key_file_load_from_file(state_config, state_filename, G_KEY_FILE_NONE, &error);
366+ if (error && !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
367+ g_warning("[Configuration] Failed to load state from %s: %s", state_filename, error->message);
368+ g_clear_error(&error);
369+
370+
371+ gint i;
372+ GList* files = NULL;
373+
374+ const gchar* const* dirs = g_get_system_data_dirs();
375+ for(i = 0; dirs[i]; ++i)
376+ files = append_directory_content(files, dirs[i]);
377+
378+ dirs = g_get_system_config_dirs();
379+ for(i = 0; dirs[i]; ++i)
380+ files = append_directory_content(files, dirs[i]);
381+
382+ gchar* config_path_tmp = g_path_get_dirname(CONFIG_FILE);
383+ gchar* config_path = g_path_get_dirname(config_path_tmp);
384+ files = append_directory_content(files, config_path);
385+ g_free(config_path_tmp);
386+ g_free(config_path);
387+
388+ files = g_list_reverse(files);
389+
390+ GKeyFile* tmp_config = NULL;
391+ GList* file_iter = NULL;
392+ for(file_iter = files; file_iter; file_iter = g_list_next(file_iter))
393+ {
394+ const gchar* path = file_iter->data;
395+
396+ if(!tmp_config)
397+ tmp_config = g_key_file_new();
398+
399+ if(!g_key_file_load_from_file(tmp_config, path, G_KEY_FILE_NONE, &error))
400+ {
401+ if(error)
402+ {
403+ g_warning("[Configuration] Failed to read file '%s': %s", path, error->message);
404+ g_clear_error(&error);
405+ }
406+ else
407+ g_warning("[Configuration] Failed to read file '%s'", path);
408+ continue;
409+ }
410+ g_message("[Configuration] Reading file: %s", path);
411+
412+ if(!greeter_config)
413+ {
414+ greeter_config = tmp_config;
415+ tmp_config = NULL;
416+ continue;
417+ }
418+
419+ gchar** group_iter = NULL;
420+ gchar** groups = g_key_file_get_groups(tmp_config, NULL);
421+ for(group_iter = groups; *group_iter; ++group_iter)
422+ {
423+ if(**group_iter == '-')
424+ {
425+ g_key_file_remove_group(greeter_config, *group_iter + 1, NULL);
426+ continue;
427+ }
428+
429+ gchar** key_iter = NULL;
430+ gchar** keys = g_key_file_get_keys(tmp_config, *group_iter, NULL, NULL);
431+ for(key_iter = keys; *key_iter; ++key_iter)
432+ {
433+ if(**key_iter == '-')
434+ {
435+ g_key_file_remove_key(greeter_config, *group_iter, *key_iter + 1, NULL);
436+ continue;
437+ }
438+
439+ gchar* value = g_key_file_get_value(tmp_config, *group_iter, *key_iter, NULL);
440+ if(value)
441+ {
442+ g_key_file_set_value(greeter_config, *group_iter, *key_iter, value);
443+ g_free(value);
444+ }
445+ }
446+ g_strfreev(keys);
447+ }
448+ g_strfreev(groups);
449+ }
450+ if (tmp_config)
451+ g_key_file_unref(tmp_config);
452+ g_list_free_full(files, g_free);
453+
454+ if(!greeter_config)
455+ greeter_config = g_key_file_new();
456+}
457+
458+static GKeyFile*
459+get_file_for_group(const gchar** group)
460+{
461+ if(!*group)
462+ *group = CONFIG_GROUP_DEFAULT;
463+
464+ if(*group[0] == '/')
465+ {
466+ (*group)++;
467+ return state_config;
468+ }
469+
470+ return greeter_config;
471+}
472+
473+static void
474+save_key_file(GKeyFile* config, const gchar* path)
475+{
476+ GError* error = NULL;
477+ gsize data_length = 0;
478+ gchar* data = g_key_file_to_data(config, &data_length, &error);
479+
480+ if(error)
481+ {
482+ g_warning("[Configuration] Failed to save file: %s", error->message);
483+ g_clear_error(&error);
484+ }
485+
486+ if(data)
487+ {
488+ g_file_set_contents(path, data, data_length, &error);
489+ if(error)
490+ {
491+ g_warning("[Configuration] Failed to save file: %s", error->message);
492+ g_clear_error(&error);
493+ }
494+ g_free(data);
495+ }
496+}
497+
498+static gboolean
499+get_int(GKeyFile* config, const gchar* group, const gchar* key, gint* out)
500+{
501+ GError* error = NULL;
502+ *out = g_key_file_get_integer(config, group, key, &error);
503+ if(!error)
504+ return TRUE;
505+ if(g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE))
506+ g_warning("[Configuration] Failed to parse integer value [%s] %s: %s", group, key, error->message);
507+ g_clear_error(&error);
508+ return FALSE;
509+}
510+
511+static gboolean
512+get_bool(GKeyFile* config, const gchar* group, const gchar* key, gboolean* out)
513+{
514+ GError* error = NULL;
515+ *out = g_key_file_get_boolean(config, group, key, &error);
516+ if(!error)
517+ return TRUE;
518+ if(g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE))
519+ g_warning("[Configuration] Failed to parse boolean value [%s] %s: %s", group, key, error->message);
520+ g_clear_error(&error);
521+ return FALSE;
522+}
523+
524+gchar**
525+config_get_groups(const gchar* prefix)
526+{
527+ gsize groups_size = 0, i, next;
528+ gchar** groups = g_key_file_get_groups(greeter_config, &groups_size);
529+
530+ for(i = next = 0; i < groups_size; ++i)
531+ if(groups[i] && g_str_has_prefix(groups[i], prefix))
532+ {
533+ if(i != next)
534+ {
535+ g_free (groups[next]);
536+ groups[next] = groups[i];
537+ groups[i] = NULL;
538+ }
539+ ++next;
540+ }
541+
542+ if(groups)
543+ groups[next] = NULL;
544+
545+ return groups;
546+}
547+
548+gboolean
549+config_has_key(const gchar* group, const gchar* key)
550+{
551+ GKeyFile* file = get_file_for_group(&group);
552+ return g_key_file_has_key(file, group, key, NULL);
553+}
554+
555+gchar*
556+config_get_string(const gchar* group, const gchar* key, const gchar* fallback)
557+{
558+ GKeyFile* file = get_file_for_group(&group);
559+ gchar* value = g_key_file_get_value(file, group, key, NULL);
560+ return value || !fallback ? value : g_strdup(fallback);
561+}
562+
563+void
564+config_set_string(const gchar* group, const gchar* key, const gchar* value)
565+{
566+ if(get_file_for_group(&group) != state_config)
567+ {
568+ g_warning("[Configuration] %s(%s, %s, '%s')", __func__, group, key, value);
569+ return;
570+ }
571+
572+ g_key_file_set_value(state_config, group, key, value);
573+ save_key_file(state_config, state_filename);
574+}
575+
576+gchar**
577+config_get_string_list(const gchar* group, const gchar* key, gchar** fallback)
578+{
579+ GKeyFile* file = get_file_for_group(&group);
580+ gchar** value = g_key_file_get_string_list(file, group, key, NULL, NULL);
581+ return value || !fallback ? value : g_strdupv(fallback);
582+}
583+
584+gint
585+config_get_int(const gchar* group, const gchar* key, gint fallback)
586+{
587+ GKeyFile* file = get_file_for_group(&group);
588+ gint value;
589+ if(!get_int(file, group, key, &value))
590+ return fallback;
591+ return value;
592+}
593+
594+void
595+config_set_int(const gchar* group, const gchar* key, gint value)
596+{
597+ if(get_file_for_group(&group) != state_config)
598+ {
599+ g_warning("[Configuration] %s(%s, %s, %d)", __func__, group, key, value);
600+ return;
601+ }
602+
603+ g_key_file_set_integer(state_config, group, key, value);
604+ save_key_file(state_config, state_filename);
605+}
606+
607+gboolean
608+config_get_bool(const gchar* group, const gchar* key, gboolean fallback)
609+{
610+ GKeyFile* file = get_file_for_group(&group);
611+ gboolean value;
612+ if(!get_bool(file, group, key, &value))
613+ return fallback;
614+ return value;
615+}
616+
617+void
618+config_set_bool(const gchar* group, const gchar* key, gboolean value)
619+{
620+ if(get_file_for_group(&group) != state_config)
621+ {
622+ g_warning("[Configuration] %s(%s, %s, %d)", __func__, group, key, value);
623+ return;
624+ }
625+
626+ g_key_file_set_boolean(state_config, group, key, value);
627+ save_key_file(state_config, state_filename);
628+}
629+
630+gint
631+config_get_enum(const gchar* group, const gchar* key, gint fallback, const gchar* first_item, ...)
632+{
633+ if(!first_item)
634+ return fallback;
635+
636+ GKeyFile* file = get_file_for_group(&group);
637+ gchar* value = g_key_file_get_value(file, group, key, NULL);
638+
639+ if(!value)
640+ return fallback;
641+
642+ va_list var_args;
643+ va_start(var_args, first_item);
644+
645+ gboolean found = FALSE;
646+ const gchar* item_name = first_item;
647+ while(item_name)
648+ {
649+ gint item_value = va_arg(var_args, gint);
650+ if(g_strcmp0(value, item_name) == 0)
651+ {
652+ found = TRUE;
653+ fallback = item_value;
654+ break;
655+ }
656+ item_name = va_arg(var_args, gchar*);
657+ }
658+ va_end(var_args);
659+
660+ if(!found)
661+ g_warning("[Configuration] Failed to parse enum value [%s] %s: %s", group, key, value);
662+
663+ return fallback;
664+}
665+
666
667=== added file 'src/greeterconfiguration.h'
668--- src/greeterconfiguration.h 1970-01-01 00:00:00 +0000
669+++ src/greeterconfiguration.h 2015-03-29 05:44:39 +0000
670@@ -0,0 +1,57 @@
671+
672+#ifndef GREETER_CONFIGURATION_H
673+#define GREETER_CONFIGURATION_H
674+
675+#include <glib.h>
676+
677+
678+#define CONFIG_GROUP_DEFAULT "greeter"
679+#define CONFIG_KEY_INDICATORS "indicators"
680+#define CONFIG_KEY_DEBUGGING "allow-debugging"
681+#define CONFIG_KEY_SCREENSAVER_TIMEOUT "screensaver-timeout"
682+#define CONFIG_KEY_THEME "theme-name"
683+#define CONFIG_KEY_ICON_THEME "icon-theme-name"
684+#define CONFIG_KEY_FONT "font-name"
685+#define CONFIG_KEY_DPI "xft-dpi"
686+#define CONFIG_KEY_ANTIALIAS "xft-antialias"
687+#define CONFIG_KEY_HINT_STYLE "xft-hintstyle"
688+#define CONFIG_KEY_RGBA "xft-rgba"
689+#define CONFIG_KEY_HIDE_USER_IMAGE "hide-user-image"
690+#define CONFIG_KEY_DEFAULT_USER_IMAGE "default-user-image"
691+#define CONFIG_KEY_KEYBOARD "keyboard"
692+#define CONFIG_KEY_READER "reader"
693+#define CONFIG_KEY_CLOCK_FORMAT "clock-format"
694+#define CONFIG_KEY_ACTIVE_MONITOR "active-monitor"
695+#define CONFIG_KEY_POSITION "position"
696+#define CONFIG_KEY_PANEL_POSITION "panel-position"
697+#define CONFIG_KEY_KEYBOARD_POSITION "keyboard-position"
698+#define CONFIG_KEY_A11Y_STATES "a11y-states"
699+
700+#define CONFIG_GROUP_MONITOR "monitor:"
701+#define CONFIG_KEY_BACKGROUND "background"
702+#define CONFIG_KEY_USER_BACKGROUND "user-background"
703+#define CONFIG_KEY_LAPTOP "laptop"
704+#define CONFIG_KEY_T_TYPE "transition-type"
705+#define CONFIG_KEY_T_DURATION "transition-duration"
706+
707+#define STATE_SECTION_GREETER "/greeter"
708+#define STATE_SECTION_A11Y "/a11y-states"
709+#define STATE_KEY_LAST_USER "last-user"
710+#define STATE_KEY_LAST_SESSION "last-session"
711+
712+
713+void config_init (void);
714+
715+gchar** config_get_groups (const gchar* prefix);
716+gboolean config_has_key (const gchar* group, const gchar* key);
717+
718+gchar* config_get_string (const gchar* group, const gchar* key, const gchar* fallback);
719+void config_set_string (const gchar* group, const gchar* key, const gchar* value);
720+gchar** config_get_string_list (const gchar* group, const gchar* key, gchar** fallback);
721+gint config_get_int (const gchar* group, const gchar* key, gint fallback);
722+void config_set_int (const gchar* group, const gchar* key, gint value);
723+gboolean config_get_bool (const gchar* group, const gchar* key, gboolean fallback);
724+void config_set_bool (const gchar* group, const gchar* key, gboolean value);
725+gint config_get_enum (const gchar* group, const gchar* key, gint fallback, const gchar* first_name, ...) G_GNUC_NULL_TERMINATED;
726+
727+#endif //GREETER_CONFIGURATION_H
728
729=== modified file 'src/lightdm-gtk-greeter-fallback.css'
730--- src/lightdm-gtk-greeter-fallback.css 2014-05-22 19:52:34 +0000
731+++ src/lightdm-gtk-greeter-fallback.css 2015-03-29 05:44:39 +0000
732@@ -1,12 +1,12 @@
733 #layout_menuitem>GtkLabel
734 {
735- border: 1px solid alpha(@menu_fg_color, 0.8);
736- border-radius: 0.5em;
737- padding: 0px 0.25em;
738- background: alpha(@menu_fg_color, 0.2);
739+ border: 1px solid alpha(@menu_fg_color, 0.8);
740+ border-radius: 0.5em;
741+ padding: 0px 0.25em;
742+ background: alpha(@menu_fg_color, 0.2);
743 }
744
745 #layout_menuitem
746 {
747- padding: 1px;
748+ padding: 1px;
749 }
750
751=== modified file 'src/lightdm-gtk-greeter.c'
752--- src/lightdm-gtk-greeter.c 2015-01-26 14:41:10 +0000
753+++ src/lightdm-gtk-greeter.c 2015-03-29 05:44:39 +0000
754@@ -47,19 +47,16 @@
755
756 #include <lightdm.h>
757
758+#include "src/greeterconfiguration.h"
759 #include "src/greetermenubar.h"
760 #include "src/greeterbackground.h"
761 #include "src/lightdm-gtk-greeter-ui.h"
762 #include "src/lightdm-gtk-greeter-css-fallback.h"
763 #include "src/lightdm-gtk-greeter-css-application.h"
764
765+
766 static LightDMGreeter *greeter;
767
768-/* State file */
769-static GKeyFile *state;
770-static gchar *state_filename;
771-static void save_state_file (void);
772-
773 /* List of spawned processes */
774 static GSList *pids_to_close = NULL;
775 static GPid spawn_argv_pid (gchar **argv, GSpawnFlags flags, gint *pfd, GError **perror);
776@@ -70,7 +67,8 @@
777 static void sigterm_cb (gpointer user_data);
778
779 /* Screen window */
780-static GtkOverlay *screen_overlay;
781+static GtkOverlay *screen_overlay;
782+static GtkWidget *screen_overlay_child;
783
784 /* Login window */
785 static GtkWidget *login_window;
786@@ -123,7 +121,7 @@
787 DimensionPosition width, height;
788 } WindowPosition;
789
790-static WindowPosition* key_file_get_position (GKeyFile *key_file, const gchar *group_name, const gchar *key, const WindowPosition *default_value);
791+static WindowPosition* str_to_position (const gchar *str, const WindowPosition *default_value);
792 /* Function translate user defined coordinates to absolute value */
793 static gint get_absolute_position (const DimensionPosition *p, gint screen, gint window);
794 gboolean screen_overlay_get_child_position_cb (GtkWidget *overlay, GtkWidget *widget, GdkRectangle *allocation, gpointer user_data);
795@@ -263,7 +261,7 @@
796 /* Maybe unnecessary (in future) trick to enable accelerators for hidden/detached menu items */
797 static void reassign_menu_item_accel (GtkWidget *item);
798
799-static void init_indicators (GKeyFile* config);
800+static void init_indicators (void);
801
802 static void layout_selected_cb (GtkCheckMenuItem *menuitem, gpointer user_data);
803 static void update_layouts_menu (void);
804@@ -283,21 +281,42 @@
805 void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data);
806 void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data);
807
808-/* Power indciator */
809+/* Power indicator */
810 static void power_menu_cb (GtkWidget *menuitem, gpointer userdata);
811 void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
812 void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
813 void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
814 void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
815
816+static void read_monitor_configuration (const gchar *group, const gchar *name);
817+
818+struct SavedFocusData
819+{
820+ GtkWidget *widget;
821+ gint editable_pos;
822+};
823+
824 gpointer greeter_save_focus(GtkWidget* widget);
825 void greeter_restore_focus(const gpointer saved_data);
826
827-struct SavedFocusData
828+
829+static void
830+read_monitor_configuration (const gchar *group, const gchar *name)
831 {
832- GtkWidget *widget;
833- gint editable_pos;
834-};
835+ g_debug ("[Configuration] Monitor configuration found: '%s'", name);
836+
837+ gchar *background = config_get_string (group, CONFIG_KEY_BACKGROUND, NULL);
838+ greeter_background_set_monitor_config (greeter_background, name, background,
839+ config_get_bool (group, CONFIG_KEY_USER_BACKGROUND, -1),
840+ config_get_bool (group, CONFIG_KEY_LAPTOP, -1),
841+ config_get_int (group, CONFIG_KEY_T_DURATION, -1),
842+ config_get_enum (group, CONFIG_KEY_T_TYPE,
843+ TRANSITION_TYPE_FALLBACK,
844+ "none", TRANSITION_TYPE_NONE,
845+ "linear", TRANSITION_TYPE_LINEAR,
846+ "ease-in-out", TRANSITION_TYPE_EASE_IN_OUT, NULL));
847+ g_free (background);
848+}
849
850 gpointer
851 greeter_save_focus(GtkWidget* widget)
852@@ -316,43 +335,16 @@
853 void
854 greeter_restore_focus(const gpointer saved_data)
855 {
856- if (!saved_data)
857- return;
858-
859 struct SavedFocusData *data = saved_data;
860- if (GTK_IS_WIDGET (data->widget))
861- gtk_widget_grab_focus (data->widget);
862+
863+ if (!saved_data || !GTK_IS_WIDGET (data->widget))
864+ return;
865+
866+ gtk_widget_grab_focus (data->widget);
867 if (GTK_IS_EDITABLE(data->widget) && data->editable_pos > -1)
868 gtk_editable_set_position(GTK_EDITABLE(data->widget), data->editable_pos);
869 }
870
871-/* State file */
872-
873-static void
874-save_state_file (void)
875-{
876- GError *error = NULL;
877- gsize data_length = 0;
878- gchar *data = g_key_file_to_data (state, &data_length, &error);
879-
880- if (error)
881- {
882- g_warning ("Failed to save state file: %s", error->message);
883- g_clear_error (&error);
884- }
885-
886- if (data)
887- {
888- g_file_set_contents (state_filename, data, data_length, &error);
889- if (error)
890- {
891- g_warning ("Failed to save state file: %s", error->message);
892- g_clear_error (&error);
893- }
894- g_free (data);
895- }
896-}
897-
898 /* Terminating */
899
900 static GPid
901@@ -564,15 +556,14 @@
902 }
903
904 static WindowPosition*
905-key_file_get_position (GKeyFile *key_file, const gchar *group_name, const gchar *key, const WindowPosition *default_value)
906+str_to_position (const gchar *str, const WindowPosition *default_value)
907 {
908 WindowPosition* pos = g_new0 (WindowPosition, 1);
909- gchar *value = g_key_file_get_value (key_file, group_name, key, NULL);
910-
911 *pos = *default_value;
912
913- if (value)
914+ if (str)
915 {
916+ gchar *value = g_strdup (str);
917 gchar *x = value;
918 gchar *y = strchr (value, ' ');
919 if (y)
920@@ -732,7 +723,7 @@
921 }
922 else
923 {
924- g_warning ("Failed to load user image: %s", error->message);
925+ g_debug ("Failed to load user image: %s", error->message);
926 g_clear_error (&error);
927 }
928 }
929@@ -849,6 +840,7 @@
930 if (id != 0 && end_ptr > text)
931 {
932 socket = GTK_SOCKET (gtk_socket_new ());
933+ gtk_container_foreach (GTK_CONTAINER (command->widget), (GtkCallback)gtk_widget_destroy, NULL);
934 gtk_container_add (GTK_CONTAINER (command->widget), GTK_WIDGET (socket));
935 gtk_socket_add_id (socket, id);
936 gtk_widget_show_all (GTK_WIDGET (command->widget));
937@@ -879,6 +871,7 @@
938 g_warning ("[Command/%s] Failed to run: %s", command->name, error->message);
939 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE);
940 }
941+
942 g_clear_error (&error);
943
944 return command->pid;
945@@ -911,8 +904,7 @@
946 static void
947 a11y_menuitem_toggled_cb (GtkCheckMenuItem *item, const gchar* name)
948 {
949- g_key_file_set_boolean (state, "a11y-states", name, gtk_check_menu_item_get_active (item));
950- save_state_file ();
951+ config_set_bool (STATE_SECTION_A11Y, name, gtk_check_menu_item_get_active (item));
952 }
953
954 /* Session */
955@@ -942,7 +934,7 @@
956 if (!session || !is_valid_session (sessions, session))
957 {
958 /* previous session */
959- last_session = g_key_file_get_value (state, "greeter", "last-session", NULL);
960+ last_session = config_get_string (STATE_SECTION_GREETER, STATE_KEY_LAST_SESSION, NULL);
961 if (last_session && g_strcmp0 (session, last_session) != 0 &&
962 is_valid_session (sessions, last_session))
963 session = last_session;
964@@ -1410,9 +1402,8 @@
965 }
966
967 static void
968-init_indicators (GKeyFile* config)
969+init_indicators (void)
970 {
971- gchar **names = NULL;
972 gsize length = 0;
973 guint i;
974 GHashTable *builtin_items = NULL;
975@@ -1421,27 +1412,14 @@
976 #ifdef HAVE_LIBINDICATOR
977 gboolean inited = FALSE;
978 #endif
979- gboolean fallback = FALSE;
980
981 const gchar *DEFAULT_LAYOUT[] = {"~host", "~spacer", "~clock", "~spacer",
982 "~session", "~language", "~a11y", "~power", NULL};
983
984- if (g_key_file_has_key (config, "greeter", "indicators", NULL))
985- { /* no option = default list, empty value = empty list */
986- names = g_key_file_get_string_list (config, "greeter", "indicators", &length, NULL);
987- }
988- else if (g_key_file_has_key (config, "greeter", "show-indicators", NULL))
989- { /* fallback mode: no option = empty value = default list */
990- names = g_key_file_get_string_list (config, "greeter", "show-indicators", &length, NULL);
991- if (length == 0)
992- fallback = TRUE;
993- }
994-
995- if (!names || fallback)
996- {
997+ gchar **names = config_get_string_list (NULL, CONFIG_KEY_INDICATORS, NULL);
998+ if (!names)
999 names = (gchar**)DEFAULT_LAYOUT;
1000- length = g_strv_length (names);
1001- }
1002+ length = g_strv_length (names);
1003
1004 builtin_items = g_hash_table_new (g_str_hash, g_str_equal);
1005
1006@@ -1925,8 +1903,7 @@
1007 pending_questions = NULL;
1008 }
1009
1010- g_key_file_set_value (state, "greeter", "last-user", username);
1011- save_state_file ();
1012+ config_set_string (STATE_SECTION_GREETER, STATE_KEY_LAST_USER, username);
1013
1014 if (g_strcmp0 (username, "*other") == 0)
1015 {
1016@@ -2018,8 +1995,7 @@
1017 session = get_session ();
1018
1019 /* Remember last choice */
1020- g_key_file_set_value (state, "greeter", "last-session", session);
1021- save_state_file ();
1022+ config_set_string (STATE_SECTION_GREETER, STATE_KEY_LAST_SESSION, session);
1023
1024 greeter_background_save_xroot (greeter_background);
1025
1026@@ -2436,7 +2412,6 @@
1027 const GList *items, *item;
1028 GtkTreeModel *model;
1029 GtkTreeIter iter;
1030- gchar *last_user;
1031 const gchar *selected_user;
1032 gboolean logged_in = FALSE;
1033
1034@@ -2474,7 +2449,7 @@
1035 2, PANGO_WEIGHT_NORMAL,
1036 -1);
1037
1038- last_user = g_key_file_get_value (state, "greeter", "last-user", NULL);
1039+ gchar *last_user = config_get_string (STATE_SECTION_GREETER, STATE_KEY_LAST_USER, NULL);
1040
1041 if (lightdm_greeter_get_select_user_hint (greeter))
1042 selected_user = lightdm_greeter_get_select_user_hint (greeter);
1043@@ -2513,54 +2488,40 @@
1044 set_displayed_user (greeter, name);
1045 g_free (name);
1046 }
1047-
1048 }
1049
1050 g_free (last_user);
1051 }
1052
1053 static GdkFilterReturn
1054-focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
1055+wm_window_filter (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
1056 {
1057- XEvent* xevent = (XEvent*)gxevent;
1058- GdkWindow* keyboard_win = a11y_keyboard_command && a11y_keyboard_command->widget ?
1059- gtk_widget_get_window (GTK_WIDGET (a11y_keyboard_command->widget)) : NULL;
1060+ XEvent *xevent = (XEvent*)gxevent;
1061 if (xevent->type == MapNotify)
1062 {
1063- Window xwin = xevent->xmap.window;
1064- Window keyboard_xid = 0;
1065- GdkDisplay* display = gdk_x11_lookup_xdisplay (xevent->xmap.display);
1066- GdkWindow* win = gdk_x11_window_foreign_new_for_display (display, xwin);
1067+ GdkDisplay *display = gdk_x11_lookup_xdisplay (xevent->xmap.display);
1068+ GdkWindow *win = gdk_x11_window_foreign_new_for_display (display, xevent->xmap.window);
1069 GdkWindowTypeHint win_type = gdk_window_get_type_hint (win);
1070
1071- /* Check to see if this window is our onboard window, since we don't want to focus it. */
1072- if (keyboard_win)
1073- keyboard_xid = gdk_x11_window_get_xid (keyboard_win);
1074-
1075- if (xwin != keyboard_xid
1076- && win_type != GDK_WINDOW_TYPE_HINT_TOOLTIP
1077- && win_type != GDK_WINDOW_TYPE_HINT_NOTIFICATION)
1078- {
1079+ if (win_type != GDK_WINDOW_TYPE_HINT_COMBO &&
1080+ win_type != GDK_WINDOW_TYPE_HINT_TOOLTIP &&
1081+ win_type != GDK_WINDOW_TYPE_HINT_NOTIFICATION)
1082+ /*
1083+ if (win_type == GDK_WINDOW_TYPE_HINT_DESKTOP ||
1084+ win_type == GDK_WINDOW_TYPE_HINT_DIALOG)
1085+ */
1086 gdk_window_focus (win, GDK_CURRENT_TIME);
1087- /* Make sure to keep keyboard above */
1088- if (keyboard_win)
1089- gdk_window_raise (keyboard_win);
1090- }
1091 }
1092 else if (xevent->type == UnmapNotify)
1093 {
1094 Window xwin;
1095- int revert_to;
1096+ int revert_to = RevertToNone;
1097+
1098 XGetInputFocus (xevent->xunmap.display, &xwin, &revert_to);
1099-
1100 if (revert_to == RevertToNone)
1101- {
1102- gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
1103- /* Make sure to keep keyboard above */
1104- if (keyboard_win)
1105- gdk_window_raise (keyboard_win);
1106- }
1107+ gdk_window_lower (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (screen_overlay))));
1108 }
1109+
1110 return GDK_FILTER_CONTINUE;
1111 }
1112
1113@@ -2583,19 +2544,19 @@
1114 int
1115 main (int argc, char **argv)
1116 {
1117- GKeyFile *config;
1118 GtkBuilder *builder;
1119 const GList *items, *item;
1120 GtkWidget *image;
1121- gchar *value, **values, *state_dir;
1122+ gchar *value;
1123 GtkIconTheme *icon_theme;
1124 GtkCssProvider *css_provider;
1125 GError *error = NULL;
1126- Display *display;
1127
1128 /* Prevent memory from being swapped out, as we are dealing with passwords */
1129 mlockall (MCL_CURRENT | MCL_FUTURE);
1130
1131+ g_message ("Starting %s (%s, %s)", PACKAGE_STRING, __DATE__, __TIME__);
1132+
1133 /* Disable global menus */
1134 g_unsetenv ("UBUNTU_MENUPROXY");
1135
1136@@ -2613,13 +2574,9 @@
1137
1138 g_unix_signal_add (SIGTERM, (GSourceFunc)sigterm_cb, NULL);
1139
1140- config = g_key_file_new ();
1141- g_key_file_load_from_file (config, CONFIG_FILE, G_KEY_FILE_NONE, &error);
1142- if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
1143- g_warning ("Failed to load configuration from %s: %s\n", CONFIG_FILE, error->message);
1144- g_clear_error (&error);
1145+ config_init ();
1146
1147- if (g_key_file_get_boolean (config, "greeter", "allow-debugging", NULL))
1148+ if (config_get_bool (NULL, CONFIG_KEY_DEBUGGING, FALSE))
1149 g_log_set_default_handler (debug_log_handler, NULL);
1150
1151 /* init gtk */
1152@@ -2628,7 +2585,7 @@
1153 /* Disabling GtkInspector shortcuts.
1154 It is still possible to run GtkInspector with GTK_DEBUG=interactive.
1155 Assume that user knows what he's doing. */
1156- if (!g_key_file_get_boolean (config, "greeter", "allow-debugging", NULL))
1157+ if (!config_get_bool (NULL, CONFIG_KEY_DEBUGGING, FALSE))
1158 {
1159 GtkWidget *fake_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1160 GtkBindingSet *set = gtk_binding_set_by_class (G_OBJECT_GET_CLASS (fake_window));
1161@@ -2660,20 +2617,10 @@
1162 }
1163
1164 #ifdef HAVE_LIBIDO
1165+ g_debug ("Initializing IDO library");
1166 ido_init ();
1167 #endif
1168
1169- state_dir = g_build_filename (g_get_user_cache_dir (), "lightdm-gtk-greeter", NULL);
1170- g_mkdir_with_parents (state_dir, 0775);
1171- state_filename = g_build_filename (state_dir, "state", NULL);
1172- g_free (state_dir);
1173-
1174- state = g_key_file_new ();
1175- g_key_file_load_from_file (state, state_filename, G_KEY_FILE_NONE, &error);
1176- if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
1177- g_warning ("Failed to load state from %s: %s\n", state_filename, error->message);
1178- g_clear_error (&error);
1179-
1180 greeter = lightdm_greeter_new ();
1181 g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);
1182 g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);
1183@@ -2686,69 +2633,65 @@
1184 gdk_window_set_cursor (gdk_get_default_root_window (), gdk_cursor_new (GDK_LEFT_PTR));
1185
1186 /* Make the greeter behave a bit more like a screensaver if used as un/lock-screen by blanking the screen */
1187- gchar* end_ptr = NULL;
1188- int screensaver_timeout = 60;
1189- value = g_key_file_get_value (config, "greeter", "screensaver-timeout", NULL);
1190- if (value)
1191- screensaver_timeout = g_ascii_strtoll (value, &end_ptr, 0);
1192- g_free (value);
1193-
1194- display = gdk_x11_display_get_xdisplay (gdk_display_get_default ());
1195 if (lightdm_greeter_get_lock_hint (greeter))
1196 {
1197+ Display *display = gdk_x11_display_get_xdisplay (gdk_display_get_default ());
1198 XGetScreenSaver (display, &timeout, &interval, &prefer_blanking, &allow_exposures);
1199 XForceScreenSaver (display, ScreenSaverActive);
1200- XSetScreenSaver (display, screensaver_timeout, 0, ScreenSaverActive, DefaultExposures);
1201+ XSetScreenSaver (display, config_get_int (NULL, CONFIG_KEY_SCREENSAVER_TIMEOUT, 60), 0,
1202+ ScreenSaverActive, DefaultExposures);
1203 }
1204
1205 /* Set GTK+ settings */
1206- value = g_key_file_get_value (config, "greeter", "theme-name", NULL);
1207+ value = config_get_string (NULL, CONFIG_KEY_THEME, NULL);
1208 if (value)
1209 {
1210- g_debug ("Using Gtk+ theme %s", value);
1211+ g_debug ("[Configuration] Changing GTK+ theme to '%s'", value);
1212 g_object_set (gtk_settings_get_default (), "gtk-theme-name", value, NULL);
1213+ g_free (value);
1214 }
1215- g_free (value);
1216 g_object_get (gtk_settings_get_default (), "gtk-theme-name", &default_theme_name, NULL);
1217- g_debug ("Default Gtk+ theme is '%s'", default_theme_name);
1218+ g_debug ("[Configuration] GTK+ theme: '%s'", default_theme_name);
1219
1220- value = g_key_file_get_value (config, "greeter", "icon-theme-name", NULL);
1221+ value = config_get_string (NULL, CONFIG_KEY_ICON_THEME, NULL);
1222 if (value)
1223 {
1224- g_debug ("Using icon theme %s", value);
1225+ g_debug ("[Configuration] Changing icons theme to '%s'", value);
1226 g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", value, NULL);
1227+ g_free (value);
1228 }
1229- g_free (value);
1230 g_object_get (gtk_settings_get_default (), "gtk-icon-theme-name", &default_icon_theme_name, NULL);
1231- g_debug ("Default theme is '%s'", default_icon_theme_name);
1232+ g_debug ("[Configuration] Icons theme: '%s'", default_icon_theme_name);
1233
1234- value = g_key_file_get_value (config, "greeter", "font-name", NULL);
1235+ value = config_get_string (NULL, CONFIG_KEY_FONT, "Sans 10");
1236 if (value)
1237 {
1238- g_debug ("Using font %s", value);
1239- g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
1240- }
1241- else
1242- {
1243- value = g_strdup ("Sans 10");
1244- g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
1245+ g_debug ("[Configuration] Changing font to '%s'", value);
1246+ g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
1247+ g_free (value);
1248 }
1249 g_object_get (gtk_settings_get_default (), "gtk-font-name", &default_font_name, NULL);
1250- value = g_key_file_get_value (config, "greeter", "xft-dpi", NULL);
1251- if (value)
1252- g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", (int) (1024 * atof (value)), NULL);
1253- value = g_key_file_get_value (config, "greeter", "xft-antialias", NULL);
1254- if (value)
1255- g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", g_strcmp0 (value, "true") == 0, NULL);
1256- g_free (value);
1257- value = g_key_file_get_value (config, "greeter", "xft-hintstyle", NULL);
1258- if (value)
1259+ g_debug ("[Configuration] Font: '%s'", default_font_name);
1260+
1261+ if (config_has_key (NULL, CONFIG_KEY_DPI))
1262+ g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", 1024*config_get_int (NULL, CONFIG_KEY_DPI, 96), NULL);
1263+
1264+ if (config_has_key (NULL, CONFIG_KEY_ANTIALIAS))
1265+ g_object_set (gtk_settings_get_default (), "gtk-xft-antialias", config_get_bool (NULL, CONFIG_KEY_ANTIALIAS, FALSE), NULL);
1266+
1267+ value = config_get_string (NULL, CONFIG_KEY_HINT_STYLE, NULL);
1268+ if (value)
1269+ {
1270 g_object_set (gtk_settings_get_default (), "gtk-xft-hintstyle", value, NULL);
1271- g_free (value);
1272- value = g_key_file_get_value (config, "greeter", "xft-rgba", NULL);
1273+ g_free (value);
1274+ }
1275+
1276+ value = config_get_string (NULL, CONFIG_KEY_RGBA, NULL);
1277 if (value)
1278+ {
1279 g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);
1280- g_free (value);
1281+ g_free (value);
1282+ }
1283
1284 #ifdef AT_SPI_COMMAND
1285 spawn_line_pid (AT_SPI_COMMAND, G_SPAWN_SEARCH_PATH, NULL);
1286@@ -2769,6 +2712,7 @@
1287
1288 /* Screen window */
1289 screen_overlay = GTK_OVERLAY (gtk_builder_get_object (builder, "screen_overlay"));
1290+ screen_overlay_child = GTK_WIDGET (gtk_builder_get_object (builder, "screen_overlay_child"));
1291
1292 /* Login window */
1293 login_window = GTK_WIDGET (gtk_builder_get_object (builder, "login_window"));
1294@@ -2817,7 +2761,7 @@
1295 gtk_accel_map_add_entry ("<Login>/a11y/reader", GDK_KEY_F4, 0);
1296 gtk_accel_map_add_entry ("<Login>/power/shutdown", GDK_KEY_F4, GDK_MOD1_MASK);
1297
1298- init_indicators (config);
1299+ init_indicators ();
1300
1301 /* Hide empty panel */
1302 GList *menubar_items = gtk_container_get_children (GTK_CONTAINER (menubar));
1303@@ -2826,7 +2770,7 @@
1304 else
1305 g_list_free (menubar_items);
1306
1307- if (g_key_file_get_boolean (config, "greeter", "hide-user-image", NULL))
1308+ if (config_get_bool (NULL, CONFIG_KEY_HIDE_USER_IMAGE, FALSE))
1309 {
1310 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "user_image_border")));
1311 gtk_widget_hide (GTK_WIDGET (user_image)); /* Hide to mark image is disabled */
1312@@ -2834,7 +2778,7 @@
1313 }
1314 else
1315 {
1316- value = g_key_file_get_value (config, "greeter", "default-user-image", NULL);
1317+ value = config_get_string (NULL, CONFIG_KEY_DEFAULT_USER_IMAGE, NULL);
1318 if (value)
1319 {
1320 if (value[0] == '#')
1321@@ -2929,16 +2873,23 @@
1322 gtk_container_add (GTK_CONTAINER (a11y_menuitem), image);
1323 }
1324
1325- value = g_key_file_get_value (config, "greeter", "keyboard", NULL);
1326- a11y_keyboard_command = menu_command_parse_extended ("keyboard", value, keyboard_menuitem, "onboard", "--xid");
1327- g_free (value);
1328-
1329+ value = config_get_string (NULL, CONFIG_KEY_KEYBOARD, NULL);
1330+ if (value)
1331+ {
1332+ a11y_keyboard_command = menu_command_parse_extended ("keyboard", value, keyboard_menuitem, "onboard", "--xid");
1333+ g_free (value);
1334+ }
1335 gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);
1336
1337- value = g_key_file_get_value (config, "greeter", "reader", NULL);
1338- a11y_reader_command = menu_command_parse ("reader", value, reader_menuitem);
1339+
1340+
1341+ value = config_get_string (NULL, CONFIG_KEY_READER, NULL);
1342+ if (value)
1343+ {
1344+ a11y_reader_command = menu_command_parse ("reader", value, reader_menuitem);
1345+ g_free (value);
1346+ }
1347 gtk_widget_set_visible (reader_menuitem, a11y_reader_command != NULL);
1348- g_free (value);
1349
1350 /* Power menu */
1351 if (gtk_widget_get_visible (power_menuitem))
1352@@ -2997,9 +2948,7 @@
1353 {
1354 gtk_menu_item_set_label (GTK_MENU_ITEM (clock_menuitem), "");
1355 clock_label = gtk_bin_get_child (GTK_BIN (clock_menuitem));
1356- clock_format = g_key_file_get_value (config, "greeter", "clock-format", NULL);
1357- if (!clock_format)
1358- clock_format = "%a, %H:%M";
1359+ clock_format = config_get_string (NULL, CONFIG_KEY_CLOCK_FORMAT, "%a, %H:%M");
1360 clock_timeout_thread ();
1361 gdk_threads_add_timeout (1000, (GSourceFunc) clock_timeout_thread, NULL);
1362 }
1363@@ -3023,49 +2972,21 @@
1364 /* Background */
1365 greeter_background = greeter_background_new (GTK_WIDGET (screen_overlay));
1366
1367- value = g_key_file_get_value (config, "greeter", "active-monitor", NULL);
1368+ value = config_get_string (NULL, CONFIG_KEY_ACTIVE_MONITOR, NULL);
1369 greeter_background_set_active_monitor_config (greeter_background, value ? value : "#cursor");
1370 g_free (value);
1371
1372- const gchar *CONFIG_MONITOR_PREFIX = "monitor:";
1373+ read_monitor_configuration (CONFIG_GROUP_DEFAULT, GREETER_BACKGROUND_DEFAULT);
1374+
1375 gchar **config_group;
1376- gchar **config_groups = g_key_file_get_groups (config, NULL);
1377+ gchar **config_groups = config_get_groups (CONFIG_GROUP_MONITOR);
1378 for (config_group = config_groups; *config_group; ++config_group)
1379 {
1380- gchar *name_to_free = NULL;
1381- const gchar *name = *config_group;
1382-
1383- if (g_strcmp0 (*config_group, "greeter") != 0)
1384- {
1385- if (!g_str_has_prefix (name, CONFIG_MONITOR_PREFIX))
1386- continue;
1387- name = *config_group + sizeof (CONFIG_MONITOR_PREFIX);
1388- while (*name && g_ascii_isspace (*name))
1389- ++name;
1390- }
1391- else
1392- name = name_to_free = g_strdup (GREETER_BACKGROUND_DEFAULT);
1393-
1394- g_debug ("Monitor configuration found: '%s'", name);
1395-
1396- GError *user_bg_error = NULL, *laptop_error = NULL, *duration_error = NULL;
1397- gboolean user_bg = g_key_file_get_boolean (config, *config_group, "user-background", &user_bg_error);
1398- gboolean laptop = g_key_file_get_boolean (config, *config_group, "laptop", &laptop_error);
1399- gchar *background = g_key_file_get_value (config, *config_group, "background", NULL);
1400- gchar *tr_type = g_key_file_get_string (config, *config_group, "transition-type", NULL);
1401- gint tr_duration = g_key_file_get_integer (config, *config_group, "transition-duration", &duration_error);
1402-
1403- greeter_background_set_monitor_config (greeter_background, name, background,
1404- user_bg, user_bg_error == NULL,
1405- laptop, laptop_error == NULL,
1406- duration_error == NULL ? tr_duration : -1,
1407- tr_type);
1408-
1409- g_free (tr_type);
1410- g_free (background);
1411- g_free (name_to_free);
1412- g_clear_error (&user_bg_error);
1413- g_clear_error (&laptop_error);
1414+ const gchar *name = *config_group + sizeof (CONFIG_GROUP_MONITOR);
1415+ while (*name && g_ascii_isspace (*name))
1416+ ++name;
1417+
1418+ read_monitor_configuration (*config_group, name);
1419 }
1420 g_strfreev (config_groups);
1421
1422@@ -3087,22 +3008,26 @@
1423 }
1424
1425 /* Windows positions */
1426- g_object_set_data_full (G_OBJECT (login_window), WINDOW_DATA_POSITION,
1427- key_file_get_position (config, "greeter", "position", &WINDOW_POS_CENTER), g_free);
1428-
1429- value = g_key_file_get_value (config, "greeter", "panel-position", NULL);
1430- if (g_strcmp0 (value, "bottom") == 0)
1431- gtk_widget_set_valign (panel_window, GTK_ALIGN_END);
1432+ value = config_get_string (NULL, CONFIG_KEY_POSITION, NULL);
1433+ g_object_set_data_full (G_OBJECT (login_window), WINDOW_DATA_POSITION, str_to_position (value, &WINDOW_POS_CENTER), g_free);
1434 g_free (value);
1435
1436+
1437+ gtk_widget_set_valign (panel_window, config_get_enum (NULL, CONFIG_KEY_PANEL_POSITION, GTK_ALIGN_START,
1438+ "bottom", GTK_ALIGN_END,
1439+ "top", GTK_ALIGN_START, NULL));
1440+
1441 if (a11y_keyboard_command)
1442- g_object_set_data_full (G_OBJECT (a11y_keyboard_command->widget), WINDOW_DATA_POSITION,
1443- key_file_get_position (config, "greeter", "keyboard-position", &KEYBOARD_POSITION), g_free);
1444+ {
1445+ value = config_get_string (NULL, CONFIG_KEY_KEYBOARD_POSITION, NULL);
1446+ g_object_set_data_full (G_OBJECT (a11y_keyboard_command->widget), WINDOW_DATA_POSITION, str_to_position (value, &KEYBOARD_POSITION), g_free);
1447+ g_free (value);
1448+ }
1449
1450 gtk_builder_connect_signals (builder, greeter);
1451
1452- values = g_key_file_get_string_list (config, "greeter", "a11y-states", NULL, NULL);
1453- if (values && *values)
1454+ gchar **a11y_states = config_get_string_list (NULL, CONFIG_KEY_A11Y_STATES, NULL);
1455+ if (a11y_states && *a11y_states)
1456 {
1457 GHashTable *items = g_hash_table_new (g_str_hash, g_str_equal);
1458 g_hash_table_insert (items, "contrast", contrast_menuitem);
1459@@ -3112,7 +3037,7 @@
1460
1461 gpointer item;
1462 gchar **values_iter;
1463- for (values_iter = values; *values_iter; ++values_iter)
1464+ for (values_iter = a11y_states; *values_iter; ++values_iter)
1465 {
1466 value = *values_iter;
1467 switch (value[0])
1468@@ -3131,19 +3056,19 @@
1469 gtk_widget_get_visible (GTK_WIDGET (item)))
1470 {
1471 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
1472- g_key_file_get_boolean (state, "a11y-states", value, NULL));
1473+ config_get_bool (STATE_SECTION_A11Y, value, FALSE));
1474 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (a11y_menuitem_toggled_cb), g_strdup (value));
1475 }
1476 }
1477 }
1478 g_hash_table_unref (items);
1479 }
1480- g_strfreev (values);
1481+ g_strfreev (a11y_states);
1482
1483- /* focus fix (source: unity-greeter) */
1484+ /* There is no window manager, so we need to implement some of its functionality */
1485 GdkWindow* root_window = gdk_get_default_root_window ();
1486 gdk_window_set_events (root_window, gdk_window_get_events (root_window) | GDK_SUBSTRUCTURE_MASK);
1487- gdk_window_add_filter (root_window, focus_upon_map, NULL);
1488+ gdk_window_add_filter (root_window, wm_window_filter, NULL);
1489
1490 gtk_widget_show (GTK_WIDGET (screen_overlay));
1491
1492
1493=== modified file 'src/lightdm-gtk-greeter.glade'
1494--- src/lightdm-gtk-greeter.glade 2014-12-10 07:59:02 +0000
1495+++ src/lightdm-gtk-greeter.glade 2015-03-29 05:44:39 +0000
1496@@ -282,6 +282,7 @@
1497 <property name="name">cancel_button</property>
1498 <property name="visible">True</property>
1499 <property name="can_focus">True</property>
1500+ <property name="receives_default">False</property>
1501 <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/>
1502 </object>
1503 <packing>
1504@@ -296,6 +297,7 @@
1505 <property name="name">power_ok_button</property>
1506 <property name="visible">True</property>
1507 <property name="can_focus">True</property>
1508+ <property name="receives_default">False</property>
1509 <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/>
1510 </object>
1511 <packing>
1512@@ -326,10 +328,9 @@
1513 <property name="vexpand">True</property>
1514 <signal name="get-child-position" handler="screen_overlay_get_child_position_cb" swapped="no"/>
1515 <child>
1516- <object class="GtkBox" id="screen-child">
1517+ <object class="GtkEventBox" id="screen_overlay_child">
1518 <property name="visible">True</property>
1519 <property name="can_focus">False</property>
1520- <property name="orientation">vertical</property>
1521 <child>
1522 <placeholder/>
1523 </child>
1524@@ -541,6 +542,7 @@
1525 <property name="name">cancel_button</property>
1526 <property name="visible">True</property>
1527 <property name="can_focus">True</property>
1528+ <property name="receives_default">False</property>
1529 <signal name="clicked" handler="cancel_cb" swapped="no"/>
1530 </object>
1531 <packing>
1532@@ -555,6 +557,7 @@
1533 <property name="name">login_button</property>
1534 <property name="visible">True</property>
1535 <property name="can_focus">True</property>
1536+ <property name="receives_default">False</property>
1537 <signal name="clicked" handler="login_cb" swapped="no"/>
1538 </object>
1539 <packing>

Subscribers

People subscribed via source and target branches