*
* Copyright 2001, 2002 Sun Microsystems Inc.,
* Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
}
static void
-atspi_match_rule_finalize (GObject *obj)
+atspi_match_rule_dispose (GObject *object)
{
- AtspiMatchRule *rule = ATSPI_MATCH_RULE (obj);
+ AtspiMatchRule *rule = ATSPI_MATCH_RULE (object);
if (rule->states)
+ {
g_object_unref (rule->states);
+ rule->states = NULL;
+ }
+
if (rule->attributes)
+ {
g_hash_table_unref (rule->attributes);
- if (rule->roles)
- g_array_free (rule->roles, TRUE);
+ rule->attributes = NULL;
+ }
+
+ G_OBJECT_CLASS (atspi_match_rule_parent_class)->dispose (object);
+}
+
+static void
+atspi_match_rule_finalize (GObject *object)
+{
+ AtspiMatchRule *rule = ATSPI_MATCH_RULE (object);
+
/* TODO: Check that interfaces don't leak */
if (rule->interfaces)
g_array_free (rule->interfaces, TRUE);
+
+ if (rule->attributes)
+ g_hash_table_unref (rule->attributes);
+
+ G_OBJECT_CLASS (atspi_match_rule_parent_class)->finalize (object);
}
static void
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = atspi_match_rule_dispose;
object_class->finalize = atspi_match_rule_finalize;
}
/**
* atspi_match_rule_new:
- *
* @states: An #AtspiStateSet specifying the states to match or NULL if none.
* @statematchtype: An #AtspiCollectionMatchType specifying how to interpret
- * @states.
+ * @states.
* @attributes: (element-type gchar* gchar*): A #GHashTable specifying
- * attributes to match.
+ * attributes to match. To specify multiple attribute values,
+ * separate each value with a :: If an attribute value contains a :,
+ * then it can be escaped by preceding it with a \. A backslash can
+ * likewise be escaped by inserting a double backslash.
* @attributematchtype: An #AtspiCollectionMatchType specifying how to
- * interpret @attributes.
- * @roles: (element-type AtspiRole): A #GArray of roles to match, or NULL if
- * not applicable.
+ * interpret @attributes.
* @interfaces: (element-type gchar*): An array of interfaces to match, or
- * NUL if not appliable. Interface names should be specified
- * by their DBus names (org.a11y.Atspi.Accessible,
- * org.a11y.Atspi.Component, etc).
+ * NULL if not applicable. Interface names should be specified
+ * by their DBus names (org.a11y.Atspi.Accessible,
+ * org.a11y.Atspi.Component, etc).
* @interfacematchtype: An #AtspiCollectionMatchType specifying how to
- * interpret @interfaces.
- * @invert: Specifies whether results should be inverted.
- * TODO: Document this parameter better.
+ * interpret @interfaces.
+ * @roles: (element-type AtspiRole): A #GArray of roles to match, or NULL if
+ * not applicable.
+ * @rolematchtype: An #AtspiCollectionMatchType specifying how to
+ * interpret @roles.
+ * @invert: if #TRUE, the match rule should be denied (inverted); if #FALSE,
+ * it should not. For example, if the match rule defines that a match is
+ * an object of ROLE_HEADING which has STATE_FOCUSABLE and a click action,
+ * inverting it would match all objects that are not of ROLE_HEADING,
+ * focusable and clickable at the same time.
+ *
+ * Creates a new #AtspiMatchRule with specified @states, @attributes,
+ * @interfaces, and @roles.
*
* Returns: (transfer full): A new #AtspiMatchRule.
- */
+ **/
AtspiMatchRule *
atspi_match_rule_new (AtspiStateSet *states,
AtspiCollectionMatchType statematchtype,
AtspiCollectionMatchType attributematchtype,
GArray *roles,
AtspiCollectionMatchType rolematchtype,
+ GArray *interfaces,
+ AtspiCollectionMatchType interfacematchtype,
gboolean invert)
{
AtspiMatchRule *rule = g_object_new (ATSPI_TYPE_MATCH_RULE, NULL);
-
- if (!rule)
- return NULL;
+ int i;
if (states)
rule->states = g_object_ref (states);
rule->statematchtype = statematchtype;
if (attributes)
- rule->attributes = g_object_ref (attributes);
- rule->attributematchtype = attributematchtype;
+ {
+ GHashTableIter hash_table_iter;
+ gchar *key, *value;
+ rule->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+ g_hash_table_iter_init (&hash_table_iter, attributes);
+ while (g_hash_table_iter_next (&hash_table_iter, (gpointer *)&key,
+ (gpointer *)&value))
+ g_hash_table_insert (rule->attributes, g_strdup (key), g_strdup (value));
+ } else
+ rule->attributes = NULL;
+ rule->attributematchtype = attributematchtype;
+
+ if (interfaces)
+ rule->interfaces = g_array_ref (interfaces);
+ rule->interfacematchtype = interfacematchtype;
if (roles)
- rule->roles = g_array_ref(roles);
+ {
+ for (i = 0; i < roles->len; i++)
+ {
+ AtspiRole role = g_array_index (roles, AtspiRole, i);
+ if (role < 128)
+ rule->roles [role / 32] |= (1 << (role % 32));
+ else
+ g_warning ("Atspi: unexpected role %d\n", role);
+ }
+ }
+ else
+ rule->roles [0] = rule->roles [1] = 0;
rule->rolematchtype = rolematchtype;
rule->invert = invert;
}
static void
-append_entry (gpointer *key, gpointer *val, gpointer data)
+append_entry (gpointer key, gpointer val, gpointer data)
{
DBusMessageIter *iter = data;
DBusMessageIter iter_entry;
dbus_uint32_t d_rolematchtype = rule->rolematchtype;
dbus_bool_t d_invert = rule->invert;
gint i;
+ dbus_int32_t d_role;
- if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, "(aiiasiaiisib)",
+ if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
&iter_struct))
return FALSE;
{
states [0] = states [1] = 0;
}
- dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "u", &iter_array);
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i", &iter_array);
dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [0]);
dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [1]);
dbus_message_iter_close_container (&iter_struct, &iter_array);
dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_statematchtype);
/* attributes */
- if (!dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}",
+ if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}",
&iter_dict))
return FALSE;
- g_hash_table_foreach (rule->attributes, append_entry, &iter_dict);
- dbus_message_iter_close_container (iter, &iter_dict);
+ if (rule->attributes)
+ g_hash_table_foreach (rule->attributes, append_entry, &iter_dict);
+ dbus_message_iter_close_container (&iter_struct, &iter_dict);
dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_attributematchtype);
- /* roles */
if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i",
&iter_array))
return FALSE;
- if (rule->roles)
+ d_role = rule->roles [0];
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
+ d_role = rule->roles [1];
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
+ d_role = rule->roles [2];
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
+ d_role = rule->roles [3];
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
+ dbus_message_iter_close_container (&iter_struct, &iter_array);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32,
+ &d_rolematchtype);
+
+ /* interfaces */
+ if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
+ &iter_array))
+ return FALSE;
+ if (rule->interfaces)
{
- for (i = 0; i < rule->roles->len; i++)
+ for (i = 0; i < rule->interfaces->len; i++)
{
- dbus_int32_t d_role = g_array_index (rule->roles, AtspiRole, i);
- dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
+ char *val = g_array_index (rule->interfaces, gchar *, i);
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &val);
}
}
dbus_message_iter_close_container (&iter_struct, &iter_array);
- dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32,
- &d_rolematchtype);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_interfacematchtype);
dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &d_invert);