1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <libintl.h>
24 #include <locale.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <errno.h>
29
30 #include <glib/gi18n.h>
31 #include <gdk/gdkx.h>
32 #include <gtk/gtk.h>
33
34 #include "gdm-common.h"
35 #include "gdm-log.h"
36
37 #include "gdm-chooser-session.h"
38
39 #define ACCESSIBILITY_KEY "/desktop/gnome/interface/accessibility"
40
41 static Atom AT_SPI_IOR;
42
43
44 static gboolean
assistive_registry_launch(void)45 assistive_registry_launch (void)
46 {
47 GPid pid;
48 GError *error;
49 const char *command;
50 char **argv;
51 gboolean res;
52
53 command = AT_SPI_REGISTRYD_DIR "/at-spi2-registryd";
54
55 argv = NULL;
56 error = NULL;
57 res = g_shell_parse_argv (command, NULL, &argv, &error);
58 if (! res) {
59 g_warning ("Unable to parse command: %s", error->message);
60 return FALSE;
61 }
62
63 error = NULL;
64 res = g_spawn_async (NULL,
65 argv,
66 NULL,
67 G_SPAWN_SEARCH_PATH
68 | G_SPAWN_STDOUT_TO_DEV_NULL
69 | G_SPAWN_STDERR_TO_DEV_NULL,
70 NULL,
71 NULL,
72 &pid,
73 &error);
74 g_strfreev (argv);
75
76 if (! res) {
77 g_warning ("Unable to run command %s: %s", command, error->message);
78 return FALSE;
79 }
80
81 if (kill (pid, 0) < 0) {
82 g_warning ("at-spi-registryd not running");
83 return FALSE;
84 }
85
86 return TRUE;
87 }
88
89 static GdkFilterReturn
filter_watch(GdkXEvent * xevent,GdkEvent * event,gpointer data)90 filter_watch (GdkXEvent *xevent,
91 GdkEvent *event,
92 gpointer data)
93 {
94 XEvent *xev = (XEvent *)xevent;
95
96 if (xev->xany.type == PropertyNotify
97 && xev->xproperty.atom == AT_SPI_IOR) {
98 gtk_main_quit ();
99
100 return GDK_FILTER_REMOVE;
101 }
102
103 return GDK_FILTER_CONTINUE;
104 }
105
106 static gboolean
filter_timeout(gpointer data)107 filter_timeout (gpointer data)
108 {
109 g_warning ("The accessibility registry was not found.");
110
111 gtk_main_quit ();
112
113 return FALSE;
114 }
115
116 static void
assistive_registry_start(void)117 assistive_registry_start (void)
118 {
119 GdkWindow *root;
120 guint tid;
121
122 root = gdk_get_default_root_window ();
123
124 if ( ! AT_SPI_IOR) {
125 AT_SPI_IOR = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "AT_SPI_IOR", False);
126 }
127
128 gdk_window_set_events (root, GDK_PROPERTY_CHANGE_MASK);
129
130 if ( ! assistive_registry_launch ()) {
131 g_warning ("The accessibility registry could not be started.");
132 return;
133 }
134
135 gdk_window_add_filter (root, filter_watch, NULL);
136 tid = g_timeout_add_seconds (5, filter_timeout, NULL);
137
138 gtk_main ();
139
140 gdk_window_remove_filter (root, filter_watch, NULL);
141 g_source_remove (tid);
142 }
143
144 static void
at_set_gtk_modules(void)145 at_set_gtk_modules (void)
146 {
147 GSList *modules_list;
148 GSList *l;
149 const char *old;
150 char **modules;
151 gboolean found_gail;
152 gboolean found_atk_bridge;
153 int n;
154
155 n = 0;
156 modules_list = NULL;
157 found_gail = FALSE;
158 found_atk_bridge = FALSE;
159
160 if ((old = g_getenv ("GTK_MODULES")) != NULL) {
161 modules = g_strsplit (old, ":", -1);
162 for (n = 0; modules[n]; n++) {
163 if (!strcmp (modules[n], "gail")) {
164 found_gail = TRUE;
165 } else if (!strcmp (modules[n], "atk-bridge")) {
166 found_atk_bridge = TRUE;
167 }
168
169 modules_list = g_slist_prepend (modules_list, modules[n]);
170 modules[n] = NULL;
171 }
172 g_free (modules);
173 }
174
175 if (!found_gail) {
176 modules_list = g_slist_prepend (modules_list, "gail");
177 ++n;
178 }
179
180 if (!found_atk_bridge) {
181 modules_list = g_slist_prepend (modules_list, "atk-bridge");
182 ++n;
183 }
184
185 modules = g_new (char *, n + 1);
186 modules[n--] = NULL;
187 for (l = modules_list; l; l = l->next) {
188 modules[n--] = g_strdup (l->data);
189 }
190
191 g_setenv ("GTK_MODULES", g_strjoinv (":", modules), TRUE);
192 g_strfreev (modules);
193 g_slist_free (modules_list);
194 }
195
196 static void
load_a11y(void)197 load_a11y (void)
198 {
199 assistive_registry_start ();
200 at_set_gtk_modules ();
201 }
202
203 int
main(int argc,char * argv[])204 main (int argc, char *argv[])
205 {
206 GdmChooserSession *session;
207 gboolean res;
208 GError *error;
209
210 bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
211 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
212 textdomain (GETTEXT_PACKAGE);
213
214 setlocale (LC_ALL, "");
215
216 gdm_log_init ();
217 gdm_log_set_debug (TRUE);
218
219 g_debug ("Chooser for display %s xauthority:%s",
220 g_getenv ("DISPLAY"),
221 g_getenv ("XAUTHORITY"));
222
223 gdk_init (&argc, &argv);
224
225 load_a11y ();
226
227 gtk_init (&argc, &argv);
228
229 session = gdm_chooser_session_new ();
230 if (session == NULL) {
231 g_critical ("Unable to create chooser session");
232 exit (EXIT_FAILURE);
233 }
234
235 error = NULL;
236 res = gdm_chooser_session_start (session, &error);
237 if (! res) {
238 g_warning ("Unable to start chooser session: %s", error->message);
239 g_error_free (error);
240 exit (EXIT_FAILURE);
241 }
242
243 gtk_main ();
244
245 if (session != NULL) {
246 g_object_unref (session);
247 }
248
249 return 0;
250 }
251