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 GOwnPtr<gchar> attributeData(g_strconcat(attribute->name, ":", attribute->value, NULL));
144 g_string_append(str, attributeData.get());
145 if (attributes->next)
146 g_string_append(str, ", ");
149 return g_string_free(str, FALSE);
152 JSStringRef AccessibilityUIElement::allAttributes()
155 return JSStringCreateWithCharacters(0, 0);
157 ASSERT(ATK_IS_OBJECT(m_element));
158 GOwnPtr<gchar> attributeData(attributeSetToString(atk_object_get_attributes(ATK_OBJECT(m_element))));
159 return JSStringCreateWithUTF8CString(attributeData.get());
162 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
165 return JSStringCreateWithCharacters(0, 0);
168 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
171 return JSStringCreateWithCharacters(0, 0);
174 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
180 AccessibilityUIElement AccessibilityUIElement::parentElement()
185 ASSERT(ATK_IS_OBJECT(m_element));
187 AtkObject* parent = atk_object_get_parent(ATK_OBJECT(m_element));
188 return parent ? AccessibilityUIElement(parent) : 0;
191 JSStringRef AccessibilityUIElement::attributesOfChildren()
194 return JSStringCreateWithCharacters(0, 0);
197 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
200 return JSStringCreateWithCharacters(0, 0);
203 JSStringRef AccessibilityUIElement::role()
205 AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
208 return JSStringCreateWithCharacters(0, 0);
210 const gchar* roleName = atk_role_get_name(role);
211 GOwnPtr<gchar> axRole(g_strdup_printf("AXRole: %s", roleName));
213 return JSStringCreateWithUTF8CString(axRole.get());
216 JSStringRef AccessibilityUIElement::subrole()
221 JSStringRef AccessibilityUIElement::roleDescription()
226 JSStringRef AccessibilityUIElement::title()
228 const gchar* name = atk_object_get_name(ATK_OBJECT(m_element));
231 return JSStringCreateWithCharacters(0, 0);
233 GOwnPtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name));
235 return JSStringCreateWithUTF8CString(axTitle.get());
238 JSStringRef AccessibilityUIElement::description()
240 const gchar* description = atk_object_get_description(ATK_OBJECT(m_element));
243 return JSStringCreateWithCharacters(0, 0);
245 GOwnPtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
247 return JSStringCreateWithUTF8CString(axDesc.get());
250 JSStringRef AccessibilityUIElement::stringValue()
253 return JSStringCreateWithCharacters(0, 0);
256 JSStringRef AccessibilityUIElement::language()
259 return JSStringCreateWithCharacters(0, 0);
262 JSStringRef AccessibilityUIElement::helpText() const
265 return JSStringCreateWithCharacters(0, 0);
267 ASSERT(ATK_IS_OBJECT(m_element));
269 CString helpText = DumpRenderTreeSupportGtk::accessibilityHelpText(ATK_OBJECT(m_element));
270 GOwnPtr<gchar> axHelpText(g_strdup_printf("AXHelp: %s", helpText.data()));
271 return JSStringCreateWithUTF8CString(axHelpText.get());
274 double AccessibilityUIElement::x()
278 atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
283 double AccessibilityUIElement::y()
287 atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
292 double AccessibilityUIElement::width()
296 atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
301 double AccessibilityUIElement::height()
305 atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
310 double AccessibilityUIElement::clickPointX()
315 double AccessibilityUIElement::clickPointY()
320 JSStringRef AccessibilityUIElement::orientation() const
325 double AccessibilityUIElement::intValue() const
327 GValue value = { 0, { { 0 } } };
329 if (!ATK_IS_VALUE(m_element))
332 atk_value_get_current_value(ATK_VALUE(m_element), &value);
333 if (!G_VALUE_HOLDS_FLOAT(&value))
335 return g_value_get_float(&value);
338 double AccessibilityUIElement::minValue()
340 GValue value = { 0, { { 0 } } };
342 if (!ATK_IS_VALUE(m_element))
345 atk_value_get_minimum_value(ATK_VALUE(m_element), &value);
346 if (!G_VALUE_HOLDS_FLOAT(&value))
348 return g_value_get_float(&value);
351 double AccessibilityUIElement::maxValue()
353 GValue value = { 0, { { 0 } } };
355 if (!ATK_IS_VALUE(m_element))
358 atk_value_get_maximum_value(ATK_VALUE(m_element), &value);
359 if (!G_VALUE_HOLDS_FLOAT(&value))
361 return g_value_get_float(&value);
364 JSStringRef AccessibilityUIElement::valueDescription()
367 return JSStringCreateWithCharacters(0, 0);
370 static bool checkElementState(PlatformUIElement element, AtkStateType stateType)
372 if (!ATK_IS_OBJECT(element))
375 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(element)));
376 return atk_state_set_contains_state(stateSet.get(), stateType);
379 bool AccessibilityUIElement::isEnabled()
381 return checkElementState(m_element, ATK_STATE_ENABLED);
384 int AccessibilityUIElement::insertionPointLineNumber()
390 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
396 bool AccessibilityUIElement::isRequired() const
402 bool AccessibilityUIElement::isFocused() const
404 if (!ATK_IS_OBJECT(m_element))
407 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
408 gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED);
413 bool AccessibilityUIElement::isSelected() const
415 return checkElementState(m_element, ATK_STATE_SELECTED);
418 int AccessibilityUIElement::hierarchicalLevel() const
424 bool AccessibilityUIElement::ariaIsGrabbed() const
429 JSStringRef AccessibilityUIElement::ariaDropEffects() const
434 bool AccessibilityUIElement::isExpanded() const
436 if (!ATK_IS_OBJECT(m_element))
439 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
440 gboolean isExpanded = atk_state_set_contains_state(stateSet.get(), ATK_STATE_EXPANDED);
445 bool AccessibilityUIElement::isChecked() const
447 if (!ATK_IS_OBJECT(m_element))
450 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
451 gboolean isChecked = atk_state_set_contains_state(stateSet.get(), ATK_STATE_CHECKED);
456 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
459 return JSStringCreateWithCharacters(0, 0);
462 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
465 return JSStringCreateWithCharacters(0, 0);
468 JSStringRef AccessibilityUIElement::attributesOfColumns()
471 return JSStringCreateWithCharacters(0, 0);
474 JSStringRef AccessibilityUIElement::attributesOfRows()
477 return JSStringCreateWithCharacters(0, 0);
480 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
483 return JSStringCreateWithCharacters(0, 0);
486 JSStringRef AccessibilityUIElement::attributesOfHeader()
489 return JSStringCreateWithCharacters(0, 0);
492 int AccessibilityUIElement::indexInTable()
498 static JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
500 GOwnPtr<gchar> rangeString(g_strdup("{0, 0}"));
503 return JSStringCreateWithUTF8CString(rangeString.get());
505 ASSERT(ATK_IS_OBJECT(element));
507 AtkObject* axTable = atk_object_get_parent(ATK_OBJECT(element));
508 if (!axTable || !ATK_IS_TABLE(axTable))
509 return JSStringCreateWithUTF8CString(rangeString.get());
511 // Look for the cell in the table.
512 gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element));
513 if (indexInParent == -1)
514 return JSStringCreateWithUTF8CString(rangeString.get());
518 row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent);
519 column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent);
521 // Get the actual values, if row and columns are valid values.
522 if (row != -1 && column != -1) {
527 length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column);
530 length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column);
532 rangeString.set(g_strdup_printf("{%d, %d}", base, length));
535 return JSStringCreateWithUTF8CString(rangeString.get());
538 JSStringRef AccessibilityUIElement::rowIndexRange()
540 // Range in table for rows.
541 return indexRangeInTable(m_element, true);
544 JSStringRef AccessibilityUIElement::columnIndexRange()
546 // Range in table for columns.
547 return indexRangeInTable(m_element, false);
550 int AccessibilityUIElement::lineForIndex(int)
556 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
559 return JSStringCreateWithCharacters(0, 0);
562 JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned)
565 return JSStringCreateWithCharacters(0, 0);
568 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
571 return JSStringCreateWithCharacters(0, 0);
574 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
580 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
586 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
591 ASSERT(ATK_IS_TABLE(m_element));
593 AtkObject* foundCell = atk_table_ref_at(ATK_TABLE(m_element), row, column);
594 return foundCell ? AccessibilityUIElement(foundCell) : 0;
597 JSStringRef AccessibilityUIElement::selectedTextRange()
600 return JSStringCreateWithCharacters(0, 0);
603 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
608 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
611 return JSStringCreateWithCharacters(0, 0);
614 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
620 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
626 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
632 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
637 static void alterCurrentValue(PlatformUIElement element, int factor)
642 ASSERT(ATK_IS_VALUE(element));
644 GValue currentValue = G_VALUE_INIT;
645 atk_value_get_current_value(ATK_VALUE(element), ¤tValue);
647 GValue increment = G_VALUE_INIT;
648 atk_value_get_minimum_increment(ATK_VALUE(element), &increment);
650 GValue newValue = G_VALUE_INIT;
651 g_value_init(&newValue, G_TYPE_FLOAT);
653 g_value_set_float(&newValue, g_value_get_float(¤tValue) + factor * g_value_get_float(&increment));
654 atk_value_set_current_value(ATK_VALUE(element), &newValue);
656 g_value_unset(&newValue);
657 g_value_unset(&increment);
658 g_value_unset(¤tValue);
661 void AccessibilityUIElement::increment()
663 alterCurrentValue(m_element, 1);
666 void AccessibilityUIElement::decrement()
668 alterCurrentValue(m_element, -1);
671 void AccessibilityUIElement::press()
676 ASSERT(ATK_IS_OBJECT(m_element));
678 if (!ATK_IS_ACTION(m_element))
681 // Only one action per object is supported so far.
682 atk_action_do_action(ATK_ACTION(m_element), 0);
685 void AccessibilityUIElement::showMenu()
690 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
695 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
700 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
705 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
710 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
715 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
720 JSStringRef AccessibilityUIElement::accessibilityValue() const
723 return JSStringCreateWithCharacters(0, 0);
726 JSStringRef AccessibilityUIElement::documentEncoding()
728 AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
729 if (role != ATK_ROLE_DOCUMENT_FRAME)
730 return JSStringCreateWithCharacters(0, 0);
732 return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "Encoding"));
735 JSStringRef AccessibilityUIElement::documentURI()
737 AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
738 if (role != ATK_ROLE_DOCUMENT_FRAME)
739 return JSStringCreateWithCharacters(0, 0);
741 return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "URI"));
744 JSStringRef AccessibilityUIElement::url()
747 return JSStringCreateWithCharacters(0, 0);
750 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
756 void AccessibilityUIElement::removeNotificationListener()
761 bool AccessibilityUIElement::isFocusable() const
763 if (!ATK_IS_OBJECT(m_element))
766 GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
767 gboolean isFocusable = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSABLE);
772 bool AccessibilityUIElement::isSelectable() const
778 bool AccessibilityUIElement::isMultiSelectable() const
784 bool AccessibilityUIElement::isSelectedOptionActive() const
790 bool AccessibilityUIElement::isVisible() const
796 bool AccessibilityUIElement::isOffScreen() const
802 bool AccessibilityUIElement::isCollapsed() const
808 bool AccessibilityUIElement::isIgnored() const
814 bool AccessibilityUIElement::hasPopup() const
820 void AccessibilityUIElement::takeFocus()
825 void AccessibilityUIElement::takeSelection()
830 void AccessibilityUIElement::addSelection()
835 void AccessibilityUIElement::removeSelection()
840 void AccessibilityUIElement::scrollToMakeVisible()
845 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
850 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)