-/* GAIL - The GNOME Accessibility Implementation Library
+/* GTK+ - accessibility implementations
* Copyright 2001, 2002, 2003 Sun Microsystems Inc.
*
* This library is free software; you can redistribute it and/or
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
+#include <string.h>
#include <gtk/gtk.h>
#include "gtkpango.h"
#include "gtkentryaccessible.h"
+#include "gtkentryprivate.h"
#include "gtkcomboboxaccessible.h"
+#define GTK_TYPE_ENTRY_ICON_ACCESSIBLE (gtk_entry_icon_accessible_get_type ())
+#define GTK_ENTRY_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ENTRY_ICON_ACCESSIBLE, GtkEntryIconAccessible))
+#define GTK_IS_ENTRY_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ENTRY_ICON_ACCESSIBLE))
+
+struct _GtkEntryAccessiblePrivate
+{
+ gint cursor_position;
+ gint selection_bound;
+ AtkObject *icons[2];
+};
+
+typedef struct _GtkEntryIconAccessible GtkEntryIconAccessible;
+typedef struct _GtkEntryIconAccessibleClass GtkEntryIconAccessibleClass;
+
+struct _GtkEntryIconAccessible
+{
+ AtkObject parent;
+
+ GtkEntryAccessible *entry;
+ GtkEntryIconPosition pos;
+};
+
+struct _GtkEntryIconAccessibleClass
+{
+ AtkObjectClass parent_class;
+};
+
+static void atk_action_interface_init (AtkActionIface *iface);
+
+static void icon_atk_action_interface_init (AtkActionIface *iface);
+static void icon_atk_component_interface_init (AtkComponentIface *iface);
+
+GType gtk_entry_icon_accessible_get_type (void);
+
+G_DEFINE_TYPE_WITH_CODE (GtkEntryIconAccessible, gtk_entry_icon_accessible, ATK_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, icon_atk_action_interface_init)
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, icon_atk_component_interface_init))
+
+static void
+gtk_entry_icon_accessible_remove_entry (gpointer data, GObject *obj)
+{
+ GtkEntryIconAccessible *icon = data;
+
+ if (icon->entry)
+ {
+ icon->entry = NULL;
+ g_object_notify (G_OBJECT (icon), "accessible-parent");
+ atk_object_notify_state_change (ATK_OBJECT (icon), ATK_STATE_DEFUNCT, TRUE);
+ }
+}
+
+static AtkObject *
+gtk_entry_icon_accessible_new (GtkEntryAccessible *entry,
+ GtkEntryIconPosition pos)
+{
+ GtkEntryIconAccessible *icon;
+ AtkObject *accessible;
+
+ icon = g_object_new (gtk_entry_icon_accessible_get_type (), NULL);
+ icon->entry = entry;
+ g_object_weak_ref (G_OBJECT (entry),
+ gtk_entry_icon_accessible_remove_entry,
+ icon);
+ icon->pos = pos;
+
+ accessible = ATK_OBJECT (icon);
+ atk_object_initialize (accessible, NULL);
+ return accessible;
+}
+
+static void
+gtk_entry_icon_accessible_init (GtkEntryIconAccessible *icon)
+{
+}
+
+static void
+gtk_entry_icon_accessible_initialize (AtkObject *obj,
+ gpointer data)
+{
+ GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (obj);
+ GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
+ GtkEntry *gtk_entry = GTK_ENTRY (widget);
+ const gchar *name;
+ gchar *text;
+
+ ATK_OBJECT_CLASS (gtk_entry_icon_accessible_parent_class)->initialize (obj, data);
+ atk_object_set_role (obj, ATK_ROLE_ICON);
+
+ name = gtk_entry_get_icon_name (gtk_entry, icon->pos);
+ if (name)
+ atk_object_set_name (obj, name);
+
+ text = gtk_entry_get_icon_tooltip_text (gtk_entry, icon->pos);
+ if (text)
+ {
+ atk_object_set_description (obj, text);
+ g_free (text);
+ }
+
+ atk_object_set_parent (obj, ATK_OBJECT (icon->entry));
+}
+
+static AtkObject *
+gtk_entry_icon_accessible_get_parent (AtkObject *accessible)
+{
+ GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (accessible);
+
+ return ATK_OBJECT (icon->entry);
+}
+
+static AtkStateSet *
+gtk_entry_icon_accessible_ref_state_set (AtkObject *accessible)
+{
+ GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (accessible);
+ AtkStateSet *set = atk_state_set_new ();
+ AtkStateSet *entry_set;
+ GtkWidget *widget;
+ GtkEntry *gtk_entry;
+
+ if (!icon->entry)
+ {
+ atk_state_set_add_state (set, ATK_STATE_DEFUNCT);
+ return set;
+ }
+
+ entry_set = atk_object_ref_state_set (ATK_OBJECT (icon->entry));
+ if (!entry_set || atk_state_set_contains_state (entry_set, ATK_STATE_DEFUNCT))
+ {
+ atk_state_set_add_state (set, ATK_STATE_DEFUNCT);
+ g_clear_object (&entry_set);
+ return set;
+ }
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
+ gtk_entry = GTK_ENTRY (widget);
+
+ if (atk_state_set_contains_state (entry_set, ATK_STATE_ENABLED))
+ atk_state_set_add_state (set, ATK_STATE_ENABLED);
+ if (atk_state_set_contains_state (entry_set, ATK_STATE_SENSITIVE))
+ atk_state_set_add_state (set, ATK_STATE_SENSITIVE);
+ if (atk_state_set_contains_state (entry_set, ATK_STATE_SHOWING))
+ atk_state_set_add_state (set, ATK_STATE_SHOWING);
+ if (atk_state_set_contains_state (entry_set, ATK_STATE_VISIBLE))
+ atk_state_set_add_state (set, ATK_STATE_VISIBLE);
+
+ if (!gtk_entry_get_icon_sensitive (gtk_entry, icon->pos))
+ atk_state_set_remove_state (set, ATK_STATE_SENSITIVE);
+ if (!gtk_entry_get_icon_activatable (gtk_entry, icon->pos))
+ atk_state_set_remove_state (set, ATK_STATE_ENABLED);
+
+ g_object_unref (entry_set);
+ return set;
+}
+
+static void
+gtk_entry_icon_accessible_invalidate (GtkEntryIconAccessible *icon)
+{
+ if (!icon->entry)
+ return;
+ g_object_weak_unref (G_OBJECT (icon->entry),
+ gtk_entry_icon_accessible_remove_entry,
+ icon);
+ gtk_entry_icon_accessible_remove_entry (icon, NULL);
+}
+
+static void
+gtk_entry_icon_accessible_finalize (GObject *object)
+{
+ GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (object);
+
+ gtk_entry_icon_accessible_invalidate (icon);
+
+ G_OBJECT_CLASS (gtk_entry_icon_accessible_parent_class)->finalize (object);
+}
+
+static void
+gtk_entry_icon_accessible_class_init (GtkEntryIconAccessibleClass *klass)
+{
+ AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ atk_class->initialize = gtk_entry_icon_accessible_initialize;
+ atk_class->get_parent = gtk_entry_icon_accessible_get_parent;
+ atk_class->ref_state_set = gtk_entry_icon_accessible_ref_state_set;
+
+ gobject_class->finalize = gtk_entry_icon_accessible_finalize;
+}
+
+static gboolean
+gtk_entry_icon_accessible_do_action (AtkAction *action,
+ gint i)
+{
+ GtkEntryIconAccessible *icon = (GtkEntryIconAccessible *)action;
+ GtkWidget *widget;
+ GtkEntry *gtk_entry;
+ GdkEvent event;
+ GdkRectangle icon_area;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
+ if (widget == NULL)
+ return FALSE;
+
+ if (i != 0)
+ return FALSE;
+
+ if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_visible (widget))
+ return FALSE;
+
+ gtk_entry = GTK_ENTRY (widget);
+
+ if (!gtk_entry_get_icon_sensitive (gtk_entry, icon->pos) ||
+ !gtk_entry_get_icon_activatable (gtk_entry, icon->pos))
+ return FALSE;
+
+ gtk_entry_get_icon_area (gtk_entry, icon->pos, &icon_area);
+ memset (&event, 0, sizeof (event));
+ event.button.type = GDK_BUTTON_PRESS;
+ event.button.window = gtk_widget_get_window (widget);
+ event.button.button = 1;
+ event.button.send_event = TRUE;
+ event.button.time = GDK_CURRENT_TIME;
+ event.button.x = icon_area.x;
+ event.button.y = icon_area.y;
+
+ g_signal_emit_by_name (widget, "icon-press", 0, icon->pos, &event);
+ return TRUE;
+}
+
+static gint
+gtk_entry_icon_accessible_get_n_actions (AtkAction *action)
+{
+ GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (action);
+ GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
+ GtkEntry *gtk_entry = GTK_ENTRY (widget);
+
+ return (gtk_entry_get_icon_activatable (gtk_entry, icon->pos) ? 1 : 0);
+}
+
+static const gchar *
+gtk_entry_icon_accessible_get_name (AtkAction *action,
+ gint i)
+{
+ GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (action);
+ GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
+ GtkEntry *gtk_entry = GTK_ENTRY (widget);
+
+ if (i != 0)
+ return NULL;
+ if (!gtk_entry_get_icon_activatable (gtk_entry, icon->pos))
+ return NULL;
+
+ return "activate";
+}
+
+static void
+icon_atk_action_interface_init (AtkActionIface *iface)
+{
+ iface->do_action = gtk_entry_icon_accessible_do_action;
+ iface->get_n_actions = gtk_entry_icon_accessible_get_n_actions;
+ iface->get_name = gtk_entry_icon_accessible_get_name;
+}
+
+static void
+gtk_entry_icon_accessible_get_extents (AtkComponent *component,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coord_type)
+{
+ GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (component);
+ GdkRectangle icon_area;
+ GtkEntry *gtk_entry;
+ GtkWidget *widget;
+
+ *x = G_MININT;
+ atk_component_get_extents (ATK_COMPONENT (icon->entry), x, y, width, height,
+ coord_type);
+ if (*x == G_MININT)
+ return;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
+ gtk_entry = GTK_ENTRY (widget);
+ gtk_entry_get_icon_area (gtk_entry, icon->pos, &icon_area);
+ *width = icon_area.width;
+ *height = icon_area.height;
+ *x += icon_area.x;
+ *y += icon_area.y;
+}
+
+static void
+gtk_entry_icon_accessible_get_position (AtkComponent *component,
+ gint *x,
+ gint *y,
+ AtkCoordType coord_type)
+{
+ GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (component);
+ GdkRectangle icon_area;
+ GtkEntry *gtk_entry;
+ GtkWidget *widget;
+
+ *x = G_MININT;
+ atk_component_get_position (ATK_COMPONENT (icon->entry), x, y, coord_type);
+ if (*x == G_MININT)
+ return;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
+ gtk_entry = GTK_ENTRY (widget);
+ gtk_entry_get_icon_area (gtk_entry, icon->pos, &icon_area);
+ *x += icon_area.x;
+ *y += icon_area.y;
+}
+
+static void
+gtk_entry_icon_accessible_get_size (AtkComponent *component,
+ gint *width,
+ gint *height)
+{
+ GtkEntryIconAccessible *icon = GTK_ENTRY_ICON_ACCESSIBLE (component);
+ GdkRectangle icon_area;
+ GtkEntry *gtk_entry;
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry));
+ gtk_entry = GTK_ENTRY (widget);
+ gtk_entry_get_icon_area (gtk_entry, icon->pos, &icon_area);
+ *width = icon_area.width;
+ *height = icon_area.height;
+}
+
+static void
+icon_atk_component_interface_init (AtkComponentIface *iface)
+{
+ iface->get_extents = gtk_entry_icon_accessible_get_extents;
+ iface->get_size = gtk_entry_icon_accessible_get_size;
+ iface->get_position = gtk_entry_icon_accessible_get_position;
+}
+
/* Callbacks */
static void insert_text_cb (GtkEditable *editable,
static void delete_text_cb (GtkEditable *editable,
gint start,
gint end);
-static void changed_cb (GtkEditable *editable);
static gboolean check_for_selection_change (GtkEntryAccessible *entry,
GtkEntry *gtk_entry);
static void atk_action_interface_init (AtkActionIface *iface);
-G_DEFINE_TYPE_WITH_CODE (GtkEntryAccessible, _gtk_entry_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
+G_DEFINE_TYPE_WITH_CODE (GtkEntryAccessible, gtk_entry_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT, atk_editable_text_interface_init)
G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
if (widget == NULL)
return NULL;
- state_set = ATK_OBJECT_CLASS (_gtk_entry_accessible_parent_class)->ref_state_set (accessible);
+ state_set = ATK_OBJECT_CLASS (gtk_entry_accessible_parent_class)->ref_state_set (accessible);
g_object_get (G_OBJECT (widget), "editable", &value, NULL);
if (value)
AtkAttribute *placeholder_text;
const gchar *text;
- attributes = ATK_OBJECT_CLASS (_gtk_entry_accessible_parent_class)->get_attributes (accessible);
+ attributes = ATK_OBJECT_CLASS (gtk_entry_accessible_parent_class)->get_attributes (accessible);
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
if (widget == NULL)
GtkEntryAccessible *gtk_entry_accessible;
gint start_pos, end_pos;
- ATK_OBJECT_CLASS (_gtk_entry_accessible_parent_class)->initialize (obj, data);
+ ATK_OBJECT_CLASS (gtk_entry_accessible_parent_class)->initialize (obj, data);
gtk_entry_accessible = GTK_ENTRY_ACCESSIBLE (obj);
entry = GTK_ENTRY (data);
- gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
- &start_pos, &end_pos);
- gtk_entry_accessible->cursor_position = end_pos;
- gtk_entry_accessible->selection_bound = start_pos;
+ gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos);
+ gtk_entry_accessible->priv->cursor_position = end_pos;
+ gtk_entry_accessible->priv->selection_bound = start_pos;
/* Set up signal callbacks */
g_signal_connect (entry, "insert-text", G_CALLBACK (insert_text_cb), NULL);
g_signal_connect (entry, "delete-text", G_CALLBACK (delete_text_cb), NULL);
- g_signal_connect (entry, "changed", G_CALLBACK (changed_cb), NULL);
if (gtk_entry_get_visibility (entry))
obj->role = ATK_ROLE_TEXT;
AtkObject* atk_obj;
GtkEntry* gtk_entry;
GtkEntryAccessible* entry;
+ GtkEntryAccessiblePrivate *priv;
widget = GTK_WIDGET (obj);
atk_obj = gtk_widget_get_accessible (widget);
gtk_entry = GTK_ENTRY (widget);
entry = GTK_ENTRY_ACCESSIBLE (atk_obj);
+ priv = entry->priv;
if (g_strcmp0 (pspec->name, "cursor-position") == 0)
{
* The entry cursor position has moved so generate the signal.
*/
g_signal_emit_by_name (atk_obj, "text-caret-moved",
- entry->cursor_position);
+ entry->priv->cursor_position);
}
else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
{
new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
atk_object_set_role (atk_obj, new_role);
}
+ else if (g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0)
+ {
+ if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_PRIMARY])
+ {
+ priv->icons[GTK_ENTRY_ICON_PRIMARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_PRIMARY);
+ g_signal_emit_by_name (entry, "children-changed::add", 0,
+ priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
+ }
+ else if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_PRIMARY])
+ {
+ gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_PRIMARY]));
+ g_signal_emit_by_name (entry, "children-changed::remove", 0,
+ priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
+ g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]);
+ }
+ }
+ else if (g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0)
+ {
+ gint index = (priv->icons[GTK_ENTRY_ICON_PRIMARY] ? 1 : 0);
+ if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_SECONDARY])
+ {
+ priv->icons[GTK_ENTRY_ICON_SECONDARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_SECONDARY);
+ g_signal_emit_by_name (entry, "children-changed::add", index,
+ priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
+ }
+ else if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_SECONDARY])
+ {
+ gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_SECONDARY]));
+ g_signal_emit_by_name (entry, "children-changed::remove", index,
+ priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
+ g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]);
+ }
+ }
+ else if (g_strcmp0 (pspec->name, "primary-icon-name") == 0)
+ {
+ if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
+ {
+ const gchar *name;
+ name = gtk_entry_get_icon_name (gtk_entry,
+ GTK_ENTRY_ICON_PRIMARY);
+ if (name)
+ atk_object_set_name (priv->icons[GTK_ENTRY_ICON_PRIMARY], name);
+ }
+ }
+ else if (g_strcmp0 (pspec->name, "secondary-icon-name") == 0)
+ {
+ if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
+ {
+ const gchar *name;
+ name = gtk_entry_get_icon_name (gtk_entry,
+ GTK_ENTRY_ICON_SECONDARY);
+ if (name)
+ atk_object_set_name (priv->icons[GTK_ENTRY_ICON_SECONDARY], name);
+ }
+ }
+ else if (g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0)
+ {
+ if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
+ {
+ gchar *text;
+ text = gtk_entry_get_icon_tooltip_text (gtk_entry,
+ GTK_ENTRY_ICON_PRIMARY);
+ atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY],
+ text);
+ g_free (text);
+ }
+ }
+ else if (g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0)
+ {
+ if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
+ {
+ gchar *text;
+ text = gtk_entry_get_icon_tooltip_text (gtk_entry,
+ GTK_ENTRY_ICON_SECONDARY);
+ atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY],
+ text);
+ g_free (text);
+ }
+ }
+ else if (g_strcmp0 (pspec->name, "primary-icon-activatable") == 0)
+ {
+ if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
+ {
+ gboolean on = gtk_entry_get_icon_activatable (gtk_entry, GTK_ENTRY_ICON_PRIMARY);
+ atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
+ ATK_STATE_ENABLED, on);
+ }
+ }
+ else if (g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0)
+ {
+ if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
+ {
+ gboolean on = gtk_entry_get_icon_activatable (gtk_entry, GTK_ENTRY_ICON_SECONDARY);
+ atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
+ ATK_STATE_ENABLED, on);
+ }
+ }
+ else if (g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0)
+ {
+ if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
+ {
+ gboolean on = gtk_entry_get_icon_sensitive (gtk_entry, GTK_ENTRY_ICON_PRIMARY);
+ atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
+ ATK_STATE_SENSITIVE, on);
+ }
+ }
+ else if (g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0)
+ {
+ if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
+ {
+ gboolean on = gtk_entry_get_icon_sensitive (gtk_entry, GTK_ENTRY_ICON_SECONDARY);
+ atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
+ ATK_STATE_SENSITIVE, on);
+ }
+ }
else
- GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_entry_accessible_parent_class)->notify_gtk (obj, pspec);
+ GTK_WIDGET_ACCESSIBLE_CLASS (gtk_entry_accessible_parent_class)->notify_gtk (obj, pspec);
}
static gint
if (GTK_IS_COMBO_BOX_ACCESSIBLE (accessible->accessible_parent))
return 1;
- return ATK_OBJECT_CLASS (_gtk_entry_accessible_parent_class)->get_index_in_parent (accessible);
+ return ATK_OBJECT_CLASS (gtk_entry_accessible_parent_class)->get_index_in_parent (accessible);
+}
+
+static gint
+gtk_entry_accessible_get_n_children (AtkObject* obj)
+{
+ GtkWidget *widget;
+ GtkEntry *entry;
+ gint count = 0;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
+ if (widget == NULL)
+ return 0;
+
+ entry = GTK_ENTRY (widget);
+
+ if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
+ count++;
+ if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
+ count++;
+ return count;
+}
+
+static AtkObject *
+gtk_entry_accessible_ref_child (AtkObject *obj,
+ gint i)
+{
+ GtkEntryAccessible *accessible = GTK_ENTRY_ACCESSIBLE (obj);
+ GtkEntryAccessiblePrivate *priv = accessible->priv;
+ GtkWidget *widget;
+ GtkEntry *entry;
+ GtkEntryIconPosition pos;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
+ if (widget == NULL)
+ return NULL;
+
+ entry = GTK_ENTRY (widget);
+
+ switch (i)
+ {
+ case 0:
+ if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
+ pos = GTK_ENTRY_ICON_PRIMARY;
+ else if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
+ pos = GTK_ENTRY_ICON_SECONDARY;
+ else
+ return NULL;
+ break;
+ case 1:
+ if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY)
+ return NULL;
+ if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY)
+ return NULL;
+ pos = GTK_ENTRY_ICON_SECONDARY;
+ break;
+ default:
+ return NULL;
+ }
+
+ if (!priv->icons[pos])
+ priv->icons[pos] = gtk_entry_icon_accessible_new (accessible, pos);
+ return g_object_ref (priv->icons[pos]);
}
static void
-_gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass)
+gtk_entry_accessible_finalize (GObject *object)
+{
+ GtkEntryAccessible *entry = GTK_ENTRY_ACCESSIBLE (object);
+ GtkEntryAccessiblePrivate *priv = entry->priv;
+
+ g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]);
+ g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]);
+
+ G_OBJECT_CLASS (gtk_entry_accessible_parent_class)->finalize (object);
+}
+
+static void
+gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
class->ref_state_set = gtk_entry_accessible_ref_state_set;
class->get_index_in_parent = gtk_entry_accessible_get_index_in_parent;
class->initialize = gtk_entry_accessible_initialize;
class->get_attributes = gtk_entry_accessible_get_attributes;
+ class->get_n_children = gtk_entry_accessible_get_n_children;
+ class->ref_child = gtk_entry_accessible_ref_child;
widget_class->notify_gtk = gtk_entry_accessible_notify_gtk;
+
+ gobject_class->finalize = gtk_entry_accessible_finalize;
+
+ g_type_class_add_private (klass, sizeof (GtkEntryAccessiblePrivate));
}
static void
-_gtk_entry_accessible_init (GtkEntryAccessible *entry)
+gtk_entry_accessible_init (GtkEntryAccessible *entry)
{
- entry->length_insert = 0;
- entry->length_delete = 0;
- entry->cursor_position = 0;
- entry->selection_bound = 0;
+ entry->priv = G_TYPE_INSTANCE_GET_PRIVATE (entry,
+ GTK_TYPE_ENTRY_ACCESSIBLE,
+ GtkEntryAccessiblePrivate);
+ entry->priv->cursor_position = 0;
+ entry->priv->selection_bound = 0;
}
static gchar *
gint end_pos)
{
GtkWidget *widget;
- const gchar *text;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
return NULL;
- /* FIXME: is this acceptable ? */
- if (!gtk_entry_get_visibility (GTK_ENTRY (widget)))
- return g_strdup ("");
-
- text = gtk_entry_get_text (GTK_ENTRY (widget));
-
- if (text)
- return g_utf8_substring (text, start_pos, end_pos > -1 ? end_pos : g_utf8_strlen (text, -1));
-
- return NULL;
+ return _gtk_entry_get_display_text (GTK_ENTRY (widget), start_pos, end_pos);
}
static gchar *
if (widget == NULL)
return NULL;
- /* FIXME: is this acceptable ? */
- if (!gtk_entry_get_visibility (GTK_ENTRY (widget)))
- return g_strdup ("");
-
return _gtk_pango_get_text_before (gtk_entry_get_layout (GTK_ENTRY (widget)),
boundary_type, offset,
start_offset, end_offset);
if (widget == NULL)
return NULL;
- /* FIXME: is this acceptable ? */
- if (!gtk_entry_get_visibility (GTK_ENTRY (widget)))
- return g_strdup ("");
-
return _gtk_pango_get_text_at (gtk_entry_get_layout (GTK_ENTRY (widget)),
boundary_type, offset,
start_offset, end_offset);
if (widget == NULL)
return NULL;
- /* FIXME: is this acceptable ? */
- if (!gtk_entry_get_visibility (GTK_ENTRY (widget)))
- return g_strdup ("");
-
return _gtk_pango_get_text_after (gtk_entry_get_layout (GTK_ENTRY (widget)),
boundary_type, offset,
start_offset, end_offset);
gtk_entry_accessible_get_character_count (AtkText *atk_text)
{
GtkWidget *widget;
- const gchar *text;
+ gchar *text;
+ glong char_count;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
return 0;
- text = gtk_entry_get_text (GTK_ENTRY (widget));
+ text = _gtk_entry_get_display_text (GTK_ENTRY (widget), 0, -1);
+ char_count = 0;
if (text)
- return g_utf8_strlen (text, -1);
+ {
+ char_count = g_utf8_strlen (text, -1);
+ g_free (text);
+ }
- return 0;
+ return char_count;
}
static gint
GtkWidget *widget;
GtkEntry *entry;
PangoRectangle char_rect;
- const gchar *entry_text;
+ gchar *entry_text;
gint index, x_layout, y_layout;
GdkWindow *window;
gint x_window, y_window;
entry = GTK_ENTRY (widget);
gtk_entry_get_layout_offsets (entry, &x_layout, &y_layout);
- entry_text = gtk_entry_get_text (entry);
+ entry_text = _gtk_entry_get_display_text (entry, 0, -1);
index = g_utf8_offset_to_pointer (entry_text, offset) - entry_text;
+ g_free (entry_text);
+
pango_layout_index_to_pos (gtk_entry_get_layout (entry), index, &char_rect);
pango_extents_to_pixels (&char_rect, NULL);
{
GtkWidget *widget;
GtkEntry *entry;
- const gchar *text;
+ gchar *text;
gint index, x_layout, y_layout;
gint x_window, y_window;
gint x_local, y_local;
GdkWindow *window;
+ glong offset;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
index = -1;
}
+ offset = -1;
if (index != -1)
{
- text = gtk_entry_get_text (entry);
- return g_utf8_pointer_to_offset (text, text + index);
+ text = _gtk_entry_get_display_text (entry, 0, -1);
+ offset = g_utf8_pointer_to_offset (text, text + index);
+ g_free (text);
}
- return -1;
+ return offset;
}
static gint
gint offset)
{
GtkWidget *widget;
- const gchar *text;
+ gchar *text;
gchar *index;
+ gunichar result;
+
+ result = '\0';
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
- return '\0';
+ return result;
if (!gtk_entry_get_visibility (GTK_ENTRY (widget)))
- return '\0';
+ return result;
- text = gtk_entry_get_text (GTK_ENTRY (widget));
- if (offset >= g_utf8_strlen (text, -1))
- return '\0';
-
- index = g_utf8_offset_to_pointer (text, offset);
+ text = _gtk_entry_get_display_text (GTK_ENTRY (widget), 0, -1);
+ if (offset < g_utf8_strlen (text, -1))
+ {
+ index = g_utf8_offset_to_pointer (text, offset);
+ result = g_utf8_get_char (index);
+ g_free (text);
+ }
- return g_utf8_get_char (index);
+ return result;
}
static void
return;
accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
- if (accessible->length_insert == 0)
- {
- accessible->position_insert = *position;
- accessible->length_insert = g_utf8_strlen (new_text, new_text_length);
- }
+
+ g_signal_emit_by_name (accessible,
+ "text-changed::insert",
+ *position,
+ g_utf8_strlen (new_text, new_text_length));
}
/* We connect to GtkEditable::delete-text, since it carries
{
GtkEntryAccessible *accessible;
+ accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
+
if (end < 0)
{
- const gchar *text;
+ gchar *text;
- text = gtk_entry_get_text (GTK_ENTRY (editable));
+ text = _gtk_entry_get_display_text (GTK_ENTRY (editable), 0, -1);
end = g_utf8_strlen (text, -1);
+ g_free (text);
}
if (end == start)
return;
- accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
- if (accessible->length_delete == 0)
- {
- accessible->position_delete = start;
- accessible->length_delete = end - start;
- }
-}
-
-/* Note the assumption here: A single ::changed emission
- * will only collect a single deletion/insertion, and there
- * won't be multiple insertions or deletions in a single
- * change.
- */
-static void
-changed_cb (GtkEditable *editable)
-{
- GtkEntryAccessible *accessible;
-
- accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
-
- if (accessible->length_delete > 0)
- {
- g_signal_emit_by_name (accessible,
- "text-changed::delete",
- accessible->position_delete,
- accessible->length_delete);
- accessible->length_delete = 0;
- }
- if (accessible->length_insert > 0)
- {
- g_signal_emit_by_name (accessible,
- "text-changed::insert",
- accessible->position_insert,
- accessible->length_insert);
- accessible->length_insert = 0;
- }
+ g_signal_emit_by_name (accessible,
+ "text-changed::delete",
+ start,
+ end);
}
static gboolean
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
{
- if (end != accessible->cursor_position ||
- start != accessible->selection_bound)
+ if (end != accessible->priv->cursor_position ||
+ start != accessible->priv->selection_bound)
/*
* This check is here as this function can be called
* for notification of selection_bound and current_pos.
else
{
/* We had a selection */
- ret_val = (accessible->cursor_position != accessible->selection_bound);
+ ret_val = (accessible->priv->cursor_position != accessible->priv->selection_bound);
}
- accessible->cursor_position = end;
- accessible->selection_bound = start;
+ accessible->priv->cursor_position = end;
+ accessible->priv->selection_bound = start;
return ret_val;
}