📄 accessibilityobject.cpp
字号:
} VisiblePositionRange AccessibilityObject::visiblePositionRangeForUnorderedPositions(const VisiblePosition& visiblePos1, const VisiblePosition& visiblePos2) const{ if (visiblePos1.isNull() || visiblePos2.isNull()) return VisiblePositionRange(); VisiblePosition startPos; VisiblePosition endPos; bool alreadyInOrder; // upstream is ordered before downstream for the same position if (visiblePos1 == visiblePos2 && visiblePos2.affinity() == UPSTREAM) alreadyInOrder = false; // use selection order to see if the positions are in order else alreadyInOrder = VisibleSelection(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){ // A line in the accessibility sense should include floating objects, such as aligned image, as part of a line. // So let's update the position to include that. 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(); // make a caret selection for the position before marker position (to make sure // we move off of a line start) VisiblePosition prevVisiblePos = visiblePos.previous(); if (prevVisiblePos.isNull()) return VisiblePositionRange(); VisiblePosition startPosition = startOfLine(prevVisiblePos); // keep searching for a valid line start position. Unless the VisiblePosition is at the very beginning, there should // always be a valid line range. However, startOfLine will return null for position next to a floating object, // since floating object doesn't really belong to any line. // This check will reposition the marker before the floating object, to ensure we get a line start. 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(); // make sure we move off of a line end VisiblePosition nextVisiblePos = visiblePos.next(); if (nextVisiblePos.isNull()) return VisiblePositionRange(); VisiblePosition startPosition = startOfLine(nextVisiblePos); // fetch for a valid line start position if (startPosition.isNull() ) { startPosition = visiblePos; nextVisiblePos = nextVisiblePos.next(); } else startPosition = updateAXLineStartForVisiblePosition(startPosition); VisiblePosition endPosition = endOfLine(nextVisiblePos); // as long as the position hasn't reached the end of the doc, keep searching for a valid line end position // Unless the VisiblePosition is at the very end, there should always be a valid line range. However, endOfLine will // return null for position by a floating object, since floating object doesn't really belong to any line. // This check will reposition the marker after the floating object, to ensure we get a line end. while (endPosition.isNull() && nextVisiblePos.isNotNull()) { nextVisiblePos = nextVisiblePos.next(); endPosition = endOfLine(nextVisiblePos); } return VisiblePositionRange(startPosition, endPosition);}VisiblePositionRange AccessibilityObject::sentenceForPosition(const VisiblePosition& visiblePos) const{ // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer) // Related? <rdar://problem/3927736> Text selection broken in 8A336 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(); // traverse backward by renderer to look for style change for (RenderObject* r = renderer->previousInPreOrder(); r; r = r->previousInPreOrder()) { // skip non-leaf nodes if (r->firstChild()) continue; // stop at style change if (r->style() != style) break; // remember match 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(); // traverse forward by renderer to look for style change for (RenderObject* r = renderer->nextInPreOrder(); r; r = r->nextInPreOrder()) { // skip non-leaf nodes if (r->firstChild()) continue; // stop at style change if (r->style() != style) break; // remember match 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));}// NOTE: Consider providing this utility method as AX APIVisiblePositionRange 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){ // we should always be given a rendered node and a replaced node, but be safe // replaced nodes are either attachments (widgets) or images if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) { return false; } // create an AX object, but skip it if it is not supposed to be seen AccessibilityObject* object = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(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()) { // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX) if (it.length() != 0) { resultVector.append(it.characters(), it.length()); } else { // locate the node and starting offset for this replaced range 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{ // FIXME: Multi-byte support 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()) { // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX) if (it.length() != 0) { length += it.length(); } else { // locate the node and starting offset for this replaced range 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(); // make sure we move off of a word end 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(); // make sure we move off of a word start 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(); // to make sure we move off of a line end VisiblePosition nextVisiblePos = visiblePos.next(); if (nextVisiblePos.isNull()) return VisiblePosition();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -