1 #include "MyAtkComponent.h"
4 //*************************implementation***********************
5 static MyParentChildClass *component_parent_class = NULL;
7 static AtkComponent* focus_object = NULL;
9 static guint focus_signal_id = 0;
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.
14 static guint focus_tracker_id = 0;
15 static void my_event_listener(AtkObject* obj)
17 //simply exist for register as focus_tracker
20 * If this flag is TRUE, then focus cannot be changed until someone clears the flag
21 * via my_atk_component_set_modal(FALSE).
23 static gboolean is_modal = FALSE;
25 void print_extent(AtkRectangle *extent)
27 printf("{%d,%d,%d,%d}", extent->x, extent->y, extent->width, extent->height);
30 static void emit_bounds_changed(MyAtkComponent *component)
32 static guint bounds_changed_id = 0;
33 if(bounds_changed_id == 0)
35 bounds_changed_id = g_signal_lookup("bounds-changed", ATK_TYPE_COMPONENT);
37 AtkRectangle *param = g_boxed_copy(ATK_TYPE_RECTANGLE, &(component->extent));
38 g_signal_emit(component, bounds_changed_id, 0, param);
40 static void change_focus(AtkComponent* component, gboolean is_gain)
42 const gchar* state_name = atk_state_type_get_name(ATK_STATE_FOCUSED);
44 g_signal_emit_by_name(component, "focus-event", is_gain);
45 g_signal_emit_by_name(component, "state-change::focused",
48 AtkObject* parent = atk_object_get_parent((AtkObject*)component);
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);
58 //implementation of virtual functions
59 //******************ref_state_set(AtkObject)*****************************
60 static AtkStateSet* my_atk_component_ref_state_set(AtkObject *object)
62 MyAtkComponent *self = (MyAtkComponent*)object;
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);
70 //******************get_size*******************
71 static void my_atk_component_get_size(AtkComponent *component, gint *width, gint *height)
73 g_return_if_fail(MY_IS_ATK_COMPONENT(component));
75 MyAtkComponent *self = MY_ATK_COMPONENT(component);
76 *width = self->extent.width;
77 *height = self->extent.height;
79 //*********************get_position*******************
80 static void my_atk_component_get_position(AtkComponent *component, gint *x, gint *y, AtkCoordType coord_type)
82 g_return_if_fail(MY_IS_ATK_COMPONENT(component));
84 MyAtkComponent *self = MY_ATK_COMPONENT(component);
88 //**********************get_extents*******************
90 static void my_atk_component_get_extents(AtkComponent *component, gint *x, gint *y,
91 gint *width, gint *height, AtkCoordType coord_type)
93 g_return_if_fail(MY_IS_ATK_COMPONENT(component));
95 MyAtkComponent *self = MY_ATK_COMPONENT(component);
98 *width = self->extent.width;
99 *height = self->extent.height;
102 //**************************set_size*******************
103 static gboolean my_atk_component_set_size(AtkComponent *component, gint width, gint height)
105 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
107 MyAtkComponent *self = MY_ATK_COMPONENT(component);
108 if(self->is_extent_may_changed)
110 self->extent.width = width;
111 self->extent.height = height;
113 emit_bounds_changed(self);
119 //**************************set_position********************
120 static gboolean my_atk_component_set_position(AtkComponent *component,
121 gint x, gint y, AtkCoordType coord_type)
123 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
125 MyAtkComponent *self = MY_ATK_COMPONENT(component);
126 if(self->is_extent_may_changed)
131 emit_bounds_changed(self);
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)
141 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
143 MyAtkComponent *self = MY_ATK_COMPONENT(component);
145 if(self->is_extent_may_changed)
149 self->extent.width = width;
150 self->extent.height = height;
152 emit_bounds_changed(self);
158 //**************************get_layer****************
159 static AtkLayer my_atk_component_get_layer(AtkComponent *component)
161 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), ATK_LAYER_INVALID);
163 MyAtkComponent *self = MY_ATK_COMPONENT(component);
166 //**************************get_mdi_zorder****************
167 static gint my_atk_component_get_mdi_zorder(AtkComponent *component)
169 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), G_MININT);
171 MyAtkComponent *self = MY_ATK_COMPONENT(component);
174 //***********************contains**********************
175 static gboolean my_atk_component_contains(AtkComponent *component,
176 gint x, gint y, AtkCoordType coord_type)
178 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
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);
183 if( (x >= x_tmp) &&(y >= y_tmp) &&(x < x_tmp + width_tmp) && (y < y_tmp + height_tmp) )
192 //**********************ref_accessible_at_point***********************
194 * Retuns accessible child that implements AtkCOmponent and contains the given point.
196 static AtkObject* my_atk_component_ref_accessible_at_point(AtkComponent* component,
197 gint x, gint y, AtkCoordType coord_type)
199 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), NULL);
202 gint n_children = atk_object_get_n_accessible_children((AtkObject*)component);
203 for(i = 0; i < n_children; i++)
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))
211 g_object_unref(child);
215 //*************************************grab_focus*********************************
216 static gboolean my_atk_component_grab_focus(AtkComponent* component)
218 if(component == focus_object)
228 AtkComponent *focus_object_old = focus_object;
229 focus_object = component;
231 atk_focus_tracker_notify((AtkObject*)component);
233 if(focus_object_old != NULL)
235 //signals for object which lost focus
236 change_focus(focus_object_old, FALSE);
238 if(component != NULL)
240 //signals for object which grab focus
241 change_focus(component, TRUE);
245 //***********************my_atk_component_add_focus_handler*********************
246 static guint my_atk_component_add_focus_handler(AtkComponent *component, AtkFocusHandler handler)
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,
257 if(found_handler_id == 0)
259 //handler hasn't been connected yet
260 return g_signal_connect_closure_by_id(component,
263 g_cclosure_new( (GCallback)handler,
268 else/* found_handler_id != 0*/
270 //handler has already been connected
275 //***********************my_atk_component_remove_focus_handler*********************
276 static void my_atk_component_remove_focus_handler(AtkComponent *component, guint handler_id)
278 g_signal_handler_disconnect(component, handler_id);
280 //***********************my_atk_component_set_modal(my function)***************
281 void my_atk_component_set_modal(gboolean value)
285 //******************my_atk_component_set_manage_descendants(my_function)*******
286 void my_atk_component_set_manage_descendants(MyAtkComponent* component, gboolean value)
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);
294 static void my_atk_component_instance_init(GTypeInstance *obj, gpointer g_class)
296 MyAtkComponent *self = (MyAtkComponent*)obj;
297 //set defaults values
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;
306 static void my_atk_component_instance_finalize(GObject* obj)
308 MyAtkComponent* component = (MyAtkComponent*)obj;
310 if(((AtkObject*)component) == atk_get_focus_object())
312 atk_focus_tracker_notify(NULL);
316 static void my_atk_component_class_init(gpointer g_class, gpointer class_data)
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;
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);
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.
337 /*static void my_atk_component_class_finalize(gpointer g_class, gpointer class_data)
340 if(focus_tracker_id != 0)
342 atk_remove_focus_tracker(focus_tracker_id);
343 focus_tracker_id = 0;
346 static void my_atk_component_interface_init(gpointer g_iface, gpointer iface_data)
348 AtkComponentIface *klass = (AtkComponentIface*)g_iface;
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;
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;
358 klass->contains = my_atk_component_contains;
359 klass->ref_accessible_at_point = my_atk_component_ref_accessible_at_point;
361 klass->get_layer = my_atk_component_get_layer;
362 klass->get_mdi_zorder = my_atk_component_get_mdi_zorder;
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;
369 GType my_atk_component_get_type()
371 static GType type = 0;
374 static const GTypeInfo typeInfo =
376 sizeof(MyAtkComponentClass),
378 NULL, //base_finalize
379 my_atk_component_class_init, //class_init
380 NULL, //class_finalize
382 sizeof(MyAtkComponent),
384 my_atk_component_instance_init //instance_init
387 static const GInterfaceInfo iface_info =
389 my_atk_component_interface_init, /* interface_init*/
390 NULL, /* interface_finalize*/
391 NULL /* interface_data */
393 type = g_type_register_static(MY_TYPE_PARENT_CHILD, "MyAtkComponent", &typeInfo, 0);
394 g_type_add_interface_static(type,