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.
7 * Copyright 2010, 2011 Novell, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
25 #include "atspi-private.h"
27 G_DEFINE_TYPE (AtspiMatchRule, atspi_match_rule, G_TYPE_OBJECT)
30 atspi_match_rule_init (AtspiMatchRule *match_rule)
35 atspi_match_rule_dispose (GObject *object)
37 AtspiMatchRule *rule = ATSPI_MATCH_RULE (object);
41 g_object_unref (rule->states);
47 g_hash_table_unref (rule->attributes);
48 rule->attributes = NULL;
51 G_OBJECT_CLASS (atspi_match_rule_parent_class)->dispose (object);
55 atspi_match_rule_finalize (GObject *object)
57 AtspiMatchRule *rule = ATSPI_MATCH_RULE (object);
62 for (i = 0; i < rule->interfaces->len; i++)
63 g_free (g_array_index (rule->interfaces, gchar *, i));
64 g_array_free (rule->interfaces, TRUE);
68 g_hash_table_unref (rule->attributes);
70 G_OBJECT_CLASS (atspi_match_rule_parent_class)->finalize (object);
74 atspi_match_rule_class_init (AtspiMatchRuleClass *klass)
76 GObjectClass *object_class = G_OBJECT_CLASS (klass);
78 object_class->dispose = atspi_match_rule_dispose;
79 object_class->finalize = atspi_match_rule_finalize;
83 * atspi_match_rule_new:
84 * @states: An #AtspiStateSet specifying the states to match or NULL if none.
85 * @statematchtype: An #AtspiCollectionMatchType specifying how to interpret
87 * @attributes: (element-type gchar* gchar*): A #GHashTable specifying
88 * attributes to match. To specify multiple attribute values,
89 * separate each value with a :: If an attribute value contains a :,
90 * then it can be escaped by preceding it with a \. A backslash can
91 * likewise be escaped by inserting a double backslash.
92 * @attributematchtype: An #AtspiCollectionMatchType specifying how to
93 * interpret @attributes.
94 * @interfaces: (element-type gchar*): An array of interfaces to match, or
95 * NULL if not applicable. Interface names should be specified
96 * by their DBus names (org.a11y.Atspi.Accessible,
97 * org.a11y.Atspi.Component, etc).
98 * @interfacematchtype: An #AtspiCollectionMatchType specifying how to
99 * interpret @interfaces.
100 * @roles: (element-type AtspiRole): A #GArray of roles to match, or NULL if
102 * @rolematchtype: An #AtspiCollectionMatchType specifying how to
104 * @invert: if #TRUE, the match rule should be denied (inverted); if #FALSE,
105 * it should not. For example, if the match rule defines that a match is
106 * an object of ROLE_HEADING which has STATE_FOCUSABLE and a click action,
107 * inverting it would match all objects that are not of ROLE_HEADING,
108 * focusable and clickable at the same time.
110 * Creates a new #AtspiMatchRule with specified @states, @attributes,
111 * @interfaces, and @roles.
113 * Returns: (transfer full): A new #AtspiMatchRule.
116 atspi_match_rule_new (AtspiStateSet *states,
117 AtspiCollectionMatchType statematchtype,
118 GHashTable *attributes,
119 AtspiCollectionMatchType attributematchtype,
121 AtspiCollectionMatchType rolematchtype,
123 AtspiCollectionMatchType interfacematchtype,
126 AtspiMatchRule *rule = g_object_new (ATSPI_TYPE_MATCH_RULE, NULL);
130 rule->states = g_object_ref (states);
131 rule->statematchtype = statematchtype;
135 GHashTableIter hash_table_iter;
137 rule->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
138 (GDestroyNotify) g_free,
139 (GDestroyNotify) g_free);
140 g_hash_table_iter_init (&hash_table_iter, attributes);
141 while (g_hash_table_iter_next (&hash_table_iter, (gpointer *)&key,
143 g_hash_table_insert (rule->attributes, g_strdup (key), g_strdup (value));
145 rule->attributes = NULL;
146 rule->attributematchtype = attributematchtype;
150 rule->interfaces = g_array_new (TRUE, TRUE, sizeof (gchar *));
151 for (i = 0; i < interfaces->len; i++)
153 gchar *val = g_strdup (g_array_index (interfaces, gchar *, i));
154 rule->interfaces = g_array_append_val (rule->interfaces, val);
157 rule->interfacematchtype = interfacematchtype;
161 for (i = 0; i < roles->len; i++)
163 AtspiRole role = g_array_index (roles, AtspiRole, i);
165 rule->roles [role / 32] |= (1 << (role % 32));
167 g_warning ("Atspi: unexpected role %d\n", role);
171 rule->roles [0] = rule->roles [1] = 0;
172 rule->rolematchtype = rolematchtype;
174 rule->invert = invert;
180 append_entry (gpointer key, gpointer val, gpointer data)
182 DBusMessageIter *iter = data;
183 DBusMessageIter iter_entry;
185 if (!dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL,
188 dbus_message_iter_append_basic (&iter_entry, DBUS_TYPE_STRING, &key);
189 dbus_message_iter_append_basic (&iter_entry, DBUS_TYPE_STRING, &val);
190 dbus_message_iter_close_container (iter, &iter_entry);
194 _atspi_match_rule_marshal (AtspiMatchRule *rule, DBusMessageIter *iter)
196 DBusMessageIter iter_struct, iter_array, iter_dict;
197 dbus_int32_t states [2];
198 dbus_int32_t d_statematchtype = rule->statematchtype;
199 dbus_int32_t d_attributematchtype = rule->attributematchtype;
200 dbus_int32_t d_interfacematchtype = rule->interfacematchtype;
201 dbus_uint32_t d_rolematchtype = rule->rolematchtype;
202 dbus_bool_t d_invert = rule->invert;
206 if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
213 states [0] = rule->states->states & 0xffffffff;
214 states [1] = rule->states->states >> 32;
218 states [0] = states [1] = 0;
220 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i", &iter_array);
221 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [0]);
222 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [1]);
223 dbus_message_iter_close_container (&iter_struct, &iter_array);
224 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_statematchtype);
227 if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}",
230 if (rule->attributes)
231 g_hash_table_foreach (rule->attributes, append_entry, &iter_dict);
232 dbus_message_iter_close_container (&iter_struct, &iter_dict);
233 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_attributematchtype);
235 if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i",
238 d_role = rule->roles [0];
239 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
240 d_role = rule->roles [1];
241 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
242 d_role = rule->roles [2];
243 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
244 d_role = rule->roles [3];
245 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
246 dbus_message_iter_close_container (&iter_struct, &iter_array);
247 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32,
251 if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
254 if (rule->interfaces)
256 for (i = 0; i < rule->interfaces->len; i++)
258 char *val = g_array_index (rule->interfaces, gchar *, i);
259 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &val);
262 dbus_message_iter_close_container (&iter_struct, &iter_array);
263 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_interfacematchtype);
265 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &d_invert);
267 dbus_message_iter_close_container (iter, &iter_struct);