4e176e1268258e466ef41f0d60344ffd1e0af6ba
[platform/core/uifw/at-spi2-atk.git] / spi-common / spi-dbus.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2008 Novell, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
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  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <glib.h>
27 #include <glib-object.h>
28 #include <dbus/dbus.h>
29
30 #include "spi-types.h"
31
32 GHashTable *path2ptr;
33 static guint objindex;
34
35 static void
36 deregister_object (gpointer data, GObject *obj)
37 {
38   spi_dbus_notify_remove(ATK_OBJECT(obj), NULL);
39   g_hash_table_remove (path2ptr, &obj);
40 }
41
42 static guint
43 register_object (GObject * obj)
44 {
45   gint *new_int;
46
47   if (!path2ptr)
48     {
49       path2ptr = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL);
50       if (!path2ptr)
51         return ++objindex;
52     }
53   objindex++;
54   while (g_hash_table_lookup (path2ptr, &objindex))
55     {
56       objindex++;
57       /* g_object_get_data returning 0 means no data, so handle wrap-around */
58       if (objindex == 0)
59         objindex++;
60     }
61   new_int = (gint *)g_malloc(sizeof(gint));
62   if (new_int)
63   {
64     *new_int = objindex;
65     g_hash_table_insert (path2ptr, new_int, obj);
66   }
67   g_object_set_data (G_OBJECT (obj), "dbus-id", (gpointer) objindex);
68   g_object_weak_ref(G_OBJECT(obj), deregister_object, NULL);
69   spi_dbus_notify_change(obj, TRUE, NULL);
70   return objindex;
71 }
72
73 DBusMessage *
74 spi_dbus_general_error (DBusMessage * message)
75 {
76   return dbus_message_new_error (message,
77                                  "org.freedesktop.atspi.GeneralError",
78                                  "General error");
79 }
80
81
82 DBusMessage *
83 spi_dbus_return_rect (DBusMessage * message, gint ix, gint iy, gint iwidth,
84                       gint iheight)
85 {
86   DBusMessage *reply;
87   dbus_uint32_t x, y, width, height;
88
89   x = ix;
90   y = iy;
91   width = iwidth;
92   height = iheight;
93   reply = dbus_message_new_method_return (message);
94   if (reply)
95     {
96       DBusMessageIter iter, sub;
97       dbus_message_iter_init_append (reply, &iter);
98       if (!dbus_message_iter_open_container
99           (&iter, DBUS_TYPE_STRUCT, NULL, &sub))
100         goto oom;
101       dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &x);
102       dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &y);
103       dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &width);
104       dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &height);
105       if (!dbus_message_iter_close_container (&iter, &sub))
106         goto oom;
107     }
108   return reply;
109 oom:
110   /* todo: return an error */
111   return reply;
112 }
113
114 void spi_dbus_emit_valist(DBusConnection *bus, const char *path, const char *interface, const char *name, int first_arg_type, va_list args)
115 {
116   DBusMessage *sig;
117
118   sig = dbus_message_new_signal(path, interface, name);
119   if (first_arg_type != DBUS_TYPE_INVALID)
120   {
121     dbus_message_append_args_valist(sig, first_arg_type, args);
122   }
123   dbus_connection_send(bus, sig, NULL);
124   dbus_message_unref(sig);
125 }
126
127 dbus_bool_t spi_dbus_message_iter_get_struct(DBusMessageIter *iter, ...)
128 {
129   va_list args;
130   DBusMessageIter iter_struct;
131   int type;
132   void *ptr;
133
134   dbus_message_iter_recurse(iter, &iter_struct);
135   va_start(args, iter);
136   for (;;)
137   {
138     type = va_arg(args, int);
139     if (type == DBUS_TYPE_INVALID) break;
140     if (type != dbus_message_iter_get_arg_type(&iter_struct))
141     {
142       va_end(args);
143       return FALSE;
144     }
145     ptr = va_arg(args, void *);
146     dbus_message_iter_get_basic(&iter_struct, ptr);
147     dbus_message_iter_next(&iter_struct);
148   }
149   dbus_message_iter_next(iter);
150   va_end(args);
151   return TRUE;
152 }
153
154 dbus_bool_t spi_dbus_message_iter_append_struct(DBusMessageIter *iter, ...)
155 {
156   va_list args;
157   DBusMessageIter iter_struct;
158   int type;
159   void *ptr;
160
161   if (!dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &iter_struct)) return FALSE;
162   va_start(args, iter);
163   for (;;)
164   {
165     type = va_arg(args, int);
166     if (type == DBUS_TYPE_INVALID) break;
167     ptr = va_arg(args, void *);
168     dbus_message_iter_append_basic(&iter_struct, type, ptr);
169   }
170   if (!dbus_message_iter_close_container(iter, &iter_struct)) return FALSE;
171   va_end(args);
172   return TRUE;
173 }
174
175 dbus_bool_t spi_dbus_marshall_deviceEvent(DBusMessage *message, const Accessibility_DeviceEvent *e)
176 {
177   DBusMessageIter iter;
178
179   if (!message) return FALSE;
180   dbus_message_iter_init_append(message, &iter);
181   return spi_dbus_message_iter_append_struct(&iter, DBUS_TYPE_UINT32, &e->type, DBUS_TYPE_INT32, &e->id, DBUS_TYPE_INT16, &e->hw_code, DBUS_TYPE_INT16, &e->modifiers, DBUS_TYPE_INT32, &e->timestamp, DBUS_TYPE_STRING, &e->event_string, DBUS_TYPE_BOOLEAN, &e->is_text, DBUS_TYPE_INVALID);
182 }
183
184 dbus_bool_t spi_dbus_demarshall_deviceEvent(DBusMessage *message, Accessibility_DeviceEvent *e)
185 {
186   DBusMessageIter iter;
187
188   dbus_message_iter_init(message, &iter);
189   return spi_dbus_message_iter_get_struct(&iter, DBUS_TYPE_UINT32, &e->type, DBUS_TYPE_INT32, &e->id, DBUS_TYPE_INT16, &e->hw_code, DBUS_TYPE_INT16, &e->modifiers, DBUS_TYPE_INT32, &e->timestamp, DBUS_TYPE_STRING, &e->event_string, DBUS_TYPE_BOOLEAN, &e->is_text, DBUS_TYPE_INVALID);
190 }