Merge lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/lp-1319848-states-and-orca into lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/trunk

Proposed by Andrew P.
Status: Merged
Merged at revision: 297
Proposed branch: lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/lp-1319848-states-and-orca
Merge into: lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/trunk
Diff against target: 748 lines (+345/-168)
3 files modified
data/lightdm-gtk-greeter.conf (+4/-1)
src/lightdm-gtk-greeter.c (+330/-167)
src/lightdm-gtk-greeter.glade (+11/-0)
To merge this branch: bzr merge lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/lp-1319848-states-and-orca
Reviewer Review Type Date Requested Status
Sean Davis Approve
Review via email: mp+225811@code.launchpad.net

Description of the change

1. New option:
reader=screen-reader-program

Adds new item to a11y menu: Screen Reader (F4 key).

2. New option:
a11y-states=list-of-a11y-features

Controls state of a11y tools at startup. Allowed items: contrast;font;keyboard;reader.

"name" - save state on exit and restore it at start
"-name" - always disabled at start (default value)
"+name" - always enabled at start

Start screen reader at start and use saved state of "contrast" menu item:
a11y-states=+reader;contrast

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

Typo in default .conf

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

This is sane and good for accessibility. Approve.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/lightdm-gtk-greeter.conf'
2--- data/lightdm-gtk-greeter.conf 2014-02-09 20:03:35 +0000
3+++ data/lightdm-gtk-greeter.conf 2014-07-07 12:35:18 +0000
4@@ -10,7 +10,9 @@
5 # show-indicators = semi-colon ";" separated list of allowed indicator modules. Built-in indicators include "~a11y", "~language", "~session", "~power". Unity indicators can be represented by short name (e.g. "sound", "power"), service file name, or absolute path
6 # show-clock (true or false)
7 # clock-format = strftime-format string, e.g. %H:%M
8-# keyboard = command to launch on-screen keyboard
9+# keyboard = command to launch on-screen keyboard (e.g. onboard)
10+# reader = command to launch screen reader (e.g. orca)
11+# a11y-states = states of accessibility features: "name" - save state on exit, "-name" - disabled at start (default value for unlisted), "+name" - enabled at start. Allowed names: contrast, font, keyboard.
12 # position = main window position: x y
13 # default-user-image = Image used as default user icon, path or #icon-name
14 # screensaver-timeout = Timeout (in seconds) until the screen blanks when the greeter is called as lockscreen
15@@ -28,5 +30,6 @@
16 #show-clock=
17 #clock-format=
18 #keyboard=
19+#reader=
20 #position=
21 #screensaver-timeout=
22
23=== modified file 'src/lightdm-gtk-greeter.c'
24--- src/lightdm-gtk-greeter.c 2014-07-05 16:46:13 +0000
25+++ src/lightdm-gtk-greeter.c 2014-07-07 12:35:18 +0000
26@@ -64,8 +64,10 @@
27 #endif
28
29 static LightDMGreeter *greeter;
30+
31 static GKeyFile *state;
32 static gchar *state_filename;
33+static void save_state_file (void);
34
35 /* Defaults */
36 static gchar *default_font_name, *default_theme_name, *default_icon_theme_name;
37@@ -78,7 +80,8 @@
38 static GtkWidget *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem,
39 *layout_menuitem, *session_badge;
40 static GtkWidget *suspend_menuitem, *hibernate_menuitem, *restart_menuitem, *shutdown_menuitem;
41-static GtkWidget *keyboard_menuitem, *clock_menuitem, *clock_label, *host_menuitem;
42+static GtkWidget *clock_menuitem, *clock_label, *host_menuitem;
43+static GtkWidget *contrast_menuitem, *font_menuitem, *keyboard_menuitem, *reader_menuitem;
44 static GtkMenu *session_menu, *language_menu, *layout_menu;
45
46 /* Login Window Widgets */
47@@ -91,10 +94,52 @@
48 static GtkButton *cancel_button, *login_button;
49
50 static gchar *clock_format;
51-static gchar **a11y_keyboard_command;
52-static GPid a11y_kbd_pid = 0;
53-static GError *a11y_keyboard_error;
54-static GtkWindow *onboard_window;
55+
56+typedef struct
57+{
58+ gint value;
59+ /* +0 and -0 */
60+ gint sign;
61+ /* interpret 'value' as percentage of screen width/height */
62+ gboolean percentage;
63+ /* -1: left/top, 0: center, +1: right,bottom */
64+ gint anchor;
65+} DimensionPosition;
66+
67+typedef struct
68+{
69+ DimensionPosition x, y;
70+} WindowPosition;
71+
72+/* Function translate user defined coordinates to absolute value */
73+static gint get_absolute_position (const DimensionPosition *p, gint screen, gint window);
74+static const WindowPosition CENTERED_WINDOW_POS = {.x = {50, +1, TRUE, 0}, .y = {50, +1, TRUE, 0}};
75+static const WindowPosition ONBOARD_WINDOW_POS = {.x = {50, +1, TRUE, 0}, .y = { 0, -1, FALSE, +1}};
76+static const WindowPosition ONBOARD_WINDOW_SIZE = {.x = {610, 0, FALSE,0}, .y = {210, 0, FALSE, 0}};
77+static WindowPosition main_window_pos;
78+
79+typedef struct
80+{
81+ gchar **argv;
82+ gint argc;
83+
84+ GPid pid;
85+ GtkWidget *menu_item;
86+ GtkWidget *widget;
87+} MenuCommand;
88+
89+static MenuCommand *menu_command_parse (const gchar *value, GtkWidget *menu_item);
90+static MenuCommand *menu_command_parse_extended (const gchar *value, GtkWidget *menu_item,
91+ const gchar *xid_supported, const gchar *xid_arg,
92+ const WindowPosition *size);
93+static gboolean menu_command_run (MenuCommand *command);
94+static gboolean menu_command_stop (MenuCommand *command);
95+static void command_terminated_cb (GPid pid, gint status, MenuCommand *command);
96+
97+static MenuCommand *a11y_keyboard_command;
98+static MenuCommand *a11y_reader_command;
99+
100+static void a11y_menuitem_toggled_cb (GtkCheckMenuItem *item, const gchar* name);
101
102 /* Pending Questions */
103 static GSList *pending_questions = NULL;
104@@ -130,25 +175,6 @@
105 gchar *text;
106 } PAMConversationMessage;
107
108-typedef struct
109-{
110- gint value;
111- /* +0 and -0 */
112- gint sign;
113- /* interpret 'value' as percentage of screen width/height */
114- gboolean percentage;
115- /* -1: left/top, 0: center, +1: right,bottom */
116- gint anchor;
117-} DimensionPosition;
118-
119-typedef struct
120-{
121- DimensionPosition x, y;
122-} WindowPosition;
123-
124-static const WindowPosition CENTERED_WINDOW_POS = { .x = {50, +1, TRUE, 0}, .y = {50, +1, TRUE, 0} };
125-static WindowPosition main_window_pos;
126-
127 static GdkPixbuf* default_user_pixbuf = NULL;
128 static gchar* default_user_icon = "avatar-default";
129
130@@ -197,6 +223,201 @@
131 static const gchar *INDICATOR_DATA_MENUITEMS = "indicator-data-menuitems";
132 #endif
133
134+
135+static void
136+save_state_file (void)
137+{
138+ GError *error = NULL;
139+ gsize data_length = 0;
140+ gchar *data = g_key_file_to_data (state, &data_length, &error);
141+
142+ if (error)
143+ {
144+ g_warning ("Failed to save state file: %s", error->message);
145+ g_clear_error (&error);
146+ }
147+
148+ if (data)
149+ {
150+ g_file_set_contents (state_filename, data, data_length, &error);
151+ if (error)
152+ {
153+ g_warning ("Failed to save state file: %s", error->message);
154+ g_clear_error (&error);
155+ }
156+ g_free (data);
157+ }
158+}
159+
160+/* MenuCommand */
161+
162+static MenuCommand*
163+menu_command_parse (const gchar *value, GtkWidget *menu_item)
164+{
165+ return menu_command_parse_extended (value, menu_item, NULL, NULL, NULL);
166+}
167+
168+static MenuCommand*
169+menu_command_parse_extended (const gchar *value, GtkWidget *menu_item,
170+ const gchar *xid_supported, const gchar *xid_arg,
171+ const WindowPosition *size)
172+{
173+ if (!value)
174+ return NULL;
175+
176+ GError *error = NULL;
177+ gchar **argv;
178+ gint argc = 0;
179+
180+ if (!g_shell_parse_argv (value, &argc, &argv, &error))
181+ {
182+ if (error)
183+ g_warning ("Failed to parse command line: %s", error->message);
184+ g_clear_error (&error);
185+ return NULL;
186+ }
187+
188+ MenuCommand *command = g_new0 (MenuCommand, 1);
189+ command->menu_item = menu_item;
190+ command->argc = argc;
191+ command->argv = argv;
192+
193+ if (g_strcmp0 (argv[0], xid_supported) == 0)
194+ {
195+ gboolean have_xid_arg = FALSE;
196+ gint i;
197+ for (i = 1; i < argc; ++i)
198+ if (g_strcmp0 (argv[i], xid_arg) == 0)
199+ {
200+ have_xid_arg = TRUE;
201+ break;
202+ }
203+ if (!have_xid_arg)
204+ {
205+ gchar *new_value = g_strdup_printf ("%s %s", value, xid_arg);
206+
207+ if (g_shell_parse_argv (new_value, &argc, &argv, &error))
208+ {
209+ g_strfreev (command->argv);
210+ command->argc = argc;
211+ command->argv = argv;
212+ have_xid_arg = TRUE;
213+ }
214+ else
215+ {
216+ if (error)
217+ g_warning ("Failed to parse command line: %s", error->message);
218+ g_clear_error (&error);
219+ }
220+ g_free (new_value);
221+ }
222+
223+ if (have_xid_arg)
224+ {
225+ GdkRectangle screen;
226+ command->widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
227+ gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
228+ /* must be replaced with background->active_monitor */
229+ gdk_screen_get_primary_monitor (gdk_screen_get_default ()),
230+ &screen);
231+ gtk_widget_set_size_request (command->widget,
232+ get_absolute_position (&size->x, screen.width, 0),
233+ get_absolute_position (&size->y, screen.height, 0));
234+ }
235+ }
236+ return command;
237+}
238+
239+static gboolean
240+menu_command_run (MenuCommand *command)
241+{
242+ g_return_val_if_fail (command && g_strv_length (command->argv), FALSE);
243+
244+ GError *error = NULL;
245+ gboolean spawned = FALSE;
246+ if (command->widget)
247+ {
248+ GtkSocket* socket = NULL;
249+ gint out_fd = 0;
250+
251+ if (g_spawn_async_with_pipes (NULL, command->argv, NULL, G_SPAWN_SEARCH_PATH,
252+ NULL, NULL, &command->pid, NULL, &out_fd, NULL, &error))
253+ {
254+ gchar* text = NULL;
255+ GIOChannel* out_channel = g_io_channel_unix_new (out_fd);
256+ if (g_io_channel_read_line (out_channel, &text, NULL, NULL, &error) == G_IO_STATUS_NORMAL)
257+ {
258+ gchar* end_ptr = NULL;
259+
260+ text = g_strstrip (text);
261+ gint id = g_ascii_strtoll (text, &end_ptr, 0);
262+
263+ if (id != 0 && end_ptr > text)
264+ {
265+ socket = GTK_SOCKET (gtk_socket_new ());
266+ gtk_container_add (GTK_CONTAINER (command->widget), GTK_WIDGET (socket));
267+ gtk_socket_add_id (socket, id);
268+ gtk_widget_show_all (GTK_WIDGET (command->widget));
269+ spawned = TRUE;
270+ }
271+ else
272+ g_warning ("Failed to get '%s' socket: unrecognized output", command->argv[0]);
273+
274+ g_free(text);
275+ }
276+ }
277+ }
278+ else
279+ {
280+ spawned = g_spawn_async (NULL, command->argv, NULL,
281+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
282+ NULL, NULL, &command->pid, &error);
283+ if (spawned)
284+ g_child_watch_add (command->pid, (GChildWatchFunc)command_terminated_cb, command);
285+ }
286+
287+ if(!spawned)
288+ {
289+ if (error)
290+ g_warning ("Command spawning error: '%s'", error->message);
291+ command->pid = 0;
292+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE);
293+ }
294+ g_clear_error(&error);
295+ return spawned;
296+}
297+
298+static gboolean
299+menu_command_stop (MenuCommand *command)
300+{
301+ g_return_val_if_fail (command, FALSE);
302+
303+ if (command->pid)
304+ {
305+ kill (command->pid, SIGTERM);
306+ g_spawn_close_pid (command->pid);
307+ command->pid = 0;
308+ if (command->menu_item)
309+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE);
310+ if (command->widget)
311+ gtk_widget_hide (command->widget);
312+ }
313+ return TRUE;
314+}
315+
316+static void
317+command_terminated_cb (GPid pid, gint status, MenuCommand *command)
318+{
319+ menu_command_stop (command);
320+}
321+
322+static void
323+a11y_menuitem_toggled_cb (GtkCheckMenuItem *item, const gchar* name)
324+{
325+ g_key_file_set_boolean (state, "a11y-states", name, gtk_check_menu_item_get_active (item));
326+ save_state_file ();
327+}
328+
329 static void
330 pam_message_finalize (PAMConversationMessage *message)
331 {
332@@ -734,9 +955,7 @@
333 for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
334 {
335 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_iter->data)))
336- {
337 return g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), LANGUAGE_DATA_CODE));
338- }
339 }
340
341 return NULL;
342@@ -792,7 +1011,9 @@
343 {
344 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_iter->data)))
345 {
346- gtk_menu_item_set_label (GTK_MENU_ITEM (language_menuitem), g_strdup (g_object_get_data (G_OBJECT (menu_iter->data), LANGUAGE_DATA_CODE)));
347+ gtk_menu_item_set_label (GTK_MENU_ITEM (language_menuitem),
348+ g_strdup (g_object_get_data (G_OBJECT (menu_iter->data),
349+ LANGUAGE_DATA_CODE)));
350 break;
351 }
352 }
353@@ -870,6 +1091,7 @@
354
355 if (username)
356 user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
357+
358 if (user)
359 {
360 path = lightdm_user_get_image (user);
361@@ -896,7 +1118,6 @@
362 gtk_image_set_from_icon_name (GTK_IMAGE (user_image), default_user_icon, GTK_ICON_SIZE_DIALOG);
363 }
364
365-/* Function translate user defined coordinates to absolute value */
366 static gint
367 get_absolute_position (const DimensionPosition *p, gint screen, gint window)
368 {
369@@ -987,7 +1208,7 @@
370
371 region = gdk_region_rectangle (&rect);
372
373- while(x >= y)
374+ while (x >= y)
375 {
376
377 rect.x = -x + radius;
378@@ -1002,12 +1223,12 @@
379 rect.width = y - radius + width - rect.x;
380 rect.height = x - radius + height - rect.y;
381
382- gdk_region_union_with_rect(region, &rect);
383+ gdk_region_union_with_rect (region, &rect);
384
385 y++;
386 radiusError += yChange;
387 yChange += 2;
388- if(((radiusError << 1) + xChange) > 0)
389+ if (((radiusError << 1) + xChange) > 0)
390 {
391 x--;
392 radiusError += xChange;
393@@ -1025,9 +1246,10 @@
394
395 GdkWindow *window = gtk_widget_get_window (widget);
396 if (window_region)
397- gdk_region_destroy(window_region);
398+ gdk_region_destroy (window_region);
399 window_region = cairo_region_from_rectangle (allocation->width, allocation->height, radius);
400- if (window) {
401+ if (window)
402+ {
403 gdk_window_shape_combine_region(window, window_region, 0, 0);
404 gdk_window_input_shape_combine_region(window, window_region, 0, 0);
405 }
406@@ -1053,10 +1275,6 @@
407 static void
408 start_authentication (const gchar *username)
409 {
410- gchar *data;
411- gsize data_length;
412- GError *error = NULL;
413-
414 cancelling = FALSE;
415 prompted = FALSE;
416 password_prompted = FALSE;
417@@ -1069,18 +1287,7 @@
418 }
419
420 g_key_file_set_value (state, "greeter", "last-user", username);
421- data = g_key_file_to_data (state, &data_length, &error);
422- if (error)
423- g_warning ("Failed to save state file: %s", error->message);
424- g_clear_error (&error);
425- if (data)
426- {
427- g_file_set_contents (state_filename, data, data_length, &error);
428- if (error)
429- g_warning ("Failed to save state file: %s", error->message);
430- g_clear_error (&error);
431- }
432- g_free (data);
433+ save_state_file ();
434
435 if (g_strcmp0 (username, "*other") == 0)
436 {
437@@ -1163,9 +1370,6 @@
438 {
439 gchar *language;
440 gchar *session;
441- gchar *data;
442- gsize data_length;
443- GError *error = NULL;
444
445 language = get_language ();
446 if (language)
447@@ -1176,19 +1380,7 @@
448
449 /* Remember last choice */
450 g_key_file_set_value (state, "greeter", "last-session", session);
451-
452- data = g_key_file_to_data (state, &data_length, &error);
453- if (error)
454- g_warning ("Failed to save state file: %s", error->message);
455- g_clear_error (&error);
456- if (data)
457- {
458- g_file_set_contents (state_filename, data, data_length, &error);
459- if (error)
460- g_warning ("Failed to save state file: %s", error->message);
461- g_clear_error (&error);
462- }
463- g_free (data);
464+ save_state_file ();
465
466 if (!lightdm_greeter_start_session_sync (greeter, session, NULL))
467 {
468@@ -1851,82 +2043,26 @@
469 }
470 }
471
472-static void
473-keyboard_terminated_cb (GPid pid, gint status, gpointer user_data)
474+void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data);
475+G_MODULE_EXPORT
476+void
477+a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data)
478 {
479- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (keyboard_menuitem), FALSE);
480+ if (gtk_check_menu_item_get_active (item))
481+ menu_command_run (a11y_keyboard_command);
482+ else
483+ menu_command_stop (a11y_keyboard_command);
484 }
485
486-void a11y_keyboard_cb (GtkCheckMenuItem *item);
487+void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data);
488 G_MODULE_EXPORT
489 void
490-a11y_keyboard_cb (GtkCheckMenuItem *item)
491+a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data)
492 {
493 if (gtk_check_menu_item_get_active (item))
494- {
495- gboolean spawned = FALSE;
496- if (onboard_window)
497- {
498- GtkSocket* socket = NULL;
499- gint out_fd = 0;
500-
501- if (g_spawn_async_with_pipes (NULL, a11y_keyboard_command, NULL, G_SPAWN_SEARCH_PATH,
502- NULL, NULL, &a11y_kbd_pid, NULL, &out_fd, NULL,
503- &a11y_keyboard_error))
504- {
505- gchar* text = NULL;
506- GIOChannel* out_channel = g_io_channel_unix_new (out_fd);
507- if (g_io_channel_read_line(out_channel, &text, NULL, NULL, &a11y_keyboard_error) == G_IO_STATUS_NORMAL)
508- {
509- gchar* end_ptr = NULL;
510-
511- text = g_strstrip (text);
512- gint id = g_ascii_strtoll (text, &end_ptr, 0);
513-
514- if (id != 0 && end_ptr > text)
515- {
516- socket = GTK_SOCKET (gtk_socket_new ());
517- gtk_container_add (GTK_CONTAINER (onboard_window), GTK_WIDGET (socket));
518- gtk_socket_add_id (socket, id);
519- gtk_widget_show_all (GTK_WIDGET (onboard_window));
520- spawned = TRUE;
521- }
522- else
523- g_debug ("onboard keyboard command error : 'unrecognized output'");
524-
525- g_free(text);
526- }
527- }
528- }
529- else
530- {
531- spawned = g_spawn_async (NULL, a11y_keyboard_command, NULL,
532- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
533- NULL, NULL, &a11y_kbd_pid, &a11y_keyboard_error);
534- if (spawned)
535- g_child_watch_add (a11y_kbd_pid, keyboard_terminated_cb, NULL);
536- }
537-
538- if(!spawned)
539- {
540- if (a11y_keyboard_error)
541- g_debug ("a11y keyboard command error : '%s'", a11y_keyboard_error->message);
542- a11y_kbd_pid = 0;
543- g_clear_error(&a11y_keyboard_error);
544- gtk_check_menu_item_set_active (item, FALSE);
545- }
546- }
547+ menu_command_run (a11y_reader_command);
548 else
549- {
550- if (a11y_kbd_pid != 0)
551- {
552- kill (a11y_kbd_pid, SIGTERM);
553- g_spawn_close_pid (a11y_kbd_pid);
554- a11y_kbd_pid = 0;
555- if (onboard_window)
556- gtk_widget_hide (GTK_WIDGET(onboard_window));
557- }
558- }
559+ menu_command_stop (a11y_reader_command);
560 }
561
562 static void
563@@ -2320,7 +2456,8 @@
564 focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
565 {
566 XEvent* xevent = (XEvent*)gxevent;
567- GdkWindow* keyboard_win = onboard_window ? gtk_widget_get_window (GTK_WIDGET (onboard_window)) : NULL;
568+ GdkWindow* keyboard_win = a11y_keyboard_command && a11y_keyboard_command->widget ?
569+ gtk_widget_get_window (GTK_WIDGET (a11y_keyboard_command->widget)) : NULL;
570 if (xevent->type == MapNotify)
571 {
572 Window xwin = xevent->xmap.window;
573@@ -2343,11 +2480,8 @@
574 {
575 gdk_window_focus (win, GDK_CURRENT_TIME);
576 /* Make sure to keep keyboard above */
577- if (onboard_window)
578- {
579- if (keyboard_win)
580- gdk_window_raise (keyboard_win);
581- }
582+ if (keyboard_win)
583+ gdk_window_raise (keyboard_win);
584 }
585 }
586 else if (xevent->type == UnmapNotify)
587@@ -2360,11 +2494,8 @@
588 {
589 gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
590 /* Make sure to keep keyboard above */
591- if (onboard_window)
592- {
593- if (keyboard_win)
594- gdk_window_raise (keyboard_win);
595- }
596+ if (keyboard_win)
597+ gdk_window_raise (keyboard_win);
598 }
599 }
600 return GDK_FILTER_CONTINUE;
601@@ -2553,7 +2684,7 @@
602 const GList *items, *item;
603 GtkCellRenderer *renderer;
604 GtkWidget *image, *infobar_compat, *content_area;
605- gchar *value, *state_dir;
606+ gchar *value, **values, *state_dir;
607 #if GTK_CHECK_VERSION (3, 0, 0)
608 GdkRGBA background_color;
609 GtkIconTheme *icon_theme;
610@@ -2734,15 +2865,7 @@
611 if (value)
612 g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);
613 g_free (value);
614-
615- /* Get a11y on screen keyboard command*/
616- gint argp;
617- value = g_key_file_get_value (config, "greeter", "keyboard", NULL);
618- g_debug ("a11y keyboard command is '%s'", value);
619- /* Set NULL to blank to avoid warnings */
620- if (!value) { value = g_strdup(""); }
621- g_shell_parse_argv (value, &argp, &a11y_keyboard_command, NULL);
622- g_free (value);
623+
624
625 builder = gtk_builder_new ();
626 if (!gtk_builder_add_from_string (builder, lightdm_gtk_greeter_ui,
627@@ -2816,16 +2939,20 @@
628 language_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "language_menuitem"));
629 language_menu = GTK_MENU(gtk_builder_get_object (builder, "language_menu"));
630 a11y_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "a11y_menuitem"));
631+ contrast_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "high_contrast_menuitem"));
632+ font_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "large_font_menuitem"));
633+ keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
634+ reader_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "reader_menuitem"));
635 power_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "power_menuitem"));
636 layout_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "layout_menuitem"));
637 layout_menu = GTK_MENU(gtk_builder_get_object (builder, "layout_menu"));
638- keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
639 clock_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "clock_menuitem"));
640 host_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "host_menuitem"));
641
642 gtk_accel_map_add_entry ("<Login>/a11y/font", GDK_KEY_F1, 0);
643 gtk_accel_map_add_entry ("<Login>/a11y/contrast", GDK_KEY_F2, 0);
644 gtk_accel_map_add_entry ("<Login>/a11y/keyboard", GDK_KEY_F3, 0);
645+ gtk_accel_map_add_entry ("<Login>/a11y/reader", GDK_KEY_F4, 0);
646 gtk_accel_map_add_entry ("<Login>/power/shutdown", GDK_KEY_F4, GDK_MOD1_MASK);
647
648 #ifdef START_INDICATOR_SERVICES
649@@ -2934,6 +3061,20 @@
650 gtk_container_add (GTK_CONTAINER (a11y_menuitem), image);
651 }
652
653+ value = g_key_file_get_value (config, "greeter", "keyboard", NULL);
654+ a11y_keyboard_command = menu_command_parse_extended (value, keyboard_menuitem, "onboard", "--xid",
655+ &ONBOARD_WINDOW_SIZE);
656+ g_free (value);
657+
658+ gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);
659+ if (a11y_keyboard_command)
660+ g_signal_connect (a11y_keyboard_command->widget, "size-allocate", G_CALLBACK (center_window), (gpointer)&ONBOARD_WINDOW_POS);
661+
662+ value = g_key_file_get_value (config, "greeter", "reader", NULL);
663+ a11y_reader_command = menu_command_parse (value, reader_menuitem);
664+ gtk_widget_set_visible (reader_menuitem, a11y_reader_command != NULL);
665+ g_free (value);
666+
667 /* Power menu */
668 if (gtk_widget_get_visible (power_menuitem))
669 {
670@@ -3115,22 +3256,44 @@
671 gtk_widget_show (GTK_WIDGET (login_window));
672 gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
673
674- if (a11y_keyboard_command)
675+ values = g_key_file_get_string_list (config, "greeter", "a11y-states", NULL, NULL);
676+ if (values && *values)
677 {
678- /* If command is onboard, position the application at the bottom-center of the screen */
679- if (g_strcmp0(a11y_keyboard_command[0], "onboard") == 0)
680+ GHashTable *items = g_hash_table_new (g_str_hash, g_str_equal);
681+ g_hash_table_insert (items, "contrast", contrast_menuitem);
682+ g_hash_table_insert (items, "font", font_menuitem);
683+ g_hash_table_insert (items, "keyboard", keyboard_menuitem);
684+ g_hash_table_insert (items, "reader", reader_menuitem);
685+
686+ gpointer item;
687+ gchar **values_iter;
688+ for (values_iter = values; *values_iter; ++values_iter)
689 {
690- gint argp;
691- value = "onboard --xid";
692- g_debug ("a11y keyboard command is now '%s'", value);
693- g_shell_parse_argv (value, &argp, &a11y_keyboard_command, NULL);
694- onboard_window = GTK_WINDOW (gtk_window_new(GTK_WINDOW_TOPLEVEL));
695- gtk_widget_set_size_request (GTK_WIDGET (onboard_window), 605, 205);
696- gtk_window_move (onboard_window, (monitor_geometry.width - 605)/2, monitor_geometry.height - 205);
697+ value = *values_iter;
698+ switch (value[0])
699+ {
700+ case '-':
701+ continue;
702+ case '+':
703+ if (g_hash_table_lookup_extended (items, &value[1], NULL, &item) &&
704+ gtk_widget_get_visible (GTK_WIDGET (item)))
705+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
706+ break;
707+ case '~':
708+ value++;
709+ default:
710+ if (g_hash_table_lookup_extended (items, value, NULL, &item) &&
711+ gtk_widget_get_visible (GTK_WIDGET (item)))
712+ {
713+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
714+ g_key_file_get_boolean (state, "a11y-states", value, NULL));
715+ g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (a11y_menuitem_toggled_cb), g_strdup (value));
716+ }
717+ }
718 }
719+ g_hash_table_unref (items);
720 }
721- gtk_widget_set_sensitive (keyboard_menuitem, a11y_keyboard_command != NULL);
722- gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);
723+ g_strfreev (values);
724
725 /* focus fix (source: unity-greeter) */
726 GdkWindow* root_window = gdk_get_default_root_window ();
727
728=== modified file 'src/lightdm-gtk-greeter.glade'
729--- src/lightdm-gtk-greeter.glade 2014-06-09 16:14:37 +0000
730+++ src/lightdm-gtk-greeter.glade 2014-07-07 12:35:18 +0000
731@@ -108,6 +108,17 @@
732 <signal name="toggled" handler="a11y_keyboard_cb" swapped="no"/>
733 </object>
734 </child>
735+ <child>
736+ <object class="GtkCheckMenuItem" id="reader_menuitem">
737+ <property name="use_action_appearance">False</property>
738+ <property name="visible">True</property>
739+ <property name="can_focus">False</property>
740+ <property name="accel_path">&lt;Login&gt;/a11y/reader</property>
741+ <property name="label" translatable="yes">Screen Reader</property>
742+ <property name="use_underline">True</property>
743+ <signal name="toggled" handler="a11y_reader_cb" swapped="no"/>
744+ </object>
745+ </child>
746 </object>
747 </child>
748 </object>

Subscribers

People subscribed via source and target branches