Updated FSF's address
[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, see <http://www.gnu.org/licenses/>.
16  */
17
18
19 #include "atkcomponent.h"
20
21 /**
22  * SECTION:atkcomponent
23  * @Short_description: The ATK interface provided by UI components
24  * which occupy a physical area on the screen.
25  * which the user can activate/interact with.
26  * @Title:AtkComponent
27  *
28  * #AtkComponent should be implemented by most if not all UI elements
29  * with an actual on-screen presence, i.e. components which can be
30  * said to have a screen-coordinate bounding box.  Virtually all
31  * widgets will need to have #AtkComponent implementations provided
32  * for their corresponding #AtkObject class.  In short, only UI
33  * elements which are *not* GUI elements will omit this ATK interface.
34  *
35  * A possible exception might be textual information with a
36  * transparent background, in which case text glyph bounding box
37  * information is provided by #AtkText.
38  */
39
40 enum {
41   BOUNDS_CHANGED,
42   LAST_SIGNAL
43 };
44
45 static void       atk_component_base_init (AtkComponentIface *class);
46
47 static gboolean   atk_component_real_contains                (AtkComponent *component,
48                                                               gint         x,
49                                                               gint         y,
50                                                               AtkCoordType coord_type);
51
52 static AtkObject* atk_component_real_ref_accessible_at_point (AtkComponent *component,
53                                                               gint         x,
54                                                               gint         y,
55                                                               AtkCoordType coord_type);
56
57 static void      atk_component_real_get_position             (AtkComponent *component,
58                                                               gint         *x,
59                                                               gint         *y,
60                                                               AtkCoordType coord_type);
61
62 static void      atk_component_real_get_size                 (AtkComponent *component,
63                                                               gint         *width,
64                                                               gint         *height);
65
66 static guint atk_component_signals[LAST_SIGNAL] = { 0 };
67
68 GType
69 atk_component_get_type (void)
70 {
71   static GType type = 0;
72
73   if (!type) {
74     static const GTypeInfo tinfo =
75     {
76       sizeof (AtkComponentIface),
77       (GBaseInitFunc) atk_component_base_init,
78       (GBaseFinalizeFunc) NULL,
79
80     };
81
82     type = g_type_register_static (G_TYPE_INTERFACE, "AtkComponent", &tinfo, 0);
83   }
84
85   return type;
86 }
87
88 static void
89 atk_component_base_init (AtkComponentIface *class)
90 {
91   static gboolean initialized = FALSE;
92
93   if (! initialized)
94     {
95       class->ref_accessible_at_point = atk_component_real_ref_accessible_at_point;
96       class->contains = atk_component_real_contains;
97       class->get_position = atk_component_real_get_position;
98       class->get_size = atk_component_real_get_size;
99
100
101       /**
102        * AtkComponent::bounds-changed:
103        * @atkcomponent: the object which received the signal.
104        * @arg1: The AtkRectangle giving the new position and size.
105        *
106        * The 'bounds-changed" signal is emitted when the bposition or
107        * size of the component changes.
108        */
109       atk_component_signals[BOUNDS_CHANGED] =
110         g_signal_new ("bounds_changed",
111                       ATK_TYPE_COMPONENT,
112                       G_SIGNAL_RUN_LAST,
113                       G_STRUCT_OFFSET (AtkComponentIface, bounds_changed),
114                       (GSignalAccumulator) NULL, NULL,
115                       g_cclosure_marshal_VOID__BOXED,
116                       G_TYPE_NONE, 1,
117                       ATK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
118
119       initialized = TRUE;
120     }
121 }
122
123
124 /**
125  * atk_component_add_focus_handler:
126  * @component: The #AtkComponent to attach the @handler to
127  * @handler: The #AtkFocusHandler to be attached to @component
128  *
129  * Add the specified handler to the set of functions to be called 
130  * when this object receives focus events (in or out). If the handler is
131  * already added it is not added again
132  *
133  * Deprecated: This method is deprecated since ATK version 2.9.4. If
134  * you need to track when an object gains or lose the focus, use
135  * state-changed:focused notification instead.
136  *
137  * Returns: a handler id which can be used in atk_component_remove_focus_handler()
138  * or zero if the handler was already added.
139  **/
140 guint
141 atk_component_add_focus_handler (AtkComponent    *component,
142                                  AtkFocusHandler handler)
143 {
144   AtkComponentIface *iface = NULL;
145   g_return_val_if_fail (ATK_IS_COMPONENT (component), 0);
146
147   iface = ATK_COMPONENT_GET_IFACE (component);
148
149   if (iface->add_focus_handler)
150     return (iface->add_focus_handler) (component, handler);
151   else
152     return 0;
153 }
154
155 /**
156  * atk_component_remove_focus_handler:
157  * @component: the #AtkComponent to remove the focus handler from
158  * @handler_id: the handler id of the focus handler to be removed
159  * from @component
160  *
161  * Remove the handler specified by @handler_id from the list of
162  * functions to be executed when this object receives focus events 
163  * (in or out).
164  *
165  * Deprecated: This method is deprecated since ATK version 2.9.4. If
166  * you need to track when an object gains or lose the focus, use
167  * state-changed:focused notification instead.
168  *
169  **/
170 void
171 atk_component_remove_focus_handler (AtkComponent    *component,
172                                     guint           handler_id)
173 {
174   AtkComponentIface *iface = NULL;
175   g_return_if_fail (ATK_IS_COMPONENT (component));
176
177   iface = ATK_COMPONENT_GET_IFACE (component);
178
179   if (iface->remove_focus_handler)
180     (iface->remove_focus_handler) (component, handler_id);
181 }
182
183 /**
184  * atk_component_contains:
185  * @component: the #AtkComponent
186  * @x: x coordinate
187  * @y: y coordinate
188  * @coord_type: specifies whether the coordinates are relative to the screen
189  * or to the components top level window
190  *
191  * Checks whether the specified point is within the extent of the @component.
192  *
193  * Returns: %TRUE or %FALSE indicating whether the specified point is within
194  * the extent of the @component or not
195  **/
196 gboolean
197 atk_component_contains (AtkComponent    *component,
198                         gint            x,
199                         gint            y,
200                         AtkCoordType    coord_type)
201 {
202   AtkComponentIface *iface = NULL;
203   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
204
205   iface = ATK_COMPONENT_GET_IFACE (component);
206
207   if (iface->contains)
208     return (iface->contains) (component, x, y, coord_type);
209   else
210     return FALSE;
211 }
212
213 /**
214  * atk_component_ref_accessible_at_point:
215  * @component: the #AtkComponent
216  * @x: x coordinate
217  * @y: y coordinate
218  * @coord_type: specifies whether the coordinates are relative to the screen
219  * or to the components top level window
220  *
221  * Gets a reference to the accessible child, if one exists, at the
222  * coordinate point specified by @x and @y.
223  *
224  * Returns: (transfer full): a reference to the accessible child, if one exists
225  **/
226 AtkObject*
227 atk_component_ref_accessible_at_point (AtkComponent    *component,
228                                        gint            x,
229                                        gint            y,
230                                        AtkCoordType    coord_type)
231 {
232   AtkComponentIface *iface = NULL;
233   g_return_val_if_fail (ATK_IS_COMPONENT (component), NULL);
234
235   iface = ATK_COMPONENT_GET_IFACE (component);
236
237   if (iface->ref_accessible_at_point)
238     return (iface->ref_accessible_at_point) (component, x, y, coord_type);
239   else
240     return NULL;
241 }
242
243 /**
244  * atk_component_get_extents:
245  * @component: an #AtkComponent
246  * @x: address of #gint to put x coordinate
247  * @y: address of #gint to put y coordinate
248  * @width: address of #gint to put width
249  * @height: address of #gint to put height
250  * @coord_type: specifies whether the coordinates are relative to the screen
251  * or to the components top level window
252  *
253  * Gets the rectangle which gives the extent of the @component.
254  *
255  **/
256 void
257 atk_component_get_extents    (AtkComponent    *component,
258                               gint            *x,
259                               gint            *y,
260                               gint            *width,
261                               gint            *height,
262                               AtkCoordType    coord_type)
263 {
264   AtkComponentIface *iface = NULL;
265   gint local_x, local_y, local_width, local_height;
266   gint *real_x, *real_y, *real_width, *real_height;
267
268   g_return_if_fail (ATK_IS_COMPONENT (component));
269
270   if (x)
271     real_x = x;
272   else
273     real_x = &local_x;
274   if (y)
275     real_y = y;
276   else
277     real_y = &local_y;
278   if (width)
279     real_width = width;
280   else
281     real_width = &local_width;
282   if (height)
283     real_height = height;
284   else
285     real_height = &local_height;
286
287   iface = ATK_COMPONENT_GET_IFACE (component);
288
289   if (iface->get_extents)
290     (iface->get_extents) (component, real_x, real_y, real_width, real_height, coord_type);
291 }
292
293 /**
294  * atk_component_get_position:
295  * @component: an #AtkComponent
296  * @x: address of #gint to put x coordinate position
297  * @y: address of #gint to put y coordinate position
298  * @coord_type: specifies whether the coordinates are relative to the screen
299  * or to the components top level window
300  *
301  * Gets the position of @component in the form of 
302  * a point specifying @component's top-left corner.
303  **/
304 void
305 atk_component_get_position   (AtkComponent    *component,
306                               gint            *x,
307                               gint            *y,
308                               AtkCoordType    coord_type)
309 {
310   AtkComponentIface *iface = NULL;
311   gint local_x, local_y;
312   gint *real_x, *real_y;
313
314   g_return_if_fail (ATK_IS_COMPONENT (component));
315
316   if (x)
317     real_x = x;
318   else
319     real_x = &local_x;
320   if (y)
321     real_y = y;
322   else
323     real_y = &local_y;
324
325   iface = ATK_COMPONENT_GET_IFACE (component);
326
327   if (iface->get_position)
328     (iface->get_position) (component, real_x, real_y, coord_type);
329 }
330
331 /**
332  * atk_component_get_size:
333  * @component: an #AtkComponent
334  * @width: address of #gint to put width of @component
335  * @height: address of #gint to put height of @component
336  *
337  * Gets the size of the @component in terms of width and height.
338  **/
339 void
340 atk_component_get_size       (AtkComponent    *component,
341                               gint            *width,
342                               gint            *height)
343 {
344   AtkComponentIface *iface = NULL;
345   gint local_width, local_height;
346   gint *real_width, *real_height;
347
348   g_return_if_fail (ATK_IS_COMPONENT (component));
349
350   if (width)
351     real_width = width;
352   else
353     real_width = &local_width;
354   if (height)
355     real_height = height;
356   else
357     real_height = &local_height;
358
359   g_return_if_fail (ATK_IS_COMPONENT (component));
360
361   iface = ATK_COMPONENT_GET_IFACE (component);
362
363   if (iface->get_size)
364     (iface->get_size) (component, real_width, real_height);
365 }
366
367 /**
368  * atk_component_get_layer:
369  * @component: an #AtkComponent
370  *
371  * Gets the layer of the component.
372  *
373  * Returns: an #AtkLayer which is the layer of the component
374  **/
375 AtkLayer
376 atk_component_get_layer (AtkComponent *component) 
377 {
378   AtkComponentIface *iface;
379
380   g_return_val_if_fail (ATK_IS_COMPONENT (component), ATK_LAYER_INVALID);
381
382   iface = ATK_COMPONENT_GET_IFACE (component);
383   if (iface->get_layer)
384     return (iface->get_layer) (component);
385   else
386     return ATK_LAYER_WIDGET;
387 }
388
389 /**
390  * atk_component_get_mdi_zorder:
391  * @component: an #AtkComponent
392  *
393  * Gets the zorder of the component. The value G_MININT will be returned 
394  * if the layer of the component is not ATK_LAYER_MDI or ATK_LAYER_WINDOW.
395  *
396  * Returns: a gint which is the zorder of the component, i.e. the depth at 
397  * which the component is shown in relation to other components in the same 
398  * container.
399  **/
400 gint
401 atk_component_get_mdi_zorder (AtkComponent *component) 
402 {
403   AtkComponentIface *iface;
404
405   g_return_val_if_fail (ATK_IS_COMPONENT (component), G_MININT);
406
407   iface = ATK_COMPONENT_GET_IFACE (component);
408   if (iface->get_mdi_zorder)
409     return (iface->get_mdi_zorder) (component);
410   else
411     return G_MININT;
412 }
413
414 /**
415  * atk_component_get_alpha:
416  * @component: an #AtkComponent
417  *
418  * Returns the alpha value (i.e. the opacity) for this
419  * @component, on a scale from 0 (fully transparent) to 1.0
420  * (fully opaque).
421  *
422  * Returns: An alpha value from 0 to 1.0, inclusive.
423  * Since: 1.12
424  **/
425 gdouble
426 atk_component_get_alpha (AtkComponent    *component)
427 {
428   AtkComponentIface *iface;
429
430   g_return_val_if_fail (ATK_IS_COMPONENT (component), G_MININT);
431
432   iface = ATK_COMPONENT_GET_IFACE (component);
433   if (iface->get_alpha)
434     return (iface->get_alpha) (component);
435   else
436     return (gdouble) 1.0;
437 }
438
439 /**
440  * atk_component_grab_focus:
441  * @component: an #AtkComponent
442  *
443  * Grabs focus for this @component.
444  *
445  * Returns: %TRUE if successful, %FALSE otherwise.
446  **/
447 gboolean
448 atk_component_grab_focus (AtkComponent    *component)
449 {
450   AtkComponentIface *iface = NULL;
451   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
452
453   iface = ATK_COMPONENT_GET_IFACE (component);
454
455   if (iface->grab_focus)
456     return (iface->grab_focus) (component);
457   else
458     return FALSE;
459 }
460
461 /**
462  * atk_component_set_extents:
463  * @component: an #AtkComponent
464  * @x: x coordinate
465  * @y: y coordinate
466  * @width: width to set for @component
467  * @height: height to set for @component
468  * @coord_type: specifies whether the coordinates are relative to the screen
469  * or to the components top level window
470  *
471  * Sets the extents of @component.
472  *
473  * Returns: %TRUE or %FALSE whether the extents were set or not
474  **/
475 gboolean
476 atk_component_set_extents   (AtkComponent    *component,
477                              gint            x,
478                              gint            y,
479                              gint            width,
480                              gint            height,
481                              AtkCoordType    coord_type)
482 {
483   AtkComponentIface *iface = NULL;
484   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
485
486   iface = ATK_COMPONENT_GET_IFACE (component);
487
488   if (iface->set_extents)
489     return (iface->set_extents) (component, x, y, width, height, coord_type);
490   else
491     return FALSE;
492 }
493
494 /**
495  * atk_component_set_position:
496  * @component: an #AtkComponent
497  * @x: x coordinate
498  * @y: y coordinate
499  * @coord_type: specifies whether the coordinates are relative to the screen
500  * or to the components top level window
501  *
502  * Sets the postition of @component.
503  * 
504  * Returns: %TRUE or %FALSE whether or not the position was set or not
505  **/
506 gboolean
507 atk_component_set_position   (AtkComponent    *component,
508                               gint            x,
509                               gint            y,
510                               AtkCoordType    coord_type)
511 {
512   AtkComponentIface *iface = NULL;
513   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
514
515   iface = ATK_COMPONENT_GET_IFACE (component);
516
517   if (iface->set_position)
518     return (iface->set_position) (component, x, y, coord_type);
519   else
520     return FALSE;
521 }
522
523 /**
524  * atk_component_set_size:
525  * @component: an #AtkComponent
526  * @width: width to set for @component
527  * @height: height to set for @component
528  *
529  * Set the size of the @component in terms of width and height.
530  *
531  * Returns: %TRUE or %FALSE whether the size was set or not
532  **/
533 gboolean
534 atk_component_set_size       (AtkComponent    *component,
535                               gint            x,
536                               gint            y)
537 {
538   AtkComponentIface *iface = NULL;
539   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
540
541   iface = ATK_COMPONENT_GET_IFACE (component);
542
543   if (iface->set_size)
544     return (iface->set_size) (component, x, y);
545   else
546     return FALSE;
547 }
548
549 static gboolean
550 atk_component_real_contains (AtkComponent *component,
551                              gint         x,
552                              gint         y,
553                              AtkCoordType coord_type)
554 {
555   gint real_x, real_y, width, height;
556
557   real_x = real_y = width = height = 0;
558
559   atk_component_get_extents (component, &real_x, &real_y, &width, &height, coord_type);
560
561   if ((x >= real_x) &&
562       (x < real_x + width) &&
563       (y >= real_y) &&
564       (y < real_y + height))
565     return TRUE;
566   else
567     return FALSE;
568 }
569
570 static AtkObject* 
571 atk_component_real_ref_accessible_at_point (AtkComponent *component,
572                                             gint         x,
573                                             gint         y,
574                                             AtkCoordType coord_type)
575 {
576   gint count, i;
577
578   count = atk_object_get_n_accessible_children (ATK_OBJECT (component));
579
580   for (i = 0; i < count; i++)
581   {
582     AtkObject *obj;
583
584     obj = atk_object_ref_accessible_child (ATK_OBJECT (component), i);
585
586     if (obj != NULL)
587     {
588       if (atk_component_contains (ATK_COMPONENT (obj), x, y, coord_type))
589       {
590         return obj;
591       }
592       else
593       {
594         g_object_unref (obj);
595       }
596     }
597   }
598   return NULL;
599 }
600
601 static void
602 atk_component_real_get_position (AtkComponent *component,
603                                  gint         *x,
604                                  gint         *y,
605                                  AtkCoordType coord_type)
606 {
607   gint width, height;
608
609   atk_component_get_extents (component, x, y, &width, &height, coord_type);
610 }
611
612 static void
613 atk_component_real_get_size (AtkComponent *component,
614                              gint         *width,
615                              gint         *height)
616 {
617   gint x, y;
618   AtkCoordType coord_type;
619
620   /*
621    * Pick one coordinate type; it does not matter for size
622    */
623   coord_type = ATK_XY_WINDOW;
624
625   atk_component_get_extents (component, &x, &y, width, height, coord_type);
626 }
627
628 static AtkRectangle *
629 atk_rectangle_copy (const AtkRectangle *rectangle)
630 {
631   AtkRectangle *result = g_new (AtkRectangle, 1);
632   *result = *rectangle;
633
634   return result;
635 }
636
637 GType
638 atk_rectangle_get_type (void)
639 {
640   static GType our_type = 0;
641
642   if (our_type == 0)
643     our_type = g_boxed_type_register_static ("AtkRectangle",
644                                              (GBoxedCopyFunc)atk_rectangle_copy,
645                                              (GBoxedFreeFunc)g_free);
646   return our_type;
647 }
648