5 #include "my-atk-object.h"
6 #include "my-atk-component.h"
8 //*************************implementation***********************
9 static MyAtkObjectClass *component_parent_class = NULL;
10 //current focus object
11 static AtkComponent* focus_object = NULL;
13 static guint focus_signal_id = 0;
15 * Because of implementation of AtkUtils, we need to ensure that list of focus_trackers
16 * is not empty. Otherwise function atk_focus_tracker_notify will not change focus.
18 static guint focus_tracker_id = 0;
19 static void my_event_listener(AtkObject* obj)
21 //simply exist for register as focus_tracker
24 * If this flag is TRUE, then focus cannot be changed until someone clears the flag
25 * via my_atk_component_set_modal(FALSE).
27 static gboolean is_modal = FALSE;
29 void print_extent(AtkRectangle *extent)
31 printf("{%d,%d,%d,%d}", extent->x, extent->y, extent->width, extent->height);
34 static void emit_bounds_changed(MyAtkComponent *component)
36 static guint bounds_changed_id = 0;
37 if(bounds_changed_id == 0)
39 bounds_changed_id = g_signal_lookup("bounds-changed", ATK_TYPE_COMPONENT);
41 AtkRectangle *param = g_boxed_copy(ATK_TYPE_RECTANGLE, &(component->extent));
42 g_signal_emit(component, bounds_changed_id, 0, param);
44 static void change_focus(AtkComponent* component, gboolean is_gain)
46 const gchar* state_name = atk_state_type_get_name(ATK_STATE_FOCUSED);
48 g_signal_emit_by_name(component, "focus-event", is_gain);
49 g_signal_emit_by_name(component, "state-change::focused",
52 AtkObject* parent = atk_object_get_parent((AtkObject*)component);
55 AtkStateSet* stateSet = atk_object_ref_state_set(parent);
56 if(atk_state_set_contains_state(stateSet, ATK_STATE_MANAGES_DESCENDANTS))
57 g_signal_emit_by_name(parent, "active-descendant-changed",
58 atk_get_focus_object());
59 g_object_unref(stateSet);
62 //implementation of virtual functions
63 //******************ref_state_set(AtkObject)*****************************
64 static AtkStateSet* my_atk_component_ref_state_set(AtkObject *object)
66 MyAtkComponent *self = (MyAtkComponent*)object;
68 AtkStateSet* result = ((AtkObjectClass*)component_parent_class)->
69 ref_state_set(object);
70 if(self->is_manage_descendants)
71 atk_state_set_add_state(result, ATK_STATE_MANAGES_DESCENDANTS);
74 //******************get_size*******************
75 static void my_atk_component_get_size(AtkComponent *component, gint *width, gint *height)
77 g_return_if_fail(MY_IS_ATK_COMPONENT(component));
79 MyAtkComponent *self = MY_ATK_COMPONENT(component);
80 *width = self->extent.width;
81 *height = self->extent.height;
83 //*********************get_position*******************
84 static void my_atk_component_get_position(AtkComponent *component, gint *x, gint *y, AtkCoordType coord_type)
86 g_return_if_fail(MY_IS_ATK_COMPONENT(component));
88 MyAtkComponent *self = MY_ATK_COMPONENT(component);
92 //**********************get_extents*******************
94 static void my_atk_component_get_extents(AtkComponent *component, gint *x, gint *y,
95 gint *width, gint *height, AtkCoordType coord_type)
97 g_return_if_fail(MY_IS_ATK_COMPONENT(component));
99 MyAtkComponent *self = MY_ATK_COMPONENT(component);
102 *width = self->extent.width;
103 *height = self->extent.height;
106 //**************************set_size*******************
107 static gboolean my_atk_component_set_size(AtkComponent *component, gint width, gint height)
109 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
111 MyAtkComponent *self = MY_ATK_COMPONENT(component);
112 if(self->is_extent_may_changed)
114 self->extent.width = width;
115 self->extent.height = height;
117 emit_bounds_changed(self);
123 //**************************set_position********************
124 static gboolean my_atk_component_set_position(AtkComponent *component,
125 gint x, gint y, AtkCoordType coord_type)
127 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
129 MyAtkComponent *self = MY_ATK_COMPONENT(component);
130 if(self->is_extent_may_changed)
135 emit_bounds_changed(self);
141 //*************************************set_extents***************
142 static gboolean my_atk_component_set_extents(AtkComponent *component,
143 gint x, gint y, gint width, gint height, AtkCoordType coord_type)
145 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
147 MyAtkComponent *self = MY_ATK_COMPONENT(component);
149 if(self->is_extent_may_changed)
153 self->extent.width = width;
154 self->extent.height = height;
156 emit_bounds_changed(self);
162 //**************************get_layer****************
163 static AtkLayer my_atk_component_get_layer(AtkComponent *component)
165 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), ATK_LAYER_INVALID);
167 MyAtkComponent *self = MY_ATK_COMPONENT(component);
170 //**************************get_mdi_zorder****************
171 static gint my_atk_component_get_mdi_zorder(AtkComponent *component)
173 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), G_MININT);
175 MyAtkComponent *self = MY_ATK_COMPONENT(component);
178 //***********************contains**********************
179 static gboolean my_atk_component_contains(AtkComponent *component,
180 gint x, gint y, AtkCoordType coord_type)
182 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), FALSE);
184 gint x_tmp, y_tmp, width_tmp, height_tmp;
185 my_atk_component_get_extents(component, &x_tmp, &y_tmp, &width_tmp, &height_tmp, coord_type);
187 if( (x >= x_tmp) &&(y >= y_tmp) &&(x < x_tmp + width_tmp) && (y < y_tmp + height_tmp) )
196 //**********************ref_accessible_at_point***********************
198 * Retuns accessible child that implements AtkCOmponent and contains the given point.
200 static AtkObject* my_atk_component_ref_accessible_at_point(AtkComponent* component,
201 gint x, gint y, AtkCoordType coord_type)
203 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component), NULL);
206 gint n_children = atk_object_get_n_accessible_children((AtkObject*)component);
207 for(i = 0; i < n_children; i++)
209 AtkObject *child = atk_object_ref_accessible_child((AtkObject*)component, i);
210 if(ATK_IS_COMPONENT(child)
211 && atk_component_contains((AtkComponent*)child, x, y, coord_type))
215 g_object_unref(child);
219 //*************************************grab_focus*********************************
220 static gboolean my_atk_component_grab_focus(AtkComponent* component)
222 if(component == focus_object)
232 AtkComponent *focus_object_old = focus_object;
233 focus_object = component;
235 atk_focus_tracker_notify((AtkObject*)component);
237 if(focus_object_old != NULL)
239 //signals for object which lost focus
240 change_focus(focus_object_old, FALSE);
242 if(component != NULL)
244 //signals for object which grab focus
245 change_focus(component, TRUE);
249 //***********************my_atk_component_add_focus_handler*********************
250 static guint my_atk_component_add_focus_handler(AtkComponent *component, AtkFocusHandler handler)
252 g_return_val_if_fail(MY_IS_ATK_COMPONENT(component),0);
253 //verify whether handler already connect to object
254 gulong found_handler_id = g_signal_handler_find(component,
255 G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC,
261 if(found_handler_id == 0)
263 //handler hasn't been connected yet
264 return g_signal_connect_closure_by_id(component,
267 g_cclosure_new( (GCallback)handler,
272 else/* found_handler_id != 0*/
274 //handler has already been connected
279 //***********************my_atk_component_remove_focus_handler*********************
280 static void my_atk_component_remove_focus_handler(AtkComponent *component, guint handler_id)
282 g_signal_handler_disconnect(component, handler_id);
284 //***********************my_atk_component_set_modal(my function)***************
285 void my_atk_component_set_modal(gboolean value)
289 //******************my_atk_component_set_manage_descendants(my_function)*******
290 void my_atk_component_set_manage_descendants(MyAtkComponent* component, gboolean value)
292 if(component->is_manage_descendants == value)return;
293 component->is_manage_descendants = value;
294 g_signal_emit_by_name(component, "state-change::manages-descendants",
295 "manages-descendants", value);
298 static void my_atk_component_instance_init(GTypeInstance *obj, gpointer g_class)
300 MyAtkComponent *self = (MyAtkComponent*)obj;
301 //set defaults values
304 self->extent.width = 10;
305 self->extent.height = 10;
306 self->is_extent_may_changed = TRUE;
307 self->layer = ATK_LAYER_INVALID;
308 self->zorder = -2147;
310 static void my_atk_component_instance_finalize(GObject* obj)
312 MyAtkComponent* component = (MyAtkComponent*)obj;
314 if(((AtkObject*)component) == atk_get_focus_object())
316 atk_focus_tracker_notify(NULL);
320 static void my_atk_component_class_init(gpointer g_class, gpointer class_data)
322 GObjectClass* g_object_class = (GObjectClass*)g_class;
323 AtkObjectClass* atkObject_class = (AtkObjectClass*)g_class;
324 //GObject virtual table
325 g_object_class->finalize = my_atk_component_instance_finalize;
326 //AtkObject virtual table
327 atkObject_class->ref_state_set = my_atk_component_ref_state_set;
329 component_parent_class = g_type_class_peek_parent(g_class);
330 //make focus_tracker's table not empty.
331 focus_tracker_id = atk_add_focus_tracker(my_event_listener);
332 //store "focus-event"-signal id
333 focus_signal_id = g_signal_lookup("focus-event",MY_TYPE_ATK_COMPONENT);
336 * Though, according to the documentation, this function will never called for
337 * static-registred types.
338 * Base_init function doesn't suite for this work,
339 * because it will called in every derived classes.
341 /*static void my_atk_component_class_finalize(gpointer g_class, gpointer class_data)
344 if(focus_tracker_id != 0)
346 atk_remove_focus_tracker(focus_tracker_id);
347 focus_tracker_id = 0;
350 static void my_atk_component_interface_init(gpointer g_iface, gpointer iface_data)
352 AtkComponentIface *klass = (AtkComponentIface*)g_iface;
354 klass->get_extents = my_atk_component_get_extents;
355 klass->get_position = my_atk_component_get_position;
356 klass->get_size = my_atk_component_get_size;
358 klass->set_extents = my_atk_component_set_extents;
359 klass->set_position = my_atk_component_set_position;
360 klass->set_size = my_atk_component_set_size;
362 klass->contains = my_atk_component_contains;
363 klass->ref_accessible_at_point = my_atk_component_ref_accessible_at_point;
365 klass->get_layer = my_atk_component_get_layer;
366 klass->get_mdi_zorder = my_atk_component_get_mdi_zorder;
368 klass->grab_focus = my_atk_component_grab_focus;
369 klass->add_focus_handler = my_atk_component_add_focus_handler;
370 klass->remove_focus_handler = my_atk_component_remove_focus_handler;
373 GType my_atk_component_get_type()
375 static GType type = 0;
378 static const GTypeInfo typeInfo =
380 sizeof(MyAtkComponentClass),
382 NULL, //base_finalize
383 my_atk_component_class_init, //class_init
384 NULL, //class_finalize
386 sizeof(MyAtkComponent),
388 my_atk_component_instance_init //instance_init
391 static const GInterfaceInfo iface_info =
393 my_atk_component_interface_init, /* interface_init*/
394 NULL, /* interface_finalize*/
395 NULL /* interface_data */
397 type = g_type_register_static(MY_TYPE_ATK_OBJECT, "MyAtkComponent", &typeInfo, 0);
398 g_type_add_interface_static(type,