summaryrefslogtreecommitdiff
path: root/libview/ev-link-accessible.c
diff options
context:
space:
mode:
Diffstat (limited to 'libview/ev-link-accessible.c')
-rw-r--r--libview/ev-link-accessible.c121
1 files changed, 120 insertions, 1 deletions
diff --git a/libview/ev-link-accessible.c b/libview/ev-link-accessible.c
index d1f91064..a9ee85dc 100644
--- a/libview/ev-link-accessible.c
+++ b/libview/ev-link-accessible.c
@@ -32,6 +32,8 @@ struct _EvLinkAccessiblePrivate {
EvRectangle area;
EvHyperlink *hyperlink;
+
+ gchar *name;
};
struct _EvHyperlink {
@@ -187,10 +189,71 @@ ev_hyperlink_init (EvHyperlink *link)
static void ev_link_accessible_hyperlink_impl_iface_init (AtkHyperlinkImplIface *iface);
static void ev_link_accessible_action_interface_init (AtkActionIface *iface);
+static void ev_link_accessible_component_iface_init (AtkComponentIface *iface);
G_DEFINE_TYPE_WITH_CODE (EvLinkAccessible, ev_link_accessible, ATK_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (ATK_TYPE_HYPERLINK_IMPL, ev_link_accessible_hyperlink_impl_iface_init)
- G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, ev_link_accessible_action_interface_init))
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, ev_link_accessible_action_interface_init)
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, ev_link_accessible_component_iface_init))
+
+static const gchar *
+ev_link_accessible_get_name (AtkObject *atk_object)
+{
+ EvLinkAccessiblePrivate *priv;
+ gint start_index;
+ gint end_index;
+
+ priv = EV_LINK_ACCESSIBLE (atk_object)->priv;
+ if (priv->name)
+ return priv->name;
+
+ start_index = ev_hyperlink_get_start_index (ATK_HYPERLINK (priv->hyperlink));
+ end_index = ev_hyperlink_get_end_index (ATK_HYPERLINK (priv->hyperlink));
+ priv->name = atk_text_get_text (ATK_TEXT (atk_object_get_parent (atk_object)), start_index, end_index);
+
+ return priv->name;
+}
+
+static AtkObject *
+ev_link_accessible_get_parent (AtkObject *atk_object)
+{
+ EvLinkAccessiblePrivate *priv = EV_LINK_ACCESSIBLE (atk_object)->priv;
+
+ return ATK_OBJECT (priv->page);
+}
+
+static AtkStateSet *
+ev_link_accessible_ref_state_set (AtkObject *atk_object)
+{
+ AtkStateSet *state_set;
+ AtkStateSet *copy_set;
+ AtkStateSet *page_accessible_state_set;
+ EvLinkAccessible *self;
+ EvViewAccessible *view_accessible;
+ EvView *view;
+ gint page;
+
+ self = EV_LINK_ACCESSIBLE (atk_object);
+ state_set = ATK_OBJECT_CLASS (ev_link_accessible_parent_class)->ref_state_set (atk_object);
+ atk_state_set_clear_states (state_set);
+
+ page_accessible_state_set = atk_object_ref_state_set (ATK_OBJECT (self->priv->page));
+ copy_set = atk_state_set_or_sets (state_set, page_accessible_state_set);
+
+ view_accessible = ev_page_accessible_get_view_accessible (self->priv->page);
+ page = ev_page_accessible_get_page (self->priv->page);
+ if (!ev_view_accessible_is_doc_rect_showing (view_accessible, page, &self->priv->area))
+ atk_state_set_remove_state (copy_set, ATK_STATE_SHOWING);
+
+ view = ev_page_accessible_get_view (self->priv->page);
+ if (!view->focused_element || view->focused_element->data != self->priv->link)
+ atk_state_set_remove_state (copy_set, ATK_STATE_FOCUSED);
+
+ g_object_unref (state_set);
+ g_object_unref (page_accessible_state_set);
+
+ return copy_set;
+}
static void
ev_link_accessible_finalize (GObject *object)
@@ -198,6 +261,7 @@ ev_link_accessible_finalize (GObject *object)
EvLinkAccessible *link = EV_LINK_ACCESSIBLE (object);
g_clear_object (&link->priv->hyperlink);
+ g_free (link->priv->name);
G_OBJECT_CLASS (ev_link_accessible_parent_class)->finalize (object);
}
@@ -206,15 +270,21 @@ static void
ev_link_accessible_class_init (EvLinkAccessibleClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
object_class->finalize = ev_link_accessible_finalize;
g_type_class_add_private (klass, sizeof (EvLinkAccessiblePrivate));
+
+ atk_class->get_parent = ev_link_accessible_get_parent;
+ atk_class->get_name = ev_link_accessible_get_name;
+ atk_class->ref_state_set = ev_link_accessible_ref_state_set;
}
static void
ev_link_accessible_init (EvLinkAccessible *link)
{
+ atk_object_set_role (ATK_OBJECT (link), ATK_ROLE_LINK);
link->priv = G_TYPE_INSTANCE_GET_PRIVATE (link, EV_TYPE_LINK_ACCESSIBLE, EvLinkAccessiblePrivate);
}
@@ -286,6 +356,55 @@ ev_link_accessible_action_interface_init (AtkActionIface *iface)
iface->get_name = ev_link_accessible_action_get_name;
}
+static void
+ev_link_accessible_get_extents (AtkComponent *atk_component,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coord_type)
+{
+ EvLinkAccessible *self;
+ EvViewAccessible *view_accessible;
+ gint page;
+ EvRectangle atk_rect;
+
+ self = EV_LINK_ACCESSIBLE (atk_component);
+ view_accessible = ev_page_accessible_get_view_accessible (self->priv->page);
+ page = ev_page_accessible_get_page (self->priv->page);
+ _transform_doc_rect_to_atk_rect (view_accessible, page, &self->priv->area, &atk_rect, coord_type);
+ *x = atk_rect.x1;
+ *y = atk_rect.y1;
+ *width = atk_rect.x2 - atk_rect.x1;
+ *height = atk_rect.y2 - atk_rect.y1;
+}
+
+static gboolean
+ev_link_accessible_grab_focus (AtkComponent *atk_component)
+{
+ EvLinkAccessible *self;
+ EvView *view;
+ EvMappingList *link_mapping;
+ EvMapping *mapping;
+ gint page;
+
+ self = EV_LINK_ACCESSIBLE (atk_component);
+ view = ev_page_accessible_get_view (self->priv->page);
+ page = ev_page_accessible_get_page (self->priv->page);
+ link_mapping = ev_page_cache_get_link_mapping (view->page_cache, page);
+ mapping = ev_mapping_list_find (link_mapping, self->priv->link);
+ _ev_view_set_focused_element (view, mapping, page);
+
+ return TRUE;
+}
+
+static void
+ev_link_accessible_component_iface_init (AtkComponentIface *iface)
+{
+ iface->get_extents = ev_link_accessible_get_extents;
+ iface->grab_focus = ev_link_accessible_grab_focus;
+}
+
EvLinkAccessible *
ev_link_accessible_new (EvPageAccessible *page,
EvLink *link,