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-host.h"
38 #include "gdm-host-chooser-dialog.h"
39 
40 #define ACCESSIBILITY_KEY         "/desktop/gnome/interface/accessibility"
41 
42 static Atom AT_SPI_IOR;
43 
44 
45 static gboolean
assistive_registry_launch(void)46 assistive_registry_launch (void)
47 {
48         GPid        pid;
49         GError     *error;
50         const char *command;
51         char      **argv;
52         gboolean    res;
53 
54         command = AT_SPI_REGISTRYD_DIR "/at-spi2-registryd";
55 
56         argv = NULL;
57         error = NULL;
58         res = g_shell_parse_argv (command, NULL, &argv, &error);
59         if (! res) {
60                 g_warning ("Unable to parse command: %s", error->message);
61                 return FALSE;
62         }
63 
64         error = NULL;
65         res = g_spawn_async (NULL,
66                              argv,
67                              NULL,
68                              G_SPAWN_SEARCH_PATH
69                              | G_SPAWN_STDOUT_TO_DEV_NULL
70                              | G_SPAWN_STDERR_TO_DEV_NULL,
71                              NULL,
72                              NULL,
73                              &pid,
74                              &error);
75         g_strfreev (argv);
76 
77         if (! res) {
78                 g_warning ("Unable to run command %s: %s", command, error->message);
79                 return FALSE;
80         }
81 
82         if (kill (pid, 0) < 0) {
83                 g_warning ("at-spi-registryd not running");
84                 return FALSE;
85         }
86 
87         return TRUE;
88 }
89 
90 static GdkFilterReturn
filter_watch(GdkXEvent * xevent,GdkEvent * event,gpointer data)91 filter_watch (GdkXEvent *xevent,
92               GdkEvent  *event,
93               gpointer   data)
94 {
95         XEvent *xev = (XEvent *)xevent;
96 
97         if (xev->xany.type == PropertyNotify
98             && xev->xproperty.atom == AT_SPI_IOR) {
99                 gtk_main_quit ();
100 
101                 return GDK_FILTER_REMOVE;
102         }
103 
104         return GDK_FILTER_CONTINUE;
105 }
106 
107 static gboolean
filter_timeout(gpointer data)108 filter_timeout (gpointer data)
109 {
110         g_warning ("The accessibility registry was not found.");
111 
112         gtk_main_quit ();
113 
114         return FALSE;
115 }
116 
117 static void
assistive_registry_start(void)118 assistive_registry_start (void)
119 {
120         GdkWindow *root;
121         guint      tid;
122 
123         root = gdk_get_default_root_window ();
124 
125         if ( ! AT_SPI_IOR) {
126                 AT_SPI_IOR = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "AT_SPI_IOR", False);
127         }
128 
129         gdk_window_set_events (root,  GDK_PROPERTY_CHANGE_MASK);
130 
131         if ( ! assistive_registry_launch ()) {
132                 g_warning ("The accessibility registry could not be started.");
133                 return;
134         }
135 
136         gdk_window_add_filter (root, filter_watch, NULL);
137         tid = g_timeout_add_seconds (5, filter_timeout, NULL);
138 
139         gtk_main ();
140 
141         gdk_window_remove_filter (root, filter_watch, NULL);
142         g_source_remove (tid);
143 }
144 
145 static void
at_set_gtk_modules(void)146 at_set_gtk_modules (void)
147 {
148         GSList     *modules_list;
149         GSList     *l;
150         const char *old;
151         char      **modules;
152         gboolean    found_gail;
153         gboolean    found_atk_bridge;
154         int         n;
155 
156         n = 0;
157         modules_list = NULL;
158         found_gail = FALSE;
159         found_atk_bridge = FALSE;
160 
161         if ((old = g_getenv ("GTK_MODULES")) != NULL) {
162                 modules = g_strsplit (old, ":", -1);
163                 for (n = 0; modules[n]; n++) {
164                         if (!strcmp (modules[n], "gail")) {
165                                 found_gail = TRUE;
166                         } else if (!strcmp (modules[n], "atk-bridge")) {
167                                 found_atk_bridge = TRUE;
168                         }
169 
170                         modules_list = g_slist_prepend (modules_list, modules[n]);
171                         modules[n] = NULL;
172                 }
173                 g_free (modules);
174         }
175 
176         if (!found_gail) {
177                 modules_list = g_slist_prepend (modules_list, "gail");
178                 ++n;
179         }
180 
181         if (!found_atk_bridge) {
182                 modules_list = g_slist_prepend (modules_list, "atk-bridge");
183                 ++n;
184         }
185 
186         modules = g_new (char *, n + 1);
187         modules[n--] = NULL;
188         for (l = modules_list; l; l = l->next) {
189                 modules[n--] = g_strdup (l->data);
190         }
191 
192         g_setenv ("GTK_MODULES", g_strjoinv (":", modules), TRUE);
193         g_strfreev (modules);
194         g_slist_free (modules_list);
195 }
196 
197 static void
load_a11y(void)198 load_a11y (void)
199 {
200         assistive_registry_start ();
201         at_set_gtk_modules ();
202 }
203 
204 int
main(int argc,char * argv[])205 main (int argc, char *argv[])
206 {
207         GtkWidget        *chooser;
208 
209         bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
210         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
211         textdomain (GETTEXT_PACKAGE);
212 
213         setlocale (LC_ALL, "");
214 
215         gdm_log_init ();
216         gdm_log_set_debug (TRUE);
217 
218         g_debug ("Chooser for display %s xauthority:%s",
219                  g_getenv ("DISPLAY"),
220                  g_getenv ("XAUTHORITY"));
221 
222         gdk_init (&argc, &argv);
223 
224         load_a11y ();
225 
226         gtk_init (&argc, &argv);
227 
228         chooser = gdm_host_chooser_dialog_new (GDM_CHOOSER_HOST_KIND_MASK_ALL);
229         gtk_widget_set_size_request (chooser, 480, 600);
230 
231         if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_OK) {
232                 GdmChooserHost *host;
233 
234                 host = gdm_host_chooser_dialog_get_host (GDM_HOST_CHOOSER_DIALOG (chooser));
235                 if (host != NULL) {
236                         char *hostname;
237                         /* FIXME: handle different host types here? */
238 
239                         hostname = NULL;
240                         gdm_address_get_hostname (gdm_chooser_host_get_address (host), &hostname);
241                         /* FIXME: fall back to numerical address? */
242                         if (hostname != NULL) {
243                                 g_print ("hostname: %s\n", hostname);
244                                 g_free (hostname);
245                         }
246                 }
247         }
248 
249         gtk_widget_destroy (chooser);
250 
251         return 0;
252 }
253