summaryrefslogtreecommitdiffstats
path: root/WebCore/accessibility
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/accessibility')
-rw-r--r--WebCore/accessibility/AccessibilityImageMapLink.cpp8
-rw-r--r--WebCore/accessibility/AccessibilityImageMapLink.h10
-rw-r--r--WebCore/accessibility/AccessibilityMenuListOption.cpp7
-rw-r--r--WebCore/accessibility/AccessibilityMenuListOption.h1
-rw-r--r--WebCore/accessibility/AccessibilityObject.cpp5
-rw-r--r--WebCore/accessibility/AccessibilityRenderObject.cpp23
-rw-r--r--WebCore/accessibility/AccessibilityRenderObject.h1
-rw-r--r--WebCore/accessibility/gtk/AXObjectCacheAtk.cpp11
-rw-r--r--WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp150
9 files changed, 165 insertions, 51 deletions
diff --git a/WebCore/accessibility/AccessibilityImageMapLink.cpp b/WebCore/accessibility/AccessibilityImageMapLink.cpp
index 9b77400..870efe3 100644
--- a/WebCore/accessibility/AccessibilityImageMapLink.cpp
+++ b/WebCore/accessibility/AccessibilityImageMapLink.cpp
@@ -59,7 +59,7 @@ AccessibilityObject* AccessibilityImageMapLink::parentObject() const
if (m_parent)
return m_parent;
- if (!m_mapElement || !m_mapElement->renderer())
+ if (!m_mapElement.get() || !m_mapElement->renderer())
return 0;
return m_mapElement->document()->axObjectCache()->getOrCreate(m_mapElement->renderer());
@@ -84,12 +84,12 @@ Element* AccessibilityImageMapLink::actionElement() const
Element* AccessibilityImageMapLink::anchorElement() const
{
- return m_areaElement;
+ return m_areaElement.get();
}
KURL AccessibilityImageMapLink::url() const
{
- if (!m_areaElement)
+ if (!m_areaElement.get())
return KURL();
return m_areaElement->href();
@@ -121,7 +121,7 @@ String AccessibilityImageMapLink::title() const
IntRect AccessibilityImageMapLink::elementRect() const
{
- if (!m_mapElement || !m_areaElement)
+ if (!m_mapElement.get() || !m_areaElement.get())
return IntRect();
RenderObject* renderer;
diff --git a/WebCore/accessibility/AccessibilityImageMapLink.h b/WebCore/accessibility/AccessibilityImageMapLink.h
index e2e1544..011d5de 100644
--- a/WebCore/accessibility/AccessibilityImageMapLink.h
+++ b/WebCore/accessibility/AccessibilityImageMapLink.h
@@ -44,12 +44,12 @@ public:
virtual ~AccessibilityImageMapLink();
void setHTMLAreaElement(HTMLAreaElement* element) { m_areaElement = element; }
- HTMLAreaElement* areaElement() const { return m_areaElement; }
+ HTMLAreaElement* areaElement() const { return m_areaElement.get(); }
void setHTMLMapElement(HTMLMapElement* element) { m_mapElement = element; }
- HTMLMapElement* mapElement() const { return m_mapElement; }
+ HTMLMapElement* mapElement() const { return m_mapElement.get(); }
- virtual Node* node() const { return m_areaElement; }
+ virtual Node* node() const { return m_areaElement.get(); }
void setParent(AccessibilityObject* parent) { m_parent = parent; }
virtual AccessibilityRole roleValue() const;
@@ -72,8 +72,8 @@ public:
virtual IntRect elementRect() const;
private:
- HTMLAreaElement* m_areaElement;
- HTMLMapElement* m_mapElement;
+ RefPtr<HTMLAreaElement> m_areaElement;
+ RefPtr<HTMLMapElement> m_mapElement;
AccessibilityObject* m_parent;
virtual bool isImageMapLink() const { return true; }
diff --git a/WebCore/accessibility/AccessibilityMenuListOption.cpp b/WebCore/accessibility/AccessibilityMenuListOption.cpp
index d7473de..5bca580 100644
--- a/WebCore/accessibility/AccessibilityMenuListOption.cpp
+++ b/WebCore/accessibility/AccessibilityMenuListOption.cpp
@@ -91,7 +91,7 @@ void AccessibilityMenuListOption::setSelected(bool b)
String AccessibilityMenuListOption::nameForMSAA() const
{
- return static_cast<HTMLOptionElement*>(m_element.get())->text();
+ return stringValue();
}
bool AccessibilityMenuListOption::canSetSelectedAttribute() const
@@ -110,4 +110,9 @@ IntRect AccessibilityMenuListOption::elementRect() const
return grandparent->elementRect();
}
+String AccessibilityMenuListOption::stringValue() const
+{
+ return static_cast<HTMLOptionElement*>(m_element.get())->text();
+}
+
} // namespace WebCore
diff --git a/WebCore/accessibility/AccessibilityMenuListOption.h b/WebCore/accessibility/AccessibilityMenuListOption.h
index 7e27888..9393d56 100644
--- a/WebCore/accessibility/AccessibilityMenuListOption.h
+++ b/WebCore/accessibility/AccessibilityMenuListOption.h
@@ -59,6 +59,7 @@ private:
virtual void setSelected(bool);
virtual bool canSetSelectedAttribute() const;
virtual IntRect elementRect() const;
+ virtual String stringValue() const;
RefPtr<HTMLElement> m_element;
AccessibilityMenuListPopup* m_popup;
diff --git a/WebCore/accessibility/AccessibilityObject.cpp b/WebCore/accessibility/AccessibilityObject.cpp
index caf12dc..327a736 100644
--- a/WebCore/accessibility/AccessibilityObject.cpp
+++ b/WebCore/accessibility/AccessibilityObject.cpp
@@ -937,9 +937,8 @@ static ARIARoleMap* createARIARoleMap()
{ "treeitem", TreeItemRole }
};
ARIARoleMap* roleMap = new ARIARoleMap;
-
- const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
- for (unsigned i = 0; i < numRoles; ++i)
+
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(roles); ++i)
roleMap->set(roles[i].ariaRole, roles[i].webcoreRole);
return roleMap;
}
diff --git a/WebCore/accessibility/AccessibilityRenderObject.cpp b/WebCore/accessibility/AccessibilityRenderObject.cpp
index 141d725..3c6079b 100644
--- a/WebCore/accessibility/AccessibilityRenderObject.cpp
+++ b/WebCore/accessibility/AccessibilityRenderObject.cpp
@@ -1325,17 +1325,30 @@ String AccessibilityRenderObject::ariaDescribedByAttribute() const
return accessibilityDescriptionForElements(elements);
}
+
+String AccessibilityRenderObject::ariaAccessibilityDescription() const
+{
+ const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
+ if (!ariaLabel.isEmpty())
+ return ariaLabel;
+
+ String ariaDescription = ariaDescribedByAttribute();
+ if (!ariaDescription.isEmpty())
+ return ariaDescription;
+
+ return String();
+}
String AccessibilityRenderObject::accessibilityDescription() const
{
if (!m_renderer)
return String();
- const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
- if (!ariaLabel.isEmpty())
- return ariaLabel;
+ // Static text should not have a description, it should only have a stringValue.
+ if (roleValue() == StaticTextRole)
+ return String();
- String ariaDescription = ariaDescribedByAttribute();
+ String ariaDescription = ariaAccessibilityDescription();
if (!ariaDescription.isEmpty())
return ariaDescription;
@@ -1895,7 +1908,7 @@ String AccessibilityRenderObject::text() const
{
// If this is a user defined static text, use the accessible name computation.
if (ariaRoleAttribute() == StaticTextRole)
- return accessibilityDescription();
+ return ariaAccessibilityDescription();
if (!isTextControl() || isPasswordField())
return String();
diff --git a/WebCore/accessibility/AccessibilityRenderObject.h b/WebCore/accessibility/AccessibilityRenderObject.h
index 970ef9f..a01008a 100644
--- a/WebCore/accessibility/AccessibilityRenderObject.h
+++ b/WebCore/accessibility/AccessibilityRenderObject.h
@@ -300,6 +300,7 @@ private:
String accessibilityDescriptionForElements(Vector<Element*> &elements) const;
void elementsFromAttribute(Vector<Element*>& elements, const QualifiedName& name) const;
+ String ariaAccessibilityDescription() const;
virtual ESpeak speakProperty() const;
diff --git a/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp b/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
index 4216be4..c341a2d 100644
--- a/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
+++ b/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
@@ -95,10 +95,19 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object)
void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AXNotification notification)
{
+ AtkObject* axObject = coreObject->wrapper();
+ if (!axObject)
+ return;
+
if (notification == AXCheckedStateChanged) {
if (!coreObject->isCheckboxOrRadio())
return;
- g_signal_emit_by_name(coreObject->wrapper(), "state-change", "checked", coreObject->isChecked());
+ g_signal_emit_by_name(axObject, "state-change", "checked", coreObject->isChecked());
+ } else if (notification == AXMenuListValueChanged) {
+ if (!coreObject->isMenuList())
+ return;
+ g_signal_emit_by_name(axObject, "focus-event", true);
+ g_signal_emit_by_name(axObject, "state-change", "focused", true);
} else if (notification == AXSelectedChildrenChanged)
notifyChildrenSelectionChange(coreObject);
}
diff --git a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
index 726cdb1..ca0d80b 100644
--- a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
+++ b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
@@ -58,6 +58,7 @@
#include "RenderListItem.h"
#include "RenderListMarker.h"
#include "RenderText.h"
+#include "SelectElement.h"
#include "TextEncoding.h"
#include "TextIterator.h"
#include "WebKitAccessibleHyperlink.h"
@@ -500,6 +501,12 @@ static void setAtkStateSetFromCoreObject(AccessibilityObject* coreObject, AtkSta
atk_state_set_add_state(stateSet, ATK_STATE_SENSITIVE);
}
+ if (coreObject->canSetExpandedAttribute())
+ atk_state_set_add_state(stateSet, ATK_STATE_EXPANDABLE);
+
+ if (coreObject->isExpanded())
+ atk_state_set_add_state(stateSet, ATK_STATE_EXPANDED);
+
if (coreObject->canSetFocusAttribute())
atk_state_set_add_state(stateSet, ATK_STATE_FOCUSABLE);
@@ -694,13 +701,44 @@ static void atk_action_interface_init(AtkActionIface* iface)
// Selection (for controls)
+static AccessibilityObject* listObjectForSelection(AtkSelection* selection)
+{
+ AccessibilityObject* coreSelection = core(selection);
+
+ // Only list boxes and menu lists supported so far.
+ if (!coreSelection->isListBox() && !coreSelection->isMenuList())
+ return 0;
+
+ // For list boxes the list object is just itself.
+ if (coreSelection->isListBox())
+ return coreSelection;
+
+ // For menu lists we need to return the first accessible child,
+ // with role MenuListPopupRole, since that's the one holding the list
+ // of items with role MenuListOptionRole.
+ AccessibilityObject::AccessibilityChildrenVector children = coreSelection->children();
+ if (!children.size())
+ return 0;
+
+ AccessibilityObject* listObject = children.at(0).get();
+ if (!listObject->isMenuListPopup())
+ return 0;
+
+ return listObject;
+}
+
static AccessibilityObject* optionFromList(AtkSelection* selection, gint i)
{
AccessibilityObject* coreSelection = core(selection);
if (!coreSelection || i < 0)
return 0;
- AccessibilityRenderObject::AccessibilityChildrenVector options = core(selection)->children();
+ // Need to select the proper list object depending on the type.
+ AccessibilityObject* listObject = listObjectForSelection(selection);
+ if (!listObject)
+ return 0;
+
+ AccessibilityRenderObject::AccessibilityChildrenVector options = listObject->children();
if (i < static_cast<gint>(options.size()))
return options.at(i).get();
@@ -712,14 +750,26 @@ static AccessibilityObject* optionFromSelection(AtkSelection* selection, gint i)
// i is the ith selection as opposed to the ith child.
AccessibilityObject* coreSelection = core(selection);
- if (!coreSelection || i < 0)
+ if (!coreSelection || !coreSelection->isAccessibilityRenderObject() || i < 0)
return 0;
AccessibilityRenderObject::AccessibilityChildrenVector selectedItems;
if (coreSelection->isListBox())
- static_cast<AccessibilityListBox*>(coreSelection)->selectedChildren(selectedItems);
+ coreSelection->selectedChildren(selectedItems);
+ else if (coreSelection->isMenuList()) {
+ RenderObject* renderer = toAccessibilityRenderObject(coreSelection)->renderer();
+ if (!renderer)
+ return 0;
+
+ SelectElement* selectNode = toSelectElement(static_cast<Element*>(renderer->node()));
+ int selectedIndex = selectNode->selectedIndex();
+ const Vector<Element*> listItems = selectNode->listItems();
- // TODO: Combo boxes
+ if (selectedIndex < 0 || selectedIndex >= static_cast<int>(listItems.size()))
+ return 0;
+
+ return optionFromList(selection, selectedIndex);
+ }
if (i < static_cast<gint>(selectedItems.size()))
return selectedItems.at(i).get();
@@ -729,11 +779,14 @@ static AccessibilityObject* optionFromSelection(AtkSelection* selection, gint i)
static gboolean webkit_accessible_selection_add_selection(AtkSelection* selection, gint i)
{
+ AccessibilityObject* coreSelection = core(selection);
+ if (!coreSelection)
+ return false;
+
AccessibilityObject* option = optionFromList(selection, i);
- if (option && core(selection)->isListBox()) {
- AccessibilityListBoxOption* listBoxOption = static_cast<AccessibilityListBoxOption*>(option);
- listBoxOption->setSelected(true);
- return listBoxOption->isSelected();
+ if (option && (coreSelection->isListBox() || coreSelection->isMenuList())) {
+ option->setSelected(true);
+ return option->isSelected();
}
return false;
@@ -746,7 +799,7 @@ static gboolean webkit_accessible_selection_clear_selection(AtkSelection* select
return false;
AccessibilityRenderObject::AccessibilityChildrenVector selectedItems;
- if (coreSelection->isListBox()) {
+ if (coreSelection->isListBox() || coreSelection->isMenuList()) {
// Set the list of selected items to an empty list; then verify that it worked.
AccessibilityListBox* listBox = static_cast<AccessibilityListBox*>(coreSelection);
listBox->setSelectedChildren(selectedItems);
@@ -771,32 +824,54 @@ static AtkObject* webkit_accessible_selection_ref_selection(AtkSelection* select
static gint webkit_accessible_selection_get_selection_count(AtkSelection* selection)
{
AccessibilityObject* coreSelection = core(selection);
- if (coreSelection && coreSelection->isListBox()) {
+ if (!coreSelection || !coreSelection->isAccessibilityRenderObject())
+ return 0;
+
+ if (coreSelection->isListBox()) {
AccessibilityRenderObject::AccessibilityChildrenVector selectedItems;
- static_cast<AccessibilityListBox*>(coreSelection)->selectedChildren(selectedItems);
+ coreSelection->selectedChildren(selectedItems);
return static_cast<gint>(selectedItems.size());
}
+ if (coreSelection->isMenuList()) {
+ RenderObject* renderer = toAccessibilityRenderObject(coreSelection)->renderer();
+ if (!renderer)
+ return 0;
+
+ SelectElement* selectNode = toSelectElement(static_cast<Element*>(renderer->node()));
+ int selectedIndex = selectNode->selectedIndex();
+ const Vector<Element*> listItems = selectNode->listItems();
+
+ return selectedIndex >= 0 && selectedIndex < static_cast<int>(listItems.size());
+ }
+
return 0;
}
static gboolean webkit_accessible_selection_is_child_selected(AtkSelection* selection, gint i)
{
+ AccessibilityObject* coreSelection = core(selection);
+ if (!coreSelection)
+ return 0;
+
AccessibilityObject* option = optionFromList(selection, i);
- if (option && core(selection)->isListBox())
- return static_cast<AccessibilityListBoxOption*>(option)->isSelected();
+ if (option && (coreSelection->isListBox() || coreSelection->isMenuList()))
+ return option->isSelected();
return false;
}
static gboolean webkit_accessible_selection_remove_selection(AtkSelection* selection, gint i)
{
+ AccessibilityObject* coreSelection = core(selection);
+ if (!coreSelection)
+ return 0;
+
// TODO: This is only getting called if i == 0. What is preventing the rest?
AccessibilityObject* option = optionFromSelection(selection, i);
- if (option && core(selection)->isListBox()) {
- AccessibilityListBoxOption* listBoxOption = static_cast<AccessibilityListBoxOption*>(option);
- listBoxOption->setSelected(false);
- return !listBoxOption->isSelected();
+ if (option && (coreSelection->isListBox() || coreSelection->isMenuList())) {
+ option->setSelected(false);
+ return !option->isSelected();
}
return false;
@@ -969,8 +1044,11 @@ static gchar* webkit_accessible_text_get_text(AtkText* text, gint startOffset, g
if (coreObject->isTextControl())
ret = coreObject->doAXStringForRange(PlainTextRange(start, length));
- else
- ret = coreObject->textUnderElement().substring(start, length);
+ else {
+ ret = coreObject->stringValue().substring(start, length);
+ if (!ret)
+ ret = coreObject->textUnderElement().substring(start, length);
+ }
if (!ret.length()) {
// This can happen at least with anonymous RenderBlocks (e.g. body text amongst paragraphs)
@@ -1433,13 +1511,13 @@ static void getSelectionOffsetsForObject(AccessibilityObject* coreObject, Visibl
if (!coreObject->isAccessibilityRenderObject())
return;
- // Early return if the selection doesn't affect the selected node
+ // Early return if the selection doesn't affect the selected node.
if (!selectionBelongsToObject(coreObject, selection))
return;
// We need to find the exact start and end positions in the
// selected node that intersects the selection, to later on get
- // the right values for the effective start and end offsets
+ // the right values for the effective start and end offsets.
ExceptionCode ec = 0;
Position nodeRangeStart;
Position nodeRangeEnd;
@@ -1449,7 +1527,7 @@ static void getSelectionOffsetsForObject(AccessibilityObject* coreObject, Visibl
// If the selection affects the selected node and its first
// possible position is also in the selection, we must set
// nodeRangeStart to that position, otherwise to the selection's
- // start position (it would belong to the node anyway)
+ // start position (it would belong to the node anyway).
Node* firstLeafNode = node->firstDescendant();
if (selRange->isPointInRange(firstLeafNode, 0, ec))
nodeRangeStart = firstPositionInNode(firstLeafNode);
@@ -1459,16 +1537,20 @@ static void getSelectionOffsetsForObject(AccessibilityObject* coreObject, Visibl
// If the selection affects the selected node and its last
// possible position is also in the selection, we must set
// nodeRangeEnd to that position, otherwise to the selection's
- // end position (it would belong to the node anyway)
+ // end position (it would belong to the node anyway).
Node* lastLeafNode = node->lastDescendant();
if (selRange->isPointInRange(lastLeafNode, lastOffsetInNode(lastLeafNode), ec))
nodeRangeEnd = lastPositionInNode(lastLeafNode);
else
nodeRangeEnd = selRange->endPosition();
- // Set values for start and end offsets
+ // Calculate position of the selected range inside the object.
+ Position parentFirstPosition = firstPositionInNode(node);
+ RefPtr<Range> rangeInParent = Range::create(node->document(), parentFirstPosition, nodeRangeStart);
+
+ // Set values for start and end offsets.
+ startOffset = TextIterator::rangeLength(rangeInParent.get());
RefPtr<Range> nodeRange = Range::create(node->document(), nodeRangeStart, nodeRangeEnd);
- startOffset = nodeRangeStart.offsetInContainerNode();
endOffset = startOffset + TextIterator::rangeLength(nodeRange.get());
}
@@ -2173,19 +2255,23 @@ static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject)
AccessibilityRole role = coreObject->roleValue();
// Action
- if (!coreObject->actionVerb().isEmpty()) {
- interfaceMask |= 1 << WAI_ACTION;
+ // As the implementation of the AtkAction interface is a very
+ // basic one (just relays in executing the default action for each
+ // object, and only supports having one action per object), it is
+ // better just to implement this interface for every instance of
+ // the WebKitAccessible class and let WebCore decide what to do.
+ interfaceMask |= 1 << WAI_ACTION;
- if (!coreObject->accessibilityIsIgnored() && coreObject->isLink())
- interfaceMask |= 1 << WAI_HYPERLINK;
- }
+ // Hyperlink
+ if (coreObject->isLink())
+ interfaceMask |= 1 << WAI_HYPERLINK;
// Selection
- if (coreObject->isListBox())
+ if (coreObject->isListBox() || coreObject->isMenuList())
interfaceMask |= 1 << WAI_SELECTION;
// Text & Editable Text
- if (role == StaticTextRole)
+ if (role == StaticTextRole || coreObject->isMenuListOption())
interfaceMask |= 1 << WAI_TEXT;
else if (coreObject->isAccessibilityRenderObject()) {
if (coreObject->isTextControl()) {