1 /* GAIL - The GNOME Accessibility Implementation Library
2 * Copyright 2001, 2002, 2003 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, see <http://www.gnu.org/licenses/>.
23 #include "gtkentryaccessible.h"
24 #include "gtkentryprivate.h"
25 #include "gtkcomboboxaccessible.h"
27 #define GTK_TYPE_ENTRY_ICON_ACCESSIBLE (_gtk_entry_icon_accessible_get_type ())
28 #define GTK_ENTRY_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ENTRY_ICON_ACCESSIBLE, GtkEntryIconAccessible))
29 #define GTK_IS_ENTRY_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ENTRY_ICON_ACCESSIBLE))
31 struct _GtkEntryAccessiblePrivate
38 typedef struct _GtkEntryIconAccessible GtkEntryIconAccessible;
39 typedef struct _GtkEntryIconAccessibleClass GtkEntryIconAccessibleClass;
41 struct _GtkEntryIconAccessible
45 GtkEntryAccessible *entry;
46 GtkEntryIconPosition pos;
49 struct _GtkEntryIconAccessibleClass
51 AtkObjectClass parent_class;
54 static void atk_action_interface_init (AtkActionIface *iface);
56 static void icon_atk_action_interface_init (AtkActionIface *iface);
57 static void icon_atk_component_interface_init (AtkComponentIface *iface);
59 GType _gtk_entry_icon_accessible_get_type (void);
61 G_DEFINE_TYPE_WITH_CODE (GtkEntryIconAccessible, _gtk_entry_icon_accessible, ATK_TYPE_OBJECT,
62 G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, icon_atk_action_interface_init)
63 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, icon_atk_component_interface_init))
66 gtk_entry_icon_accessible_remove_entry (gpointer data, GObject *obj)
68 GtkEntryIconAccessible *icon = data;
73 g_object_notify (G_OBJECT (icon), "accessible-parent");
74 atk_object_notify_state_change (ATK_OBJECT (icon), ATK_STATE_DEFUNCT, TRUE);
79 gtk_entry_icon_accessible_new (GtkEntryAccessible *entry,
80 GtkEntryIconPosition pos)
82 GtkEntryIconAccessible *icon;
83 AtkObject *accessible;
85 icon = g_object_new (_gtk_entry_icon_accessible_get_type (), NULL);
87 g_object_weak_ref (G_OBJECT (entry),
88 gtk_entry_icon_accessible_remove_entry,
92 accessible = ATK_OBJECT (icon);
93 atk_object_initialize (accessible, NULL);
98 _gtk_entry_icon_accessible_init (GtkEntryIconAccessible *icon)
103 gtk_entry_icon_accessible_initialize (AtkObject *obj,
106 GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (obj);
107 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
108 GtkEntry *gtk_entry = GTK_ENTRY (widget);
112 ATK_OBJECT_CLASS (_gtk_entry_icon_accessible_parent_class)->initialize (obj, data);
113 atk_object_set_role (obj, ATK_ROLE_ICON);
115 name = gtk_entry_get_icon_name (gtk_entry, icon->pos);
117 atk_object_set_name (obj, name);
119 text = gtk_entry_get_icon_tooltip_text (gtk_entry, icon->pos);
122 atk_object_set_description (obj, text);
126 atk_object_set_parent (obj, ATK_OBJECT (icon->entry));
130 gtk_entry_icon_accessible_get_parent (AtkObject *accessible)
132 GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (accessible);
134 return ATK_OBJECT (icon->entry);
138 gtk_entry_icon_accessible_ref_state_set (AtkObject *accessible)
140 GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (accessible);
141 AtkStateSet *set = atk_state_set_new ();
142 AtkStateSet *entry_set;
148 atk_state_set_add_state (set, ATK_STATE_DEFUNCT);
152 entry_set = atk_object_ref_state_set (ATK_OBJECT (icon->entry));
153 if (!entry_set || atk_state_set_contains_state (entry_set, ATK_STATE_DEFUNCT))
155 atk_state_set_add_state (set, ATK_STATE_DEFUNCT);
156 g_clear_object (&entry_set);
160 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
161 gtk_entry = GTK_ENTRY (widget);
163 if (atk_state_set_contains_state (entry_set, ATK_STATE_ENABLED))
164 atk_state_set_add_state (set, ATK_STATE_ENABLED);
165 if (atk_state_set_contains_state (entry_set, ATK_STATE_SENSITIVE))
166 atk_state_set_add_state (set, ATK_STATE_SENSITIVE);
167 if (atk_state_set_contains_state (entry_set, ATK_STATE_SHOWING))
168 atk_state_set_add_state (set, ATK_STATE_SHOWING);
169 if (atk_state_set_contains_state (entry_set, ATK_STATE_VISIBLE))
170 atk_state_set_add_state (set, ATK_STATE_VISIBLE);
172 if (!gtk_entry_get_icon_sensitive (gtk_entry, icon->pos))
173 atk_state_set_remove_state (set, ATK_STATE_SENSITIVE);
174 if (!gtk_entry_get_icon_activatable (gtk_entry, icon->pos))
175 atk_state_set_remove_state (set, ATK_STATE_ENABLED);
177 g_object_unref (entry_set);
182 gtk_entry_icon_accessible_invalidate (GtkEntryIconAccessible *icon)
186 g_object_weak_unref (G_OBJECT (icon->entry),
187 gtk_entry_icon_accessible_remove_entry,
189 gtk_entry_icon_accessible_remove_entry (icon, NULL);
193 gtk_entry_icon_accessible_finalize (GObject *object)
195 GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (object);
197 gtk_entry_icon_accessible_invalidate (icon);
199 G_OBJECT_CLASS (_gtk_entry_icon_accessible_parent_class)->finalize (object);
203 _gtk_entry_icon_accessible_class_init (GtkEntryIconAccessibleClass *klass)
205 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
206 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
208 atk_class->initialize = gtk_entry_icon_accessible_initialize;
209 atk_class->get_parent = gtk_entry_icon_accessible_get_parent;
210 atk_class->ref_state_set = gtk_entry_icon_accessible_ref_state_set;
212 gobject_class->finalize = gtk_entry_icon_accessible_finalize;
216 gtk_entry_icon_accessible_do_action (AtkAction *action,
219 GtkEntryIconAccessible *icon = (GtkEntryIconAccessible *)action;
223 GdkRectangle icon_area;
225 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
232 if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_visible (widget))
235 gtk_entry = GTK_ENTRY (widget);
237 if (!gtk_entry_get_icon_sensitive (gtk_entry, icon->pos) ||
238 !gtk_entry_get_icon_activatable (gtk_entry, icon->pos))
241 gtk_entry_get_icon_area (gtk_entry, icon->pos, &icon_area);
242 memset (&event, 0, sizeof (event));
243 event.button.type = GDK_BUTTON_PRESS;
244 event.button.window = gtk_widget_get_window (widget);
245 event.button.button = 1;
246 event.button.send_event = TRUE;
247 event.button.time = GDK_CURRENT_TIME;
248 event.button.x = icon_area.x;
249 event.button.y = icon_area.y;
251 g_signal_emit_by_name (widget, "icon-press", 0, icon->pos, &event);
256 gtk_entry_icon_accessible_get_n_actions (AtkAction *action)
258 GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (action);
259 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
260 GtkEntry *gtk_entry = GTK_ENTRY (widget);
262 return (gtk_entry_get_icon_activatable (gtk_entry, icon->pos) ? 1 : 0);
266 gtk_entry_icon_accessible_get_name (AtkAction *action,
269 GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (action);
270 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
271 GtkEntry *gtk_entry = GTK_ENTRY (widget);
275 if (!gtk_entry_get_icon_activatable (gtk_entry, icon->pos))
282 icon_atk_action_interface_init (AtkActionIface *iface)
284 iface->do_action = gtk_entry_icon_accessible_do_action;
285 iface->get_n_actions = gtk_entry_icon_accessible_get_n_actions;
286 iface->get_name = gtk_entry_icon_accessible_get_name;
290 gtk_entry_icon_accessible_get_extents (AtkComponent *component,
295 AtkCoordType coord_type)
297 GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (component);
298 GdkRectangle icon_area;
303 atk_component_get_extents (ATK_COMPONENT (icon->entry), x, y, width, height,
308 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
309 gtk_entry = GTK_ENTRY (widget);
310 gtk_entry_get_icon_area (gtk_entry, icon->pos, &icon_area);
311 *width = icon_area.width;
312 *height = icon_area.height;
318 gtk_entry_icon_accessible_get_position (AtkComponent *component,
321 AtkCoordType coord_type)
323 GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (component);
324 GdkRectangle icon_area;
329 atk_component_get_position (ATK_COMPONENT (icon->entry), x, y, coord_type);
333 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
334 gtk_entry = GTK_ENTRY (widget);
335 gtk_entry_get_icon_area (gtk_entry, icon->pos, &icon_area);
341 gtk_entry_icon_accessible_get_size (AtkComponent *component,
345 GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (component);
346 GdkRectangle icon_area;
350 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
351 gtk_entry = GTK_ENTRY (widget);
352 gtk_entry_get_icon_area (gtk_entry, icon->pos, &icon_area);
353 *width = icon_area.width;
354 *height = icon_area.height;
358 icon_atk_component_interface_init (AtkComponentIface *iface)
360 iface->get_extents = gtk_entry_icon_accessible_get_extents;
361 iface->get_size = gtk_entry_icon_accessible_get_size;
362 iface->get_position = gtk_entry_icon_accessible_get_position;
367 static void insert_text_cb (GtkEditable *editable,
369 gint new_text_length,
371 static void delete_text_cb (GtkEditable *editable,
375 static gboolean check_for_selection_change (GtkEntryAccessible *entry,
376 GtkEntry *gtk_entry);
379 static void atk_editable_text_interface_init (AtkEditableTextIface *iface);
380 static void atk_text_interface_init (AtkTextIface *iface);
381 static void atk_action_interface_init (AtkActionIface *iface);
384 G_DEFINE_TYPE_WITH_CODE (GtkEntryAccessible, _gtk_entry_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
385 G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT, atk_editable_text_interface_init)
386 G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
387 G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
391 gtk_entry_accessible_ref_state_set (AtkObject *accessible)
393 AtkStateSet *state_set;
397 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
401 state_set = ATK_OBJECT_CLASS (_gtk_entry_accessible_parent_class)->ref_state_set (accessible);
403 g_object_get (G_OBJECT (widget), "editable", &value, NULL);
405 atk_state_set_add_state (state_set, ATK_STATE_EDITABLE);
406 atk_state_set_add_state (state_set, ATK_STATE_SINGLE_LINE);
411 static AtkAttributeSet *
412 gtk_entry_accessible_get_attributes (AtkObject *accessible)
415 AtkAttributeSet *attributes;
416 AtkAttribute *placeholder_text;
419 attributes = ATK_OBJECT_CLASS (_gtk_entry_accessible_parent_class)->get_attributes (accessible);
421 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
425 text = gtk_entry_get_placeholder_text (GTK_ENTRY (widget));
429 placeholder_text = g_malloc (sizeof (AtkAttribute));
430 placeholder_text->name = g_strdup ("placeholder-text");
431 placeholder_text->value = g_strdup (text);
433 attributes = g_slist_append (attributes, placeholder_text);
439 gtk_entry_accessible_initialize (AtkObject *obj,
443 GtkEntryAccessible *gtk_entry_accessible;
444 gint start_pos, end_pos;
446 ATK_OBJECT_CLASS (_gtk_entry_accessible_parent_class)->initialize (obj, data);
448 gtk_entry_accessible = GTK_ENTRY_ACCESSIBLE (obj);
450 entry = GTK_ENTRY (data);
451 gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos);
452 gtk_entry_accessible->priv->cursor_position = end_pos;
453 gtk_entry_accessible->priv->selection_bound = start_pos;
455 /* Set up signal callbacks */
456 g_signal_connect (entry, "insert-text", G_CALLBACK (insert_text_cb), NULL);
457 g_signal_connect (entry, "delete-text", G_CALLBACK (delete_text_cb), NULL);
459 if (gtk_entry_get_visibility (entry))
460 obj->role = ATK_ROLE_TEXT;
462 obj->role = ATK_ROLE_PASSWORD_TEXT;
466 gtk_entry_accessible_notify_gtk (GObject *obj,
472 GtkEntryAccessible* entry;
473 GtkEntryAccessiblePrivate *priv;
475 widget = GTK_WIDGET (obj);
476 atk_obj = gtk_widget_get_accessible (widget);
477 gtk_entry = GTK_ENTRY (widget);
478 entry = GTK_ENTRY_ACCESSIBLE (atk_obj);
481 if (g_strcmp0 (pspec->name, "cursor-position") == 0)
483 if (check_for_selection_change (entry, gtk_entry))
484 g_signal_emit_by_name (atk_obj, "text-selection-changed");
486 * The entry cursor position has moved so generate the signal.
488 g_signal_emit_by_name (atk_obj, "text-caret-moved",
489 entry->priv->cursor_position);
491 else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
493 if (check_for_selection_change (entry, gtk_entry))
494 g_signal_emit_by_name (atk_obj, "text-selection-changed");
496 else if (g_strcmp0 (pspec->name, "editable") == 0)
500 g_object_get (obj, "editable", &value, NULL);
501 atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, value);
503 else if (g_strcmp0 (pspec->name, "visibility") == 0)
508 visibility = gtk_entry_get_visibility (gtk_entry);
509 new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
510 atk_object_set_role (atk_obj, new_role);
512 else if (g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0)
514 if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_PRIMARY])
516 priv->icons[GTK_ENTRY_ICON_PRIMARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_PRIMARY);
517 g_signal_emit_by_name (entry, "children-changed::add", 0,
518 priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
520 else if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_PRIMARY])
522 gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_PRIMARY]));
523 g_signal_emit_by_name (entry, "children-changed::remove", 0,
524 priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
525 g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]);
528 else if (g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0)
530 gint index = (priv->icons[GTK_ENTRY_ICON_PRIMARY] ? 1 : 0);
531 if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_SECONDARY])
533 priv->icons[GTK_ENTRY_ICON_SECONDARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_SECONDARY);
534 g_signal_emit_by_name (entry, "children-changed::add", index,
535 priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
537 else if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_SECONDARY])
539 gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_SECONDARY]));
540 g_signal_emit_by_name (entry, "children-changed::remove", index,
541 priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
542 g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]);
545 else if (g_strcmp0 (pspec->name, "primary-icon-name") == 0)
547 if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
550 name = gtk_entry_get_icon_name (gtk_entry,
551 GTK_ENTRY_ICON_PRIMARY);
552 atk_object_set_name (priv->icons[GTK_ENTRY_ICON_PRIMARY], name);
555 else if (g_strcmp0 (pspec->name, "secondary-icon-name") == 0)
557 if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
560 name = gtk_entry_get_icon_name (gtk_entry,
561 GTK_ENTRY_ICON_SECONDARY);
562 atk_object_set_name (priv->icons[GTK_ENTRY_ICON_SECONDARY], name);
565 else if (g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0)
567 if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
570 text = gtk_entry_get_icon_tooltip_text (gtk_entry,
571 GTK_ENTRY_ICON_PRIMARY);
572 atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY],
577 else if (g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0)
579 if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
582 text = gtk_entry_get_icon_tooltip_text (gtk_entry,
583 GTK_ENTRY_ICON_SECONDARY);
584 atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY],
589 else if (g_strcmp0 (pspec->name, "primary-icon-activatable") == 0)
591 if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
593 gboolean on = gtk_entry_get_icon_activatable (gtk_entry, GTK_ENTRY_ICON_PRIMARY);
594 atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
595 ATK_STATE_ENABLED, on);
598 else if (g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0)
600 if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
602 gboolean on = gtk_entry_get_icon_activatable (gtk_entry, GTK_ENTRY_ICON_SECONDARY);
603 atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
604 ATK_STATE_ENABLED, on);
607 else if (g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0)
609 if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
611 gboolean on = gtk_entry_get_icon_sensitive (gtk_entry, GTK_ENTRY_ICON_PRIMARY);
612 atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
613 ATK_STATE_SENSITIVE, on);
616 else if (g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0)
618 if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
620 gboolean on = gtk_entry_get_icon_sensitive (gtk_entry, GTK_ENTRY_ICON_SECONDARY);
621 atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
622 ATK_STATE_SENSITIVE, on);
626 GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_entry_accessible_parent_class)->notify_gtk (obj, pspec);
630 gtk_entry_accessible_get_index_in_parent (AtkObject *accessible)
633 * If the parent widget is a combo box then the index is 1
634 * otherwise do the normal thing.
636 if (accessible->accessible_parent)
637 if (GTK_IS_COMBO_BOX_ACCESSIBLE (accessible->accessible_parent))
640 return ATK_OBJECT_CLASS (_gtk_entry_accessible_parent_class)->get_index_in_parent (accessible);
644 gtk_entry_accessible_get_n_children (AtkObject* obj)
650 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
654 entry = GTK_ENTRY (widget);
656 if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
658 if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
664 gtk_entry_accessible_ref_child (AtkObject *obj,
667 GtkEntryAccessible *accessible = GTK_ENTRY_ACCESSIBLE (obj);
668 GtkEntryAccessiblePrivate *priv = accessible->priv;
671 GtkEntryIconPosition pos;
673 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
677 entry = GTK_ENTRY (widget);
682 if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
683 pos = GTK_ENTRY_ICON_PRIMARY;
684 else if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
685 pos = GTK_ENTRY_ICON_SECONDARY;
690 if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY)
692 if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY)
694 pos = GTK_ENTRY_ICON_SECONDARY;
700 if (!priv->icons[pos])
701 priv->icons[pos] = gtk_entry_icon_accessible_new (accessible, pos);
702 return g_object_ref (priv->icons[pos]);
706 gtk_entry_accessible_finalize (GObject *object)
708 GtkEntryAccessible *entry = GTK_ENTRY_ACCESSIBLE (object);
709 GtkEntryAccessiblePrivate *priv = entry->priv;
711 g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]);
712 g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]);
714 G_OBJECT_CLASS (_gtk_entry_accessible_parent_class)->finalize (object);
718 _gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass)
720 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
721 GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
722 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
724 class->ref_state_set = gtk_entry_accessible_ref_state_set;
725 class->get_index_in_parent = gtk_entry_accessible_get_index_in_parent;
726 class->initialize = gtk_entry_accessible_initialize;
727 class->get_attributes = gtk_entry_accessible_get_attributes;
728 class->get_n_children = gtk_entry_accessible_get_n_children;
729 class->ref_child = gtk_entry_accessible_ref_child;
731 widget_class->notify_gtk = gtk_entry_accessible_notify_gtk;
733 gobject_class->finalize = gtk_entry_accessible_finalize;
735 g_type_class_add_private (klass, sizeof (GtkEntryAccessiblePrivate));
739 _gtk_entry_accessible_init (GtkEntryAccessible *entry)
741 entry->priv = G_TYPE_INSTANCE_GET_PRIVATE (entry,
742 GTK_TYPE_ENTRY_ACCESSIBLE,
743 GtkEntryAccessiblePrivate);
744 entry->priv->cursor_position = 0;
745 entry->priv->selection_bound = 0;
749 gtk_entry_accessible_get_text (AtkText *atk_text,
755 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
759 return _gtk_entry_get_display_text (GTK_ENTRY (widget), start_pos, end_pos);
763 gtk_entry_accessible_get_text_before_offset (AtkText *text,
765 AtkTextBoundary boundary_type,
771 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
775 return _gtk_pango_get_text_before (gtk_entry_get_layout (GTK_ENTRY (widget)),
776 boundary_type, offset,
777 start_offset, end_offset);
781 gtk_entry_accessible_get_text_at_offset (AtkText *text,
783 AtkTextBoundary boundary_type,
789 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
793 return _gtk_pango_get_text_at (gtk_entry_get_layout (GTK_ENTRY (widget)),
794 boundary_type, offset,
795 start_offset, end_offset);
799 gtk_entry_accessible_get_text_after_offset (AtkText *text,
801 AtkTextBoundary boundary_type,
807 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
811 return _gtk_pango_get_text_after (gtk_entry_get_layout (GTK_ENTRY (widget)),
812 boundary_type, offset,
813 start_offset, end_offset);
817 gtk_entry_accessible_get_character_count (AtkText *atk_text)
823 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
827 text = _gtk_entry_get_display_text (GTK_ENTRY (widget), 0, -1);
832 char_count = g_utf8_strlen (text, -1);
840 gtk_entry_accessible_get_caret_offset (AtkText *text)
844 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
848 return gtk_editable_get_position (GTK_EDITABLE (widget));
852 gtk_entry_accessible_set_caret_offset (AtkText *text,
857 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
861 gtk_editable_set_position (GTK_EDITABLE (widget), offset);
866 static AtkAttributeSet *
867 add_text_attribute (AtkAttributeSet *attributes,
868 AtkTextAttribute attr,
873 at = g_new (AtkAttribute, 1);
874 at->name = g_strdup (atk_text_attribute_get_name (attr));
875 at->value = g_strdup (atk_text_attribute_get_value (attr, i));
877 return g_slist_prepend (attributes, at);
880 static AtkAttributeSet *
881 gtk_entry_accessible_get_run_attributes (AtkText *text,
887 AtkAttributeSet *attributes;
889 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
894 attributes = add_text_attribute (attributes, ATK_TEXT_ATTR_DIRECTION,
895 gtk_widget_get_direction (widget));
896 attributes = _gtk_pango_get_run_attributes (attributes,
897 gtk_entry_get_layout (GTK_ENTRY (widget)),
905 static AtkAttributeSet *
906 gtk_entry_accessible_get_default_attributes (AtkText *text)
909 AtkAttributeSet *attributes;
911 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
916 attributes = add_text_attribute (attributes, ATK_TEXT_ATTR_DIRECTION,
917 gtk_widget_get_direction (widget));
918 attributes = _gtk_pango_get_default_attributes (attributes,
919 gtk_entry_get_layout (GTK_ENTRY (widget)));
920 attributes = _gtk_style_context_get_attributes (attributes,
921 gtk_widget_get_style_context (widget),
922 gtk_widget_get_state_flags (widget));
928 gtk_entry_accessible_get_character_extents (AtkText *text,
938 PangoRectangle char_rect;
940 gint index, x_layout, y_layout;
942 gint x_window, y_window;
944 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
948 entry = GTK_ENTRY (widget);
950 gtk_entry_get_layout_offsets (entry, &x_layout, &y_layout);
951 entry_text = _gtk_entry_get_display_text (entry, 0, -1);
952 index = g_utf8_offset_to_pointer (entry_text, offset) - entry_text;
955 pango_layout_index_to_pos (gtk_entry_get_layout (entry), index, &char_rect);
956 pango_extents_to_pixels (&char_rect, NULL);
958 window = gtk_widget_get_window (widget);
959 gdk_window_get_origin (window, &x_window, &y_window);
961 *x = x_window + x_layout + char_rect.x;
962 *y = y_window + y_layout + char_rect.y;
963 *width = char_rect.width;
964 *height = char_rect.height;
966 if (coords == ATK_XY_WINDOW)
968 window = gdk_window_get_toplevel (window);
969 gdk_window_get_origin (window, &x_window, &y_window);
977 gtk_entry_accessible_get_offset_at_point (AtkText *atk_text,
985 gint index, x_layout, y_layout;
986 gint x_window, y_window;
987 gint x_local, y_local;
991 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
995 entry = GTK_ENTRY (widget);
997 gtk_entry_get_layout_offsets (entry, &x_layout, &y_layout);
999 window = gtk_widget_get_window (widget);
1000 gdk_window_get_origin (window, &x_window, &y_window);
1002 x_local = x - x_layout - x_window;
1003 y_local = y - y_layout - y_window;
1005 if (coords == ATK_XY_WINDOW)
1007 window = gdk_window_get_toplevel (window);
1008 gdk_window_get_origin (window, &x_window, &y_window);
1010 x_local += x_window;
1011 y_local += y_window;
1013 if (!pango_layout_xy_to_index (gtk_entry_get_layout (entry),
1014 x_local * PANGO_SCALE,
1015 y_local * PANGO_SCALE,
1018 if (x_local < 0 || y_local < 0)
1027 text = _gtk_entry_get_display_text (entry, 0, -1);
1028 offset = g_utf8_pointer_to_offset (text, text + index);
1036 gtk_entry_accessible_get_n_selections (AtkText *text)
1041 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1045 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (widget), &start, &end))
1052 gtk_entry_accessible_get_selection (AtkText *text,
1059 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1063 if (selection_num != 0)
1066 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (widget), start_pos, end_pos))
1067 return gtk_editable_get_chars (GTK_EDITABLE (widget), *start_pos, *end_pos);
1073 gtk_entry_accessible_add_selection (AtkText *text,
1081 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1085 entry = GTK_ENTRY (widget);
1087 if (!gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
1089 gtk_editable_select_region (GTK_EDITABLE (entry), start_pos, end_pos);
1097 gtk_entry_accessible_remove_selection (AtkText *text,
1103 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1107 if (selection_num != 0)
1110 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (widget), &start, &end))
1112 gtk_editable_select_region (GTK_EDITABLE (widget), end, end);
1120 gtk_entry_accessible_set_selection (AtkText *text,
1128 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1132 if (selection_num != 0)
1135 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (widget), &start, &end))
1137 gtk_editable_select_region (GTK_EDITABLE (widget), start_pos, end_pos);
1145 gtk_entry_accessible_get_character_at_offset (AtkText *atk_text,
1155 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
1159 if (!gtk_entry_get_visibility (GTK_ENTRY (widget)))
1162 text = _gtk_entry_get_display_text (GTK_ENTRY (widget), 0, -1);
1163 if (offset < g_utf8_strlen (text, -1))
1165 index = g_utf8_offset_to_pointer (text, offset);
1166 result = g_utf8_get_char (index);
1174 atk_text_interface_init (AtkTextIface *iface)
1176 iface->get_text = gtk_entry_accessible_get_text;
1177 iface->get_character_at_offset = gtk_entry_accessible_get_character_at_offset;
1178 iface->get_text_before_offset = gtk_entry_accessible_get_text_before_offset;
1179 iface->get_text_at_offset = gtk_entry_accessible_get_text_at_offset;
1180 iface->get_text_after_offset = gtk_entry_accessible_get_text_after_offset;
1181 iface->get_caret_offset = gtk_entry_accessible_get_caret_offset;
1182 iface->set_caret_offset = gtk_entry_accessible_set_caret_offset;
1183 iface->get_character_count = gtk_entry_accessible_get_character_count;
1184 iface->get_n_selections = gtk_entry_accessible_get_n_selections;
1185 iface->get_selection = gtk_entry_accessible_get_selection;
1186 iface->add_selection = gtk_entry_accessible_add_selection;
1187 iface->remove_selection = gtk_entry_accessible_remove_selection;
1188 iface->set_selection = gtk_entry_accessible_set_selection;
1189 iface->get_run_attributes = gtk_entry_accessible_get_run_attributes;
1190 iface->get_default_attributes = gtk_entry_accessible_get_default_attributes;
1191 iface->get_character_extents = gtk_entry_accessible_get_character_extents;
1192 iface->get_offset_at_point = gtk_entry_accessible_get_offset_at_point;
1196 gtk_entry_accessible_set_text_contents (AtkEditableText *text,
1197 const gchar *string)
1201 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1205 if (!gtk_editable_get_editable (GTK_EDITABLE (widget)))
1208 gtk_entry_set_text (GTK_ENTRY (widget), string);
1212 gtk_entry_accessible_insert_text (AtkEditableText *text,
1213 const gchar *string,
1218 GtkEditable *editable;
1220 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1224 editable = GTK_EDITABLE (widget);
1225 if (!gtk_editable_get_editable (editable))
1228 gtk_editable_insert_text (editable, string, length, position);
1229 gtk_editable_set_position (editable, *position);
1233 gtk_entry_accessible_copy_text (AtkEditableText *text,
1238 GtkEditable *editable;
1240 GtkClipboard *clipboard;
1242 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1246 if (!gtk_widget_has_screen (widget))
1249 editable = GTK_EDITABLE (widget);
1250 str = gtk_editable_get_chars (editable, start_pos, end_pos);
1251 clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
1252 gtk_clipboard_set_text (clipboard, str, -1);
1257 gtk_entry_accessible_cut_text (AtkEditableText *text,
1262 GtkEditable *editable;
1264 GtkClipboard *clipboard;
1266 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1270 if (!gtk_widget_has_screen (widget))
1273 editable = GTK_EDITABLE (widget);
1274 if (!gtk_editable_get_editable (editable))
1277 str = gtk_editable_get_chars (editable, start_pos, end_pos);
1278 clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
1279 gtk_clipboard_set_text (clipboard, str, -1);
1280 gtk_editable_delete_text (editable, start_pos, end_pos);
1284 gtk_entry_accessible_delete_text (AtkEditableText *text,
1289 GtkEditable *editable;
1291 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1295 editable = GTK_EDITABLE (widget);
1296 if (!gtk_editable_get_editable (editable))
1299 gtk_editable_delete_text (editable, start_pos, end_pos);
1309 paste_received_cb (GtkClipboard *clipboard,
1313 PasteData *paste = data;
1316 gtk_editable_insert_text (GTK_EDITABLE (paste->entry), text, -1,
1319 g_object_unref (paste->entry);
1324 gtk_entry_accessible_paste_text (AtkEditableText *text,
1328 GtkEditable *editable;
1330 GtkClipboard *clipboard;
1332 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
1336 if (!gtk_widget_has_screen (widget))
1339 editable = GTK_EDITABLE (widget);
1340 if (!gtk_editable_get_editable (editable))
1343 paste = g_new0 (PasteData, 1);
1344 paste->entry = GTK_ENTRY (widget);
1345 paste->position = position;
1347 g_object_ref (paste->entry);
1348 clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
1349 gtk_clipboard_request_text (clipboard, paste_received_cb, paste);
1353 atk_editable_text_interface_init (AtkEditableTextIface *iface)
1355 iface->set_text_contents = gtk_entry_accessible_set_text_contents;
1356 iface->insert_text = gtk_entry_accessible_insert_text;
1357 iface->copy_text = gtk_entry_accessible_copy_text;
1358 iface->cut_text = gtk_entry_accessible_cut_text;
1359 iface->delete_text = gtk_entry_accessible_delete_text;
1360 iface->paste_text = gtk_entry_accessible_paste_text;
1361 iface->set_run_attributes = NULL;
1364 /* We connect to GtkEditable::insert-text, since it carries
1365 * the information we need. But we delay emitting our own
1366 * text_changed::insert signal until the entry has update
1367 * all its internal state and emits GtkEntry::changed.
1370 insert_text_cb (GtkEditable *editable,
1372 gint new_text_length,
1375 GtkEntryAccessible *accessible;
1377 if (new_text_length == 0)
1380 accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
1382 g_signal_emit_by_name (accessible,
1383 "text-changed::insert",
1385 g_utf8_strlen (new_text, new_text_length));
1388 /* We connect to GtkEditable::delete-text, since it carries
1389 * the information we need. But we delay emitting our own
1390 * text_changed::delete signal until the entry has update
1391 * all its internal state and emits GtkEntry::changed.
1394 delete_text_cb (GtkEditable *editable,
1398 GtkEntryAccessible *accessible;
1400 accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
1406 text = _gtk_entry_get_display_text (GTK_ENTRY (editable), 0, -1);
1407 end = g_utf8_strlen (text, -1);
1414 g_signal_emit_by_name (accessible,
1415 "text-changed::delete",
1421 check_for_selection_change (GtkEntryAccessible *accessible,
1424 gboolean ret_val = FALSE;
1427 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
1429 if (end != accessible->priv->cursor_position ||
1430 start != accessible->priv->selection_bound)
1432 * This check is here as this function can be called
1433 * for notification of selection_bound and current_pos.
1434 * The values of current_pos and selection_bound may be the same
1435 * for both notifications and we only want to generate one
1436 * text_selection_changed signal.
1442 /* We had a selection */
1443 ret_val = (accessible->priv->cursor_position != accessible->priv->selection_bound);
1446 accessible->priv->cursor_position = end;
1447 accessible->priv->selection_bound = start;
1453 gtk_entry_accessible_do_action (AtkAction *action,
1458 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
1462 if (!gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
1468 gtk_widget_activate (widget);
1474 gtk_entry_accessible_get_n_actions (AtkAction *action)
1479 static const gchar *
1480 gtk_entry_accessible_get_keybinding (AtkAction *action,
1485 AtkRelationSet *set;
1486 AtkRelation *relation;
1488 gpointer target_object;
1494 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
1498 set = atk_object_ref_relation_set (ATK_OBJECT (action));
1503 relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
1506 target = atk_relation_get_target (relation);
1508 target_object = g_ptr_array_index (target, 0);
1509 label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object));
1512 g_object_unref (set);
1514 if (GTK_IS_LABEL (label))
1516 key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
1517 if (key_val != GDK_KEY_VoidSymbol)
1518 return gtk_accelerator_name (key_val, GDK_MOD1_MASK);
1525 gtk_entry_accessible_action_get_name (AtkAction *action,
1535 atk_action_interface_init (AtkActionIface *iface)
1537 iface->do_action = gtk_entry_accessible_do_action;
1538 iface->get_n_actions = gtk_entry_accessible_get_n_actions;
1539 iface->get_keybinding = gtk_entry_accessible_get_keybinding;
1540 iface->get_name = gtk_entry_accessible_action_get_name;