| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "content/browser/accessibility/browser_accessibility_gtk.h" | |
| 6 | |
| 7 #include "base/utf_string_conversions.h" | |
| 8 #include "content/browser/accessibility/browser_accessibility_manager_gtk.h" | |
| 9 #include "content/common/accessibility_messages.h" | |
| 10 | |
| 11 #include <gtk/gtk.h> | |
| 12 | |
| 13 using webkit_glue::WebAccessibility; | |
| 14 | |
| 15 // The maximum length of an autogenerated unique type name string, | |
| 16 // generated from the 16-bit interface mask from an AtkObject. | |
| 17 // 30 is enough for the prefix "WAIType" + 5 hex chars (max) */ | |
| 18 static const int kWAITypeNameLen = 30; | |
| 19 | |
| 20 static gpointer browser_accessibility_parent_class = NULL; | |
| 21 | |
| 22 static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk( | |
| 23 BrowserAccessibilityAtk* atk_object) { | |
| 24 if (!atk_object) | |
| 25 return NULL; | |
| 26 | |
| 27 return atk_object->m_object; | |
| 28 } | |
| 29 | |
| 30 static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk( | |
| 31 AtkObject* atk_object) { | |
| 32 if (!IS_BROWSER_ACCESSIBILITY(atk_object)) | |
| 33 return NULL; | |
| 34 | |
| 35 return ToBrowserAccessibilityGtk(BROWSER_ACCESSIBILITY(atk_object)); | |
| 36 } | |
| 37 | |
| 38 static const gchar* browser_accessibility_get_name(AtkObject* atk_object) { | |
| 39 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); | |
| 40 return obj->atk_acc_name().c_str(); | |
| 41 } | |
| 42 | |
| 43 static const gchar* browser_accessibility_get_description( | |
| 44 AtkObject* atk_object) { | |
| 45 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); | |
| 46 string16 description; | |
| 47 obj->GetStringAttribute(WebAccessibility::ATTR_DESCRIPTION, &description); | |
| 48 return UTF16ToUTF8(description).c_str(); | |
| 49 } | |
| 50 | |
| 51 static AtkObject* browser_accessibility_get_parent(AtkObject* atk_object) { | |
| 52 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); | |
| 53 if (obj->parent()) | |
| 54 return obj->parent()->ToBrowserAccessibilityGtk()->GetAtkObject(); | |
| 55 else | |
| 56 return gtk_widget_get_accessible(obj->manager()->GetParentView()); | |
| 57 } | |
| 58 | |
| 59 static gint browser_accessibility_get_n_children(AtkObject* atk_object) { | |
| 60 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); | |
| 61 return obj->children().size(); | |
| 62 } | |
| 63 | |
| 64 static AtkObject* browser_accessibility_ref_child( | |
| 65 AtkObject* atk_object, gint index) { | |
| 66 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); | |
| 67 AtkObject* result = | |
| 68 obj->children()[index]->ToBrowserAccessibilityGtk()->GetAtkObject(); | |
| 69 g_object_ref(result); | |
| 70 return result; | |
| 71 } | |
| 72 | |
| 73 static gint browser_accessibility_get_index_in_parent(AtkObject* atk_object) { | |
| 74 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); | |
| 75 return obj->index_in_parent(); | |
| 76 } | |
| 77 | |
| 78 static AtkAttributeSet* browser_accessibility_get_attributes( | |
| 79 AtkObject* atk_object) { | |
| 80 return NULL; | |
| 81 } | |
| 82 | |
| 83 static AtkRole browser_accessibility_get_role(AtkObject* atk_object) { | |
| 84 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); | |
| 85 return obj->atk_role(); | |
| 86 } | |
| 87 | |
| 88 static AtkStateSet* browser_accessibility_ref_state_set(AtkObject* atk_object) { | |
| 89 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); | |
| 90 AtkStateSet* state_set = | |
| 91 ATK_OBJECT_CLASS(browser_accessibility_parent_class)-> | |
| 92 ref_state_set(atk_object); | |
| 93 int32 state = obj->state(); | |
| 94 | |
| 95 if ((state >> WebAccessibility::STATE_FOCUSABLE) & 1) | |
| 96 atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE); | |
| 97 if (obj->manager()->GetFocus(NULL) == obj) | |
| 98 atk_state_set_add_state(state_set, ATK_STATE_FOCUSED); | |
| 99 | |
| 100 return state_set; | |
| 101 } | |
| 102 | |
| 103 static AtkRelationSet* browser_accessibility_ref_relation_set( | |
| 104 AtkObject* atk_object) { | |
| 105 AtkRelationSet* relation_set = | |
| 106 ATK_OBJECT_CLASS(browser_accessibility_parent_class) | |
| 107 ->ref_relation_set(atk_object); | |
| 108 return relation_set; | |
| 109 } | |
| 110 | |
| 111 static void browser_accessibility_init(AtkObject* atk_object, gpointer data) { | |
| 112 if (ATK_OBJECT_CLASS(browser_accessibility_parent_class)->initialize) { | |
| 113 ATK_OBJECT_CLASS(browser_accessibility_parent_class)->initialize( | |
| 114 atk_object, data); | |
| 115 } | |
| 116 | |
| 117 BROWSER_ACCESSIBILITY(atk_object)->m_object = | |
| 118 reinterpret_cast<BrowserAccessibilityGtk*>(data); | |
| 119 } | |
| 120 | |
| 121 static void browser_accessibility_finalize(GObject* atk_object) { | |
| 122 G_OBJECT_CLASS(browser_accessibility_parent_class)->finalize(atk_object); | |
| 123 } | |
| 124 | |
| 125 static void browser_accessibility_class_init(AtkObjectClass* klass) { | |
| 126 GObjectClass* gobject_class = G_OBJECT_CLASS(klass); | |
| 127 browser_accessibility_parent_class = g_type_class_peek_parent(klass); | |
| 128 | |
| 129 gobject_class->finalize = browser_accessibility_finalize; | |
| 130 klass->initialize = browser_accessibility_init; | |
| 131 klass->get_name = browser_accessibility_get_name; | |
| 132 klass->get_description = browser_accessibility_get_description; | |
| 133 klass->get_parent = browser_accessibility_get_parent; | |
| 134 klass->get_n_children = browser_accessibility_get_n_children; | |
| 135 klass->ref_child = browser_accessibility_ref_child; | |
| 136 klass->get_role = browser_accessibility_get_role; | |
| 137 klass->ref_state_set = browser_accessibility_ref_state_set; | |
| 138 klass->get_index_in_parent = browser_accessibility_get_index_in_parent; | |
| 139 klass->get_attributes = browser_accessibility_get_attributes; | |
| 140 klass->ref_relation_set = browser_accessibility_ref_relation_set; | |
| 141 } | |
| 142 | |
| 143 GType browser_accessibility_get_type() { | |
| 144 static volatile gsize type_volatile = 0; | |
| 145 | |
| 146 if (g_once_init_enter(&type_volatile)) { | |
| 147 static const GTypeInfo tinfo = { | |
| 148 sizeof(BrowserAccessibilityAtkClass), | |
| 149 (GBaseInitFunc) 0, | |
| 150 (GBaseFinalizeFunc) 0, | |
| 151 (GClassInitFunc) browser_accessibility_class_init, | |
| 152 (GClassFinalizeFunc) 0, | |
| 153 0, /* class data */ | |
| 154 sizeof(BrowserAccessibilityAtk), /* instance size */ | |
| 155 0, /* nb preallocs */ | |
| 156 (GInstanceInitFunc) 0, | |
| 157 0 /* value table */ | |
| 158 }; | |
| 159 | |
| 160 GType type = g_type_register_static( | |
| 161 ATK_TYPE_OBJECT, "BrowserAccessibility", &tinfo, GTypeFlags(0)); | |
| 162 g_once_init_leave(&type_volatile, type); | |
| 163 } | |
| 164 | |
| 165 return type_volatile; | |
| 166 } | |
| 167 | |
| 168 static guint16 GetInterfaceMaskFromObject(BrowserAccessibilityGtk* obj) { | |
| 169 return 0; | |
| 170 } | |
| 171 | |
| 172 static const char* GetUniqueAccessibilityTypeName(guint16 interface_mask) | |
| 173 { | |
| 174 static char name[kWAITypeNameLen + 1]; | |
| 175 | |
| 176 sprintf(name, "WAIType%x", interface_mask); | |
| 177 name[kWAITypeNameLen] = '\0'; | |
| 178 | |
| 179 return name; | |
| 180 } | |
| 181 | |
| 182 static const GInterfaceInfo AtkInterfacesInitFunctions[] = { | |
| 183 }; | |
| 184 | |
| 185 enum WAIType { | |
| 186 WAI_ACTION, | |
| 187 WAI_SELECTION, | |
| 188 WAI_EDITABLE_TEXT, | |
| 189 WAI_TEXT, | |
| 190 WAI_COMPONENT, | |
| 191 WAI_IMAGE, | |
| 192 WAI_TABLE, | |
| 193 WAI_HYPERTEXT, | |
| 194 WAI_HYPERLINK, | |
| 195 WAI_DOCUMENT, | |
| 196 WAI_VALUE, | |
| 197 }; | |
| 198 | |
| 199 static GType GetAtkInterfaceTypeFromWAIType(WAIType type) { | |
| 200 switch (type) { | |
| 201 case WAI_ACTION: | |
| 202 return ATK_TYPE_ACTION; | |
| 203 case WAI_SELECTION: | |
| 204 return ATK_TYPE_SELECTION; | |
| 205 case WAI_EDITABLE_TEXT: | |
| 206 return ATK_TYPE_EDITABLE_TEXT; | |
| 207 case WAI_TEXT: | |
| 208 return ATK_TYPE_TEXT; | |
| 209 case WAI_COMPONENT: | |
| 210 return ATK_TYPE_COMPONENT; | |
| 211 case WAI_IMAGE: | |
| 212 return ATK_TYPE_IMAGE; | |
| 213 case WAI_TABLE: | |
| 214 return ATK_TYPE_TABLE; | |
| 215 case WAI_HYPERTEXT: | |
| 216 return ATK_TYPE_HYPERTEXT; | |
| 217 case WAI_HYPERLINK: | |
| 218 return ATK_TYPE_HYPERLINK_IMPL; | |
| 219 case WAI_DOCUMENT: | |
| 220 return ATK_TYPE_DOCUMENT; | |
| 221 case WAI_VALUE: | |
| 222 return ATK_TYPE_VALUE; | |
| 223 } | |
| 224 | |
| 225 return G_TYPE_INVALID; | |
| 226 } | |
| 227 | |
| 228 static GType GetAccessibilityTypeFromObject(BrowserAccessibilityGtk* obj) { | |
| 229 static const GTypeInfo type_info = { | |
| 230 sizeof(BrowserAccessibilityAtkClass), | |
| 231 (GBaseInitFunc) 0, | |
| 232 (GBaseFinalizeFunc) 0, | |
| 233 (GClassInitFunc) 0, | |
| 234 (GClassFinalizeFunc) 0, | |
| 235 0, /* class data */ | |
| 236 sizeof(BrowserAccessibilityAtk), /* instance size */ | |
| 237 0, /* nb preallocs */ | |
| 238 (GInstanceInitFunc) 0, | |
| 239 0 /* value table */ | |
| 240 }; | |
| 241 | |
| 242 guint16 interface_mask = GetInterfaceMaskFromObject(obj); | |
| 243 const char* atk_type_name = GetUniqueAccessibilityTypeName(interface_mask); | |
| 244 GType type = g_type_from_name(atk_type_name); | |
| 245 if (type) | |
| 246 return type; | |
| 247 | |
| 248 type = g_type_register_static(BROWSER_ACCESSIBILITY_TYPE, | |
| 249 atk_type_name, | |
| 250 &type_info, | |
| 251 GTypeFlags(0)); | |
| 252 for (guint i = 0; i < G_N_ELEMENTS(AtkInterfacesInitFunctions); i++) { | |
| 253 if (interface_mask & (1 << i)) { | |
| 254 g_type_add_interface_static( | |
| 255 type, | |
| 256 GetAtkInterfaceTypeFromWAIType(static_cast<WAIType>(i)), | |
| 257 &AtkInterfacesInitFunctions[i]); | |
| 258 } | |
| 259 } | |
| 260 | |
| 261 return type; | |
| 262 } | |
| 263 | |
| 264 BrowserAccessibilityAtk* browser_accessibility_new( | |
| 265 BrowserAccessibilityGtk* obj) { | |
| 266 GType type = GetAccessibilityTypeFromObject(obj); | |
| 267 AtkObject* atk_object = static_cast<AtkObject*>(g_object_new(type, 0)); | |
| 268 | |
| 269 atk_object_initialize(atk_object, obj); | |
| 270 | |
| 271 return BROWSER_ACCESSIBILITY(atk_object); | |
| 272 } | |
| 273 | |
| 274 void browser_accessibility_detach(BrowserAccessibilityAtk* atk_object) { | |
| 275 } | |
| 276 | |
| 277 // static | |
| 278 BrowserAccessibility* BrowserAccessibility::Create() { | |
| 279 return new BrowserAccessibilityGtk(); | |
| 280 } | |
| 281 | |
| 282 BrowserAccessibilityGtk* BrowserAccessibility::ToBrowserAccessibilityGtk() { | |
| 283 return static_cast<BrowserAccessibilityGtk*>(this); | |
| 284 } | |
| 285 | |
| 286 BrowserAccessibilityGtk::BrowserAccessibilityGtk() { | |
| 287 atk_object_ = ATK_OBJECT(browser_accessibility_new(this)); | |
| 288 } | |
| 289 | |
| 290 BrowserAccessibilityGtk::~BrowserAccessibilityGtk() { | |
| 291 browser_accessibility_detach(BROWSER_ACCESSIBILITY(atk_object_)); | |
| 292 } | |
| 293 | |
| 294 AtkObject* BrowserAccessibilityGtk::GetAtkObject() const { | |
| 295 if (!G_IS_OBJECT(atk_object_)) | |
| 296 return NULL; | |
| 297 return atk_object_; | |
| 298 } | |
| 299 | |
| 300 void BrowserAccessibilityGtk::PreInitialize() { | |
| 301 BrowserAccessibility::PreInitialize(); | |
| 302 InitRoleAndState(); | |
| 303 | |
| 304 if (this->parent()) { | |
| 305 atk_object_set_parent( | |
| 306 atk_object_, | |
| 307 this->parent()->ToBrowserAccessibilityGtk()->GetAtkObject()); | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 void BrowserAccessibilityGtk::InitRoleAndState() { | |
| 312 atk_acc_name_ = UTF16ToUTF8(name()).c_str(); | |
| 313 | |
| 314 switch(role_) { | |
| 315 case WebAccessibility::ROLE_BUTTON: | |
| 316 atk_role_ = ATK_ROLE_PUSH_BUTTON; | |
| 317 break; | |
| 318 case WebAccessibility::ROLE_CHECKBOX: | |
| 319 atk_role_ = ATK_ROLE_CHECK_BOX; | |
| 320 break; | |
| 321 case WebAccessibility::ROLE_COMBO_BOX: | |
| 322 atk_role_ = ATK_ROLE_COMBO_BOX; | |
| 323 break; | |
| 324 case WebAccessibility::ROLE_LINK: | |
| 325 atk_role_ = ATK_ROLE_LINK; | |
| 326 break; | |
| 327 case WebAccessibility::ROLE_RADIO_BUTTON: | |
| 328 atk_role_ = ATK_ROLE_RADIO_BUTTON; | |
| 329 break; | |
| 330 case WebAccessibility::ROLE_TEXTAREA: | |
| 331 atk_role_ = ATK_ROLE_ENTRY; | |
| 332 break; | |
| 333 case WebAccessibility::ROLE_TEXT_FIELD: | |
| 334 atk_role_ = ATK_ROLE_ENTRY; | |
| 335 break; | |
| 336 case WebAccessibility::ROLE_WEBCORE_LINK: | |
| 337 atk_role_ = ATK_ROLE_LINK; | |
| 338 break; | |
| 339 default: | |
| 340 atk_role_ = ATK_ROLE_UNKNOWN; | |
| 341 break; | |
| 342 } | |
| 343 } | |
| OLD | NEW |