2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2009 Jan Michael Alonzo
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "AccessibilityUIElement.h"
32 #include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
33 #include <JavaScriptCore/JSStringRef.h>
36 #include <wtf/Assertions.h>
38 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
43 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
44 : m_element(other.m_element)
48 AccessibilityUIElement::~AccessibilityUIElement()
52 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elements)
57 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
62 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
64 int count = childrenCount();
65 for (int i = 0; i < count; i++) {
66 AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
67 children.append(AccessibilityUIElement(child));
71 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned start, unsigned end)
73 for (unsigned i = start; i < end; i++) {
74 AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
75 elementVector.append(AccessibilityUIElement(child));
79 int AccessibilityUIElement::rowCount()
84 ASSERT(ATK_IS_TABLE(m_element));
86 return atk_table_get_n_rows(ATK_TABLE(m_element));
89 int AccessibilityUIElement::columnCount()
94 ASSERT(ATK_IS_TABLE(m_element));
96 return atk_table_get_n_columns(ATK_TABLE(m_element));
99 int AccessibilityUIElement::childrenCount()
104 ASSERT(ATK_IS_OBJECT(m_element));
106 return atk_object_get_n_accessible_children(ATK_OBJECT(m_element));
109 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
115 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
121 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
123 Vector<AccessibilityUIElement> children;
124 getChildrenWithRange(children, index, index + 1);
126 if (children.size() == 1)
127 return children.at(0);
132 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
138 gchar* attributeSetToString(AtkAttributeSet* attributeSet)
140 GString* str = g_string_new(0);
141 for (GSList* attributes = attributeSet; attributes; attributes = attributes->next) {
142 AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
143 g_string_append(str, g_strconcat(attribute->name, ":", attribute->value, NULL));
144 if (attributes->next)
145 g_string_append(str, ", ");
148 return g_string_free(str, FALSE);
151 JSStringRef AccessibilityUIElement::allAttributes()
154 return JSStringCreateWithCharacters(0, 0);
156 ASSERT(ATK_IS_OBJECT(m_element));
157 return JSStringCreateWithUTF8CString(attributeSetToString(atk_object_get_attributes(ATK_OBJECT(m_element))));
160 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
163 return JSStringCreateWithCharacters(0, 0);
166 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
169 return JSStringCreateWithCharacters(0, 0);
172 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
178 AccessibilityUIElement AccessibilityUIElement::parentElement()
183 ASSERT(ATK_IS_OBJECT(m_element));
185 AtkObject* parent = atk_object_get_parent(ATK_OBJECT(m_element));
186 return parent ? AccessibilityUIElement(parent) : 0;
189 JSStringRef AccessibilityUIElement::attributesOfChildren()
192 return JSStringCreateWithCharacters(0, 0);
195 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
198 return JSStringCreateWithCharacters(0, 0);
201 JSStringRef AccessibilityUIElement::role()
203 AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
206 return JSStringCreateWithCharacters(0, 0);
208 const gchar* roleName = atk_role_get_name(role);
209 GOwnPtr<gchar> axRole(g_strdup_printf("AXRole: %s", roleName));
211 return JSStringCreateWithUTF8CString(axRole.get());
214 JSStringRef AccessibilityUIElement::subrole()
219 JSStringRef AccessibilityUIElement::roleDescription()
224 JSStringRef AccessibilityUIElement::title()
226 const gchar* name = atk_object_get_name(ATK_OBJECT(m_element));
229 return JSStringCreateWithCharacters(0, 0);
231 GOwnPtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name));
233 return JSStringCreateWithUTF8CString(axTitle.get());
236 JSStringRef AccessibilityUIElement::description()
238 const gchar* description = atk_object_get_description(ATK_OBJECT(m_element));
241 return JSStringCreateWithCharacters(0, 0);
243 GOwnPtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
245 return JSStringCreateWithUTF8CString(axDesc.get());
248 JSStringRef AccessibilityUIElement::stringValue()
251 return JSStringCreateWithCharacters(0, 0);
254 JSStringRef AccessibilityUIElement::language()
257 return JSStringCreateWithCharacters(0, 0);
260 JSStringRef AccessibilityUIElement::helpText() const
265 double AccessibilityUIElement::x()
269 atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
274 double AccessibilityUIElement::y()
278 atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
283 double AccessibilityUIElement::width()
287 atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
292 double AccessibilityUIElement::height()
296 atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
301 double AccessibilityUIElement::clickPointX()
306 double AccessibilityUIElement::clickPointY()
311 JSStringRef AccessibilityUIElement::orientation() const
316 double AccessibilityUIElement::intValue() const
318 GValue value = { 0, { { 0 } } };
320 if (!ATK_IS_VALUE(m_element))
323 atk_value_get_current_value(ATK_VALUE(m_element), &value);
325 if (G_VALUE_HOLDS_DOUBLE(&value))
326 return g_value_get_double(&value);
327 else if (G_VALUE_HOLDS_INT(&value))
328 return static_cast<double>(g_value_get_int(&value));
333 double AccessibilityUIElement::minValue()
335 GValue value = { 0, { { 0 } } };
337 if (!ATK_IS_VALUE(m_element))
340 atk_value_get_minimum_value(ATK_VALUE(m_element), &value);
342 if (G_VALUE_HOLDS_DOUBLE(&value))
343 return g_value_get_double(&value);
344 else if (G_VALUE_HOLDS_INT(&value))
345 return static_cast<double>(g_value_get_int(&value));
350 double AccessibilityUIElement::maxValue()
352 GValue value = { 0, { { 0 } } };
354 if (!ATK_IS_VALUE(m_element))
357 atk_value_get_maximum_value(ATK_VALUE(m_element), &value);
359 if (G_VALUE_HOLDS_DOUBLE(&value))
360 return g_value_get_double(&value);
361 else if (G_VALUE_HOLDS_INT(&value))
362 return static_cast<double>(g_value_get_int(&value));
367 JSStringRef AccessibilityUIElement::valueDescription()
370 return JSStringCreateWithCharacters(0, 0);
373 static bool checkElementState(PlatformUIElement element, AtkStateType stateType)
375 if (!ATK_IS_OBJECT(element))
378 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(element)));
379 return atk_state_set_contains_state(stateSet.get(), stateType);
382 bool AccessibilityUIElement::isEnabled()
384 return checkElementState(m_element, ATK_STATE_ENABLED);
387 int AccessibilityUIElement::insertionPointLineNumber()
393 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
399 bool AccessibilityUIElement::isRequired() const
405 bool AccessibilityUIElement::isFocused() const
407 if (!ATK_IS_OBJECT(m_element))
410 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
411 gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED);
416 bool AccessibilityUIElement::isSelected() const
418 return checkElementState(m_element, ATK_STATE_SELECTED);
421 int AccessibilityUIElement::hierarchicalLevel() const
427 bool AccessibilityUIElement::ariaIsGrabbed() const
432 JSStringRef AccessibilityUIElement::ariaDropEffects() const
437 bool AccessibilityUIElement::isExpanded() const
439 if (!ATK_IS_OBJECT(m_element))
442 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
443 gboolean isExpanded = atk_state_set_contains_state(stateSet.get(), ATK_STATE_EXPANDED);
448 bool AccessibilityUIElement::isChecked() const
450 if (!ATK_IS_OBJECT(m_element))
453 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
454 gboolean isChecked = atk_state_set_contains_state(stateSet.get(), ATK_STATE_CHECKED);
459 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
462 return JSStringCreateWithCharacters(0, 0);
465 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
468 return JSStringCreateWithCharacters(0, 0);
471 JSStringRef AccessibilityUIElement::attributesOfColumns()
474 return JSStringCreateWithCharacters(0, 0);
477 JSStringRef AccessibilityUIElement::attributesOfRows()
480 return JSStringCreateWithCharacters(0, 0);
483 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
486 return JSStringCreateWithCharacters(0, 0);
489 JSStringRef AccessibilityUIElement::attributesOfHeader()
492 return JSStringCreateWithCharacters(0, 0);
495 int AccessibilityUIElement::indexInTable()
501 static JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
503 GOwnPtr<gchar> rangeString(g_strdup("{0, 0}"));
506 return JSStringCreateWithUTF8CString(rangeString.get());
508 ASSERT(ATK_IS_OBJECT(element));
510 AtkObject* axTable = atk_object_get_parent(ATK_OBJECT(element));
511 if (!axTable || !ATK_IS_TABLE(axTable))
512 return JSStringCreateWithUTF8CString(rangeString.get());
514 // Look for the cell in the table.
515 gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element));
516 if (indexInParent == -1)
517 return JSStringCreateWithUTF8CString(rangeString.get());
521 row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent);
522 column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent);
524 // Get the actual values, if row and columns are valid values.
525 if (row != -1 && column != -1) {
530 length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column);
533 length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column);
535 rangeString.set(g_strdup_printf("{%d, %d}", base, length));
538 return JSStringCreateWithUTF8CString(rangeString.get());
541 JSStringRef AccessibilityUIElement::rowIndexRange()
543 // Range in table for rows.
544 return indexRangeInTable(m_element, true);
547 JSStringRef AccessibilityUIElement::columnIndexRange()
549 // Range in table for columns.
550 return indexRangeInTable(m_element, false);
553 int AccessibilityUIElement::lineForIndex(int)
559 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
562 return JSStringCreateWithCharacters(0, 0);
565 JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned)
568 return JSStringCreateWithCharacters(0, 0);
571 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
574 return JSStringCreateWithCharacters(0, 0);
577 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
583 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
589 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
594 ASSERT(ATK_IS_TABLE(m_element));
596 AtkObject* foundCell = atk_table_ref_at(ATK_TABLE(m_element), row, column);
597 return foundCell ? AccessibilityUIElement(foundCell) : 0;
600 JSStringRef AccessibilityUIElement::selectedTextRange()
603 return JSStringCreateWithCharacters(0, 0);
606 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
611 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
614 return JSStringCreateWithCharacters(0, 0);
617 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
623 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
629 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
635 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
640 void AccessibilityUIElement::increment()
645 ASSERT(ATK_IS_OBJECT(m_element));
646 DumpRenderTreeSupportGtk::incrementAccessibilityValue(ATK_OBJECT(m_element));
649 void AccessibilityUIElement::decrement()
654 ASSERT(ATK_IS_OBJECT(m_element));
655 DumpRenderTreeSupportGtk::decrementAccessibilityValue(ATK_OBJECT(m_element));
658 void AccessibilityUIElement::press()
663 ASSERT(ATK_IS_OBJECT(m_element));
665 if (!ATK_IS_ACTION(m_element))
668 // Only one action per object is supported so far.
669 atk_action_do_action(ATK_ACTION(m_element), 0);
672 void AccessibilityUIElement::showMenu()
677 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
682 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
687 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
692 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
697 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
702 JSStringRef AccessibilityUIElement::accessibilityValue() const
705 return JSStringCreateWithCharacters(0, 0);
708 JSStringRef AccessibilityUIElement::documentEncoding()
710 AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
711 if (role != ATK_ROLE_DOCUMENT_FRAME)
712 return JSStringCreateWithCharacters(0, 0);
714 return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "Encoding"));
717 JSStringRef AccessibilityUIElement::documentURI()
719 AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
720 if (role != ATK_ROLE_DOCUMENT_FRAME)
721 return JSStringCreateWithCharacters(0, 0);
723 return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "URI"));
726 JSStringRef AccessibilityUIElement::url()
729 return JSStringCreateWithCharacters(0, 0);
732 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
738 void AccessibilityUIElement::removeNotificationListener()
743 bool AccessibilityUIElement::isFocusable() const
745 if (!ATK_IS_OBJECT(m_element))
748 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
749 gboolean isFocusable = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSABLE);
754 bool AccessibilityUIElement::isSelectable() const
760 bool AccessibilityUIElement::isMultiSelectable() const
766 bool AccessibilityUIElement::isVisible() const
772 bool AccessibilityUIElement::isOffScreen() const
778 bool AccessibilityUIElement::isCollapsed() const
784 bool AccessibilityUIElement::isIgnored() const
790 bool AccessibilityUIElement::hasPopup() const
796 void AccessibilityUIElement::takeFocus()
801 void AccessibilityUIElement::takeSelection()
806 void AccessibilityUIElement::addSelection()
811 void AccessibilityUIElement::removeSelection()