Add navigation helper functions for screen-reader and friends (part 2)
[platform/upstream/at-spi2-core.git] / atspi / atspi-stateset.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
7  * Copyright 2010, 2011 Novell, Inc.
8  *
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.
13  *
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.
18  *
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.
23  */
24
25 #include "atspi-private.h"
26
27 static void atspi_state_set_class_init (AtspiStateSetClass *klass);
28
29 G_DEFINE_TYPE (AtspiStateSet, atspi_state_set, G_TYPE_OBJECT)
30
31 static void
32 atspi_state_set_init (AtspiStateSet *set)
33 {
34   set->states = 0;
35 }
36
37 static void
38 atspi_state_set_class_init (AtspiStateSetClass* klass)
39 {
40 }
41
42 /**
43  * atspi_state_set_new:
44  * @states: (element-type AtspiStateType): An array of states with which the
45  *          method initializes the state set.
46  *
47  * Generates an #AtspiStateSet with the given @states.
48  *
49  * Returns: A new #AtspiStateSet with the given states.
50  **/
51 AtspiStateSet *
52 atspi_state_set_new (GArray *states)
53 {
54   AtspiStateSet *set = g_object_new (ATSPI_TYPE_STATE_SET, NULL);
55   gint i;
56
57   if (!set || !states)
58     return set;
59
60   for (i = 0; i < states->len; i++)
61     atspi_state_set_add (set, g_array_index (states, AtspiStateType, i));
62   return set;
63 }
64
65 AtspiStateSet *
66 _atspi_state_set_new_internal (AtspiAccessible *accessible, gint64 states)
67 {
68   AtspiStateSet *set;
69   
70   set = g_object_new (ATSPI_TYPE_STATE_SET, NULL);
71   g_return_val_if_fail (set != NULL, NULL);
72
73   set->accessible = accessible;
74   set->states = states;
75   return set;
76 }
77
78 /**
79  * atspi_state_set_set_by_name:
80  * @set: a pointer to the #AtspiStateSet object on which to operate.
81  * @name: a string corresponding to a state name.
82  * @enabled: if #TRUE, @name should be enabled in the @set in question;
83  *          otherwise, it should be disabled.
84  *
85  * Enables/disables a state in an #AtspiStateSet according to its @name.
86  **/
87 void
88 atspi_state_set_set_by_name (AtspiStateSet *set, const gchar *name, gboolean enabled)
89 {
90   GTypeClass *type_class;
91   GEnumValue *value;
92
93   if (set->accessible &&
94       !(set->accessible->cached_properties & ATSPI_CACHE_STATES))
95     return;
96
97   type_class = g_type_class_ref (ATSPI_TYPE_STATE_TYPE);
98
99   value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name);
100
101   if (!value)
102   {
103     g_warning ("AT-SPI: Attempt to set unknown state '%s'", name);
104     return;
105   }
106
107   if (enabled)
108     set->states |= ((gint64)1 << value->value);
109   else
110     set->states &= ~((gint64)1 << value->value);
111
112   g_type_class_unref (type_class);
113 }
114
115 static void
116 refresh_states (AtspiStateSet *set)
117 {
118   GArray *state_array;
119   dbus_uint32_t *states;
120
121   if (!set->accessible ||
122       (set->accessible->cached_properties & ATSPI_CACHE_STATES))
123     return;
124
125   if (!_atspi_dbus_call (set->accessible, atspi_interface_accessible, "GetState", NULL, "=>au", &state_array))
126     return;
127
128   states = (dbus_uint32_t *) state_array->data;
129
130   set->states = ((gint64)states [1]) << 32;
131   set->states |= (gint64) states [0];
132   g_array_free (state_array, TRUE);
133 }
134
135 /**
136  * atspi_state_set_add:
137  * @set: a pointer to the #AtspiStateSet object on which to operate.
138  * @state: an #AtspiStateType to be added to the specified #AtspiStateSet.
139  *
140  * Adds a particular #AtspiState to an #AtspiStateSet (i.e. sets the
141  *       given state to #TRUE in the stateset).
142  *
143  **/
144 void
145 atspi_state_set_add (AtspiStateSet *set, AtspiStateType state)
146 {
147   g_return_if_fail (set != NULL);
148   set->states |= (((gint64)1) << state);
149 }
150
151 /**
152  * atspi_state_set_compare:
153  * @set: a pointer to the first #AtspiStateSet object on which to operate.
154  * @set2: a pointer to the second #AtspiStateSet object on which to operate.
155  *
156  * Determines the differences between two instances of #AtspiStateSet.
157  *
158  * @see #atspi_state_set_equals.
159  *
160  * Returns: (transfer full): an #AtspiStateSet object containing all states
161  * contained on one of the two sets but not the other.
162  *
163  **/
164 AtspiStateSet *
165 atspi_state_set_compare (AtspiStateSet *set,
166                          AtspiStateSet *set2)
167 {
168   g_return_val_if_fail (set != NULL, NULL);
169   g_return_val_if_fail (set2 != NULL, NULL);
170
171   return _atspi_state_set_new_internal (NULL, set->states ^ set2->states);
172 }
173
174 /**
175  * atspi_state_set_contains:
176  * @set: a pointer to the #AtspiStateSet object on which to operate.
177  * @state: an #AtspiStateType for which the specified #AtspiStateSet
178  *          will be queried.
179  *
180  * Determines whether a given #AtspiStateSet includes a given state; that is,
181  *          whether @state is true for the @set in question.
182  *
183  * Returns: #TRUE if @state is true/included in the given #AtspiStateSet,
184  *          otherwise #FALSE.
185  *
186  **/
187 gboolean
188 atspi_state_set_contains (AtspiStateSet *set,
189                              AtspiStateType state)
190 {
191   if (!set)
192     return FALSE;
193   refresh_states (set);
194   return (set->states & ((gint64)1 << state)) ? TRUE : FALSE;
195 }
196
197 /**
198  * atspi_state_set_equals:
199  * @set: a pointer to the first #AtspiStateSet object on which to operate.
200  * @set2: a pointer to the second #AtspiStateSet object on which to operate.
201  *
202  * Determines whether two instances of #AtspiStateSet are equivalent (i.e.
203  *          consist of the same #AtspiStates).  Useful for checking multiple
204  *          state variables at once.
205  *
206  * @see #atspi_state_set_compare.
207  *
208  * Returns: #TRUE if the two #AtspiStateSets are equivalent,
209  * otherwise #FALSE.
210  *
211  **/
212 gboolean
213 atspi_state_set_equals (AtspiStateSet *set,
214                            AtspiStateSet *set2)
215 {
216   if (set == set2)
217     return TRUE;
218   if (set == NULL || set2 == NULL)
219     return FALSE;
220   return (set->states == set2->states);
221 }
222
223 /**
224  * atspi_state_set_get_states:
225  * @set: The #AtspiStateSet to be queried.
226  *
227  * Returns the states in an #AtspiStateSet as an array.
228  *
229  * Returns: (element-type AtspiStateType) (transfer full): A #GArray of state
230  *          types representing the current state.
231  **/
232 GArray *
233 atspi_state_set_get_states (AtspiStateSet *set)
234 {
235   gint i = 0;
236   guint64 val = 1;
237   GArray *ret;
238
239   g_return_val_if_fail (set != NULL, NULL);
240   refresh_states (set);
241   ret = g_array_new (TRUE, TRUE, sizeof (AtspiStateType));
242   if (!ret)
243     return NULL;
244   for (i = 0; i < 64; i++)
245   {
246     if (set->states & val)
247       ret = g_array_append_val (ret, i);
248     val <<= 1;
249   }
250   return ret;
251 }
252
253 /**
254  * atspi_state_set_is_empty:
255  * @set: The #AtspiStateSet to query.
256  *
257  * Returns: #TRUE if the state set contains no states; #FALSE otherwise.
258  **/
259 gboolean
260 atspi_state_set_is_empty (AtspiStateSet *set)
261 {
262   return (set->states == 0);
263 }
264
265 /**
266  * atspi_state_set_remove:
267  * @set: a pointer to the #AtspiStateSet object on which to operate.
268  * @state: an #AtspiStateType to remove from the specified @set.
269  *
270  * Removes a particular #AtspiState to an #AtspiStateSet (i.e. sets the
271  *       given state to #FALSE in the stateset.)
272  *
273  **/
274 void
275 atspi_state_set_remove (AtspiStateSet *set, AtspiStateType state)
276 {
277   g_return_if_fail (set != NULL);
278   set->states &= ~((gint64)1 << state);
279 }