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"
30 #include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
31 #include <JavaScriptCore/JSStringRef.h>
34 #include <wtf/Assertions.h>
35 #include <wtf/gobject/GOwnPtr.h>
36 #include <wtf/gobject/GRefPtr.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
263 return JSStringCreateWithCharacters(0, 0);
265 ASSERT(ATK_IS_OBJECT(m_element));
267 CString helpText = DumpRenderTreeSupportGtk::accessibilityHelpText(ATK_OBJECT(m_element));
268 GOwnPtr<gchar> axHelpText(g_strdup_printf("AXHelp: %s", helpText.data()));
269 return JSStringCreateWithUTF8CString(axHelpText.get());
272 double AccessibilityUIElement::x()
276 atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
281 double AccessibilityUIElement::y()
285 atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
290 double AccessibilityUIElement::width()
294 atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
299 double AccessibilityUIElement::height()
303 atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
308 double AccessibilityUIElement::clickPointX()
313 double AccessibilityUIElement::clickPointY()
318 JSStringRef AccessibilityUIElement::orientation() const
323 double AccessibilityUIElement::intValue() const
325 GValue value = { 0, { { 0 } } };
327 if (!ATK_IS_VALUE(m_element))
330 atk_value_get_current_value(ATK_VALUE(m_element), &value);
332 if (G_VALUE_HOLDS_DOUBLE(&value))
333 return g_value_get_double(&value);
334 else if (G_VALUE_HOLDS_INT(&value))
335 return static_cast<double>(g_value_get_int(&value));
340 double AccessibilityUIElement::minValue()
342 GValue value = { 0, { { 0 } } };
344 if (!ATK_IS_VALUE(m_element))
347 atk_value_get_minimum_value(ATK_VALUE(m_element), &value);
349 if (G_VALUE_HOLDS_DOUBLE(&value))
350 return g_value_get_double(&value);
351 else if (G_VALUE_HOLDS_INT(&value))
352 return static_cast<double>(g_value_get_int(&value));
357 double AccessibilityUIElement::maxValue()
359 GValue value = { 0, { { 0 } } };
361 if (!ATK_IS_VALUE(m_element))
364 atk_value_get_maximum_value(ATK_VALUE(m_element), &value);
366 if (G_VALUE_HOLDS_DOUBLE(&value))
367 return g_value_get_double(&value);
368 else if (G_VALUE_HOLDS_INT(&value))
369 return static_cast<double>(g_value_get_int(&value));
374 JSStringRef AccessibilityUIElement::valueDescription()
377 return JSStringCreateWithCharacters(0, 0);
380 static bool checkElementState(PlatformUIElement element, AtkStateType stateType)
382 if (!ATK_IS_OBJECT(element))
385 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(element)));
386 return atk_state_set_contains_state(stateSet.get(), stateType);
389 bool AccessibilityUIElement::isEnabled()
391 return checkElementState(m_element, ATK_STATE_ENABLED);
394 int AccessibilityUIElement::insertionPointLineNumber()
400 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
406 bool AccessibilityUIElement::isRequired() const
412 bool AccessibilityUIElement::isFocused() const
414 if (!ATK_IS_OBJECT(m_element))
417 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
418 gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED);
423 bool AccessibilityUIElement::isSelected() const
425 return checkElementState(m_element, ATK_STATE_SELECTED);
428 int AccessibilityUIElement::hierarchicalLevel() const
434 bool AccessibilityUIElement::ariaIsGrabbed() const
439 JSStringRef AccessibilityUIElement::ariaDropEffects() const
444 bool AccessibilityUIElement::isExpanded() const
446 if (!ATK_IS_OBJECT(m_element))
449 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
450 gboolean isExpanded = atk_state_set_contains_state(stateSet.get(), ATK_STATE_EXPANDED);
455 bool AccessibilityUIElement::isChecked() const
457 if (!ATK_IS_OBJECT(m_element))
460 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
461 gboolean isChecked = atk_state_set_contains_state(stateSet.get(), ATK_STATE_CHECKED);
466 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
469 return JSStringCreateWithCharacters(0, 0);
472 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
475 return JSStringCreateWithCharacters(0, 0);
478 JSStringRef AccessibilityUIElement::attributesOfColumns()
481 return JSStringCreateWithCharacters(0, 0);
484 JSStringRef AccessibilityUIElement::attributesOfRows()
487 return JSStringCreateWithCharacters(0, 0);
490 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
493 return JSStringCreateWithCharacters(0, 0);
496 JSStringRef AccessibilityUIElement::attributesOfHeader()
499 return JSStringCreateWithCharacters(0, 0);
502 int AccessibilityUIElement::indexInTable()
508 static JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
510 GOwnPtr<gchar> rangeString(g_strdup("{0, 0}"));
513 return JSStringCreateWithUTF8CString(rangeString.get());
515 ASSERT(ATK_IS_OBJECT(element));
517 AtkObject* axTable = atk_object_get_parent(ATK_OBJECT(element));
518 if (!axTable || !ATK_IS_TABLE(axTable))
519 return JSStringCreateWithUTF8CString(rangeString.get());
521 // Look for the cell in the table.
522 gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element));
523 if (indexInParent == -1)
524 return JSStringCreateWithUTF8CString(rangeString.get());
528 row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent);
529 column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent);
531 // Get the actual values, if row and columns are valid values.
532 if (row != -1 && column != -1) {
537 length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column);
540 length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column);
542 rangeString.set(g_strdup_printf("{%d, %d}", base, length));
545 return JSStringCreateWithUTF8CString(rangeString.get());
548 JSStringRef AccessibilityUIElement::rowIndexRange()
550 // Range in table for rows.
551 return indexRangeInTable(m_element, true);
554 JSStringRef AccessibilityUIElement::columnIndexRange()
556 // Range in table for columns.
557 return indexRangeInTable(m_element, false);
560 int AccessibilityUIElement::lineForIndex(int)
566 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
569 return JSStringCreateWithCharacters(0, 0);
572 JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned)
575 return JSStringCreateWithCharacters(0, 0);
578 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
581 return JSStringCreateWithCharacters(0, 0);
584 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
590 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
596 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
601 ASSERT(ATK_IS_TABLE(m_element));
603 AtkObject* foundCell = atk_table_ref_at(ATK_TABLE(m_element), row, column);
604 return foundCell ? AccessibilityUIElement(foundCell) : 0;
607 JSStringRef AccessibilityUIElement::selectedTextRange()
610 return JSStringCreateWithCharacters(0, 0);
613 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
618 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
621 return JSStringCreateWithCharacters(0, 0);
624 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
630 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
636 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
642 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
647 void AccessibilityUIElement::increment()
652 ASSERT(ATK_IS_OBJECT(m_element));
653 DumpRenderTreeSupportGtk::incrementAccessibilityValue(ATK_OBJECT(m_element));
656 void AccessibilityUIElement::decrement()
661 ASSERT(ATK_IS_OBJECT(m_element));
662 DumpRenderTreeSupportGtk::decrementAccessibilityValue(ATK_OBJECT(m_element));
665 void AccessibilityUIElement::press()
670 ASSERT(ATK_IS_OBJECT(m_element));
672 if (!ATK_IS_ACTION(m_element))
675 // Only one action per object is supported so far.
676 atk_action_do_action(ATK_ACTION(m_element), 0);
679 void AccessibilityUIElement::showMenu()
684 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
689 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
694 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
699 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
704 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
709 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
714 JSStringRef AccessibilityUIElement::accessibilityValue() const
717 return JSStringCreateWithCharacters(0, 0);
720 JSStringRef AccessibilityUIElement::documentEncoding()
722 AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
723 if (role != ATK_ROLE_DOCUMENT_FRAME)
724 return JSStringCreateWithCharacters(0, 0);
726 return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "Encoding"));
729 JSStringRef AccessibilityUIElement::documentURI()
731 AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
732 if (role != ATK_ROLE_DOCUMENT_FRAME)
733 return JSStringCreateWithCharacters(0, 0);
735 return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "URI"));
738 JSStringRef AccessibilityUIElement::url()
741 return JSStringCreateWithCharacters(0, 0);
744 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
750 void AccessibilityUIElement::removeNotificationListener()
755 bool AccessibilityUIElement::isFocusable() const
757 if (!ATK_IS_OBJECT(m_element))
760 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
761 gboolean isFocusable = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSABLE);
766 bool AccessibilityUIElement::isSelectable() const
772 bool AccessibilityUIElement::isMultiSelectable() const
778 bool AccessibilityUIElement::isSelectedOptionActive() const
784 bool AccessibilityUIElement::isVisible() const
790 bool AccessibilityUIElement::isOffScreen() const
796 bool AccessibilityUIElement::isCollapsed() const
802 bool AccessibilityUIElement::isIgnored() const
808 bool AccessibilityUIElement::hasPopup() const
814 void AccessibilityUIElement::takeFocus()
819 void AccessibilityUIElement::takeSelection()
824 void AccessibilityUIElement::addSelection()
829 void AccessibilityUIElement::removeSelection()
834 void AccessibilityUIElement::scrollToMakeVisible()
839 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
844 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)