summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/accessibility
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/accessibility')
-rw-r--r--Source/WebCore/accessibility/AXObjectCache.cpp2
-rw-r--r--Source/WebCore/accessibility/AXObjectCache.h3
-rw-r--r--Source/WebCore/accessibility/AccessibilityImageMapLink.cpp1
-rw-r--r--Source/WebCore/accessibility/AccessibilityObject.h4
-rw-r--r--Source/WebCore/accessibility/AccessibilityRenderObject.cpp47
-rw-r--r--Source/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp11
-rw-r--r--Source/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp23
-rw-r--r--Source/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp104
-rw-r--r--Source/WebCore/accessibility/gtk/WebKitAccessibleHyperlink.cpp21
-rw-r--r--Source/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm37
10 files changed, 183 insertions, 70 deletions
diff --git a/Source/WebCore/accessibility/AXObjectCache.cpp b/Source/WebCore/accessibility/AXObjectCache.cpp
index a01cb59..b471201 100644
--- a/Source/WebCore/accessibility/AXObjectCache.cpp
+++ b/Source/WebCore/accessibility/AXObjectCache.cpp
@@ -616,7 +616,7 @@ void AXObjectCache::textMarkerDataForVisiblePosition(TextMarkerData& textMarkerD
return;
if (domNode->isHTMLElement()) {
- InputElement* inputElement = toInputElement(static_cast<Element*>(domNode));
+ InputElement* inputElement = domNode->toInputElement();
if (inputElement && inputElement->isPasswordField())
return;
}
diff --git a/Source/WebCore/accessibility/AXObjectCache.h b/Source/WebCore/accessibility/AXObjectCache.h
index 4c231b5..4805a7f 100644
--- a/Source/WebCore/accessibility/AXObjectCache.h
+++ b/Source/WebCore/accessibility/AXObjectCache.h
@@ -96,7 +96,8 @@ public:
void handleScrollbarUpdate(ScrollView*);
static void enableAccessibility() { gAccessibilityEnabled = true; }
- static void enableEnhancedUserInterfaceAccessibility() { gAccessibilityEnhancedUserInterfaceEnabled = true; }
+ // Enhanced user interface accessibility can be toggled by the assistive technology.
+ static void setEnhancedUserInterfaceAccessibility(bool flag) { gAccessibilityEnhancedUserInterfaceEnabled = flag; }
static bool accessibilityEnabled() { return gAccessibilityEnabled; }
static bool accessibilityEnhancedUserInterfaceEnabled() { return gAccessibilityEnhancedUserInterfaceEnabled; }
diff --git a/Source/WebCore/accessibility/AccessibilityImageMapLink.cpp b/Source/WebCore/accessibility/AccessibilityImageMapLink.cpp
index 0844d02..a41f228 100644
--- a/Source/WebCore/accessibility/AccessibilityImageMapLink.cpp
+++ b/Source/WebCore/accessibility/AccessibilityImageMapLink.cpp
@@ -42,6 +42,7 @@ using namespace HTMLNames;
AccessibilityImageMapLink::AccessibilityImageMapLink()
: m_areaElement(0)
, m_mapElement(0)
+ , m_parent(0)
{
}
diff --git a/Source/WebCore/accessibility/AccessibilityObject.h b/Source/WebCore/accessibility/AccessibilityObject.h
index 4687cae..2d27e39 100644
--- a/Source/WebCore/accessibility/AccessibilityObject.h
+++ b/Source/WebCore/accessibility/AccessibilityObject.h
@@ -171,6 +171,10 @@ enum AccessibilityRole {
ListItemRole,
MenuListPopupRole,
MenuListOptionRole,
+ ParagraphRole,
+ LabelRole,
+ DivRole,
+ FormRole,
// ARIA Grouping roles
LandmarkApplicationRole,
diff --git a/Source/WebCore/accessibility/AccessibilityRenderObject.cpp b/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
index a626950..9b54a69 100644
--- a/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
+++ b/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
@@ -495,7 +495,7 @@ bool AccessibilityRenderObject::isPasswordField() const
if (ariaRoleAttribute() != UnknownRole)
return false;
- InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node()));
+ InputElement* inputElement = m_renderer->node()->toInputElement();
if (!inputElement)
return false;
@@ -585,10 +585,10 @@ bool AccessibilityRenderObject::isPressed() const
bool AccessibilityRenderObject::isIndeterminate() const
{
ASSERT(m_renderer);
- if (!m_renderer->node() || !m_renderer->node()->isElementNode())
+ if (!m_renderer->node())
return false;
- InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node()));
+ InputElement* inputElement = m_renderer->node()->toInputElement();
if (!inputElement)
return false;
@@ -598,8 +598,8 @@ bool AccessibilityRenderObject::isIndeterminate() const
bool AccessibilityRenderObject::isNativeCheckboxOrRadio() const
{
Node* elementNode = node();
- if (elementNode && elementNode->isElementNode()) {
- InputElement* input = toInputElement(static_cast<Element*>(elementNode));
+ if (elementNode) {
+ InputElement* input = elementNode->toInputElement();
if (input)
return input->isCheckbox() || input->isRadioButton();
}
@@ -610,11 +610,11 @@ bool AccessibilityRenderObject::isNativeCheckboxOrRadio() const
bool AccessibilityRenderObject::isChecked() const
{
ASSERT(m_renderer);
- if (!m_renderer->node() || !m_renderer->node()->isElementNode())
+ if (!m_renderer->node())
return false;
// First test for native checkedness semantics
- InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node()));
+ InputElement* inputElement = m_renderer->node()->toInputElement();
if (inputElement)
return inputElement->isChecked();
@@ -661,10 +661,10 @@ bool AccessibilityRenderObject::isReadOnly() const
return true;
HTMLElement* body = document->body();
- if (body && body->isContentEditable())
+ if (body && body->rendererIsEditable())
return false;
- return !document->inDesignMode();
+ return !document->rendererIsEditable();
}
if (m_renderer->isBoxModelObject()) {
@@ -675,7 +675,7 @@ bool AccessibilityRenderObject::isReadOnly() const
return static_cast<HTMLTextAreaElement*>(box->node())->readOnly();
}
- return !m_renderer->node() || !m_renderer->node()->isContentEditable();
+ return !m_renderer->node() || !m_renderer->node()->rendererIsEditable();
}
bool AccessibilityRenderObject::isOffScreen() const
@@ -1829,7 +1829,7 @@ bool AccessibilityRenderObject::accessibilityIsIgnored() const
return false;
// Anything that is content editable should not be ignored.
- // However, one cannot just call node->isContentEditable() since that will ask if its parents
+ // However, one cannot just call node->rendererIsEditable() since that will ask if its parents
// are also editable. Only the top level content editable region should be exposed.
if (node && node->isElementNode()) {
Element* element = static_cast<Element*>(node);
@@ -1838,6 +1838,10 @@ bool AccessibilityRenderObject::accessibilityIsIgnored() const
return false;
}
+ // List items play an important role in defining the structure of lists. They should not be ignored.
+ if (roleValue() == ListItemRole)
+ return false;
+
// if this element has aria attributes on it, it should not be ignored.
if (supportsARIAAttributes())
return false;
@@ -2401,8 +2405,8 @@ VisiblePositionRange AccessibilityRenderObject::visiblePositionRange() const
if (!node)
return VisiblePositionRange();
- VisiblePosition startPos = firstDeepEditingPositionForNode(node);
- VisiblePosition endPos = lastDeepEditingPositionForNode(node);
+ VisiblePosition startPos = firstPositionInOrBeforeNode(node);
+ VisiblePosition endPos = lastPositionInOrAfterNode(node);
// the VisiblePositions are equal for nodes like buttons, so adjust for that
// FIXME: Really? [button, 0] and [button, 1] are distinct (before and after the button)
@@ -3083,9 +3087,24 @@ AccessibilityRole AccessibilityRenderObject::determineAccessibilityRole()
#if PLATFORM(GTK)
if (m_renderer->isHR())
return SplitterRole;
+
+ if (node && node->hasTagName(pTag))
+ return ParagraphRole;
+
+ if (node && node->hasTagName(labelTag))
+ return LabelRole;
+
+ if (node && node->hasTagName(divTag))
+ return DivRole;
+
+ if (node && node->hasTagName(formTag))
+ return FormRole;
+#else
+ if (node && node->hasTagName(labelTag))
+ return GroupRole;
#endif
- if (m_renderer->isBlockFlow() || (node && node->hasTagName(labelTag)))
+ if (m_renderer->isBlockFlow())
return GroupRole;
// If the element does not have role, but it has ARIA attributes, accessibility should fallback to exposing it as a group.
diff --git a/Source/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp b/Source/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
index 0701ece..f910ca6 100644
--- a/Source/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
+++ b/Source/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
@@ -143,6 +143,17 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AX
g_signal_emit_by_name(axObject, "state-change", "focused", true);
}
notifyChildrenSelectionChange(coreObject);
+ } else if (notification == AXValueChanged) {
+ if (!ATK_IS_VALUE(axObject))
+ return;
+
+ AtkPropertyValues propertyValues;
+ propertyValues.property_name = "accessible-value";
+
+ memset(&propertyValues.new_value, 0, sizeof(GValue));
+ atk_value_get_current_value(ATK_VALUE(axObject), &propertyValues.new_value);
+
+ g_signal_emit_by_name(ATK_OBJECT(axObject), "property-change::accessible-value", &propertyValues, NULL);
}
}
diff --git a/Source/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp b/Source/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp
index c8c1951..850bcbe 100644
--- a/Source/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp
+++ b/Source/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp
@@ -43,17 +43,10 @@ AccessibilityObjectInclusion AccessibilityObject::accessibilityPlatformIncludesO
if (roleValue() == SplitterRole)
return IncludeObject;
- if (isGroup()) {
- // When a list item is made up entirely of children (e.g. paragraphs)
- // the list item gets ignored. We need it.
- if (parent->isList())
- return IncludeObject;
-
- // We expect the parent of a table cell to be a table.
- AccessibilityObject* child = firstChild();
- if (child && child->roleValue() == CellRole)
- return IgnoreObject;
- }
+ // When a list item is made up entirely of children (e.g. paragraphs)
+ // the list item gets ignored. We need it.
+ if (isGroup() && parent->isList())
+ return IncludeObject;
// Entries and password fields have extraneous children which we want to ignore.
if (parent->isPasswordField() || parent->isTextControl())
@@ -105,7 +98,13 @@ void AccessibilityObject::setWrapper(AccessibilityObjectWrapper* wrapper)
bool AccessibilityObject::allowsTextRanges() const
{
- return isTextControl() || isWebArea() || isGroup() || isLink() || isHeading() || isListItem();
+ // Check type for the AccessibilityObject.
+ if (isTextControl() || isWebArea() || isGroup() || isLink() || isHeading() || isListItem())
+ return true;
+
+ // Check roles as the last fallback mechanism.
+ AccessibilityRole role = roleValue();
+ return role == ParagraphRole || role == LabelRole || role == DivRole || role == FormRole;
}
unsigned AccessibilityObject::getLengthForTextRange() const
diff --git a/Source/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp b/Source/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
index 1d23612..7dff2e3 100644
--- a/Source/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
+++ b/Source/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
@@ -158,6 +158,11 @@ static AccessibilityObject* core(AtkDocument* document)
return core(ATK_OBJECT(document));
}
+static AccessibilityObject* core(AtkValue* value)
+{
+ return core(ATK_OBJECT(value));
+}
+
static gchar* webkit_accessible_text_get_text(AtkText* text, gint startOffset, gint endOffset);
static const gchar* webkit_accessible_get_name(AtkObject* object)
@@ -471,6 +476,14 @@ static AtkRole atkRole(AccessibilityRole role)
case ListItemRole:
case ListBoxOptionRole:
return ATK_ROLE_LIST_ITEM;
+ case ParagraphRole:
+ return ATK_ROLE_PARAGRAPH;
+ case LabelRole:
+ return ATK_ROLE_LABEL;
+ case DivRole:
+ return ATK_ROLE_SECTION;
+ case FormRole:
+ return ATK_ROLE_FORM;
default:
return ATK_ROLE_UNKNOWN;
}
@@ -478,31 +491,16 @@ static AtkRole atkRole(AccessibilityRole role)
static AtkRole webkit_accessible_get_role(AtkObject* object)
{
- AccessibilityObject* axObject = core(object);
+ AccessibilityObject* coreObject = core(object);
- if (!axObject)
+ if (!coreObject)
return ATK_ROLE_UNKNOWN;
- // WebCore does not know about paragraph role, label role, or section role
- if (axObject->isAccessibilityRenderObject()) {
- Node* node = static_cast<AccessibilityRenderObject*>(axObject)->renderer()->node();
- if (node) {
- if (node->hasTagName(HTMLNames::pTag))
- return ATK_ROLE_PARAGRAPH;
- if (node->hasTagName(HTMLNames::labelTag))
- return ATK_ROLE_LABEL;
- if (node->hasTagName(HTMLNames::divTag))
- return ATK_ROLE_SECTION;
- if (node->hasTagName(HTMLNames::formTag))
- return ATK_ROLE_FORM;
- }
- }
-
// Note: Why doesn't WebCore have a password field for this
- if (axObject->isPasswordField())
+ if (coreObject->isPasswordField())
return ATK_ROLE_PASSWORD_TEXT;
- return atkRole(axObject->roleValue());
+ return atkRole(coreObject->roleValue());
}
static bool selectionBelongsToObject(AccessibilityObject* coreObject, VisibleSelection& selection)
@@ -2301,6 +2299,63 @@ static void atk_document_interface_init(AtkDocumentIface* iface)
iface->get_document_locale = webkit_accessible_document_get_locale;
}
+
+static void webkitAccessibleValueGetCurrentValue(AtkValue* value, GValue* gValue)
+{
+ memset(gValue, 0, sizeof(GValue));
+ g_value_init(gValue, G_TYPE_DOUBLE);
+ g_value_set_double(gValue, core(value)->valueForRange());
+}
+
+static void webkitAccessibleValueGetMaximumValue(AtkValue* value, GValue* gValue)
+{
+ memset(gValue, 0, sizeof(GValue));
+ g_value_init(gValue, G_TYPE_DOUBLE);
+ g_value_set_double(gValue, core(value)->maxValueForRange());
+}
+
+static void webkitAccessibleValueGetMinimumValue(AtkValue* value, GValue* gValue)
+{
+ memset(gValue, 0, sizeof(GValue));
+ g_value_init(gValue, G_TYPE_DOUBLE);
+ g_value_set_double(gValue, core(value)->minValueForRange());
+}
+
+static gboolean webkitAccessibleValueSetCurrentValue(AtkValue* value, const GValue* gValue)
+{
+ if (!G_VALUE_HOLDS_DOUBLE(gValue) && !G_VALUE_HOLDS_INT(gValue))
+ return FALSE;
+
+ AccessibilityObject* coreObject = core(value);
+ if (!coreObject->canSetValueAttribute())
+ return FALSE;
+
+ if (G_VALUE_HOLDS_DOUBLE(gValue))
+ coreObject->setValue(String::number(g_value_get_double(gValue)));
+ else
+ coreObject->setValue(String::number(g_value_get_int(gValue)));
+
+ return TRUE;
+}
+
+static void webkitAccessibleValueGetMinimumIncrement(AtkValue* value, GValue* gValue)
+{
+ memset(gValue, 0, sizeof(GValue));
+ g_value_init(gValue, G_TYPE_DOUBLE);
+
+ // There's not such a thing in the WAI-ARIA specification, thus return zero.
+ g_value_set_double(gValue, 0.0);
+}
+
+static void atkValueInterfaceInit(AtkValueIface* iface)
+{
+ iface->get_current_value = webkitAccessibleValueGetCurrentValue;
+ iface->get_maximum_value = webkitAccessibleValueGetMaximumValue;
+ iface->get_minimum_value = webkitAccessibleValueGetMinimumValue;
+ iface->set_current_value = webkitAccessibleValueSetCurrentValue;
+ iface->get_minimum_increment = webkitAccessibleValueGetMinimumIncrement;
+}
+
static const GInterfaceInfo AtkInterfacesInitFunctions[] = {
{(GInterfaceInitFunc)atk_action_interface_init,
(GInterfaceFinalizeFunc) 0, 0},
@@ -2321,6 +2376,8 @@ static const GInterfaceInfo AtkInterfacesInitFunctions[] = {
{(GInterfaceInitFunc)atkHyperlinkImplInterfaceInit,
(GInterfaceFinalizeFunc) 0, 0},
{(GInterfaceInitFunc)atk_document_interface_init,
+ (GInterfaceFinalizeFunc) 0, 0},
+ {(GInterfaceInitFunc)atkValueInterfaceInit,
(GInterfaceFinalizeFunc) 0, 0}
};
@@ -2334,7 +2391,8 @@ enum WAIType {
WAI_TABLE,
WAI_HYPERTEXT,
WAI_HYPERLINK,
- WAI_DOCUMENT
+ WAI_DOCUMENT,
+ WAI_VALUE,
};
static GType GetAtkInterfaceTypeFromWAIType(WAIType type)
@@ -2360,6 +2418,8 @@ static GType GetAtkInterfaceTypeFromWAIType(WAIType type)
return ATK_TYPE_HYPERLINK_IMPL;
case WAI_DOCUMENT:
return ATK_TYPE_DOCUMENT;
+ case WAI_VALUE:
+ return ATK_TYPE_VALUE;
}
return G_TYPE_INVALID;
@@ -2431,6 +2491,10 @@ static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject)
if (role == WebAreaRole)
interfaceMask |= 1 << WAI_DOCUMENT;
+ // Value
+ if (role == SliderRole)
+ interfaceMask |= 1 << WAI_VALUE;
+
return interfaceMask;
}
diff --git a/Source/WebCore/accessibility/gtk/WebKitAccessibleHyperlink.cpp b/Source/WebCore/accessibility/gtk/WebKitAccessibleHyperlink.cpp
index 5927430..b9e483c 100644
--- a/Source/WebCore/accessibility/gtk/WebKitAccessibleHyperlink.cpp
+++ b/Source/WebCore/accessibility/gtk/WebKitAccessibleHyperlink.cpp
@@ -32,6 +32,7 @@
#include "RenderListMarker.h"
#include "RenderObject.h"
#include "TextIterator.h"
+#include "htmlediting.h"
#include <atk/atk.h>
#include <glib.h>
@@ -230,11 +231,19 @@ static gint webkitAccessibleHyperlinkGetStartIndex(AtkHyperlink* link)
if (!coreObject)
return 0;
+ AccessibilityObject* parentUnignored = coreObject->parentObjectUnignored();
+ if (!parentUnignored)
+ return 0;
+
Node* node = coreObject->node();
if (!node)
return 0;
- RefPtr<Range> range = Range::create(node->document(), firstPositionInNode(node->parentNode()), firstPositionInNode(node));
+ Node* parentNode = parentUnignored->node();
+ if (!parentNode)
+ return 0;
+
+ RefPtr<Range> range = Range::create(node->document(), firstPositionInOrBeforeNode(parentNode), firstPositionInOrBeforeNode(node));
return getRangeLengthForObject(coreObject, range.get());
}
@@ -246,11 +255,19 @@ static gint webkitAccessibleHyperlinkGetEndIndex(AtkHyperlink* link)
if (!coreObject)
return 0;
+ AccessibilityObject* parentUnignored = coreObject->parentObjectUnignored();
+ if (!parentUnignored)
+ return 0;
+
Node* node = coreObject->node();
if (!node)
return 0;
- RefPtr<Range> range = Range::create(node->document(), firstPositionInNode(node->parentNode()), lastPositionInNode(node));
+ Node* parentNode = parentUnignored->node();
+ if (!parentNode)
+ return 0;
+
+ RefPtr<Range> range = Range::create(node->document(), firstPositionInOrBeforeNode(parentNode), lastPositionInOrAfterNode(node));
return getRangeLengthForObject(coreObject, range.get());
}
diff --git a/Source/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm b/Source/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
index a71ccd4..c0dd795 100644
--- a/Source/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
+++ b/Source/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
@@ -41,6 +41,7 @@
#import "AccessibilityTableCell.h"
#import "AccessibilityTableRow.h"
#import "AccessibilityTableColumn.h"
+#import "Chrome.h"
#import "ColorMac.h"
#import "Frame.h"
#import "FrameLoaderClient.h"
@@ -1286,7 +1287,11 @@ static const AccessibilityRoleMap& createAccessibilityRoleMap()
{ TabPanelRole, NSAccessibilityGroupRole },
{ TreeRole, NSAccessibilityOutlineRole },
{ TreeItemRole, NSAccessibilityRowRole },
- { ListItemRole, NSAccessibilityGroupRole }
+ { ListItemRole, NSAccessibilityGroupRole },
+ { ParagraphRole, NSAccessibilityGroupRole },
+ { LabelRole, NSAccessibilityGroupRole },
+ { DivRole, NSAccessibilityGroupRole },
+ { FormRole, NSAccessibilityGroupRole }
};
AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
@@ -2330,28 +2335,20 @@ static NSString* roleValueToNSString(AccessibilityRole value)
FrameView* frameView = m_object->documentFrameView();
if (!frameView)
return;
+ Frame* frame = frameView->frame();
+ if (!frame)
+ return;
+ Page* page = frame->page();
+ if (!page)
+ return;
- // simulate a click in the middle of the object
+ // Simulate a click in the middle of the object.
IntPoint clickPoint = m_object->clickPoint();
- NSPoint nsClickPoint = NSMakePoint(clickPoint.x(), clickPoint.y());
-
- NSView* view = nil;
- if (m_object->isAttachment())
- view = [self attachmentView];
- else
- view = frameView->documentView();
-
- if (!view)
- return;
-
- NSPoint nsScreenPoint = [view convertPoint:nsClickPoint toView:nil];
-
- // Show the contextual menu for this event.
- NSEvent* event = [NSEvent mouseEventWithType:NSRightMouseDown location:nsScreenPoint modifierFlags:0 timestamp:0 windowNumber:[[view window] windowNumber] context:0 eventNumber:0 clickCount:1 pressure:1];
- NSMenu* menu = [view menuForEvent:event];
- if (menu)
- [NSMenu popUpContextMenu:menu withEvent:event forView:view];
+ PlatformMouseEvent mouseEvent(clickPoint, clickPoint, RightButton, MouseEventPressed, 1, false, false, false, false, currentTime());
+ bool handled = frame->eventHandler()->sendContextMenuEvent(mouseEvent);
+ if (handled)
+ page->chrome()->showContextMenu();
}
- (void)accessibilityPerformAction:(NSString*)action