Set vtable entry for default implementations (atk_text_get_range_extents):
[platform/upstream/atk.git] / atk / atkcomponent.c
1 /* ATK -  Accessibility Toolkit
2  * Copyright 2001 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20
21 #include "atkcomponent.h"
22
23 static void       atk_component_base_init (AtkComponentIface *class);
24
25 static gboolean   atk_component_real_contains                (AtkComponent *component,
26                                                               gint         x,
27                                                               gint         y,
28                                                               AtkCoordType coord_type);
29
30 static AtkObject* atk_component_real_ref_accessible_at_point (AtkComponent *component,
31                                                               gint         x,
32                                                               gint         y,
33                                                               AtkCoordType coord_type);
34
35 static void      atk_component_real_get_position             (AtkComponent *component,
36                                                               gint         *x,
37                                                               gint         *y,
38                                                               AtkCoordType coord_type);
39
40 static void      atk_component_real_get_size                 (AtkComponent *component,
41                                                               gint         *width,
42                                                               gint         *height);
43
44 GType
45 atk_component_get_type (void)
46 {
47   static GType type = 0;
48
49   if (!type) {
50     static const GTypeInfo tinfo =
51     {
52       sizeof (AtkComponentIface),
53       (GBaseInitFunc) atk_component_base_init,
54       (GBaseFinalizeFunc) NULL,
55
56     };
57
58     type = g_type_register_static (G_TYPE_INTERFACE, "AtkComponent", &tinfo, 0);
59   }
60
61   return type;
62 }
63
64 static void
65 atk_component_base_init (AtkComponentIface *class)
66 {
67   static gboolean initialized = FALSE;
68
69   if (! initialized)
70     {
71       class->ref_accessible_at_point = atk_component_real_ref_accessible_at_point;
72       class->contains = atk_component_real_contains;
73       class->get_position = atk_component_real_get_position;
74       class->get_size = atk_component_real_get_size;
75     }
76 }
77
78
79 /**
80  * atk_component_add_focus_handler:
81  * @component: The #AtkComponent to attach the @handler to
82  * @handler: The #AtkFocusHandler to be attached to @component
83  *
84  * Add the specified handler to the set of functions to be called 
85  * when this object receives focus events (in or out). If the handler is
86  * already added it is not added again
87  *
88  * Returns: a handler id which can be used in atk_component_remove_focus_handler
89  * or zero if the handler was already added.
90  **/
91 guint
92 atk_component_add_focus_handler (AtkComponent    *component,
93                                  AtkFocusHandler handler)
94 {
95   AtkComponentIface *iface = NULL;
96   g_return_val_if_fail (ATK_IS_COMPONENT (component), 0);
97
98   iface = ATK_COMPONENT_GET_IFACE (component);
99
100   if (iface->add_focus_handler)
101     return (iface->add_focus_handler) (component, handler);
102   else
103     return 0;
104 }
105
106 /**
107  * atk_component_remove_focus_handler:
108  * @component: the #AtkComponent to remove the focus handler from
109  * @handler_id: the handler id of the focus handler to be removed
110  * from @component
111  *
112  * Remove the handler specified by @handler_id from the list of
113  * functions to be executed when this object receives focus events 
114  * (in or out).
115  **/
116 void
117 atk_component_remove_focus_handler (AtkComponent    *component,
118                                     guint           handler_id)
119 {
120   AtkComponentIface *iface = NULL;
121   g_return_if_fail (ATK_IS_COMPONENT (component));
122
123   iface = ATK_COMPONENT_GET_IFACE (component);
124
125   if (iface->remove_focus_handler)
126     (iface->remove_focus_handler) (component, handler_id);
127 }
128
129 /**
130  * atk_component_contains:
131  * @component: the #AtkComponent
132  * @x: x coordinate
133  * @y: y coordinate
134  * @coord_type: specifies whether the coordinates are relative to the screen
135  * or to the components top level window
136  *
137  * Checks whether the specified point is within the extent of the @component.
138  *
139  * Returns: %TRUE or %FALSE indicating whether the specified point is within
140  * the extent of the @component or not
141  **/
142 gboolean
143 atk_component_contains (AtkComponent    *component,
144                         gint            x,
145                         gint            y,
146                         AtkCoordType    coord_type)
147 {
148   AtkComponentIface *iface = NULL;
149   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
150
151   iface = ATK_COMPONENT_GET_IFACE (component);
152
153   if (iface->contains)
154     return (iface->contains) (component, x, y, coord_type);
155   else
156     return FALSE;
157 }
158
159 /**
160  * atk_component_ref_accessible_at_point:
161  * @component: the #AtkComponent
162  * @x: x coordinate
163  * @y: y coordinate
164  * @coord_type: specifies whether the coordinates are relative to the screen
165  * or to the components top level window
166  *
167  * Gets a reference to the accessible child, if one exists, at the
168  * coordinate point specified by @x and @y.
169  *
170  * Returns: a reference to the accessible child, if one exists
171  **/
172 AtkObject*
173 atk_component_ref_accessible_at_point (AtkComponent    *component,
174                                        gint            x,
175                                        gint            y,
176                                        AtkCoordType    coord_type)
177 {
178   AtkComponentIface *iface = NULL;
179   g_return_val_if_fail (ATK_IS_COMPONENT (component), NULL);
180
181   iface = ATK_COMPONENT_GET_IFACE (component);
182
183   if (iface->ref_accessible_at_point)
184     return (iface->ref_accessible_at_point) (component, x, y, coord_type);
185   else
186     return NULL;
187 }
188
189 /**
190  * atk_component_get_extents:
191  * @component: an #AtkComponent
192  * @x: address of #gint to put x coordinate
193  * @y: address of #gint to put y coordinate
194  * @width: address of #gint to put width
195  * @height: address of #gint to put height
196  * @coord_type: specifies whether the coordinates are relative to the screen
197  * or to the components top level window
198  *
199  * Gets the rectangle which gives the extent of the @component.
200  *
201  **/
202 void
203 atk_component_get_extents    (AtkComponent    *component,
204                               gint            *x,
205                               gint            *y,
206                               gint            *width,
207                               gint            *height,
208                               AtkCoordType    coord_type)
209 {
210   AtkComponentIface *iface = NULL;
211   gint local_x, local_y, local_width, local_height;
212   gint *real_x, *real_y, *real_width, *real_height;
213
214   g_return_if_fail (ATK_IS_COMPONENT (component));
215
216   if (x)
217     real_x = x;
218   else
219     real_x = &local_x;
220   if (y)
221     real_y = y;
222   else
223     real_y = &local_y;
224   if (width)
225     real_width = width;
226   else
227     real_width = &local_width;
228   if (height)
229     real_height = height;
230   else
231     real_height = &local_height;
232
233   iface = ATK_COMPONENT_GET_IFACE (component);
234
235   if (iface->get_extents)
236     (iface->get_extents) (component, real_x, real_y, real_width, real_height, coord_type);
237 }
238
239 /**
240  * atk_component_get_position:
241  * @component: an #AtkComponent
242  * @x: address of #gint to put x coordinate position
243  * @y: address of #gint to put y coordinate position
244  * @coord_type: specifies whether the coordinates are relative to the screen
245  * or to the components top level window
246  *
247  * Gets the position of @component in the form of 
248  * a point specifying @component's top-left corner.
249  **/
250 void
251 atk_component_get_position   (AtkComponent    *component,
252                               gint            *x,
253                               gint            *y,
254                               AtkCoordType    coord_type)
255 {
256   AtkComponentIface *iface = NULL;
257   gint local_x, local_y;
258   gint *real_x, *real_y;
259
260   g_return_if_fail (ATK_IS_COMPONENT (component));
261
262   if (x)
263     real_x = x;
264   else
265     real_x = &local_x;
266   if (y)
267     real_y = y;
268   else
269     real_y = &local_y;
270
271   iface = ATK_COMPONENT_GET_IFACE (component);
272
273   if (iface->get_position)
274     (iface->get_position) (component, real_x, real_y, coord_type);
275 }
276
277 /**
278  * atk_component_get_size:
279  * @component: an #AtkComponent
280  * @width: address of #gint to put width of @component
281  * @height: address of #gint to put height of @component
282  *
283  * Gets the size of the @component in terms of width and height.
284  **/
285 void
286 atk_component_get_size       (AtkComponent    *component,
287                               gint            *width,
288                               gint            *height)
289 {
290   AtkComponentIface *iface = NULL;
291   gint local_width, local_height;
292   gint *real_width, *real_height;
293
294   g_return_if_fail (ATK_IS_COMPONENT (component));
295
296   if (width)
297     real_width = width;
298   else
299     real_width = &local_width;
300   if (height)
301     real_height = height;
302   else
303     real_height = &local_height;
304
305   g_return_if_fail (ATK_IS_COMPONENT (component));
306
307   iface = ATK_COMPONENT_GET_IFACE (component);
308
309   if (iface->get_size)
310     (iface->get_size) (component, real_width, real_height);
311 }
312
313 /**
314  * atk_component_get_layer:
315  * @component: an #AtkComponent
316  *
317  * Gets the layer of the component.
318  *
319  * Returns: an #AtkLayer which is the layer of the component
320  **/
321 AtkLayer
322 atk_component_get_layer (AtkComponent *component) 
323 {
324   AtkComponentIface *iface;
325
326   g_return_val_if_fail (ATK_IS_COMPONENT (component), ATK_LAYER_INVALID);
327
328   iface = ATK_COMPONENT_GET_IFACE (component);
329   if (iface->get_layer)
330     return (iface->get_layer) (component);
331   else
332     return ATK_LAYER_WIDGET;
333 }
334
335 /**
336  * atk_component_get_mdi_zorder:
337  * @component: an #AtkComponent
338  *
339  * Gets the zorder of the component. The value G_MININT will be returned 
340  * if the layer of the component is not ATK_LAYER_MDI or ATK_LAYER_WINDOW.
341  *
342  * Returns: a gint which is the zorder of the component, i.e. the depth at 
343  * which the component is shown in relation to other components in the same 
344  * container.
345  **/
346 gint
347 atk_component_get_mdi_zorder (AtkComponent *component) 
348 {
349   AtkComponentIface *iface;
350
351   g_return_val_if_fail (ATK_IS_COMPONENT (component), G_MININT);
352
353   iface = ATK_COMPONENT_GET_IFACE (component);
354   if (iface->get_mdi_zorder)
355     return (iface->get_mdi_zorder) (component);
356   else
357     return G_MININT;
358 }
359
360 /**
361  * atk_component_grab_focus:
362  * @component: an #AtkComponent
363  *
364  * Grabs focus for this @component.
365  *
366  * Returns: %TRUE if successful, %FALSE otherwise.
367  **/
368 gboolean
369 atk_component_grab_focus (AtkComponent    *component)
370 {
371   AtkComponentIface *iface = NULL;
372   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
373
374   iface = ATK_COMPONENT_GET_IFACE (component);
375
376   if (iface->grab_focus)
377     return (iface->grab_focus) (component);
378   else
379     return FALSE;
380 }
381
382 /**
383  * atk_component_set_extents:
384  * @component: an #AtkComponent
385  * @x: x coordinate
386  * @y: y coordinate
387  * @width: width to set for @component
388  * @height: height to set for @component
389  * @coord_type: specifies whether the coordinates are relative to the screen
390  * or to the components top level window
391  *
392  * Sets the extents of @component.
393  *
394  * Returns: %TRUE or %FALSE whether the extents were set or not
395  **/
396 gboolean
397 atk_component_set_extents   (AtkComponent    *component,
398                              gint            x,
399                              gint            y,
400                              gint            width,
401                              gint            height,
402                              AtkCoordType    coord_type)
403 {
404   AtkComponentIface *iface = NULL;
405   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
406
407   iface = ATK_COMPONENT_GET_IFACE (component);
408
409   if (iface->set_extents)
410     return (iface->set_extents) (component, x, y, width, height, coord_type);
411   else
412     return FALSE;
413 }
414
415 /**
416  * atk_component_set_position:
417  * @component: an #AtkComponent
418  * @x: x coordinate
419  * @y: y coordinate
420  * @coord_type: specifies whether the coordinates are relative to the screen
421  * or to the components top level window
422  *
423  * Sets the postition of @component.
424  * 
425  * Returns: %TRUE or %FALSE whether or not the position was set or not
426  **/
427 gboolean
428 atk_component_set_position   (AtkComponent    *component,
429                               gint            x,
430                               gint            y,
431                               AtkCoordType    coord_type)
432 {
433   AtkComponentIface *iface = NULL;
434   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
435
436   iface = ATK_COMPONENT_GET_IFACE (component);
437
438   if (iface->set_position)
439     return (iface->set_position) (component, x, y, coord_type);
440   else
441     return FALSE;
442 }
443
444 /**
445  * atk_component_set_size:
446  * @component: an #AtkComponent
447  * @width: width to set for @component
448  * @height: height to set for @component
449  *
450  * Set the size of the @component in terms of width and height.
451  *
452  * Returns: %TRUE or %FALSE whether the size was set or not
453  **/
454 gboolean
455 atk_component_set_size       (AtkComponent    *component,
456                               gint            x,
457                               gint            y)
458 {
459   AtkComponentIface *iface = NULL;
460   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
461
462   iface = ATK_COMPONENT_GET_IFACE (component);
463
464   if (iface->set_size)
465     return (iface->set_size) (component, x, y);
466   else
467     return FALSE;
468 }
469
470 static gboolean
471 atk_component_real_contains (AtkComponent *component,
472                              gint         x,
473                              gint         y,
474                              AtkCoordType coord_type)
475 {
476   gint real_x, real_y, width, height;
477
478   real_x = real_y = width = height = 0;
479
480   atk_component_get_extents (component, &real_x, &real_y, &width, &height, coord_type);
481
482   if ((x >= real_x) &&
483       (x < real_x + width) &&
484       (y >= real_y) &&
485       (y < real_y + height))
486     return TRUE;
487   else
488     return FALSE;
489 }
490
491 static AtkObject* 
492 atk_component_real_ref_accessible_at_point (AtkComponent *component,
493                                             gint         x,
494                                             gint         y,
495                                             AtkCoordType coord_type)
496 {
497   gint count, i;
498
499   count = atk_object_get_n_accessible_children (ATK_OBJECT (component));
500
501   for (i = 0; i < count; i++)
502   {
503     AtkObject *obj;
504
505     obj = atk_object_ref_accessible_child (ATK_OBJECT (component), i);
506
507     if (obj != NULL)
508     {
509       if (atk_component_contains (ATK_COMPONENT (obj), x, y, coord_type))
510       {
511         return obj;
512       }
513       else
514       {
515         g_object_unref (obj);
516       }
517     }
518   }
519   return NULL;
520 }
521
522 static void
523 atk_component_real_get_position (AtkComponent *component,
524                                  gint         *x,
525                                  gint         *y,
526                                  AtkCoordType coord_type)
527 {
528   gint width, height;
529
530   atk_component_get_extents (component, x, y, &width, &height, coord_type);
531 }
532
533 static void
534 atk_component_real_get_size (AtkComponent *component,
535                              gint         *width,
536                              gint         *height)
537 {
538   gint x, y;
539   AtkCoordType coord_type;
540
541   /*
542    * Pick one coordinate type; it does not matter for size
543    */
544   coord_type = ATK_XY_WINDOW;
545
546   atk_component_get_extents (component, &x, &y, width, height, coord_type);
547 }
548
549
550