Index: content/browser/accessibility/browser_accessibility_gtk.cc |
diff --git a/content/browser/accessibility/browser_accessibility_gtk.cc b/content/browser/accessibility/browser_accessibility_gtk.cc |
index f5539b78b5d42ec8a1eb12e0da5553c891f4b7ea..50364282b3df00eb6e0834962e7c5536fc5b87c0 100644 |
--- a/content/browser/accessibility/browser_accessibility_gtk.cc |
+++ b/content/browser/accessibility/browser_accessibility_gtk.cc |
@@ -12,11 +12,6 @@ |
namespace content { |
-// The maximum length of an autogenerated unique type name string, |
-// generated from the 16-bit interface mask from an AtkObject. |
-// 30 is enough for the prefix "WAIType" + 5 hex chars (max) */ |
-static const int kWAITypeNameLen = 30; |
- |
static gpointer browser_accessibility_parent_class = NULL; |
static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk( |
@@ -27,6 +22,150 @@ static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk( |
return atk_object->m_object; |
} |
+// |
+// AtkComponent interface. |
+// |
+ |
+static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk( |
+ AtkComponent* atk_object) { |
+ if (!IS_BROWSER_ACCESSIBILITY(atk_object)) |
+ return NULL; |
+ |
+ return ToBrowserAccessibilityGtk(BROWSER_ACCESSIBILITY(atk_object)); |
+} |
+ |
+static AtkObject* browser_accessibility_accessible_at_point( |
+ AtkComponent* component, gint x, gint y, AtkCoordType coord_type) { |
+ BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(component); |
+ if (!obj) |
+ return NULL; |
+ |
+ gfx::Point point(x, y); |
+ if (!obj->GetGlobalBoundsRect().Contains(point)) |
+ return NULL; |
+ |
+ BrowserAccessibility* result = obj->BrowserAccessibilityForPoint(point); |
+ if (!result) |
+ return NULL; |
+ |
+ AtkObject* atk_result = result->ToBrowserAccessibilityGtk()->GetAtkObject(); |
+ g_object_ref(atk_result); |
+ return atk_result; |
+} |
+ |
+static void browser_accessibility_get_extents( |
+ AtkComponent* component, gint* x, gint* y, gint* width, gint* height, |
+ AtkCoordType coord_type) { |
+ BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(component); |
+ if (!obj) |
+ return; |
+ |
+ gfx::Rect bounds = obj->GetGlobalBoundsRect(); |
+ *x = bounds.x(); |
+ *y = bounds.y(); |
+ *width = bounds.width(); |
+ *height = bounds.height(); |
+} |
+ |
+static gboolean browser_accessibility_grab_focus(AtkComponent* component) { |
+ BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(component); |
+ if (!obj) |
+ return false; |
+ |
+ obj->manager()->SetFocus(obj, true); |
+ return true; |
+} |
+ |
+static void ComponentInterfaceInit(AtkComponentIface* iface) { |
+ iface->ref_accessible_at_point = browser_accessibility_accessible_at_point; |
+ iface->get_extents = browser_accessibility_get_extents; |
+ iface->grab_focus = browser_accessibility_grab_focus; |
+} |
+ |
+static const GInterfaceInfo ComponentInfo = { |
+ reinterpret_cast<GInterfaceInitFunc>(ComponentInterfaceInit), 0, 0 |
+}; |
+ |
+// |
+// AtkValue interface. |
+// |
+ |
+static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk( |
+ AtkValue* atk_object) { |
+ if (!IS_BROWSER_ACCESSIBILITY(atk_object)) |
+ return NULL; |
+ |
+ return ToBrowserAccessibilityGtk(BROWSER_ACCESSIBILITY(atk_object)); |
+} |
+ |
+static void browser_accessibility_get_current_value( |
+ AtkValue* atk_object, GValue* value) { |
+ BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); |
+ if (!obj) |
+ return; |
+ |
+ float float_val; |
+ if (obj->GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, |
+ &float_val)) { |
+ memset(value, 0, sizeof(*value)); |
+ g_value_init(value, G_TYPE_FLOAT); |
+ g_value_set_float(value, float_val); |
+ } |
+} |
+ |
+static void browser_accessibility_get_minimum_value( |
+ AtkValue* atk_object, GValue* value) { |
+ BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); |
+ if (!obj) |
+ return; |
+ |
+ float float_val; |
+ if (obj->GetFloatAttribute(AccessibilityNodeData::ATTR_MIN_VALUE_FOR_RANGE, |
+ &float_val)) { |
+ memset(value, 0, sizeof(*value)); |
+ g_value_init(value, G_TYPE_FLOAT); |
+ g_value_set_float(value, float_val); |
+ } |
+} |
+ |
+static void browser_accessibility_get_maximum_value( |
+ AtkValue* atk_object, GValue* value) { |
+ BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); |
+ if (!obj) |
+ return; |
+ |
+ float float_val; |
+ if (obj->GetFloatAttribute(AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE, |
+ &float_val)) { |
+ memset(value, 0, sizeof(*value)); |
+ g_value_init(value, G_TYPE_FLOAT); |
+ g_value_set_float(value, float_val); |
+ } |
+} |
+ |
+static void browser_accessibility_get_minimum_increment( |
+ AtkValue* atk_object, GValue* value) { |
+ // TODO(dmazzoni): get the correct value from an <input type=range>. |
+ memset(value, 0, sizeof(*value)); |
+ g_value_init(value, G_TYPE_FLOAT); |
+ g_value_set_float(value, 1.0); |
+} |
+ |
+static void ValueInterfaceInit(AtkValueIface* iface) { |
+ iface->get_current_value = browser_accessibility_get_current_value; |
+ iface->get_minimum_value = browser_accessibility_get_minimum_value; |
+ iface->get_maximum_value = browser_accessibility_get_maximum_value; |
+ iface->get_minimum_increment = browser_accessibility_get_minimum_increment; |
+} |
+ |
+static const GInterfaceInfo ValueInfo = { |
+ reinterpret_cast<GInterfaceInitFunc>(ValueInterfaceInit), 0, 0 |
+}; |
+ |
+// |
+// AtkObject interface |
+// |
+ |
static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk( |
AtkObject* atk_object) { |
if (!IS_BROWSER_ACCESSIBILITY(atk_object)) |
@@ -126,6 +265,11 @@ static AtkRelationSet* browser_accessibility_ref_relation_set( |
return relation_set; |
} |
+// |
+// The rest of the BrowserAccessibilityGtk code, not specific to one |
+// of the Atk* interfaces. |
+// |
+ |
static void browser_accessibility_init(AtkObject* atk_object, gpointer data) { |
if (ATK_OBJECT_CLASS(browser_accessibility_parent_class)->initialize) { |
ATK_OBJECT_CLASS(browser_accessibility_parent_class)->initialize( |
@@ -183,64 +327,42 @@ GType browser_accessibility_get_type() { |
return type_volatile; |
} |
-static guint16 GetInterfaceMaskFromObject(BrowserAccessibilityGtk* obj) { |
- return 0; |
-} |
- |
-static const char* GetUniqueAccessibilityTypeName(guint16 interface_mask) |
+static const char* GetUniqueAccessibilityTypeName(int interface_mask) |
{ |
- static char name[kWAITypeNameLen + 1]; |
- |
- sprintf(name, "WAIType%x", interface_mask); |
- name[kWAITypeNameLen] = '\0'; |
- |
+ // 20 characters is enough for "Chrome%x" with any integer value. |
+ static char name[20]; |
+ snprintf(name, sizeof(name), "Chrome%x", interface_mask); |
return name; |
} |
-static const GInterfaceInfo AtkInterfacesInitFunctions[] = { |
+enum AtkInterfaces { |
+ ATK_ACTION_INTERFACE, |
+ ATK_COMPONENT_INTERFACE, |
+ ATK_DOCUMENT_INTERFACE, |
+ ATK_EDITABLE_TEXT_INTERFACE, |
+ ATK_HYPERLINK_INTERFACE, |
+ ATK_HYPERTEXT_INTERFACE, |
+ ATK_IMAGE_INTERFACE, |
+ ATK_SELECTION_INTERFACE, |
+ ATK_TABLE_INTERFACE, |
+ ATK_TEXT_INTERFACE, |
+ ATK_VALUE_INTERFACE, |
}; |
-enum WAIType { |
- WAI_ACTION, |
- WAI_SELECTION, |
- WAI_EDITABLE_TEXT, |
- WAI_TEXT, |
- WAI_COMPONENT, |
- WAI_IMAGE, |
- WAI_TABLE, |
- WAI_HYPERTEXT, |
- WAI_HYPERLINK, |
- WAI_DOCUMENT, |
- WAI_VALUE, |
-}; |
+static int GetInterfaceMaskFromObject(BrowserAccessibilityGtk* obj) { |
+ int interface_mask = 0; |
+ |
+ // Component interface is always supported. |
+ interface_mask |= 1 << ATK_COMPONENT_INTERFACE; |
-static GType GetAtkInterfaceTypeFromWAIType(WAIType type) { |
- switch (type) { |
- case WAI_ACTION: |
- return ATK_TYPE_ACTION; |
- case WAI_SELECTION: |
- return ATK_TYPE_SELECTION; |
- case WAI_EDITABLE_TEXT: |
- return ATK_TYPE_EDITABLE_TEXT; |
- case WAI_TEXT: |
- return ATK_TYPE_TEXT; |
- case WAI_COMPONENT: |
- return ATK_TYPE_COMPONENT; |
- case WAI_IMAGE: |
- return ATK_TYPE_IMAGE; |
- case WAI_TABLE: |
- return ATK_TYPE_TABLE; |
- case WAI_HYPERTEXT: |
- return ATK_TYPE_HYPERTEXT; |
- case WAI_HYPERLINK: |
- return ATK_TYPE_HYPERLINK_IMPL; |
- case WAI_DOCUMENT: |
- return ATK_TYPE_DOCUMENT; |
- case WAI_VALUE: |
- return ATK_TYPE_VALUE; |
+ int role = obj->role(); |
+ if (role == AccessibilityNodeData::ROLE_PROGRESS_INDICATOR || |
+ role == AccessibilityNodeData::ROLE_SCROLLBAR || |
+ role == AccessibilityNodeData::ROLE_SLIDER) { |
+ interface_mask |= 1 << ATK_VALUE_INTERFACE; |
} |
- return G_TYPE_INVALID; |
+ return interface_mask; |
} |
static GType GetAccessibilityTypeFromObject(BrowserAccessibilityGtk* obj) { |
@@ -257,7 +379,7 @@ static GType GetAccessibilityTypeFromObject(BrowserAccessibilityGtk* obj) { |
0 /* value table */ |
}; |
- guint16 interface_mask = GetInterfaceMaskFromObject(obj); |
+ int interface_mask = GetInterfaceMaskFromObject(obj); |
const char* atk_type_name = GetUniqueAccessibilityTypeName(interface_mask); |
GType type = g_type_from_name(atk_type_name); |
if (type) |
@@ -267,14 +389,10 @@ static GType GetAccessibilityTypeFromObject(BrowserAccessibilityGtk* obj) { |
atk_type_name, |
&type_info, |
GTypeFlags(0)); |
- for (guint i = 0; i < G_N_ELEMENTS(AtkInterfacesInitFunctions); i++) { |
- if (interface_mask & (1 << i)) { |
- g_type_add_interface_static( |
- type, |
- GetAtkInterfaceTypeFromWAIType(static_cast<WAIType>(i)), |
- &AtkInterfacesInitFunctions[i]); |
- } |
- } |
+ if (interface_mask & (1 << ATK_COMPONENT_INTERFACE)) |
+ g_type_add_interface_static(type, ATK_TYPE_COMPONENT, &ComponentInfo); |
+ if (interface_mask & (1 << ATK_VALUE_INTERFACE)) |
+ g_type_add_interface_static(type, ATK_TYPE_VALUE, &ValueInfo); |
return type; |
} |
@@ -302,13 +420,14 @@ BrowserAccessibilityGtk* BrowserAccessibility::ToBrowserAccessibilityGtk() { |
return static_cast<BrowserAccessibilityGtk*>(this); |
} |
-BrowserAccessibilityGtk::BrowserAccessibilityGtk() { |
- atk_object_ = ATK_OBJECT(browser_accessibility_new(this)); |
+BrowserAccessibilityGtk::BrowserAccessibilityGtk() |
+ : atk_object_(NULL) { |
} |
BrowserAccessibilityGtk::~BrowserAccessibilityGtk() { |
browser_accessibility_detach(BROWSER_ACCESSIBILITY(atk_object_)); |
- g_object_unref(atk_object_); |
+ if (atk_object_) |
+ g_object_unref(atk_object_); |
} |
AtkObject* BrowserAccessibilityGtk::GetAtkObject() const { |
@@ -321,10 +440,25 @@ void BrowserAccessibilityGtk::PreInitialize() { |
BrowserAccessibility::PreInitialize(); |
InitRoleAndState(); |
- if (this->parent()) { |
- atk_object_set_parent( |
- atk_object_, |
- this->parent()->ToBrowserAccessibilityGtk()->GetAtkObject()); |
+ if (atk_object_) { |
+ // If the object's role changes and that causes its |
+ // interface mask to change, we need to create a new |
+ // AtkObject for it. |
+ int interface_mask = GetInterfaceMaskFromObject(this); |
+ if (interface_mask != interface_mask_) { |
+ g_object_unref(atk_object_); |
+ atk_object_ = NULL; |
+ } |
+ } |
+ |
+ if (!atk_object_) { |
+ interface_mask_ = GetInterfaceMaskFromObject(this); |
+ atk_object_ = ATK_OBJECT(browser_accessibility_new(this)); |
+ if (this->parent()) { |
+ atk_object_set_parent( |
+ atk_object_, |
+ this->parent()->ToBrowserAccessibilityGtk()->GetAtkObject()); |
+ } |
} |
} |