]> Pileus Git - ~andy/gtk/blob - gtk/a11y/tests/testobject.c
gail: Move from modules/other/gail to gtk/a11y
[~andy/gtk] / gtk / a11y / tests / testobject.c
1 #include <gtk/gtk.h>
2 #include "testlib.h"
3
4 static void _print_accessible (AtkObject *obj);
5 static void _print_type (AtkObject *obj);
6 static void _print_states (AtkObject *obj);
7 static void _check_children (AtkObject *obj);
8 static void _check_relation (AtkObject *obj);
9 static void _create_event_watcher (void);
10 static void _focus_handler (AtkObject *obj, gboolean focus_in);
11 static gboolean _children_changed (GSignalInvocationHint *ihint,
12                                    guint                  n_param_values,
13                                    const GValue          *param_values,
14                                    gpointer               data);
15
16 static guint id;
17
18 static void _print_states (AtkObject *obj)
19 {
20   AtkStateSet *state_set;
21   gint i;
22
23   state_set = atk_object_ref_state_set (obj);
24
25   g_print ("*** Start states ***\n");
26   for (i = 0; i < 64; i++)
27     {
28        AtkStateType one_state;
29        const gchar *name;
30
31        if (atk_state_set_contains_state (state_set, i))
32          {
33            one_state = i;
34
35            name = atk_state_type_get_name (one_state);
36
37            if (name)
38              g_print("%s\n", name);
39          }
40     }
41   g_object_unref (state_set);
42   g_print ("*** End states ***\n");
43 }
44
45 static void _print_type (AtkObject *obj)
46 {
47   const gchar * typename = NULL;
48   const gchar * name = NULL;
49   AtkRole role;
50   static gboolean in_print_type = FALSE;
51    
52   if (GTK_IS_ACCESSIBLE (obj))
53     {
54       GtkWidget* widget = NULL;
55
56       widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
57       typename = g_type_name (G_OBJECT_TYPE (widget));
58       g_print ("Widget type name: %s\n", typename ? typename : "NULL");
59     }
60   typename = g_type_name (G_OBJECT_TYPE (obj));
61   g_print ("Accessible type name: %s\n", typename ? typename : "NULL");
62   name = atk_object_get_name (obj);
63   g_print("Accessible Name: %s\n", (name) ? name : "NULL");
64   role = atk_object_get_role (obj);
65   g_print ("Accessible Role: %s\n", atk_role_get_name (role));
66
67   if (ATK_IS_COMPONENT (obj))
68     {
69       gint x, y, width, height;
70       AtkStateSet *states;
71
72       _print_states (obj);
73       states = atk_object_ref_state_set (obj);
74       if (atk_state_set_contains_state (states, ATK_STATE_VISIBLE))
75         {
76           AtkObject *parent;
77
78           atk_component_get_extents (ATK_COMPONENT (obj), 
79                                      &x, &y, &width, &height, 
80                                      ATK_XY_SCREEN);
81           g_print ("ATK_XY_SCREEN: x: %d y: %d width: %d height: %d\n",
82                    x, y, width, height);
83
84           atk_component_get_extents (ATK_COMPONENT (obj), 
85                                      &x, &y, &width, &height, 
86                                      ATK_XY_WINDOW);
87           g_print ("ATK_XY_WINDOW: x: %d y: %d width: %d height: %d\n", 
88                    x, y, width, height);
89           if (atk_state_set_contains_state (states, ATK_STATE_SHOWING) &&
90               ATK_IS_TEXT (obj))
91             {
92               gint offset;
93
94               atk_text_get_character_extents (ATK_TEXT (obj), 1, 
95                                               &x, &y, &width, &height, 
96                                               ATK_XY_WINDOW);
97               g_print ("Character extents : %d %d %d %d\n", 
98                        x, y, width, height);
99               if (width != 0 && height != 0)
100                 {
101                   offset = atk_text_get_offset_at_point (ATK_TEXT (obj), 
102                                                          x, y, 
103                                                          ATK_XY_WINDOW);
104                   if (offset != 1)
105                     {
106                       g_print ("Wrong offset returned (%d) %d\n", 1, offset);
107                     }
108                 }
109             }
110           if (in_print_type)
111             return;
112
113           parent = atk_object_get_parent (obj);
114           if (!ATK_IS_COMPONENT (parent))
115             {
116               /* Assume toplevel */
117               g_object_unref (G_OBJECT (states));
118               return;
119             }
120 #if 0
121           obj1 = atk_component_ref_accessible_at_point (ATK_COMPONENT (parent),
122                                                         x, y, ATK_XY_WINDOW);
123           if (obj != obj1)
124             {
125               g_print ("Inconsistency between object and ref_accessible_at_point\n");
126               in_print_type = TRUE;
127               _print_type (obj1);
128               in_print_type = FALSE;
129             }
130 #endif
131         }
132       g_object_unref (G_OBJECT (states));
133     }
134 }
135
136 static void _print_accessible (AtkObject *obj)
137 {
138   GtkWidget* widget = NULL;
139   AtkObject* parent_atk;
140   AtkObject* ref_obj;
141   AtkRole    role;
142   static gboolean first_time = TRUE;
143
144   if (first_time)
145     {
146       first_time = FALSE;
147       atk_add_global_event_listener (_children_changed, 
148                                      "Atk:AtkObject:children_changed");
149     }
150
151   /*
152    * Check that the object returned by the atk_implementor_ref_accessible()
153    * for a widget is the same as the accessible object
154    */
155   if (GTK_IS_ACCESSIBLE (obj))
156     {
157       widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
158       ref_obj = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (widget));
159       g_assert (ref_obj == obj);
160       g_object_unref (G_OBJECT (ref_obj));
161     }
162   /*
163    * Add a focus handler so we see focus out events as well
164    */
165   if (ATK_IS_COMPONENT (obj))
166     atk_component_add_focus_handler (ATK_COMPONENT (obj), _focus_handler);
167   g_print ("Object:\n");
168   _print_type (obj);
169   _print_states (obj);
170
171   /*
172    * Get the parent object
173    */
174   parent_atk = atk_object_get_parent (obj);
175   if (parent_atk)
176     {
177       g_print ("Parent Object:\n");
178       _print_type (parent_atk);
179       parent_atk = atk_object_get_parent (parent_atk);
180       if (parent_atk)
181         {
182           g_print ("Grandparent Object:\n");
183           _print_type (parent_atk);
184         }
185     } 
186   else 
187     {
188       g_print ("No parent\n");
189     }
190
191   role = atk_object_get_role (obj);
192
193   if ((role == ATK_ROLE_FRAME) || (role == ATK_ROLE_DIALOG))
194     {
195       _check_children (obj);
196     }
197 }
198
199 static void _check_relation (AtkObject *obj)
200 {
201   AtkRelationSet* relation_set = atk_object_ref_relation_set (obj);
202   gint n_relations, i;
203
204   g_return_if_fail (relation_set);
205
206   n_relations = atk_relation_set_get_n_relations (relation_set);
207   for (i = 0; i < n_relations; i++)
208     {
209       AtkRelation* relation = atk_relation_set_get_relation (relation_set, i);
210
211       g_print ("Index: %d Relation type: %d Number: %d\n", i,
212                 atk_relation_get_relation_type (relation),
213                 atk_relation_get_target (relation)->len);
214     }
215   g_object_unref (relation_set);
216 }
217
218 static void _check_children (AtkObject *obj)
219 {
220   gint n_children, i;
221   AtkLayer layer;
222   AtkRole role;
223
224   g_print ("Start Check Children\n");
225   n_children = atk_object_get_n_accessible_children (obj);
226   g_print ("Number of children: %d\n", n_children);
227
228   role = atk_object_get_role (obj);
229
230   if (ATK_IS_COMPONENT (obj))
231     {
232       atk_component_add_focus_handler (ATK_COMPONENT (obj), _focus_handler);
233       layer = atk_component_get_layer (ATK_COMPONENT (obj));
234       if (role == ATK_ROLE_MENU)
235               g_assert (layer == ATK_LAYER_POPUP);
236       else
237               g_print ("Layer: %d\n", layer);
238     }
239
240   for (i = 0; i < n_children; i++)
241     {
242       AtkObject *child;
243       AtkObject *parent;
244       int j;
245
246       child = atk_object_ref_accessible_child (obj, i);
247       parent = atk_object_get_parent (child);
248       j = atk_object_get_index_in_parent (child);
249       _print_type (child);
250       _check_relation (child);
251       _check_children (child);
252       if (obj != parent)
253         {
254           g_print ("*** Inconsistency between atk_object_get_parent() and "
255                    "atk_object_ref_accessible_child() ***\n");
256           _print_type (child);
257           _print_type (obj);
258           if (parent)
259             _print_type (parent);
260         }
261       g_object_unref (G_OBJECT (child));
262                  
263       if (j != i)
264         g_print ("*** Inconsistency between parent and children %d %d ***\n",
265                  i, j);
266     }
267   g_print ("End Check Children\n");
268 }
269
270 static gboolean
271 _children_changed (GSignalInvocationHint *ihint,
272                    guint                  n_param_values,
273                    const GValue          *param_values,
274                    gpointer               data)
275 {
276   GObject *object;
277   guint index;
278   gpointer target;
279   const gchar *target_name = "NotAtkObject";
280
281   object = g_value_get_object (param_values + 0);
282   index = g_value_get_uint (param_values + 1);
283   target = g_value_get_pointer (param_values + 2);
284   if (G_IS_OBJECT (target))
285     {
286       if (ATK_IS_OBJECT (target))
287         {
288           target_name = atk_object_get_name (target);
289         }
290       if (!target_name) 
291         target_name = g_type_name (G_OBJECT_TYPE (G_OBJECT (target)));
292     }
293   else
294     {
295       if (!target)
296         {
297           AtkObject *child;
298
299           child = atk_object_ref_accessible_child (ATK_OBJECT (object), index);
300           if (child)
301             {
302               target_name = g_type_name (G_OBJECT_TYPE (G_OBJECT (child)));
303               g_object_unref (child);
304             }
305         }
306     }
307   g_print ("_children_watched: %s %s %s index: %d\n", 
308            g_type_name (G_OBJECT_TYPE (object)),
309            g_quark_to_string (ihint->detail),
310            target_name, index);
311   return TRUE;
312 }
313
314 static void
315 _create_event_watcher (void)
316 {
317   /*
318    * _print_accessible() will be called for an accessible object when its
319    * widget receives focus.
320    */
321   id = atk_add_focus_tracker (_print_accessible);
322 }
323
324 static void 
325 _focus_handler (AtkObject *obj, gboolean focus_in)
326 {
327   g_print ("In _focus_handler focus_in: %s\n", focus_in ? "true" : "false"); 
328   _print_type (obj);
329 }
330
331 int
332 gtk_module_init(gint argc, char* argv[])
333 {
334   g_print("testobject Module loaded\n");
335
336   _create_event_watcher();
337
338   return 0;
339 }