Chromium Code Reviews| Index: Source/testing/runner/AccessibilityUIElementChromium.cpp |
| diff --git a/Source/testing/runner/AccessibilityUIElementChromium.cpp b/Source/testing/runner/AccessibilityUIElementChromium.cpp |
| index 9859ff2d2b9c395c0473514fffe93c5b4001534e..45989bffba45324ddab529f528638329be8528fd 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,108 @@ string getAttributes(const WebAXObject& object) |
| return attributes; |
| } |
| +WebRect boundsForCharacter(const WebAXObject& object, int characterIndex) |
| +{ |
| + BLINK_ASSERT(object.role() == WebAXRoleStaticText); |
| + int end = 0; |
| + for (unsigned i = 0; i < object.childCount(); i++) { |
| + WebAXObject child = object.childAt(i); |
|
aboxhall
2013/10/17 22:27:55
s/child/textBox/g ?
dmazzoni
2013/10/19 06:48:07
Done.
|
| + BLINK_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); |
| + BLINK_ASSERT(characterOffsets.size() > 0 && characterOffsets.size() == child.stringValue().length()); |
| + switch (child.textDirection()) { |
| + case WebAXTextDirectionLR: { |
| + if (localIndex) { |
|
aboxhall
2013/10/17 22:27:55
I know it's not WebKit/Blink style, but I think ex
dmazzoni
2013/10/19 06:48:07
I agree with you, but the style checker actually d
|
| + 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); |
| + } |
| + case WebAXTextDirectionRL: { |
| + int right = childRect.x + childRect.width; |
| + |
| + if (localIndex) { |
| + int left = right - characterOffsets[localIndex]; |
| + int width = characterOffsets[localIndex] - characterOffsets[localIndex - 1]; |
| + return WebRect(left, childRect.y, width, childRect.height); |
| + } |
| + int left = right - characterOffsets[0]; |
| + return WebRect(left, childRect.y, characterOffsets[0], childRect.height); |
| + } |
| + case WebAXTextDirectionTB: { |
| + if (localIndex) { |
| + int top = childRect.y + characterOffsets[localIndex - 1]; |
| + int height = characterOffsets[localIndex] - characterOffsets[localIndex - 1]; |
| + return WebRect(childRect.x, top, childRect.width, height); |
| + } |
| + return WebRect(childRect.x, childRect.y, childRect.width, characterOffsets[0]); |
| + } |
| + case WebAXTextDirectionBT: { |
| + int bottom = childRect.y + childRect.height; |
| + |
| + if (localIndex) { |
| + int top = bottom - characterOffsets[localIndex]; |
| + int height = characterOffsets[localIndex] - characterOffsets[localIndex - 1]; |
| + return WebRect(childRect.x, top, childRect.width, height); |
| + } |
| + int top = bottom - characterOffsets[0]; |
| + return WebRect(childRect.x, top, childRect.width, characterOffsets[0]); |
| + } |
| + } |
| + } |
| + |
| + BLINK_ASSERT(false); |
| + return WebRect(); |
| +} |
| + |
| +void getWordBoundaries(const WebAXObject& object, int characterIndex, int& wordStart, int& wordEnd) |
|
aboxhall
2013/10/17 22:27:55
This method name confuses me a bit - it's similar
dmazzoni
2013/10/19 06:48:07
Done.
|
| +{ |
| + int end = 0; |
| + for (unsigned i = 0; i < object.childCount(); i++) { |
| + WebAXObject child = object.childAt(i); |
|
aboxhall
2013/10/17 22:27:55
similarly, s/child/textBox/g ?
dmazzoni
2013/10/19 06:48:07
Done.
|
| + BLINK_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(); |
| + BLINK_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 +562,8 @@ AccessibilityUIElement::AccessibilityUIElement(const WebAXObject& object, Factor |
| 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 +853,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 +1168,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. |