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