Patch from Yue Wang. Bug #575794.
[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, 1,
91                       ATK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
92
93       initialized = TRUE;
94     }
95 }
96
97
98 /**
99  * atk_component_add_focus_handler:
100  * @component: The #AtkComponent to attach the @handler to
101  * @handler: The #AtkFocusHandler to be attached to @component
102  *
103  * Add the specified handler to the set of functions to be called 
104  * when this object receives focus events (in or out). If the handler is
105  * already added it is not added again
106  *
107  * Returns: a handler id which can be used in atk_component_remove_focus_handler
108  * or zero if the handler was already added.
109  **/
110 guint
111 atk_component_add_focus_handler (AtkComponent    *component,
112                                  AtkFocusHandler handler)
113 {
114   AtkComponentIface *iface = NULL;
115   g_return_val_if_fail (ATK_IS_COMPONENT (component), 0);
116
117   iface = ATK_COMPONENT_GET_IFACE (component);
118
119   if (iface->add_focus_handler)
120     return (iface->add_focus_handler) (component, handler);
121   else
122     return 0;
123 }
124
125 /**
126  * atk_component_remove_focus_handler:
127  * @component: the #AtkComponent to remove the focus handler from
128  * @handler_id: the handler id of the focus handler to be removed
129  * from @component
130  *
131  * Remove the handler specified by @handler_id from the list of
132  * functions to be executed when this object receives focus events 
133  * (in or out).
134  **/
135 void
136 atk_component_remove_focus_handler (AtkComponent    *component,
137                                     guint           handler_id)
138 {
139   AtkComponentIface *iface = NULL;
140   g_return_if_fail (ATK_IS_COMPONENT (component));
141
142   iface = ATK_COMPONENT_GET_IFACE (component);
143
144   if (iface->remove_focus_handler)
145     (iface->remove_focus_handler) (component, handler_id);
146 }
147
148 /**
149  * atk_component_contains:
150  * @component: the #AtkComponent
151  * @x: x coordinate
152  * @y: y coordinate
153  * @coord_type: specifies whether the coordinates are relative to the screen
154  * or to the components top level window
155  *
156  * Checks whether the specified point is within the extent of the @component.
157  *
158  * Returns: %TRUE or %FALSE indicating whether the specified point is within
159  * the extent of the @component or not
160  **/
161 gboolean
162 atk_component_contains (AtkComponent    *component,
163                         gint            x,
164                         gint            y,
165                         AtkCoordType    coord_type)
166 {
167   AtkComponentIface *iface = NULL;
168   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
169
170   iface = ATK_COMPONENT_GET_IFACE (component);
171
172   if (iface->contains)
173     return (iface->contains) (component, x, y, coord_type);
174   else
175     return FALSE;
176 }
177
178 /**
179  * atk_component_ref_accessible_at_point:
180  * @component: the #AtkComponent
181  * @x: x coordinate
182  * @y: y coordinate
183  * @coord_type: specifies whether the coordinates are relative to the screen
184  * or to the components top level window
185  *
186  * Gets a reference to the accessible child, if one exists, at the
187  * coordinate point specified by @x and @y.
188  *
189  * Returns: a reference to the accessible child, if one exists
190  **/
191 AtkObject*
192 atk_component_ref_accessible_at_point (AtkComponent    *component,
193                                        gint            x,
194                                        gint            y,
195                                        AtkCoordType    coord_type)
196 {
197   AtkComponentIface *iface = NULL;
198   g_return_val_if_fail (ATK_IS_COMPONENT (component), NULL);
199
200   iface = ATK_COMPONENT_GET_IFACE (component);
201
202   if (iface->ref_accessible_at_point)
203     return (iface->ref_accessible_at_point) (component, x, y, coord_type);
204   else
205     return NULL;
206 }
207
208 /**
209  * atk_component_get_extents:
210  * @component: an #AtkComponent
211  * @x: address of #gint to put x coordinate
212  * @y: address of #gint to put y coordinate
213  * @width: address of #gint to put width
214  * @height: address of #gint to put height
215  * @coord_type: specifies whether the coordinates are relative to the screen
216  * or to the components top level window
217  *
218  * Gets the rectangle which gives the extent of the @component.
219  *
220  **/
221 void
222 atk_component_get_extents    (AtkComponent    *component,
223                               gint            *x,
224                               gint            *y,
225                               gint            *width,
226                               gint            *height,
227                               AtkCoordType    coord_type)
228 {
229   AtkComponentIface *iface = NULL;
230   gint local_x, local_y, local_width, local_height;
231   gint *real_x, *real_y, *real_width, *real_height;
232
233   g_return_if_fail (ATK_IS_COMPONENT (component));
234
235   if (x)
236     real_x = x;
237   else
238     real_x = &local_x;
239   if (y)
240     real_y = y;
241   else
242     real_y = &local_y;
243   if (width)
244     real_width = width;
245   else
246     real_width = &local_width;
247   if (height)
248     real_height = height;
249   else
250     real_height = &local_height;
251
252   iface = ATK_COMPONENT_GET_IFACE (component);
253
254   if (iface->get_extents)
255     (iface->get_extents) (component, real_x, real_y, real_width, real_height, coord_type);
256 }
257
258 /**
259  * atk_component_get_position:
260  * @component: an #AtkComponent
261  * @x: address of #gint to put x coordinate position
262  * @y: address of #gint to put y coordinate position
263  * @coord_type: specifies whether the coordinates are relative to the screen
264  * or to the components top level window
265  *
266  * Gets the position of @component in the form of 
267  * a point specifying @component's top-left corner.
268  **/
269 void
270 atk_component_get_position   (AtkComponent    *component,
271                               gint            *x,
272                               gint            *y,
273                               AtkCoordType    coord_type)
274 {
275   AtkComponentIface *iface = NULL;
276   gint local_x, local_y;
277   gint *real_x, *real_y;
278
279   g_return_if_fail (ATK_IS_COMPONENT (component));
280
281   if (x)
282     real_x = x;
283   else
284     real_x = &local_x;
285   if (y)
286     real_y = y;
287   else
288     real_y = &local_y;
289
290   iface = ATK_COMPONENT_GET_IFACE (component);
291
292   if (iface->get_position)
293     (iface->get_position) (component, real_x, real_y, coord_type);
294 }
295
296 /**
297  * atk_component_get_size:
298  * @component: an #AtkComponent
299  * @width: address of #gint to put width of @component
300  * @height: address of #gint to put height of @component
301  *
302  * Gets the size of the @component in terms of width and height.
303  **/
304 void
305 atk_component_get_size       (AtkComponent    *component,
306                               gint            *width,
307                               gint            *height)
308 {
309   AtkComponentIface *iface = NULL;
310   gint local_width, local_height;
311   gint *real_width, *real_height;
312
313   g_return_if_fail (ATK_IS_COMPONENT (component));
314
315   if (width)
316     real_width = width;
317   else
318     real_width = &local_width;
319   if (height)
320     real_height = height;
321   else
322     real_height = &local_height;
323
324   g_return_if_fail (ATK_IS_COMPONENT (component));
325
326   iface = ATK_COMPONENT_GET_IFACE (component);
327
328   if (iface->get_size)
329     (iface->get_size) (component, real_width, real_height);
330 }
331
332 /**
333  * atk_component_get_layer:
334  * @component: an #AtkComponent
335  *
336  * Gets the layer of the component.
337  *
338  * Returns: an #AtkLayer which is the layer of the component
339  **/
340 AtkLayer
341 atk_component_get_layer (AtkComponent *component) 
342 {
343   AtkComponentIface *iface;
344
345   g_return_val_if_fail (ATK_IS_COMPONENT (component), ATK_LAYER_INVALID);
346
347   iface = ATK_COMPONENT_GET_IFACE (component);
348   if (iface->get_layer)
349     return (iface->get_layer) (component);
350   else
351     return ATK_LAYER_WIDGET;
352 }
353
354 /**
355  * atk_component_get_mdi_zorder:
356  * @component: an #AtkComponent
357  *
358  * Gets the zorder of the component. The value G_MININT will be returned 
359  * if the layer of the component is not ATK_LAYER_MDI or ATK_LAYER_WINDOW.
360  *
361  * Returns: a gint which is the zorder of the component, i.e. the depth at 
362  * which the component is shown in relation to other components in the same 
363  * container.
364  **/
365 gint
366 atk_component_get_mdi_zorder (AtkComponent *component) 
367 {
368   AtkComponentIface *iface;
369
370   g_return_val_if_fail (ATK_IS_COMPONENT (component), G_MININT);
371
372   iface = ATK_COMPONENT_GET_IFACE (component);
373   if (iface->get_mdi_zorder)
374     return (iface->get_mdi_zorder) (component);
375   else
376     return G_MININT;
377 }
378
379 /**
380  * atk_component_get_alpha:
381  * @component: an #AtkComponent
382  *
383  * Returns the alpha value (i.e. the opacity) for this
384  * @component, on a scale from 0 (fully transparent) to 1.0
385  * (fully opaque).
386  *
387  * Returns: An alpha value from 0 to 1.0, inclusive.
388  * Since: 1.12
389  **/
390 gdouble
391 atk_component_get_alpha (AtkComponent    *component)
392 {
393   AtkComponentIface *iface;
394
395   g_return_val_if_fail (ATK_IS_COMPONENT (component), G_MININT);
396
397   iface = ATK_COMPONENT_GET_IFACE (component);
398   if (iface->get_alpha)
399     return (iface->get_alpha) (component);
400   else
401     return (gdouble) 1.0;
402 }
403
404 /**
405  * atk_component_grab_focus:
406  * @component: an #AtkComponent
407  *
408  * Grabs focus for this @component.
409  *
410  * Returns: %TRUE if successful, %FALSE otherwise.
411  **/
412 gboolean
413 atk_component_grab_focus (AtkComponent    *component)
414 {
415   AtkComponentIface *iface = NULL;
416   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
417
418   iface = ATK_COMPONENT_GET_IFACE (component);
419
420   if (iface->grab_focus)
421     return (iface->grab_focus) (component);
422   else
423     return FALSE;
424 }
425
426 /**
427  * atk_component_set_extents:
428  * @component: an #AtkComponent
429  * @x: x coordinate
430  * @y: y coordinate
431  * @width: width to set for @component
432  * @height: height to set for @component
433  * @coord_type: specifies whether the coordinates are relative to the screen
434  * or to the components top level window
435  *
436  * Sets the extents of @component.
437  *
438  * Returns: %TRUE or %FALSE whether the extents were set or not
439  **/
440 gboolean
441 atk_component_set_extents   (AtkComponent    *component,
442                              gint            x,
443                              gint            y,
444                              gint            width,
445                              gint            height,
446                              AtkCoordType    coord_type)
447 {
448   AtkComponentIface *iface = NULL;
449   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
450
451   iface = ATK_COMPONENT_GET_IFACE (component);
452
453   if (iface->set_extents)
454     return (iface->set_extents) (component, x, y, width, height, coord_type);
455   else
456     return FALSE;
457 }
458
459 /**
460  * atk_component_set_position:
461  * @component: an #AtkComponent
462  * @x: x coordinate
463  * @y: y coordinate
464  * @coord_type: specifies whether the coordinates are relative to the screen
465  * or to the components top level window
466  *
467  * Sets the postition of @component.
468  * 
469  * Returns: %TRUE or %FALSE whether or not the position was set or not
470  **/
471 gboolean
472 atk_component_set_position   (AtkComponent    *component,
473                               gint            x,
474                               gint            y,
475                               AtkCoordType    coord_type)
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_position)
483     return (iface->set_position) (component, x, y, coord_type);
484   else
485     return FALSE;
486 }
487
488 /**
489  * atk_component_set_size:
490  * @component: an #AtkComponent
491  * @width: width to set for @component
492  * @height: height to set for @component
493  *
494  * Set the size of the @component in terms of width and height.
495  *
496  * Returns: %TRUE or %FALSE whether the size was set or not
497  **/
498 gboolean
499 atk_component_set_size       (AtkComponent    *component,
500                               gint            x,
501                               gint            y)
502 {
503   AtkComponentIface *iface = NULL;
504   g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
505
506   iface = ATK_COMPONENT_GET_IFACE (component);
507
508   if (iface->set_size)
509     return (iface->set_size) (component, x, y);
510   else
511     return FALSE;
512 }
513
514 static gboolean
515 atk_component_real_contains (AtkComponent *component,
516                              gint         x,
517                              gint         y,
518                              AtkCoordType coord_type)
519 {
520   gint real_x, real_y, width, height;
521
522   real_x = real_y = width = height = 0;
523
524   atk_component_get_extents (component, &real_x, &real_y, &width, &height, coord_type);
525
526   if ((x >= real_x) &&
527       (x < real_x + width) &&
528       (y >= real_y) &&
529       (y < real_y + height))
530     return TRUE;
531   else
532     return FALSE;
533 }
534
535 static AtkObject* 
536 atk_component_real_ref_accessible_at_point (AtkComponent *component,
537                                             gint         x,
538                                             gint         y,
539                                             AtkCoordType coord_type)
540 {
541   gint count, i;
542
543   count = atk_object_get_n_accessible_children (ATK_OBJECT (component));
544
545   for (i = 0; i < count; i++)
546   {
547     AtkObject *obj;
548
549     obj = atk_object_ref_accessible_child (ATK_OBJECT (component), i);
550
551     if (obj != NULL)
552     {
553       if (atk_component_contains (ATK_COMPONENT (obj), x, y, coord_type))
554       {
555         return obj;
556       }
557       else
558       {
559         g_object_unref (obj);
560       }
561     }
562   }
563   return NULL;
564 }
565
566 static void
567 atk_component_real_get_position (AtkComponent *component,
568                                  gint         *x,
569                                  gint         *y,
570                                  AtkCoordType coord_type)
571 {
572   gint width, height;
573
574   atk_component_get_extents (component, x, y, &width, &height, coord_type);
575 }
576
577 static void
578 atk_component_real_get_size (AtkComponent *component,
579                              gint         *width,
580                              gint         *height)
581 {
582   gint x, y;
583   AtkCoordType coord_type;
584
585   /*
586    * Pick one coordinate type; it does not matter for size
587    */
588   coord_type = ATK_XY_WINDOW;
589
590   atk_component_get_extents (component, &x, &y, width, height, coord_type);
591 }
592
593 static gdouble
594 atk_component_real_get_alpha (AtkComponent    *component)
595 {
596     return (gdouble) 1.0;
597 }
598
599 static AtkRectangle *
600 atk_rectangle_copy (const AtkRectangle *rectangle)
601 {
602   AtkRectangle *result = g_new (AtkRectangle, 1);
603   *result = *rectangle;
604
605   return result;
606 }
607
608 GType
609 atk_rectangle_get_type (void)
610 {
611   static GType our_type = 0;
612
613   if (our_type == 0)
614     our_type = g_boxed_type_register_static ("AtkRectangle",
615                                              (GBoxedCopyFunc)atk_rectangle_copy,
616                                              (GBoxedFreeFunc)g_free);
617   return our_type;
618 }
619