1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2007 IBM Corp.
6  * Copyright 2010, 2011 Novell, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
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  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #include "atspi-private.h"
25 
26 /* TODO: Improve documentation and implement some missing functions */
27 
28 /**
29  * atspi_collection_is_ancestor_of:
30  *
31  * Not yet implemented.
32  *
33  **/
34 gboolean
atspi_collection_is_ancestor_of(AtspiCollection * collection,AtspiAccessible * test,GError ** error)35 atspi_collection_is_ancestor_of (AtspiCollection *collection,
36                                  AtspiAccessible *test,
37                                  GError **error)
38 {
39   g_warning ("AT-SPI: TODO: Implement is_ancestor_of");
40   return FALSE;
41 }
42 
43 static DBusMessage *
new_message(AtspiCollection * collection,char * method)44 new_message (AtspiCollection *collection, char *method)
45 {
46   AtspiAccessible *accessible;
47 
48   if (!collection)
49     return NULL;
50 
51   accessible = ATSPI_ACCESSIBLE (collection);
52   if (!accessible->parent.app)
53     return NULL;
54   return dbus_message_new_method_call (accessible->parent.app->bus_name,
55                                        accessible->parent.path,
56                                        atspi_interface_collection,
57                                        method);
58 }
59 
60 static gboolean
append_match_rule(DBusMessage * message,AtspiMatchRule * rule)61 append_match_rule (DBusMessage *message, AtspiMatchRule *rule)
62 {
63   DBusMessageIter iter;
64 
65   dbus_message_iter_init_append (message, &iter);
66   return _atspi_match_rule_marshal (rule, &iter);
67 }
68 
69 static gboolean
append_accessible(DBusMessage * message,AtspiAccessible * accessible)70 append_accessible (DBusMessage *message, AtspiAccessible *accessible)
71 {
72   DBusMessageIter iter;
73 
74   dbus_message_iter_init_append (message, &iter);
75   dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH,
76                                   &accessible->parent.path);
77   return TRUE;	/* TODO: Check for out-of-memory */
78 }
79 
80 static GArray *
return_accessibles(DBusMessage * message)81 return_accessibles (DBusMessage *message)
82 {
83   DBusMessageIter iter, iter_array;
84   GArray *ret = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *));
85 
86   _ATSPI_DBUS_CHECK_SIG (message, "a(so)", NULL, NULL);
87 
88   dbus_message_iter_init (message, &iter);
89   dbus_message_iter_recurse (&iter, &iter_array);
90 
91   while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
92   {
93     AtspiAccessible *accessible;
94     accessible = _atspi_dbus_return_accessible_from_iter (&iter_array);
95     ret = g_array_append_val (ret, accessible);
96     /* Iter was moved already, so no need to call dbus_message_iter_next */
97   }
98   dbus_message_unref (message);
99   return ret;
100 }
101 
102 /**
103  * atspi_collection_get_matches:
104  * @collection: A pointer to the #AtspiCollection to query.
105  * @rule: An #AtspiMatchRule describing the match criteria.
106  * @sortby: An #AtspiCollectionSortOrder specifying the way the results are to
107  *          be sorted.
108  * @count: The maximum number of results to return, or 0 for no limit.
109  * @traverse: Not supported.
110  *
111  * Gets all #AtspiAccessible objects from the @collection matching a given
112  * @rule.
113  *
114  * Returns: (element-type AtspiAccessible*) (transfer full): All
115  *          #AtspiAccessible objects matching the given match rule.
116  **/
117 GArray *
atspi_collection_get_matches(AtspiCollection * collection,AtspiMatchRule * rule,AtspiCollectionSortOrder sortby,gint count,gboolean traverse,GError ** error)118 atspi_collection_get_matches (AtspiCollection *collection,
119                               AtspiMatchRule *rule,
120                               AtspiCollectionSortOrder sortby,
121                               gint count,
122                               gboolean traverse,
123                               GError **error)
124 {
125   DBusMessage *message = new_message (collection, "GetMatches");
126   DBusMessage *reply;
127   dbus_int32_t d_sortby = sortby;
128   dbus_int32_t d_count = count;
129   dbus_bool_t d_traverse = traverse;
130 
131   if (!message)
132     return NULL;
133 
134   if (!append_match_rule (message, rule))
135     return NULL;
136   dbus_message_append_args (message, DBUS_TYPE_UINT32, &d_sortby,
137                             DBUS_TYPE_INT32, &d_count,
138                             DBUS_TYPE_BOOLEAN, &d_traverse,
139                             DBUS_TYPE_INVALID);
140   reply = _atspi_dbus_send_with_reply_and_block (message, error);
141   if (!reply)
142     return NULL;
143   return return_accessibles (reply);
144 }
145 
146 /**
147  * atspi_collection_get_matches_to:
148  * @collection: A pointer to the #AtspiCollection to query.
149  * @current_object: The object at which to start searching.
150  * @rule: An #AtspiMatchRule describing the match criteria.
151  * @sortby: An #AtspiCollectionSortOrder specifying the way the results are to
152  *          be sorted.
153  * @tree: An #AtspiCollectionTreeTraversalType specifying restrictions on
154  *          the objects to be traversed.
155  * @limit_scope: If #TRUE, only descendants of @current_object's parent
156  *          will be returned. Otherwise (if #FALSE), any accessible may be
157  *          returned if it would preceed @current_object in a flattened
158  *          hierarchy.
159  * @count: The maximum number of results to return, or 0 for no limit.
160  * @traverse: Not supported.
161  *
162  * Gets all #AtspiAccessible objects from the @collection, after
163  * @current_object, matching a given @rule.
164  *
165  * Returns: (element-type AtspiAccessible*) (transfer full): All
166  *          #AtspiAccessible objects matching the given match rule after
167  *          @current_object.
168  **/
169 GArray *
atspi_collection_get_matches_to(AtspiCollection * collection,AtspiAccessible * current_object,AtspiMatchRule * rule,AtspiCollectionSortOrder sortby,AtspiCollectionTreeTraversalType tree,gboolean limit_scope,gint count,gboolean traverse,GError ** error)170 atspi_collection_get_matches_to (AtspiCollection *collection,
171                               AtspiAccessible *current_object,
172                               AtspiMatchRule *rule,
173                               AtspiCollectionSortOrder sortby,
174                               AtspiCollectionTreeTraversalType tree,
175                               gboolean limit_scope,
176                               gint count,
177                               gboolean traverse,
178                               GError **error)
179 {
180   DBusMessage *message = new_message (collection, "GetMatchesTo");
181   DBusMessage *reply;
182   dbus_int32_t d_sortby = sortby;
183   dbus_int32_t d_tree = tree;
184   dbus_bool_t d_limit_scope = limit_scope;
185   dbus_int32_t d_count = count;
186   dbus_bool_t d_traverse = traverse;
187 
188   if (!message)
189     return NULL;
190 
191   if (!append_accessible (message, current_object))
192     return NULL;
193   if (!append_match_rule (message, rule))
194     return NULL;
195   dbus_message_append_args (message, DBUS_TYPE_UINT32, &d_sortby,
196                                      DBUS_TYPE_UINT32, &d_tree,
197                             DBUS_TYPE_BOOLEAN, &d_limit_scope,
198                             DBUS_TYPE_INT32, &d_count,
199                             DBUS_TYPE_BOOLEAN, &d_traverse,
200                             DBUS_TYPE_INVALID);
201   reply = _atspi_dbus_send_with_reply_and_block (message, error);
202   if (!reply)
203     return NULL;
204   return return_accessibles (reply);
205 }
206 
207 /**
208  * atspi_collection_get_matches_from:
209  * @collection: A pointer to the #AtspiCollection to query.
210  * @current_object: Upon reaching this object, searching should stop.
211  * @rule: An #AtspiMatchRule describing the match criteria.
212  * @sortby: An #AtspiCollectionSortOrder specifying the way the results are to
213  *          be sorted.
214  * @tree: An #AtspiCollectionTreeTraversalType specifying restrictions on
215  *          the objects to be traversed.
216  * @count: The maximum number of results to return, or 0 for no limit.
217  * @traverse: Not supported.
218  *
219  * Gets all #AtspiAccessible objects from the @collection, before
220  * @current_object, matching a given @rule.
221  *
222  * Returns: (element-type AtspiAccessible*) (transfer full): All
223  *          #AtspiAccessible objects matching the given match rule that preceed
224  *          @current_object.
225  **/
226 GArray *
atspi_collection_get_matches_from(AtspiCollection * collection,AtspiAccessible * current_object,AtspiMatchRule * rule,AtspiCollectionSortOrder sortby,AtspiCollectionTreeTraversalType tree,gint count,gboolean traverse,GError ** error)227 atspi_collection_get_matches_from (AtspiCollection *collection,
228                               AtspiAccessible *current_object,
229                               AtspiMatchRule *rule,
230                               AtspiCollectionSortOrder sortby,
231                               AtspiCollectionTreeTraversalType tree,
232                               gint count,
233                               gboolean traverse,
234                               GError **error)
235 {
236   DBusMessage *message = new_message (collection, "GetMatchesFrom");
237   DBusMessage *reply;
238   dbus_int32_t d_sortby = sortby;
239   dbus_int32_t d_tree = tree;
240   dbus_int32_t d_count = count;
241   dbus_bool_t d_traverse = traverse;
242 
243   if (!message)
244     return NULL;
245 
246   if (!append_accessible (message, current_object))
247     return NULL;
248   if (!append_match_rule (message, rule))
249     return NULL;
250   dbus_message_append_args (message, DBUS_TYPE_UINT32, &d_sortby,
251                             DBUS_TYPE_UINT32, &d_tree,
252                             DBUS_TYPE_INT32, &d_count,
253                             DBUS_TYPE_BOOLEAN, &d_traverse,
254                             DBUS_TYPE_INVALID);
255   reply = _atspi_dbus_send_with_reply_and_block (message, error);
256   if (!reply)
257     return NULL;
258   return return_accessibles (reply);
259 }
260 
261 /**
262  * atspi_collection_get_active_descendant:
263  *
264 * Returns: (transfer full): The active descendant of the given object.
265  * Not yet implemented.
266  **/
267 AtspiAccessible *
atspi_collection_get_active_descendant(AtspiCollection * collection,GError ** error)268 atspi_collection_get_active_descendant (AtspiCollection *collection, GError **error)
269 {
270   g_warning ("AT-SPI: TODO: Implement get_active_descendants");
271   return NULL;
272 }
273 
274 static void
atspi_collection_base_init(AtspiCollection * klass)275 atspi_collection_base_init (AtspiCollection *klass)
276 {
277 }
278 
279 GType
atspi_collection_get_type(void)280 atspi_collection_get_type (void)
281 {
282   static GType type = 0;
283 
284   if (!type) {
285     static const GTypeInfo tinfo =
286     {
287       sizeof (AtspiCollection),
288       (GBaseInitFunc) atspi_collection_base_init,
289       (GBaseFinalizeFunc) NULL,
290     };
291 
292     type = g_type_register_static (G_TYPE_INTERFACE, "AtspiCollection", &tinfo, 0);
293 
294   }
295   return type;
296 }
297