| Index: Source/testing/runner/AccessibilityUIElementChromium.cpp
|
| diff --git a/Source/testing/runner/AccessibilityUIElementChromium.cpp b/Source/testing/runner/AccessibilityUIElementChromium.cpp
|
| index e48d75c71f9b12f4821fb8d9766f186ba26a7ef3..0483968d4592ae76e5a84415da9ff061a908c885 100644
|
| --- a/Source/testing/runner/AccessibilityUIElementChromium.cpp
|
| +++ b/Source/testing/runner/AccessibilityUIElementChromium.cpp
|
| @@ -132,6 +132,8 @@ string roleToString(WebAXRole role)
|
| return result.append("Image");
|
| case WebAXRoleIncrementor:
|
| return result.append("Incrementor");
|
| + case WebAXRoleInlineTextBox:
|
| + return result.append("InlineTextBox");
|
| case WebAXRoleLabel:
|
| return result.append("Label");
|
| case WebAXRoleLegend:
|
| @@ -345,6 +347,87 @@ string getAttributes(const WebAccessibilityObject& object)
|
| return attributes;
|
| }
|
|
|
| +WebRect boundsForCharacter(const WebAccessibilityObject& object, int characterIndex)
|
| +{
|
| + WEBKIT_ASSERT(object.role() == WebAXRoleStaticText);
|
| + int end = 0;
|
| + for (unsigned i = 0; i < object.childCount(); i++) {
|
| + WebAccessibilityObject child = object.childAt(i);
|
| + WEBKIT_ASSERT(child.role() == WebAXRoleInlineTextBox);
|
| + int start = end;
|
| + end += child.stringValue().length();
|
| + if (end <= characterIndex)
|
| + continue;
|
| + WebRect childRect = child.boundingBoxRect();
|
| + int localIndex = characterIndex - start;
|
| + WebVector<int> characterOffsets;
|
| + child.characterOffsets(characterOffsets);
|
| + WEBKIT_ASSERT(characterOffsets.size() > 0 && characterOffsets.size() == child.stringValue().length());
|
| + if (characterOffsets[characterOffsets.size() - 1] < 0) {
|
| + // RTL.
|
| + int right = childRect.x + childRect.width;
|
| +
|
| + if (localIndex) {
|
| + int left = right + characterOffsets[localIndex];
|
| + int width = characterOffsets[localIndex - 1] - characterOffsets[localIndex];
|
| + return WebRect(left, childRect.y, width, childRect.height);
|
| + }
|
| + int left = right + characterOffsets[0];
|
| + return WebRect(left, childRect.y, -characterOffsets[0], childRect.height);
|
| + }
|
| +
|
| + if (localIndex) {
|
| + int left = childRect.x + characterOffsets[localIndex - 1];
|
| + int width = characterOffsets[localIndex] - characterOffsets[localIndex - 1];
|
| + return WebRect(left, childRect.y, width, childRect.height);
|
| + }
|
| + return WebRect(childRect.x, childRect.y, characterOffsets[0], childRect.height);
|
| + }
|
| +
|
| + WEBKIT_ASSERT(false);
|
| + return WebRect();
|
| +}
|
| +
|
| +void getWordBoundaries(const WebAccessibilityObject& object, int characterIndex, int& wordStart, int& wordEnd)
|
| +{
|
| + int end = 0;
|
| + for (unsigned i = 0; i < object.childCount(); i++) {
|
| + WebAccessibilityObject child = object.childAt(i);
|
| + WEBKIT_ASSERT(child.role() == WebAXRoleInlineTextBox);
|
| + int start = end;
|
| + end += child.stringValue().length();
|
| + if (end <= characterIndex)
|
| + continue;
|
| + int localIndex = characterIndex - start;
|
| +
|
| + WebVector<int> starts;
|
| + WebVector<int> ends;
|
| + child.wordBoundaries(starts, ends);
|
| + size_t wordCount = starts.size();
|
| + WEBKIT_ASSERT(ends.size() == wordCount);
|
| +
|
| + // If there are no words, use the InlineTextBox boundaries.
|
| + if (!wordCount) {
|
| + wordStart = start;
|
| + wordEnd = end;
|
| + return;
|
| + }
|
| +
|
| + // Look for a character within any word other than the last.
|
| + for (size_t j = 0; j < wordCount - 1; j++) {
|
| + if (localIndex <= ends[j]) {
|
| + wordStart = start + starts[j];
|
| + wordEnd = start + ends[j];
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // Return the last word by default.
|
| + wordStart = start + starts[wordCount - 1];
|
| + wordEnd = start + ends[wordCount - 1];
|
| + return;
|
| + }
|
| +}
|
|
|
| // Collects attributes into a string, delimited by dashes. Used by all methods
|
| // that output lists of attributes: attributesOfLinkedUIElementsCallback,
|
| @@ -458,6 +541,8 @@ AccessibilityUIElement::AccessibilityUIElement(const WebAccessibilityObject& obj
|
| bindMethod("scrollToMakeVisible", &AccessibilityUIElement::scrollToMakeVisibleCallback);
|
| bindMethod("scrollToMakeVisibleWithSubFocus", &AccessibilityUIElement::scrollToMakeVisibleWithSubFocusCallback);
|
| bindMethod("scrollToGlobalPoint", &AccessibilityUIElement::scrollToGlobalPointCallback);
|
| + bindMethod("wordStart", &AccessibilityUIElement::wordStartCallback);
|
| + bindMethod("wordEnd", &AccessibilityUIElement::wordEndCallback);
|
|
|
| bindFallbackMethod(&AccessibilityUIElement::fallbackCallback);
|
| }
|
| @@ -747,9 +832,36 @@ void AccessibilityUIElement::lineForIndexCallback(const CppArgumentList& argumen
|
| result->set(line);
|
| }
|
|
|
| -void AccessibilityUIElement::boundsForRangeCallback(const CppArgumentList&, CppVariant* result)
|
| +void AccessibilityUIElement::boundsForRangeCallback(const CppArgumentList& arguments, CppVariant* result)
|
| {
|
| result->setNull();
|
| +
|
| + if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
|
| + return;
|
| +
|
| + if (accessibilityObject().role() != WebAXRoleStaticText)
|
| + return;
|
| +
|
| + int start = arguments[0].toInt32();
|
| + int end = arguments[1].toInt32();
|
| + int len = end - start;
|
| +
|
| + // Get the bounds for each character and union them into one large rectangle.
|
| + // This is just for testing so it doesn't need to be efficient.
|
| + WebRect bounds = boundsForCharacter(accessibilityObject(), start);
|
| + for (int i = 1; i < len; i++) {
|
| + WebRect next = boundsForCharacter(accessibilityObject(), start + i);
|
| + int right = std::max(bounds.x + bounds.width, next.x + next.width);
|
| + int bottom = std::max(bounds.y + bounds.height, next.y + next.height);
|
| + bounds.x = std::min(bounds.x, next.x);
|
| + bounds.y = std::min(bounds.y, next.y);
|
| + bounds.width = right - bounds.x;
|
| + bounds.height = bottom - bounds.y;
|
| + }
|
| +
|
| + char buffer[100];
|
| + snprintf(buffer, sizeof(buffer), "{x: %d, y: %d, width: %d, height: %d}", bounds.x, bounds.y, bounds.width, bounds.height);
|
| + result->set(string(buffer));
|
| }
|
|
|
| void AccessibilityUIElement::stringForRangeCallback(const CppArgumentList&, CppVariant* result)
|
| @@ -1035,6 +1147,38 @@ void AccessibilityUIElement::scrollToGlobalPointCallback(const CppArgumentList&
|
| result->setNull();
|
| }
|
|
|
| +void AccessibilityUIElement::wordStartCallback(const CppArgumentList& arguments, CppVariant* result)
|
| +{
|
| + result->setNull();
|
| +
|
| + if (arguments.size() != 1 || !arguments[0].isNumber())
|
| + return;
|
| +
|
| + if (accessibilityObject().role() != WebAXRoleStaticText)
|
| + return;
|
| +
|
| + int characterIndex = arguments[0].toInt32();
|
| + int wordStart, wordEnd;
|
| + getWordBoundaries(accessibilityObject(), characterIndex, wordStart, wordEnd);
|
| + result->set(wordStart);
|
| +}
|
| +
|
| +void AccessibilityUIElement::wordEndCallback(const CppArgumentList& arguments, CppVariant* result)
|
| +{
|
| + result->setNull();
|
| +
|
| + if (arguments.size() != 1 || !arguments[0].isNumber())
|
| + return;
|
| +
|
| + if (accessibilityObject().role() != WebAXRoleStaticText)
|
| + return;
|
| +
|
| + int characterIndex = arguments[0].toInt32();
|
| + int wordStart, wordEnd;
|
| + getWordBoundaries(accessibilityObject(), characterIndex, wordStart, wordEnd);
|
| + result->set(wordEnd);
|
| +}
|
| +
|
| void AccessibilityUIElement::fallbackCallback(const CppArgumentList &, CppVariant* result)
|
| {
|
| // FIXME: Implement this.
|
|
|