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., 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 /* desktop.c: implements SpiDesktop.idl */
29 #include <atk/atkcomponent.h>
30 #include <gdk/gdkscreen.h>
33 #include <spi-common/spi-dbus.h>
38 G_DEFINE_TYPE(SpiDesktop, spi_desktop, G_TYPE_OBJECT)
40 /* SpiDesktop signals */
46 static guint spi_desktop_signals[LAST_SIGNAL];
49 /* Our parent Gtk object type */
50 #define PARENT_TYPE SPI_ACCESSIBLE_TYPE
52 static gboolean exiting = FALSE;
54 /* A pointer to our parent object class */
55 static GObjectClass *parent_class;
57 #define SPI_TYPE_ATK_DESKTOP (spi_atk_desktop_get_type ())
58 #define SPI_ATK_DESKTOP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_TYPE_ATK_DESKTOP, SpiAtkDesktop))
59 #define SPI_IS_ATK_DESKTOP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SPI_TYPE_ATK_DESKTOP))
68 AtkObjectClass parent;
71 static void spi_atk_desktop_init (SpiAtkDesktop *desktop);
72 static void atk_component_interface_init (AtkComponentIface *iface);
73 static void spi_atk_desktop_get_extents (AtkComponent *component,
78 AtkCoordType coord_type);
81 spi_atk_desktop_get_type (void)
83 static GType type = 0;
87 static const GTypeInfo typeInfo =
89 sizeof (SpiAtkDesktopClass),
91 (GBaseFinalizeFunc) NULL,
92 (GClassInitFunc) NULL,
93 (GClassFinalizeFunc) NULL,
95 sizeof (SpiAtkDesktop),
97 (GInstanceInitFunc) spi_atk_desktop_init,
99 static const GInterfaceInfo atk_component_info =
101 (GInterfaceInitFunc) atk_component_interface_init,
102 (GInterfaceFinalizeFunc) NULL,
106 type = g_type_register_static (ATK_TYPE_OBJECT,
107 "SpiAtkDesktop", &typeInfo, 0);
108 g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
109 &atk_component_info);
115 spi_atk_desktop_init (SpiAtkDesktop *desktop)
119 atk_object_set_name (ATK_OBJECT (desktop), "main");
120 display = gdk_x11_lookup_xdisplay (GDK_DISPLAY ());
121 desktop->screen = gdk_display_get_default_screen (display);
125 atk_component_interface_init (AtkComponentIface *iface)
127 g_return_if_fail (iface != NULL);
129 iface->get_extents = spi_atk_desktop_get_extents;
133 spi_atk_desktop_get_extents (AtkComponent *component,
138 AtkCoordType coord_type)
140 SpiAtkDesktop *desktop;
142 g_return_if_fail (SPI_IS_ATK_DESKTOP (component));
143 desktop = SPI_ATK_DESKTOP (component);
146 *width = gdk_screen_get_width (desktop->screen);
147 *height = gdk_screen_get_height (desktop->screen);
151 spi_desktop_init (SpiDesktop *desktop)
153 desktop->applications = NULL;
157 spi_desktop_dispose (GObject *object)
159 SpiDesktop *desktop = (SpiDesktop *) object;
161 while (desktop->applications)
163 SpiDesktopApplication *app = desktop->applications->data;
164 g_assert (app != NULL);
165 spi_desktop_remove_application (desktop, app->bus_name);
168 G_OBJECT_CLASS (parent_class)->dispose (object);
172 impl_desktop_get_child_count (const char *path, DBusMessageIter * iter,
175 SpiDesktop *desktop = SPI_REGISTRY(user_data)->desktop;
177 if (desktop->applications)
179 return droute_return_v_int32(iter, g_list_length (desktop->applications));
183 return droute_return_v_int32(iter, 0);
188 impl_desktop_get_child_at_index (DBusConnection *bus, DBusMessage *message, void *user_data)
190 SpiDesktop *desktop = SPI_REGISTRY(user_data)->desktop;
193 SpiDesktopApplication *app;
194 const char *bus_name;
197 dbus_error_init (&error);
198 if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID))
200 return spi_dbus_general_error (message);
202 app = g_list_nth_data (desktop->applications, index);
203 bus_name = (app? app->bus_name: "");
205 reply = dbus_message_new_method_return (message);
208 dbus_message_append_args (reply, DBUS_TYPE_STRING, &bus_name, DBUS_TYPE_INVALID);
215 impl_desktop_get_children (DBusConnection *bus, DBusMessage *message, void *user_data)
217 SpiDesktop *desktop = SPI_REGISTRY(user_data)->desktop;
221 SpiDesktopApplication *app;
223 DBusMessageIter iter, iter_array;
225 reply = dbus_message_new_method_return (message);
226 if (!reply) return NULL;
227 dbus_message_iter_init_append (reply, &iter);
228 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &iter_array))
232 count = g_list_length (desktop->applications);
233 for (i = 0; i < count; i++)
235 app = g_list_nth_data (desktop->applications, i);
238 g_warning ("Null app\n");
241 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &app->bus_name);
243 if (!dbus_message_iter_close_container (&iter, &iter_array))
249 // TODO: Handle out of memory
254 impl_get_name (const char *path, DBusMessageIter * iter, void *user_data)
256 if (strcmp (path, SPI_DBUS_PATH_DESKTOP) != 0)
258 // TODO: call atk_object_get_name
259 return droute_return_v_string (iter, "main");
263 spi_desktop_exiting (void)
269 spi_desktop_class_init (SpiDesktopClass *klass)
271 GObjectClass * object_class = (GObjectClass *) klass;
273 object_class->dispose = spi_desktop_dispose;
275 parent_class = g_type_class_ref (G_TYPE_OBJECT);
277 spi_desktop_signals[APPLICATION_ADDED] =
278 g_signal_new ("application_added",
279 G_TYPE_FROM_CLASS (klass),
281 G_STRUCT_OFFSET (SpiDesktopClass, application_added),
283 g_cclosure_marshal_VOID__UINT,
286 spi_desktop_signals[APPLICATION_REMOVED] =
287 g_signal_new ("application_removed",
288 G_TYPE_FROM_CLASS (klass),
290 G_STRUCT_OFFSET (SpiDesktopClass, application_removed),
292 g_cclosure_marshal_VOID__UINT,
295 g_atexit (spi_desktop_exiting);
299 spi_desktop_new (void)
301 return g_object_new (SPI_DESKTOP_TYPE, NULL);
305 abnormal_application_termination (gpointer object, SpiDesktopApplication *app)
307 g_return_if_fail (SPI_IS_DESKTOP (app->desktop));
310 spi_desktop_remove_application (app->desktop, app->bus_name);
314 spi_desktop_add_application (SpiDesktop *desktop,
315 const char *application)
317 SpiDesktopApplication *app;
319 g_return_if_fail (SPI_IS_DESKTOP (desktop));
321 app = g_new (SpiDesktopApplication, 1);
322 app->desktop = desktop;
323 app->bus_name = g_strdup (application);
325 desktop->applications = g_list_append (desktop->applications, app);
327 // TODO: Listen for termination, and call abnormal_application_termination
329 g_signal_emit (G_OBJECT (desktop),
330 spi_desktop_signals[APPLICATION_ADDED], 0,
331 g_list_index (desktop->applications, app));
335 spi_desktop_remove_application (SpiDesktop *desktop,
336 const char *bus_name)
340 SpiDesktopApplication *app;
342 g_return_if_fail ( bus_name != NULL);
343 g_return_if_fail (SPI_IS_DESKTOP (desktop));
346 for (l = desktop->applications; l; l = l->next)
348 app = (SpiDesktopApplication *) l->data;
350 if (!strcmp(app->bus_name, bus_name))
359 g_signal_emit (G_OBJECT (desktop), spi_desktop_signals[APPLICATION_REMOVED], 0, idx);
361 desktop->applications = g_list_delete_link (desktop->applications, l);
363 g_free (app->bus_name);
367 static DRouteMethod methods_desktop[] =
369 { impl_desktop_get_child_at_index, "getChildAtIndex" },
370 { impl_desktop_get_children, "getChildren" },
374 static DRouteProperty properties_desktop[] =
376 { impl_desktop_get_child_count, NULL, "getChildCount" },
380 static DRouteProperty properties_accessible[] =
382 { impl_get_name, "getName" },
387 spi_registry_initialize_desktop_interface (DRouteData * data)
389 droute_add_interface (data, SPI_DBUS_INTERFACE_DESKTOP, methods_desktop,
390 properties_desktop, NULL, NULL);
391 droute_add_interface (data, SPI_DBUS_INTERFACE_ACCESSIBLE, NULL,
392 properties_accessible, NULL, NULL);