2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2001, 2002 Sun Microsystems Inc.,
6 * Copyright 2001, 2002 Ximian, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
24 /* registry.c: the main accessibility service registry implementation */
26 #undef SPI_LISTENER_DEBUG
28 #undef SPI_QUEUE_DEBUG
35 #include <spi-common/spi-dbus.h>
38 #include "dbus/dbus-glib-lowlevel.h"
40 /* Our parent GObject type */
41 #define PARENT_TYPE G_OBJECT_TYPE
57 const char *event_name;
58 EventTypeCategory type_cat;
59 GQuark major; /* from string segment[1] */
60 GQuark minor; /* from string segment[1]+segment[2] */
61 GQuark detail; /* from string segment[3] (not concatenated) */
64 G_DEFINE_TYPE(SpiRegistry, spi_registry, G_TYPE_OBJECT)
67 spi_registry_set_debug (const char *debug_flag_string)
69 if (debug_flag_string)
70 _dbg = (int) g_ascii_strtod (debug_flag_string, NULL);
73 static void emit(SpiRegistry *registry, const char *name, int first_type, ...)
77 va_start(arg, first_type);
78 spi_dbus_emit_valist(registry->droute.bus, SPI_DBUS_PATH_REGISTRY, SPI_DBUS_INTERFACE_REGISTRY, name, first_type, arg);
83 desktop_add_application (SpiDesktop *desktop,
84 guint index, gpointer data)
86 SpiRegistry *registry = SPI_REGISTRY (data);
87 const SpiDesktopApplication *app = g_list_nth_data(desktop->applications, index);
89 emit(registry, "ApplicationAdd", DBUS_TYPE_UINT32, &index, DBUS_TYPE_STRING, &app->path, DBUS_TYPE_INVALID);
95 desktop_remove_application (SpiDesktop *desktop,
96 guint index, gpointer data)
98 SpiRegistry *registry = SPI_REGISTRY (data);
99 const char *name = g_list_nth_data(desktop->applications, index);
101 emit(registry, "ApplicationRemove", DBUS_TYPE_UINT32, &index, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
106 spi_registry_object_finalize (GObject *object)
108 DBG (1, g_warning ("spi_registry_object_finalize called\n"));
109 g_object_unref (SPI_REGISTRY (object)->de_controller);
111 G_OBJECT_CLASS (spi_registry_parent_class)->finalize (object);
115 * registerApplication:
116 * @application: a reference to the requesting @Application
117 * return values: void
119 * Register a new application with the accessibility broker.
123 impl_accessibility_registry_register_application (DBusConnection *bus, DBusMessage *message, void *user_data)
125 SpiRegistry *registry = SPI_REGISTRY (user_data);
126 const char *application = dbus_message_get_sender (message);
129 fprintf (stderr, "registering app %s\n", application);
131 spi_desktop_add_application (registry->desktop, application);
134 * TODO: change the implementation below to a WM-aware one;
135 * e.g. don't add all apps to the SpiDesktop
137 return dbus_message_new_method_return (message);
141 * deregisterApplication:
142 * @application: a reference to the @Application
143 * to be deregistered.
144 * return values: void
146 * De-register an application previously registered with the broker.
150 impl_accessibility_registry_deregister_application (DBusConnection *bus, DBusMessage *message, void *user_data)
152 SpiRegistry *registry = SPI_REGISTRY (user_data);
153 const char *application = dbus_message_get_sender (message);
155 spi_desktop_remove_application (registry->desktop, application);
158 fprintf (stderr, "de-registered app %s\n", application);
160 return dbus_message_new_method_return (message);
165 * return values: a short integer indicating the current number of
168 * Get the current number of desktops.
172 impl_accessibility_registry_get_desktop_count (DBusConnection *bus, DBusMessage *message, void *user_data)
174 dbus_int16_t n_desktops = 1;
177 /* TODO: implement support for multiple virtual desktops */
178 reply = dbus_message_new_method_return (message);
181 dbus_message_append_args (reply, DBUS_TYPE_INT16, &n_desktops, DBUS_TYPE_INVALID);
188 * @n: the index of the requested @Desktop.
189 * return values: a reference to the requested @Desktop.
191 * Get the nth accessible desktop.
195 impl_accessibility_registry_get_desktop (DBusConnection *bus, DBusMessage *message, void *user_data)
202 /* TODO: implement support for multiple virtual desktops */
203 dbus_error_init (&error);
204 if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT16, &n, DBUS_TYPE_INVALID))
206 return spi_dbus_general_error (message);
208 path = (n == 0? SPI_DBUS_PATH_DESKTOP: "/");
209 reply = dbus_message_new_method_return (message);
212 dbus_message_append_args (reply, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID);
220 * return values: a sequence containing references to
223 * Get a list of accessible desktops.
227 impl_accessibility_registry_get_desktop_list (DBusConnection *bus, DBusMessage *message, void *user_data)
230 DBusMessageIter iter, iter_array;
231 const char *path = SPI_DBUS_PATH_DESKTOP;
233 reply = dbus_message_new_method_return (message);
234 if (!reply) return NULL;
235 dbus_message_iter_init_append(reply, &iter);
236 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "o", &iter_array)) goto oom;
237 dbus_message_iter_append_basic(&iter_array, DBUS_TYPE_STRING, &path);
238 if (!dbus_message_iter_close_container (&iter, &iter_array)) goto oom;
241 // TODO: handle out-of-memory
247 impl_accessibility_registry_get_device_event_controller (DBusConnection *bus, DBusMessage *message, void *user_data)
250 const char *path = SPI_DBUS_PATH_DEC;
252 reply = dbus_message_new_method_return (message);
255 dbus_message_append_args (reply, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID);
262 spi_registry_class_init (SpiRegistryClass *klass)
264 GObjectClass * object_class = (GObjectClass *) klass;
266 spi_registry_parent_class = g_type_class_ref (G_TYPE_OBJECT);
268 object_class->finalize = spi_registry_object_finalize;
271 static DBusObjectPathVTable droute_vtable =
275 NULL, NULL, NULL, NULL
279 spi_registry_init (SpiRegistry *registry)
283 spi_registry_set_debug (g_getenv ("AT_SPI_DEBUG"));
285 * TODO: FIXME, this module makes the foolish assumptions that
286 * registryd uses the same display as the apps, and that the
287 * DISPLAY environment variable is set.
289 gdk_init (NULL, NULL);
291 registry->exit_notify_timeout = 200;
292 registry->queue_handler_id = 0;
294 dbus_error_init (&error);
295 registry->droute.bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
296 if (!registry->droute.bus)
298 g_warning("Couldn't connect to dbus: %s\n", error.message);
301 registry->droute.user_data = registry;
302 spi_registry_initialize_registry_interface (®istry->droute);
303 spi_registry_initialize_desktop_interface (®istry->droute);
304 spi_registry_initialize_dec_interface (®istry->droute);
305 // todo: initialize accessible and component interfaces, for desktop?
306 if (!dbus_connection_try_register_fallback (registry->droute.bus, "/org/freedesktop/atspi", &droute_vtable, ®istry->droute, &error))
308 g_warning("Couldn't register droute.\n");
310 dbus_connection_setup_with_g_main(registry->droute.bus, g_main_context_default());
312 // TODO: decide whether focus_object is still relevant
313 registry->desktop = spi_desktop_new ();
314 /* Register callback notification for application addition and removal */
315 g_signal_connect (G_OBJECT (registry->desktop),
317 G_CALLBACK (desktop_add_application),
320 g_signal_connect (G_OBJECT (registry->desktop),
321 "application_removed",
322 G_CALLBACK (desktop_remove_application),
325 registry->de_controller = spi_device_event_controller_new (registry);
329 spi_registry_new (void)
331 SpiRegistry *retval = g_object_new (SPI_REGISTRY_TYPE, NULL);
335 static DRouteMethod methods[] =
337 { impl_accessibility_registry_register_application , "registerApplication" },
338 { impl_accessibility_registry_deregister_application, "deregisterApplication" },
339 { impl_accessibility_registry_get_desktop_count, "getDesktopCount" },
340 { impl_accessibility_registry_get_desktop, "getDesktop" },
341 { impl_accessibility_registry_get_desktop_list, "getDesktopList" },
342 { impl_accessibility_registry_get_device_event_controller, "getDeviceEventController" },
347 spi_registry_initialize_registry_interface (DRouteData * data)
349 droute_add_interface (data, "org.freedesktop.atspi.Registry", methods,