1 /* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
3 * at-spi-bus-launcher: Manage the a11y bus as a child process
5 * Copyright 2011-2018 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
29 #include <sys/prctl.h>
30 #include <sys/socket.h>
40 #include <X11/Xatom.h>
43 #include <systemd/sd-login.h>
48 A11Y_BUS_STATE_IDLE = 0,
49 A11Y_BUS_STATE_READING_ADDRESS,
50 A11Y_BUS_STATE_RUNNING,
56 gboolean launch_immediately;
57 gboolean a11y_enabled;
58 gboolean screen_reader_enabled;
59 GDBusConnection *session_bus;
60 GSettings *a11y_schema;
61 GSettings *interface_schema;
64 GDBusProxy *client_proxy;
67 /* -1 == error, 0 == pending, > 0 == running */
70 char *a11y_bus_address;
72 gboolean x11_prop_set;
76 char *a11y_launch_error_message;
80 static A11yBusLauncher *_global_app = NULL;
82 static const gchar introspection_xml[] =
84 " <interface name='org.a11y.Bus'>"
85 " <method name='GetAddress'>"
86 " <arg type='s' name='address' direction='out'/>"
89 " <interface name='org.a11y.Status'>"
90 " <property name='IsEnabled' type='b' access='readwrite'/>"
91 " <property name='ScreenReaderEnabled' type='b' access='readwrite'/>"
94 static GDBusNodeInfo *introspection_data = NULL;
97 respond_to_end_session (GDBusProxy *proxy)
101 parameters = g_variant_new ("(bs)", TRUE, "");
103 g_dbus_proxy_call (proxy,
104 "EndSessionResponse", parameters,
105 G_DBUS_CALL_FLAGS_NONE,
106 -1, NULL, NULL, NULL);
110 g_signal_cb (GDBusProxy *proxy,
113 GVariant *parameters,
116 A11yBusLauncher *app = user_data;
118 if (g_strcmp0 (signal_name, "QueryEndSession") == 0)
119 respond_to_end_session (proxy);
120 else if (g_strcmp0 (signal_name, "EndSession") == 0)
121 respond_to_end_session (proxy);
122 else if (g_strcmp0 (signal_name, "Stop") == 0)
123 g_main_loop_quit (app->loop);
127 client_proxy_ready_cb (GObject *source_object,
131 A11yBusLauncher *app = user_data;
132 GError *error = NULL;
134 app->client_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
138 g_warning ("Failed to get a client proxy: %s", error->message);
139 g_error_free (error);
144 g_signal_connect (app->client_proxy, "g-signal",
145 G_CALLBACK (g_signal_cb), app);
149 client_registered (GObject *source,
150 GAsyncResult *result,
153 A11yBusLauncher *app = user_data;
154 GError *error = NULL;
157 GDBusProxyFlags flags;
159 variant = g_dbus_proxy_call_finish (app->sm_proxy, result, &error);
164 g_warning ("Failed to register client: %s", error->message);
165 g_error_free (error);
170 g_variant_get (variant, "(o)", &object_path);
171 g_variant_unref (variant);
173 flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES;
174 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, flags, NULL,
175 "org.gnome.SessionManager", object_path,
176 "org.gnome.SessionManager.ClientPrivate",
177 NULL, client_proxy_ready_cb, app);
179 g_free (object_path);
181 g_clear_object (&app->sm_proxy);
185 register_client (A11yBusLauncher *app)
187 GDBusProxyFlags flags;
190 const gchar *autostart_id;
191 gchar *client_startup_id;
192 GVariant *parameters;
194 flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
195 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
198 app->sm_proxy = g_dbus_proxy_new_sync (app->session_bus, flags, NULL,
199 "org.gnome.SessionManager",
200 "/org/gnome/SessionManager",
201 "org.gnome.SessionManager",
206 g_warning ("Failed to get session manager proxy: %s", error->message);
207 g_error_free (error);
212 app_id = "at-spi-bus-launcher";
213 autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
215 if (autostart_id != NULL)
217 client_startup_id = g_strdup (autostart_id);
218 g_unsetenv ("DESKTOP_AUTOSTART_ID");
222 client_startup_id = g_strdup ("");
225 parameters = g_variant_new ("(ss)", app_id, client_startup_id);
226 g_free (client_startup_id);
229 g_dbus_proxy_call (app->sm_proxy,
230 "RegisterClient", parameters,
231 G_DBUS_CALL_FLAGS_NONE,
232 G_MAXINT, NULL, client_registered, app);
237 name_appeared_handler (GDBusConnection *connection,
239 const gchar *name_owner,
242 A11yBusLauncher *app = user_data;
244 register_client (app);
248 * unix_read_all_fd_to_string:
250 * Read all data from a file descriptor to a C string buffer.
253 unix_read_all_fd_to_string (int fd,
258 g_assert (max_bytes > 1);
261 max_bytes -= 1; /* allow space for nul terminator */
263 while (max_bytes > 1)
268 bytes_read = read (fd, buf, max_bytes);
274 else if (bytes_read > 0)
277 max_bytes -= bytes_read;
279 else if (errno == EINTR)
285 int err_save = errno;
286 *error_msg = g_strdup_printf ("Failed to read data from accessibility bus: %s", g_strerror (err_save));
296 on_bus_exited (GPid pid,
300 A11yBusLauncher *app = data;
302 app->a11y_bus_pid = -1;
303 app->state = A11Y_BUS_STATE_ERROR;
304 if (app->a11y_launch_error_message == NULL)
306 if (WIFEXITED (status))
307 app->a11y_launch_error_message = g_strdup_printf ("Bus exited with code %d", WEXITSTATUS (status));
308 else if (WIFSIGNALED (status))
309 app->a11y_launch_error_message = g_strdup_printf ("Bus killed by signal %d", WTERMSIG (status));
310 else if (WIFSTOPPED (status))
311 app->a11y_launch_error_message = g_strdup_printf ("Bus stopped by signal %d", WSTOPSIG (status));
313 g_main_loop_quit (app->loop);
318 ensure_a11y_bus_daemon (A11yBusLauncher *app, char *config_path)
322 if (app->socket_name)
324 gchar *escaped_address = g_dbus_address_escape_value (app->socket_name);
325 address_param = g_strconcat ("--address=unix:path=", escaped_address, NULL);
326 g_free (escaped_address);
330 address_param = NULL;
333 if (pipe (app->pipefd) < 0)
334 g_error ("Failed to create pipe: %s", strerror (errno));
336 char *print_address_fd_param = g_strdup_printf ("%d", app->pipefd[1]);
338 char *argv[] = { DBUS_DAEMON, config_path, "--nofork", "--print-address", print_address_fd_param, address_param, NULL };
339 gint source_fds[1] = { app->pipefd[1] };
340 gint target_fds[1] = { app->pipefd[1] };
341 G_STATIC_ASSERT (G_N_ELEMENTS (source_fds) == G_N_ELEMENTS (target_fds));
344 GError *error = NULL;
345 char *error_from_read;
347 g_clear_pointer (&app->a11y_launch_error_message, g_free);
349 if (!g_spawn_async_with_pipes_and_fds (NULL,
350 (const gchar * const *) argv,
352 G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
353 NULL, /* child_setup */
360 G_N_ELEMENTS (source_fds), /* n_fds in source_fds and target_fds */
362 NULL, /* stdin_pipe_out */
363 NULL, /* stdout_pipe_out */
364 NULL, /* stderr_pipe_out */
367 app->a11y_bus_pid = -1;
368 app->a11y_launch_error_message = g_strdup (error->message);
369 g_clear_error (&error);
370 g_free (address_param);
371 g_free (print_address_fd_param);
375 g_free (address_param);
376 g_free (print_address_fd_param);
377 close (app->pipefd[1]);
380 g_child_watch_add (pid, on_bus_exited, app);
382 app->state = A11Y_BUS_STATE_READING_ADDRESS;
383 app->a11y_bus_pid = pid;
384 g_debug ("Launched a11y bus, child is %ld", (long) pid);
385 error_from_read = NULL;
386 if (!unix_read_all_fd_to_string (app->pipefd[0], addr_buf, sizeof (addr_buf), &error_from_read))
388 app->a11y_launch_error_message = error_from_read;
389 kill (app->a11y_bus_pid, SIGTERM);
390 g_spawn_close_pid (app->a11y_bus_pid);
391 app->a11y_bus_pid = -1;
394 close (app->pipefd[0]);
396 app->state = A11Y_BUS_STATE_RUNNING;
398 /* Trim the trailing newline */
399 app->a11y_bus_address = g_strchomp (g_strdup (addr_buf));
400 g_debug ("a11y bus address: %s", app->a11y_bus_address);
405 close (app->pipefd[0]);
406 close (app->pipefd[1]);
407 app->state = A11Y_BUS_STATE_ERROR;
413 ensure_a11y_bus_daemon (A11yBusLauncher *app, char *config_path)
421 setup_bus_child_broker (gpointer data)
423 A11yBusLauncher *app = data;
427 dup2 (app->listenfd, 3);
428 close (app->listenfd);
429 g_setenv("LISTEN_FDS", "1", TRUE);
431 pid_str = g_strdup_printf("%u", getpid());
432 g_setenv("LISTEN_PID", pid_str, TRUE);
437 ensure_a11y_bus_broker (A11yBusLauncher *app, char *config_path)
439 char *argv[] = { DBUS_BROKER, config_path, "--scope", "user", NULL };
441 struct sockaddr_un addr = { .sun_family = AF_UNIX, "" };
442 socklen_t addr_len = sizeof(addr);
444 GError *error = NULL;
446 if (app->socket_name)
448 strcpy (addr.sun_path, app->socket_name);
449 unlink (app->socket_name);
452 /* This detects whether we are running under systemd. We only try to
453 * use dbus-broker if we are running under systemd because D-Bus
454 * service activation won't work otherwise.
456 if (sd_pid_get_user_unit (getpid (), &unit) >= 0)
462 app->state = A11Y_BUS_STATE_ERROR;
466 if ((app->listenfd = socket (PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0)
467 g_error ("Failed to create listening socket: %s", strerror (errno));
469 if (bind (app->listenfd, (struct sockaddr *)&addr, addr_len) < 0)
470 g_error ("Failed to bind listening socket: %s", strerror (errno));
472 if (!app->socket_name &&
473 getsockname (app->listenfd, (struct sockaddr *)&addr, &addr_len) < 0)
474 g_error ("Failed to get socket name for listening socket: %s", strerror(errno));
476 if (listen (app->listenfd, 1024) < 0)
477 g_error ("Failed to listen on socket: %s", strerror(errno));
479 g_clear_pointer (&app->a11y_launch_error_message, g_free);
481 if (!g_spawn_async (NULL,
484 G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
485 setup_bus_child_broker,
490 app->a11y_bus_pid = -1;
491 app->a11y_launch_error_message = g_strdup (error->message);
492 g_clear_error (&error);
496 close (app->listenfd);
499 g_child_watch_add (pid, on_bus_exited, app);
500 app->a11y_bus_pid = pid;
501 g_debug ("Launched a11y bus, child is %ld", (long) pid);
502 app->state = A11Y_BUS_STATE_RUNNING;
504 if (app->socket_name)
505 app->a11y_bus_address = g_strconcat("unix:path=", addr.sun_path, NULL);
507 app->a11y_bus_address = g_strconcat("unix:abstract=", addr.sun_path + 1, NULL);
508 g_debug ("a11y bus address: %s", app->a11y_bus_address);
513 close (app->listenfd);
514 app->state = A11Y_BUS_STATE_ERROR;
520 ensure_a11y_bus_broker (A11yBusLauncher *app, char *config_path)
527 ensure_a11y_bus (A11yBusLauncher *app)
529 char *config_path = NULL;
530 gboolean success = FALSE;
531 const gchar *xdg_runtime_dir;
533 if (app->a11y_bus_pid != 0)
536 if (g_file_test (SYSCONFDIR"/at-spi2/accessibility.conf", G_FILE_TEST_EXISTS))
537 config_path = "--config-file="SYSCONFDIR"/at-spi2/accessibility.conf";
539 config_path = "--config-file="DATADIR"/defaults/at-spi2/accessibility.conf";
541 xdg_runtime_dir = g_get_user_runtime_dir ();
544 const gchar *display = g_getenv ("DISPLAY");
545 gchar *at_spi_dir = g_strconcat (xdg_runtime_dir, "/at-spi", NULL);
547 mkdir (xdg_runtime_dir, 0700);
548 if (!g_path_is_absolute (at_spi_dir))
550 gchar *new_dir = g_canonicalize_filename (at_spi_dir, NULL);
552 at_spi_dir = new_dir;
554 if (mkdir (at_spi_dir, 0700) == 0 || errno == EEXIST)
556 app->socket_name = g_strconcat (at_spi_dir, "/bus", display, NULL);
558 p = strchr (app->socket_name, ':');
561 if (strlen (app->socket_name) >= 100)
563 g_free (app->socket_name);
564 app->socket_name = NULL;
571 #ifdef WANT_DBUS_BROKER
572 success = ensure_a11y_bus_broker (app, config_path);
575 if (!ensure_a11y_bus_daemon (app, config_path))
579 success = ensure_a11y_bus_daemon (app, config_path);
582 if (!ensure_a11y_bus_broker (app, config_path))
588 if (g_getenv ("DISPLAY") != NULL && g_getenv ("WAYLAND_DISPLAY") == NULL)
590 Display *display = XOpenDisplay (NULL);
593 Atom bus_address_atom = XInternAtom (display, "AT_SPI_BUS", False);
594 XChangeProperty (display,
595 XDefaultRootWindow (display),
597 XA_STRING, 8, PropModeReplace,
598 (guchar *) app->a11y_bus_address, strlen (app->a11y_bus_address));
600 XCloseDisplay (display);
601 app->x11_prop_set = TRUE;
610 handle_method_call (GDBusConnection *connection,
612 const gchar *object_path,
613 const gchar *interface_name,
614 const gchar *method_name,
615 GVariant *parameters,
616 GDBusMethodInvocation *invocation,
619 A11yBusLauncher *app = user_data;
621 if (g_strcmp0 (method_name, "GetAddress") == 0)
623 ensure_a11y_bus (app);
624 if (app->a11y_bus_pid > 0)
625 g_dbus_method_invocation_return_value (invocation,
626 g_variant_new ("(s)", app->a11y_bus_address));
628 g_dbus_method_invocation_return_dbus_error (invocation,
629 "org.a11y.Bus.Error",
630 app->a11y_launch_error_message);
635 handle_get_property (GDBusConnection *connection,
637 const gchar *object_path,
638 const gchar *interface_name,
639 const gchar *property_name,
643 A11yBusLauncher *app = user_data;
645 if (g_strcmp0 (property_name, "IsEnabled") == 0)
646 return g_variant_new ("b", app->a11y_enabled);
647 else if (g_strcmp0 (property_name, "ScreenReaderEnabled") == 0)
648 return g_variant_new ("b", app->screen_reader_enabled);
654 handle_a11y_enabled_change (A11yBusLauncher *app, gboolean enabled,
655 gboolean notify_gsettings)
657 GVariantBuilder builder;
658 GVariantBuilder invalidated_builder;
660 if (enabled == app->a11y_enabled)
663 app->a11y_enabled = enabled;
665 if (notify_gsettings && app->interface_schema)
667 g_settings_set_boolean (app->interface_schema, "toolkit-accessibility",
672 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
673 g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
674 g_variant_builder_add (&builder, "{sv}", "IsEnabled",
675 g_variant_new_boolean (enabled));
677 g_dbus_connection_emit_signal (app->session_bus, NULL, "/org/a11y/bus",
678 "org.freedesktop.DBus.Properties",
680 g_variant_new ("(sa{sv}as)", "org.a11y.Status",
682 &invalidated_builder),
685 g_variant_builder_clear (&builder);
686 g_variant_builder_clear (&invalidated_builder);
690 handle_screen_reader_enabled_change (A11yBusLauncher *app, gboolean enabled,
691 gboolean notify_gsettings)
693 GVariantBuilder builder;
694 GVariantBuilder invalidated_builder;
696 if (enabled == app->screen_reader_enabled)
699 /* If the screen reader is being enabled, we should enable accessibility
700 * if it isn't enabled already */
702 handle_a11y_enabled_change (app, enabled, notify_gsettings);
704 app->screen_reader_enabled = enabled;
706 if (notify_gsettings && app->a11y_schema)
708 g_settings_set_boolean (app->a11y_schema, "screen-reader-enabled",
713 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
714 g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
715 g_variant_builder_add (&builder, "{sv}", "ScreenReaderEnabled",
716 g_variant_new_boolean (enabled));
718 g_dbus_connection_emit_signal (app->session_bus, NULL, "/org/a11y/bus",
719 "org.freedesktop.DBus.Properties",
721 g_variant_new ("(sa{sv}as)", "org.a11y.Status",
723 &invalidated_builder),
726 g_variant_builder_clear (&builder);
727 g_variant_builder_clear (&invalidated_builder);
731 handle_set_property (GDBusConnection *connection,
733 const gchar *object_path,
734 const gchar *interface_name,
735 const gchar *property_name,
740 A11yBusLauncher *app = user_data;
741 const gchar *type = g_variant_get_type_string (value);
744 if (g_strcmp0 (type, "b") != 0)
746 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
747 "org.a11y.Status.%s expects a boolean but got %s", property_name, type);
751 enabled = g_variant_get_boolean (value);
753 if (g_strcmp0 (property_name, "IsEnabled") == 0)
755 handle_a11y_enabled_change (app, enabled, TRUE);
758 else if (g_strcmp0 (property_name, "ScreenReaderEnabled") == 0)
760 handle_screen_reader_enabled_change (app, enabled, TRUE);
765 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
766 "Unknown property '%s'", property_name);
771 static const GDBusInterfaceVTable bus_vtable =
774 NULL, /* handle_get_property, */
775 NULL /* handle_set_property */
778 static const GDBusInterfaceVTable status_vtable =
780 NULL, /* handle_method_call */
786 on_bus_acquired (GDBusConnection *connection,
790 A11yBusLauncher *app = user_data;
792 guint registration_id;
794 if (connection == NULL)
796 g_main_loop_quit (app->loop);
799 app->session_bus = connection;
802 registration_id = g_dbus_connection_register_object (connection,
804 introspection_data->interfaces[0],
809 if (registration_id == 0)
811 g_error ("%s", error->message);
812 g_clear_error (&error);
815 g_dbus_connection_register_object (connection,
817 introspection_data->interfaces[1],
825 on_name_lost (GDBusConnection *connection,
829 A11yBusLauncher *app = user_data;
830 if (app->session_bus == NULL
831 && connection == NULL
832 && app->a11y_launch_error_message == NULL)
833 app->a11y_launch_error_message = g_strdup ("Failed to connect to session bus");
834 g_main_loop_quit (app->loop);
838 on_name_acquired (GDBusConnection *connection,
842 A11yBusLauncher *app = user_data;
844 if (app->launch_immediately)
846 ensure_a11y_bus (app);
847 if (app->state == A11Y_BUS_STATE_ERROR)
849 g_main_loop_quit (app->loop);
854 g_bus_watch_name (G_BUS_TYPE_SESSION,
855 "org.gnome.SessionManager",
856 G_BUS_NAME_WATCHER_FLAGS_NONE,
857 name_appeared_handler, NULL,
861 static int sigterm_pipefd[2];
864 sigterm_handler (int signum)
866 write (sigterm_pipefd[1], "X", 1);
870 on_sigterm_pipe (GIOChannel *channel,
871 GIOCondition condition,
874 A11yBusLauncher *app = data;
876 g_main_loop_quit (app->loop);
882 init_sigterm_handling (A11yBusLauncher *app)
884 GIOChannel *sigterm_channel;
886 if (pipe (sigterm_pipefd) < 0)
887 g_error ("Failed to create pipe: %s", strerror (errno));
888 signal (SIGTERM, sigterm_handler);
890 sigterm_channel = g_io_channel_unix_new (sigterm_pipefd[0]);
891 g_io_add_watch (sigterm_channel,
892 G_IO_IN | G_IO_ERR | G_IO_HUP,
898 get_schema (const gchar *name)
900 #if GLIB_CHECK_VERSION (2, 32, 0)
901 GSettingsSchemaSource *source = g_settings_schema_source_get_default ();
904 g_error ("Cannot get the default GSettingsSchemaSource - is the gsettings-desktop-schemas package installed?");
907 GSettingsSchema *schema = g_settings_schema_source_lookup (source, name, FALSE);
912 return g_settings_new_full (schema, NULL, NULL);
914 const char * const *schemas = NULL;
917 schemas = g_settings_list_schemas ();
918 for (i = 0; schemas[i]; i++)
920 if (!strcmp (schemas[i], name))
921 return g_settings_new (schemas[i]);
929 gsettings_key_changed (GSettings *gsettings, const gchar *key, void *user_data)
931 gboolean new_val = g_settings_get_boolean (gsettings, key);
933 if (!strcmp (key, "toolkit-accessibility"))
934 handle_a11y_enabled_change (_global_app, new_val, FALSE);
935 else if (!strcmp (key, "screen-reader-enabled"))
936 handle_screen_reader_enabled_change (_global_app, new_val, FALSE);
943 gboolean a11y_set = FALSE;
944 gboolean screen_reader_set = FALSE;
947 _global_app = g_new0 (A11yBusLauncher, 1);
948 _global_app->loop = g_main_loop_new (NULL, FALSE);
950 for (i = 1; i < argc; i++)
952 if (!strcmp (argv[i], "--launch-immediately"))
953 _global_app->launch_immediately = TRUE;
954 else if (sscanf (argv[i], "--a11y=%d", &_global_app->a11y_enabled) == 1)
956 else if (sscanf (argv[i], "--screen-reader=%d",
957 &_global_app->screen_reader_enabled) == 1)
958 screen_reader_set = TRUE;
960 g_error ("usage: %s [--launch-immediately] [--a11y=0|1] [--screen-reader=0|1]", argv[0]);
963 _global_app->interface_schema = get_schema ("org.gnome.desktop.interface");
964 _global_app->a11y_schema = get_schema ("org.gnome.desktop.a11y.applications");
968 _global_app->a11y_enabled = _global_app->interface_schema
969 ? g_settings_get_boolean (_global_app->interface_schema, "toolkit-accessibility")
970 : _global_app->launch_immediately;
973 if (!screen_reader_set)
975 _global_app->screen_reader_enabled = _global_app->a11y_schema
976 ? g_settings_get_boolean (_global_app->a11y_schema, "screen-reader-enabled")
980 if (_global_app->interface_schema)
981 g_signal_connect (_global_app->interface_schema,
982 "changed::toolkit-accessibility",
983 G_CALLBACK (gsettings_key_changed), _global_app);
985 if (_global_app->a11y_schema)
986 g_signal_connect (_global_app->a11y_schema,
987 "changed::screen-reader-enabled",
988 G_CALLBACK (gsettings_key_changed), _global_app);
990 init_sigterm_handling (_global_app);
992 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
993 g_assert (introspection_data != NULL);
995 _global_app->name_owner_id =
996 g_bus_own_name (G_BUS_TYPE_SESSION,
998 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
1005 g_main_loop_run (_global_app->loop);
1007 if (_global_app->a11y_bus_pid > 0)
1009 kill (_global_app->a11y_bus_pid, SIGTERM);
1010 g_spawn_close_pid (_global_app->a11y_bus_pid);
1011 _global_app->a11y_bus_pid = -1;
1014 /* Clear the X property if our bus is gone; in the case where e.g.
1015 * GDM is launching a login on an X server it was using before,
1016 * we don't want early login processes to pick up the stale address.
1019 if (_global_app->x11_prop_set)
1021 Display *display = XOpenDisplay (NULL);
1024 Atom bus_address_atom = XInternAtom (display, "AT_SPI_BUS", False);
1025 XDeleteProperty (display,
1026 XDefaultRootWindow (display),
1030 XCloseDisplay (display);
1035 if (_global_app->a11y_launch_error_message)
1037 g_printerr ("Failed to launch bus: %s", _global_app->a11y_launch_error_message);