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. |