1 /* GAIL - The GNOME Accessibility Implementation Library
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 Library 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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library 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.
27 /* IMPORTANT!!! This source file does NOT contain the implementation
28 * code for AtkUtil - for that code, please see gail/gail.c.
33 * @Short_description: GailMisc is a set of utility functions which may be
34 * useful to implementors of Atk interfaces for custom widgets.
37 * GailMisc is a set of utility function which are used in the implemementation
38 * of Atk interfaces for GTK+ widgets. They may be useful to implementors of
39 * Atk interfaces for custom widgets.
44 * gail_misc_get_extents_from_pango_rectangle:
45 * @widget: The widget that contains the PangoLayout, that contains
47 * @char_rect: The #PangoRectangle from which to calculate extents
48 * @x_layout: The x-offset at which the widget displays the
49 * PangoLayout that contains the PangoRectangle, relative to @widget
50 * @y_layout: The y-offset at which the widget displays the
51 * PangoLayout that contains the PangoRectangle, relative to @widget
52 * @x: The x-position of the #PangoRectangle relative to @coords
53 * @y: The y-position of the #PangoRectangle relative to @coords
54 * @width: The width of the #PangoRectangle
55 * @height: The height of the #PangoRectangle
56 * @coords: An #AtkCoordType enumeration
58 * Gets the extents of @char_rect in device coordinates,
59 * relative to either top-level window or screen coordinates as
60 * specified by @coords.
63 gail_misc_get_extents_from_pango_rectangle (GtkWidget *widget,
64 PangoRectangle *char_rect,
73 gint x_window, y_window, x_toplevel, y_toplevel;
75 gail_misc_get_origins (widget, &x_window, &y_window,
76 &x_toplevel, &y_toplevel);
78 *x = (char_rect->x / PANGO_SCALE) + x_layout + x_window;
79 *y = (char_rect->y / PANGO_SCALE) + y_layout + y_window;
80 if (coords == ATK_XY_WINDOW)
85 else if (coords != ATK_XY_SCREEN)
93 *height = char_rect->height / PANGO_SCALE;
94 *width = char_rect->width / PANGO_SCALE;
100 * gail_misc_get_index_at_point_in_layout:
101 * @widget: A #GtkWidget
102 * @layout: The #PangoLayout from which to get the index at the
104 * @x_layout: The x-offset at which the widget displays the
105 * #PangoLayout, relative to @widget
106 * @y_layout: The y-offset at which the widget displays the
107 * #PangoLayout, relative to @widget
108 * @x: The x-coordinate relative to @coords at which to
109 * calculate the index
110 * @y: The y-coordinate relative to @coords at which to
111 * calculate the index
112 * @coords: An #AtkCoordType enumeration
114 * Gets the byte offset at the specified @x and @y in a #PangoLayout.
116 * Returns: the byte offset at the specified @x and @y in a
120 gail_misc_get_index_at_point_in_layout (GtkWidget *widget,
128 gint index, x_window, y_window, x_toplevel, y_toplevel;
132 gail_misc_get_origins (widget, &x_window, &y_window,
133 &x_toplevel, &y_toplevel);
134 x_temp = x - x_layout - x_window;
135 y_temp = y - y_layout - y_window;
136 if (coords == ATK_XY_WINDOW)
138 x_temp += x_toplevel;
139 y_temp += y_toplevel;
141 else if (coords != ATK_XY_SCREEN)
144 ret = pango_layout_xy_to_index (layout,
145 x_temp * PANGO_SCALE,
146 y_temp * PANGO_SCALE,
150 if (x_temp < 0 || y_temp < 0)
159 * gail_misc_add_attribute:
160 * @attrib_set: The #AtkAttributeSet to add the attribute to
161 * @attr: The AtkTextAttrribute which identifies the attribute to be added
162 * @value: The attribute value
164 * Creates an #AtkAttribute from @attr and @value, and adds it
167 * Returns: A pointer to the new #AtkAttributeSet.
170 gail_misc_add_attribute (AtkAttributeSet *attrib_set,
171 AtkTextAttribute attr,
174 AtkAttributeSet *return_set;
175 AtkAttribute *at = g_malloc (sizeof (AtkAttribute));
176 at->name = g_strdup (atk_text_attribute_get_name (attr));
178 return_set = g_slist_prepend(attrib_set, at);
183 * gail_misc_layout_get_run_attributes:
184 * @attrib_set: The #AtkAttributeSet to add the attribute to
185 * @layout: The PangoLayout from which the attributes will be obtained
187 * @offset: The offset at which the attributes are required
188 * @start_offset: The start offset of the current run
189 * @end_offset: The end offset of the current run
191 * Adds the attributes for the run starting at offset to the specified
194 * Returns: A pointer to the #AtkAttributeSet.
197 gail_misc_layout_get_run_attributes (AtkAttributeSet *attrib_set,
204 PangoAttrIterator *iter;
206 PangoAttrString *pango_string;
207 PangoAttrInt *pango_int;
208 PangoAttrColor *pango_color;
209 PangoAttrLanguage *pango_lang;
210 PangoAttrFloat *pango_float;
211 gint index, start_index, end_index;
212 gboolean is_next = TRUE;
216 len = g_utf8_strlen (text, -1);
217 /* Grab the attributes of the PangoLayout, if any */
218 if ((attr = pango_layout_get_attributes (layout)) == NULL)
224 iter = pango_attr_list_get_iterator (attr);
225 /* Get invariant range offsets */
226 /* If offset out of range, set offset in range */
232 index = g_utf8_offset_to_pointer (text, offset) - text;
233 pango_attr_iterator_range (iter, &start_index, &end_index);
236 if (index >= start_index && index < end_index)
238 *start_offset = g_utf8_pointer_to_offset (text,
240 if (end_index == G_MAXINT)
244 *end_offset = g_utf8_pointer_to_offset (text,
248 is_next = pango_attr_iterator_next (iter);
249 pango_attr_iterator_range (iter, &start_index, &end_index);
252 if ((pango_string = (PangoAttrString*) pango_attr_iterator_get (iter,
253 PANGO_ATTR_FAMILY)) != NULL)
255 value = g_strdup_printf("%s", pango_string->value);
256 attrib_set = gail_misc_add_attribute (attrib_set,
257 ATK_TEXT_ATTR_FAMILY_NAME,
260 if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
261 PANGO_ATTR_STYLE)) != NULL)
263 attrib_set = gail_misc_add_attribute (attrib_set,
265 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STYLE, pango_int->value)));
267 if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
268 PANGO_ATTR_WEIGHT)) != NULL)
270 value = g_strdup_printf("%i", pango_int->value);
271 attrib_set = gail_misc_add_attribute (attrib_set,
272 ATK_TEXT_ATTR_WEIGHT,
275 if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
276 PANGO_ATTR_VARIANT)) != NULL)
278 attrib_set = gail_misc_add_attribute (attrib_set,
279 ATK_TEXT_ATTR_VARIANT,
280 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_VARIANT, pango_int->value)));
282 if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
283 PANGO_ATTR_STRETCH)) != NULL)
285 attrib_set = gail_misc_add_attribute (attrib_set,
286 ATK_TEXT_ATTR_STRETCH,
287 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRETCH, pango_int->value)));
289 if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
290 PANGO_ATTR_SIZE)) != NULL)
292 value = g_strdup_printf("%i", pango_int->value / PANGO_SCALE);
293 attrib_set = gail_misc_add_attribute (attrib_set,
297 if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
298 PANGO_ATTR_UNDERLINE)) != NULL)
300 attrib_set = gail_misc_add_attribute (attrib_set,
301 ATK_TEXT_ATTR_UNDERLINE,
302 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_UNDERLINE, pango_int->value)));
304 if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
305 PANGO_ATTR_STRIKETHROUGH)) != NULL)
307 attrib_set = gail_misc_add_attribute (attrib_set,
308 ATK_TEXT_ATTR_STRIKETHROUGH,
309 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRIKETHROUGH, pango_int->value)));
311 if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
312 PANGO_ATTR_RISE)) != NULL)
314 value = g_strdup_printf("%i", pango_int->value);
315 attrib_set = gail_misc_add_attribute (attrib_set,
319 if ((pango_lang = (PangoAttrLanguage*) pango_attr_iterator_get (iter,
320 PANGO_ATTR_LANGUAGE)) != NULL)
322 value = g_strdup( pango_language_to_string( pango_lang->value));
323 attrib_set = gail_misc_add_attribute (attrib_set,
324 ATK_TEXT_ATTR_LANGUAGE,
327 if ((pango_float = (PangoAttrFloat*) pango_attr_iterator_get (iter,
328 PANGO_ATTR_SCALE)) != NULL)
330 value = g_strdup_printf("%g", pango_float->value);
331 attrib_set = gail_misc_add_attribute (attrib_set,
335 if ((pango_color = (PangoAttrColor*) pango_attr_iterator_get (iter,
336 PANGO_ATTR_FOREGROUND)) != NULL)
338 value = g_strdup_printf ("%u,%u,%u",
339 pango_color->color.red,
340 pango_color->color.green,
341 pango_color->color.blue);
342 attrib_set = gail_misc_add_attribute (attrib_set,
343 ATK_TEXT_ATTR_FG_COLOR,
346 if ((pango_color = (PangoAttrColor*) pango_attr_iterator_get (iter,
347 PANGO_ATTR_BACKGROUND)) != NULL)
349 value = g_strdup_printf ("%u,%u,%u",
350 pango_color->color.red,
351 pango_color->color.green,
352 pango_color->color.blue);
353 attrib_set = gail_misc_add_attribute (attrib_set,
354 ATK_TEXT_ATTR_BG_COLOR,
357 pango_attr_iterator_destroy (iter);
362 * gail_misc_get_default_attributes:
363 * @attrib_set: The #AtkAttributeSet to add the attribute to
364 * @layout: The PangoLayout from which the attributes will be obtained
365 * @widget: The GtkWidget for which the default attributes are required.
367 * Adds the default attributes to the specified attribute set.
369 * Returns: A pointer to the #AtkAttributeSet.
372 gail_misc_get_default_attributes (AtkAttributeSet *attrib_set,
376 PangoContext *context;
377 GtkStyleContext *style_context;
383 attrib_set = gail_misc_add_attribute (attrib_set,
384 ATK_TEXT_ATTR_DIRECTION,
385 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION,
386 gtk_widget_get_direction (widget))));
388 context = pango_layout_get_context (layout);
391 PangoLanguage* language;
392 PangoFontDescription* font;
394 language = pango_context_get_language (context);
397 attrib_set = gail_misc_add_attribute (attrib_set,
398 ATK_TEXT_ATTR_LANGUAGE,
399 g_strdup (pango_language_to_string (language)));
401 font = pango_context_get_font_description (context);
404 attrib_set = gail_misc_add_attribute (attrib_set,
406 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STYLE,
407 pango_font_description_get_style (font))));
408 attrib_set = gail_misc_add_attribute (attrib_set,
409 ATK_TEXT_ATTR_VARIANT,
410 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_VARIANT,
411 pango_font_description_get_variant (font))));
412 attrib_set = gail_misc_add_attribute (attrib_set,
413 ATK_TEXT_ATTR_STRETCH,
414 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRETCH,
415 pango_font_description_get_stretch (font))));
416 attrib_set = gail_misc_add_attribute (attrib_set,
417 ATK_TEXT_ATTR_FAMILY_NAME,
418 g_strdup (pango_font_description_get_family (font)));
419 attrib_set = gail_misc_add_attribute (attrib_set,
420 ATK_TEXT_ATTR_WEIGHT,
421 g_strdup_printf ("%d",
422 pango_font_description_get_weight (font)));
423 attrib_set = gail_misc_add_attribute (attrib_set,
425 g_strdup_printf ("%i",
426 pango_font_description_get_size (font) / PANGO_SCALE));
429 if (pango_layout_get_justify (layout))
435 PangoAlignment align;
437 align = pango_layout_get_alignment (layout);
438 if (align == PANGO_ALIGN_LEFT)
440 else if (align == PANGO_ALIGN_CENTER)
442 else /* if (align == PANGO_ALIGN_RIGHT) */
445 attrib_set = gail_misc_add_attribute (attrib_set,
446 ATK_TEXT_ATTR_JUSTIFICATION,
447 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_JUSTIFICATION,
449 mode = pango_layout_get_wrap (layout);
450 if (mode == PANGO_WRAP_WORD)
452 else /* if (mode == PANGO_WRAP_CHAR) */
454 attrib_set = gail_misc_add_attribute (attrib_set,
455 ATK_TEXT_ATTR_WRAP_MODE,
456 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_WRAP_MODE,
459 style_context = gtk_widget_get_style_context (widget);
461 gtk_style_context_get_background_color (style_context, 0, &color);
462 value = g_strdup_printf ("%u,%u,%u",
463 (guint) ceil (color.red * 65536 - color.red),
464 (guint) ceil (color.green * 65536 - color.green),
465 (guint) ceil (color.blue * 65536 - color.blue));
466 attrib_set = gail_misc_add_attribute (attrib_set,
467 ATK_TEXT_ATTR_BG_COLOR,
470 gtk_style_context_get_color (style_context, 0, &color);
471 value = g_strdup_printf ("%u,%u,%u",
472 (guint) ceil (color.red * 65536 - color.red),
473 (guint) ceil (color.green * 65536 - color.green),
474 (guint) ceil (color.blue * 65536 - color.blue));
475 attrib_set = gail_misc_add_attribute (attrib_set,
476 ATK_TEXT_ATTR_FG_COLOR,
479 attrib_set = gail_misc_add_attribute (attrib_set,
480 ATK_TEXT_ATTR_FG_STIPPLE,
481 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_FG_STIPPLE,
483 attrib_set = gail_misc_add_attribute (attrib_set,
484 ATK_TEXT_ATTR_BG_STIPPLE,
485 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_BG_STIPPLE,
487 attrib_set = gail_misc_add_attribute (attrib_set,
488 ATK_TEXT_ATTR_STRIKETHROUGH,
489 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRIKETHROUGH,
491 attrib_set = gail_misc_add_attribute (attrib_set,
492 ATK_TEXT_ATTR_UNDERLINE,
493 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_UNDERLINE,
495 attrib_set = gail_misc_add_attribute (attrib_set,
497 g_strdup_printf ("%i", 0));
498 attrib_set = gail_misc_add_attribute (attrib_set,
500 g_strdup_printf ("%g", 1.0));
501 attrib_set = gail_misc_add_attribute (attrib_set,
502 ATK_TEXT_ATTR_BG_FULL_HEIGHT,
503 g_strdup_printf ("%i", 0));
504 attrib_set = gail_misc_add_attribute (attrib_set,
505 ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP,
506 g_strdup_printf ("%i", 0));
507 attrib_set = gail_misc_add_attribute (attrib_set,
508 ATK_TEXT_ATTR_PIXELS_BELOW_LINES,
509 g_strdup_printf ("%i", 0));
510 attrib_set = gail_misc_add_attribute (attrib_set,
511 ATK_TEXT_ATTR_PIXELS_ABOVE_LINES,
512 g_strdup_printf ("%i", 0));
513 attrib_set = gail_misc_add_attribute (attrib_set,
514 ATK_TEXT_ATTR_EDITABLE,
515 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_EDITABLE,
517 attrib_set = gail_misc_add_attribute (attrib_set,
518 ATK_TEXT_ATTR_INVISIBLE,
519 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_INVISIBLE,
521 attrib_set = gail_misc_add_attribute (attrib_set,
522 ATK_TEXT_ATTR_INDENT,
523 g_strdup_printf ("%i", 0));
524 attrib_set = gail_misc_add_attribute (attrib_set,
525 ATK_TEXT_ATTR_RIGHT_MARGIN,
526 g_strdup_printf ("%i", 0));
527 attrib_set = gail_misc_add_attribute (attrib_set,
528 ATK_TEXT_ATTR_LEFT_MARGIN,
529 g_strdup_printf ("%i", 0));
534 * gail_misc_get_origins:
535 * @widget: a #GtkWidget
536 * @x_window: the x-origin of the widget->window
537 * @y_window: the y-origin of the widget->window
538 * @x_toplevel: the x-origin of the toplevel window for widget->window
539 * @y_toplevel: the y-origin of the toplevel window for widget->window
541 * Gets the origin of the widget window, and the origin of the
542 * widgets top-level window.
545 gail_misc_get_origins (GtkWidget *widget,
553 if (GTK_IS_TREE_VIEW (widget))
554 window = gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget));
556 window = gtk_widget_get_window (widget);
558 gdk_window_get_origin (window, x_window, y_window);
559 window = gdk_window_get_toplevel (gtk_widget_get_window (widget));
560 gdk_window_get_origin (window, x_toplevel, y_toplevel);