OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 case WebAXRoleIgnored: | 125 case WebAXRoleIgnored: |
126 return result.append("Ignored"); | 126 return result.append("Ignored"); |
127 case WebAXRoleImageMapLink: | 127 case WebAXRoleImageMapLink: |
128 return result.append("ImageMapLink"); | 128 return result.append("ImageMapLink"); |
129 case WebAXRoleImageMap: | 129 case WebAXRoleImageMap: |
130 return result.append("ImageMap"); | 130 return result.append("ImageMap"); |
131 case WebAXRoleImage: | 131 case WebAXRoleImage: |
132 return result.append("Image"); | 132 return result.append("Image"); |
133 case WebAXRoleIncrementor: | 133 case WebAXRoleIncrementor: |
134 return result.append("Incrementor"); | 134 return result.append("Incrementor"); |
| 135 case WebAXRoleInlineTextBox: |
| 136 return result.append("InlineTextBox"); |
135 case WebAXRoleLabel: | 137 case WebAXRoleLabel: |
136 return result.append("Label"); | 138 return result.append("Label"); |
137 case WebAXRoleLegend: | 139 case WebAXRoleLegend: |
138 return result.append("Legend"); | 140 return result.append("Legend"); |
139 case WebAXRoleLink: | 141 case WebAXRoleLink: |
140 return result.append("Link"); | 142 return result.append("Link"); |
141 case WebAXRoleListBoxOption: | 143 case WebAXRoleListBoxOption: |
142 return result.append("ListBoxOption"); | 144 return result.append("ListBoxOption"); |
143 case WebAXRoleListBox: | 145 case WebAXRoleListBox: |
144 return result.append("ListBox"); | 146 return result.append("ListBox"); |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 { | 340 { |
339 // FIXME: Concatenate all attributes of the AccessibilityObject. | 341 // FIXME: Concatenate all attributes of the AccessibilityObject. |
340 string attributes(getTitle(object)); | 342 string attributes(getTitle(object)); |
341 attributes.append("\n"); | 343 attributes.append("\n"); |
342 attributes.append(getRole(object)); | 344 attributes.append(getRole(object)); |
343 attributes.append("\n"); | 345 attributes.append("\n"); |
344 attributes.append(getDescription(object)); | 346 attributes.append(getDescription(object)); |
345 return attributes; | 347 return attributes; |
346 } | 348 } |
347 | 349 |
| 350 WebRect boundsForCharacter(const WebAccessibilityObject& object, int characterIn
dex) |
| 351 { |
| 352 WEBKIT_ASSERT(object.role() == WebAXRoleStaticText); |
| 353 int end = 0; |
| 354 for (unsigned i = 0; i < object.childCount(); i++) { |
| 355 WebAccessibilityObject child = object.childAt(i); |
| 356 WEBKIT_ASSERT(child.role() == WebAXRoleInlineTextBox); |
| 357 int start = end; |
| 358 end += child.stringValue().length(); |
| 359 if (end <= characterIndex) |
| 360 continue; |
| 361 WebRect childRect = child.boundingBoxRect(); |
| 362 int localIndex = characterIndex - start; |
| 363 WebVector<int> characterOffsets; |
| 364 child.characterOffsets(characterOffsets); |
| 365 WEBKIT_ASSERT(characterOffsets.size() > 0 && characterOffsets.size() ==
child.stringValue().length()); |
| 366 if (characterOffsets[characterOffsets.size() - 1] < 0) { |
| 367 // RTL. |
| 368 int right = childRect.x + childRect.width; |
| 369 |
| 370 if (localIndex) { |
| 371 int left = right + characterOffsets[localIndex]; |
| 372 int width = characterOffsets[localIndex - 1] - characterOffsets[
localIndex]; |
| 373 return WebRect(left, childRect.y, width, childRect.height); |
| 374 } |
| 375 int left = right + characterOffsets[0]; |
| 376 return WebRect(left, childRect.y, -characterOffsets[0], childRect.he
ight); |
| 377 } |
| 378 |
| 379 if (localIndex) { |
| 380 int left = childRect.x + characterOffsets[localIndex - 1]; |
| 381 int width = characterOffsets[localIndex] - characterOffsets[localInd
ex - 1]; |
| 382 return WebRect(left, childRect.y, width, childRect.height); |
| 383 } |
| 384 return WebRect(childRect.x, childRect.y, characterOffsets[0], childRect.
height); |
| 385 } |
| 386 |
| 387 WEBKIT_ASSERT(false); |
| 388 return WebRect(); |
| 389 } |
| 390 |
| 391 void getWordBoundaries(const WebAccessibilityObject& object, int characterIndex,
int& wordStart, int& wordEnd) |
| 392 { |
| 393 int end = 0; |
| 394 for (unsigned i = 0; i < object.childCount(); i++) { |
| 395 WebAccessibilityObject child = object.childAt(i); |
| 396 WEBKIT_ASSERT(child.role() == WebAXRoleInlineTextBox); |
| 397 int start = end; |
| 398 end += child.stringValue().length(); |
| 399 if (end <= characterIndex) |
| 400 continue; |
| 401 int localIndex = characterIndex - start; |
| 402 |
| 403 WebVector<int> starts; |
| 404 WebVector<int> ends; |
| 405 child.wordBoundaries(starts, ends); |
| 406 size_t wordCount = starts.size(); |
| 407 WEBKIT_ASSERT(ends.size() == wordCount); |
| 408 |
| 409 // If there are no words, use the InlineTextBox boundaries. |
| 410 if (!wordCount) { |
| 411 wordStart = start; |
| 412 wordEnd = end; |
| 413 return; |
| 414 } |
| 415 |
| 416 // Look for a character within any word other than the last. |
| 417 for (size_t j = 0; j < wordCount - 1; j++) { |
| 418 if (localIndex <= ends[j]) { |
| 419 wordStart = start + starts[j]; |
| 420 wordEnd = start + ends[j]; |
| 421 return; |
| 422 } |
| 423 } |
| 424 |
| 425 // Return the last word by default. |
| 426 wordStart = start + starts[wordCount - 1]; |
| 427 wordEnd = start + ends[wordCount - 1]; |
| 428 return; |
| 429 } |
| 430 } |
348 | 431 |
349 // Collects attributes into a string, delimited by dashes. Used by all methods | 432 // Collects attributes into a string, delimited by dashes. Used by all methods |
350 // that output lists of attributes: attributesOfLinkedUIElementsCallback, | 433 // that output lists of attributes: attributesOfLinkedUIElementsCallback, |
351 // AttributesOfChildrenCallback, etc. | 434 // AttributesOfChildrenCallback, etc. |
352 class AttributesCollector { | 435 class AttributesCollector { |
353 public: | 436 public: |
354 void collectAttributes(const WebAccessibilityObject& object) | 437 void collectAttributes(const WebAccessibilityObject& object) |
355 { | 438 { |
356 m_attributes.append("\n------------\n"); | 439 m_attributes.append("\n------------\n"); |
357 m_attributes.append(getAttributes(object)); | 440 m_attributes.append(getAttributes(object)); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 bindMethod("decrement", &AccessibilityUIElement::decrementCallback); | 534 bindMethod("decrement", &AccessibilityUIElement::decrementCallback); |
452 bindMethod("showMenu", &AccessibilityUIElement::showMenuCallback); | 535 bindMethod("showMenu", &AccessibilityUIElement::showMenuCallback); |
453 bindMethod("press", &AccessibilityUIElement::pressCallback); | 536 bindMethod("press", &AccessibilityUIElement::pressCallback); |
454 bindMethod("isEqual", &AccessibilityUIElement::isEqualCallback); | 537 bindMethod("isEqual", &AccessibilityUIElement::isEqualCallback); |
455 bindMethod("addNotificationListener", &AccessibilityUIElement::addNotificati
onListenerCallback); | 538 bindMethod("addNotificationListener", &AccessibilityUIElement::addNotificati
onListenerCallback); |
456 bindMethod("removeNotificationListener", &AccessibilityUIElement::removeNoti
ficationListenerCallback); | 539 bindMethod("removeNotificationListener", &AccessibilityUIElement::removeNoti
ficationListenerCallback); |
457 bindMethod("takeFocus", &AccessibilityUIElement::takeFocusCallback); | 540 bindMethod("takeFocus", &AccessibilityUIElement::takeFocusCallback); |
458 bindMethod("scrollToMakeVisible", &AccessibilityUIElement::scrollToMakeVisib
leCallback); | 541 bindMethod("scrollToMakeVisible", &AccessibilityUIElement::scrollToMakeVisib
leCallback); |
459 bindMethod("scrollToMakeVisibleWithSubFocus", &AccessibilityUIElement::scrol
lToMakeVisibleWithSubFocusCallback); | 542 bindMethod("scrollToMakeVisibleWithSubFocus", &AccessibilityUIElement::scrol
lToMakeVisibleWithSubFocusCallback); |
460 bindMethod("scrollToGlobalPoint", &AccessibilityUIElement::scrollToGlobalPoi
ntCallback); | 543 bindMethod("scrollToGlobalPoint", &AccessibilityUIElement::scrollToGlobalPoi
ntCallback); |
| 544 bindMethod("wordStart", &AccessibilityUIElement::wordStartCallback); |
| 545 bindMethod("wordEnd", &AccessibilityUIElement::wordEndCallback); |
461 | 546 |
462 bindFallbackMethod(&AccessibilityUIElement::fallbackCallback); | 547 bindFallbackMethod(&AccessibilityUIElement::fallbackCallback); |
463 } | 548 } |
464 | 549 |
465 AccessibilityUIElement* AccessibilityUIElement::getChildAtIndex(unsigned index) | 550 AccessibilityUIElement* AccessibilityUIElement::getChildAtIndex(unsigned index) |
466 { | 551 { |
467 return m_factory->getOrCreate(accessibilityObject().childAt(index)); | 552 return m_factory->getOrCreate(accessibilityObject().childAt(index)); |
468 } | 553 } |
469 | 554 |
470 bool AccessibilityUIElement::isEqual(const WebKit::WebAccessibilityObject& other
) | 555 bool AccessibilityUIElement::isEqual(const WebKit::WebAccessibilityObject& other
) |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 | 825 |
741 WebVector<int> lineBreaks; | 826 WebVector<int> lineBreaks; |
742 accessibilityObject().lineBreaks(lineBreaks); | 827 accessibilityObject().lineBreaks(lineBreaks); |
743 int line = 0; | 828 int line = 0; |
744 int vectorSize = static_cast<int>(lineBreaks.size()); | 829 int vectorSize = static_cast<int>(lineBreaks.size()); |
745 while (line < vectorSize && lineBreaks[line] <= index) | 830 while (line < vectorSize && lineBreaks[line] <= index) |
746 line++; | 831 line++; |
747 result->set(line); | 832 result->set(line); |
748 } | 833 } |
749 | 834 |
750 void AccessibilityUIElement::boundsForRangeCallback(const CppArgumentList&, CppV
ariant* result) | 835 void AccessibilityUIElement::boundsForRangeCallback(const CppArgumentList& argum
ents, CppVariant* result) |
751 { | 836 { |
752 result->setNull(); | 837 result->setNull(); |
| 838 |
| 839 if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNum
ber()) |
| 840 return; |
| 841 |
| 842 if (accessibilityObject().role() != WebAXRoleStaticText) |
| 843 return; |
| 844 |
| 845 int start = arguments[0].toInt32(); |
| 846 int end = arguments[1].toInt32(); |
| 847 int len = end - start; |
| 848 |
| 849 // Get the bounds for each character and union them into one large rectangle
. |
| 850 // This is just for testing so it doesn't need to be efficient. |
| 851 WebRect bounds = boundsForCharacter(accessibilityObject(), start); |
| 852 for (int i = 1; i < len; i++) { |
| 853 WebRect next = boundsForCharacter(accessibilityObject(), start + i); |
| 854 int right = std::max(bounds.x + bounds.width, next.x + next.width); |
| 855 int bottom = std::max(bounds.y + bounds.height, next.y + next.height); |
| 856 bounds.x = std::min(bounds.x, next.x); |
| 857 bounds.y = std::min(bounds.y, next.y); |
| 858 bounds.width = right - bounds.x; |
| 859 bounds.height = bottom - bounds.y; |
| 860 } |
| 861 |
| 862 char buffer[100]; |
| 863 snprintf(buffer, sizeof(buffer), "{x: %d, y: %d, width: %d, height: %d}", bo
unds.x, bounds.y, bounds.width, bounds.height); |
| 864 result->set(string(buffer)); |
753 } | 865 } |
754 | 866 |
755 void AccessibilityUIElement::stringForRangeCallback(const CppArgumentList&, CppV
ariant* result) | 867 void AccessibilityUIElement::stringForRangeCallback(const CppArgumentList&, CppV
ariant* result) |
756 { | 868 { |
757 result->setNull(); | 869 result->setNull(); |
758 } | 870 } |
759 | 871 |
760 void AccessibilityUIElement::childAtIndexCallback(const CppArgumentList& argumen
ts, CppVariant* result) | 872 void AccessibilityUIElement::childAtIndexCallback(const CppArgumentList& argumen
ts, CppVariant* result) |
761 { | 873 { |
762 if (!arguments.size() || !arguments[0].isNumber()) { | 874 if (!arguments.size() || !arguments[0].isNumber()) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1028 || !arguments[1].isNumber()) | 1140 || !arguments[1].isNumber()) |
1029 return; | 1141 return; |
1030 | 1142 |
1031 int x = arguments[0].toInt32(); | 1143 int x = arguments[0].toInt32(); |
1032 int y = arguments[1].toInt32(); | 1144 int y = arguments[1].toInt32(); |
1033 | 1145 |
1034 accessibilityObject().scrollToGlobalPoint(WebPoint(x, y)); | 1146 accessibilityObject().scrollToGlobalPoint(WebPoint(x, y)); |
1035 result->setNull(); | 1147 result->setNull(); |
1036 } | 1148 } |
1037 | 1149 |
| 1150 void AccessibilityUIElement::wordStartCallback(const CppArgumentList& arguments,
CppVariant* result) |
| 1151 { |
| 1152 result->setNull(); |
| 1153 |
| 1154 if (arguments.size() != 1 || !arguments[0].isNumber()) |
| 1155 return; |
| 1156 |
| 1157 if (accessibilityObject().role() != WebAXRoleStaticText) |
| 1158 return; |
| 1159 |
| 1160 int characterIndex = arguments[0].toInt32(); |
| 1161 int wordStart, wordEnd; |
| 1162 getWordBoundaries(accessibilityObject(), characterIndex, wordStart, wordEnd)
; |
| 1163 result->set(wordStart); |
| 1164 } |
| 1165 |
| 1166 void AccessibilityUIElement::wordEndCallback(const CppArgumentList& arguments, C
ppVariant* result) |
| 1167 { |
| 1168 result->setNull(); |
| 1169 |
| 1170 if (arguments.size() != 1 || !arguments[0].isNumber()) |
| 1171 return; |
| 1172 |
| 1173 if (accessibilityObject().role() != WebAXRoleStaticText) |
| 1174 return; |
| 1175 |
| 1176 int characterIndex = arguments[0].toInt32(); |
| 1177 int wordStart, wordEnd; |
| 1178 getWordBoundaries(accessibilityObject(), characterIndex, wordStart, wordEnd)
; |
| 1179 result->set(wordEnd); |
| 1180 } |
| 1181 |
1038 void AccessibilityUIElement::fallbackCallback(const CppArgumentList &, CppVarian
t* result) | 1182 void AccessibilityUIElement::fallbackCallback(const CppArgumentList &, CppVarian
t* result) |
1039 { | 1183 { |
1040 // FIXME: Implement this. | 1184 // FIXME: Implement this. |
1041 result->setNull(); | 1185 result->setNull(); |
1042 } | 1186 } |
1043 | 1187 |
1044 RootAccessibilityUIElement::RootAccessibilityUIElement(const WebAccessibilityObj
ect &object, Factory *factory) | 1188 RootAccessibilityUIElement::RootAccessibilityUIElement(const WebAccessibilityObj
ect &object, Factory *factory) |
1045 : AccessibilityUIElement(object, factory) { } | 1189 : AccessibilityUIElement(object, factory) { } |
1046 | 1190 |
1047 AccessibilityUIElement* RootAccessibilityUIElement::getChildAtIndex(unsigned ind
ex) | 1191 AccessibilityUIElement* RootAccessibilityUIElement::getChildAtIndex(unsigned ind
ex) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 } | 1226 } |
1083 | 1227 |
1084 AccessibilityUIElement* AccessibilityUIElementList::createRoot(const WebAccessib
ilityObject& object) | 1228 AccessibilityUIElement* AccessibilityUIElementList::createRoot(const WebAccessib
ilityObject& object) |
1085 { | 1229 { |
1086 AccessibilityUIElement* element = new RootAccessibilityUIElement(object, thi
s); | 1230 AccessibilityUIElement* element = new RootAccessibilityUIElement(object, thi
s); |
1087 m_elements.push_back(element); | 1231 m_elements.push_back(element); |
1088 return element; | 1232 return element; |
1089 } | 1233 } |
1090 | 1234 |
1091 } | 1235 } |
OLD | NEW |