atkcomponent: Add ScrollTo and ScrollToPoint component interfaces
[atk.git] / atk / atkcomponent.c
blobdd3895da7e906af98114f397cca2bf27a7d7be70
1 /* ATK - Accessibility Toolkit
2 * Copyright 2001 Sun Microsystems Inc.
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.
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.
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.
20 #include "config.h"
22 #include "atkcomponent.h"
24 /**
25 * SECTION:atkcomponent
26 * @Short_description: The ATK interface provided by UI components
27 * which occupy a physical area on the screen.
28 * which the user can activate/interact with.
29 * @Title:AtkComponent
31 * #AtkComponent should be implemented by most if not all UI elements
32 * with an actual on-screen presence, i.e. components which can be
33 * said to have a screen-coordinate bounding box. Virtually all
34 * widgets will need to have #AtkComponent implementations provided
35 * for their corresponding #AtkObject class. In short, only UI
36 * elements which are *not* GUI elements will omit this ATK interface.
38 * A possible exception might be textual information with a
39 * transparent background, in which case text glyph bounding box
40 * information is provided by #AtkText.
43 enum {
44 BOUNDS_CHANGED,
45 LAST_SIGNAL
48 static void atk_component_base_init (AtkComponentIface *class);
50 static gboolean atk_component_real_contains (AtkComponent *component,
51 gint x,
52 gint y,
53 AtkCoordType coord_type);
55 static AtkObject* atk_component_real_ref_accessible_at_point (AtkComponent *component,
56 gint x,
57 gint y,
58 AtkCoordType coord_type);
60 static void atk_component_real_get_position (AtkComponent *component,
61 gint *x,
62 gint *y,
63 AtkCoordType coord_type);
65 static void atk_component_real_get_size (AtkComponent *component,
66 gint *width,
67 gint *height);
69 static guint atk_component_signals[LAST_SIGNAL] = { 0 };
71 GType
72 atk_component_get_type (void)
74 static GType type = 0;
76 if (!type) {
77 static const GTypeInfo tinfo =
79 sizeof (AtkComponentIface),
80 (GBaseInitFunc) atk_component_base_init,
81 (GBaseFinalizeFunc) NULL,
85 type = g_type_register_static (G_TYPE_INTERFACE, "AtkComponent", &tinfo, 0);
88 return type;
91 static void
92 atk_component_base_init (AtkComponentIface *class)
94 static gboolean initialized = FALSE;
96 if (! initialized)
98 class->ref_accessible_at_point = atk_component_real_ref_accessible_at_point;
99 class->contains = atk_component_real_contains;
100 class->get_position = atk_component_real_get_position;
101 class->get_size = atk_component_real_get_size;
105 * AtkComponent::bounds-changed:
106 * @atkcomponent: the object which received the signal.
107 * @arg1: The AtkRectangle giving the new position and size.
109 * The 'bounds-changed" signal is emitted when the bposition or
110 * size of the component changes.
112 atk_component_signals[BOUNDS_CHANGED] =
113 g_signal_new ("bounds_changed",
114 ATK_TYPE_COMPONENT,
115 G_SIGNAL_RUN_LAST,
116 G_STRUCT_OFFSET (AtkComponentIface, bounds_changed),
117 (GSignalAccumulator) NULL, NULL,
118 g_cclosure_marshal_VOID__BOXED,
119 G_TYPE_NONE, 1,
120 ATK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
122 initialized = TRUE;
128 * atk_component_add_focus_handler: (skip)
129 * @component: The #AtkComponent to attach the @handler to
130 * @handler: The #AtkFocusHandler to be attached to @component
132 * Add the specified handler to the set of functions to be called
133 * when this object receives focus events (in or out). If the handler is
134 * already added it is not added again
136 * Deprecated: 2.9.4: If you need to track when an object gains or
137 * lose the focus, use the #AtkObject::state-change "focused" notification instead.
139 * Returns: a handler id which can be used in atk_component_remove_focus_handler()
140 * or zero if the handler was already added.
142 guint
143 atk_component_add_focus_handler (AtkComponent *component,
144 AtkFocusHandler handler)
146 AtkComponentIface *iface = NULL;
147 g_return_val_if_fail (ATK_IS_COMPONENT (component), 0);
149 iface = ATK_COMPONENT_GET_IFACE (component);
151 if (iface->add_focus_handler)
152 return (iface->add_focus_handler) (component, handler);
153 else
154 return 0;
158 * atk_component_remove_focus_handler:
159 * @component: the #AtkComponent to remove the focus handler from
160 * @handler_id: the handler id of the focus handler to be removed
161 * from @component
163 * Remove the handler specified by @handler_id from the list of
164 * functions to be executed when this object receives focus events
165 * (in or out).
167 * Deprecated: 2.9.4: If you need to track when an object gains or
168 * lose the focus, use the #AtkObject::state-change "focused" notification instead.
171 void
172 atk_component_remove_focus_handler (AtkComponent *component,
173 guint handler_id)
175 AtkComponentIface *iface = NULL;
176 g_return_if_fail (ATK_IS_COMPONENT (component));
178 iface = ATK_COMPONENT_GET_IFACE (component);
180 if (iface->remove_focus_handler)
181 (iface->remove_focus_handler) (component, handler_id);
185 * atk_component_contains:
186 * @component: the #AtkComponent
187 * @x: x coordinate
188 * @y: y coordinate
189 * @coord_type: specifies whether the coordinates are relative to the screen
190 * or to the components top level window
192 * Checks whether the specified point is within the extent of the @component.
194 * Toolkit implementor note: ATK provides a default implementation for
195 * this virtual method. In general there are little reason to
196 * re-implement it.
198 * Returns: %TRUE or %FALSE indicating whether the specified point is within
199 * the extent of the @component or not
201 gboolean
202 atk_component_contains (AtkComponent *component,
203 gint x,
204 gint y,
205 AtkCoordType coord_type)
207 AtkComponentIface *iface = NULL;
208 g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
210 iface = ATK_COMPONENT_GET_IFACE (component);
212 if (iface->contains)
213 return (iface->contains) (component, x, y, coord_type);
214 else
215 return FALSE;
219 * atk_component_ref_accessible_at_point:
220 * @component: the #AtkComponent
221 * @x: x coordinate
222 * @y: y coordinate
223 * @coord_type: specifies whether the coordinates are relative to the screen
224 * or to the components top level window
226 * Gets a reference to the accessible child, if one exists, at the
227 * coordinate point specified by @x and @y.
229 * Returns: (nullable) (transfer full): a reference to the accessible
230 * child, if one exists
232 AtkObject*
233 atk_component_ref_accessible_at_point (AtkComponent *component,
234 gint x,
235 gint y,
236 AtkCoordType coord_type)
238 AtkComponentIface *iface = NULL;
239 g_return_val_if_fail (ATK_IS_COMPONENT (component), NULL);
241 iface = ATK_COMPONENT_GET_IFACE (component);
243 if (iface->ref_accessible_at_point)
244 return (iface->ref_accessible_at_point) (component, x, y, coord_type);
245 else
246 return NULL;
250 * atk_component_get_extents:
251 * @component: an #AtkComponent
252 * @x: (out) (optional): address of #gint to put x coordinate
253 * @y: (out) (optional): address of #gint to put y coordinate
254 * @width: (out) (optional): address of #gint to put width
255 * @height: (out) (optional): address of #gint to put height
256 * @coord_type: specifies whether the coordinates are relative to the screen
257 * or to the components top level window
259 * Gets the rectangle which gives the extent of the @component.
262 void
263 atk_component_get_extents (AtkComponent *component,
264 gint *x,
265 gint *y,
266 gint *width,
267 gint *height,
268 AtkCoordType coord_type)
270 AtkComponentIface *iface = NULL;
271 gint local_x, local_y, local_width, local_height;
272 gint *real_x, *real_y, *real_width, *real_height;
274 g_return_if_fail (ATK_IS_COMPONENT (component));
276 if (x)
277 real_x = x;
278 else
279 real_x = &local_x;
280 if (y)
281 real_y = y;
282 else
283 real_y = &local_y;
284 if (width)
285 real_width = width;
286 else
287 real_width = &local_width;
288 if (height)
289 real_height = height;
290 else
291 real_height = &local_height;
293 iface = ATK_COMPONENT_GET_IFACE (component);
295 if (iface->get_extents)
296 (iface->get_extents) (component, real_x, real_y, real_width, real_height, coord_type);
300 * atk_component_get_position:
301 * @component: an #AtkComponent
302 * @x: (out) (optional): address of #gint to put x coordinate position
303 * @y: (out) (optional): address of #gint to put y coordinate position
304 * @coord_type: specifies whether the coordinates are relative to the screen
305 * or to the components top level window
307 * Gets the position of @component in the form of
308 * a point specifying @component's top-left corner.
310 * Deprecated: Since 2.12. Use atk_component_get_extents() instead.
312 void
313 atk_component_get_position (AtkComponent *component,
314 gint *x,
315 gint *y,
316 AtkCoordType coord_type)
318 AtkComponentIface *iface = NULL;
319 gint local_x, local_y;
320 gint *real_x, *real_y;
322 g_return_if_fail (ATK_IS_COMPONENT (component));
324 if (x)
325 real_x = x;
326 else
327 real_x = &local_x;
328 if (y)
329 real_y = y;
330 else
331 real_y = &local_y;
333 iface = ATK_COMPONENT_GET_IFACE (component);
335 if (iface->get_position)
336 (iface->get_position) (component, real_x, real_y, coord_type);
340 * atk_component_get_size:
341 * @component: an #AtkComponent
342 * @width: (out) (optional): address of #gint to put width of @component
343 * @height: (out) (optional): address of #gint to put height of @component
345 * Gets the size of the @component in terms of width and height.
347 * Deprecated: Since 2.12. Use atk_component_get_extents() instead.
349 void
350 atk_component_get_size (AtkComponent *component,
351 gint *width,
352 gint *height)
354 AtkComponentIface *iface = NULL;
355 gint local_width, local_height;
356 gint *real_width, *real_height;
358 g_return_if_fail (ATK_IS_COMPONENT (component));
360 if (width)
361 real_width = width;
362 else
363 real_width = &local_width;
364 if (height)
365 real_height = height;
366 else
367 real_height = &local_height;
369 g_return_if_fail (ATK_IS_COMPONENT (component));
371 iface = ATK_COMPONENT_GET_IFACE (component);
373 if (iface->get_size)
374 (iface->get_size) (component, real_width, real_height);
378 * atk_component_get_layer:
379 * @component: an #AtkComponent
381 * Gets the layer of the component.
383 * Returns: an #AtkLayer which is the layer of the component
385 AtkLayer
386 atk_component_get_layer (AtkComponent *component)
388 AtkComponentIface *iface;
390 g_return_val_if_fail (ATK_IS_COMPONENT (component), ATK_LAYER_INVALID);
392 iface = ATK_COMPONENT_GET_IFACE (component);
393 if (iface->get_layer)
394 return (iface->get_layer) (component);
395 else
396 return ATK_LAYER_WIDGET;
400 * atk_component_get_mdi_zorder:
401 * @component: an #AtkComponent
403 * Gets the zorder of the component. The value G_MININT will be returned
404 * if the layer of the component is not ATK_LAYER_MDI or ATK_LAYER_WINDOW.
406 * Returns: a gint which is the zorder of the component, i.e. the depth at
407 * which the component is shown in relation to other components in the same
408 * container.
410 gint
411 atk_component_get_mdi_zorder (AtkComponent *component)
413 AtkComponentIface *iface;
415 g_return_val_if_fail (ATK_IS_COMPONENT (component), G_MININT);
417 iface = ATK_COMPONENT_GET_IFACE (component);
418 if (iface->get_mdi_zorder)
419 return (iface->get_mdi_zorder) (component);
420 else
421 return G_MININT;
425 * atk_component_get_alpha:
426 * @component: an #AtkComponent
428 * Returns the alpha value (i.e. the opacity) for this
429 * @component, on a scale from 0 (fully transparent) to 1.0
430 * (fully opaque).
432 * Returns: An alpha value from 0 to 1.0, inclusive.
433 * Since: 1.12
435 gdouble
436 atk_component_get_alpha (AtkComponent *component)
438 AtkComponentIface *iface;
440 g_return_val_if_fail (ATK_IS_COMPONENT (component), G_MININT);
442 iface = ATK_COMPONENT_GET_IFACE (component);
443 if (iface->get_alpha)
444 return (iface->get_alpha) (component);
445 else
446 return (gdouble) 1.0;
450 * atk_component_grab_focus:
451 * @component: an #AtkComponent
453 * Grabs focus for this @component.
455 * Returns: %TRUE if successful, %FALSE otherwise.
457 gboolean
458 atk_component_grab_focus (AtkComponent *component)
460 AtkComponentIface *iface = NULL;
461 g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
463 iface = ATK_COMPONENT_GET_IFACE (component);
465 if (iface->grab_focus)
466 return (iface->grab_focus) (component);
467 else
468 return FALSE;
472 * atk_component_set_extents:
473 * @component: an #AtkComponent
474 * @x: x coordinate
475 * @y: y coordinate
476 * @width: width to set for @component
477 * @height: height to set for @component
478 * @coord_type: specifies whether the coordinates are relative to the screen
479 * or to the components top level window
481 * Sets the extents of @component.
483 * Returns: %TRUE or %FALSE whether the extents were set or not
485 gboolean
486 atk_component_set_extents (AtkComponent *component,
487 gint x,
488 gint y,
489 gint width,
490 gint height,
491 AtkCoordType coord_type)
493 AtkComponentIface *iface = NULL;
494 g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
496 iface = ATK_COMPONENT_GET_IFACE (component);
498 if (iface->set_extents)
499 return (iface->set_extents) (component, x, y, width, height, coord_type);
500 else
501 return FALSE;
505 * atk_component_set_position:
506 * @component: an #AtkComponent
507 * @x: x coordinate
508 * @y: y coordinate
509 * @coord_type: specifies whether the coordinates are relative to the screen
510 * or to the component's top level window
512 * Sets the position of @component.
514 * Contrary to atk_component_scroll_to, this does not trigger any scrolling,
515 * this just moves @component in its parent.
517 * Returns: %TRUE or %FALSE whether or not the position was set or not
519 gboolean
520 atk_component_set_position (AtkComponent *component,
521 gint x,
522 gint y,
523 AtkCoordType coord_type)
525 AtkComponentIface *iface = NULL;
526 g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
528 iface = ATK_COMPONENT_GET_IFACE (component);
530 if (iface->set_position)
531 return (iface->set_position) (component, x, y, coord_type);
532 else
533 return FALSE;
537 * atk_component_set_size:
538 * @component: an #AtkComponent
539 * @width: width to set for @component
540 * @height: height to set for @component
542 * Set the size of the @component in terms of width and height.
544 * Returns: %TRUE or %FALSE whether the size was set or not
546 gboolean
547 atk_component_set_size (AtkComponent *component,
548 gint x,
549 gint y)
551 AtkComponentIface *iface = NULL;
552 g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
554 iface = ATK_COMPONENT_GET_IFACE (component);
556 if (iface->set_size)
557 return (iface->set_size) (component, x, y);
558 else
559 return FALSE;
563 * atk_component_scroll_to (AtkComponent *accessible, AtkScrollType type)
564 * @component: an #AtkComponent
565 * @type: specify where the object should be made visible.
567 * Makes @component visible on the screen by scrolling all necessary parents.
569 * Contrary to atk_component_set_position, this does not actually move
570 * @component in its parent, this only makes the parents scroll so that the
571 * object shows up on the screen, given its current position within the parents.
573 * Since: 2.30
575 * Returns: whether scrolling was successful.
577 gboolean
578 atk_component_scroll_to (AtkComponent *component, AtkScrollType type)
580 AtkComponentIface *iface = NULL;
581 g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
583 iface = ATK_COMPONENT_GET_IFACE (component);
585 if (iface->scroll_to)
586 return (iface->scroll_to) (component, type);
587 else
588 return FALSE;
592 * atk_component_scroll_to_point (AtkComponent *accessible, AtkScrollType type, gint x, gint y)
593 * @coords: specify whether coordinates are relative to the screen or to the
594 * parent object.
595 * @x: x-position where to scroll to
596 * @y: y-position where to scroll to
598 * Makes an object visible on the screen at a given position by scrolling all
599 * necessary parents.
601 * Since: 2.30
603 * Returns: whether scrolling was successful.
605 gboolean
606 atk_component_scroll_to_point (AtkComponent *component, AtkCoordType coords, gint x, gint y)
608 AtkComponentIface *iface = NULL;
609 g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE);
611 iface = ATK_COMPONENT_GET_IFACE (component);
613 if (iface->scroll_to_point)
614 return (iface->scroll_to_point) (component, coords, x, y);
615 else
616 return FALSE;
619 static gboolean
620 atk_component_real_contains (AtkComponent *component,
621 gint x,
622 gint y,
623 AtkCoordType coord_type)
625 gint real_x, real_y, width, height;
627 real_x = real_y = width = height = 0;
629 atk_component_get_extents (component, &real_x, &real_y, &width, &height, coord_type);
631 if ((x >= real_x) &&
632 (x < real_x + width) &&
633 (y >= real_y) &&
634 (y < real_y + height))
635 return TRUE;
636 else
637 return FALSE;
640 static AtkObject*
641 atk_component_real_ref_accessible_at_point (AtkComponent *component,
642 gint x,
643 gint y,
644 AtkCoordType coord_type)
646 gint count, i;
648 count = atk_object_get_n_accessible_children (ATK_OBJECT (component));
650 for (i = 0; i < count; i++)
652 AtkObject *obj;
654 obj = atk_object_ref_accessible_child (ATK_OBJECT (component), i);
656 if (obj != NULL)
658 if (atk_component_contains (ATK_COMPONENT (obj), x, y, coord_type))
660 return obj;
662 else
664 g_object_unref (obj);
668 return NULL;
671 static void
672 atk_component_real_get_position (AtkComponent *component,
673 gint *x,
674 gint *y,
675 AtkCoordType coord_type)
677 gint width, height;
679 atk_component_get_extents (component, x, y, &width, &height, coord_type);
682 static void
683 atk_component_real_get_size (AtkComponent *component,
684 gint *width,
685 gint *height)
687 gint x, y;
688 AtkCoordType coord_type;
691 * Pick one coordinate type; it does not matter for size
693 coord_type = ATK_XY_WINDOW;
695 atk_component_get_extents (component, &x, &y, width, height, coord_type);
698 static AtkRectangle *
699 atk_rectangle_copy (const AtkRectangle *rectangle)
701 AtkRectangle *result = g_new (AtkRectangle, 1);
702 *result = *rectangle;
704 return result;
707 GType
708 atk_rectangle_get_type (void)
710 static GType our_type = 0;
712 if (our_type == 0)
713 our_type = g_boxed_type_register_static ("AtkRectangle",
714 (GBoxedCopyFunc)atk_rectangle_copy,
715 (GBoxedFreeFunc)g_free);
716 return our_type;