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_grab_focus: |
---|
381 | * @component: an #AtkComponent |
---|
382 | * |
---|
383 | * Grabs focus for this @component. |
---|
384 | * |
---|
385 | * Returns: %TRUE if successful, %FALSE otherwise. |
---|
386 | **/ |
---|
387 | gboolean |
---|
388 | atk_component_grab_focus (AtkComponent *component) |
---|
389 | { |
---|
390 | AtkComponentIface *iface = NULL; |
---|
391 | g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE); |
---|
392 | |
---|
393 | iface = ATK_COMPONENT_GET_IFACE (component); |
---|
394 | |
---|
395 | if (iface->grab_focus) |
---|
396 | return (iface->grab_focus) (component); |
---|
397 | else |
---|
398 | return FALSE; |
---|
399 | } |
---|
400 | |
---|
401 | /** |
---|
402 | * atk_component_set_extents: |
---|
403 | * @component: an #AtkComponent |
---|
404 | * @x: x coordinate |
---|
405 | * @y: y coordinate |
---|
406 | * @width: width to set for @component |
---|
407 | * @height: height to set for @component |
---|
408 | * @coord_type: specifies whether the coordinates are relative to the screen |
---|
409 | * or to the components top level window |
---|
410 | * |
---|
411 | * Sets the extents of @component. |
---|
412 | * |
---|
413 | * Returns: %TRUE or %FALSE whether the extents were set or not |
---|
414 | **/ |
---|
415 | gboolean |
---|
416 | atk_component_set_extents (AtkComponent *component, |
---|
417 | gint x, |
---|
418 | gint y, |
---|
419 | gint width, |
---|
420 | gint height, |
---|
421 | AtkCoordType coord_type) |
---|
422 | { |
---|
423 | AtkComponentIface *iface = NULL; |
---|
424 | g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE); |
---|
425 | |
---|
426 | iface = ATK_COMPONENT_GET_IFACE (component); |
---|
427 | |
---|
428 | if (iface->set_extents) |
---|
429 | return (iface->set_extents) (component, x, y, width, height, coord_type); |
---|
430 | else |
---|
431 | return FALSE; |
---|
432 | } |
---|
433 | |
---|
434 | /** |
---|
435 | * atk_component_set_position: |
---|
436 | * @component: an #AtkComponent |
---|
437 | * @x: x coordinate |
---|
438 | * @y: y coordinate |
---|
439 | * @coord_type: specifies whether the coordinates are relative to the screen |
---|
440 | * or to the components top level window |
---|
441 | * |
---|
442 | * Sets the postition of @component. |
---|
443 | * |
---|
444 | * Returns: %TRUE or %FALSE whether or not the position was set or not |
---|
445 | **/ |
---|
446 | gboolean |
---|
447 | atk_component_set_position (AtkComponent *component, |
---|
448 | gint x, |
---|
449 | gint y, |
---|
450 | AtkCoordType coord_type) |
---|
451 | { |
---|
452 | AtkComponentIface *iface = NULL; |
---|
453 | g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE); |
---|
454 | |
---|
455 | iface = ATK_COMPONENT_GET_IFACE (component); |
---|
456 | |
---|
457 | if (iface->set_position) |
---|
458 | return (iface->set_position) (component, x, y, coord_type); |
---|
459 | else |
---|
460 | return FALSE; |
---|
461 | } |
---|
462 | |
---|
463 | /** |
---|
464 | * atk_component_set_size: |
---|
465 | * @component: an #AtkComponent |
---|
466 | * @width: width to set for @component |
---|
467 | * @height: height to set for @component |
---|
468 | * |
---|
469 | * Set the size of the @component in terms of width and height. |
---|
470 | * |
---|
471 | * Returns: %TRUE or %FALSE whether the size was set or not |
---|
472 | **/ |
---|
473 | gboolean |
---|
474 | atk_component_set_size (AtkComponent *component, |
---|
475 | gint x, |
---|
476 | gint y) |
---|
477 | { |
---|
478 | AtkComponentIface *iface = NULL; |
---|
479 | g_return_val_if_fail (ATK_IS_COMPONENT (component), FALSE); |
---|
480 | |
---|
481 | iface = ATK_COMPONENT_GET_IFACE (component); |
---|
482 | |
---|
483 | if (iface->set_size) |
---|
484 | return (iface->set_size) (component, x, y); |
---|
485 | else |
---|
486 | return FALSE; |
---|
487 | } |
---|
488 | |
---|
489 | static gboolean |
---|
490 | atk_component_real_contains (AtkComponent *component, |
---|
491 | gint x, |
---|
492 | gint y, |
---|
493 | AtkCoordType coord_type) |
---|
494 | { |
---|
495 | gint real_x, real_y, width, height; |
---|
496 | |
---|
497 | real_x = real_y = width = height = 0; |
---|
498 | |
---|
499 | atk_component_get_extents (component, &real_x, &real_y, &width, &height, coord_type); |
---|
500 | |
---|
501 | if ((x >= real_x) && |
---|
502 | (x < real_x + width) && |
---|
503 | (y >= real_y) && |
---|
504 | (y < real_y + height)) |
---|
505 | return TRUE; |
---|
506 | else |
---|
507 | return FALSE; |
---|
508 | } |
---|
509 | |
---|
510 | static AtkObject* |
---|
511 | atk_component_real_ref_accessible_at_point (AtkComponent *component, |
---|
512 | gint x, |
---|
513 | gint y, |
---|
514 | AtkCoordType coord_type) |
---|
515 | { |
---|
516 | gint count, i; |
---|
517 | |
---|
518 | count = atk_object_get_n_accessible_children (ATK_OBJECT (component)); |
---|
519 | |
---|
520 | for (i = 0; i < count; i++) |
---|
521 | { |
---|
522 | AtkObject *obj; |
---|
523 | |
---|
524 | obj = atk_object_ref_accessible_child (ATK_OBJECT (component), i); |
---|
525 | |
---|
526 | if (obj != NULL) |
---|
527 | { |
---|
528 | if (atk_component_contains (ATK_COMPONENT (obj), x, y, coord_type)) |
---|
529 | { |
---|
530 | return obj; |
---|
531 | } |
---|
532 | else |
---|
533 | { |
---|
534 | g_object_unref (obj); |
---|
535 | } |
---|
536 | } |
---|
537 | } |
---|
538 | return NULL; |
---|
539 | } |
---|
540 | |
---|
541 | static void |
---|
542 | atk_component_real_get_position (AtkComponent *component, |
---|
543 | gint *x, |
---|
544 | gint *y, |
---|
545 | AtkCoordType coord_type) |
---|
546 | { |
---|
547 | gint width, height; |
---|
548 | |
---|
549 | atk_component_get_extents (component, x, y, &width, &height, coord_type); |
---|
550 | } |
---|
551 | |
---|
552 | static void |
---|
553 | atk_component_real_get_size (AtkComponent *component, |
---|
554 | gint *width, |
---|
555 | gint *height) |
---|
556 | { |
---|
557 | gint x, y; |
---|
558 | AtkCoordType coord_type; |
---|
559 | |
---|
560 | /* |
---|
561 | * Pick one coordinate type; it does not matter for size |
---|
562 | */ |
---|
563 | coord_type = ATK_XY_WINDOW; |
---|
564 | |
---|
565 | atk_component_get_extents (component, &x, &y, width, height, coord_type); |
---|
566 | } |
---|
567 | |
---|
568 | static AtkRectangle * |
---|
569 | atk_rectangle_copy (const AtkRectangle *rectangle) |
---|
570 | { |
---|
571 | AtkRectangle *result = g_new (AtkRectangle, 1); |
---|
572 | *result = *rectangle; |
---|
573 | |
---|
574 | return result; |
---|
575 | } |
---|
576 | |
---|
577 | GType |
---|
578 | atk_rectangle_get_type (void) |
---|
579 | { |
---|
580 | static GType our_type = 0; |
---|
581 | |
---|
582 | if (our_type == 0) |
---|
583 | our_type = g_boxed_type_register_static ("AtkRectangle", |
---|
584 | (GBoxedCopyFunc)atk_rectangle_copy, |
---|
585 | (GBoxedFreeFunc)g_free); |
---|
586 | return our_type; |
---|
587 | } |
---|
588 | |
---|