1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/atk/nsMaiHyperlink.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,259 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "nsIURI.h" 1.11 +#include "nsMaiHyperlink.h" 1.12 + 1.13 +using namespace mozilla::a11y; 1.14 + 1.15 +/* MaiAtkHyperlink */ 1.16 + 1.17 +#define MAI_TYPE_ATK_HYPERLINK (mai_atk_hyperlink_get_type ()) 1.18 +#define MAI_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ 1.19 + MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink)) 1.20 +#define MAI_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\ 1.21 + MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass)) 1.22 +#define MAI_IS_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ 1.23 + MAI_TYPE_ATK_HYPERLINK)) 1.24 +#define MAI_IS_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\ 1.25 + MAI_TYPE_ATK_HYPERLINK)) 1.26 +#define MAI_ATK_HYPERLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\ 1.27 + MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass)) 1.28 + 1.29 +/** 1.30 + * This MaiAtkHyperlink is a thin wrapper, in the MAI namespace, 1.31 + * for AtkHyperlink 1.32 + */ 1.33 + 1.34 +struct MaiAtkHyperlink 1.35 +{ 1.36 + AtkHyperlink parent; 1.37 + 1.38 + /* 1.39 + * The MaiHyperlink whose properties and features are exported via this 1.40 + * hyperlink instance. 1.41 + */ 1.42 + MaiHyperlink *maiHyperlink; 1.43 +}; 1.44 + 1.45 +struct MaiAtkHyperlinkClass 1.46 +{ 1.47 + AtkHyperlinkClass parent_class; 1.48 +}; 1.49 + 1.50 +GType mai_atk_hyperlink_get_type(void); 1.51 + 1.52 +G_BEGIN_DECLS 1.53 +/* callbacks for AtkHyperlink */ 1.54 +static void classInitCB(AtkHyperlinkClass *aClass); 1.55 +static void finalizeCB(GObject *aObj); 1.56 + 1.57 +/* callbacks for AtkHyperlink virtual functions */ 1.58 +static gchar *getUriCB(AtkHyperlink *aLink, gint aLinkIndex); 1.59 +static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex); 1.60 +static gint getEndIndexCB(AtkHyperlink *aLink); 1.61 +static gint getStartIndexCB(AtkHyperlink *aLink); 1.62 +static gboolean isValidCB(AtkHyperlink *aLink); 1.63 +static gint getAnchorCountCB(AtkHyperlink *aLink); 1.64 +G_END_DECLS 1.65 + 1.66 +static gpointer parent_class = nullptr; 1.67 +static Accessible* 1.68 +get_accessible_hyperlink(AtkHyperlink *aHyperlink); 1.69 + 1.70 +GType 1.71 +mai_atk_hyperlink_get_type(void) 1.72 +{ 1.73 + static GType type = 0; 1.74 + 1.75 + if (!type) { 1.76 + static const GTypeInfo tinfo = { 1.77 + sizeof(MaiAtkHyperlinkClass), 1.78 + (GBaseInitFunc)nullptr, 1.79 + (GBaseFinalizeFunc)nullptr, 1.80 + (GClassInitFunc)classInitCB, 1.81 + (GClassFinalizeFunc)nullptr, 1.82 + nullptr, /* class data */ 1.83 + sizeof(MaiAtkHyperlink), /* instance size */ 1.84 + 0, /* nb preallocs */ 1.85 + (GInstanceInitFunc)nullptr, 1.86 + nullptr /* value table */ 1.87 + }; 1.88 + 1.89 + type = g_type_register_static(ATK_TYPE_HYPERLINK, 1.90 + "MaiAtkHyperlink", 1.91 + &tinfo, GTypeFlags(0)); 1.92 + } 1.93 + return type; 1.94 +} 1.95 + 1.96 +MaiHyperlink::MaiHyperlink(Accessible* aHyperLink) : 1.97 + mHyperlink(aHyperLink), 1.98 + mMaiAtkHyperlink(nullptr) 1.99 +{ 1.100 +} 1.101 + 1.102 +MaiHyperlink::~MaiHyperlink() 1.103 +{ 1.104 + if (mMaiAtkHyperlink) { 1.105 + MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr; 1.106 + g_object_unref(mMaiAtkHyperlink); 1.107 + } 1.108 +} 1.109 + 1.110 +AtkHyperlink* 1.111 +MaiHyperlink::GetAtkHyperlink(void) 1.112 +{ 1.113 + NS_ENSURE_TRUE(mHyperlink, nullptr); 1.114 + 1.115 + if (mMaiAtkHyperlink) 1.116 + return mMaiAtkHyperlink; 1.117 + 1.118 + if (!mHyperlink->IsLink()) 1.119 + return nullptr; 1.120 + 1.121 + mMaiAtkHyperlink = 1.122 + reinterpret_cast<AtkHyperlink *> 1.123 + (g_object_new(mai_atk_hyperlink_get_type(), nullptr)); 1.124 + NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY"); 1.125 + NS_ENSURE_TRUE(mMaiAtkHyperlink, nullptr); 1.126 + 1.127 + /* be sure to initialize it with "this" */ 1.128 + MaiHyperlink::Initialize(mMaiAtkHyperlink, this); 1.129 + 1.130 + return mMaiAtkHyperlink; 1.131 +} 1.132 + 1.133 +/* static */ 1.134 + 1.135 +/* remember to call this static function when a MaiAtkHyperlink 1.136 + * is created 1.137 + */ 1.138 + 1.139 +nsresult 1.140 +MaiHyperlink::Initialize(AtkHyperlink *aObj, MaiHyperlink *aHyperlink) 1.141 +{ 1.142 + NS_ENSURE_ARG(MAI_IS_ATK_HYPERLINK(aObj)); 1.143 + NS_ENSURE_ARG(aHyperlink); 1.144 + 1.145 + /* initialize hyperlink */ 1.146 + MAI_ATK_HYPERLINK(aObj)->maiHyperlink = aHyperlink; 1.147 + return NS_OK; 1.148 +} 1.149 + 1.150 +/* static functions for ATK callbacks */ 1.151 + 1.152 +void 1.153 +classInitCB(AtkHyperlinkClass *aClass) 1.154 +{ 1.155 + GObjectClass *gobject_class = G_OBJECT_CLASS(aClass); 1.156 + 1.157 + parent_class = g_type_class_peek_parent(aClass); 1.158 + 1.159 + aClass->get_uri = getUriCB; 1.160 + aClass->get_object = getObjectCB; 1.161 + aClass->get_end_index = getEndIndexCB; 1.162 + aClass->get_start_index = getStartIndexCB; 1.163 + aClass->is_valid = isValidCB; 1.164 + aClass->get_n_anchors = getAnchorCountCB; 1.165 + 1.166 + gobject_class->finalize = finalizeCB; 1.167 +} 1.168 + 1.169 +void 1.170 +finalizeCB(GObject *aObj) 1.171 +{ 1.172 + NS_ASSERTION(MAI_IS_ATK_HYPERLINK(aObj), "Invalid MaiAtkHyperlink"); 1.173 + if (!MAI_IS_ATK_HYPERLINK(aObj)) 1.174 + return; 1.175 + 1.176 + MaiAtkHyperlink *maiAtkHyperlink = MAI_ATK_HYPERLINK(aObj); 1.177 + maiAtkHyperlink->maiHyperlink = nullptr; 1.178 + 1.179 + /* call parent finalize function */ 1.180 + if (G_OBJECT_CLASS (parent_class)->finalize) 1.181 + G_OBJECT_CLASS (parent_class)->finalize(aObj); 1.182 +} 1.183 + 1.184 +gchar * 1.185 +getUriCB(AtkHyperlink *aLink, gint aLinkIndex) 1.186 +{ 1.187 + Accessible* hyperlink = get_accessible_hyperlink(aLink); 1.188 + NS_ENSURE_TRUE(hyperlink, nullptr); 1.189 + 1.190 + nsCOMPtr<nsIURI> uri = hyperlink->AnchorURIAt(aLinkIndex); 1.191 + if (!uri) 1.192 + return nullptr; 1.193 + 1.194 + nsAutoCString cautoStr; 1.195 + nsresult rv = uri->GetSpec(cautoStr); 1.196 + NS_ENSURE_SUCCESS(rv, nullptr); 1.197 + 1.198 + return g_strdup(cautoStr.get()); 1.199 +} 1.200 + 1.201 +AtkObject * 1.202 +getObjectCB(AtkHyperlink *aLink, gint aLinkIndex) 1.203 +{ 1.204 + Accessible* hyperlink = get_accessible_hyperlink(aLink); 1.205 + NS_ENSURE_TRUE(hyperlink, nullptr); 1.206 + 1.207 + Accessible* anchor = hyperlink->AnchorAt(aLinkIndex); 1.208 + NS_ENSURE_TRUE(anchor, nullptr); 1.209 + 1.210 + AtkObject* atkObj = AccessibleWrap::GetAtkObject(anchor); 1.211 + //no need to add ref it, because it is "get" not "ref" 1.212 + return atkObj; 1.213 +} 1.214 + 1.215 +gint 1.216 +getEndIndexCB(AtkHyperlink *aLink) 1.217 +{ 1.218 + Accessible* hyperlink = get_accessible_hyperlink(aLink); 1.219 + NS_ENSURE_TRUE(hyperlink, -1); 1.220 + 1.221 + return static_cast<gint>(hyperlink->EndOffset()); 1.222 +} 1.223 + 1.224 +gint 1.225 +getStartIndexCB(AtkHyperlink *aLink) 1.226 +{ 1.227 + Accessible* hyperlink = get_accessible_hyperlink(aLink); 1.228 + NS_ENSURE_TRUE(hyperlink, -1); 1.229 + 1.230 + return static_cast<gint>(hyperlink->StartOffset()); 1.231 +} 1.232 + 1.233 +gboolean 1.234 +isValidCB(AtkHyperlink *aLink) 1.235 +{ 1.236 + Accessible* hyperlink = get_accessible_hyperlink(aLink); 1.237 + NS_ENSURE_TRUE(hyperlink, FALSE); 1.238 + 1.239 + return static_cast<gboolean>(hyperlink->IsLinkValid()); 1.240 +} 1.241 + 1.242 +gint 1.243 +getAnchorCountCB(AtkHyperlink *aLink) 1.244 +{ 1.245 + Accessible* hyperlink = get_accessible_hyperlink(aLink); 1.246 + NS_ENSURE_TRUE(hyperlink, -1); 1.247 + 1.248 + return static_cast<gint>(hyperlink->AnchorCount()); 1.249 +} 1.250 + 1.251 +// Check if aHyperlink is a valid MaiHyperlink, and return the 1.252 +// HyperLinkAccessible related. 1.253 +Accessible* 1.254 +get_accessible_hyperlink(AtkHyperlink *aHyperlink) 1.255 +{ 1.256 + NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr); 1.257 + MaiHyperlink * maiHyperlink = 1.258 + MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink; 1.259 + NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr); 1.260 + NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr); 1.261 + return maiHyperlink->GetAccHyperlink(); 1.262 +}