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 |