Change parameter names *offset to *_offset Do not crash if NULL pointers
[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 gboolean   atk_component_real_contains                (AtkComponent *component,
24                                                               gint         x,
25                                                               gint         y,
26                                                               AtkCoordType coord_type);
27
28 static AtkObject* atk_component_real_ref_accessible_at_point (AtkComponent *component,
29                                                               gint         x,
30                                                               gint         y,
31                                                               AtkCoordType coord_type);
32
33 static void      atk_component_real_get_position             (AtkComponent *component,
34                                                               gint         *x,
35                                                               gint         *y,
36                                                               AtkCoordType coord_type);
37
38 static void      atk_component_real_get_size                 (AtkComponent *component,
39                                                               gint         *width,
40                                                               gint         *height);
41
42 GType
43 atk_component_get_type ()
44 {
45   static GType type = 0;
46
47   if (!type) {
48     static const GTypeInfo tinfo =
49     {
50       sizeof (AtkComponentIface),
51       (GBaseInitFunc) NULL,
52       (GBaseFinalizeFunc) NULL,
53
54     };
55
56     type = g_type_register_static (G_TYPE_INTERFACE, "AtkComponent", &tinfo, 0);
57   }
58
59   return type;
60 }
61
62 /**
63  * atk_component_add_focus_handler:
64  * @component: The #AtkComponent to attach the @handler to
65  * @handler: The #AtkFocusHandler to be attached to @component
66  *
67  * Add the specified handler to the set of functions to be called 
68  * when this object receives focus events (in or out).
69  *
70  * Returns:
71  **/
72 guint
73 atk_component_add_focus_handler (AtkComponent    *component,
74                                  AtkFocusHandler handler)
75 {
76   AtkComponentIface *iface = NULL;
77   g_return_val_if_fail (ATK_IS_COMPONENT (component), 0);
78
79   iface = ATK_COMPONENT_GET_IFACE (component);
80
81   if (iface->add_focus_handler)
82     return (iface->add_focus_handler) (component, handler);
83   else
84     return 0;
85 }
86
87 /**
88  * atk_component_remove_focus_handler:
89  * @component: the #AtkComponent to remove the focus handler from
90  * @handler_id: the handler id of the focus handler to be removed
91  * from @component
92  *
93  * Remove the handler specified by @handler_id from the list of
94  * functions to be executed when this object receives focus events 
95  * (in or out).
96  **/
97 void
98 atk_component_remove_focus_handler (AtkComponent    *component,
99                                     guint           handler_id)
100 {
101   AtkComponentIface *iface = NULL;
102   g_return_if_fail (ATK_IS_COMPONENT (component));
103
104   iface = ATK_COMPONENT_GET_IFACE (component);
105
106   if (iface->remove_focus_handler)
107     (iface->remove_focus_handler) (component, handler_id);
108 }
109
110 /**
111  * atk_component_contains:
112  * @component: the #AtkComponent
113  * @x: x coordinate
114  * @y: y coordinate
115  * @coord_type: specifies whether the coordinates are relative to the screen
116  * or to the components top level window
117  *
118  * Checks whether the specified point is within the extent of the @component.
119  *
120  * Returns: %TRUE or %FALSE indicating whether the specified point is within
121  * the extent of the @component or not
122  **/
123 gboolean
124 atk_component_contains (AtkComponent    *component,
125                         gint            x,
126                         gint            y,
127                         AtkCoordType    coord_type)
128 {
129   AtkComponentIface *iface = NULL;
130   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
131
132   iface = ATK_COMPONENT_GET_IFACE (component);
133
134   if (iface->contains)
135     return (iface->contains) (component, x, y, coord_type);
136   else
137   {
138     /*
139      * if this method is not overridden use the default implementation.
140      */
141     return atk_component_real_contains (component, x, y, coord_type);
142   }
143 }
144
145 /**
146  * atk_component_ref_accessible_at_point:
147  * @component: the #AtkComponent
148  * @x: x coordinate
149  * @y: y coordinate
150  * @coord_type: specifies whether the coordinates are relative to the screen
151  * or to the components top level window
152  *
153  * Gets a reference to the accessible child, if one exists, at the
154  * coordinate point specified by @x and @y.
155  *
156  * Returns: a reference to the accessible child, if one exists
157  **/
158 AtkObject*
159 atk_component_ref_accessible_at_point (AtkComponent    *component,
160                                        gint            x,
161                                        gint            y,
162                                        AtkCoordType    coord_type)
163 {
164   AtkComponentIface *iface = NULL;
165   g_return_val_if_fail (ATK_IS_COMPONENT (component), NULL);
166
167   iface = ATK_COMPONENT_GET_IFACE (component);
168
169   if (iface->ref_accessible_at_point)
170     return (iface->ref_accessible_at_point) (component, x, y, coord_type);
171   else
172   {
173     /*
174      * if this method is not overridden use the default implementation.
175      */
176     return atk_component_real_ref_accessible_at_point (component, x, y, coord_type);
177   }
178 }
179
180 /**
181  * atk_component_get_extents:
182  * @component: an #AtkComponent
183  * @x: address of #gint to put x coordinate
184  * @y: address of #gint to put y coordinate
185  * @width: address of #gint to put width
186  * @height: address of #gint to put height
187  * @coord_type: specifies whether the coordinates are relative to the screen
188  * or to the components top level window
189  *
190  * Gets the rectangle which gives the extent of the @component.
191  *
192  **/
193 void
194 atk_component_get_extents    (AtkComponent    *component,
195                               gint            *x,
196                               gint            *y,
197                               gint            *width,
198                               gint            *height,
199                               AtkCoordType    coord_type)
200 {
201   AtkComponentIface *iface = NULL;
202   gint local_x, local_y, local_width, local_height;
203   gint *real_x, *real_y, *real_width, *real_height;
204
205   g_return_if_fail (ATK_IS_COMPONENT (component));
206
207   if (x)
208     real_x = x;
209   else
210     real_x = &local_x;
211   if (y)
212     real_y = y;
213   else
214     real_y = &local_y;
215   if (width)
216     real_width = width;
217   else
218     real_width = &local_width;
219   if (height)
220     real_height = height;
221   else
222     real_height = &local_height;
223
224   iface = ATK_COMPONENT_GET_IFACE (component);
225
226   if (iface->get_extents)
227     (iface->get_extents) (component, real_x, real_y, real_width, real_height, coord_type);
228 }
229
230 /**
231  * atk_component_get_position:
232  * @component: an #AtkComponent
233  * @x: address of #gint to put x coordinate position
234  * @y: address of #gint to put y coordinate position
235  * @coord_type: specifies whether the coordinates are relative to the screen
236  * or to the components top level window
237  *
238  * Gets the position of @component in the form of 
239  * a point specifying @component's top-left corner.
240  **/
241 void
242 atk_component_get_position   (AtkComponent    *component,
243                               gint            *x,
244                               gint            *y,
245                               AtkCoordType    coord_type)
246 {
247   AtkComponentIface *iface = NULL;
248   gint local_x, local_y;
249   gint *real_x, *real_y;
250
251   g_return_if_fail (ATK_IS_COMPONENT (component));
252
253   if (x)
254     real_x = x;
255   else
256     real_x = &local_x;
257   if (y)
258     real_y = y;
259   else
260     real_y = &local_y;
261
262   iface = ATK_COMPONENT_GET_IFACE (component);
263
264   if (iface->get_position)
265     (iface->get_position) (component, real_x, real_y, coord_type);
266   else
267   {
268     /*
269      * if this method is not overridden use the default implementation.
270      */
271     atk_component_real_get_position (component, real_x, real_y, coord_type);
272   }
273 }
274
275 /**
276  * atk_component_get_size:
277  * @component: an #AtkComponent
278  * @width: address of #gint to put width of @component
279  * @height: address of #gint to put height of @component
280  *
281  * Gets the size of the @component in terms of width and height.
282  **/
283 void
284 atk_component_get_size       (AtkComponent    *component,
285                               gint            *width,
286                               gint            *height)
287 {
288   AtkComponentIface *iface = NULL;
289   gint local_width, local_height;
290   gint *real_width, *real_height;
291
292   g_return_if_fail (ATK_IS_COMPONENT (component));
293
294   if (width)
295     real_width = width;
296   else
297     real_width = &local_width;
298   if (height)
299     real_height = height;
300   else
301     real_height = &local_height;
302
303   iface = ATK_COMPONENT_GET_IFACE (component);
304   g_return_if_fail (ATK_IS_COMPONENT (component));
305
306   iface = ATK_COMPONENT_GET_IFACE (component);
307
308   if (iface->get_size)
309     (iface->get_size) (component, real_width, real_height);
310   else
311   {
312     /*
313      * if this method is not overridden use the default implementation.
314      */
315     atk_component_real_get_size (component, real_width, real_height);
316   }
317 }
318
319 /**
320  * atk_component_grab_focus:
321  * @component: an #AtkComponent
322  *
323  * Grabs focus for this @component.
324  *
325  * Returns: %TRUE if successful, %FALSE otherwise.
326  **/
327 gboolean
328 atk_component_grab_focus (AtkComponent    *component)
329 {
330   AtkComponentIface *iface = NULL;
331   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
332
333   iface = ATK_COMPONENT_GET_IFACE (component);
334
335   if (iface->grab_focus)
336     return (iface->grab_focus) (component);
337   else
338     return FALSE;
339 }
340
341 /**
342  * atk_component_set_extents:
343  * @component: an #AtkComponent
344  * @x: x coordinate
345  * @y: y coordinate
346  * @width: width to set for @component
347  * @height: height to set for @component
348  * @coord_type: specifies whether the coordinates are relative to the screen
349  * or to the components top level window
350  *
351  * Sets the extents of @component.
352  *
353  * Returns: %TRUE or %FALSE whether the extents were set or not
354  **/
355 gboolean
356 atk_component_set_extents   (AtkComponent    *component,
357                              gint            x,
358                              gint            y,
359                              gint            width,
360                              gint            height,
361                              AtkCoordType    coord_type)
362 {
363   AtkComponentIface *iface = NULL;
364   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
365
366   iface = ATK_COMPONENT_GET_IFACE (component);
367
368   if (iface->set_extents)
369     return (iface->set_extents) (component, x, y, width, height, coord_type);
370   else
371     return FALSE;
372 }
373
374 /**
375  * atk_component_set_position:
376  * @component: an #AtkComponent
377  * @x: x coordinate
378  * @y: y coordinate
379  * @coord_type: specifies whether the coordinates are relative to the screen
380  * or to the components top level window
381  *
382  * Sets the postition of @component.
383  * 
384  * Returns: %TRUE or %FALSE whether or not the position was set or not
385  **/
386 gboolean
387 atk_component_set_position   (AtkComponent    *component,
388                               gint            x,
389                               gint            y,
390                               AtkCoordType    coord_type)
391 {
392   AtkComponentIface *iface = NULL;
393   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
394
395   iface = ATK_COMPONENT_GET_IFACE (component);
396
397   if (iface->set_position)
398     return (iface->set_position) (component, x, y, coord_type);
399   else
400     return FALSE;
401 }
402
403 /**
404  * atk_component_set_size:
405  * @component: an #AtkComponent
406  * @width: width to set for @component
407  * @height: height to set for @component
408  *
409  * Set the size of the @component in terms of width and height.
410  *
411  * Returns: %TRUE or %FALSE whether the size was set or not
412  **/
413 gboolean
414 atk_component_set_size       (AtkComponent    *component,
415                               gint            x,
416                               gint            y)
417 {
418   AtkComponentIface *iface = NULL;
419   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
420
421   iface = ATK_COMPONENT_GET_IFACE (component);
422
423   if (iface->set_size)
424     return (iface->set_size) (component, x, y);
425   else
426     return FALSE;
427 }
428
429 static gboolean
430 atk_component_real_contains (AtkComponent *component,
431                              gint         x,
432                              gint         y,
433                              AtkCoordType coord_type)
434 {
435   gint real_x, real_y, width, height;
436
437   real_x = real_y = width = height = 0;
438
439   atk_component_get_extents (component, &real_x, &real_y, &width, &height, coord_type);
440
441   if ((x >= real_x) &&
442       (x < real_x + width) &&
443       (y >= real_y) &&
444       (y < real_y + height))
445     return TRUE;
446   else
447     return FALSE;
448 }
449
450 static AtkObject* 
451 atk_component_real_ref_accessible_at_point (AtkComponent *component,
452                                             gint         x,
453                                             gint         y,
454                                             AtkCoordType coord_type)
455 {
456   gint count, i;
457
458   count = atk_object_get_n_accessible_children (ATK_OBJECT (component));
459
460   g_return_val_if_fail (count != 0, NULL);
461
462   for (i = 0; i < count; i++)
463   {
464     AtkObject *obj;
465
466     obj = atk_object_ref_accessible_child (ATK_OBJECT (component), i);
467
468     if (obj != NULL)
469     {
470       if (atk_component_contains (ATK_COMPONENT (obj), x, y, coord_type))
471       {
472         return obj;
473       }
474       else
475       {
476         g_object_unref (obj);
477       }
478     }
479   }
480   return NULL;
481 }
482
483 static void
484 atk_component_real_get_position (AtkComponent *component,
485                                  gint         *x,
486                                  gint         *y,
487                                  AtkCoordType coord_type)
488 {
489   gint width, height;
490
491   atk_component_get_extents (component, x, y, &width, &height, coord_type);
492 }
493
494 static void
495 atk_component_real_get_size (AtkComponent *component,
496                              gint         *width,
497                              gint         *height)
498 {
499   gint x, y;
500   AtkCoordType coord_type;
501
502   /*
503    * Pick one coordinate type; it does not matter for size
504    */
505   coord_type = ATK_XY_WINDOW;
506
507   atk_component_get_extents (component, &x, &y, width, height, coord_type);
508 }