| 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());
|
| + }
|
| }
|
| }
|
|
|
|
|