summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew P. <pan.pav.7c5@gmail.com>2014-08-09 17:18:49 +0300
committerAndrew P. <pan.pav.7c5@gmail.com>2014-08-09 17:18:49 +0300
commita97438ffc3154e71e02797f3cf5409ef4df9d57a (patch)
treed5aeae182f195da718f24e949d7d01aa4559e77c
parentd8ccd45bd6bf07a53bedfc98a1b6a04d8e7d6884 (diff)
parentdc21d736355c97e9289f0e90c2e7e3c704da832a (diff)
downloadlightdm-gtk-greeter-git-a97438ffc3154e71e02797f3cf5409ef4df9d57a.tar.gz
Merge "states-and-orca" branch
-rw-r--r--data/lightdm-gtk-greeter.conf5
-rw-r--r--src/lightdm-gtk-greeter.c496
-rw-r--r--src/lightdm-gtk-greeter.glade11
3 files changed, 343 insertions, 169 deletions
diff --git a/data/lightdm-gtk-greeter.conf b/data/lightdm-gtk-greeter.conf
index 442e84b..762a513 100644
--- a/data/lightdm-gtk-greeter.conf
+++ b/data/lightdm-gtk-greeter.conf
@@ -12,7 +12,9 @@
# 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
# show-clock (true or false)
# clock-format = strftime-format string, e.g. %H:%M
-# keyboard = command to launch on-screen keyboard
+# keyboard = command to launch on-screen keyboard (e.g. onboard)
+# reader = command to launch screen reader (e.g. orca)
+# 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, reader.
# position = main window position: x y
# default-user-image = Image used as default user icon, path or #icon-name
# hide-user-image = true|false, false by default
@@ -32,5 +34,6 @@
#show-clock=
#clock-format=
#keyboard=
+#reader=
#position=
#screensaver-timeout=
diff --git a/src/lightdm-gtk-greeter.c b/src/lightdm-gtk-greeter.c
index 1a7a553..accb323 100644
--- a/src/lightdm-gtk-greeter.c
+++ b/src/lightdm-gtk-greeter.c
@@ -61,8 +61,10 @@
#endif
static LightDMGreeter *greeter;
+
static GKeyFile *state;
static gchar *state_filename;
+static void save_state_file (void);
/* Defaults */
static gchar *default_font_name, *default_theme_name, *default_icon_theme_name;
@@ -73,7 +75,8 @@ static GtkWidget *menubar;
static GtkWidget *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem,
*layout_menuitem, *session_badge;
static GtkWidget *suspend_menuitem, *hibernate_menuitem, *restart_menuitem, *shutdown_menuitem;
-static GtkWidget *keyboard_menuitem, *clock_menuitem, *clock_label, *host_menuitem;
+static GtkWidget *clock_menuitem, *clock_label, *host_menuitem;
+static GtkWidget *contrast_menuitem, *font_menuitem, *keyboard_menuitem, *reader_menuitem;
static GtkMenu *session_menu, *language_menu, *layout_menu;
/* Login Window Widgets */
@@ -86,10 +89,54 @@ static GtkInfoBar *info_bar;
static GtkButton *cancel_button, *login_button;
static gchar *clock_format;
-static gchar **a11y_keyboard_command;
-static GPid a11y_kbd_pid = 0;
-static GError *a11y_keyboard_error;
-static GtkWindow *onboard_window;
+
+typedef struct
+{
+ gint value;
+ /* +0 and -0 */
+ gint sign;
+ /* interpret 'value' as percentage of screen width/height */
+ gboolean percentage;
+ /* -1: left/top, 0: center, +1: right,bottom */
+ gint anchor;
+} DimensionPosition;
+
+typedef struct
+{
+ DimensionPosition x, y;
+} WindowPosition;
+
+/* Function translate user defined coordinates to absolute value */
+static gint get_absolute_position (const DimensionPosition *p, gint screen, gint window);
+static const WindowPosition WINDOW_POS_CENTER = {.x = { 50, +1, TRUE, 0}, .y = { 50, +1, TRUE, 0}};
+static const WindowPosition WINDOW_POS_TOP_LEFT = {.x = { 0, +1, FALSE, -1}, .y = { 0, +1, FALSE, -1}};
+static const WindowPosition ONBOARD_WINDOW_POS = {.x = { 50, +1, TRUE, 0}, .y = { 0, -1, FALSE, +1}};
+static const WindowPosition ONBOARD_WINDOW_SIZE = {.x = {610, 0, FALSE, 0}, .y = {210, 0, FALSE, 0}};
+static WindowPosition main_window_pos;
+static WindowPosition panel_window_pos;
+
+typedef struct
+{
+ gchar **argv;
+ gint argc;
+
+ GPid pid;
+ GtkWidget *menu_item;
+ GtkWidget *widget;
+} MenuCommand;
+
+static MenuCommand *menu_command_parse (const gchar *value, GtkWidget *menu_item);
+static MenuCommand *menu_command_parse_extended (const gchar *value, GtkWidget *menu_item,
+ const gchar *xid_supported, const gchar *xid_arg,
+ const WindowPosition *size);
+static gboolean menu_command_run (MenuCommand *command);
+static gboolean menu_command_stop (MenuCommand *command);
+static void command_terminated_cb (GPid pid, gint status, MenuCommand *command);
+
+static MenuCommand *a11y_keyboard_command;
+static MenuCommand *a11y_reader_command;
+
+static void a11y_menuitem_toggled_cb (GtkCheckMenuItem *item, const gchar* name);
/* Pending Questions */
static GSList *pending_questions = NULL;
@@ -120,27 +167,6 @@ typedef struct
gchar *text;
} PAMConversationMessage;
-typedef struct
-{
- gint value;
- /* +0 and -0 */
- gint sign;
- /* interpret 'value' as percentage of screen width/height */
- gboolean percentage;
- /* -1: left/top, 0: center, +1: right,bottom */
- gint anchor;
-} DimensionPosition;
-
-typedef struct
-{
- DimensionPosition x, y;
-} WindowPosition;
-
-static const WindowPosition WINDOW_POS_CENTER = {.x = {50, +1, TRUE, 0}, .y = {50, +1, TRUE, 0}};
-static const WindowPosition WINDOW_POS_TOP_LEFT = {.x = {0, +1, FALSE, -1}, .y = {0, +1, FALSE, -1}};
-static WindowPosition main_window_pos;
-static WindowPosition panel_window_pos;
-
static GdkPixbuf* default_user_pixbuf = NULL;
static gchar* default_user_icon = "avatar-default";
@@ -201,6 +227,200 @@ key_file_get_boolean_extended (GKeyFile *key_file, const gchar *group_name, cons
}
static void
+save_state_file (void)
+{
+ GError *error = NULL;
+ gsize data_length = 0;
+ gchar *data = g_key_file_to_data (state, &data_length, &error);
+
+ if (error)
+ {
+ g_warning ("Failed to save state file: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ if (data)
+ {
+ g_file_set_contents (state_filename, data, data_length, &error);
+ if (error)
+ {
+ g_warning ("Failed to save state file: %s", error->message);
+ g_clear_error (&error);
+ }
+ g_free (data);
+ }
+}
+
+/* MenuCommand */
+
+static MenuCommand*
+menu_command_parse (const gchar *value, GtkWidget *menu_item)
+{
+ return menu_command_parse_extended (value, menu_item, NULL, NULL, NULL);
+}
+
+static MenuCommand*
+menu_command_parse_extended (const gchar *value, GtkWidget *menu_item,
+ const gchar *xid_supported, const gchar *xid_arg,
+ const WindowPosition *size)
+{
+ if (!value)
+ return NULL;
+
+ GError *error = NULL;
+ gchar **argv;
+ gint argc = 0;
+
+ if (!g_shell_parse_argv (value, &argc, &argv, &error))
+ {
+ if (error)
+ g_warning ("Failed to parse command line: %s", error->message);
+ g_clear_error (&error);
+ return NULL;
+ }
+
+ MenuCommand *command = g_new0 (MenuCommand, 1);
+ command->menu_item = menu_item;
+ command->argc = argc;
+ command->argv = argv;
+
+ if (g_strcmp0 (argv[0], xid_supported) == 0)
+ {
+ gboolean have_xid_arg = FALSE;
+ gint i;
+ for (i = 1; i < argc; ++i)
+ if (g_strcmp0 (argv[i], xid_arg) == 0)
+ {
+ have_xid_arg = TRUE;
+ break;
+ }
+ if (!have_xid_arg)
+ {
+ gchar *new_value = g_strdup_printf ("%s %s", value, xid_arg);
+
+ if (g_shell_parse_argv (new_value, &argc, &argv, &error))
+ {
+ g_strfreev (command->argv);
+ command->argc = argc;
+ command->argv = argv;
+ have_xid_arg = TRUE;
+ }
+ else
+ {
+ if (error)
+ g_warning ("Failed to parse command line: %s", error->message);
+ g_clear_error (&error);
+ }
+ g_free (new_value);
+ }
+
+ if (have_xid_arg)
+ {
+ GdkRectangle screen;
+ command->widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
+ /* must be replaced with background->active_monitor */
+ gdk_screen_get_primary_monitor (gdk_screen_get_default ()),
+ &screen);
+ gtk_widget_set_size_request (command->widget,
+ get_absolute_position (&size->x, screen.width, 0),
+ get_absolute_position (&size->y, screen.height, 0));
+ }
+ }
+ return command;
+}
+
+static gboolean
+menu_command_run (MenuCommand *command)
+{
+ g_return_val_if_fail (command && g_strv_length (command->argv), FALSE);
+
+ GError *error = NULL;
+ gboolean spawned = FALSE;
+ if (command->widget)
+ {
+ GtkSocket* socket = NULL;
+ gint out_fd = 0;
+
+ if (g_spawn_async_with_pipes (NULL, command->argv, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, &command->pid, NULL, &out_fd, NULL, &error))
+ {
+ gchar* text = NULL;
+ GIOChannel* out_channel = g_io_channel_unix_new (out_fd);
+ if (g_io_channel_read_line (out_channel, &text, NULL, NULL, &error) == G_IO_STATUS_NORMAL)
+ {
+ gchar* end_ptr = NULL;
+
+ text = g_strstrip (text);
+ gint id = g_ascii_strtoll (text, &end_ptr, 0);
+
+ if (id != 0 && end_ptr > text)
+ {
+ socket = GTK_SOCKET (gtk_socket_new ());
+ gtk_container_add (GTK_CONTAINER (command->widget), GTK_WIDGET (socket));
+ gtk_socket_add_id (socket, id);
+ gtk_widget_show_all (GTK_WIDGET (command->widget));
+ spawned = TRUE;
+ }
+ else
+ g_warning ("Failed to get '%s' socket: unrecognized output", command->argv[0]);
+
+ g_free(text);
+ }
+ }
+ }
+ else
+ {
+ spawned = g_spawn_async (NULL, command->argv, NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, &command->pid, &error);
+ if (spawned)
+ g_child_watch_add (command->pid, (GChildWatchFunc)command_terminated_cb, command);
+ }
+
+ if(!spawned)
+ {
+ if (error)
+ g_warning ("Command spawning error: '%s'", error->message);
+ command->pid = 0;
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE);
+ }
+ g_clear_error(&error);
+ return spawned;
+}
+
+static gboolean
+menu_command_stop (MenuCommand *command)
+{
+ g_return_val_if_fail (command, FALSE);
+
+ if (command->pid)
+ {
+ kill (command->pid, SIGTERM);
+ g_spawn_close_pid (command->pid);
+ command->pid = 0;
+ if (command->menu_item)
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE);
+ if (command->widget)
+ gtk_widget_hide (command->widget);
+ }
+ return TRUE;
+}
+
+static void
+command_terminated_cb (GPid pid, gint status, MenuCommand *command)
+{
+ menu_command_stop (command);
+}
+
+static void
+a11y_menuitem_toggled_cb (GtkCheckMenuItem *item, const gchar* name)
+{
+ g_key_file_set_boolean (state, "a11y-states", name, gtk_check_menu_item_get_active (item));
+ save_state_file ();
+}
+
+static void
pam_message_finalize (PAMConversationMessage *message)
{
g_free (message->text);
@@ -858,6 +1078,7 @@ set_user_image (const gchar *username)
if (username)
user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
+
if (user)
{
path = lightdm_user_get_image (user);
@@ -956,7 +1177,7 @@ cairo_region_from_rectangle (gint width, gint height, gint radius)
region = gdk_region_rectangle (&rect);
- while(x >= y)
+ while (x >= y)
{
rect.x = -x + radius;
@@ -971,12 +1192,12 @@ cairo_region_from_rectangle (gint width, gint height, gint radius)
rect.width = y - radius + width - rect.x;
rect.height = x - radius + height - rect.y;
- gdk_region_union_with_rect(region, &rect);
+ gdk_region_union_with_rect (region, &rect);
y++;
radiusError += yChange;
yChange += 2;
- if(((radiusError << 1) + xChange) > 0)
+ if (((radiusError << 1) + xChange) > 0)
{
x--;
radiusError += xChange;
@@ -994,9 +1215,10 @@ login_window_size_allocate (GtkWidget *widget, GdkRectangle *allocation, gpointe
GdkWindow *window = gtk_widget_get_window (widget);
if (window_region)
- gdk_region_destroy(window_region);
+ gdk_region_destroy (window_region);
window_region = cairo_region_from_rectangle (allocation->width, allocation->height, radius);
- if (window) {
+ if (window)
+ {
gdk_window_shape_combine_region(window, window_region, 0, 0);
gdk_window_input_shape_combine_region(window, window_region, 0, 0);
}
@@ -1008,10 +1230,6 @@ login_window_size_allocate (GtkWidget *widget, GdkRectangle *allocation, gpointe
static void
start_authentication (const gchar *username)
{
- gchar *data;
- gsize data_length;
- GError *error = NULL;
-
cancelling = FALSE;
prompted = FALSE;
password_prompted = FALSE;
@@ -1024,18 +1242,7 @@ start_authentication (const gchar *username)
}
g_key_file_set_value (state, "greeter", "last-user", username);
- data = g_key_file_to_data (state, &data_length, &error);
- if (error)
- g_warning ("Failed to save state file: %s", error->message);
- g_clear_error (&error);
- if (data)
- {
- g_file_set_contents (state_filename, data, data_length, &error);
- if (error)
- g_warning ("Failed to save state file: %s", error->message);
- g_clear_error (&error);
- }
- g_free (data);
+ save_state_file ();
if (g_strcmp0 (username, "*other") == 0)
{
@@ -1118,9 +1325,6 @@ start_session (void)
{
gchar *language;
gchar *session;
- gchar *data;
- gsize data_length;
- GError *error = NULL;
language = get_language ();
if (language)
@@ -1131,21 +1335,7 @@ start_session (void)
/* Remember last choice */
g_key_file_set_value (state, "greeter", "last-session", session);
-
- greeter_background_save_xroot (greeter_background);
-
- data = g_key_file_to_data (state, &data_length, &error);
- if (error)
- g_warning ("Failed to save state file: %s", error->message);
- g_clear_error (&error);
- if (data)
- {
- g_file_set_contents (state_filename, data, data_length, &error);
- if (error)
- g_warning ("Failed to save state file: %s", error->message);
- g_clear_error (&error);
- }
- g_free (data);
+ save_state_file ();
if (!lightdm_greeter_start_session_sync (greeter, session, NULL))
{
@@ -1843,82 +2033,26 @@ a11y_contrast_cb (GtkCheckMenuItem *item)
}
}
-static void
-keyboard_terminated_cb (GPid pid, gint status, gpointer user_data)
+void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data);
+G_MODULE_EXPORT
+void
+a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data)
{
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (keyboard_menuitem), FALSE);
+ if (gtk_check_menu_item_get_active (item))
+ menu_command_run (a11y_keyboard_command);
+ else
+ menu_command_stop (a11y_keyboard_command);
}
-void a11y_keyboard_cb (GtkCheckMenuItem *item);
+void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data);
G_MODULE_EXPORT
void
-a11y_keyboard_cb (GtkCheckMenuItem *item)
+a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data)
{
if (gtk_check_menu_item_get_active (item))
- {
- gboolean spawned = FALSE;
- if (onboard_window)
- {
- GtkSocket* socket = NULL;
- gint out_fd = 0;
-
- if (g_spawn_async_with_pipes (NULL, a11y_keyboard_command, NULL, G_SPAWN_SEARCH_PATH,
- NULL, NULL, &a11y_kbd_pid, NULL, &out_fd, NULL,
- &a11y_keyboard_error))
- {
- gchar* text = NULL;
- GIOChannel* out_channel = g_io_channel_unix_new (out_fd);
- if (g_io_channel_read_line(out_channel, &text, NULL, NULL, &a11y_keyboard_error) == G_IO_STATUS_NORMAL)
- {
- gchar* end_ptr = NULL;
-
- text = g_strstrip (text);
- gint id = g_ascii_strtoll (text, &end_ptr, 0);
-
- if (id != 0 && end_ptr > text)
- {
- socket = GTK_SOCKET (gtk_socket_new ());
- gtk_container_add (GTK_CONTAINER (onboard_window), GTK_WIDGET (socket));
- gtk_socket_add_id (socket, id);
- gtk_widget_show_all (GTK_WIDGET (onboard_window));
- spawned = TRUE;
- }
- else
- g_debug ("onboard keyboard command error : 'unrecognized output'");
-
- g_free(text);
- }
- }
- }
- else
- {
- spawned = g_spawn_async (NULL, a11y_keyboard_command, NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL, &a11y_kbd_pid, &a11y_keyboard_error);
- if (spawned)
- g_child_watch_add (a11y_kbd_pid, keyboard_terminated_cb, NULL);
- }
-
- if(!spawned)
- {
- if (a11y_keyboard_error)
- g_debug ("a11y keyboard command error : '%s'", a11y_keyboard_error->message);
- a11y_kbd_pid = 0;
- g_clear_error(&a11y_keyboard_error);
- gtk_check_menu_item_set_active (item, FALSE);
- }
- }
+ menu_command_run (a11y_reader_command);
else
- {
- if (a11y_kbd_pid != 0)
- {
- kill (a11y_kbd_pid, SIGTERM);
- g_spawn_close_pid (a11y_kbd_pid);
- a11y_kbd_pid = 0;
- if (onboard_window)
- gtk_widget_hide (GTK_WIDGET(onboard_window));
- }
- }
+ menu_command_stop (a11y_reader_command);
}
static void
@@ -2063,7 +2197,8 @@ static GdkFilterReturn
focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
{
XEvent* xevent = (XEvent*)gxevent;
- GdkWindow* keyboard_win = onboard_window ? gtk_widget_get_window (GTK_WIDGET (onboard_window)) : NULL;
+ GdkWindow* keyboard_win = a11y_keyboard_command && a11y_keyboard_command->widget ?
+ gtk_widget_get_window (GTK_WIDGET (a11y_keyboard_command->widget)) : NULL;
if (xevent->type == MapNotify)
{
Window xwin = xevent->xmap.window;
@@ -2086,11 +2221,8 @@ focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
{
gdk_window_focus (win, GDK_CURRENT_TIME);
/* Make sure to keep keyboard above */
- if (onboard_window)
- {
- if (keyboard_win)
- gdk_window_raise (keyboard_win);
- }
+ if (keyboard_win)
+ gdk_window_raise (keyboard_win);
}
}
else if (xevent->type == UnmapNotify)
@@ -2103,11 +2235,8 @@ focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
{
gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
/* Make sure to keep keyboard above */
- if (onboard_window)
- {
- if (keyboard_win)
- gdk_window_raise (keyboard_win);
- }
+ if (keyboard_win)
+ gdk_window_raise (keyboard_win);
}
}
return GDK_FILTER_CONTINUE;
@@ -2291,12 +2420,11 @@ int
main (int argc, char **argv)
{
GKeyFile *config;
- GdkRectangle monitor_geometry;
GtkBuilder *builder;
const GList *items, *item;
GtkCellRenderer *renderer;
GtkWidget *image, *infobar_compat, *content_area;
- gchar *value, *state_dir;
+ gchar *value, **values, *state_dir;
#if GTK_CHECK_VERSION (3, 0, 0)
GtkIconTheme *icon_theme;
GtkCssProvider *css_provider;
@@ -2427,15 +2555,7 @@ main (int argc, char **argv)
if (value)
g_object_set (gtk_settings_get_default (), "gtk-xft-rgba", value, NULL);
g_free (value);
-
- /* Get a11y on screen keyboard command*/
- gint argp;
- value = g_key_file_get_value (config, "greeter", "keyboard", NULL);
- g_debug ("a11y keyboard command is '%s'", value);
- /* Set NULL to blank to avoid warnings */
- if (!value) { value = g_strdup(""); }
- g_shell_parse_argv (value, &argp, &a11y_keyboard_command, NULL);
- g_free (value);
+
builder = gtk_builder_new ();
if (!gtk_builder_add_from_string (builder, lightdm_gtk_greeter_ui,
@@ -2506,16 +2626,20 @@ main (int argc, char **argv)
language_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "language_menuitem"));
language_menu = GTK_MENU(gtk_builder_get_object (builder, "language_menu"));
a11y_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "a11y_menuitem"));
+ contrast_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "high_contrast_menuitem"));
+ font_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "large_font_menuitem"));
+ keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
+ reader_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "reader_menuitem"));
power_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "power_menuitem"));
layout_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "layout_menuitem"));
layout_menu = GTK_MENU(gtk_builder_get_object (builder, "layout_menu"));
- keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
clock_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "clock_menuitem"));
host_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "host_menuitem"));
gtk_accel_map_add_entry ("<Login>/a11y/font", GDK_KEY_F1, 0);
gtk_accel_map_add_entry ("<Login>/a11y/contrast", GDK_KEY_F2, 0);
gtk_accel_map_add_entry ("<Login>/a11y/keyboard", GDK_KEY_F3, 0);
+ gtk_accel_map_add_entry ("<Login>/a11y/reader", GDK_KEY_F4, 0);
gtk_accel_map_add_entry ("<Login>/power/shutdown", GDK_KEY_F4, GDK_MOD1_MASK);
#ifdef START_INDICATOR_SERVICES
@@ -2635,6 +2759,20 @@ main (int argc, char **argv)
gtk_container_add (GTK_CONTAINER (a11y_menuitem), image);
}
+ value = g_key_file_get_value (config, "greeter", "keyboard", NULL);
+ a11y_keyboard_command = menu_command_parse_extended (value, keyboard_menuitem, "onboard", "--xid",
+ &ONBOARD_WINDOW_SIZE);
+ g_free (value);
+
+ gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);
+ if (a11y_keyboard_command)
+ g_signal_connect (a11y_keyboard_command->widget, "size-allocate", G_CALLBACK (center_window), (gpointer)&ONBOARD_WINDOW_POS);
+
+ value = g_key_file_get_value (config, "greeter", "reader", NULL);
+ a11y_reader_command = menu_command_parse (value, reader_menuitem);
+ gtk_widget_set_visible (reader_menuitem, a11y_reader_command != NULL);
+ g_free (value);
+
/* Power menu */
if (gtk_widget_get_visible (power_menuitem))
{
@@ -2814,22 +2952,44 @@ main (int argc, char **argv)
g_signal_connect (GTK_WIDGET (login_window), "size-allocate", G_CALLBACK (center_window), &main_window_pos);
gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
- if (a11y_keyboard_command)
+ values = g_key_file_get_string_list (config, "greeter", "a11y-states", NULL, NULL);
+ if (values && *values)
{
- /* If command is onboard, position the application at the bottom-center of the screen */
- if (g_strcmp0(a11y_keyboard_command[0], "onboard") == 0)
+ GHashTable *items = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (items, "contrast", contrast_menuitem);
+ g_hash_table_insert (items, "font", font_menuitem);
+ g_hash_table_insert (items, "keyboard", keyboard_menuitem);
+ g_hash_table_insert (items, "reader", reader_menuitem);
+
+ gpointer item;
+ gchar **values_iter;
+ for (values_iter = values; *values_iter; ++values_iter)
{
- gint argp;
- value = "onboard --xid";
- g_debug ("a11y keyboard command is now '%s'", value);
- g_shell_parse_argv (value, &argp, &a11y_keyboard_command, NULL);
- onboard_window = GTK_WINDOW (gtk_window_new(GTK_WINDOW_TOPLEVEL));
- gtk_widget_set_size_request (GTK_WIDGET (onboard_window), 605, 205);
- gtk_window_move (onboard_window, (monitor_geometry.width - 605)/2, monitor_geometry.height - 205);
+ value = *values_iter;
+ switch (value[0])
+ {
+ case '-':
+ continue;
+ case '+':
+ if (g_hash_table_lookup_extended (items, &value[1], NULL, &item) &&
+ gtk_widget_get_visible (GTK_WIDGET (item)))
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
+ break;
+ case '~':
+ value++;
+ default:
+ if (g_hash_table_lookup_extended (items, value, NULL, &item) &&
+ gtk_widget_get_visible (GTK_WIDGET (item)))
+ {
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
+ g_key_file_get_boolean (state, "a11y-states", value, NULL));
+ g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (a11y_menuitem_toggled_cb), g_strdup (value));
+ }
+ }
}
+ g_hash_table_unref (items);
}
- gtk_widget_set_sensitive (keyboard_menuitem, a11y_keyboard_command != NULL);
- gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);
+ g_strfreev (values);
/* focus fix (source: unity-greeter) */
GdkWindow* root_window = gdk_get_default_root_window ();
diff --git a/src/lightdm-gtk-greeter.glade b/src/lightdm-gtk-greeter.glade
index 5f12713..2c174d8 100644
--- a/src/lightdm-gtk-greeter.glade
+++ b/src/lightdm-gtk-greeter.glade
@@ -108,6 +108,17 @@
<signal name="toggled" handler="a11y_keyboard_cb" swapped="no"/>
</object>
</child>
+ <child>
+ <object class="GtkCheckMenuItem" id="reader_menuitem">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="accel_path">&lt;Login&gt;/a11y/reader</property>
+ <property name="label" translatable="yes">Screen Reader</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="a11y_reader_cb" swapped="no"/>
+ </object>
+ </child>
</object>
</child>
</object>