AccessibilityObject.cpp [plain text]
#include "config.h"
#include "AccessibilityObject.h"
#include "AccessibilityRenderObject.h"
#include "AXObjectCache.h"
#include "CharacterNames.h"
#include "FloatRect.h"
#include "FocusController.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "LocalizedStrings.h"
#include "NodeList.h"
#include "NotImplemented.h"
#include "Page.h"
#include "RenderImage.h"
#include "RenderListMarker.h"
#include "RenderMenuList.h"
#include "RenderTextControl.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "RenderWidget.h"
#include "SelectionController.h"
#include "TextIterator.h"
#include "htmlediting.h"
#include "visible_units.h"
#include <wtf/StdLibExtras.h>
using namespace std;
namespace WebCore {
using namespace HTMLNames;
AccessibilityObject::AccessibilityObject()
: m_id(0)
, m_haveChildren(false)
#if PLATFORM(GTK)
, m_wrapper(0)
#endif
{
}
AccessibilityObject::~AccessibilityObject()
{
ASSERT(isDetached());
}
void AccessibilityObject::detach()
{
removeAXObjectID();
#if HAVE(ACCESSIBILITY)
setWrapper(0);
#endif
}
AccessibilityObject* AccessibilityObject::firstChild() const
{
return 0;
}
AccessibilityObject* AccessibilityObject::lastChild() const
{
return 0;
}
AccessibilityObject* AccessibilityObject::previousSibling() const
{
return 0;
}
AccessibilityObject* AccessibilityObject::nextSibling() const
{
return 0;
}
AccessibilityObject* AccessibilityObject::parentObject() const
{
return 0;
}
AccessibilityObject* AccessibilityObject::parentObjectUnignored() const
{
AccessibilityObject* parent;
for (parent = parentObject(); parent && parent->accessibilityIsIgnored(); parent = parent->parentObject())
;
return parent;
}
int AccessibilityObject::layoutCount() const
{
return 0;
}
String AccessibilityObject::text() const
{
return String();
}
String AccessibilityObject::helpText() const
{
return String();
}
String AccessibilityObject::textUnderElement() const
{
return String();
}
bool AccessibilityObject::isARIAInput(AccessibilityRole ariaRole)
{
return ariaRole == RadioButtonRole || ariaRole == CheckBoxRole || ariaRole == TextFieldRole;
}
bool AccessibilityObject::isARIAControl(AccessibilityRole ariaRole)
{
return isARIAInput(ariaRole) || ariaRole == TextAreaRole || ariaRole == ButtonRole
|| ariaRole == ComboBoxRole || ariaRole == SliderRole;
}
int AccessibilityObject::intValue() const
{
return 0;
}
String AccessibilityObject::stringValue() const
{
return String();
}
String AccessibilityObject::ariaAccessiblityName(const String&) const
{
return String();
}
String AccessibilityObject::ariaLabeledByAttribute() const
{
return String();
}
String AccessibilityObject::title() const
{
return String();
}
String AccessibilityObject::ariaDescribedByAttribute() const
{
return String();
}
String AccessibilityObject::accessibilityDescription() const
{
return String();
}
IntRect AccessibilityObject::boundingBoxRect() const
{
return IntRect();
}
IntRect AccessibilityObject::elementRect() const
{
return IntRect();
}
IntSize AccessibilityObject::size() const
{
return IntSize();
}
IntPoint AccessibilityObject::clickPoint() const
{
IntRect rect = elementRect();
return IntPoint(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2);
}
void AccessibilityObject::linkedUIElements(AccessibilityChildrenVector&) const
{
return;
}
AccessibilityObject* AccessibilityObject::titleUIElement() const
{
return 0;
}
int AccessibilityObject::textLength() const
{
return 0;
}
PassRefPtr<Range> AccessibilityObject::ariaSelectedTextDOMRange() const
{
return 0;
}
String AccessibilityObject::selectedText() const
{
return String();
}
const AtomicString& AccessibilityObject::accessKey() const
{
return nullAtom;
}
Selection AccessibilityObject::selection() const
{
return Selection();
}
PlainTextRange AccessibilityObject::selectedTextRange() const
{
return PlainTextRange();
}
unsigned AccessibilityObject::selectionStart() const
{
return selectedTextRange().start;
}
unsigned AccessibilityObject::selectionEnd() const
{
return selectedTextRange().length;
}
void AccessibilityObject::setSelectedText(const String&)
{
notImplemented();
}
void AccessibilityObject::setSelectedTextRange(const PlainTextRange&)
{
}
void AccessibilityObject::makeRangeVisible(const PlainTextRange&)
{
notImplemented();
}
KURL AccessibilityObject::url() const
{
return KURL();
}
void AccessibilityObject::setFocused(bool)
{
}
void AccessibilityObject::setValue(const String&)
{
}
void AccessibilityObject::setSelected(bool)
{
}
bool AccessibilityObject::press() const
{
Element* actionElem = actionElement();
if (!actionElem)
return false;
if (Frame* f = actionElem->document()->frame())
f->loader()->resetMultipleFormSubmissionProtection();
actionElem->accessKeyAction(true);
return true;
}
String AccessibilityObject::language() const
{
AccessibilityObject* parent = parentObject();
if (!parent) {
Document* doc = document();
if (doc)
return doc->contentLanguage();
return String();
}
return parent->language();
}
AXObjectCache* AccessibilityObject::axObjectCache() const
{
return 0;
}
Widget* AccessibilityObject::widget() const
{
return 0;
}
Widget* AccessibilityObject::widgetForAttachmentView() const
{
return 0;
}
Element* AccessibilityObject::anchorElement() const
{
return 0;
}
Element* AccessibilityObject::actionElement() const
{
return 0;
}
VisiblePositionRange AccessibilityObject::visiblePositionRange() const
{
return VisiblePositionRange();
}
VisiblePositionRange AccessibilityObject::visiblePositionRangeForLine(unsigned) const
{
return VisiblePositionRange();
}
VisiblePosition AccessibilityObject::visiblePositionForIndex(int) const
{
return VisiblePosition();
}
int AccessibilityObject::indexForVisiblePosition(const VisiblePosition&) const
{
return 0;
}
VisiblePositionRange AccessibilityObject::visiblePositionRangeForUnorderedPositions(const VisiblePosition& visiblePos1, const VisiblePosition& visiblePos2) const
{
if (visiblePos1.isNull() || visiblePos2.isNull())
return VisiblePositionRange();
VisiblePosition startPos;
VisiblePosition endPos;
bool alreadyInOrder;
if (visiblePos1 == visiblePos2 && visiblePos2.affinity() == UPSTREAM)
alreadyInOrder = false;
else
alreadyInOrder = Selection(visiblePos1, visiblePos2).isBaseFirst();
if (alreadyInOrder) {
startPos = visiblePos1;
endPos = visiblePos2;
} else {
startPos = visiblePos2;
endPos = visiblePos1;
}
return VisiblePositionRange(startPos, endPos);
}
VisiblePositionRange AccessibilityObject::positionOfLeftWord(const VisiblePosition& visiblePos) const
{
VisiblePosition startPosition = startOfWord(visiblePos, LeftWordIfOnBoundary);
VisiblePosition endPosition = endOfWord(startPosition);
return VisiblePositionRange(startPosition, endPosition);
}
VisiblePositionRange AccessibilityObject::positionOfRightWord(const VisiblePosition& visiblePos) const
{
VisiblePosition startPosition = startOfWord(visiblePos, RightWordIfOnBoundary);
VisiblePosition endPosition = endOfWord(startPosition);
return VisiblePositionRange(startPosition, endPosition);
}
static VisiblePosition updateAXLineStartForVisiblePosition(const VisiblePosition& visiblePosition)
{
VisiblePosition tempPosition;
VisiblePosition startPosition = visiblePosition;
Position p;
RenderObject* renderer;
while (true) {
tempPosition = startPosition.previous();
if (tempPosition.isNull())
break;
p = tempPosition.deepEquivalent();
if (!p.node())
break;
renderer = p.node()->renderer();
if (!renderer || renderer->isRenderBlock() && !p.offset())
break;
InlineBox* box;
int ignoredCaretOffset;
p.getInlineBoxAndOffset(tempPosition.affinity(), box, ignoredCaretOffset);
if (box)
break;
startPosition = tempPosition;
}
return startPosition;
}
VisiblePositionRange AccessibilityObject::leftLineVisiblePositionRange(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePositionRange();
VisiblePosition prevVisiblePos = visiblePos.previous();
if (prevVisiblePos.isNull())
return VisiblePositionRange();
VisiblePosition startPosition = startOfLine(prevVisiblePos);
if (startPosition.isNull()) {
while (startPosition.isNull() && prevVisiblePos.isNotNull()) {
prevVisiblePos = prevVisiblePos.previous();
startPosition = startOfLine(prevVisiblePos);
}
} else
startPosition = updateAXLineStartForVisiblePosition(startPosition);
VisiblePosition endPosition = endOfLine(prevVisiblePos);
return VisiblePositionRange(startPosition, endPosition);
}
VisiblePositionRange AccessibilityObject::rightLineVisiblePositionRange(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePositionRange();
VisiblePosition nextVisiblePos = visiblePos.next();
if (nextVisiblePos.isNull())
return VisiblePositionRange();
VisiblePosition startPosition = startOfLine(nextVisiblePos);
if (startPosition.isNull() ) {
startPosition = visiblePos;
nextVisiblePos = nextVisiblePos.next();
} else
startPosition = updateAXLineStartForVisiblePosition(startPosition);
VisiblePosition endPosition = endOfLine(nextVisiblePos);
while (endPosition.isNull() && nextVisiblePos.isNotNull()) {
nextVisiblePos = nextVisiblePos.next();
endPosition = endOfLine(nextVisiblePos);
}
return VisiblePositionRange(startPosition, endPosition);
}
VisiblePositionRange AccessibilityObject::sentenceForPosition(const VisiblePosition& visiblePos) const
{
VisiblePosition startPosition = startOfSentence(visiblePos);
VisiblePosition endPosition = endOfSentence(startPosition);
return VisiblePositionRange(startPosition, endPosition);
}
VisiblePositionRange AccessibilityObject::paragraphForPosition(const VisiblePosition& visiblePos) const
{
VisiblePosition startPosition = startOfParagraph(visiblePos);
VisiblePosition endPosition = endOfParagraph(startPosition);
return VisiblePositionRange(startPosition, endPosition);
}
static VisiblePosition startOfStyleRange(const VisiblePosition visiblePos)
{
RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer();
RenderObject* startRenderer = renderer;
RenderStyle* style = renderer->style();
for (RenderObject* r = renderer->previousInPreOrder(); r; r = r->previousInPreOrder()) {
if (r->firstChild())
continue;
if (r->style() != style)
break;
startRenderer = r;
}
return VisiblePosition(startRenderer->node(), 0, VP_DEFAULT_AFFINITY);
}
static VisiblePosition endOfStyleRange(const VisiblePosition visiblePos)
{
RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer();
RenderObject* endRenderer = renderer;
RenderStyle* style = renderer->style();
for (RenderObject* r = renderer->nextInPreOrder(); r; r = r->nextInPreOrder()) {
if (r->firstChild())
continue;
if (r->style() != style)
break;
endRenderer = r;
}
return VisiblePosition(endRenderer->node(), maxDeepOffset(endRenderer->node()), VP_DEFAULT_AFFINITY);
}
VisiblePositionRange AccessibilityObject::styleRangeForPosition(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePositionRange();
return VisiblePositionRange(startOfStyleRange(visiblePos), endOfStyleRange(visiblePos));
}
VisiblePositionRange AccessibilityObject::visiblePositionRangeForRange(const PlainTextRange& range) const
{
if (range.start + range.length > text().length())
return VisiblePositionRange();
VisiblePosition startPosition = visiblePositionForIndex(range.start);
startPosition.setAffinity(DOWNSTREAM);
VisiblePosition endPosition = visiblePositionForIndex(range.start + range.length);
return VisiblePositionRange(startPosition, endPosition);
}
static bool replacedNodeNeedsCharacter(Node* replacedNode)
{
if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {
return false;
}
AccessibilityObject* object = replacedNode->renderer()->document()->axObjectCache()->get(replacedNode->renderer());
if (object->accessibilityIsIgnored())
return false;
return true;
}
String AccessibilityObject::stringForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const
{
if (visiblePositionRange.isNull())
return String();
Vector<UChar> resultVector;
RefPtr<Range> range = makeRange(visiblePositionRange.start, visiblePositionRange.end);
for (TextIterator it(range.get()); !it.atEnd(); it.advance()) {
if (it.length() != 0) {
resultVector.append(it.characters(), it.length());
} else {
int exception = 0;
Node* node = it.range()->startContainer(exception);
ASSERT(node == it.range()->endContainer(exception));
int offset = it.range()->startOffset(exception);
if (replacedNodeNeedsCharacter(node->childNode(offset))) {
resultVector.append(objectReplacementCharacter);
}
}
}
return String::adopt(resultVector);
}
IntRect AccessibilityObject::boundsForVisiblePositionRange(const VisiblePositionRange&) const
{
return IntRect();
}
int AccessibilityObject::lengthForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const
{
if (visiblePositionRange.isNull())
return -1;
int length = 0;
RefPtr<Range> range = makeRange(visiblePositionRange.start, visiblePositionRange.end);
for (TextIterator it(range.get()); !it.atEnd(); it.advance()) {
if (it.length() != 0) {
length += it.length();
} else {
int exception = 0;
Node* node = it.range()->startContainer(exception);
ASSERT(node == it.range()->endContainer(exception));
int offset = it.range()->startOffset(exception);
if (replacedNodeNeedsCharacter(node->childNode(offset)))
length++;
}
}
return length;
}
void AccessibilityObject::setSelectedVisiblePositionRange(const VisiblePositionRange&) const
{
}
VisiblePosition AccessibilityObject::visiblePositionForPoint(const IntPoint&) const
{
return VisiblePosition();
}
VisiblePosition AccessibilityObject::nextVisiblePosition(const VisiblePosition& visiblePos) const
{
return visiblePos.next();
}
VisiblePosition AccessibilityObject::previousVisiblePosition(const VisiblePosition& visiblePos) const
{
return visiblePos.previous();
}
VisiblePosition AccessibilityObject::nextWordEnd(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePosition();
VisiblePosition nextVisiblePos = visiblePos.next();
if (nextVisiblePos.isNull())
return VisiblePosition();
return endOfWord(nextVisiblePos, LeftWordIfOnBoundary);
}
VisiblePosition AccessibilityObject::previousWordStart(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePosition();
VisiblePosition prevVisiblePos = visiblePos.previous();
if (prevVisiblePos.isNull())
return VisiblePosition();
return startOfWord(prevVisiblePos, RightWordIfOnBoundary);
}
VisiblePosition AccessibilityObject::nextLineEndPosition(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePosition();
VisiblePosition nextVisiblePos = visiblePos.next();
if (nextVisiblePos.isNull())
return VisiblePosition();
VisiblePosition endPosition = endOfLine(nextVisiblePos);
while (endPosition.isNull() && nextVisiblePos.isNotNull()) {
nextVisiblePos = nextVisiblePos.next();
endPosition = endOfLine(nextVisiblePos);
}
return endPosition;
}
VisiblePosition AccessibilityObject::previousLineStartPosition(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePosition();
VisiblePosition prevVisiblePos = visiblePos.previous();
if (prevVisiblePos.isNull())
return VisiblePosition();
VisiblePosition startPosition = startOfLine(prevVisiblePos);
if (startPosition.isNull()) {
while (startPosition.isNull() && prevVisiblePos.isNotNull()) {
prevVisiblePos = prevVisiblePos.previous();
startPosition = startOfLine(prevVisiblePos);
}
} else
startPosition = updateAXLineStartForVisiblePosition(startPosition);
return startPosition;
}
VisiblePosition AccessibilityObject::nextSentenceEndPosition(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePosition();
VisiblePosition nextVisiblePos = visiblePos.next();
if (nextVisiblePos.isNull())
return VisiblePosition();
VisiblePosition endPosition;
String lineString = plainText(makeRange(startOfLine(nextVisiblePos), endOfLine(nextVisiblePos)).get());
if (lineString.isEmpty())
endPosition = nextVisiblePos;
else
endPosition = endOfSentence(nextVisiblePos);
return endPosition;
}
VisiblePosition AccessibilityObject::previousSentenceStartPosition(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePosition();
VisiblePosition previousVisiblePos = visiblePos.previous();
if (previousVisiblePos.isNull())
return VisiblePosition();
VisiblePosition startPosition;
String lineString = plainText(makeRange(startOfLine(previousVisiblePos), endOfLine(previousVisiblePos)).get());
if (lineString.isEmpty())
startPosition = previousVisiblePos;
else
startPosition = startOfSentence(previousVisiblePos);
return startPosition;
}
VisiblePosition AccessibilityObject::nextParagraphEndPosition(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePosition();
VisiblePosition nextPos = visiblePos.next();
if (nextPos.isNull())
return VisiblePosition();
return endOfParagraph(nextPos);
}
VisiblePosition AccessibilityObject::previousParagraphStartPosition(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return VisiblePosition();
VisiblePosition previousPos = visiblePos.previous();
if (previousPos.isNull())
return VisiblePosition();
return startOfParagraph(previousPos);
}
VisiblePosition AccessibilityObject::visiblePositionForIndex(unsigned, bool) const
{
return VisiblePosition();
}
AccessibilityObject* AccessibilityObject::accessibilityObjectForPosition(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return 0;
RenderObject* obj = visiblePos.deepEquivalent().node()->renderer();
if (!obj)
return 0;
return obj->document()->axObjectCache()->get(obj);
}
int AccessibilityObject::lineForPosition(const VisiblePosition& visiblePos) const
{
if (visiblePos.isNull())
return 0;
unsigned lineCount = 0;
VisiblePosition currentVisiblePos = visiblePos;
VisiblePosition savedVisiblePos;
while (currentVisiblePos.isNotNull() && !(inSameLine(currentVisiblePos, savedVisiblePos))) {
++lineCount;
savedVisiblePos = currentVisiblePos;
VisiblePosition prevVisiblePos = previousLinePosition(currentVisiblePos, 0);
currentVisiblePos = prevVisiblePos;
}
return lineCount - 1;
}
PlainTextRange AccessibilityObject::plainTextRangeForVisiblePositionRange(const VisiblePositionRange& positionRange) const
{
int index1 = index(positionRange.start);
int index2 = index(positionRange.end);
if (index1 < 0 || index2 < 0 || index1 > index2)
return PlainTextRange();
return PlainTextRange(index1, index2 - index1);
}
int AccessibilityObject::index(const VisiblePosition&) const
{
return -1;
}
PlainTextRange AccessibilityObject::doAXRangeForLine(unsigned) const
{
return PlainTextRange();
}
PlainTextRange AccessibilityObject::doAXRangeForPosition(const IntPoint& point) const
{
int i = index(visiblePositionForPoint(point));
if (i < 0)
return PlainTextRange();
return PlainTextRange(i, 1);
}
PlainTextRange AccessibilityObject::doAXRangeForIndex(unsigned) const
{
return PlainTextRange();
}
PlainTextRange AccessibilityObject::doAXStyleRangeForIndex(unsigned index) const
{
VisiblePositionRange range = styleRangeForPosition(visiblePositionForIndex(index, false));
return plainTextRangeForVisiblePositionRange(range);
}
String AccessibilityObject::doAXStringForRange(const PlainTextRange&) const
{
return String();
}
IntRect AccessibilityObject::doAXBoundsForRange(const PlainTextRange&) const
{
return IntRect();
}
unsigned AccessibilityObject::doAXLineForIndex(unsigned index)
{
return lineForPosition(visiblePositionForIndex(index, false));
}
FrameView* AccessibilityObject::documentFrameView() const
{
const AccessibilityObject* object = this;
while (object && !object->isAccessibilityRenderObject())
object = object->parentObject();
if (!object)
return 0;
return object->documentFrameView();
}
AccessibilityObject* AccessibilityObject::doAccessibilityHitTest(const IntPoint&) const
{
return 0;
}
AccessibilityObject* AccessibilityObject::focusedUIElement() const
{
return 0;
}
AccessibilityObject* AccessibilityObject::observableObject() const
{
return 0;
}
AccessibilityRole AccessibilityObject::roleValue() const
{
return UnknownRole;
}
AccessibilityRole AccessibilityObject::ariaRoleAttribute() const
{
return UnknownRole;
}
bool AccessibilityObject::isPresentationalChildOfAriaRole() const
{
return false;
}
bool AccessibilityObject::ariaRoleHasPresentationalChildren() const
{
return false;
}
void AccessibilityObject::clearChildren()
{
m_haveChildren = false;
m_children.clear();
}
void AccessibilityObject::childrenChanged()
{
return;
}
void AccessibilityObject::addChildren()
{
}
void AccessibilityObject::selectedChildren(AccessibilityChildrenVector&)
{
}
void AccessibilityObject::visibleChildren(AccessibilityChildrenVector&)
{
}
unsigned AccessibilityObject::axObjectID() const
{
return m_id;
}
void AccessibilityObject::setAXObjectID(unsigned axObjectID)
{
m_id = axObjectID;
}
void AccessibilityObject::removeAXObjectID()
{
return;
}
const String& AccessibilityObject::actionVerb() const
{
DEFINE_STATIC_LOCAL(const String, noAction, ());
return noAction;
}
void AccessibilityObject::updateBackingStore()
{
}
}