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
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