Added atk tests
[platform/core/uifw/at-spi2-atk.git] / atk-tests / MyAtkComponent.c
1 #include "MyAtkComponent.h"
2 #include <stdio.h>
3
4 //*************************implementation***********************
5 static MyParentChildClass *component_parent_class = NULL;
6 //current focus object
7 static AtkComponent* focus_object = NULL;
8
9 static guint focus_signal_id = 0;
10 /*
11  * Because of implementation of AtkUtils, we need to ensure that list of focus_trackers 
12  * is not empty. Otherwise function atk_focus_tracker_notify will not change focus.
13  */
14 static guint focus_tracker_id = 0;
15 static void my_event_listener(AtkObject* obj)
16 {
17     //simply exist for register as focus_tracker
18 }
19 /*
20  * If this flag is TRUE, then focus cannot be changed until someone clears the flag
21  * via my_atk_component_set_modal(FALSE).
22  */
23 static gboolean is_modal = FALSE;
24 //for debug
25 void print_extent(AtkRectangle *extent)
26 {
27     printf("{%d,%d,%d,%d}", extent->x, extent->y, extent->width, extent->height);
28 }
29 //for internal use
30 static void emit_bounds_changed(MyAtkComponent *component)
31 {
32     static guint bounds_changed_id = 0;
33     if(bounds_changed_id == 0)
34     {
35         bounds_changed_id = g_signal_lookup("bounds-changed", ATK_TYPE_COMPONENT);
36     }
37     AtkRectangle *param = g_boxed_copy(ATK_TYPE_RECTANGLE, &(component->extent));
38     g_signal_emit(component, bounds_changed_id, 0, param);
39 }
40 static void change_focus(AtkComponent* component, gboolean is_gain)
41 {
42     const gchar* state_name = atk_state_type_get_name(ATK_STATE_FOCUSED);
43     
44     g_signal_emit_by_name(component, "focus-event", is_gain);
45     g_signal_emit_by_name(component, "state-change::focused",
46         state_name, is_gain);
47     
48     AtkObject* parent = atk_object_get_parent((AtkObject*)component);
49     if(parent != NULL)
50     {
51         AtkStateSet* stateSet = atk_object_ref_state_set(parent);
52         if(atk_state_set_contains_state(stateSet, ATK_STATE_MANAGES_DESCENDANTS))
53             g_signal_emit_by_name(parent, "active-descendant-changed",
54                 atk_get_focus_object());
55         g_object_unref(stateSet);
56     }
57 }
58 //implementation of virtual functions
59 //******************ref_state_set(AtkObject)*****************************
60 static AtkStateSet* my_atk_component_ref_state_set(AtkObject *object)
61 {
62     MyAtkComponent *self = (MyAtkComponent*)object;
63     
64     AtkStateSet* result = ((AtkObjectClass*)component_parent_class)->
65         ref_state_set(object);
66     if(self->is_manage_descendants) 
67         atk_state_set_add_state(result, ATK_STATE_MANAGES_DESCENDANTS);
68     return result;
69 }
70 //******************get_size*******************
71 static void my_atk_component_get_size(AtkComponent *component, gint *width, gint *height)
72 {
73     g_return_if_fail(MY_IS_ATK_COMPONENT(component));
74     
75     MyAtkComponent *self = MY_ATK_COMPONENT(component);
76     *width = self->extent.width;
77     *height = self->extent.height;
78 }
79 //*********************get_position*******************
80 static void my_atk_component_get_position(AtkComponent *component, gint *x, gint *y, AtkCoordType coord_type)
81 {
82     g_return_if_fail(MY_IS_ATK_COMPONENT(component));
83     
84     MyAtkComponent *self = MY_ATK_COMPONENT(component);
85     *x = self->extent.x;
86     *y = self->extent.y;
87     
88 //**********************get_extents*******************
89 }
90 static void my_atk_component_get_extents(AtkComponent *component, gint *x, gint *y,
91     gint *width, gint *height, AtkCoordType coord_type)
92 {
93     g_return_if_fail(MY_IS_ATK_COMPONENT(component));
94     
95     MyAtkComponent *self = MY_ATK_COMPONENT(component);
96     *x = self->extent.x;
97     *y = self->extent.y;
98     *width = self->extent.width;
99     *height = self->extent.height;
100 }
101
102 //**************************set_size*******************
103 static gboolean my_atk_component_set_size(AtkComponent *component, gint width, gint height)
104 {
105     g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
106     
107     MyAtkComponent *self = MY_ATK_COMPONENT(component);
108     if(self->is_extent_may_changed)
109     {
110         self->extent.width = width;
111         self->extent.height = height;
112     
113         emit_bounds_changed(self);
114         
115         return TRUE;
116     }
117     return FALSE;
118 }
119 //**************************set_position********************
120 static gboolean my_atk_component_set_position(AtkComponent *component,
121     gint x, gint y, AtkCoordType coord_type)
122 {
123     g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
124     
125     MyAtkComponent *self = MY_ATK_COMPONENT(component);
126     if(self->is_extent_may_changed)
127     {
128         self->extent.x = x;
129         self->extent.y = y;
130         
131         emit_bounds_changed(self);
132
133         return TRUE;
134     }
135     return FALSE;
136 }
137 //*************************************set_extents***************
138 static gboolean my_atk_component_set_extents(AtkComponent *component,
139     gint x, gint y, gint width, gint height, AtkCoordType coord_type)
140 {
141     g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
142     
143     MyAtkComponent *self = MY_ATK_COMPONENT(component);
144     
145     if(self->is_extent_may_changed)
146     {
147         self->extent.x = x;
148         self->extent.y = y;
149         self->extent.width = width;
150         self->extent.height = height;
151         
152         emit_bounds_changed(self);
153         
154         return TRUE;
155     }
156     return FALSE;
157 }
158 //**************************get_layer****************
159 static AtkLayer my_atk_component_get_layer(AtkComponent *component)
160 {
161     g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), ATK_LAYER_INVALID);
162     
163     MyAtkComponent *self = MY_ATK_COMPONENT(component);
164     return self->layer;
165 }
166 //**************************get_mdi_zorder****************
167 static gint my_atk_component_get_mdi_zorder(AtkComponent *component)
168 {
169     g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), G_MININT);
170     
171     MyAtkComponent *self = MY_ATK_COMPONENT(component);
172     return self->zorder;
173 }
174 //***********************contains**********************
175 static gboolean my_atk_component_contains(AtkComponent *component,
176     gint x, gint y, AtkCoordType coord_type)
177 {
178     g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
179     //for extract extent
180     gint x_tmp, y_tmp, width_tmp, height_tmp;
181     my_atk_component_get_extents(component, &x_tmp, &y_tmp, &width_tmp, &height_tmp, coord_type);
182     
183     if( (x >= x_tmp) &&(y >= y_tmp) &&(x < x_tmp + width_tmp) && (y < y_tmp + height_tmp) )
184     {
185         return TRUE;
186     }
187     else
188     {
189         return FALSE;
190     }
191 }
192 //**********************ref_accessible_at_point***********************
193 /*
194  * Retuns accessible child that implements AtkCOmponent and contains the given point.
195  */
196 static AtkObject* my_atk_component_ref_accessible_at_point(AtkComponent* component,
197     gint x, gint y, AtkCoordType coord_type)
198 {
199     g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), NULL);
200     gint i;
201     
202     gint n_children = atk_object_get_n_accessible_children((AtkObject*)component);
203     for(i = 0; i < n_children; i++)
204     {
205         AtkObject *child = atk_object_ref_accessible_child((AtkObject*)component, i);
206         if(ATK_IS_COMPONENT(child)
207             && atk_component_contains((AtkComponent*)child, x, y, coord_type))
208         {
209             return child;
210         }
211         g_object_unref(child);
212     }
213     return NULL;
214 }
215 //*************************************grab_focus*********************************
216 static gboolean my_atk_component_grab_focus(AtkComponent* component)
217 {
218     if(component == focus_object)
219     { 
220         //Already has focus
221         return TRUE;
222     }
223     if(is_modal)
224     {
225         //cannot grab focus
226         return FALSE;
227     }
228     AtkComponent *focus_object_old = focus_object;
229     focus_object = component;
230     
231     atk_focus_tracker_notify((AtkObject*)component);
232     
233     if(focus_object_old != NULL)
234     {
235         //signals for object which lost focus
236         change_focus(focus_object_old, FALSE);
237     }
238     if(component != NULL)
239     {
240         //signals for object which grab focus
241         change_focus(component, TRUE);
242     }
243     return TRUE;
244 }
245 //***********************my_atk_component_add_focus_handler*********************
246 static guint my_atk_component_add_focus_handler(AtkComponent *component, AtkFocusHandler handler)
247 {
248     g_return_val_if_fail(MY_IS_ATK_COMPONENT(component),0);
249     //verify whether handler already connect to object
250     gulong found_handler_id = g_signal_handler_find(component,
251         G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC,
252         focus_signal_id,
253         0,
254         NULL,
255         (gpointer)handler,
256         NULL);
257     if(found_handler_id == 0)
258     {
259         //handler hasn't been connected yet
260         return g_signal_connect_closure_by_id(component,
261             focus_signal_id,
262             0,
263             g_cclosure_new( (GCallback)handler,
264                 NULL,
265                 NULL),
266             NULL);
267     }
268     else/* found_handler_id != 0*/
269     {
270         //handler has already been connected
271         return 0;
272     }
273
274 }
275 //***********************my_atk_component_remove_focus_handler*********************
276 static void my_atk_component_remove_focus_handler(AtkComponent *component, guint handler_id)
277 {
278     g_signal_handler_disconnect(component, handler_id);
279 }
280 //***********************my_atk_component_set_modal(my function)***************
281 void my_atk_component_set_modal(gboolean value)
282 {
283     is_modal = value;
284 }
285 //******************my_atk_component_set_manage_descendants(my_function)*******
286 void my_atk_component_set_manage_descendants(MyAtkComponent* component, gboolean value)
287 {
288     if(component->is_manage_descendants == value)return;
289     component->is_manage_descendants = value;
290     g_signal_emit_by_name(component, "state-change::manages-descendants",
291         "manages-descendants", value);
292 }
293 //Others funtions
294 static void my_atk_component_instance_init(GTypeInstance *obj, gpointer g_class)
295 {
296     MyAtkComponent *self = (MyAtkComponent*)obj;
297     //set defaults values
298     self->extent.x = 0;
299     self->extent.y = 0;
300     self->extent.width = 10;
301     self->extent.height = 10;
302     self->is_extent_may_changed = TRUE;
303     self->layer = ATK_LAYER_INVALID;
304     self->zorder = -2147483648;
305 }
306 static void my_atk_component_instance_finalize(GObject* obj)
307 {
308     MyAtkComponent* component = (MyAtkComponent*)obj;
309
310     if(((AtkObject*)component) == atk_get_focus_object())
311     {
312         atk_focus_tracker_notify(NULL);
313     }
314 }
315
316 static void my_atk_component_class_init(gpointer g_class, gpointer class_data)
317 {
318     GObjectClass* g_object_class = (GObjectClass*)g_class;
319     AtkObjectClass* atkObject_class = (AtkObjectClass*)g_class;
320     //GObject virtual table
321     g_object_class->finalize = my_atk_component_instance_finalize;
322     //AtkObject virtual table
323     atkObject_class->ref_state_set = my_atk_component_ref_state_set;
324     //parent_class
325     component_parent_class = g_type_class_peek_parent(g_class);
326     //make focus_tracker's table not empty.
327     focus_tracker_id = atk_add_focus_tracker(my_event_listener);
328     //store "focus-event"-signal id
329     focus_signal_id = g_signal_lookup("focus-event",MY_TYPE_ATK_COMPONENT);
330 }
331 /*
332  * Though, according to the documentation, this function will never called for 
333  * static-registred types.
334  * Base_init function doesn't suite for this work,
335  * because it will called in every derived classes.
336  */
337 /*static void my_atk_component_class_finalize(gpointer g_class, gpointer class_data)
338 {
339     
340     if(focus_tracker_id != 0)
341     {
342         atk_remove_focus_tracker(focus_tracker_id);
343         focus_tracker_id = 0;
344     }
345 }*/
346 static void my_atk_component_interface_init(gpointer g_iface, gpointer iface_data)
347 {
348     AtkComponentIface *klass = (AtkComponentIface*)g_iface;
349     
350     klass->get_extents = my_atk_component_get_extents;
351     klass->get_position = my_atk_component_get_position;
352     klass->get_size = my_atk_component_get_size;
353     
354     klass->set_extents = my_atk_component_set_extents;
355     klass->set_position = my_atk_component_set_position;
356     klass->set_size = my_atk_component_set_size;
357     
358     klass->contains = my_atk_component_contains;
359     klass->ref_accessible_at_point = my_atk_component_ref_accessible_at_point;
360     
361     klass->get_layer = my_atk_component_get_layer;
362     klass->get_mdi_zorder = my_atk_component_get_mdi_zorder;
363     
364     klass->grab_focus = my_atk_component_grab_focus;
365     klass->add_focus_handler = my_atk_component_add_focus_handler;
366     klass->remove_focus_handler = my_atk_component_remove_focus_handler;
367 }
368
369 GType my_atk_component_get_type()
370 {
371     static GType type = 0;
372     if(type == 0)
373     {
374         static const GTypeInfo typeInfo = 
375         {
376             sizeof(MyAtkComponentClass),
377             NULL, //base_init
378             NULL, //base_finalize
379             my_atk_component_class_init, //class_init
380             NULL, //class_finalize
381             NULL, //class_data
382             sizeof(MyAtkComponent),
383             0, //n_preallocs
384             my_atk_component_instance_init //instance_init
385         };
386
387         static const GInterfaceInfo iface_info = 
388         {
389             my_atk_component_interface_init,    /* interface_init*/
390             NULL,                               /* interface_finalize*/
391             NULL                                /* interface_data */
392         };
393         type = g_type_register_static(MY_TYPE_PARENT_CHILD, "MyAtkComponent", &typeInfo, 0);
394         g_type_add_interface_static(type,
395             ATK_TYPE_COMPONENT,
396             &iface_info);
397     }
398     return type;    
399 }